diff --git a/.nvmrc b/.nvmrc index 641c7df3..18e0a5e2 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v8.9.4 +v8.14.0 diff --git a/abiniser/abis/AugmintReserves_ABI_024b81d1a1f75241167a8a0f6e62326f.json b/abiniser/abis/AugmintReserves_ABI_024b81d1a1f75241167a8a0f6e62326f.json new file mode 100644 index 00000000..e1fb58df --- /dev/null +++ b/abiniser/abis/AugmintReserves_ABI_024b81d1a1f75241167a8a0f6e62326f.json @@ -0,0 +1,205 @@ +{ + "contractName": "AugmintReserves", + "abiHash": "024b81d1a1f75241167a8a0f6e62326f", + "generatedAt": "2018-10-18T13:35:02.346Z", + "abi": [ + { + "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": "agent", + "type": "address" + }, + { + "name": "requiredPermissions", + "type": "bytes32[]" + } + ], + "name": "revokeMultiplePermissions", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "agent", + "type": "address" + }, + { + "name": "requiredPermissions", + "type": "bytes32[]" + } + ], + "name": "grantMultiplePermissions", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "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" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "weiAmount", + "type": "uint256" + } + ], + "name": "ReserveMigration", + "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" + }, + { + "constant": false, + "inputs": [ + { + "name": "augmintToken", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "weiAmount", + "type": "uint256" + } + ], + "name": "migrate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/abiniser/abis/Exchange_ABI_d3e7f8a261b756f9c40da097608b21cd.json b/abiniser/abis/Exchange_ABI_d3e7f8a261b756f9c40da097608b21cd.json new file mode 100644 index 00000000..292be5e0 --- /dev/null +++ b/abiniser/abis/Exchange_ABI_d3e7f8a261b756f9c40da097608b21cd.json @@ -0,0 +1,588 @@ +{ + "contractName": "Exchange", + "abiHash": "d3e7f8a261b756f9c40da097608b21cd", + "generatedAt": "2018-10-18T13:35:02.437Z", + "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint64" + } + ], + "name": "buyTokenOrders", + "outputs": [ + { + "name": "index", + "type": "uint64" + }, + { + "name": "maker", + "type": "address" + }, + { + "name": "price", + "type": "uint32" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "orderCount", + "outputs": [ + { + "name": "", + "type": "uint64" + } + ], + "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": "", + "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": 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": false, + "inputs": [ + { + "name": "agent", + "type": "address" + }, + { + "name": "requiredPermissions", + "type": "bytes32[]" + } + ], + "name": "grantMultiplePermissions", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint64" + } + ], + "name": "sellTokenOrders", + "outputs": [ + { + "name": "index", + "type": "uint64" + }, + { + "name": "maker", + "type": "address" + }, + { + "name": "price", + "type": "uint32" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "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": "_rates", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "orderId", + "type": "uint64" + }, + { + "indexed": true, + "name": "maker", + "type": "address" + }, + { + "indexed": false, + "name": "price", + "type": "uint32" + }, + { + "indexed": false, + "name": "tokenAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "weiAmount", + "type": "uint256" + } + ], + "name": "NewOrder", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "tokenBuyer", + "type": "address" + }, + { + "indexed": true, + "name": "tokenSeller", + "type": "address" + }, + { + "indexed": false, + "name": "buyTokenOrderId", + "type": "uint64" + }, + { + "indexed": false, + "name": "sellTokenOrderId", + "type": "uint64" + }, + { + "indexed": false, + "name": "publishedRate", + "type": "uint256" + }, + { + "indexed": false, + "name": "price", + "type": "uint32" + }, + { + "indexed": false, + "name": "weiAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "tokenAmount", + "type": "uint256" + } + ], + "name": "OrderFill", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "orderId", + "type": "uint64" + }, + { + "indexed": true, + "name": "maker", + "type": "address" + }, + { + "indexed": false, + "name": "tokenAmount", + "type": "uint256" + }, + { + "indexed": false, + "name": "weiAmount", + "type": "uint256" + } + ], + "name": "CancelledOrder", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "newRatesContract", + "type": "address" + } + ], + "name": "RatesContractChanged", + "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" + }, + { + "constant": false, + "inputs": [ + { + "name": "newRatesContract", + "type": "address" + } + ], + "name": "setRatesContract", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "price", + "type": "uint32" + } + ], + "name": "placeBuyTokenOrder", + "outputs": [ + { + "name": "orderId", + "type": "uint64" + } + ], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "price", + "type": "uint32" + }, + { + "name": "tokenAmount", + "type": "uint256" + } + ], + "name": "placeSellTokenOrder", + "outputs": [ + { + "name": "orderId", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "maker", + "type": "address" + }, + { + "name": "tokenAmount", + "type": "uint256" + }, + { + "name": "price", + "type": "uint256" + } + ], + "name": "transferNotification", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "buyTokenId", + "type": "uint64" + } + ], + "name": "cancelBuyTokenOrder", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "sellTokenId", + "type": "uint64" + } + ], + "name": "cancelSellTokenOrder", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "buyTokenId", + "type": "uint64" + }, + { + "name": "sellTokenId", + "type": "uint64" + } + ], + "name": "matchOrders", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "buyTokenIds", + "type": "uint64[]" + }, + { + "name": "sellTokenIds", + "type": "uint64[]" + } + ], + "name": "matchMultipleOrders", + "outputs": [ + { + "name": "matchCount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getActiveOrderCounts", + "outputs": [ + { + "name": "buyTokenOrderCount", + "type": "uint256" + }, + { + "name": "sellTokenOrderCount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "offset", + "type": "uint256" + }, + { + "name": "chunkSize", + "type": "uint16" + } + ], + "name": "getActiveBuyOrders", + "outputs": [ + { + "name": "", + "type": "uint256[4][]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "offset", + "type": "uint256" + }, + { + "name": "chunkSize", + "type": "uint16" + } + ], + "name": "getActiveSellOrders", + "outputs": [ + { + "name": "", + "type": "uint256[4][]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/abiniser/abis/LoanManager_ABI_fdf5fde95aa940c6dbfb8353c572c5fb.json b/abiniser/abis/LoanManager_ABI_fdf5fde95aa940c6dbfb8353c572c5fb.json new file mode 100644 index 00000000..c2ff1e0d --- /dev/null +++ b/abiniser/abis/LoanManager_ABI_fdf5fde95aa940c6dbfb8353c572c5fb.json @@ -0,0 +1,698 @@ +{ + "contractName": "LoanManager", + "abiHash": "fdf5fde95aa940c6dbfb8353c572c5fb", + "generatedAt": "2018-10-18T13:35:02.403Z", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "monetarySupervisor", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "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": "", + "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": 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": false, + "inputs": [ + { + "name": "agent", + "type": "address" + }, + { + "name": "requiredPermissions", + "type": "bytes32[]" + } + ], + "name": "grantMultiplePermissions", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "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" + }, + { + "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": false, + "inputs": [ + { + "name": "productId", + "type": "uint32" + }, + { + "name": "newState", + "type": "bool" + } + ], + "name": "setLoanProductActiveState", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "productId", + "type": "uint32" + } + ], + "name": "newEthBackedLoan", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "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": false, + "inputs": [ + { + "name": "loanIds", + "type": "uint256[]" + } + ], + "name": "collect", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "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": "getProductCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "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": true, + "inputs": [], + "name": "getLoanCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "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": true, + "inputs": [ + { + "name": "borrower", + "type": "address" + } + ], + "name": "getLoanCountForAddress", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "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": true, + "inputs": [ + { + "name": "loanId", + "type": "uint256" + } + ], + "name": "getLoanTuple", + "outputs": [ + { + "name": "result", + "type": "uint256[10]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/abiniser/abis/Locker_ABI_f59526398823aef0f0c1454d0b6b4eac.json b/abiniser/abis/Locker_ABI_f59526398823aef0f0c1454d0b6b4eac.json new file mode 100644 index 00000000..78cb98c1 --- /dev/null +++ b/abiniser/abis/Locker_ABI_f59526398823aef0f0c1454d0b6b4eac.json @@ -0,0 +1,629 @@ +{ + "contractName": "Locker", + "abiHash": "f59526398823aef0f0c1454d0b6b4eac", + "generatedAt": "2018-10-18T13:35:02.422Z", + "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "lockProducts", + "outputs": [ + { + "name": "perTermInterest", + "type": "uint32" + }, + { + "name": "durationInSecs", + "type": "uint32" + }, + { + "name": "minimumLockAmount", + "type": "uint32" + }, + { + "name": "isActive", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "monetarySupervisor", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "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": 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": false, + "inputs": [ + { + "name": "agent", + "type": "address" + }, + { + "name": "requiredPermissions", + "type": "bytes32[]" + } + ], + "name": "grantMultiplePermissions", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "accountLocks", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "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" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "locks", + "outputs": [ + { + "name": "amountLocked", + "type": "uint256" + }, + { + "name": "owner", + "type": "address" + }, + { + "name": "productId", + "type": "uint32" + }, + { + "name": "lockedUntil", + "type": "uint40" + }, + { + "name": "isActive", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "permissionGranterContract", + "type": "address" + }, + { + "name": "_augmintToken", + "type": "address" + }, + { + "name": "_monetarySupervisor", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "lockProductId", + "type": "uint32" + }, + { + "indexed": false, + "name": "perTermInterest", + "type": "uint32" + }, + { + "indexed": false, + "name": "durationInSecs", + "type": "uint32" + }, + { + "indexed": false, + "name": "minimumLockAmount", + "type": "uint32" + }, + { + "indexed": false, + "name": "isActive", + "type": "bool" + } + ], + "name": "NewLockProduct", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "lockProductId", + "type": "uint32" + }, + { + "indexed": false, + "name": "newActiveState", + "type": "bool" + } + ], + "name": "LockProductActiveChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "lockOwner", + "type": "address" + }, + { + "indexed": false, + "name": "lockId", + "type": "uint256" + }, + { + "indexed": false, + "name": "amountLocked", + "type": "uint256" + }, + { + "indexed": false, + "name": "interestEarned", + "type": "uint256" + }, + { + "indexed": false, + "name": "lockedUntil", + "type": "uint40" + }, + { + "indexed": false, + "name": "perTermInterest", + "type": "uint32" + }, + { + "indexed": false, + "name": "durationInSecs", + "type": "uint32" + } + ], + "name": "NewLock", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "lockOwner", + "type": "address" + }, + { + "indexed": false, + "name": "lockId", + "type": "uint256" + } + ], + "name": "LockReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "newMonetarySupervisor", + "type": "address" + } + ], + "name": "MonetarySupervisorChanged", + "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" + }, + { + "constant": false, + "inputs": [ + { + "name": "perTermInterest", + "type": "uint32" + }, + { + "name": "durationInSecs", + "type": "uint32" + }, + { + "name": "minimumLockAmount", + "type": "uint32" + }, + { + "name": "isActive", + "type": "bool" + } + ], + "name": "addLockProduct", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "lockProductId", + "type": "uint32" + }, + { + "name": "isActive", + "type": "bool" + } + ], + "name": "setLockProductActiveState", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "from", + "type": "address" + }, + { + "name": "amountToLock", + "type": "uint256" + }, + { + "name": "_lockProductId", + "type": "uint256" + } + ], + "name": "transferNotification", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "lockId", + "type": "uint256" + } + ], + "name": "releaseFunds", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "newMonetarySupervisor", + "type": "address" + } + ], + "name": "setMonetarySupervisor", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getLockProductCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "offset", + "type": "uint256" + }, + { + "name": "chunkSize", + "type": "uint16" + } + ], + "name": "getLockProducts", + "outputs": [ + { + "name": "", + "type": "uint256[5][]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getLockCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "lockOwner", + "type": "address" + } + ], + "name": "getLockCountForAddress", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "offset", + "type": "uint256" + }, + { + "name": "chunkSize", + "type": "uint16" + } + ], + "name": "getLocks", + "outputs": [ + { + "name": "", + "type": "uint256[8][]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "lockOwner", + "type": "address" + }, + { + "name": "offset", + "type": "uint256" + }, + { + "name": "chunkSize", + "type": "uint16" + } + ], + "name": "getLocksForAddress", + "outputs": [ + { + "name": "", + "type": "uint256[7][]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "perTermInterest", + "type": "uint32" + }, + { + "name": "amountToLock", + "type": "uint256" + } + ], + "name": "calculateInterest", + "outputs": [ + { + "name": "interestEarned", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/abiniser/abis/MonetarySupervisor_ABI_7f500b43397413e97de925528187f9cd.json b/abiniser/abis/MonetarySupervisor_ABI_7f500b43397413e97de925528187f9cd.json new file mode 100644 index 00000000..4b880bca --- /dev/null +++ b/abiniser/abis/MonetarySupervisor_ABI_7f500b43397413e97de925528187f9cd.json @@ -0,0 +1,693 @@ +{ + "contractName": "MonetarySupervisor", + "abiHash": "7f500b43397413e97de925528187f9cd", + "generatedAt": "2018-10-18T13:35:02.377Z", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "totalLockedAmount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "ltdParams", + "outputs": [ + { + "name": "lockDifferenceLimit", + "type": "uint256" + }, + { + "name": "loanDifferenceLimit", + "type": "uint256" + }, + { + "name": "allowedDifferenceAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "burnedByStabilityBoard", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalLoanAmount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "bytes32" + } + ], + "name": "permissions", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "interestEarnedAccount", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "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": true, + "inputs": [], + "name": "issuedByStabilityBoard", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "augmintToken", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "PERCENT_100", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "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": "", + "type": "address" + } + ], + "name": "acceptedLegacyAugmintTokens", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "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": false, + "inputs": [ + { + "name": "agent", + "type": "address" + }, + { + "name": "requiredPermission", + "type": "bytes32" + } + ], + "name": "grantPermission", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "augmintReserves", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "permissionGranterContract", + "type": "address" + }, + { + "name": "_augmintToken", + "type": "address" + }, + { + "name": "_augmintReserves", + "type": "address" + }, + { + "name": "_interestEarnedAccount", + "type": "address" + }, + { + "name": "lockDifferenceLimit", + "type": "uint256" + }, + { + "name": "loanDifferenceLimit", + "type": "uint256" + }, + { + "name": "allowedDifferenceAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "lockDifferenceLimit", + "type": "uint256" + }, + { + "indexed": false, + "name": "loanDifferenceLimit", + "type": "uint256" + }, + { + "indexed": false, + "name": "allowedDifferenceAmount", + "type": "uint256" + } + ], + "name": "LtdParamsChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "augmintTokenAddress", + "type": "address" + }, + { + "indexed": false, + "name": "newAcceptedState", + "type": "bool" + } + ], + "name": "AcceptedLegacyAugmintTokenChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "oldTokenAddress", + "type": "address" + }, + { + "indexed": false, + "name": "account", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "LegacyTokenConverted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "totalLoanAmountAdjustment", + "type": "uint256" + }, + { + "indexed": false, + "name": "totalLockedAmountAdjustment", + "type": "uint256" + } + ], + "name": "KPIsAdjusted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "newInterestEarnedAccount", + "type": "address" + }, + { + "indexed": false, + "name": "newAugmintReserves", + "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" + }, + { + "constant": false, + "inputs": [ + { + "name": "amount", + "type": "uint256" + } + ], + "name": "issueToReserve", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFromReserve", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "amountToLock", + "type": "uint256" + }, + { + "name": "interestAmount", + "type": "uint256" + } + ], + "name": "requestInterest", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "lockedAmount", + "type": "uint256" + } + ], + "name": "releaseFundsNotification", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "borrower", + "type": "address" + }, + { + "name": "loanAmount", + "type": "uint256" + } + ], + "name": "issueLoan", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "loanAmount", + "type": "uint256" + } + ], + "name": "loanRepaymentNotification", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "totalLoanAmountCollected", + "type": "uint256" + } + ], + "name": "loanCollectionNotification", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "legacyAugmintTokenAddress", + "type": "address" + }, + { + "name": "newAcceptedState", + "type": "bool" + } + ], + "name": "setAcceptedLegacyAugmintToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "lockDifferenceLimit", + "type": "uint256" + }, + { + "name": "loanDifferenceLimit", + "type": "uint256" + }, + { + "name": "allowedDifferenceAmount", + "type": "uint256" + } + ], + "name": "setLtdParams", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "totalLoanAmountAdjustment", + "type": "uint256" + }, + { + "name": "totalLockedAmountAdjustment", + "type": "uint256" + } + ], + "name": "adjustKPIs", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "newInterestEarnedAccount", + "type": "address" + }, + { + "name": "newAugmintReserves", + "type": "address" + } + ], + "name": "setSystemContracts", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "from", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "", + "type": "uint256" + } + ], + "name": "transferNotification", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "minLockAmount", + "type": "uint256" + }, + { + "name": "interestPt", + "type": "uint256" + } + ], + "name": "getMaxLockAmount", + "outputs": [ + { + "name": "maxLock", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "minLoanAmount", + "type": "uint256" + } + ], + "name": "getMaxLoanAmount", + "outputs": [ + { + "name": "maxLoan", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getMaxLockAmountAllowedByLtd", + "outputs": [ + { + "name": "maxLockByLtd", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getMaxLoanAmountAllowedByLtd", + "outputs": [ + { + "name": "maxLoanByLtd", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/abiniser/abis/PreTokenProxy_ABI_dd40c0d39ea8bad8a388522667a84687.json b/abiniser/abis/PreTokenProxy_ABI_dd40c0d39ea8bad8a388522667a84687.json new file mode 100644 index 00000000..ab525939 --- /dev/null +++ b/abiniser/abis/PreTokenProxy_ABI_dd40c0d39ea8bad8a388522667a84687.json @@ -0,0 +1,332 @@ +{ + "contractName": "PreTokenProxy", + "abiHash": "dd40c0d39ea8bad8a388522667a84687", + "generatedAt": "2018-10-18T13:35:02.451Z", + "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "offset", + "type": "uint256" + }, + { + "name": "chunkSize", + "type": "uint16" + } + ], + "name": "getSigners", + "outputs": [ + { + "name": "", + "type": "uint256[3][]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "offset", + "type": "uint256" + }, + { + "name": "chunkSize", + "type": "uint16" + } + ], + "name": "getScripts", + "outputs": [ + { + "name": "", + "type": "uint256[4][]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "activeSignersCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "scriptAddress", + "type": "address" + } + ], + "name": "cancelScript", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "scriptAddress", + "type": "address" + } + ], + "name": "execute", + "outputs": [ + { + "name": "result", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "isSigner", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "signers", + "type": "address[]" + } + ], + "name": "removeSigners", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getScriptsCount", + "outputs": [ + { + "name": "scriptsCount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "scriptAddresses", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "scripts", + "outputs": [ + { + "name": "state", + "type": "uint8" + }, + { + "name": "signCount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getAllSignersCount", + "outputs": [ + { + "name": "allSignersCount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "allSigners", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "signers", + "type": "address[]" + } + ], + "name": "addSigners", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "scriptAddress", + "type": "address" + } + ], + "name": "sign", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "signer", + "type": "address" + } + ], + "name": "SignerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "signer", + "type": "address" + } + ], + "name": "SignerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "scriptAddress", + "type": "address" + }, + { + "indexed": false, + "name": "signer", + "type": "address" + } + ], + "name": "ScriptSigned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "scriptAddress", + "type": "address" + } + ], + "name": "ScriptApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "scriptAddress", + "type": "address" + } + ], + "name": "ScriptCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "scriptAddress", + "type": "address" + }, + { + "indexed": false, + "name": "result", + "type": "bool" + } + ], + "name": "ScriptExecuted", + "type": "event" + } + ] +} \ No newline at end of file diff --git a/abiniser/abis/PreToken_ABI_7f69e33e7b345c780ac9e43f391437d9.json b/abiniser/abis/PreToken_ABI_7f69e33e7b345c780ac9e43f391437d9.json new file mode 100644 index 00000000..0f73ea60 --- /dev/null +++ b/abiniser/abis/PreToken_ABI_7f69e33e7b345c780ac9e43f391437d9.json @@ -0,0 +1,490 @@ +{ + "contractName": "PreToken", + "abiHash": "7f69e33e7b345c780ac9e43f391437d9", + "generatedAt": "2018-10-18T13:35:02.467Z", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "allAgreements", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "agreementOwners", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "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": "agent", + "type": "address" + }, + { + "name": "requiredPermissions", + "type": "bytes32[]" + } + ], + "name": "revokeMultiplePermissions", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "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": "", + "type": "bytes32" + } + ], + "name": "agreements", + "outputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "balance", + "type": "uint256" + }, + { + "name": "discount", + "type": "uint32" + }, + { + "name": "valuationCap", + "type": "uint32" + } + ], + "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" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "name": "agreementHash", + "type": "bytes32" + }, + { + "indexed": false, + "name": "discount", + "type": "uint32" + }, + { + "indexed": false, + "name": "valuationCap", + "type": "uint32" + } + ], + "name": "NewAgreement", + "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" + }, + { + "constant": false, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "agreementHash", + "type": "bytes32" + }, + { + "name": "discount", + "type": "uint32" + }, + { + "name": "valuationCap", + "type": "uint32" + } + ], + "name": "addAgreement", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "agreementHash", + "type": "bytes32" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "issueTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "agreementHash", + "type": "bytes32" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "burnFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "agreementHash", + "type": "bytes32" + }, + { + "name": "to", + "type": "address" + } + ], + "name": "transferAgreement", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getAgreementsCount", + "outputs": [ + { + "name": "agreementsCount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "offset", + "type": "uint256" + }, + { + "name": "chunkSize", + "type": "uint16" + } + ], + "name": "getAgreements", + "outputs": [ + { + "name": "", + "type": "uint256[6][]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] +} \ No newline at end of file diff --git a/abiniser/abis/StabilityBoardProxy_ABI_dd40c0d39ea8bad8a388522667a84687.json b/abiniser/abis/StabilityBoardProxy_ABI_dd40c0d39ea8bad8a388522667a84687.json new file mode 100644 index 00000000..dd666c92 --- /dev/null +++ b/abiniser/abis/StabilityBoardProxy_ABI_dd40c0d39ea8bad8a388522667a84687.json @@ -0,0 +1,332 @@ +{ + "contractName": "StabilityBoardProxy", + "abiHash": "dd40c0d39ea8bad8a388522667a84687", + "generatedAt": "2018-10-18T13:35:02.446Z", + "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "offset", + "type": "uint256" + }, + { + "name": "chunkSize", + "type": "uint16" + } + ], + "name": "getSigners", + "outputs": [ + { + "name": "", + "type": "uint256[3][]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "offset", + "type": "uint256" + }, + { + "name": "chunkSize", + "type": "uint16" + } + ], + "name": "getScripts", + "outputs": [ + { + "name": "", + "type": "uint256[4][]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "activeSignersCount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "scriptAddress", + "type": "address" + } + ], + "name": "cancelScript", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "scriptAddress", + "type": "address" + } + ], + "name": "execute", + "outputs": [ + { + "name": "result", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "isSigner", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "signers", + "type": "address[]" + } + ], + "name": "removeSigners", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getScriptsCount", + "outputs": [ + { + "name": "scriptsCount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "scriptAddresses", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "scripts", + "outputs": [ + { + "name": "state", + "type": "uint8" + }, + { + "name": "signCount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getAllSignersCount", + "outputs": [ + { + "name": "allSignersCount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "allSigners", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "signers", + "type": "address[]" + } + ], + "name": "addSigners", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "scriptAddress", + "type": "address" + } + ], + "name": "sign", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "signer", + "type": "address" + } + ], + "name": "SignerAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "signer", + "type": "address" + } + ], + "name": "SignerRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "scriptAddress", + "type": "address" + }, + { + "indexed": false, + "name": "signer", + "type": "address" + } + ], + "name": "ScriptSigned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "scriptAddress", + "type": "address" + } + ], + "name": "ScriptApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "scriptAddress", + "type": "address" + } + ], + "name": "ScriptCancelled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "scriptAddress", + "type": "address" + }, + { + "indexed": false, + "name": "result", + "type": "bool" + } + ], + "name": "ScriptExecuted", + "type": "event" + } + ] +} \ No newline at end of file diff --git a/abiniser/abis/TokenAEur_ABI_2ea91d34a7bfefc8f38ef0e8a5ae24a5.json b/abiniser/abis/TokenAEur_ABI_2ea91d34a7bfefc8f38ef0e8a5ae24a5.json new file mode 100644 index 00000000..39a7a5c3 --- /dev/null +++ b/abiniser/abis/TokenAEur_ABI_2ea91d34a7bfefc8f38ef0e8a5ae24a5.json @@ -0,0 +1,809 @@ +{ + "contractName": "TokenAEur", + "abiHash": "2ea91d34a7bfefc8f38ef0e8a5ae24a5", + "generatedAt": "2018-10-18T13:35:02.364Z", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "target", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "data", + "type": "uint256" + } + ], + "name": "transferAndNotify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "issueTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "from", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "address" + } + ], + "name": "balances", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "peggedSymbol", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "newFeeAccount", + "type": "address" + } + ], + "name": "setFeeAccount", + "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": true, + "inputs": [ + { + "name": "", + "type": "address" + }, + { + "name": "", + "type": "address" + } + ], + "name": "allowed", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "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": true, + "inputs": [], + "name": "feeAccount", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseApproval", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "from", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "narrative", + "type": "string" + } + ], + "name": "transferFromWithNarrative", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "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": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "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": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "from", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "narrative", + "type": "string" + }, + { + "name": "maxExecutorFeeInToken", + "type": "uint256" + }, + { + "name": "nonce", + "type": "bytes32" + }, + { + "name": "signature", + "type": "bytes" + }, + { + "name": "requestedExecutorFeeInToken", + "type": "uint256" + } + ], + "name": "delegatedTransfer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_symbol", + "type": "string" + } + ], + "name": "setSymbol", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_name", + "type": "string" + } + ], + "name": "setName", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "from", + "type": "address" + }, + { + "name": "target", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "data", + "type": "uint256" + }, + { + "name": "maxExecutorFeeInToken", + "type": "uint256" + }, + { + "name": "nonce", + "type": "bytes32" + }, + { + "name": "signature", + "type": "bytes" + }, + { + "name": "requestedExecutorFeeInToken", + "type": "uint256" + } + ], + "name": "delegatedTransferAndNotify", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_addedValue", + "type": "uint256" + } + ], + "name": "increaseApproval", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "remaining", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "name": "delegatedTxHashesUsed", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "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" + }, + { + "constant": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "narrative", + "type": "string" + } + ], + "name": "transferWithNarrative", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_permissionGranterContract", + "type": "address" + }, + { + "name": "_feeAccount", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "newFeeAccount", + "type": "address" + } + ], + "name": "FeeAccountChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "transferFeePt", + "type": "uint256" + }, + { + "indexed": false, + "name": "transferFeeMin", + "type": "uint256" + }, + { + "indexed": false, + "name": "transferFeeMax", + "type": "uint256" + } + ], + "name": "TransferFeesChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "narrative", + "type": "string" + }, + { + "indexed": false, + "name": "fee", + "type": "uint256" + } + ], + "name": "AugmintTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenIssued", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "_owner", + "type": "address" + }, + { + "indexed": true, + "name": "_spender", + "type": "address" + }, + { + "indexed": false, + "name": "_value", + "type": "uint256" + } + ], + "name": "Approval", + "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" + } + ] +} \ No newline at end of file diff --git a/abiniser/deployments/1/AugmintReserves_DEPLOYS.json b/abiniser/deployments/1/AugmintReserves_DEPLOYS.json index b7eec472..ec7220a7 100644 --- a/abiniser/deployments/1/AugmintReserves_DEPLOYS.json +++ b/abiniser/deployments/1/AugmintReserves_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "AugmintReserves", - "latestAbiHash": "fe74b7986dafb00f221486e790fc70ec", + "latestAbiHash": "024b81d1a1f75241167a8a0f6e62326f", "deployedAbis": { "fe74b7986dafb00f221486e790fc70ec": { "latestDeployedAddress": "0x633cb544b2ef1bd9269b2111fd2b66fc05cd3477", @@ -19,6 +19,24 @@ "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or StabilityBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is SystemAccount {\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function burn(AugmintTokenInterface augmintToken, uint amount) external restrict(\"MonetarySupervisor\") {\n augmintToken.burn(amount);\n }\n\n}\n" } } + }, + "024b81d1a1f75241167a8a0f6e62326f": { + "latestDeployedAddress": "0x65f30f8dd20c707c1938ccad7416c7381e6eb9c8", + "deployments": { + "0x65f30f8dd20c707c1938ccad7416c7381e6eb9c8": { + "generatedAt": "2018-11-14T12:52:13.027Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.469Z", + "deployTransactionHash": "0x3f6f0c7e6d357fe0e8d195ad850ed5c787c01c99e03a8f64a7c064d429a1b666", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "5bf4ede2aaad5b0b112f7b1ebf420fd2", + "deployedBytecodeHash": "3720667df6506876043fba53c540acb6", + "sourceHash": "b9d84f5f6153164ba581845190291c88", + "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or StabilityBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is Restricted {\n\n event ReserveMigration(address to, uint weiAmount);\n\n constructor(address permissionGranterContract)\n public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function () external payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n function burn(AugmintTokenInterface augmintToken, uint amount)\n external restrict(\"MonetarySupervisor\") {\n augmintToken.burn(amount);\n }\n\n function migrate(address to, uint weiAmount)\n external restrict(\"StabilityBoard\") {\n if (weiAmount > 0) {\n to.transfer(weiAmount);\n }\n emit ReserveMigration(to, weiAmount);\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/1/Exchange_DEPLOYS.json b/abiniser/deployments/1/Exchange_DEPLOYS.json index 989d35a7..ab18e92e 100644 --- a/abiniser/deployments/1/Exchange_DEPLOYS.json +++ b/abiniser/deployments/1/Exchange_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "Exchange", - "latestAbiHash": "c28de2392aea85ef2aa1b108fce6568c", + "latestAbiHash": "d3e7f8a261b756f9c40da097608b21cd", "deployedAbis": { "b2a23202a9a0f04755a186896c2b56eb": { "latestDeployedAddress": "0x8b52b019d237d0bbe8baedf219132d5254e0690b", @@ -50,6 +50,24 @@ "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n uint public constant CHUNK_SIZE = 100;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"buy order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"sell order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price is the price of the maker (the order placed earlier)\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n require(_fillOrder(buyTokenId, sellTokenId), \"fill order failed\");\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Reverts if any match is invalid (e.g sell price > buy price)\n Skips match if any of the matched orders is removed / already filled (i.e. amount = 0)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n if(_fillOrder(buyTokenIds[i], sellTokenIds[i])) {\n matchCount++;\n }\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns CHUNK_SIZE orders starting from offset\n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) {\n uint64 orderId = activeBuyOrders[offset + i];\n Order storage order = buyTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) {\n uint64 orderId = activeSellOrders[offset + i];\n Order storage order = sellTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n uint private constant E12 = 1000000000000;\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private returns(bool success) {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n if( buy.amount == 0 || sell.amount == 0 ) {\n return false; // one order is already filled and removed.\n // we let matchMultiple continue, indivudal match will revert\n }\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n // fillRate = publishedRate * 1000000 / price\n\n uint sellWei = sell.amount.mul(uint(price)).mul(E12).roundedDiv(publishedRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(publishedRate).roundedDiv(uint(price).mul(E12));\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, tradedWei, tradedTokens);\n\n return true;\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n uint lastIndex = activeBuyOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeBuyOrders[lastIndex];\n activeBuyOrders[order.index] = movedOrderId;\n buyTokenOrders[movedOrderId].index = order.index;\n }\n activeBuyOrders.length--;\n }\n\n function _removeSellOrder(Order storage order) private {\n uint lastIndex = activeSellOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeSellOrders[lastIndex];\n activeSellOrders[order.index] = movedOrderId;\n sellTokenOrders[movedOrderId].index = order.index;\n }\n activeSellOrders.length--;\n }\n}\n" } } + }, + "d3e7f8a261b756f9c40da097608b21cd": { + "latestDeployedAddress": "0xc670ffbfa21c37481fb4ef2ea2249b9b78d2b073", + "deployments": { + "0xc670ffbfa21c37481fb4ef2ea2249b9b78d2b073": { + "generatedAt": "2018-11-14T12:52:13.099Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.470Z", + "deployTransactionHash": "0x69fd88f120b060e54cddb1ef2dce3fd3acb2ae3006544a8905933e8bf5ebc85d", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "5a731d45c1595b7ffeb40bae693ef88d", + "deployedBytecodeHash": "136e48f6880df5153792c846d87ddede", + "sourceHash": "d6ff57acb1b45199b5dd08357978d8c2", + "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"buy order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"sell order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price is the price of the maker (the order placed earlier)\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n require(_fillOrder(buyTokenId, sellTokenId), \"fill order failed\");\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Reverts if any match is invalid (e.g sell price > buy price)\n Skips match if any of the matched orders is removed / already filled (i.e. amount = 0)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n if(_fillOrder(buyTokenIds[i], sellTokenIds[i])) {\n matchCount++;\n }\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns active buy orders starting from \n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset, uint16 chunkSize)\n external view returns (uint[4][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), activeBuyOrders.length);\n uint[4][] memory response = new uint[4][](limit.sub(offset));\n for (uint i = offset; i < limit; i++) {\n uint64 orderId = activeBuyOrders[i];\n Order storage order = buyTokenOrders[orderId];\n response[i - offset] = [orderId, uint(order.maker), order.price, order.amount];\n }\n return response;\n }\n\n // returns active sell orders starting from \n // orders are encoded as [id, maker, price, amount]\n function getActiveSellOrders(uint offset, uint16 chunkSize)\n external view returns (uint[4][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), activeSellOrders.length);\n uint[4][] memory response = new uint[4][](limit.sub(offset));\n for (uint i = offset; i < limit; i++) {\n uint64 orderId = activeSellOrders[i];\n Order storage order = sellTokenOrders[orderId];\n response[i - offset] = [orderId, uint(order.maker), order.price, order.amount];\n }\n return response;\n }\n\n uint private constant E12 = 1000000000000;\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private returns(bool success) {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n if( buy.amount == 0 || sell.amount == 0 ) {\n return false; // one order is already filled and removed.\n // we let matchMultiple continue, indivudal match will revert\n }\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n // fillRate = publishedRate * 1000000 / price\n\n uint sellWei = sell.amount.mul(uint(price)).mul(E12).roundedDiv(publishedRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(publishedRate).roundedDiv(uint(price).mul(E12));\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, tradedWei, tradedTokens);\n\n return true;\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n uint lastIndex = activeBuyOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeBuyOrders[lastIndex];\n activeBuyOrders[order.index] = movedOrderId;\n buyTokenOrders[movedOrderId].index = order.index;\n }\n activeBuyOrders.length--;\n }\n\n function _removeSellOrder(Order storage order) private {\n uint lastIndex = activeSellOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeSellOrders[lastIndex];\n activeSellOrders[order.index] = movedOrderId;\n sellTokenOrders[movedOrderId].index = order.index;\n }\n activeSellOrders.length--;\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/1/FeeAccount_DEPLOYS.json b/abiniser/deployments/1/FeeAccount_DEPLOYS.json index ddf2f160..308e28ca 100644 --- a/abiniser/deployments/1/FeeAccount_DEPLOYS.json +++ b/abiniser/deployments/1/FeeAccount_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "67db260db12738df3cced3511d34c65c", "deployedAbis": { "67db260db12738df3cced3511d34c65c": { - "latestDeployedAddress": "0xf6b541e1b5e001dcc11827c1a16232759aea730a", + "latestDeployedAddress": "0xe3ed84a163b9eeaf4f69b4890ae45cc52171aa7e", "deployments": { "0xf6b541e1b5e001dcc11827c1a16232759aea730a": { "generatedAt": "2018-06-11T13:29:06.622Z", @@ -17,6 +17,19 @@ "deployedBytecodeHash": "1a57c03530d204909d1075b452099e77", "sourceHash": "653a2a034144713dc046880dafd503c9", "source": "/* Contract to collect fees from system\n TODO: calculateExchangeFee + Exchange params and setters\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/TransferFeeInterface.sol\";\n\n\ncontract FeeAccount is SystemAccount, TransferFeeInterface {\n\n using SafeMath for uint256;\n\n struct TransferFee {\n uint pt; // in parts per million (ppm) , ie. 2,000 = 0.2%\n uint min; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n uint max; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n }\n\n TransferFee public transferFee;\n\n event TransferFeesChanged(uint transferFeePt, uint transferFeeMin, uint transferFeeMax);\n\n constructor(address permissionGranterContract, uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n public SystemAccount(permissionGranterContract) {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into feeAccount (defaulting fee in ETH )\n }\n\n function setTransferFees(uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n external restrict(\"StabilityBoard\") {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n emit TransferFeesChanged(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function calculateTransferFee(address from, address to, uint amount) external view returns (uint256 fee) {\n if (!permissions[from][\"NoTransferFee\"] && !permissions[to][\"NoTransferFee\"]) {\n fee = amount.mul(transferFee.pt).div(1000000);\n if (fee > transferFee.max) {\n fee = transferFee.max;\n } else if (fee < transferFee.min) {\n fee = transferFee.min;\n }\n }\n return fee;\n }\n\n function calculateExchangeFee(uint weiAmount) external view returns (uint256 weiFee) {\n /* TODO: to be implemented and use in Exchange.sol. always revert for now */\n require(weiAmount != weiAmount, \"not yet implemented\");\n weiFee = transferFee.max; // to silence compiler warnings until it's implemented\n }\n\n}\n" + }, + "0xe3ed84a163b9eeaf4f69b4890ae45cc52171aa7e": { + "generatedAt": "2018-11-14T12:52:13.033Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.474Z", + "deployTransactionHash": "0x5ab749f0dda1932da74e9055eba69e4fbda32f1a26176ae89241f809c1b6526c", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "7f27e332912911a33f3a5831a478a40e", + "deployedBytecodeHash": "62169a6a5b1bc79360f85c7d6b7cbadf", + "sourceHash": "d8975a5e1941ad79313f4b7bb0be9f95", + "source": "/* Contract to collect fees from system\n TODO: calculateExchangeFee + Exchange params and setters\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/TransferFeeInterface.sol\";\n\n\ncontract FeeAccount is SystemAccount, TransferFeeInterface {\n\n using SafeMath for uint256;\n\n struct TransferFee {\n uint pt; // in parts per million (ppm) , ie. 2,000 = 0.2%\n uint min; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n uint max; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n }\n\n TransferFee public transferFee;\n\n event TransferFeesChanged(uint transferFeePt, uint transferFeeMin, uint transferFeeMax);\n\n constructor(address permissionGranterContract, uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n public SystemAccount(permissionGranterContract) {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function () external payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into feeAccount (defaulting fee in ETH )\n }\n\n function setTransferFees(uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n external restrict(\"StabilityBoard\") {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n emit TransferFeesChanged(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function calculateTransferFee(address from, address to, uint amount) external view returns (uint256 fee) {\n if (!permissions[from][\"NoTransferFee\"] && !permissions[to][\"NoTransferFee\"]) {\n fee = amount.mul(transferFee.pt).div(1000000);\n if (fee > transferFee.max) {\n fee = transferFee.max;\n } else if (fee < transferFee.min) {\n fee = transferFee.min;\n }\n }\n return fee;\n }\n\n function calculateExchangeFee(uint weiAmount) external view returns (uint256 weiFee) {\n /* TODO: to be implemented and use in Exchange.sol. always revert for now */\n require(weiAmount != weiAmount, \"not yet implemented\");\n weiFee = transferFee.max; // to silence compiler warnings until it's implemented\n }\n\n}\n" } } } diff --git a/abiniser/deployments/1/InterestEarnedAccount_DEPLOYS.json b/abiniser/deployments/1/InterestEarnedAccount_DEPLOYS.json index b7357ba2..0aa0559a 100644 --- a/abiniser/deployments/1/InterestEarnedAccount_DEPLOYS.json +++ b/abiniser/deployments/1/InterestEarnedAccount_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "11b039ce783db308e1a9b5f46f05824f", "deployedAbis": { "11b039ce783db308e1a9b5f46f05824f": { - "latestDeployedAddress": "0x5c1a44e07541203474d92bdd03f803ea74f6947c", + "latestDeployedAddress": "0xf23e0af0e41341127bb4e7b203aebca0185f9ebd", "deployments": { "0x5c1a44e07541203474d92bdd03f803ea74f6947c": { "generatedAt": "2018-06-11T13:54:29.127Z", @@ -17,6 +17,19 @@ "deployedBytecodeHash": "62cba71783fcbe9a394e7ef9880058da", "sourceHash": "3ae3310cda808efba999807e54bf8c9b", "source": "/* Contract to hold earned interest from loans repaid\n premiums for locks are being accrued (i.e. transferred) to Locker */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract InterestEarnedAccount is SystemAccount {\n\n constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function transferInterest(AugmintTokenInterface augmintToken, address locker, uint interestAmount)\n external restrict(\"MonetarySupervisor\") {\n augmintToken.transfer(locker, interestAmount);\n }\n\n}\n" + }, + "0xf23e0af0e41341127bb4e7b203aebca0185f9ebd": { + "generatedAt": "2018-11-14T12:52:13.038Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.475Z", + "deployTransactionHash": "0x93d43a44973d67d2fd0709b277c7580ab74b1888998b6766fa6c75901720d724", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "3994e47ec4faf784d97e783d6e3de64d", + "deployedBytecodeHash": "9b8b05d9a455663e6bc0b4aa953ef26e", + "sourceHash": "3ae3310cda808efba999807e54bf8c9b", + "source": "/* Contract to hold earned interest from loans repaid\n premiums for locks are being accrued (i.e. transferred) to Locker */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract InterestEarnedAccount is SystemAccount {\n\n constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function transferInterest(AugmintTokenInterface augmintToken, address locker, uint interestAmount)\n external restrict(\"MonetarySupervisor\") {\n augmintToken.transfer(locker, interestAmount);\n }\n\n}\n" } } } diff --git a/abiniser/deployments/1/LoanManager_DEPLOYS.json b/abiniser/deployments/1/LoanManager_DEPLOYS.json index b2cae565..e84f9749 100644 --- a/abiniser/deployments/1/LoanManager_DEPLOYS.json +++ b/abiniser/deployments/1/LoanManager_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "LoanManager", - "latestAbiHash": "ec709c3341045caa3a75374b8cfc7286", + "latestAbiHash": "fdf5fde95aa940c6dbfb8353c572c5fb", "deployedAbis": { "ec709c3341045caa3a75374b8cfc7286": { "latestDeployedAddress": "0xcbefaf199b800deeb9ead61f358ee46e06c54070", @@ -19,6 +19,24 @@ "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - make collect() run as long as gas provided allows\n*/\npragma solidity 0.4.24;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted {\n using SafeMath for uint256;\n\n uint16 public constant CHUNK_SIZE = 100;\n\n enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate\n\n struct LoanProduct {\n uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals\n uint32 term; // 1\n uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1%\n uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */\n struct LoanData {\n uint collateralAmount; // 0\n uint repaymentAmount; // 1\n address borrower; // 2\n uint32 productId; // 3\n LoanState state; // 4\n uint40 maturity; // 5\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n\n event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount, uint40 maturity);\n\n event LoanProductActiveStateChanged(uint32 productId, bool newState);\n\n event LoanProductAdded(uint32 productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n event SystemContractsChanged(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n }\n\n function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount,\n uint32 defaultingFeePt, bool isActive)\n external restrict(\"StabilityBoard\") {\n\n uint _newProductId = products.push(\n LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive)\n ) - 1;\n\n uint32 newProductId = uint32(_newProductId);\n require(newProductId == _newProductId, \"productId overflow\");\n\n emit LoanProductAdded(newProductId);\n }\n\n function setLoanProductActiveState(uint32 productId, bool newState)\n external restrict (\"StabilityBoard\") {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n products[productId].isActive = false;\n emit LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint32 productId) external payable {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n LoanProduct storage product = products[productId];\n require(product.isActive, \"product must be in active state\"); // valid product\n\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000);\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, repaymentAmount);\n\n require(loanAmount >= product.minDisbursedAmount, \"loanAmount must be >= minDisbursedAmount\");\n\n uint expiration = now.add(product.term);\n uint40 maturity = uint40(expiration);\n require(maturity == expiration, \"maturity overflow\");\n\n // Create new loan\n uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender,\n productId, LoanState.Open, maturity)) - 1;\n\n // Store ref to new loan\n accountLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n emit NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity);\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n\n _repayLoan(loanId, repaymentAmount);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n uint totalDefaultingFee;\n for (uint i = 0; i < loanIds.length; i++) {\n require(i < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanIds[i]];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(now >= loan.maturity, \"current time must be later than maturity\");\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount);\n\n loan.state = LoanState.Collected;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(),\n loan.repaymentAmount).add(defaultingFee);\n\n uint releasedCollateral;\n if (targetCollection < loan.collateralAmount) {\n releasedCollateral = loan.collateralAmount.sub(targetCollection);\n loan.borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral);\n if (defaultingFee >= collateralToCollect) {\n defaultingFee = collateralToCollect;\n collateralToCollect = 0;\n } else {\n collateralToCollect = collateralToCollect.sub(defaultingFee);\n }\n totalDefaultingFee = totalDefaultingFee.add(defaultingFee);\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee), releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect);\n }\n\n if (totalDefaultingFee > 0){\n address(augmintToken.feeAccount()).transfer(totalDefaultingFee);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n /* to allow upgrade of Rates and MonetarySupervisor contracts */\n function setSystemContracts(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n monetarySupervisor = newMonetarySupervisor;\n emit SystemContractsChanged(newRatesContract, newMonetarySupervisor);\n }\n\n function getProductCount() external view returns (uint ct) {\n return products.length;\n }\n\n // returns CHUNK_SIZE loan products starting from some offset:\n // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ]\n function getProducts(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= products.length) { break; }\n\n LoanProduct storage product = products[offset + i];\n\n response[i] = [offset + i, product.minDisbursedAmount, product.term, product.discountRate,\n product.collateralRatio, product.defaultingFeePt,\n monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ];\n }\n }\n\n function getLoanCount() external view returns (uint ct) {\n return loans.length;\n }\n\n /* returns CHUNK_SIZE loans starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoans(uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loans.length) { break; }\n\n response[i] = getLoanTuple(offset + i);\n }\n }\n\n function getLoanCountForAddress(address borrower) external view returns (uint) {\n return accountLoans[borrower].length;\n }\n\n /* returns CHUNK_SIZE loans of a given account, starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoansForAddress(address borrower, uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n uint[] storage loansForAddress = accountLoans[borrower];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loansForAddress.length) { break; }\n\n response[i] = getLoanTuple(loansForAddress[offset + i]);\n }\n }\n\n function getLoanTuple(uint loanId) public view returns (uint[10] result) {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n uint disbursementTime = loan.maturity - product.term;\n\n LoanState loanState =\n loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state;\n\n result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower),\n loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount];\n }\n\n function calculateLoanValues(LoanProduct storage product, uint repaymentAmount)\n internal view returns (uint loanAmount, uint interestAmount) {\n // calculate loan values based on repayment amount\n loanAmount = repaymentAmount.mul(product.discountRate).div(1000000);\n interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(repaymentAmount == loan.repaymentAmount, \"repaymentAmount must be equal to tokens sent\");\n require(now <= loan.maturity, \"current time must be earlier than maturity\");\n\n LoanProduct storage product = products[loan.productId];\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n\n loans[loanId].state = LoanState.Repaid;\n\n if (interestAmount > 0) {\n augmintToken.transfer(monetarySupervisor.interestEarnedAccount(), interestAmount);\n augmintToken.burn(loanAmount);\n } else {\n // negative or zero interest (i.e. discountRate >= 0)\n augmintToken.burn(repaymentAmount);\n }\n\n monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs\n\n loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral\n\n emit LoanRepayed(loanId, loan.borrower);\n }\n\n}\n" } } + }, + "fdf5fde95aa940c6dbfb8353c572c5fb": { + "latestDeployedAddress": "0x1cabc34618ecf2949f0405a86353e7705e01c38b", + "deployments": { + "0x1cabc34618ecf2949f0405a86353e7705e01c38b": { + "generatedAt": "2018-11-14T12:52:13.068Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.475Z", + "deployTransactionHash": "0xd5e9fa5fbe38bfa5702451792a191b1b711c43fdb0e4846ae9378cfc3faa8f03", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "591f565c201032e0df4b9f7798e7ec85", + "deployedBytecodeHash": "e93edcccad1eb8f9142f6c257bb23bdd", + "sourceHash": "234fd5848af85ca2444c888fd6ba61aa", + "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - make collect() run as long as gas provided allows\n*/\npragma solidity 0.4.24;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted, TokenReceiver {\n using SafeMath for uint256;\n\n enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate\n\n struct LoanProduct {\n uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals\n uint32 term; // 1\n uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1%\n uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */\n struct LoanData {\n uint collateralAmount; // 0\n uint repaymentAmount; // 1\n address borrower; // 2\n uint32 productId; // 3\n LoanState state; // 4\n uint40 maturity; // 5\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n\n event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount, uint40 maturity);\n\n event LoanProductActiveStateChanged(uint32 productId, bool newState);\n\n event LoanProductAdded(uint32 productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n event SystemContractsChanged(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n }\n\n function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount,\n uint32 defaultingFeePt, bool isActive)\n external restrict(\"StabilityBoard\") {\n\n uint _newProductId = products.push(\n LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive)\n ) - 1;\n\n uint32 newProductId = uint32(_newProductId);\n require(newProductId == _newProductId, \"productId overflow\");\n\n emit LoanProductAdded(newProductId);\n }\n\n function setLoanProductActiveState(uint32 productId, bool newState)\n external restrict (\"StabilityBoard\") {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n products[productId].isActive = newState;\n emit LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint32 productId) external payable {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n LoanProduct storage product = products[productId];\n require(product.isActive, \"product must be in active state\"); // valid product\n\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000);\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, repaymentAmount);\n\n require(loanAmount >= product.minDisbursedAmount, \"loanAmount must be >= minDisbursedAmount\");\n\n uint expiration = now.add(product.term);\n uint40 maturity = uint40(expiration);\n require(maturity == expiration, \"maturity overflow\");\n\n // Create new loan\n uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender,\n productId, LoanState.Open, maturity)) - 1;\n\n // Store ref to new loan\n accountLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n emit NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity);\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n\n _repayLoan(loanId, repaymentAmount);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n uint totalDefaultingFee;\n for (uint i = 0; i < loanIds.length; i++) {\n require(loanIds[i] < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanIds[i]];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(now >= loan.maturity, \"current time must be later than maturity\");\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount);\n\n loan.state = LoanState.Collected;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(),\n loan.repaymentAmount).add(defaultingFee);\n\n uint releasedCollateral;\n if (targetCollection < loan.collateralAmount) {\n releasedCollateral = loan.collateralAmount.sub(targetCollection);\n loan.borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral);\n if (defaultingFee >= collateralToCollect) {\n defaultingFee = collateralToCollect;\n collateralToCollect = 0;\n } else {\n collateralToCollect = collateralToCollect.sub(defaultingFee);\n }\n totalDefaultingFee = totalDefaultingFee.add(defaultingFee);\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee),\n releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect);\n }\n\n if (totalDefaultingFee > 0) {\n address(augmintToken.feeAccount()).transfer(totalDefaultingFee);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n /* to allow upgrade of Rates and MonetarySupervisor contracts */\n function setSystemContracts(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n monetarySupervisor = newMonetarySupervisor;\n emit SystemContractsChanged(newRatesContract, newMonetarySupervisor);\n }\n\n function getProductCount() external view returns (uint) {\n return products.length;\n }\n\n // returns loan products starting from some :\n // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ]\n function getProducts(uint offset, uint16 chunkSize)\n external view returns (uint[8][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), products.length);\n uint[8][] memory response = new uint[8][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n LoanProduct storage product = products[i];\n response[i - offset] = [i, product.minDisbursedAmount, product.term, product.discountRate,\n product.collateralRatio, product.defaultingFeePt,\n monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function getLoanCount() external view returns (uint) {\n return loans.length;\n }\n\n /* returns loans starting from some . Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId,\n state, maturity, disbursementTime, loanAmount, interestAmount] */\n function getLoans(uint offset, uint16 chunkSize)\n external view returns (uint[10][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), loans.length);\n uint[10][] memory response = new uint[10][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n response[i - offset] = getLoanTuple(i);\n }\n return response;\n }\n\n function getLoanCountForAddress(address borrower) external view returns (uint) {\n return accountLoans[borrower].length;\n }\n\n /* returns loans of a given account, starting from some . Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoansForAddress(address borrower, uint offset, uint16 chunkSize)\n external view returns (uint[10][]) {\n uint[] storage loansForAddress = accountLoans[borrower];\n uint limit = SafeMath.min(offset.add(chunkSize), loansForAddress.length);\n uint[10][] memory response = new uint[10][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n response[i - offset] = getLoanTuple(loansForAddress[i]);\n }\n return response;\n }\n\n function getLoanTuple(uint loanId) public view returns (uint[10] result) {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n uint disbursementTime = loan.maturity - product.term;\n\n LoanState loanState =\n loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state;\n\n result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower),\n loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount];\n }\n\n function calculateLoanValues(LoanProduct storage product, uint repaymentAmount)\n internal view returns (uint loanAmount, uint interestAmount) {\n // calculate loan values based on repayment amount\n loanAmount = repaymentAmount.mul(product.discountRate).div(1000000);\n interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(repaymentAmount == loan.repaymentAmount, \"repaymentAmount must be equal to tokens sent\");\n require(now <= loan.maturity, \"current time must be earlier than maturity\");\n\n LoanProduct storage product = products[loan.productId];\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n\n loans[loanId].state = LoanState.Repaid;\n\n if (interestAmount > 0) {\n augmintToken.transfer(monetarySupervisor.interestEarnedAccount(), interestAmount);\n augmintToken.burn(loanAmount);\n } else {\n // negative or zero interest (i.e. discountRate >= 0)\n augmintToken.burn(repaymentAmount);\n }\n\n monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs\n\n loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral\n\n emit LoanRepayed(loanId, loan.borrower);\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/1/Locker_DEPLOYS.json b/abiniser/deployments/1/Locker_DEPLOYS.json index 5dd305c1..3cc73330 100644 --- a/abiniser/deployments/1/Locker_DEPLOYS.json +++ b/abiniser/deployments/1/Locker_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "Locker", - "latestAbiHash": "619ff7809b73aead28176fe6317953c3", + "latestAbiHash": "f59526398823aef0f0c1454d0b6b4eac", "deployedAbis": { "619ff7809b73aead28176fe6317953c3": { "latestDeployedAddress": "0x26438D7c52cE617dFc75A2F02eE816557f01e5Bb", @@ -32,6 +32,24 @@ "source": "/* contract for tracking locked funds\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n -> self-destruct function?\n\n*/\n\npragma solidity 0.4.24;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n uint public constant CHUNK_SIZE = 100;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n event MonetarySupervisorChanged(MonetarySupervisor newMonetarySupervisor);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"StabilityBoard\") {\n\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId, \"lockProduct overflow\");\n emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"StabilityBoard\") {\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n\n lockProducts[lockProductId].isActive = isActive;\n emit LockProductActiveChange(lockProductId, isActive);\n\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n uint32 lockProductId = uint32(_lockProductId);\n require(lockProductId == _lockProductId, \"lockProductId overflow\");\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function releaseFunds(uint lockId) external {\n // next line would revert but require to emit reason:\n require(lockId < locks.length, \"invalid lockId\");\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive, \"lock must be in active state\");\n require(now >= lock.lockedUntil, \"current time must be later than lockedUntil\");\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n emit LockReleased(lock.owner, lockId);\n }\n\n function setMonetarySupervisor(MonetarySupervisor newMonetarySupervisor) external restrict(\"StabilityBoard\") {\n monetarySupervisor = newMonetarySupervisor;\n emit MonetarySupervisorChanged(newMonetarySupervisor);\n }\n\n function getLockProductCount() external view returns (uint) {\n\n return lockProducts.length;\n\n }\n\n // returns 20 lock products starting from some offset\n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ]\n function getLockProducts(uint offset) external view returns (uint[5][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= lockProducts.length) { break; }\n\n LockProduct storage lockProduct = lockProducts[offset + i];\n\n response[i] = [ lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount,\n monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest),\n lockProduct.isActive ? 1 : 0 ];\n }\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns CHUNK_SIZE locks starting from some offset\n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locks.length) { break; }\n\n Lock storage lock = locks[offset + i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [uint(offset + i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n }\n\n // returns CHUNK_SIZE locks of a given account, starting from some offset\n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset) external view returns (uint[7][CHUNK_SIZE] response) {\n\n uint[] storage locksForAddress = accountLocks[lockOwner];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locksForAddress.length) { break; }\n\n Lock storage lock = locks[locksForAddress[offset + i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [ locksForAddress[offset + i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).ceilDiv(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal returns(uint lockId) {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive, \"lockProduct must be in active state\");\n require(amountToLock >= lockProduct.minimumLockAmount, \"amountToLock must be >= minimumLockAmount\");\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration, \"lockedUntil overflow\");\n\n lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs);\n }\n\n}\n" } } + }, + "f59526398823aef0f0c1454d0b6b4eac": { + "latestDeployedAddress": "0x5cc161482e82f20840a4aaeb582becbcc4b539d7", + "deployments": { + "0x5cc161482e82f20840a4aaeb582becbcc4b539d7": { + "generatedAt": "2018-11-14T12:52:13.085Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.480Z", + "deployTransactionHash": "0xffe69e16f5456cdf6b5288b7f423ac4b417b4e127d33ca4540867ee4fa12a736", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "0fe102ad0cf754658fdb075cb2850270", + "deployedBytecodeHash": "211e0b56eb9155bf091df2937a90551d", + "sourceHash": "5fb19771489eecebfa02e95214887146", + "source": "/* contract for tracking locked funds\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n -> self-destruct function?\n\n*/\n\npragma solidity 0.4.24;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n event MonetarySupervisorChanged(MonetarySupervisor newMonetarySupervisor);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"StabilityBoard\") {\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId, \"lockProduct overflow\");\n emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"StabilityBoard\") {\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n\n lockProducts[lockProductId].isActive = isActive;\n emit LockProductActiveChange(lockProductId, isActive);\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n // next line would revert but require to emit reason:\n require(_lockProductId < lockProducts.length, \"invalid lockProductId\");\n uint32 lockProductId = uint32(_lockProductId);\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function releaseFunds(uint lockId) external {\n // next line would revert but require to emit reason:\n require(lockId < locks.length, \"invalid lockId\");\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive, \"lock must be in active state\");\n require(now >= lock.lockedUntil, \"current time must be later than lockedUntil\");\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n emit LockReleased(lock.owner, lockId);\n }\n\n function setMonetarySupervisor(MonetarySupervisor newMonetarySupervisor) external restrict(\"StabilityBoard\") {\n monetarySupervisor = newMonetarySupervisor;\n emit MonetarySupervisorChanged(newMonetarySupervisor);\n }\n\n function getLockProductCount() external view returns (uint) {\n return lockProducts.length;\n }\n\n // returns lock products starting from some \n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ]\n function getLockProducts(uint offset, uint16 chunkSize)\n external view returns (uint[5][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), lockProducts.length);\n uint[5][] memory response = new uint[5][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n LockProduct storage lockProduct = lockProducts[i];\n response[i - offset] = [lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount,\n monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest),\n lockProduct.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns locks starting from some \n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset, uint16 chunkSize)\n external view returns (uint[8][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), locks.length);\n uint[8][] memory response = new uint[8][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n Lock storage lock = locks[i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i - offset] = [uint(i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n return response;\n }\n\n // returns locks of a given account, starting from some \n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset, uint16 chunkSize)\n external view returns (uint[7][]) {\n uint[] storage locksForAddress = accountLocks[lockOwner];\n uint limit = SafeMath.min(offset.add(chunkSize), locksForAddress.length);\n uint[7][] memory response = new uint[7][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n Lock storage lock = locks[locksForAddress[i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i - offset] = [locksForAddress[i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).ceilDiv(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive, \"lockProduct must be in active state\");\n require(amountToLock >= lockProduct.minimumLockAmount, \"amountToLock must be >= minimumLockAmount\");\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration, \"lockedUntil overflow\");\n\n uint lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs);\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/1/Migrations_DEPLOYS.json b/abiniser/deployments/1/Migrations_DEPLOYS.json index 0b99cca8..ec9c8027 100644 --- a/abiniser/deployments/1/Migrations_DEPLOYS.json +++ b/abiniser/deployments/1/Migrations_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "78141a323f4a8416891b06a0a2b90065", "deployedAbis": { "78141a323f4a8416891b06a0a2b90065": { - "latestDeployedAddress": "0xe7e9f87805c0bec5108963d07f85e4ca5892d421", + "latestDeployedAddress": "0xf01C976E9189BC9ba68Eda0f1Dc9d94b243C78dC", "deployments": { "0xe7e9f87805c0bec5108963d07f85e4ca5892d421": { "generatedAt": "2018-06-11T12:47:06.545Z", @@ -17,6 +17,19 @@ "deployedBytecodeHash": "1c74c56a535b7d558a79121649239bdf", "sourceHash": "16ee1835a27505e14d1b6990cdfa8c2c", "source": "pragma solidity 0.4.24;\n\n\ncontract Migrations {\n address public owner;\n uint public last_completed_migration; // solhint-disable-line var-name-mixedcase\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n constructor() public {\n owner = msg.sender;\n }\n\n function setCompleted(uint completed) external restricted {\n last_completed_migration = completed;\n }\n\n function upgrade(address newAddress) external restricted {\n Migrations upgraded = Migrations(newAddress);\n upgraded.setCompleted(last_completed_migration);\n }\n}\n" + }, + "0xf01C976E9189BC9ba68Eda0f1Dc9d94b243C78dC": { + "generatedAt": "2018-11-14T12:52:13.006Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.484Z", + "deployTransactionHash": "0x004664fc07e6877233d9608292037433a6622c0bd946eb70f192f859b5c42de9", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "3bd5779c94259890d586374c5db67f2b", + "deployedBytecodeHash": "f00491b62e24c57c6d12323c73c1037e", + "sourceHash": "16ee1835a27505e14d1b6990cdfa8c2c", + "source": "pragma solidity 0.4.24;\n\n\ncontract Migrations {\n address public owner;\n uint public last_completed_migration; // solhint-disable-line var-name-mixedcase\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n constructor() public {\n owner = msg.sender;\n }\n\n function setCompleted(uint completed) external restricted {\n last_completed_migration = completed;\n }\n\n function upgrade(address newAddress) external restricted {\n Migrations upgraded = Migrations(newAddress);\n upgraded.setCompleted(last_completed_migration);\n }\n}\n" } } } diff --git a/abiniser/deployments/1/MonetarySupervisor_DEPLOYS.json b/abiniser/deployments/1/MonetarySupervisor_DEPLOYS.json index c64bbf7f..ab609147 100644 --- a/abiniser/deployments/1/MonetarySupervisor_DEPLOYS.json +++ b/abiniser/deployments/1/MonetarySupervisor_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "MonetarySupervisor", - "latestAbiHash": "54d27fedd8bf3010ad5509866a42c053", + "latestAbiHash": "7f500b43397413e97de925528187f9cd", "deployedAbis": { "54d27fedd8bf3010ad5509866a42c053": { "latestDeployedAddress": "0x1ca4f9d261707af8a856020a4909b777da218868", @@ -19,6 +19,24 @@ "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n - Converts older versions of AugmintTokens in 1:1 to new\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n uint public constant PERCENT_100 = 1000000;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByStabilityBoard; // token issued by Stability Board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /**********\n Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works\n when total loan or lock amounts are low.\n for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0\n **********/\n struct LtdParams {\n uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above\n (1 - lockDifferenceLimit) with new lock. Stored as parts per million */\n uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above\n (1 + loanDifferenceLimit) with new loan. Stored as parts per million */\n /* allowedDifferenceAmount param is to ensure the system is not \"freezing\" when totalLoanAmount or\n totalLockAmount is low.\n It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above\n lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */\n uint allowedDifferenceAmount;\n }\n\n LtdParams public ltdParams;\n\n /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() )\n NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */\n mapping(address => bool) public acceptedLegacyAugmintTokens;\n\n event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount);\n\n event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState);\n\n event LegacyTokenConverted(address oldTokenAddress, address account, uint amount);\n\n event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment);\n\n event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, AugmintReserves _augmintReserves,\n InterestEarnedAccount _interestEarnedAccount,\n uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n function issueToReserve(uint amount) external restrict(\"StabilityBoard\") {\n issuedByStabilityBoard = issuedByStabilityBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"StabilityBoard\") {\n issuedByStabilityBoard = issuedByStabilityBoard.sub(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function requestInterest(uint amountToLock, uint interestAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n require(amountToLock <= getMaxLockAmountAllowedByLtd(), \"amountToLock must be <= maxLockAmountAllowedByLtd\");\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n // next line would revert but require to emit reason:\n require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount,\n \"interestEarnedAccount balance must be >= interestAmount\");\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n /* Issue loan if LTD stays within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function issueLoan(address borrower, uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n require(loanAmount <= getMaxLoanAmountAllowedByLtd(), \"loanAmount must be <= maxLoanAmountAllowedByLtd\");\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState)\n external restrict(\"StabilityBoard\") {\n acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState;\n emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState);\n }\n\n function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n external restrict(\"StabilityBoard\") {\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n\n emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract\n when it's upgraded.\n Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */\n function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment)\n external restrict(\"StabilityBoard\") {\n totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment);\n totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment);\n\n emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment);\n }\n\n /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */\n function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves)\n external restrict(\"StabilityBoard\") {\n interestEarnedAccount = newInterestEarnedAccount;\n augmintReserves = newAugmintReserves;\n emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves);\n }\n\n /* User can request to convert their tokens from older AugmintToken versions in 1:1\n transferNotification is called from AugmintToken's transferAndNotify\n Flow for converting old tokens:\n 1) user calls old token contract's transferAndNotify with the amount to convert,\n addressing the new MonetarySupervisor Contract\n 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address\n 3) transferAndNotify calls MonetarySupervisor.transferNotification\n 4) MonetarySupervisor checks if old AugmintToken is permitted\n 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken\n 6) MonetarySupervisor burns old tokens from own balance\n */\n function transferNotification(address from, uint amount, uint /* data, not used */ ) external {\n AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender);\n require(acceptedLegacyAugmintTokens[legacyToken], \"msg.sender must be allowed in acceptedLegacyAugmintTokens\");\n\n legacyToken.burn(amount);\n augmintToken.issueTo(from, amount);\n emit LegacyTokenConverted(msg.sender, from, amount);\n }\n\n function getLoanToDepositRatio() external view returns (uint loanToDepositRatio) {\n loanToDepositRatio = totalLockedAmount == 0 ? 0 : totalLockedAmount.mul(PERCENT_100).div(totalLoanAmount);\n }\n\n /* Helper function for UI.\n Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */\n function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) {\n uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt);\n uint allowedByLtd = getMaxLockAmountAllowedByLtd();\n maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd;\n maxLock = maxLock < minLockAmount ? 0 : maxLock;\n }\n\n /* Helper function for UI.\n Returns max loan amount based on minLoanAmont using LTD params */\n function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) {\n uint allowedByLtd = getMaxLoanAmountAllowedByLtd();\n maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd;\n }\n\n /* returns maximum lockable token amount allowed by LTD params. */\n function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) {\n uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100\n .sub(ltdParams.lockDifferenceLimit));\n allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLockedAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLockedAmount >= totalLoanAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount);\n\n maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n /* returns maximum borrowable token amount allowed by LTD params */\n function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) {\n uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100))\n .div(PERCENT_100);\n allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLoanAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount >= totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount);\n\n maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n}\n" } } + }, + "7f500b43397413e97de925528187f9cd": { + "latestDeployedAddress": "0x27484AFe9e6c332fB07F21Fac82d442EBe1D22c3", + "deployments": { + "0x27484AFe9e6c332fB07F21Fac82d442EBe1D22c3": { + "generatedAt": "2018-11-14T12:52:13.052Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.484Z", + "deployTransactionHash": "0x6d043c09e99a1428e5e985e12120024c9da788c02fb2309a9d01bb67b12257f5", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "fa3e6bca24f24d5945b149c05701b69c", + "deployedBytecodeHash": "422b205eb739ddcf33fadad8edf32d7e", + "sourceHash": "62748c793556775f9ac607b991886bfb", + "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n - Converts older versions of AugmintTokens in 1:1 to new\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n uint public constant PERCENT_100 = 1000000;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByStabilityBoard; // token issued by Stability Board\n uint public burnedByStabilityBoard; // token burned by Stability Board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /**********\n Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works\n when total loan or lock amounts are low.\n for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0\n **********/\n struct LtdParams {\n uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above\n (1 - lockDifferenceLimit) with new lock. Stored as parts per million */\n uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above\n (1 + loanDifferenceLimit) with new loan. Stored as parts per million */\n /* allowedDifferenceAmount param is to ensure the system is not \"freezing\" when totalLoanAmount or\n totalLockAmount is low.\n It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above\n lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */\n uint allowedDifferenceAmount;\n }\n\n LtdParams public ltdParams;\n\n /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() )\n NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */\n mapping(address => bool) public acceptedLegacyAugmintTokens;\n\n event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount);\n\n event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState);\n\n event LegacyTokenConverted(address oldTokenAddress, address account, uint amount);\n\n event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment);\n\n event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n AugmintReserves _augmintReserves, InterestEarnedAccount _interestEarnedAccount,\n uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n function issueToReserve(uint amount) external restrict(\"StabilityBoard\") {\n issuedByStabilityBoard = issuedByStabilityBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"StabilityBoard\") {\n burnedByStabilityBoard = burnedByStabilityBoard.add(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function requestInterest(uint amountToLock, uint interestAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n require(amountToLock <= getMaxLockAmountAllowedByLtd(), \"amountToLock must be <= maxLockAmountAllowedByLtd\");\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n // next line would revert but require to emit reason:\n require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount,\n \"interestEarnedAccount balance must be >= interestAmount\");\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n /* Issue loan if LTD stays within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function issueLoan(address borrower, uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n require(loanAmount <= getMaxLoanAmountAllowedByLtd(), \"loanAmount must be <= maxLoanAmountAllowedByLtd\");\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState)\n external restrict(\"StabilityBoard\") {\n acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState;\n emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState);\n }\n\n function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n external restrict(\"StabilityBoard\") {\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract\n when it's upgraded.\n Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */\n function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment)\n external restrict(\"StabilityBoard\") {\n totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment);\n totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment);\n emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment);\n }\n\n /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */\n function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves)\n external restrict(\"StabilityBoard\") {\n interestEarnedAccount = newInterestEarnedAccount;\n augmintReserves = newAugmintReserves;\n emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves);\n }\n\n /* User can request to convert their tokens from older AugmintToken versions in 1:1\n transferNotification is called from AugmintToken's transferAndNotify\n Flow for converting old tokens:\n 1) user calls old token contract's transferAndNotify with the amount to convert,\n addressing the new MonetarySupervisor Contract\n 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address\n 3) transferAndNotify calls MonetarySupervisor.transferNotification\n 4) MonetarySupervisor checks if old AugmintToken is permitted\n 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken\n 6) MonetarySupervisor burns old tokens from own balance\n */\n function transferNotification(address from, uint amount, uint /* data, not used */ ) external {\n AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender);\n require(acceptedLegacyAugmintTokens[legacyToken], \"msg.sender must be allowed in acceptedLegacyAugmintTokens\");\n\n legacyToken.burn(amount);\n augmintToken.issueTo(from, amount);\n emit LegacyTokenConverted(msg.sender, from, amount);\n }\n\n /* Helper function for UI.\n Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */\n function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) {\n uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt);\n uint allowedByLtd = getMaxLockAmountAllowedByLtd();\n maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd;\n maxLock = maxLock < minLockAmount ? 0 : maxLock;\n }\n\n /* Helper function for UI.\n Returns max loan amount based on minLoanAmont using LTD params */\n function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) {\n uint allowedByLtd = getMaxLoanAmountAllowedByLtd();\n maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd;\n }\n\n /* returns maximum lockable token amount allowed by LTD params. */\n function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) {\n uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100\n .sub(ltdParams.lockDifferenceLimit));\n allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLockedAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLockedAmount >= totalLoanAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount);\n\n maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n /* returns maximum borrowable token amount allowed by LTD params */\n function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) {\n uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100))\n .div(PERCENT_100);\n allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLoanAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount >= totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount);\n\n maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/1/PreTokenProxy_DEPLOYS.json b/abiniser/deployments/1/PreTokenProxy_DEPLOYS.json index 8331cd9a..6712a259 100644 --- a/abiniser/deployments/1/PreTokenProxy_DEPLOYS.json +++ b/abiniser/deployments/1/PreTokenProxy_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "PreTokenProxy", - "latestAbiHash": "19ab69b650e28b2dd211d3851893f91f", + "latestAbiHash": "dd40c0d39ea8bad8a388522667a84687", "deployedAbis": { "19ab69b650e28b2dd211d3851893f91f": { "latestDeployedAddress": "0x1411b3b189b01f6e6d1ea883bffcbd3a5224934c", @@ -19,6 +19,24 @@ "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract PreTokenProxy is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" } } + }, + "dd40c0d39ea8bad8a388522667a84687": { + "latestDeployedAddress": "0x8a69cf9d1d85bc150f69feb80cc34c552f5fbea9", + "deployments": { + "0x8a69cf9d1d85bc150f69feb80cc34c552f5fbea9": { + "generatedAt": "2018-11-14T12:52:13.107Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.490Z", + "deployTransactionHash": "0xf6a3f95b073e7bc0503691f0d3b68ab0837e9939d4c8f8a9febf284a9254a5e6", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "5007bce3d0997985a9357d5b1a97103b", + "deployedBytecodeHash": "b5a32ad0b8570f3cd6b7efaef3655911", + "sourceHash": "2d172fe41d2b97c827d6dca816138047", + "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract PreTokenProxy is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/1/PreToken_DEPLOYS.json b/abiniser/deployments/1/PreToken_DEPLOYS.json index 3f9f06d6..cf93a3d5 100644 --- a/abiniser/deployments/1/PreToken_DEPLOYS.json +++ b/abiniser/deployments/1/PreToken_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "PreToken", - "latestAbiHash": "10eebbb51a771cfd3473475169a569f1", + "latestAbiHash": "7f69e33e7b345c780ac9e43f391437d9", "deployedAbis": { "10eebbb51a771cfd3473475169a569f1": { "latestDeployedAddress": "0xecb782b19be6e657ae2d88831dd98145a00d32d5", @@ -19,6 +19,24 @@ "source": "/* Augmint pretoken contract to record agreements and tokens allocated based on the agreement.\n\n Important: this is NOT an ERC20 token!\n\n PreTokens are non-fungible: agreements can have different conditions (valuationCap and discount)\n and pretokens are not tradable.\n\n Ownership can be transferred if owner wants to change wallet but the whole agreement and\n the total pretoken amount is moved to a new account\n\n PreTokenSigner can (via MultiSig):\n - add agreements and issue pretokens to an agreement\n - change owner of any agreement to handle if an owner lost a private keys\n - burn pretokens from any agreement to fix potential erroneous issuance\n These are known compromises on trustlessness hence all these tokens distributed based on signed agreements and\n preTokens are issued only to a closed group of contributors / team members.\n If despite these something goes wrong then as a last resort a new pretoken contract can be recreated from agreements.\n\n Some ERC20 functions are implemented so agreement owners can see their balances and use transfer in standard wallets.\n Restrictions:\n - only total balance can be transfered - effectively ERC20 transfer used to transfer agreement ownership\n - only agreement holders can transfer\n (i.e. can't transfer 0 amount if have no agreement to avoid polluting logs with Transfer events)\n - transfer is only allowed to accounts without an agreement yet\n - no approval and transferFrom ERC20 functions\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract PreToken is Restricted {\n using SafeMath for uint256;\n\n uint public constant CHUNK_SIZE = 100;\n\n string constant public name = \"Augmint pretokens\"; // solhint-disable-line const-name-snakecase\n string constant public symbol = \"APRE\"; // solhint-disable-line const-name-snakecase\n uint8 constant public decimals = 0; // solhint-disable-line const-name-snakecase\n\n uint public totalSupply;\n\n struct Agreement {\n address owner;\n uint balance;\n uint32 discount; // discountRate in parts per million , ie. 10,000 = 1%\n uint32 valuationCap; // in USD (no decimals)\n }\n\n /* Agreement hash is the SHA-2 (SHA-256) hash of signed agreement document.\n To generate:\n OSX: shasum -a 256 agreement.pdf\n Windows: certUtil -hashfile agreement.pdf SHA256 */\n mapping(address => bytes32) public agreementOwners; // to lookup agrement by owner\n mapping(bytes32 => Agreement) public agreements;\n\n bytes32[] public allAgreements; // all agreements to able to iterate over\n\n event Transfer(address indexed from, address indexed to, uint amount);\n\n event NewAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap);\n\n constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function addAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap)\n external restrict(\"PreTokenSigner\") {\n require(owner != address(0), \"owner must not be 0x0\");\n require(agreementOwners[owner] == 0x0, \"owner must not have an aggrement yet\");\n require(agreementHash != 0x0, \"agreementHash must not be 0x0\");\n require(discount > 0, \"discount must be > 0\");\n require(agreements[agreementHash].discount == 0, \"agreement must not exist yet\");\n\n agreements[agreementHash] = Agreement(owner, 0, discount, valuationCap);\n agreementOwners[owner] = agreementHash;\n allAgreements.push(agreementHash);\n\n emit NewAgreement(owner, agreementHash, discount, valuationCap);\n }\n\n function issueTo(bytes32 agreementHash, uint amount) external restrict(\"PreTokenSigner\") {\n Agreement storage agreement = agreements[agreementHash];\n require(agreement.discount > 0, \"agreement must exist\");\n\n agreement.balance = agreement.balance.add(amount);\n totalSupply = totalSupply.add(amount);\n\n emit Transfer(0x0, agreement.owner, amount);\n }\n\n /* Restricted function to allow pretoken signers to fix incorrect issuance */\n function burnFrom(bytes32 agreementHash, uint amount)\n public restrict(\"PreTokenSigner\") returns (bool) {\n Agreement storage agreement = agreements[agreementHash];\n require(agreement.discount > 0, \"agreement must exist\"); // this is redundant b/c of next requires but be explicit\n require(amount > 0, \"burn amount must be > 0\");\n require(agreement.balance >= amount, \"must not burn more than balance\"); // .sub would revert anyways but emit reason\n\n agreement.balance = agreement.balance.sub(amount);\n totalSupply = totalSupply.sub(amount);\n\n emit Transfer(agreement.owner, 0x0, amount);\n return true;\n }\n\n function balanceOf(address owner) public view returns (uint) {\n return agreements[agreementOwners[owner]].balance;\n }\n\n /* function to transfer agreement ownership to other wallet by owner\n it's in ERC20 form so owners can use standard ERC20 wallet just need to pass full balance as value */\n function transfer(address to, uint amount) public returns (bool) { // solhint-disable-line no-simple-event-func-name\n require(amount == agreements[agreementOwners[msg.sender]].balance, \"must transfer full balance\");\n _transfer(msg.sender, to);\n return true;\n }\n\n /* Restricted function to allow pretoken signers to fix if pretoken owner lost keys */\n function transferAgreement(bytes32 agreementHash, address to)\n public restrict(\"PreTokenSigner\") returns (bool) {\n _transfer(agreements[agreementHash].owner, to);\n return true;\n }\n\n /* private function used by transferAgreement & transfer */\n function _transfer(address from, address to) private {\n Agreement storage agreement = agreements[agreementOwners[from]];\n require(agreementOwners[from] != 0x0, \"from agreement must exists\");\n require(agreementOwners[to] == 0, \"to must not have an agreement\");\n require(to != 0x0, \"must not transfer to 0x0\");\n\n agreement.owner = to;\n\n agreementOwners[to] = agreementOwners[from];\n agreementOwners[from] = 0x0;\n\n emit Transfer(from, to, agreement.balance);\n }\n\n function getAgreementsCount() external view returns (uint agreementsCount) {\n return allAgreements.length;\n }\n\n // UI helper fx - Returns all agreements from offset as\n // [index in allAgreements, account address as uint, balance, agreementHash as uint,\n // discount as uint, valuationCap as uint ]\n function getAllAgreements(uint offset) external view returns(uint[6][CHUNK_SIZE] agreementsResult) {\n\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < allAgreements.length; i++) {\n bytes32 agreementHash = allAgreements[i + offset];\n Agreement storage agreement = agreements[agreementHash];\n\n agreementsResult[i] = [ i + offset, uint(agreement.owner), agreement.balance,\n uint(agreementHash), uint(agreement.discount), uint(agreement.valuationCap)];\n }\n }\n}\n" } } + }, + "7f69e33e7b345c780ac9e43f391437d9": { + "latestDeployedAddress": "0x97ea02179801fa94227db5fc1d13ac4277d40920", + "deployments": { + "0x97ea02179801fa94227db5fc1d13ac4277d40920": { + "generatedAt": "2018-11-14T12:52:13.115Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.487Z", + "deployTransactionHash": "0x4b26c0cee55d8431019bd8c0b47fa8221455e3711f648dcd52bde7c797dfa31c", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "8d7e449258facd1c6fab22b402de6aee", + "deployedBytecodeHash": "bf64976158eb4f8696efd994652e7f49", + "sourceHash": "6cace117c42478e4f5c8cf116bec9a62", + "source": "/* Augmint pretoken contract to record agreements and tokens allocated based on the agreement.\n\n Important: this is NOT an ERC20 token!\n\n PreTokens are non-fungible: agreements can have different conditions (valuationCap and discount)\n and pretokens are not tradable.\n\n Ownership can be transferred if owner wants to change wallet but the whole agreement and\n the total pretoken amount is moved to a new account\n\n PreTokenSigner can (via MultiSig):\n - add agreements and issue pretokens to an agreement\n - change owner of any agreement to handle if an owner lost a private keys\n - burn pretokens from any agreement to fix potential erroneous issuance\n These are known compromises on trustlessness hence all these tokens distributed based on signed agreements and\n preTokens are issued only to a closed group of contributors / team members.\n If despite these something goes wrong then as a last resort a new pretoken contract can be recreated from agreements.\n\n Some ERC20 functions are implemented so agreement owners can see their balances and use transfer in standard wallets.\n Restrictions:\n - only total balance can be transfered - effectively ERC20 transfer used to transfer agreement ownership\n - only agreement holders can transfer\n (i.e. can't transfer 0 amount if have no agreement to avoid polluting logs with Transfer events)\n - transfer is only allowed to accounts without an agreement yet\n - no approval and transferFrom ERC20 functions\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract PreToken is Restricted {\n using SafeMath for uint256;\n\n string constant public name = \"Augmint pretokens\"; // solhint-disable-line const-name-snakecase\n string constant public symbol = \"APRE\"; // solhint-disable-line const-name-snakecase\n uint8 constant public decimals = 0; // solhint-disable-line const-name-snakecase\n\n uint public totalSupply;\n\n struct Agreement {\n address owner;\n uint balance;\n uint32 discount; // discountRate in parts per million , ie. 10,000 = 1%\n uint32 valuationCap; // in USD (no decimals)\n }\n\n /* Agreement hash is the SHA-2 (SHA-256) hash of signed agreement document.\n To generate:\n OSX: shasum -a 256 agreement.pdf\n Windows: certUtil -hashfile agreement.pdf SHA256 */\n mapping(address => bytes32) public agreementOwners; // to lookup agrement by owner\n mapping(bytes32 => Agreement) public agreements;\n\n bytes32[] public allAgreements; // all agreements to able to iterate over\n\n event Transfer(address indexed from, address indexed to, uint amount);\n\n event NewAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap);\n\n constructor(address permissionGranterContract)\n public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function addAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap)\n external restrict(\"PreTokenSigner\") {\n require(owner != address(0), \"owner must not be 0x0\");\n require(agreementOwners[owner] == 0x0, \"owner must not have an aggrement yet\");\n require(agreementHash != 0x0, \"agreementHash must not be 0x0\");\n require(discount > 0, \"discount must be > 0\");\n require(agreements[agreementHash].discount == 0, \"agreement must not exist yet\");\n\n agreements[agreementHash] = Agreement(owner, 0, discount, valuationCap);\n agreementOwners[owner] = agreementHash;\n allAgreements.push(agreementHash);\n\n emit NewAgreement(owner, agreementHash, discount, valuationCap);\n }\n\n function issueTo(bytes32 agreementHash, uint amount) external restrict(\"PreTokenSigner\") {\n Agreement storage agreement = agreements[agreementHash];\n require(agreement.discount > 0, \"agreement must exist\");\n\n agreement.balance = agreement.balance.add(amount);\n totalSupply = totalSupply.add(amount);\n\n emit Transfer(0x0, agreement.owner, amount);\n }\n\n /* Restricted function to allow pretoken signers to fix incorrect issuance */\n function burnFrom(bytes32 agreementHash, uint amount)\n public restrict(\"PreTokenSigner\") returns (bool) {\n Agreement storage agreement = agreements[agreementHash];\n // this is redundant b/c of next requires but be explicit\n require(agreement.discount > 0, \"agreement must exist\");\n require(amount > 0, \"burn amount must be > 0\");\n // .sub would revert anyways but emit reason\n require(agreement.balance >= amount, \"must not burn more than balance\");\n\n agreement.balance = agreement.balance.sub(amount);\n totalSupply = totalSupply.sub(amount);\n\n emit Transfer(agreement.owner, 0x0, amount);\n return true;\n }\n\n function balanceOf(address owner) public view returns (uint) {\n return agreements[agreementOwners[owner]].balance;\n }\n\n /* function to transfer agreement ownership to other wallet by owner\n it's in ERC20 form so owners can use standard ERC20 wallet just need to pass full balance as value */\n function transfer(address to, uint amount) public returns (bool) { // solhint-disable-line no-simple-event-func-name\n require(amount == agreements[agreementOwners[msg.sender]].balance, \"must transfer full balance\");\n _transfer(msg.sender, to);\n return true;\n }\n\n /* Restricted function to allow pretoken signers to fix if pretoken owner lost keys */\n function transferAgreement(bytes32 agreementHash, address to)\n public restrict(\"PreTokenSigner\") returns (bool) {\n _transfer(agreements[agreementHash].owner, to);\n return true;\n }\n\n /* private function used by transferAgreement & transfer */\n function _transfer(address from, address to) private {\n Agreement storage agreement = agreements[agreementOwners[from]];\n require(agreementOwners[from] != 0x0, \"from agreement must exists\");\n require(agreementOwners[to] == 0, \"to must not have an agreement\");\n require(to != 0x0, \"must not transfer to 0x0\");\n\n agreement.owner = to;\n\n agreementOwners[to] = agreementOwners[from];\n agreementOwners[from] = 0x0;\n\n emit Transfer(from, to, agreement.balance);\n }\n\n function getAgreementsCount() external view returns (uint agreementsCount) {\n return allAgreements.length;\n }\n\n // UI helper fx - Returns agreements from as\n // [index in allAgreements, account address as uint, balance, agreementHash as uint,\n // discount as uint, valuationCap as uint ]\n function getAgreements(uint offset, uint16 chunkSize)\n external view returns(uint[6][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), allAgreements.length);\n uint[6][] memory response = new uint[6][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n bytes32 agreementHash = allAgreements[i];\n Agreement storage agreement = agreements[agreementHash];\n\n response[i - offset] = [i, uint(agreement.owner), agreement.balance,\n uint(agreementHash), uint(agreement.discount), uint(agreement.valuationCap)];\n }\n return response;\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/1/Rates_DEPLOYS.json b/abiniser/deployments/1/Rates_DEPLOYS.json index 49bef6cc..f3a32103 100644 --- a/abiniser/deployments/1/Rates_DEPLOYS.json +++ b/abiniser/deployments/1/Rates_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "73a17ebb0acc71773371c6a8e1c8e6ce", "deployedAbis": { "73a17ebb0acc71773371c6a8e1c8e6ce": { - "latestDeployedAddress": "0x4babbe57453e2b6af125b4e304256fcbdf744480", + "latestDeployedAddress": "0x4272dB2EB82068E898588C3D6e4B5D55c3848793", "deployments": { "0x4babbe57453e2b6af125b4e304256fcbdf744480": { "generatedAt": "2018-06-11T12:15:16.443Z", @@ -17,6 +17,19 @@ "deployedBytecodeHash": "6a3a4ec8c050710692adaa9f97d09bb6", "sourceHash": "d71ec203e7ee6ed376feeb17e5df7966", "source": "/*\n Generic symbol / WEI rates contract.\n only callable by trusted price oracles.\n Being regularly called by a price oracle\n TODO: trustless/decentrilezed price Oracle\n TODO: shall we use blockNumber instead of now for lastUpdated?\n TODO: consider if we need storing rates with variable decimals instead of fixed 4\n TODO: could we emit 1 RateChanged event from setMultipleRates (symbols and newrates arrays)?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract Rates is Restricted {\n using SafeMath for uint256;\n\n struct RateInfo {\n uint rate; // how much 1 WEI worth 1 unit , i.e. symbol/ETH rate\n // 0 rate means no rate info available\n uint lastUpdated;\n }\n\n // mapping currency symbol => rate. all rates are stored with 4 decimals. i.e. ETH/EUR = 989.12 then rate = 989,1200\n mapping(bytes32 => RateInfo) public rates;\n\n event RateChanged(bytes32 symbol, uint newRate);\n\n constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function setRate(bytes32 symbol, uint newRate) external restrict(\"RatesFeeder\") {\n rates[symbol] = RateInfo(newRate, now);\n emit RateChanged(symbol, newRate);\n }\n\n function setMultipleRates(bytes32[] symbols, uint[] newRates) external restrict(\"RatesFeeder\") {\n require(symbols.length == newRates.length, \"symobls and newRates lengths must be equal\");\n for (uint256 i = 0; i < symbols.length; i++) {\n rates[symbols[i]] = RateInfo(newRates[i], now);\n emit RateChanged(symbols[i], newRates[i]);\n }\n }\n\n function convertFromWei(bytes32 bSymbol, uint weiValue) external view returns(uint value) {\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n return weiValue.mul(rates[bSymbol].rate).roundedDiv(1000000000000000000);\n }\n\n function convertToWei(bytes32 bSymbol, uint value) external view returns(uint weiValue) {\n // next line would revert with div by zero but require to emit reason\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n /* TODO: can we make this not loosing max scale? */\n return value.mul(1000000000000000000).roundedDiv(rates[bSymbol].rate);\n }\n\n}\n" + }, + "0x4272dB2EB82068E898588C3D6e4B5D55c3848793": { + "generatedAt": "2018-11-14T12:52:13.016Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.490Z", + "deployTransactionHash": "0x3a0ca0223275fc414b93f60548060dc1e4329deaaa14b46460a9ca28bfc322ea", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "be17116585b9b88d60fbe06a5499b6dc", + "deployedBytecodeHash": "0f403183577dac202159e32b1c8c9f44", + "sourceHash": "c65f6945fead6118910fccc8bca7494c", + "source": "/*\n Generic symbol / WEI rates contract.\n only callable by trusted price oracles.\n Being regularly called by a price oracle\n TODO: trustless/decentrilezed price Oracle\n TODO: shall we use blockNumber instead of now for lastUpdated?\n TODO: consider if we need storing rates with variable decimals instead of fixed 4\n TODO: could we emit 1 RateChanged event from setMultipleRates (symbols and newrates arrays)?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract Rates is Restricted {\n using SafeMath for uint256;\n\n struct RateInfo {\n uint rate; // how much 1 WEI worth 1 unit , i.e. symbol/ETH rate\n // 0 rate means no rate info available\n uint lastUpdated;\n }\n\n // mapping currency symbol => rate. all rates are stored with 2 decimals. i.e. EUR/ETH = 989.12 then rate = 98912\n mapping(bytes32 => RateInfo) public rates;\n\n event RateChanged(bytes32 symbol, uint newRate);\n\n constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function setRate(bytes32 symbol, uint newRate) external restrict(\"RatesFeeder\") {\n rates[symbol] = RateInfo(newRate, now);\n emit RateChanged(symbol, newRate);\n }\n\n function setMultipleRates(bytes32[] symbols, uint[] newRates) external restrict(\"RatesFeeder\") {\n require(symbols.length == newRates.length, \"symobls and newRates lengths must be equal\");\n for (uint256 i = 0; i < symbols.length; i++) {\n rates[symbols[i]] = RateInfo(newRates[i], now);\n emit RateChanged(symbols[i], newRates[i]);\n }\n }\n\n function convertFromWei(bytes32 bSymbol, uint weiValue) external view returns(uint value) {\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n return weiValue.mul(rates[bSymbol].rate).roundedDiv(1000000000000000000);\n }\n\n function convertToWei(bytes32 bSymbol, uint value) external view returns(uint weiValue) {\n // next line would revert with div by zero but require to emit reason\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n /* TODO: can we make this not loosing max scale? */\n return value.mul(1000000000000000000).roundedDiv(rates[bSymbol].rate);\n }\n\n}\n" } } } diff --git a/abiniser/deployments/1/StabilityBoardProxy_DEPLOYS.json b/abiniser/deployments/1/StabilityBoardProxy_DEPLOYS.json index 6301f93f..57b7eec7 100644 --- a/abiniser/deployments/1/StabilityBoardProxy_DEPLOYS.json +++ b/abiniser/deployments/1/StabilityBoardProxy_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "StabilityBoardProxy", - "latestAbiHash": "19ab69b650e28b2dd211d3851893f91f", + "latestAbiHash": "dd40c0d39ea8bad8a388522667a84687", "deployedAbis": { "19ab69b650e28b2dd211d3851893f91f": { "latestDeployedAddress": "0x4686f017d456331ed2c1de66e134d8d05b24413d", @@ -19,6 +19,24 @@ "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract StabilityBoardProxy is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" } } + }, + "dd40c0d39ea8bad8a388522667a84687": { + "latestDeployedAddress": "0xde36a8773531406dcbeffdfd3c7b89fced7a9f84", + "deployments": { + "0xde36a8773531406dcbeffdfd3c7b89fced7a9f84": { + "generatedAt": "2018-11-14T12:52:13.104Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.516Z", + "deployTransactionHash": "0xcb0e9651d51ba99070837dcf083acfcc3f13df8c146b4a01c8bf6f4d2a924d41", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "4f899546765577ad2e325da53c3e7179", + "deployedBytecodeHash": "a5f3dd7878e556db538c1206827e5959", + "sourceHash": "4d60c55b8e4009873db939b37558d9dc", + "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract StabilityBoardProxy is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/1/TokenAEur_DEPLOYS.json b/abiniser/deployments/1/TokenAEur_DEPLOYS.json index f840b3e9..47a9558a 100644 --- a/abiniser/deployments/1/TokenAEur_DEPLOYS.json +++ b/abiniser/deployments/1/TokenAEur_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "TokenAEur", - "latestAbiHash": "9aa81519ec45a52d3f8f1a1a83d25c74", + "latestAbiHash": "2ea91d34a7bfefc8f38ef0e8a5ae24a5", "deployedAbis": { "9aa81519ec45a52d3f8f1a1a83d25c74": { "latestDeployedAddress": "0x86a635eccefffa70ff8a6db29da9c8db288e40d0", @@ -19,6 +19,24 @@ "source": "/* Augmint Crypto Euro token (A-EUR) implementation */\npragma solidity 0.4.24;\nimport \"./interfaces/TransferFeeInterface.sol\";\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n constructor(address _permissionGranterContract, TransferFeeInterface _feeAccount)\n public AugmintToken(_permissionGranterContract, \"Augmint Crypto Euro\", \"AEUR\", \"EUR\", 2, _feeAccount)\n {} // solhint-disable-line no-empty-blocks\n\n}\n" } } + }, + "2ea91d34a7bfefc8f38ef0e8a5ae24a5": { + "latestDeployedAddress": "0xc994a2deb02543db1f48688438b9903c4b305ce3", + "deployments": { + "0xc994a2deb02543db1f48688438b9903c4b305ce3": { + "generatedAt": "2018-11-14T12:52:13.041Z", + "truffleContractFileUpdatedAt": "2018-11-13T16:34:24.517Z", + "deployTransactionHash": "0x55a49768013ad9201ab71c8cf91cea967f2165d2a3f2e025a0beb7631c4b8f30", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "0398a39cdab3b394103910ea6b28eef7", + "deployedBytecodeHash": "2916088286d725e884630bc95fc19dbf", + "sourceHash": "04025a37ea64acbc6f0ea2ec8a6f3e4d", + "source": "/* Augmint Euro token (A-EUR) implementation */\npragma solidity 0.4.24;\nimport \"./interfaces/TransferFeeInterface.sol\";\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n constructor(address _permissionGranterContract, TransferFeeInterface _feeAccount)\n public AugmintToken(_permissionGranterContract, \"Augmint Euro\", \"AEUR\", \"EUR\", 2, _feeAccount)\n {} // solhint-disable-line no-empty-blocks\n\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/4/AugmintReserves_DEPLOYS.json b/abiniser/deployments/4/AugmintReserves_DEPLOYS.json index 0c99923f..73e5fc46 100644 --- a/abiniser/deployments/4/AugmintReserves_DEPLOYS.json +++ b/abiniser/deployments/4/AugmintReserves_DEPLOYS.json @@ -1,82 +1,35 @@ { "contractName": "AugmintReserves", - "latestAbiHash": "fe74b7986dafb00f221486e790fc70ec", + "latestAbiHash": "024b81d1a1f75241167a8a0f6e62326f", "deployedAbis": { - "dfbca9f4d0da7a3517b2832dc1c04d9a": { - "latestDeployedAddress": "0xf1ea22d0d75f0d247a0b43a45423392ee9b1ae86", + "024b81d1a1f75241167a8a0f6e62326f": { + "latestDeployedAddress": "0x33bec125657470e53887400666bdeed360b2168a", "deployments": { - "0x7cbaa389f8ba06790925d167ae795edb939a0d1a": { - "generatedAt": "2018-04-25T12:29:07.528Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:23:03.215Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "a437bda1eb8e4840c187e6bfcaf70e85", - "deployedBytecodeHash": "dbedf5fee478ed0af1ad2a1a5b7576e8", - "sourceHash": "74ed728bb0a86f1bfb854c62b2c39633", - "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or MonetaryBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.19;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is SystemAccount {\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n function burn(AugmintTokenInterface augmintToken, uint amount) external restrict(\"MonetarySupervisorContract\") {\n augmintToken.burn(amount);\n }\n\n}\n" - }, - "0xf1ea22d0d75f0d247a0b43a45423392ee9b1ae86": { - "generatedAt": "2018-04-25T12:30:49.066Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:25:57.853Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "141a9efe96eafc3443a43c64651fccbe", - "deployedBytecodeHash": "efad357d73a7669e916fb1efce5648a4", - "sourceHash": "74ed728bb0a86f1bfb854c62b2c39633", - "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or MonetaryBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.19;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is SystemAccount {\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n function burn(AugmintTokenInterface augmintToken, uint amount) external restrict(\"MonetarySupervisorContract\") {\n augmintToken.burn(amount);\n }\n\n}\n" - } - } - }, - "33995f203f6c629e9916d82dd78e875f": { - "latestDeployedAddress": "0xc70b65e40f877cdc6d8d2ebfd44d63efbeb7fc6d", - "deployments": { - "0xc70b65e40f877cdc6d8d2ebfd44d63efbeb7fc6d": { - "generatedAt": "2018-04-25T12:31:29.003Z", - "truffleContractFileUpdatedAt": "2018-04-20T18:14:08.862Z", - "deployTransactionHash": "0x4b9c761e7a807a4a476414e5a920d65c6a7b319b69c7607fd353c4486c3413e9", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "7a5b30598800cdd29ccd600d1342b26a", - "deployedBytecodeHash": "c64995bfa42dc887ffeaf649da038f6e", - "sourceHash": "c3fd200d4510ea1b3d7c6c7ae04683b9", - "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or MonetaryBoard or MonetarySupervisor)\n\n */\n\npragma solidity ^0.4.23;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is SystemAccount {\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n function burn(AugmintTokenInterface augmintToken, uint amount) external restrict(\"MonetarySupervisorContract\") {\n augmintToken.burn(amount);\n }\n\n}\n" - } - } - }, - "fe74b7986dafb00f221486e790fc70ec": { - "latestDeployedAddress": "0x6386f25d2029ea3164838bf6494ed85c01fc1b03", - "deployments": { - "0x8cfef73cf8cfbb78868ff8c37525e95adfabbf09": { - "generatedAt": "2018-06-04T12:49:52.498Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.420Z", - "deployTransactionHash": "0x73c20ff63833741712d10081bb744725ed3907d62fcb67cf596c868b36b8b431", + "0xc036a1dd59ac55e2fb6b3d7416cb4ecc44605834": { + "generatedAt": "2018-10-18T13:35:02.347Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.845Z", + "deployTransactionHash": "0xf3b9798a6a93bbd5a1ff68f032e92c02d5d71556e5f5b573aa25b3a35f64b923", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "95c5ad9c1fc19dfaf8ff9522923cf08b", - "deployedBytecodeHash": "72ac9e6702f78ef862f370d8c8df7c71", - "sourceHash": "c7efcf3ab406e57912d53f6c60404d94", - "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or StabilityBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is SystemAccount {\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function burn(AugmintTokenInterface augmintToken, uint amount) external restrict(\"MonetarySupervisorContract\") {\n augmintToken.burn(amount);\n }\n\n}\n" + "bytecodeHash": "5bf4ede2aaad5b0b112f7b1ebf420fd2", + "deployedBytecodeHash": "3720667df6506876043fba53c540acb6", + "sourceHash": "b9d84f5f6153164ba581845190291c88", + "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or StabilityBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is Restricted {\n\n event ReserveMigration(address to, uint weiAmount);\n\n constructor(address permissionGranterContract)\n public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function () external payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n function burn(AugmintTokenInterface augmintToken, uint amount)\n external restrict(\"MonetarySupervisor\") {\n augmintToken.burn(amount);\n }\n\n function migrate(address to, uint weiAmount)\n external restrict(\"StabilityBoard\") {\n if (weiAmount > 0) {\n to.transfer(weiAmount);\n }\n emit ReserveMigration(to, weiAmount);\n }\n}\n" }, - "0x6386f25d2029ea3164838bf6494ed85c01fc1b03": { - "generatedAt": "2018-06-10T08:34:44.824Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.124Z", - "deployTransactionHash": "0xb8d91b5ead336188b26d421e0f8a77d6daf93c093975f03d051a0633116cc666", + "0x33bec125657470e53887400666bdeed360b2168a": { + "generatedAt": "2018-10-29T15:52:43.253Z", + "truffleContractFileUpdatedAt": "2018-10-19T15:49:10.709Z", + "deployTransactionHash": "0xf76d1b2e93fd4fa074e60e0c60e7ee6ef0257d7aac0a0361b73c0b7f863a796b", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "4974a3c7784d990daf85675b5b7a0e17", - "deployedBytecodeHash": "d4f59c0df09ee0b51006f4945892828c", - "sourceHash": "d5753af67c3f621da910f47d3d749db3", - "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or StabilityBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is SystemAccount {\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function burn(AugmintTokenInterface augmintToken, uint amount) external restrict(\"MonetarySupervisor\") {\n augmintToken.burn(amount);\n }\n\n}\n" + "bytecodeHash": "5bf4ede2aaad5b0b112f7b1ebf420fd2", + "deployedBytecodeHash": "3720667df6506876043fba53c540acb6", + "sourceHash": "b9d84f5f6153164ba581845190291c88", + "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or StabilityBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is Restricted {\n\n event ReserveMigration(address to, uint weiAmount);\n\n constructor(address permissionGranterContract)\n public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function () external payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n function burn(AugmintTokenInterface augmintToken, uint amount)\n external restrict(\"MonetarySupervisor\") {\n augmintToken.burn(amount);\n }\n\n function migrate(address to, uint weiAmount)\n external restrict(\"StabilityBoard\") {\n if (weiAmount > 0) {\n to.transfer(weiAmount);\n }\n emit ReserveMigration(to, weiAmount);\n }\n}\n" } } } diff --git a/abiniser/deployments/4/Exchange_DEPLOYS.json b/abiniser/deployments/4/Exchange_DEPLOYS.json index 6764adb9..a54aa917 100644 --- a/abiniser/deployments/4/Exchange_DEPLOYS.json +++ b/abiniser/deployments/4/Exchange_DEPLOYS.json @@ -1,144 +1,35 @@ { "contractName": "Exchange", - "latestAbiHash": "c28de2392aea85ef2aa1b108fce6568c", + "latestAbiHash": "d3e7f8a261b756f9c40da097608b21cd", "deployedAbis": { - "3aa2aedd2972391a12570ba4bfca2f72": { - "latestDeployedAddress": "0x03fe291f8a30e54cd05459f368d554b40784ca78", + "d3e7f8a261b756f9c40da097608b21cd": { + "latestDeployedAddress": "0xe5d6d0c107eae79d2d30798f252ac6ff5ecad459", "deployments": { - "0x65d30e5a6191a507fda96341f6ba773c4224c0e1": { - "generatedAt": "2018-04-25T12:29:07.683Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:31:03.072Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "95533c8abeab1480f1c82f2f0593dae8", - "deployedBytecodeHash": "ce8bd79d6703d524cb59226bc11fc7d8", - "sourceHash": "c308207b18b39a21996dc30f8a59bc2f", - "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n*/\npragma solidity 0.4.19;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\ncontract Exchange {\n using SafeMath for uint256;\n AugmintTokenInterface public augmintToken;\n\n uint public constant CHUNK_SIZE = 100;\n\n struct Order {\n uint64 index;\n address maker;\n\n // tokens per ether\n uint32 price;\n\n // buy order: amount in wei \n // sell order: token amount\n uint amount; \n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount,\n uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint32 price, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n function Exchange(AugmintTokenInterface _augmintToken) public {\n augmintToken = _augmintToken;\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0);\n require(msg.value > 0);\n\n orderId = ++orderCount; \n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender);\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender);\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price meets in the middle\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n _fillOrder(buyTokenId, sellTokenId);\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Stops if any match is invalid (case when any of the orders removed after client generated the match list sent)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length);\n for (uint i = 0; i < len && msg.gas > ORDER_MATCH_WORST_GAS; i++) {\n _fillOrder(buyTokenIds[i], sellTokenIds[i]);\n matchCount++;\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns CHUNK_SIZE orders starting from offset\n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) {\n uint64 orderId = activeBuyOrders[offset + i];\n Order storage order = buyTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) {\n uint64 orderId = activeSellOrders[offset + i];\n Order storage order = sellTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) public {\n require(msg.sender == address(augmintToken));\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n\n require(buy.price >= sell.price);\n\n // meet in the middle\n uint price = uint(buy.price).add(sell.price).div(2);\n\n uint sellWei = sell.amount.mul(1 ether).div(price);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(price).div(1 ether);\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, uint32(price), tradedWei, tradedTokens);\n }\n\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0);\n require(tokenAmount > 0);\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n _removeOrder(activeBuyOrders, order.index);\n }\n\n function _removeSellOrder(Order storage order) private {\n _removeOrder(activeSellOrders, order.index);\n }\n\n function _removeOrder(uint64[] storage orders, uint64 index) private {\n if (index < orders.length - 1) {\n orders[index] = orders[orders.length - 1];\n }\n orders.length--;\n }\n\n}\n" - }, - "0x03fe291f8a30e54cd05459f368d554b40784ca78": { - "generatedAt": "2018-04-25T12:30:49.487Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:35:58.103Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "e47f3492d775d281872d832c98118822", - "deployedBytecodeHash": "8656667e0062d2a11e000c4d34d156db", - "sourceHash": "eacd00fb6a1cfd4cd37484832bef5f6b", - "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n*/\npragma solidity 0.4.19;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract Exchange {\n using SafeMath for uint256;\n AugmintTokenInterface public augmintToken;\n\n uint public constant CHUNK_SIZE = 100;\n\n struct Order {\n uint64 index;\n address maker;\n\n // tokens per ether\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount,\n uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint32 price, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n function Exchange(AugmintTokenInterface _augmintToken) public {\n augmintToken = _augmintToken;\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0);\n require(msg.value > 0);\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender);\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender);\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price meets in the middle\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n _fillOrder(buyTokenId, sellTokenId);\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Stops if any match is invalid (case when any of the orders removed after client generated the match list sent)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length);\n for (uint i = 0; i < len && msg.gas > ORDER_MATCH_WORST_GAS; i++) {\n _fillOrder(buyTokenIds[i], sellTokenIds[i]);\n matchCount++;\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns CHUNK_SIZE orders starting from offset\n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) {\n uint64 orderId = activeBuyOrders[offset + i];\n Order storage order = buyTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) {\n uint64 orderId = activeSellOrders[offset + i];\n Order storage order = sellTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) public {\n require(msg.sender == address(augmintToken));\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n\n require(buy.price >= sell.price);\n\n // meet in the middle\n uint price = uint(buy.price).add(sell.price).div(2);\n\n uint sellWei = sell.amount.mul(1 ether).roundedDiv(price);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(price).roundedDiv(1 ether);\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, uint32(price), tradedWei, tradedTokens);\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0);\n require(tokenAmount > 0);\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n _removeOrder(activeBuyOrders, order.index);\n }\n\n function _removeSellOrder(Order storage order) private {\n _removeOrder(activeSellOrders, order.index);\n }\n\n function _removeOrder(uint64[] storage orders, uint64 index) private {\n if (index < orders.length - 1) {\n orders[index] = orders[orders.length - 1];\n }\n orders.length--;\n }\n\n}\n" - } - } - }, - "7595b255e567ae1d0eeef4460d0b0c16": { - "latestDeployedAddress": "0x86abc21cbb508fcb303f881d6871e4f870ce041a", - "deployments": { - "0x86abc21cbb508fcb303f881d6871e4f870ce041a": { - "generatedAt": "2018-04-25T12:31:29.262Z", - "truffleContractFileUpdatedAt": "2018-04-20T18:25:08.442Z", - "deployTransactionHash": "0x8ac6b0922fc9cad4d2e4745b329b4ec4fa6d2bfaf4f5f6361fa816b860cff1a9", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "4dbd56e92e7a2abc0cef7a5e3b8c58db", - "deployedBytecodeHash": "7d6fb687ffba76ae852474db1aec571f", - "sourceHash": "016483ae7a2ba57c530701e7db3df989", - "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n*/\npragma solidity ^0.4.23;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract Exchange {\n using SafeMath for uint256;\n AugmintTokenInterface public augmintToken;\n\n uint public constant CHUNK_SIZE = 100;\n\n struct Order {\n uint64 index;\n address maker;\n\n // tokens per ether\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount,\n uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint32 price, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n constructor(AugmintTokenInterface _augmintToken) public {\n augmintToken = _augmintToken;\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price meets in the middle\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n _fillOrder(buyTokenId, sellTokenId);\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Stops if any match is invalid (case when any of the orders removed after client generated the match list sent)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n _fillOrder(buyTokenIds[i], sellTokenIds[i]);\n matchCount++;\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns CHUNK_SIZE orders starting from offset\n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) {\n uint64 orderId = activeBuyOrders[offset + i];\n Order storage order = buyTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) {\n uint64 orderId = activeSellOrders[offset + i];\n Order storage order = sellTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // meet in the middle\n uint price = uint(buy.price).add(sell.price).div(2);\n\n uint sellWei = sell.amount.mul(1 ether).roundedDiv(price);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(price).roundedDiv(1 ether);\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, uint32(price), tradedWei, tradedTokens);\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n _removeOrder(activeBuyOrders, order.index);\n }\n\n function _removeSellOrder(Order storage order) private {\n _removeOrder(activeSellOrders, order.index);\n }\n\n function _removeOrder(uint64[] storage orders, uint64 index) private {\n if (index < orders.length - 1) {\n orders[index] = orders[orders.length - 1];\n }\n orders.length--;\n }\n\n}\n" - } - } - }, - "3c157a5256a2093da587f166d4dbd537": { - "latestDeployedAddress": "0xc5b604f8e046dff26642ca544c9eb3064e02ecd9", - "deployments": { - "0xa2ed50765110b695816c658d5d6d1d32bcd03866": { - "generatedAt": "2018-05-03T22:05:03.992Z", - "truffleContractFileUpdatedAt": "2018-05-03T22:03:50.411Z", - "deployTransactionHash": "0x81cfef02417e36dc6538cbfc12b487a73779a6d8cdb5cde1ff2c30a02f70fb93", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "4a1da36560fdae5d5f9aeb9bb9e12f3e", - "deployedBytecodeHash": "2c390a9b03f57a87af44432fc6444647", - "sourceHash": "6e27bdbdc64d0d9cf52de1abc46c4cf7", - "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity ^0.4.23;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n uint public constant CHUNK_SIZE = 100;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint fillRate, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(AugmintTokenInterface _augmintToken, Rates _rates) public {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"MonetaryBoard\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price meets in the middle\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n _fillOrder(buyTokenId, sellTokenId);\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Stops if any match is invalid (case when any of the orders removed after client generated the match list sent)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n _fillOrder(buyTokenIds[i], sellTokenIds[i]);\n matchCount++;\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns CHUNK_SIZE orders starting from offset\n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) {\n uint64 orderId = activeBuyOrders[offset + i];\n Order storage order = buyTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) {\n uint64 orderId = activeSellOrders[offset + i];\n Order storage order = sellTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n uint fillRate = publishedRate.mul(price).roundedDiv(1000000);\n\n uint sellWei = sell.amount.mul(1 ether).roundedDiv(fillRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(fillRate).roundedDiv(1 ether);\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, fillRate, tradedWei, tradedTokens);\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n _removeOrder(activeBuyOrders, order.index);\n }\n\n function _removeSellOrder(Order storage order) private {\n _removeOrder(activeSellOrders, order.index);\n }\n\n function _removeOrder(uint64[] storage orders, uint64 index) private {\n if (index < orders.length - 1) {\n orders[index] = orders[orders.length - 1];\n }\n orders.length--;\n }\n\n}\n" - }, - "0xc5b604f8e046dff26642ca544c9eb3064e02ecd9": { - "generatedAt": "2018-05-12T01:34:38.557Z", - "truffleContractFileUpdatedAt": "2018-05-12T01:30:50.090Z", - "deployTransactionHash": "0x7f022b010da30ab1c76d7c976a0b8f19ac6d7eab34ba46d19fcbfad1695fcb21", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "0c3aae2a1e26a2cc4f1800e62fa873ee", - "deployedBytecodeHash": "4c6ad15993389d8d7326c731b2b92d63", - "sourceHash": "6e27bdbdc64d0d9cf52de1abc46c4cf7", - "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity ^0.4.23;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n uint public constant CHUNK_SIZE = 100;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint fillRate, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(AugmintTokenInterface _augmintToken, Rates _rates) public {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"MonetaryBoard\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price meets in the middle\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n _fillOrder(buyTokenId, sellTokenId);\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Stops if any match is invalid (case when any of the orders removed after client generated the match list sent)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n _fillOrder(buyTokenIds[i], sellTokenIds[i]);\n matchCount++;\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns CHUNK_SIZE orders starting from offset\n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) {\n uint64 orderId = activeBuyOrders[offset + i];\n Order storage order = buyTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) {\n uint64 orderId = activeSellOrders[offset + i];\n Order storage order = sellTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n uint fillRate = publishedRate.mul(price).roundedDiv(1000000);\n\n uint sellWei = sell.amount.mul(1 ether).roundedDiv(fillRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(fillRate).roundedDiv(1 ether);\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, fillRate, tradedWei, tradedTokens);\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n _removeOrder(activeBuyOrders, order.index);\n }\n\n function _removeSellOrder(Order storage order) private {\n _removeOrder(activeSellOrders, order.index);\n }\n\n function _removeOrder(uint64[] storage orders, uint64 index) private {\n if (index < orders.length - 1) {\n orders[index] = orders[orders.length - 1];\n }\n orders.length--;\n }\n\n}\n" - } - } - }, - "b2a23202a9a0f04755a186896c2b56eb": { - "latestDeployedAddress": "0x5e2be81ab4237c7c08d929c42b9f13cf4f9040d2", - "deployments": { - "0x27e3f7a0d2803b1a24fe05f3b609b8327b451650": { - "generatedAt": "2018-06-04T12:49:52.701Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.553Z", - "deployTransactionHash": "0x7f53b1c04ef03ad4a052a27f478bc81c7521eede0696880ab7f4912522dbfb7c", - "compiler": { - "name": "solc", - "version": "0.4.24+commit.e67f0147.Emscripten.clang" - }, - "bytecodeHash": "cb660dc8d8841df97e9c89f0917f0a0f", - "deployedBytecodeHash": "19935d4b0d34dc2565cae7aa9b3d8576", - "sourceHash": "19518ff85aecaf65bb99952a951e3369", - "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n uint public constant CHUNK_SIZE = 100;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint fillRate, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"StabilityBoardSignerContract\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"buy order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"sell order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price is the price of the maker (the order placed earlier)\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n require(_fillOrder(buyTokenId, sellTokenId), \"fill order failed\");\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Reverts if any match is invalid (e.g sell price > buy price)\n Skips match if any of the matched orders is removed / already filled (i.e. amount = 0)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n if(_fillOrder(buyTokenIds[i], sellTokenIds[i])) {\n matchCount++;\n }\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns CHUNK_SIZE orders starting from offset\n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) {\n uint64 orderId = activeBuyOrders[offset + i];\n Order storage order = buyTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) {\n uint64 orderId = activeSellOrders[offset + i];\n Order storage order = sellTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private returns(bool success) {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n if( buy.amount == 0 || sell.amount == 0 ) {\n return false; // one order is already filled and removed.\n // we let matchMultiple continue, indivudal match will revert\n }\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n uint fillRate = publishedRate.mul(price).roundedDiv(1000000);\n\n uint sellWei = sell.amount.mul(1 ether).roundedDiv(fillRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(fillRate).roundedDiv(1 ether);\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, fillRate, tradedWei, tradedTokens);\n\n return true;\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n _removeOrder(activeBuyOrders, order.index);\n }\n\n function _removeSellOrder(Order storage order) private {\n _removeOrder(activeSellOrders, order.index);\n }\n\n function _removeOrder(uint64[] storage orders, uint64 index) private {\n if (index < orders.length - 1) {\n orders[index] = orders[orders.length - 1];\n }\n orders.length--;\n }\n\n}\n" - }, - "0x5e2be81ab4237c7c08d929c42b9f13cf4f9040d2": { - "generatedAt": "2018-06-10T08:34:45.007Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:26.405Z", - "deployTransactionHash": "0xfe265a6fa30b3e8bcb4d8b4fcdc7e05bb3b76a7b14b3994d4fe0e9fa8b5641d9", - "compiler": { - "name": "solc", - "version": "0.4.24+commit.e67f0147.Emscripten.clang" - }, - "bytecodeHash": "09662358eb649fe02860d3f98722ee64", - "deployedBytecodeHash": "5dc02051446dcb33dceff75a1635ea27", - "sourceHash": "7a417a79bd6036b0b1b796d00bc176ca", - "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n uint public constant CHUNK_SIZE = 100;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint fillRate, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"buy order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"sell order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price is the price of the maker (the order placed earlier)\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n require(_fillOrder(buyTokenId, sellTokenId), \"fill order failed\");\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Reverts if any match is invalid (e.g sell price > buy price)\n Skips match if any of the matched orders is removed / already filled (i.e. amount = 0)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n if(_fillOrder(buyTokenIds[i], sellTokenIds[i])) {\n matchCount++;\n }\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns CHUNK_SIZE orders starting from offset\n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) {\n uint64 orderId = activeBuyOrders[offset + i];\n Order storage order = buyTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) {\n uint64 orderId = activeSellOrders[offset + i];\n Order storage order = sellTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private returns(bool success) {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n if( buy.amount == 0 || sell.amount == 0 ) {\n return false; // one order is already filled and removed.\n // we let matchMultiple continue, indivudal match will revert\n }\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n uint fillRate = publishedRate.mul(price).roundedDiv(1000000);\n\n uint sellWei = sell.amount.mul(1 ether).roundedDiv(fillRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(fillRate).roundedDiv(1 ether);\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, fillRate, tradedWei, tradedTokens);\n\n return true;\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n _removeOrder(activeBuyOrders, order.index);\n }\n\n function _removeSellOrder(Order storage order) private {\n _removeOrder(activeSellOrders, order.index);\n }\n\n function _removeOrder(uint64[] storage orders, uint64 index) private {\n if (index < orders.length - 1) {\n orders[index] = orders[orders.length - 1];\n }\n orders.length--;\n }\n\n}\n" - } - } - }, - "c28de2392aea85ef2aa1b108fce6568c": { - "latestDeployedAddress": "0x554817688d096ae89fdaccf52e76f629b9db8f53", - "deployments": { - "0x5c35162dbf91c794f1569c5fe1649f0c5283d2f6": { - "generatedAt": "2018-08-17T11:58:40.649Z", - "truffleContractFileUpdatedAt": "2018-08-17T11:33:06.502Z", - "deployTransactionHash": "0x616e92404a9c51356244c8acd3e7a8ce8fc5cec4629d22af7921afc00ee612f2", + "0xdf47d51028daff13424f42523fdac73079ab901b": { + "generatedAt": "2018-10-18T13:35:02.438Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.980Z", + "deployTransactionHash": "0x35b0caa7f3479a08e88a8554eb6ffea246c5364e89969941a21a095cede76c65", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "214d9b21e9fc776631897c811d75e7a7", - "deployedBytecodeHash": "c55ed2d4c5fb27f191f7d3e043afe771", - "sourceHash": "666961af517c36b10580b52699ba5ae9", - "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n uint public constant CHUNK_SIZE = 100;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"buy order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"sell order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price is the price of the maker (the order placed earlier)\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n require(_fillOrder(buyTokenId, sellTokenId), \"fill order failed\");\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Reverts if any match is invalid (e.g sell price > buy price)\n Skips match if any of the matched orders is removed / already filled (i.e. amount = 0)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n if(_fillOrder(buyTokenIds[i], sellTokenIds[i])) {\n matchCount++;\n }\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns CHUNK_SIZE orders starting from offset\n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) {\n uint64 orderId = activeBuyOrders[offset + i];\n Order storage order = buyTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) {\n uint64 orderId = activeSellOrders[offset + i];\n Order storage order = sellTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n uint private constant E12 = 1000000000000;\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private returns(bool success) {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n if( buy.amount == 0 || sell.amount == 0 ) {\n return false; // one order is already filled and removed.\n // we let matchMultiple continue, indivudal match will revert\n }\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n // fillRate = publishedRate * 1000000 / price\n\n uint sellWei = sell.amount.mul(uint(price)).mul(E12).roundedDiv(publishedRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(publishedRate).roundedDiv(uint(price).mul(E12));\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, tradedWei, tradedTokens);\n\n return true;\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n _removeOrder(activeBuyOrders, order.index);\n }\n\n function _removeSellOrder(Order storage order) private {\n _removeOrder(activeSellOrders, order.index);\n }\n\n function _removeOrder(uint64[] storage orders, uint64 index) private {\n if (index < orders.length - 1) {\n orders[index] = orders[orders.length - 1];\n }\n orders.length--;\n }\n\n}\n" + "bytecodeHash": "5a731d45c1595b7ffeb40bae693ef88d", + "deployedBytecodeHash": "136e48f6880df5153792c846d87ddede", + "sourceHash": "d6ff57acb1b45199b5dd08357978d8c2", + "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"buy order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"sell order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price is the price of the maker (the order placed earlier)\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n require(_fillOrder(buyTokenId, sellTokenId), \"fill order failed\");\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Reverts if any match is invalid (e.g sell price > buy price)\n Skips match if any of the matched orders is removed / already filled (i.e. amount = 0)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n if(_fillOrder(buyTokenIds[i], sellTokenIds[i])) {\n matchCount++;\n }\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns active buy orders starting from \n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset, uint16 chunkSize)\n external view returns (uint[4][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), activeBuyOrders.length);\n uint[4][] memory response = new uint[4][](limit.sub(offset));\n for (uint i = offset; i < limit; i++) {\n uint64 orderId = activeBuyOrders[i];\n Order storage order = buyTokenOrders[orderId];\n response[i - offset] = [orderId, uint(order.maker), order.price, order.amount];\n }\n return response;\n }\n\n // returns active sell orders starting from \n // orders are encoded as [id, maker, price, amount]\n function getActiveSellOrders(uint offset, uint16 chunkSize)\n external view returns (uint[4][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), activeSellOrders.length);\n uint[4][] memory response = new uint[4][](limit.sub(offset));\n for (uint i = offset; i < limit; i++) {\n uint64 orderId = activeSellOrders[i];\n Order storage order = sellTokenOrders[orderId];\n response[i - offset] = [orderId, uint(order.maker), order.price, order.amount];\n }\n return response;\n }\n\n uint private constant E12 = 1000000000000;\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private returns(bool success) {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n if( buy.amount == 0 || sell.amount == 0 ) {\n return false; // one order is already filled and removed.\n // we let matchMultiple continue, indivudal match will revert\n }\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n // fillRate = publishedRate * 1000000 / price\n\n uint sellWei = sell.amount.mul(uint(price)).mul(E12).roundedDiv(publishedRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(publishedRate).roundedDiv(uint(price).mul(E12));\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, tradedWei, tradedTokens);\n\n return true;\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n uint lastIndex = activeBuyOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeBuyOrders[lastIndex];\n activeBuyOrders[order.index] = movedOrderId;\n buyTokenOrders[movedOrderId].index = order.index;\n }\n activeBuyOrders.length--;\n }\n\n function _removeSellOrder(Order storage order) private {\n uint lastIndex = activeSellOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeSellOrders[lastIndex];\n activeSellOrders[order.index] = movedOrderId;\n sellTokenOrders[movedOrderId].index = order.index;\n }\n activeSellOrders.length--;\n }\n}\n" }, - "0x554817688d096ae89fdaccf52e76f629b9db8f53": { - "generatedAt": "2018-09-12T12:52:24.541Z", - "truffleContractFileUpdatedAt": "2018-09-12T12:51:02.147Z", - "deployTransactionHash": "0x579ed3f2d914cee820cbdec7a78d777923c4cb63044cb18e78c721ad2651a487", + "0xe5d6d0c107eae79d2d30798f252ac6ff5ecad459": { + "generatedAt": "2018-10-29T15:52:43.331Z", + "truffleContractFileUpdatedAt": "2018-10-19T15:49:10.813Z", + "deployTransactionHash": "0x1823548271afb6df6cb6012027d2c32f3c7d649056be0e12a5698e35c2ed1fe1", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "223ee21caaeb265ed1ea7331ad7c92c7", - "deployedBytecodeHash": "b906f4b8d33bc83dd42cf4e56efa0bf8", - "sourceHash": "2fd035bece27394255c74c60658546e5", - "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n uint public constant CHUNK_SIZE = 100;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"buy order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"sell order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price is the price of the maker (the order placed earlier)\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n require(_fillOrder(buyTokenId, sellTokenId), \"fill order failed\");\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Reverts if any match is invalid (e.g sell price > buy price)\n Skips match if any of the matched orders is removed / already filled (i.e. amount = 0)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n if(_fillOrder(buyTokenIds[i], sellTokenIds[i])) {\n matchCount++;\n }\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns CHUNK_SIZE orders starting from offset\n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) {\n uint64 orderId = activeBuyOrders[offset + i];\n Order storage order = buyTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) {\n uint64 orderId = activeSellOrders[offset + i];\n Order storage order = sellTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n uint private constant E12 = 1000000000000;\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private returns(bool success) {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n if( buy.amount == 0 || sell.amount == 0 ) {\n return false; // one order is already filled and removed.\n // we let matchMultiple continue, indivudal match will revert\n }\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n // fillRate = publishedRate * 1000000 / price\n\n uint sellWei = sell.amount.mul(uint(price)).mul(E12).roundedDiv(publishedRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(publishedRate).roundedDiv(uint(price).mul(E12));\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, tradedWei, tradedTokens);\n\n return true;\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n uint lastIndex = activeBuyOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeBuyOrders[lastIndex];\n activeBuyOrders[order.index] = movedOrderId;\n buyTokenOrders[movedOrderId].index = order.index;\n }\n activeBuyOrders.length--;\n }\n\n function _removeSellOrder(Order storage order) private {\n uint lastIndex = activeSellOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeSellOrders[lastIndex];\n activeSellOrders[order.index] = movedOrderId;\n sellTokenOrders[movedOrderId].index = order.index;\n }\n activeSellOrders.length--;\n }\n}\n" + "bytecodeHash": "5a731d45c1595b7ffeb40bae693ef88d", + "deployedBytecodeHash": "136e48f6880df5153792c846d87ddede", + "sourceHash": "d6ff57acb1b45199b5dd08357978d8c2", + "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"buy order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"sell order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price is the price of the maker (the order placed earlier)\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n require(_fillOrder(buyTokenId, sellTokenId), \"fill order failed\");\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Reverts if any match is invalid (e.g sell price > buy price)\n Skips match if any of the matched orders is removed / already filled (i.e. amount = 0)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n if(_fillOrder(buyTokenIds[i], sellTokenIds[i])) {\n matchCount++;\n }\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns active buy orders starting from \n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset, uint16 chunkSize)\n external view returns (uint[4][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), activeBuyOrders.length);\n uint[4][] memory response = new uint[4][](limit.sub(offset));\n for (uint i = offset; i < limit; i++) {\n uint64 orderId = activeBuyOrders[i];\n Order storage order = buyTokenOrders[orderId];\n response[i - offset] = [orderId, uint(order.maker), order.price, order.amount];\n }\n return response;\n }\n\n // returns active sell orders starting from \n // orders are encoded as [id, maker, price, amount]\n function getActiveSellOrders(uint offset, uint16 chunkSize)\n external view returns (uint[4][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), activeSellOrders.length);\n uint[4][] memory response = new uint[4][](limit.sub(offset));\n for (uint i = offset; i < limit; i++) {\n uint64 orderId = activeSellOrders[i];\n Order storage order = sellTokenOrders[orderId];\n response[i - offset] = [orderId, uint(order.maker), order.price, order.amount];\n }\n return response;\n }\n\n uint private constant E12 = 1000000000000;\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private returns(bool success) {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n if( buy.amount == 0 || sell.amount == 0 ) {\n return false; // one order is already filled and removed.\n // we let matchMultiple continue, indivudal match will revert\n }\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n // fillRate = publishedRate * 1000000 / price\n\n uint sellWei = sell.amount.mul(uint(price)).mul(E12).roundedDiv(publishedRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(publishedRate).roundedDiv(uint(price).mul(E12));\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, tradedWei, tradedTokens);\n\n return true;\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n uint lastIndex = activeBuyOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeBuyOrders[lastIndex];\n activeBuyOrders[order.index] = movedOrderId;\n buyTokenOrders[movedOrderId].index = order.index;\n }\n activeBuyOrders.length--;\n }\n\n function _removeSellOrder(Order storage order) private {\n uint lastIndex = activeSellOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeSellOrders[lastIndex];\n activeSellOrders[order.index] = movedOrderId;\n sellTokenOrders[movedOrderId].index = order.index;\n }\n activeSellOrders.length--;\n }\n}\n" } } } diff --git a/abiniser/deployments/4/FeeAccount_DEPLOYS.json b/abiniser/deployments/4/FeeAccount_DEPLOYS.json index d664b08f..9c2b2940 100644 --- a/abiniser/deployments/4/FeeAccount_DEPLOYS.json +++ b/abiniser/deployments/4/FeeAccount_DEPLOYS.json @@ -2,81 +2,34 @@ "contractName": "FeeAccount", "latestAbiHash": "67db260db12738df3cced3511d34c65c", "deployedAbis": { - "3bf67cdfa9f7a16596598e19aeb06b39": { - "latestDeployedAddress": "0xad897f2c86d892cf221fdbd276029c3ba732af20", - "deployments": { - "0xd87c5eacfa897a1ef04e891554b65d3f52e0b4cc": { - "generatedAt": "2018-04-25T12:29:07.534Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:21:02.850Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "69b026002a4dee77ed6f6c3751706a16", - "deployedBytecodeHash": "1667a0501fd9994acd15101d508e8b50", - "sourceHash": "683f4469ac7396c5de93d4ce60e32c47", - "source": "/* Contract to collect fees from system */\n\npragma solidity 0.4.19;\nimport \"./generic/SystemAccount.sol\";\n\n\ncontract FeeAccount is SystemAccount { // solhint-disable-line no-empty-blocks\n\n}\n" - }, - "0xad897f2c86d892cf221fdbd276029c3ba732af20": { - "generatedAt": "2018-04-25T12:30:49.084Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:23:57.497Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "590b35b115c16a5eeb45e74226771380", - "deployedBytecodeHash": "1d79d9ce02c401f7a91c98ab2d54b5e5", - "sourceHash": "683f4469ac7396c5de93d4ce60e32c47", - "source": "/* Contract to collect fees from system */\n\npragma solidity 0.4.19;\nimport \"./generic/SystemAccount.sol\";\n\n\ncontract FeeAccount is SystemAccount { // solhint-disable-line no-empty-blocks\n\n}\n" - } - } - }, - "dd4594a936e439aa46ed5b06cb69eafa": { - "latestDeployedAddress": "0xc26667132b0b798ab87864f7c29c0819c887aadb", - "deployments": { - "0xc26667132b0b798ab87864f7c29c0819c887aadb": { - "generatedAt": "2018-04-25T12:31:29.048Z", - "truffleContractFileUpdatedAt": "2018-04-20T18:26:53.864Z", - "deployTransactionHash": "0xf4b06960e7ad9995e6466aee4f5b12a28599165d85abe3fe07b9be8f28533d24", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "afe432dc74f46f15001b4d1071b890ea", - "deployedBytecodeHash": "b50181831074ded6293f030ac08dfbb9", - "sourceHash": "fe888fa25a5c364abea5c0856f1ebd5b", - "source": "/* Contract to collect fees from system\n TODO: calculateExchangeFee + Exchange params and setters\n*/\n\npragma solidity ^0.4.23;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/TransferFeeInterface.sol\";\n\n\ncontract FeeAccount is SystemAccount, TransferFeeInterface {\n\n using SafeMath for uint256;\n\n struct TransferFee {\n uint pt; // in parts per million (ppm) , ie. 2,000 = 0.2%\n uint min; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n uint max; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n }\n\n TransferFee public transferFee;\n\n event TransferFeesChanged(uint transferFeePt, uint transferFeeMin, uint transferFeeMax);\n\n constructor(uint transferFeePt, uint transferFeeMin, uint transferFeeMax) public {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into feeAccount (defaulting fee in ETH )\n }\n\n function setTransferFees(uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n external restrict(\"MonetaryBoard\") {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n emit TransferFeesChanged(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function calculateTransferFee(address from, address to, uint amount) external view returns (uint256 fee) {\n if (!permissions[from][\"NoFeeTransferContracts\"] && !permissions[to][\"NoFeeTransferContracts\"]) {\n fee = amount.mul(transferFee.pt).div(1000000);\n if (fee > transferFee.max) {\n fee = transferFee.max;\n } else if (fee < transferFee.min) {\n fee = transferFee.min;\n }\n }\n return fee;\n }\n\n function calculateExchangeFee(uint weiAmount) external view returns (uint256 weiFee) {\n /* TODO: to be implemented and use in Exchange.sol. always revert for now */\n require(weiAmount != weiAmount, \"not yet implemented\");\n weiFee = transferFee.max; // to silence compiler warnings until it's implemented\n }\n\n}\n" - } - } - }, "67db260db12738df3cced3511d34c65c": { - "latestDeployedAddress": "0x0f5983a6d760bf6e385339af0e67e87420d413ec", + "latestDeployedAddress": "0xaa16ede9093bb4140e2715ed9a1e41cdfd9d9c29", "deployments": { - "0x9b26f801c6078b76690b0d954f7fd662e04be1d1": { - "generatedAt": "2018-06-04T12:49:52.510Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.430Z", - "deployTransactionHash": "0x57679efa8918fd72e9078929b01e7445d46741f193311d0ae4ae91f512f1e9f5", + "0xb77f9cdda72eec47a57793be088c7b523f6b5014": { + "generatedAt": "2018-10-18T13:35:02.354Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.893Z", + "deployTransactionHash": "0x9fe716e506b3f5f797496ae5d4035724a698dc8b2aa606d9106d532990958c75", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "49f3316630dc6511b4e8cb2aae5ad613", - "deployedBytecodeHash": "5341f59b12bdaecb07450b1fce36c7d0", - "sourceHash": "bcfeb9008629692d46468836d98e5fe9", - "source": "/* Contract to collect fees from system\n TODO: calculateExchangeFee + Exchange params and setters\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/TransferFeeInterface.sol\";\n\n\ncontract FeeAccount is SystemAccount, TransferFeeInterface {\n\n using SafeMath for uint256;\n\n struct TransferFee {\n uint pt; // in parts per million (ppm) , ie. 2,000 = 0.2%\n uint min; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n uint max; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n }\n\n TransferFee public transferFee;\n\n event TransferFeesChanged(uint transferFeePt, uint transferFeeMin, uint transferFeeMax);\n\n constructor(address permissionGranterContract, uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n public SystemAccount(permissionGranterContract) {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into feeAccount (defaulting fee in ETH )\n }\n\n function setTransferFees(uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n external restrict(\"StabilityBoardSignerContract\") {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n emit TransferFeesChanged(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function calculateTransferFee(address from, address to, uint amount) external view returns (uint256 fee) {\n if (!permissions[from][\"NoFeeTransferContracts\"] && !permissions[to][\"NoFeeTransferContracts\"]) {\n fee = amount.mul(transferFee.pt).div(1000000);\n if (fee > transferFee.max) {\n fee = transferFee.max;\n } else if (fee < transferFee.min) {\n fee = transferFee.min;\n }\n }\n return fee;\n }\n\n function calculateExchangeFee(uint weiAmount) external view returns (uint256 weiFee) {\n /* TODO: to be implemented and use in Exchange.sol. always revert for now */\n require(weiAmount != weiAmount, \"not yet implemented\");\n weiFee = transferFee.max; // to silence compiler warnings until it's implemented\n }\n\n}\n" + "bytecodeHash": "7f27e332912911a33f3a5831a478a40e", + "deployedBytecodeHash": "62169a6a5b1bc79360f85c7d6b7cbadf", + "sourceHash": "d8975a5e1941ad79313f4b7bb0be9f95", + "source": "/* Contract to collect fees from system\n TODO: calculateExchangeFee + Exchange params and setters\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/TransferFeeInterface.sol\";\n\n\ncontract FeeAccount is SystemAccount, TransferFeeInterface {\n\n using SafeMath for uint256;\n\n struct TransferFee {\n uint pt; // in parts per million (ppm) , ie. 2,000 = 0.2%\n uint min; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n uint max; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n }\n\n TransferFee public transferFee;\n\n event TransferFeesChanged(uint transferFeePt, uint transferFeeMin, uint transferFeeMax);\n\n constructor(address permissionGranterContract, uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n public SystemAccount(permissionGranterContract) {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function () external payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into feeAccount (defaulting fee in ETH )\n }\n\n function setTransferFees(uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n external restrict(\"StabilityBoard\") {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n emit TransferFeesChanged(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function calculateTransferFee(address from, address to, uint amount) external view returns (uint256 fee) {\n if (!permissions[from][\"NoTransferFee\"] && !permissions[to][\"NoTransferFee\"]) {\n fee = amount.mul(transferFee.pt).div(1000000);\n if (fee > transferFee.max) {\n fee = transferFee.max;\n } else if (fee < transferFee.min) {\n fee = transferFee.min;\n }\n }\n return fee;\n }\n\n function calculateExchangeFee(uint weiAmount) external view returns (uint256 weiFee) {\n /* TODO: to be implemented and use in Exchange.sol. always revert for now */\n require(weiAmount != weiAmount, \"not yet implemented\");\n weiFee = transferFee.max; // to silence compiler warnings until it's implemented\n }\n\n}\n" }, - "0x0f5983a6d760bf6e385339af0e67e87420d413ec": { - "generatedAt": "2018-06-10T08:34:44.841Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.117Z", - "deployTransactionHash": "0xefc759f1286e57586ef977f85a4810f65525a46fb7754c194bc74f0c53a0da5f", + "0xaa16ede9093bb4140e2715ed9a1e41cdfd9d9c29": { + "generatedAt": "2018-10-29T15:52:43.259Z", + "truffleContractFileUpdatedAt": "2018-10-19T15:49:10.747Z", + "deployTransactionHash": "0x798c51bacfabcba263aceb1ea92f2cd6992b799e1654b11d3ac7e36a45aeb9bb", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "1db7295608dc7f030b9c01818f4afe93", - "deployedBytecodeHash": "1a57c03530d204909d1075b452099e77", - "sourceHash": "653a2a034144713dc046880dafd503c9", - "source": "/* Contract to collect fees from system\n TODO: calculateExchangeFee + Exchange params and setters\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/TransferFeeInterface.sol\";\n\n\ncontract FeeAccount is SystemAccount, TransferFeeInterface {\n\n using SafeMath for uint256;\n\n struct TransferFee {\n uint pt; // in parts per million (ppm) , ie. 2,000 = 0.2%\n uint min; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n uint max; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n }\n\n TransferFee public transferFee;\n\n event TransferFeesChanged(uint transferFeePt, uint transferFeeMin, uint transferFeeMax);\n\n constructor(address permissionGranterContract, uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n public SystemAccount(permissionGranterContract) {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into feeAccount (defaulting fee in ETH )\n }\n\n function setTransferFees(uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n external restrict(\"StabilityBoard\") {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n emit TransferFeesChanged(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function calculateTransferFee(address from, address to, uint amount) external view returns (uint256 fee) {\n if (!permissions[from][\"NoTransferFee\"] && !permissions[to][\"NoTransferFee\"]) {\n fee = amount.mul(transferFee.pt).div(1000000);\n if (fee > transferFee.max) {\n fee = transferFee.max;\n } else if (fee < transferFee.min) {\n fee = transferFee.min;\n }\n }\n return fee;\n }\n\n function calculateExchangeFee(uint weiAmount) external view returns (uint256 weiFee) {\n /* TODO: to be implemented and use in Exchange.sol. always revert for now */\n require(weiAmount != weiAmount, \"not yet implemented\");\n weiFee = transferFee.max; // to silence compiler warnings until it's implemented\n }\n\n}\n" + "bytecodeHash": "7f27e332912911a33f3a5831a478a40e", + "deployedBytecodeHash": "62169a6a5b1bc79360f85c7d6b7cbadf", + "sourceHash": "d8975a5e1941ad79313f4b7bb0be9f95", + "source": "/* Contract to collect fees from system\n TODO: calculateExchangeFee + Exchange params and setters\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/TransferFeeInterface.sol\";\n\n\ncontract FeeAccount is SystemAccount, TransferFeeInterface {\n\n using SafeMath for uint256;\n\n struct TransferFee {\n uint pt; // in parts per million (ppm) , ie. 2,000 = 0.2%\n uint min; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n uint max; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n }\n\n TransferFee public transferFee;\n\n event TransferFeesChanged(uint transferFeePt, uint transferFeeMin, uint transferFeeMax);\n\n constructor(address permissionGranterContract, uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n public SystemAccount(permissionGranterContract) {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function () external payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into feeAccount (defaulting fee in ETH )\n }\n\n function setTransferFees(uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n external restrict(\"StabilityBoard\") {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n emit TransferFeesChanged(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function calculateTransferFee(address from, address to, uint amount) external view returns (uint256 fee) {\n if (!permissions[from][\"NoTransferFee\"] && !permissions[to][\"NoTransferFee\"]) {\n fee = amount.mul(transferFee.pt).div(1000000);\n if (fee > transferFee.max) {\n fee = transferFee.max;\n } else if (fee < transferFee.min) {\n fee = transferFee.min;\n }\n }\n return fee;\n }\n\n function calculateExchangeFee(uint weiAmount) external view returns (uint256 weiFee) {\n /* TODO: to be implemented and use in Exchange.sol. always revert for now */\n require(weiAmount != weiAmount, \"not yet implemented\");\n weiFee = transferFee.max; // to silence compiler warnings until it's implemented\n }\n\n}\n" } } } diff --git a/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json b/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json index 1a7ae0d4..be5c1f7f 100644 --- a/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json +++ b/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json @@ -2,79 +2,32 @@ "contractName": "InterestEarnedAccount", "latestAbiHash": "11b039ce783db308e1a9b5f46f05824f", "deployedAbis": { - "2282749a57fa5c7d61cf33b2f04daf2b": { - "latestDeployedAddress": "0x12d3f1ea52e9e30b74720f70fbe57dd940e878f3", - "deployments": { - "0x2fdd4f69fcda83950a7e976b10b594e01a3c43f1": { - "generatedAt": "2018-04-25T12:29:07.537Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:28:03.467Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "10f2c7bcc89c991f8036cd653a9c9254", - "deployedBytecodeHash": "6d1f7692b0b3214dce6de23ef79d0567", - "sourceHash": "a08b32cfe73754d798c1e9a2f2d69bcb", - "source": "/* Contract to hold earned interest from loans repaid\n premiums for locks are being accrued (i.e. transferred) to Locker */\n\npragma solidity 0.4.19;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract InterestEarnedAccount is SystemAccount {\n\n function transferInterest(AugmintTokenInterface augmintToken, address locker, uint interestAmount)\n external restrict(\"MonetarySupervisorContract\") {\n augmintToken.transfer(locker, interestAmount);\n }\n\n}\n" - }, - "0x12d3f1ea52e9e30b74720f70fbe57dd940e878f3": { - "generatedAt": "2018-04-25T12:30:49.115Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:31:58.109Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "fa7e41b12921f5486139b113e27d9f42", - "deployedBytecodeHash": "3b0ffecb49e2308162baea06ab012022", - "sourceHash": "a08b32cfe73754d798c1e9a2f2d69bcb", - "source": "/* Contract to hold earned interest from loans repaid\n premiums for locks are being accrued (i.e. transferred) to Locker */\n\npragma solidity 0.4.19;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract InterestEarnedAccount is SystemAccount {\n\n function transferInterest(AugmintTokenInterface augmintToken, address locker, uint interestAmount)\n external restrict(\"MonetarySupervisorContract\") {\n augmintToken.transfer(locker, interestAmount);\n }\n\n}\n" - } - } - }, - "72a73972d565bb24463e7368fd263af4": { - "latestDeployedAddress": "0x3a414d7636defb9d3dfb7342984fe3f7b5125df6", - "deployments": { - "0x3a414d7636defb9d3dfb7342984fe3f7b5125df6": { - "generatedAt": "2018-04-25T12:31:29.080Z", - "truffleContractFileUpdatedAt": "2018-04-20T18:14:08.859Z", - "deployTransactionHash": "0x696dc4d8dc61fe00debe2d7b625805c5d087689de87dcaddb9fc4fe037c4b3f8", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "e12b38103657a4ae2a9c1fad1bbe7498", - "deployedBytecodeHash": "47b56a5ab267ee1bc0e0b0d050080a29", - "sourceHash": "080bdccd163b74b49fb908b443c45199", - "source": "/* Contract to hold earned interest from loans repaid\n premiums for locks are being accrued (i.e. transferred) to Locker */\n\npragma solidity ^0.4.23;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract InterestEarnedAccount is SystemAccount {\n\n function transferInterest(AugmintTokenInterface augmintToken, address locker, uint interestAmount)\n external restrict(\"MonetarySupervisorContract\") {\n augmintToken.transfer(locker, interestAmount);\n }\n\n}\n" - } - } - }, "11b039ce783db308e1a9b5f46f05824f": { - "latestDeployedAddress": "0xdf8c338a89f827a6d62804905ed415b6a382f92e", + "latestDeployedAddress": "0xdd96979697b76787b5062084eea60bf929ddd844", "deployments": { - "0xdd1b8dfd9094e319a0eb83c32b47331946cb761f": { - "generatedAt": "2018-06-04T12:49:52.515Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.439Z", - "deployTransactionHash": "0x2619c360d95a213cd49a6f9b6bd796d19f3b9acdd213d4f07990e353a176277f", + "0x489cbf1674b575e6dfcff0a4f2bbc74f7e9dde28": { + "generatedAt": "2018-10-18T13:35:02.360Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.821Z", + "deployTransactionHash": "0xaa5e1a7211cbc4d830e535773c1eb20d0866288ac86313016891c059200d8f9e", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "a2eb5944fe25fe72d5f5948c924a77e1", - "deployedBytecodeHash": "f7e6478975d25a023acd5a16ff307a5b", - "sourceHash": "1d71a7b664ac13b66b772f24e48edb32", - "source": "/* Contract to hold earned interest from loans repaid\n premiums for locks are being accrued (i.e. transferred) to Locker */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract InterestEarnedAccount is SystemAccount {\n\n constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function transferInterest(AugmintTokenInterface augmintToken, address locker, uint interestAmount)\n external restrict(\"MonetarySupervisorContract\") {\n augmintToken.transfer(locker, interestAmount);\n }\n\n}\n" + "bytecodeHash": "3994e47ec4faf784d97e783d6e3de64d", + "deployedBytecodeHash": "9b8b05d9a455663e6bc0b4aa953ef26e", + "sourceHash": "3ae3310cda808efba999807e54bf8c9b", + "source": "/* Contract to hold earned interest from loans repaid\n premiums for locks are being accrued (i.e. transferred) to Locker */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract InterestEarnedAccount is SystemAccount {\n\n constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function transferInterest(AugmintTokenInterface augmintToken, address locker, uint interestAmount)\n external restrict(\"MonetarySupervisor\") {\n augmintToken.transfer(locker, interestAmount);\n }\n\n}\n" }, - "0xdf8c338a89f827a6d62804905ed415b6a382f92e": { - "generatedAt": "2018-06-10T08:34:44.848Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.605Z", - "deployTransactionHash": "0x6a303a203866d5f5aef9cbd49cf07bfe98bdd3a10a908923b90b7319b184daaf", + "0xdd96979697b76787b5062084eea60bf929ddd844": { + "generatedAt": "2018-10-29T15:52:43.264Z", + "truffleContractFileUpdatedAt": "2018-10-19T15:49:10.698Z", + "deployTransactionHash": "0x81314fc9a671dbec1fe3632110fbaeaf89124f186d431443fa67c0ebdb9bdd4a", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "1a57f465af930a1cc7070876d2a6bde3", - "deployedBytecodeHash": "62cba71783fcbe9a394e7ef9880058da", + "bytecodeHash": "3994e47ec4faf784d97e783d6e3de64d", + "deployedBytecodeHash": "9b8b05d9a455663e6bc0b4aa953ef26e", "sourceHash": "3ae3310cda808efba999807e54bf8c9b", "source": "/* Contract to hold earned interest from loans repaid\n premiums for locks are being accrued (i.e. transferred) to Locker */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract InterestEarnedAccount is SystemAccount {\n\n constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function transferInterest(AugmintTokenInterface augmintToken, address locker, uint interestAmount)\n external restrict(\"MonetarySupervisor\") {\n augmintToken.transfer(locker, interestAmount);\n }\n\n}\n" } diff --git a/abiniser/deployments/4/LoanManager_DEPLOYS.json b/abiniser/deployments/4/LoanManager_DEPLOYS.json index 5c796fe0..f3910871 100644 --- a/abiniser/deployments/4/LoanManager_DEPLOYS.json +++ b/abiniser/deployments/4/LoanManager_DEPLOYS.json @@ -1,100 +1,35 @@ { "contractName": "LoanManager", - "latestAbiHash": "ec709c3341045caa3a75374b8cfc7286", + "latestAbiHash": "fdf5fde95aa940c6dbfb8353c572c5fb", "deployedAbis": { - "dd8d5ec97e0a22b6f9e63b04d4e11e09": { - "latestDeployedAddress": "0xfb505462633ae3234760d0ee51c557199ab249df", + "fdf5fde95aa940c6dbfb8353c572c5fb": { + "latestDeployedAddress": "0x3792c5a5077dacfe331b81837ef73bc0ea721d90", "deployments": { - "0xfb505462633ae3234760d0ee51c557199ab249df": { - "generatedAt": "2018-04-25T12:29:07.585Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:28:03.482Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "aa67baec70431e71c2be8d412df7f2d8", - "deployedBytecodeHash": "9906a9c556eabbf516789bbd2510ca24", - "sourceHash": "759bfe882bcce74bc3b207640322e232", - "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - interestEarnedAccount setter?\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - create and use InterestEarnedAccount interface instead?\n - make collect() run as long as gas provided allows\n*/\npragma solidity 0.4.19;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted {\n using SafeMath for uint256;\n\n enum LoanState { Open, Repaid, Defaulted }\n\n struct LoanProduct {\n uint term; // 0\n uint discountRate; // 1: discountRate in parts per million , ie. 10,000 = 1%\n uint collateralRatio; // 2: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint minDisbursedAmount; // 3: with 4 decimals, e.g. 31000 = 3.1ACE\n uint defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n struct LoanData {\n address borrower; // 0\n LoanState state; // 1\n uint collateralAmount; // 2\n uint repaymentAmount; // 3\n uint loanAmount; // 4\n uint interestAmount; // 5\n uint term; // 6\n uint disbursementDate; // 7\n uint maturity; // 8\n uint defaultingFeePt; // 9\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public mLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n InterestEarnedAccount public interestEarnedAccount;\n\n event NewLoan(uint productId, uint loanId, address borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount);\n\n event LoanProductActiveStateChanged(uint productId, bool newState);\n\n event LoanProductAdded(uint productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint indexed loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n function LoanManager(AugmintTokenInterface _augmintToken, MonetarySupervisor _monetarySupervisor, Rates _rates,\n InterestEarnedAccount _interestEarnedAccount)\n public {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n interestEarnedAccount = _interestEarnedAccount;\n }\n\n function addLoanProduct(uint _term, uint _discountRate, uint _collateralRatio, uint _minDisbursedAmount,\n uint _defaultingFee, bool _isActive)\n external restrict(\"MonetaryBoard\") returns (uint newProductId) {\n newProductId = products.push(\n LoanProduct(_term, _discountRate, _collateralRatio, _minDisbursedAmount, _defaultingFee, _isActive)\n ) - 1;\n\n LoanProductAdded(newProductId);\n return newProductId;\n }\n\n function setLoanProductActiveState(uint8 productId, bool newState)\n external restrict (\"MonetaryBoard\") {\n products[productId].isActive = false;\n LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint8 productId) external payable {\n require(products[productId].isActive); // valid productId?\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(products[productId].collateralRatio).roundedDiv(100000000);\n repaymentAmount = repaymentAmount * 100; // rounding 4 decimals value to 2 decimals.\n // no safe mul needed b/c of prev divide\n\n uint mul = products[productId].collateralRatio.mul(products[productId].discountRate) / 1000000;\n uint loanAmount = tokenValue.mul(mul).roundedDiv(100000000);\n loanAmount = loanAmount * 100; // rounding 4 decimals value to 2 decimals.\n // no safe mul needed b/c of prev divide\n\n require(loanAmount >= products[productId].minDisbursedAmount);\n uint interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n\n // Create new loan\n uint loanId = loans.push(\n LoanData(msg.sender, LoanState.Open, msg.value, repaymentAmount, loanAmount,\n interestAmount, products[productId].term, now, now + products[productId].term,\n products[productId].defaultingFeePt)\n ) - 1;\n\n // Store ref to new loan\n mLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n for (uint i = 0; i < loanIds.length; i++) {\n uint loanId = loanIds[i];\n require(loans[loanId].state == LoanState.Open);\n require(now >= loans[loanId].maturity);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loans[loanId].loanAmount);\n\n loans[loanId].state = LoanState.Defaulted;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loans[loanId].repaymentAmount.mul(loans[loanId].defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(), loans[loanId].repaymentAmount)\n .add(defaultingFee);\n uint releasedCollateral;\n if (targetCollection < loans[loanId].collateralAmount) {\n releasedCollateral = loans[loanId].collateralAmount.sub(targetCollection);\n loans[loanId].borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loans[loanId].collateralAmount.sub(releasedCollateral);\n if (defaultingFee > collateralToCollect) {\n defaultingFee = collateralToCollect;\n }\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n LoanCollected(loanId, loans[loanId].borrower, collateralToCollect, releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n monetarySupervisor.augmintReserves().transfer(totalCollateralToCollect);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n function getLoanCount() external view returns (uint ct) {\n return loans.length;\n }\n\n function getProductCount() external view returns (uint ct) {\n return products.length;\n }\n\n function getLoanIds(address borrower) external view returns (uint[] _loans) {\n return mLoans[borrower];\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) public {\n require(msg.sender == address(augmintToken));\n _repayLoan(loanId, repaymentAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n require(loans[loanId].state == LoanState.Open);\n require(now <= loans[loanId].maturity);\n require(loans[loanId].repaymentAmount == repaymentAmount);\n loans[loanId].state = LoanState.Repaid;\n\n augmintToken.transfer(interestEarnedAccount, loans[loanId].interestAmount);\n\n augmintToken.burn(loans[loanId].loanAmount);\n monetarySupervisor.loanRepaymentNotification(loans[loanId].loanAmount); // update KPIs\n\n loans[loanId].borrower.transfer(loans[loanId].collateralAmount); // send back ETH collateral\n\n LoanRepayed(loanId, loans[loanId].borrower);\n }\n\n}\n" - } - } - }, - "d72d3bd9689dba0d1a8cd4ec23757257": { - "latestDeployedAddress": "0xec5e35d8941386c3e08019b0ad1d4a8c40c7bcbc", - "deployments": { - "0xec5e35d8941386c3e08019b0ad1d4a8c40c7bcbc": { - "generatedAt": "2018-04-25T12:30:49.374Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:36:28.169Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "9aa1d3b1d7b1c4593514e33e4854ac41", - "deployedBytecodeHash": "60180139c1bd8c2e65ca93a4a5023884", - "sourceHash": "5663e971bf347b437fd2860c13e65ea1", - "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - interestEarnedAccount setter?\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - create and use InterestEarnedAccount interface instead?\n - make collect() run as long as gas provided allows\n*/\npragma solidity 0.4.19;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted {\n using SafeMath for uint256;\n\n uint16 public constant CHUNK_SIZE = 100;\n\n enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate\n\n struct LoanProduct {\n uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals\n uint32 term; // 1\n uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1%\n uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */\n struct LoanData {\n uint collateralAmount; // 0\n uint repaymentAmount; // 1\n address borrower; // 2\n uint32 productId; // 3\n LoanState state; // 4\n uint40 maturity; // 5\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n InterestEarnedAccount public interestEarnedAccount;\n\n event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount, uint40 maturity);\n\n event LoanProductActiveStateChanged(uint32 productId, bool newState);\n\n event LoanProductAdded(uint32 productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n function LoanManager(AugmintTokenInterface _augmintToken, MonetarySupervisor _monetarySupervisor, Rates _rates,\n InterestEarnedAccount _interestEarnedAccount)\n public {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n interestEarnedAccount = _interestEarnedAccount;\n }\n\n function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount,\n uint32 defaultingFeePt, bool isActive)\n external restrict(\"MonetaryBoard\") {\n\n uint _newProductId = products.push(\n LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive)\n ) - 1;\n\n uint32 newProductId = uint32(_newProductId);\n require(newProductId == _newProductId);\n\n LoanProductAdded(newProductId);\n }\n\n function setLoanProductActiveState(uint32 productId, bool newState)\n external restrict (\"MonetaryBoard\") {\n products[productId].isActive = false;\n LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint32 productId) external payable {\n LoanProduct storage product = products[productId];\n require(product.isActive); // valid productId?\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000);\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, repaymentAmount);\n\n require(loanAmount >= product.minDisbursedAmount);\n\n uint expiration = now.add(product.term);\n uint40 maturity = uint40(expiration);\n require(maturity == expiration);\n\n // Create new loan\n uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender,\n productId, LoanState.Open, maturity)) - 1;\n\n // Store ref to new loan\n accountLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n for (uint i = 0; i < loanIds.length; i++) {\n LoanData storage loan = loans[loanIds[i]];\n require(loan.state == LoanState.Open);\n require(now >= loan.maturity);\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount);\n\n loan.state = LoanState.Collected;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(),\n loan.repaymentAmount).add(defaultingFee);\n\n uint releasedCollateral;\n if (targetCollection < loan.collateralAmount) {\n releasedCollateral = loan.collateralAmount.sub(targetCollection);\n loan.borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral);\n if (defaultingFee > collateralToCollect) {\n defaultingFee = collateralToCollect;\n }\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n LoanCollected(loanIds[i], loan.borrower, collateralToCollect, releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n monetarySupervisor.augmintReserves().transfer(totalCollateralToCollect);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n function getProductCount() external view returns (uint ct) {\n return products.length;\n }\n\n // returns CHUNK_SIZE loan products starting from some offset:\n // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive ]\n function getProducts(uint offset) external view returns (uint[7][CHUNK_SIZE] response) {\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= products.length) { break; }\n\n LoanProduct storage product = products[offset + i];\n\n response[i] = [offset + i, product.minDisbursedAmount, product.term, product.discountRate,\n product.collateralRatio, product.defaultingFeePt, product.isActive ? 1 : 0 ];\n }\n }\n\n function getLoanCount() external view returns (uint ct) {\n return loans.length;\n }\n\n /* returns CHUNK_SIZE loans starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoans(uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loans.length) { break; }\n\n response[i] = getLoanTuple(offset + i);\n }\n }\n\n function getLoanCountForAddress(address borrower) external view returns (uint) {\n return accountLoans[borrower].length;\n }\n\n /* returns CHUNK_SIZE loans of a given account, starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoansForAddress(address borrower, uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n uint[] storage loansForAddress = accountLoans[borrower];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loansForAddress.length) { break; }\n\n response[i] = getLoanTuple(loansForAddress[offset + i]);\n }\n }\n\n function getLoanTuple(uint loanId) public view returns (uint[10] result) {\n LoanData storage loan = loans[loanId];\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n uint disbursementTime = loan.maturity - product.term;\n\n LoanState loanState =\n loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state;\n\n result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower),\n loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount];\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) public {\n require(msg.sender == address(augmintToken));\n _repayLoan(loanId, repaymentAmount);\n }\n\n function calculateLoanValues(LoanProduct storage product, uint repaymentAmount)\n internal view returns (uint loanAmount, uint interestAmount) {\n // calculate loan values based on repayment amount\n loanAmount = repaymentAmount.mul(product.discountRate).div(1000000);\n interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n LoanData storage loan = loans[loanId];\n require(loan.state == LoanState.Open);\n require(repaymentAmount == loan.repaymentAmount);\n require(now <= loan.maturity);\n\n LoanProduct storage product = products[loan.productId];\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n\n loans[loanId].state = LoanState.Repaid;\n\n if (interestAmount > 0) {\n augmintToken.transfer(interestEarnedAccount, interestAmount);\n augmintToken.burn(loanAmount);\n } else {\n // negative or zero interest (i.e. discountRate >= 0)\n augmintToken.burn(repaymentAmount);\n }\n\n monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs\n\n loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral\n\n LoanRepayed(loanId, loan.borrower);\n }\n\n}\n" - } - } - }, - "291572b8d2ffe95dca1733ebc1472e08": { - "latestDeployedAddress": "0x214919abe3f2b7ca7a43a799c4fc7132bbf78e8a", - "deployments": { - "0xbdb02f82d7ad574f9f549895caf41e23a8981b07": { - "generatedAt": "2018-04-25T12:31:29.206Z", - "truffleContractFileUpdatedAt": "2018-04-20T18:26:53.590Z", - "deployTransactionHash": "0x9a1e815db150bdf6cb73ff8548fd42adfafdf09aaa360bbac6413d9212214239", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "2572499c203be33724d3289e0a89f7a7", - "deployedBytecodeHash": "7b195ed87405ef49bec0955ea58bb0ea", - "sourceHash": "9d5f96db98b6d336c18b8c6df5c7cd92", - "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - make collect() run as long as gas provided allows\n*/\npragma solidity ^0.4.23;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted {\n using SafeMath for uint256;\n\n uint16 public constant CHUNK_SIZE = 100;\n\n enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate\n\n struct LoanProduct {\n uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals\n uint32 term; // 1\n uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1%\n uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */\n struct LoanData {\n uint collateralAmount; // 0\n uint repaymentAmount; // 1\n address borrower; // 2\n uint32 productId; // 3\n LoanState state; // 4\n uint40 maturity; // 5\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n\n event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount, uint40 maturity);\n\n event LoanProductActiveStateChanged(uint32 productId, bool newState);\n\n event LoanProductAdded(uint32 productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n event SystemContractsChanged(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor);\n\n constructor(AugmintTokenInterface _augmintToken, MonetarySupervisor _monetarySupervisor, Rates _rates)\n public {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n }\n\n function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount,\n uint32 defaultingFeePt, bool isActive)\n external restrict(\"MonetaryBoard\") {\n\n uint _newProductId = products.push(\n LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive)\n ) - 1;\n\n uint32 newProductId = uint32(_newProductId);\n require(newProductId == _newProductId, \"productId overflow\");\n\n emit LoanProductAdded(newProductId);\n }\n\n function setLoanProductActiveState(uint32 productId, bool newState)\n external restrict (\"MonetaryBoard\") {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n products[productId].isActive = false;\n emit LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint32 productId) external payable {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n LoanProduct storage product = products[productId];\n require(product.isActive, \"product must be in active state\"); // valid product\n\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000);\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, repaymentAmount);\n\n require(loanAmount >= product.minDisbursedAmount, \"loanAmount must be >= minDisbursedAmount\");\n\n uint expiration = now.add(product.term);\n uint40 maturity = uint40(expiration);\n require(maturity == expiration, \"maturity overflow\");\n\n // Create new loan\n uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender,\n productId, LoanState.Open, maturity)) - 1;\n\n // Store ref to new loan\n accountLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n emit NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity);\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n\n _repayLoan(loanId, repaymentAmount);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n uint totalDefaultingFee;\n for (uint i = 0; i < loanIds.length; i++) {\n require(i < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanIds[i]];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(now >= loan.maturity, \"current time must be later than maturity\");\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount);\n\n loan.state = LoanState.Collected;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(),\n loan.repaymentAmount).add(defaultingFee);\n\n uint releasedCollateral;\n if (targetCollection < loan.collateralAmount) {\n releasedCollateral = loan.collateralAmount.sub(targetCollection);\n loan.borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral);\n if (defaultingFee >= collateralToCollect) {\n defaultingFee = collateralToCollect;\n collateralToCollect = 0;\n } else {\n collateralToCollect = collateralToCollect.sub(defaultingFee);\n }\n totalDefaultingFee = totalDefaultingFee.add(defaultingFee);\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee), releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect);\n }\n\n if (totalDefaultingFee > 0){\n address(augmintToken.feeAccount()).transfer(totalDefaultingFee);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n /* to allow upgrade of Rates and MonetarySupervisor contracts */\n function setSystemContracts(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor)\n external restrict(\"MonetaryBoard\") {\n rates = newRatesContract;\n monetarySupervisor = newMonetarySupervisor;\n emit SystemContractsChanged(newRatesContract, newMonetarySupervisor);\n }\n\n function getProductCount() external view returns (uint ct) {\n return products.length;\n }\n\n // returns CHUNK_SIZE loan products starting from some offset:\n // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ]\n function getProducts(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= products.length) { break; }\n\n LoanProduct storage product = products[offset + i];\n\n response[i] = [offset + i, product.minDisbursedAmount, product.term, product.discountRate,\n product.collateralRatio, product.defaultingFeePt,\n monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ];\n }\n }\n\n function getLoanCount() external view returns (uint ct) {\n return loans.length;\n }\n\n /* returns CHUNK_SIZE loans starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoans(uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loans.length) { break; }\n\n response[i] = getLoanTuple(offset + i);\n }\n }\n\n function getLoanCountForAddress(address borrower) external view returns (uint) {\n return accountLoans[borrower].length;\n }\n\n /* returns CHUNK_SIZE loans of a given account, starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoansForAddress(address borrower, uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n uint[] storage loansForAddress = accountLoans[borrower];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loansForAddress.length) { break; }\n\n response[i] = getLoanTuple(loansForAddress[offset + i]);\n }\n }\n\n function getLoanTuple(uint loanId) public view returns (uint[10] result) {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n uint disbursementTime = loan.maturity - product.term;\n\n LoanState loanState =\n loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state;\n\n result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower),\n loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount];\n }\n\n function calculateLoanValues(LoanProduct storage product, uint repaymentAmount)\n internal view returns (uint loanAmount, uint interestAmount) {\n // calculate loan values based on repayment amount\n loanAmount = repaymentAmount.mul(product.discountRate).div(1000000);\n interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(repaymentAmount == loan.repaymentAmount, \"repaymentAmount must be equal to tokens sent\");\n require(now <= loan.maturity, \"current time must be earlier than maturity\");\n\n LoanProduct storage product = products[loan.productId];\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n\n loans[loanId].state = LoanState.Repaid;\n\n if (interestAmount > 0) {\n augmintToken.transfer(monetarySupervisor.interestEarnedAccount(), interestAmount);\n augmintToken.burn(loanAmount);\n } else {\n // negative or zero interest (i.e. discountRate >= 0)\n augmintToken.burn(repaymentAmount);\n }\n\n monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs\n\n loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral\n\n emit LoanRepayed(loanId, loan.borrower);\n }\n\n}\n" - }, - "0x214919abe3f2b7ca7a43a799c4fc7132bbf78e8a": { - "generatedAt": "2018-05-12T01:34:38.508Z", - "truffleContractFileUpdatedAt": "2018-05-12T01:30:50.403Z", - "deployTransactionHash": "0x809f88d01aa3ddef9c215492f1e6dcf18db2efecc925469af77b49a2c4df3b93", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "feef104fe0b04cf9bde178c2f8ee4c04", - "deployedBytecodeHash": "d16030995b358f9fd29dafc6df7e6d35", - "sourceHash": "9d5f96db98b6d336c18b8c6df5c7cd92", - "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - make collect() run as long as gas provided allows\n*/\npragma solidity ^0.4.23;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted {\n using SafeMath for uint256;\n\n uint16 public constant CHUNK_SIZE = 100;\n\n enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate\n\n struct LoanProduct {\n uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals\n uint32 term; // 1\n uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1%\n uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */\n struct LoanData {\n uint collateralAmount; // 0\n uint repaymentAmount; // 1\n address borrower; // 2\n uint32 productId; // 3\n LoanState state; // 4\n uint40 maturity; // 5\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n\n event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount, uint40 maturity);\n\n event LoanProductActiveStateChanged(uint32 productId, bool newState);\n\n event LoanProductAdded(uint32 productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n event SystemContractsChanged(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor);\n\n constructor(AugmintTokenInterface _augmintToken, MonetarySupervisor _monetarySupervisor, Rates _rates)\n public {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n }\n\n function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount,\n uint32 defaultingFeePt, bool isActive)\n external restrict(\"MonetaryBoard\") {\n\n uint _newProductId = products.push(\n LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive)\n ) - 1;\n\n uint32 newProductId = uint32(_newProductId);\n require(newProductId == _newProductId, \"productId overflow\");\n\n emit LoanProductAdded(newProductId);\n }\n\n function setLoanProductActiveState(uint32 productId, bool newState)\n external restrict (\"MonetaryBoard\") {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n products[productId].isActive = false;\n emit LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint32 productId) external payable {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n LoanProduct storage product = products[productId];\n require(product.isActive, \"product must be in active state\"); // valid product\n\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000);\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, repaymentAmount);\n\n require(loanAmount >= product.minDisbursedAmount, \"loanAmount must be >= minDisbursedAmount\");\n\n uint expiration = now.add(product.term);\n uint40 maturity = uint40(expiration);\n require(maturity == expiration, \"maturity overflow\");\n\n // Create new loan\n uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender,\n productId, LoanState.Open, maturity)) - 1;\n\n // Store ref to new loan\n accountLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n emit NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity);\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n\n _repayLoan(loanId, repaymentAmount);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n uint totalDefaultingFee;\n for (uint i = 0; i < loanIds.length; i++) {\n require(i < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanIds[i]];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(now >= loan.maturity, \"current time must be later than maturity\");\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount);\n\n loan.state = LoanState.Collected;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(),\n loan.repaymentAmount).add(defaultingFee);\n\n uint releasedCollateral;\n if (targetCollection < loan.collateralAmount) {\n releasedCollateral = loan.collateralAmount.sub(targetCollection);\n loan.borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral);\n if (defaultingFee >= collateralToCollect) {\n defaultingFee = collateralToCollect;\n collateralToCollect = 0;\n } else {\n collateralToCollect = collateralToCollect.sub(defaultingFee);\n }\n totalDefaultingFee = totalDefaultingFee.add(defaultingFee);\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee), releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect);\n }\n\n if (totalDefaultingFee > 0){\n address(augmintToken.feeAccount()).transfer(totalDefaultingFee);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n /* to allow upgrade of Rates and MonetarySupervisor contracts */\n function setSystemContracts(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor)\n external restrict(\"MonetaryBoard\") {\n rates = newRatesContract;\n monetarySupervisor = newMonetarySupervisor;\n emit SystemContractsChanged(newRatesContract, newMonetarySupervisor);\n }\n\n function getProductCount() external view returns (uint ct) {\n return products.length;\n }\n\n // returns CHUNK_SIZE loan products starting from some offset:\n // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ]\n function getProducts(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= products.length) { break; }\n\n LoanProduct storage product = products[offset + i];\n\n response[i] = [offset + i, product.minDisbursedAmount, product.term, product.discountRate,\n product.collateralRatio, product.defaultingFeePt,\n monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ];\n }\n }\n\n function getLoanCount() external view returns (uint ct) {\n return loans.length;\n }\n\n /* returns CHUNK_SIZE loans starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoans(uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loans.length) { break; }\n\n response[i] = getLoanTuple(offset + i);\n }\n }\n\n function getLoanCountForAddress(address borrower) external view returns (uint) {\n return accountLoans[borrower].length;\n }\n\n /* returns CHUNK_SIZE loans of a given account, starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoansForAddress(address borrower, uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n uint[] storage loansForAddress = accountLoans[borrower];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loansForAddress.length) { break; }\n\n response[i] = getLoanTuple(loansForAddress[offset + i]);\n }\n }\n\n function getLoanTuple(uint loanId) public view returns (uint[10] result) {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n uint disbursementTime = loan.maturity - product.term;\n\n LoanState loanState =\n loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state;\n\n result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower),\n loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount];\n }\n\n function calculateLoanValues(LoanProduct storage product, uint repaymentAmount)\n internal view returns (uint loanAmount, uint interestAmount) {\n // calculate loan values based on repayment amount\n loanAmount = repaymentAmount.mul(product.discountRate).div(1000000);\n interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(repaymentAmount == loan.repaymentAmount, \"repaymentAmount must be equal to tokens sent\");\n require(now <= loan.maturity, \"current time must be earlier than maturity\");\n\n LoanProduct storage product = products[loan.productId];\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n\n loans[loanId].state = LoanState.Repaid;\n\n if (interestAmount > 0) {\n augmintToken.transfer(monetarySupervisor.interestEarnedAccount(), interestAmount);\n augmintToken.burn(loanAmount);\n } else {\n // negative or zero interest (i.e. discountRate >= 0)\n augmintToken.burn(repaymentAmount);\n }\n\n monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs\n\n loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral\n\n emit LoanRepayed(loanId, loan.borrower);\n }\n\n}\n" - } - } - }, - "ec709c3341045caa3a75374b8cfc7286": { - "latestDeployedAddress": "0x3b5dd323534659655eeccc642c3e338aabd0b219", - "deployments": { - "0x08281151718983b6dbf0aafb810738d8bd1d2e4a": { - "generatedAt": "2018-06-04T12:49:52.625Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.491Z", - "deployTransactionHash": "0x647eff169e3c8f26658191a73332151f73007fd645ca45202cfa542de9c5eb08", + "0x6cb7731c78e677f85942b5f1d646b3485e5820c1": { + "generatedAt": "2018-10-18T13:35:02.404Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:37.002Z", + "deployTransactionHash": "0xc965162409524ff0b21cebe1a763229400994d88856dfdd766398a47f0d6493f", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "ce5c6aab66fb451d79cdeb1cbd843704", - "deployedBytecodeHash": "966eabcce3addb5a313ec1314ff54b13", - "sourceHash": "0b586306fda3d8aabd1f84b4925eb437", - "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - make collect() run as long as gas provided allows\n*/\npragma solidity 0.4.24;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted {\n using SafeMath for uint256;\n\n uint16 public constant CHUNK_SIZE = 100;\n\n enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate\n\n struct LoanProduct {\n uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals\n uint32 term; // 1\n uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1%\n uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */\n struct LoanData {\n uint collateralAmount; // 0\n uint repaymentAmount; // 1\n address borrower; // 2\n uint32 productId; // 3\n LoanState state; // 4\n uint40 maturity; // 5\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n\n event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount, uint40 maturity);\n\n event LoanProductActiveStateChanged(uint32 productId, bool newState);\n\n event LoanProductAdded(uint32 productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n event SystemContractsChanged(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n }\n\n function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount,\n uint32 defaultingFeePt, bool isActive)\n external restrict(\"StabilityBoardSignerContract\") {\n\n uint _newProductId = products.push(\n LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive)\n ) - 1;\n\n uint32 newProductId = uint32(_newProductId);\n require(newProductId == _newProductId, \"productId overflow\");\n\n emit LoanProductAdded(newProductId);\n }\n\n function setLoanProductActiveState(uint32 productId, bool newState)\n external restrict (\"StabilityBoardSignerContract\") {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n products[productId].isActive = false;\n emit LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint32 productId) external payable {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n LoanProduct storage product = products[productId];\n require(product.isActive, \"product must be in active state\"); // valid product\n\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000);\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, repaymentAmount);\n\n require(loanAmount >= product.minDisbursedAmount, \"loanAmount must be >= minDisbursedAmount\");\n\n uint expiration = now.add(product.term);\n uint40 maturity = uint40(expiration);\n require(maturity == expiration, \"maturity overflow\");\n\n // Create new loan\n uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender,\n productId, LoanState.Open, maturity)) - 1;\n\n // Store ref to new loan\n accountLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n emit NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity);\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n\n _repayLoan(loanId, repaymentAmount);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n uint totalDefaultingFee;\n for (uint i = 0; i < loanIds.length; i++) {\n require(i < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanIds[i]];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(now >= loan.maturity, \"current time must be later than maturity\");\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount);\n\n loan.state = LoanState.Collected;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(),\n loan.repaymentAmount).add(defaultingFee);\n\n uint releasedCollateral;\n if (targetCollection < loan.collateralAmount) {\n releasedCollateral = loan.collateralAmount.sub(targetCollection);\n loan.borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral);\n if (defaultingFee >= collateralToCollect) {\n defaultingFee = collateralToCollect;\n collateralToCollect = 0;\n } else {\n collateralToCollect = collateralToCollect.sub(defaultingFee);\n }\n totalDefaultingFee = totalDefaultingFee.add(defaultingFee);\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee), releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect);\n }\n\n if (totalDefaultingFee > 0){\n address(augmintToken.feeAccount()).transfer(totalDefaultingFee);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n /* to allow upgrade of Rates and MonetarySupervisor contracts */\n function setSystemContracts(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor)\n external restrict(\"StabilityBoardSignerContract\") {\n rates = newRatesContract;\n monetarySupervisor = newMonetarySupervisor;\n emit SystemContractsChanged(newRatesContract, newMonetarySupervisor);\n }\n\n function getProductCount() external view returns (uint ct) {\n return products.length;\n }\n\n // returns CHUNK_SIZE loan products starting from some offset:\n // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ]\n function getProducts(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= products.length) { break; }\n\n LoanProduct storage product = products[offset + i];\n\n response[i] = [offset + i, product.minDisbursedAmount, product.term, product.discountRate,\n product.collateralRatio, product.defaultingFeePt,\n monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ];\n }\n }\n\n function getLoanCount() external view returns (uint ct) {\n return loans.length;\n }\n\n /* returns CHUNK_SIZE loans starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoans(uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loans.length) { break; }\n\n response[i] = getLoanTuple(offset + i);\n }\n }\n\n function getLoanCountForAddress(address borrower) external view returns (uint) {\n return accountLoans[borrower].length;\n }\n\n /* returns CHUNK_SIZE loans of a given account, starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoansForAddress(address borrower, uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n uint[] storage loansForAddress = accountLoans[borrower];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loansForAddress.length) { break; }\n\n response[i] = getLoanTuple(loansForAddress[offset + i]);\n }\n }\n\n function getLoanTuple(uint loanId) public view returns (uint[10] result) {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n uint disbursementTime = loan.maturity - product.term;\n\n LoanState loanState =\n loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state;\n\n result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower),\n loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount];\n }\n\n function calculateLoanValues(LoanProduct storage product, uint repaymentAmount)\n internal view returns (uint loanAmount, uint interestAmount) {\n // calculate loan values based on repayment amount\n loanAmount = repaymentAmount.mul(product.discountRate).div(1000000);\n interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(repaymentAmount == loan.repaymentAmount, \"repaymentAmount must be equal to tokens sent\");\n require(now <= loan.maturity, \"current time must be earlier than maturity\");\n\n LoanProduct storage product = products[loan.productId];\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n\n loans[loanId].state = LoanState.Repaid;\n\n if (interestAmount > 0) {\n augmintToken.transfer(monetarySupervisor.interestEarnedAccount(), interestAmount);\n augmintToken.burn(loanAmount);\n } else {\n // negative or zero interest (i.e. discountRate >= 0)\n augmintToken.burn(repaymentAmount);\n }\n\n monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs\n\n loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral\n\n emit LoanRepayed(loanId, loan.borrower);\n }\n\n}\n" + "bytecodeHash": "591f565c201032e0df4b9f7798e7ec85", + "deployedBytecodeHash": "e93edcccad1eb8f9142f6c257bb23bdd", + "sourceHash": "234fd5848af85ca2444c888fd6ba61aa", + "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - make collect() run as long as gas provided allows\n*/\npragma solidity 0.4.24;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted, TokenReceiver {\n using SafeMath for uint256;\n\n enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate\n\n struct LoanProduct {\n uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals\n uint32 term; // 1\n uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1%\n uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */\n struct LoanData {\n uint collateralAmount; // 0\n uint repaymentAmount; // 1\n address borrower; // 2\n uint32 productId; // 3\n LoanState state; // 4\n uint40 maturity; // 5\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n\n event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount, uint40 maturity);\n\n event LoanProductActiveStateChanged(uint32 productId, bool newState);\n\n event LoanProductAdded(uint32 productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n event SystemContractsChanged(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n }\n\n function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount,\n uint32 defaultingFeePt, bool isActive)\n external restrict(\"StabilityBoard\") {\n\n uint _newProductId = products.push(\n LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive)\n ) - 1;\n\n uint32 newProductId = uint32(_newProductId);\n require(newProductId == _newProductId, \"productId overflow\");\n\n emit LoanProductAdded(newProductId);\n }\n\n function setLoanProductActiveState(uint32 productId, bool newState)\n external restrict (\"StabilityBoard\") {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n products[productId].isActive = newState;\n emit LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint32 productId) external payable {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n LoanProduct storage product = products[productId];\n require(product.isActive, \"product must be in active state\"); // valid product\n\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000);\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, repaymentAmount);\n\n require(loanAmount >= product.minDisbursedAmount, \"loanAmount must be >= minDisbursedAmount\");\n\n uint expiration = now.add(product.term);\n uint40 maturity = uint40(expiration);\n require(maturity == expiration, \"maturity overflow\");\n\n // Create new loan\n uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender,\n productId, LoanState.Open, maturity)) - 1;\n\n // Store ref to new loan\n accountLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n emit NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity);\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n\n _repayLoan(loanId, repaymentAmount);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n uint totalDefaultingFee;\n for (uint i = 0; i < loanIds.length; i++) {\n require(loanIds[i] < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanIds[i]];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(now >= loan.maturity, \"current time must be later than maturity\");\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount);\n\n loan.state = LoanState.Collected;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(),\n loan.repaymentAmount).add(defaultingFee);\n\n uint releasedCollateral;\n if (targetCollection < loan.collateralAmount) {\n releasedCollateral = loan.collateralAmount.sub(targetCollection);\n loan.borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral);\n if (defaultingFee >= collateralToCollect) {\n defaultingFee = collateralToCollect;\n collateralToCollect = 0;\n } else {\n collateralToCollect = collateralToCollect.sub(defaultingFee);\n }\n totalDefaultingFee = totalDefaultingFee.add(defaultingFee);\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee),\n releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect);\n }\n\n if (totalDefaultingFee > 0) {\n address(augmintToken.feeAccount()).transfer(totalDefaultingFee);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n /* to allow upgrade of Rates and MonetarySupervisor contracts */\n function setSystemContracts(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n monetarySupervisor = newMonetarySupervisor;\n emit SystemContractsChanged(newRatesContract, newMonetarySupervisor);\n }\n\n function getProductCount() external view returns (uint) {\n return products.length;\n }\n\n // returns loan products starting from some :\n // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ]\n function getProducts(uint offset, uint16 chunkSize)\n external view returns (uint[8][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), products.length);\n uint[8][] memory response = new uint[8][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n LoanProduct storage product = products[i];\n response[i - offset] = [i, product.minDisbursedAmount, product.term, product.discountRate,\n product.collateralRatio, product.defaultingFeePt,\n monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function getLoanCount() external view returns (uint) {\n return loans.length;\n }\n\n /* returns loans starting from some . Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId,\n state, maturity, disbursementTime, loanAmount, interestAmount] */\n function getLoans(uint offset, uint16 chunkSize)\n external view returns (uint[10][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), loans.length);\n uint[10][] memory response = new uint[10][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n response[i - offset] = getLoanTuple(i);\n }\n return response;\n }\n\n function getLoanCountForAddress(address borrower) external view returns (uint) {\n return accountLoans[borrower].length;\n }\n\n /* returns loans of a given account, starting from some . Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoansForAddress(address borrower, uint offset, uint16 chunkSize)\n external view returns (uint[10][]) {\n uint[] storage loansForAddress = accountLoans[borrower];\n uint limit = SafeMath.min(offset.add(chunkSize), loansForAddress.length);\n uint[10][] memory response = new uint[10][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n response[i - offset] = getLoanTuple(loansForAddress[i]);\n }\n return response;\n }\n\n function getLoanTuple(uint loanId) public view returns (uint[10] result) {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n uint disbursementTime = loan.maturity - product.term;\n\n LoanState loanState =\n loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state;\n\n result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower),\n loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount];\n }\n\n function calculateLoanValues(LoanProduct storage product, uint repaymentAmount)\n internal view returns (uint loanAmount, uint interestAmount) {\n // calculate loan values based on repayment amount\n loanAmount = repaymentAmount.mul(product.discountRate).div(1000000);\n interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(repaymentAmount == loan.repaymentAmount, \"repaymentAmount must be equal to tokens sent\");\n require(now <= loan.maturity, \"current time must be earlier than maturity\");\n\n LoanProduct storage product = products[loan.productId];\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n\n loans[loanId].state = LoanState.Repaid;\n\n if (interestAmount > 0) {\n augmintToken.transfer(monetarySupervisor.interestEarnedAccount(), interestAmount);\n augmintToken.burn(loanAmount);\n } else {\n // negative or zero interest (i.e. discountRate >= 0)\n augmintToken.burn(repaymentAmount);\n }\n\n monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs\n\n loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral\n\n emit LoanRepayed(loanId, loan.borrower);\n }\n}\n" }, - "0x3b5dd323534659655eeccc642c3e338aabd0b219": { - "generatedAt": "2018-06-10T08:34:44.944Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:26.250Z", - "deployTransactionHash": "0xca9aa185ff4803bbc3834dfdaee4bc48047f90af90b7f12834615f8e90aeaaf1", + "0x3792c5a5077dacfe331b81837ef73bc0ea721d90": { + "generatedAt": "2018-10-29T15:52:43.304Z", + "truffleContractFileUpdatedAt": "2018-10-19T15:49:10.833Z", + "deployTransactionHash": "0x5539b5879aacf2739d48f457fcd22a70d74d12af2512a7770ab3d9558cc587d7", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "023cda0e36eef3289f062fda7d3b3d1a", - "deployedBytecodeHash": "1b89d6141a07f61e07790d5f4d97df58", - "sourceHash": "184d41cf8c8c034dc64e026f5d33bc3c", - "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - make collect() run as long as gas provided allows\n*/\npragma solidity 0.4.24;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted {\n using SafeMath for uint256;\n\n uint16 public constant CHUNK_SIZE = 100;\n\n enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate\n\n struct LoanProduct {\n uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals\n uint32 term; // 1\n uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1%\n uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */\n struct LoanData {\n uint collateralAmount; // 0\n uint repaymentAmount; // 1\n address borrower; // 2\n uint32 productId; // 3\n LoanState state; // 4\n uint40 maturity; // 5\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n\n event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount, uint40 maturity);\n\n event LoanProductActiveStateChanged(uint32 productId, bool newState);\n\n event LoanProductAdded(uint32 productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n event SystemContractsChanged(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n }\n\n function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount,\n uint32 defaultingFeePt, bool isActive)\n external restrict(\"StabilityBoard\") {\n\n uint _newProductId = products.push(\n LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive)\n ) - 1;\n\n uint32 newProductId = uint32(_newProductId);\n require(newProductId == _newProductId, \"productId overflow\");\n\n emit LoanProductAdded(newProductId);\n }\n\n function setLoanProductActiveState(uint32 productId, bool newState)\n external restrict (\"StabilityBoard\") {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n products[productId].isActive = false;\n emit LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint32 productId) external payable {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n LoanProduct storage product = products[productId];\n require(product.isActive, \"product must be in active state\"); // valid product\n\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000);\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, repaymentAmount);\n\n require(loanAmount >= product.minDisbursedAmount, \"loanAmount must be >= minDisbursedAmount\");\n\n uint expiration = now.add(product.term);\n uint40 maturity = uint40(expiration);\n require(maturity == expiration, \"maturity overflow\");\n\n // Create new loan\n uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender,\n productId, LoanState.Open, maturity)) - 1;\n\n // Store ref to new loan\n accountLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n emit NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity);\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n\n _repayLoan(loanId, repaymentAmount);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n uint totalDefaultingFee;\n for (uint i = 0; i < loanIds.length; i++) {\n require(i < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanIds[i]];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(now >= loan.maturity, \"current time must be later than maturity\");\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount);\n\n loan.state = LoanState.Collected;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(),\n loan.repaymentAmount).add(defaultingFee);\n\n uint releasedCollateral;\n if (targetCollection < loan.collateralAmount) {\n releasedCollateral = loan.collateralAmount.sub(targetCollection);\n loan.borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral);\n if (defaultingFee >= collateralToCollect) {\n defaultingFee = collateralToCollect;\n collateralToCollect = 0;\n } else {\n collateralToCollect = collateralToCollect.sub(defaultingFee);\n }\n totalDefaultingFee = totalDefaultingFee.add(defaultingFee);\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee), releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect);\n }\n\n if (totalDefaultingFee > 0){\n address(augmintToken.feeAccount()).transfer(totalDefaultingFee);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n /* to allow upgrade of Rates and MonetarySupervisor contracts */\n function setSystemContracts(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n monetarySupervisor = newMonetarySupervisor;\n emit SystemContractsChanged(newRatesContract, newMonetarySupervisor);\n }\n\n function getProductCount() external view returns (uint ct) {\n return products.length;\n }\n\n // returns CHUNK_SIZE loan products starting from some offset:\n // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ]\n function getProducts(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= products.length) { break; }\n\n LoanProduct storage product = products[offset + i];\n\n response[i] = [offset + i, product.minDisbursedAmount, product.term, product.discountRate,\n product.collateralRatio, product.defaultingFeePt,\n monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ];\n }\n }\n\n function getLoanCount() external view returns (uint ct) {\n return loans.length;\n }\n\n /* returns CHUNK_SIZE loans starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoans(uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loans.length) { break; }\n\n response[i] = getLoanTuple(offset + i);\n }\n }\n\n function getLoanCountForAddress(address borrower) external view returns (uint) {\n return accountLoans[borrower].length;\n }\n\n /* returns CHUNK_SIZE loans of a given account, starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoansForAddress(address borrower, uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n uint[] storage loansForAddress = accountLoans[borrower];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loansForAddress.length) { break; }\n\n response[i] = getLoanTuple(loansForAddress[offset + i]);\n }\n }\n\n function getLoanTuple(uint loanId) public view returns (uint[10] result) {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n uint disbursementTime = loan.maturity - product.term;\n\n LoanState loanState =\n loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state;\n\n result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower),\n loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount];\n }\n\n function calculateLoanValues(LoanProduct storage product, uint repaymentAmount)\n internal view returns (uint loanAmount, uint interestAmount) {\n // calculate loan values based on repayment amount\n loanAmount = repaymentAmount.mul(product.discountRate).div(1000000);\n interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(repaymentAmount == loan.repaymentAmount, \"repaymentAmount must be equal to tokens sent\");\n require(now <= loan.maturity, \"current time must be earlier than maturity\");\n\n LoanProduct storage product = products[loan.productId];\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n\n loans[loanId].state = LoanState.Repaid;\n\n if (interestAmount > 0) {\n augmintToken.transfer(monetarySupervisor.interestEarnedAccount(), interestAmount);\n augmintToken.burn(loanAmount);\n } else {\n // negative or zero interest (i.e. discountRate >= 0)\n augmintToken.burn(repaymentAmount);\n }\n\n monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs\n\n loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral\n\n emit LoanRepayed(loanId, loan.borrower);\n }\n\n}\n" + "bytecodeHash": "591f565c201032e0df4b9f7798e7ec85", + "deployedBytecodeHash": "e93edcccad1eb8f9142f6c257bb23bdd", + "sourceHash": "234fd5848af85ca2444c888fd6ba61aa", + "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - make collect() run as long as gas provided allows\n*/\npragma solidity 0.4.24;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted, TokenReceiver {\n using SafeMath for uint256;\n\n enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate\n\n struct LoanProduct {\n uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals\n uint32 term; // 1\n uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1%\n uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */\n struct LoanData {\n uint collateralAmount; // 0\n uint repaymentAmount; // 1\n address borrower; // 2\n uint32 productId; // 3\n LoanState state; // 4\n uint40 maturity; // 5\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n\n event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount, uint40 maturity);\n\n event LoanProductActiveStateChanged(uint32 productId, bool newState);\n\n event LoanProductAdded(uint32 productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n event SystemContractsChanged(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n }\n\n function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount,\n uint32 defaultingFeePt, bool isActive)\n external restrict(\"StabilityBoard\") {\n\n uint _newProductId = products.push(\n LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive)\n ) - 1;\n\n uint32 newProductId = uint32(_newProductId);\n require(newProductId == _newProductId, \"productId overflow\");\n\n emit LoanProductAdded(newProductId);\n }\n\n function setLoanProductActiveState(uint32 productId, bool newState)\n external restrict (\"StabilityBoard\") {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n products[productId].isActive = newState;\n emit LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint32 productId) external payable {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n LoanProduct storage product = products[productId];\n require(product.isActive, \"product must be in active state\"); // valid product\n\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000);\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, repaymentAmount);\n\n require(loanAmount >= product.minDisbursedAmount, \"loanAmount must be >= minDisbursedAmount\");\n\n uint expiration = now.add(product.term);\n uint40 maturity = uint40(expiration);\n require(maturity == expiration, \"maturity overflow\");\n\n // Create new loan\n uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender,\n productId, LoanState.Open, maturity)) - 1;\n\n // Store ref to new loan\n accountLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n emit NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity);\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n\n _repayLoan(loanId, repaymentAmount);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n uint totalDefaultingFee;\n for (uint i = 0; i < loanIds.length; i++) {\n require(loanIds[i] < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanIds[i]];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(now >= loan.maturity, \"current time must be later than maturity\");\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount);\n\n loan.state = LoanState.Collected;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(),\n loan.repaymentAmount).add(defaultingFee);\n\n uint releasedCollateral;\n if (targetCollection < loan.collateralAmount) {\n releasedCollateral = loan.collateralAmount.sub(targetCollection);\n loan.borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral);\n if (defaultingFee >= collateralToCollect) {\n defaultingFee = collateralToCollect;\n collateralToCollect = 0;\n } else {\n collateralToCollect = collateralToCollect.sub(defaultingFee);\n }\n totalDefaultingFee = totalDefaultingFee.add(defaultingFee);\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee),\n releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect);\n }\n\n if (totalDefaultingFee > 0) {\n address(augmintToken.feeAccount()).transfer(totalDefaultingFee);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n /* to allow upgrade of Rates and MonetarySupervisor contracts */\n function setSystemContracts(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n monetarySupervisor = newMonetarySupervisor;\n emit SystemContractsChanged(newRatesContract, newMonetarySupervisor);\n }\n\n function getProductCount() external view returns (uint) {\n return products.length;\n }\n\n // returns loan products starting from some :\n // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ]\n function getProducts(uint offset, uint16 chunkSize)\n external view returns (uint[8][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), products.length);\n uint[8][] memory response = new uint[8][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n LoanProduct storage product = products[i];\n response[i - offset] = [i, product.minDisbursedAmount, product.term, product.discountRate,\n product.collateralRatio, product.defaultingFeePt,\n monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function getLoanCount() external view returns (uint) {\n return loans.length;\n }\n\n /* returns loans starting from some . Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId,\n state, maturity, disbursementTime, loanAmount, interestAmount] */\n function getLoans(uint offset, uint16 chunkSize)\n external view returns (uint[10][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), loans.length);\n uint[10][] memory response = new uint[10][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n response[i - offset] = getLoanTuple(i);\n }\n return response;\n }\n\n function getLoanCountForAddress(address borrower) external view returns (uint) {\n return accountLoans[borrower].length;\n }\n\n /* returns loans of a given account, starting from some . Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoansForAddress(address borrower, uint offset, uint16 chunkSize)\n external view returns (uint[10][]) {\n uint[] storage loansForAddress = accountLoans[borrower];\n uint limit = SafeMath.min(offset.add(chunkSize), loansForAddress.length);\n uint[10][] memory response = new uint[10][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n response[i - offset] = getLoanTuple(loansForAddress[i]);\n }\n return response;\n }\n\n function getLoanTuple(uint loanId) public view returns (uint[10] result) {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n uint disbursementTime = loan.maturity - product.term;\n\n LoanState loanState =\n loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state;\n\n result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower),\n loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount];\n }\n\n function calculateLoanValues(LoanProduct storage product, uint repaymentAmount)\n internal view returns (uint loanAmount, uint interestAmount) {\n // calculate loan values based on repayment amount\n loanAmount = repaymentAmount.mul(product.discountRate).div(1000000);\n interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(repaymentAmount == loan.repaymentAmount, \"repaymentAmount must be equal to tokens sent\");\n require(now <= loan.maturity, \"current time must be earlier than maturity\");\n\n LoanProduct storage product = products[loan.productId];\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n\n loans[loanId].state = LoanState.Repaid;\n\n if (interestAmount > 0) {\n augmintToken.transfer(monetarySupervisor.interestEarnedAccount(), interestAmount);\n augmintToken.burn(loanAmount);\n } else {\n // negative or zero interest (i.e. discountRate >= 0)\n augmintToken.burn(repaymentAmount);\n }\n\n monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs\n\n loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral\n\n emit LoanRepayed(loanId, loan.borrower);\n }\n}\n" } } } diff --git a/abiniser/deployments/4/Locker_DEPLOYS.json b/abiniser/deployments/4/Locker_DEPLOYS.json index ac8d6371..8ecd4747 100644 --- a/abiniser/deployments/4/Locker_DEPLOYS.json +++ b/abiniser/deployments/4/Locker_DEPLOYS.json @@ -1,113 +1,35 @@ { "contractName": "Locker", - "latestAbiHash": "619ff7809b73aead28176fe6317953c3", + "latestAbiHash": "f59526398823aef0f0c1454d0b6b4eac", "deployedAbis": { - "6055e2cba8c8e9cb7e04b10e4c56ab9a": { - "latestDeployedAddress": "0x617cf9ba5c9cbecdd66412bc1d073b002aa26426", + "f59526398823aef0f0c1454d0b6b4eac": { + "latestDeployedAddress": "0xc0b97fe5cad0d43d0c974c4e9a00312dc661f8ab", "deployments": { - "0x617cf9ba5c9cbecdd66412bc1d073b002aa26426": { - "generatedAt": "2018-04-25T12:29:07.651Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:29:32.229Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "66f7b66ff12fcb40830b0b95777fb852", - "deployedBytecodeHash": "75adc582771c489bbe9ef06428e8e6cf", - "sourceHash": "1135716bfcd72d7542f37f36acc8673e", - "source": "/* contract for tracking locked funds etc.\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO:\n - create MonetarySupervisorInterface and use it instead of MonetarySupervisor\n - monetarySupervisor setter?\n - store locks in array so we can iterate over them\n\n to do/think about:\n -> self-destruct function?\n -> return only active loan products from getLoanProducts?\n*/\n\npragma solidity 0.4.19;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n event NewLockProduct(uint indexed lockProductId, uint perTermInterest, uint durationInSecs,\n uint minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint indexed lockIndex, uint amountLocked, uint interestEarned,\n uint lockedUntil, uint perTermInterest, uint durationInSecs, bool isActive);\n\n event LockReleased(address indexed lockOwner, uint indexed lockIndex);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint perTermInterest;\n uint durationInSecs;\n uint minimumLockAmount;\n bool isActive;\n }\n\n struct Lock {\n uint amountLocked;\n uint interestEarned;\n uint lockedUntil;\n uint perTermInterest;\n uint durationInSecs;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n // per account locks (i.e. an id for a lock is a tuple (owner, index)):\n mapping(address => Lock[]) public locks;\n\n function Locker(AugmintTokenInterface _augmintToken, MonetarySupervisor _monetarySupervisor) public {\n\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint perTermInterest, uint durationInSecs, uint minimumLockAmount, bool isActive)\n external restrict(\"MonetaryBoard\") {\n\n uint newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n\n }\n\n function setLockProductActiveState(uint lockProductId, bool isActive) external restrict(\"MonetaryBoard\") {\n\n require(lockProductId < lockProducts.length);\n lockProducts[lockProductId].isActive = isActive;\n LockProductActiveChange(lockProductId, isActive);\n\n }\n\n function releaseFunds(address lockOwner, uint lockIndex) external {\n\n Lock storage lock = locks[lockOwner][lockIndex];\n\n require(lock.isActive && now >= lock.lockedUntil);\n\n lock.isActive = false;\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lockOwner, lock.amountLocked.add(lock.interestEarned),\n \"Funds released from lock\");\n\n LockReleased(lockOwner, lockIndex);\n }\n\n function getLockProductCount() external view returns (uint) {\n\n return lockProducts.length;\n\n }\n\n // returns 20 lock products starting from some offset\n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, isActive ]\n function getLockProducts(uint offset) external view returns (uint[4][20]) {\n\n uint[4][20] memory response;\n\n for (uint8 i = 0; i < 20; i++) {\n\n if (offset + i >= lockProducts.length) { break; }\n\n LockProduct storage lockProduct = lockProducts[offset + i];\n\n response[i] = [ lockProduct.perTermInterest, lockProduct.durationInSecs,\n lockProduct.minimumLockAmount, lockProduct.isActive ? 1 : 0 ];\n\n }\n\n return response;\n\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n\n return locks[lockOwner].length;\n\n }\n\n // returns 20 locks starting from some offset\n // lock products are encoded as\n // [amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocksForAddress(address lockOwner, uint offset) external view returns (uint[6][20]) {\n\n Lock[] storage locksForAddress = locks[lockOwner];\n uint[6][20] memory response;\n\n for (uint8 i = 0; i < 20; i++) {\n\n if (offset + i >= locksForAddress.length) { break; }\n\n Lock storage lock = locksForAddress[offset + i];\n\n response[i] = [ lock.amountLocked, lock.interestEarned, lock.lockedUntil, lock.perTermInterest,\n lock.durationInSecs, lock.isActive ? 1 : 0 ];\n\n }\n\n return response;\n\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint lockProductId) public {\n require(msg.sender == address(augmintToken));\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function calculateInterestForLockProduct(uint lockProductId, uint amountToLock) public view returns (uint) {\n\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive);\n require(amountToLock >= lockProduct.minimumLockAmount);\n\n uint interestEarned = amountToLock.mul(lockProduct.perTermInterest).div(1000000);\n\n return interestEarned;\n\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint lockProductId, address lockOwner, uint amountToLock) internal returns (uint) {\n\n // NB: calculateInterestForLockProduct will validate the lock product and amountToLock:\n uint interestEarned = calculateInterestForLockProduct(lockProductId, amountToLock);\n\n LockProduct storage lockProduct = lockProducts[lockProductId];\n\n uint lockedUntil = now.add(lockProduct.durationInSecs);\n uint lockIndex = locks[lockOwner].push(Lock(amountToLock, interestEarned, lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, true)) - 1;\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n NewLock(lockOwner, lockIndex, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs, true);\n\n return interestEarned;\n }\n\n}\n" - } - } - }, - "c95c1ab8f11cd983deebbe203f4d49be": { - "latestDeployedAddress": "0xfb6b4803c590e564a3e6810289ab638b353a1367", - "deployments": { - "0xfb6b4803c590e564a3e6810289ab638b353a1367": { - "generatedAt": "2018-04-25T12:30:49.440Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:36:28.125Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "1ee8107823c445557e111187d4dc2fe1", - "deployedBytecodeHash": "a90b815047f5c6925b959452739394ee", - "sourceHash": "d32907ca14fc212ac860efcefb66c83b", - "source": "/* contract for tracking locked funds etc.\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n - monetarySupervisor setter?\n\n to do/think about:\n -> self-destruct function?\n -> return only active loan products from getLoanProducts?\n*/\n\npragma solidity 0.4.19;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n uint public constant CHUNK_SIZE = 100;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs, bool isActive);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n function Locker(AugmintTokenInterface _augmintToken, MonetarySupervisor _monetarySupervisor) public {\n\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"MonetaryBoard\") {\n\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId);\n NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"MonetaryBoard\") {\n\n require(lockProductId < lockProducts.length);\n lockProducts[lockProductId].isActive = isActive;\n LockProductActiveChange(lockProductId, isActive);\n\n }\n\n function releaseFunds(uint lockId) external {\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive);\n require(now >= lock.lockedUntil);\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n LockReleased(lock.owner, lockId);\n }\n\n function getLockProductCount() external view returns (uint) {\n\n return lockProducts.length;\n\n }\n\n // returns 20 lock products starting from some offset\n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, isActive ]\n function getLockProducts(uint offset) external view returns (uint32[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= lockProducts.length) { break; }\n\n LockProduct storage lockProduct = lockProducts[offset + i];\n\n response[i] = [ lockProduct.perTermInterest, lockProduct.durationInSecs,\n lockProduct.minimumLockAmount, lockProduct.isActive ? 1 : 0 ];\n }\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns CHUNK_SIZE locks starting from some offset\n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locks.length) { break; }\n\n Lock storage lock = locks[offset + i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [uint(offset + i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n }\n\n // returns CHUNK_SIZE locks of a given account, starting from some offset\n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset) external view returns (uint[7][CHUNK_SIZE] response) {\n\n uint[] storage locksForAddress = accountLocks[lockOwner];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locksForAddress.length) { break; }\n\n Lock storage lock = locks[locksForAddress[offset + i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [ locksForAddress[offset + i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) public {\n require(msg.sender == address(augmintToken));\n uint32 lockProductId = uint32(_lockProductId);\n require(lockProductId == _lockProductId);\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).div(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal returns(uint lockId) {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive);\n require(amountToLock >= lockProduct.minimumLockAmount);\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration);\n\n lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs, true);\n }\n\n}\n" - } - } - }, - "66e3e89133d9bbd91baac5552f21f7e1": { - "latestDeployedAddress": "0xd0b6136c2e35c288a903e836feb9535954e4a9e9", - "deployments": { - "0xf98ae1fb568b267a7632bf54579a153c892e2ec2": { - "generatedAt": "2018-04-25T12:31:29.231Z", - "truffleContractFileUpdatedAt": "2018-04-20T18:26:53.654Z", - "deployTransactionHash": "0xc0f6ada52d0aeb577cfd3dce20af95d8c502c93aa2cebf2c7d63b3c86a4ef1b2", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "bb63b112ad6275c447016bf46e7e2dad", - "deployedBytecodeHash": "c88454f70e3cc7b363b425ef66ef47ca", - "sourceHash": "7ffe14f90465530802dc1f5762e0217f", - "source": "/* contract for tracking locked funds\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n -> self-destruct function?\n\n*/\n\npragma solidity ^0.4.23;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n uint public constant CHUNK_SIZE = 100;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n event MonetarySupervisorChanged(MonetarySupervisor newMonetarySupervisor);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n constructor(AugmintTokenInterface _augmintToken, MonetarySupervisor _monetarySupervisor) public {\n\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"MonetaryBoard\") {\n\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId, \"lockProduct overflow\");\n emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"MonetaryBoard\") {\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n\n lockProducts[lockProductId].isActive = isActive;\n emit LockProductActiveChange(lockProductId, isActive);\n\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n uint32 lockProductId = uint32(_lockProductId);\n require(lockProductId == _lockProductId, \"lockProductId overflow\");\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function releaseFunds(uint lockId) external {\n // next line would revert but require to emit reason:\n require(lockId < locks.length, \"invalid lockId\");\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive, \"lock must be in active state\");\n require(now >= lock.lockedUntil, \"current time must be later than lockedUntil\");\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n emit LockReleased(lock.owner, lockId);\n }\n\n function setMonetarySupervisor(MonetarySupervisor newMonetarySupervisor) external restrict(\"MonetaryBoard\") {\n monetarySupervisor = newMonetarySupervisor;\n emit MonetarySupervisorChanged(newMonetarySupervisor);\n }\n\n function getLockProductCount() external view returns (uint) {\n\n return lockProducts.length;\n\n }\n\n // returns 20 lock products starting from some offset\n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ]\n function getLockProducts(uint offset) external view returns (uint[5][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= lockProducts.length) { break; }\n\n LockProduct storage lockProduct = lockProducts[offset + i];\n\n response[i] = [ lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount,\n monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest),\n lockProduct.isActive ? 1 : 0 ];\n }\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns CHUNK_SIZE locks starting from some offset\n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locks.length) { break; }\n\n Lock storage lock = locks[offset + i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [uint(offset + i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n }\n\n // returns CHUNK_SIZE locks of a given account, starting from some offset\n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset) external view returns (uint[7][CHUNK_SIZE] response) {\n\n uint[] storage locksForAddress = accountLocks[lockOwner];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locksForAddress.length) { break; }\n\n Lock storage lock = locks[locksForAddress[offset + i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [ locksForAddress[offset + i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).div(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal returns(uint lockId) {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive, \"lockProduct must be in active state\");\n require(amountToLock >= lockProduct.minimumLockAmount, \"amountToLock must be >= minimumLockAmount\");\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration, \"lockedUntil overflow\");\n\n lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs);\n }\n\n}\n" - }, - "0xd0b6136c2e35c288a903e836feb9535954e4a9e9": { - "generatedAt": "2018-05-12T01:34:38.533Z", - "truffleContractFileUpdatedAt": "2018-05-12T01:30:50.619Z", - "deployTransactionHash": "0x827346689bfd341aaa1020c44d18f77943fd67afe095aa0a2c2eefe809e78a22", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "c6c9a4350153bfd4b81eaf228df169f4", - "deployedBytecodeHash": "878366e51dfa79329645837646563469", - "sourceHash": "7ffe14f90465530802dc1f5762e0217f", - "source": "/* contract for tracking locked funds\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n -> self-destruct function?\n\n*/\n\npragma solidity ^0.4.23;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n uint public constant CHUNK_SIZE = 100;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n event MonetarySupervisorChanged(MonetarySupervisor newMonetarySupervisor);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n constructor(AugmintTokenInterface _augmintToken, MonetarySupervisor _monetarySupervisor) public {\n\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"MonetaryBoard\") {\n\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId, \"lockProduct overflow\");\n emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"MonetaryBoard\") {\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n\n lockProducts[lockProductId].isActive = isActive;\n emit LockProductActiveChange(lockProductId, isActive);\n\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n uint32 lockProductId = uint32(_lockProductId);\n require(lockProductId == _lockProductId, \"lockProductId overflow\");\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function releaseFunds(uint lockId) external {\n // next line would revert but require to emit reason:\n require(lockId < locks.length, \"invalid lockId\");\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive, \"lock must be in active state\");\n require(now >= lock.lockedUntil, \"current time must be later than lockedUntil\");\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n emit LockReleased(lock.owner, lockId);\n }\n\n function setMonetarySupervisor(MonetarySupervisor newMonetarySupervisor) external restrict(\"MonetaryBoard\") {\n monetarySupervisor = newMonetarySupervisor;\n emit MonetarySupervisorChanged(newMonetarySupervisor);\n }\n\n function getLockProductCount() external view returns (uint) {\n\n return lockProducts.length;\n\n }\n\n // returns 20 lock products starting from some offset\n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ]\n function getLockProducts(uint offset) external view returns (uint[5][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= lockProducts.length) { break; }\n\n LockProduct storage lockProduct = lockProducts[offset + i];\n\n response[i] = [ lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount,\n monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest),\n lockProduct.isActive ? 1 : 0 ];\n }\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns CHUNK_SIZE locks starting from some offset\n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locks.length) { break; }\n\n Lock storage lock = locks[offset + i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [uint(offset + i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n }\n\n // returns CHUNK_SIZE locks of a given account, starting from some offset\n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset) external view returns (uint[7][CHUNK_SIZE] response) {\n\n uint[] storage locksForAddress = accountLocks[lockOwner];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locksForAddress.length) { break; }\n\n Lock storage lock = locks[locksForAddress[offset + i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [ locksForAddress[offset + i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).div(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal returns(uint lockId) {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive, \"lockProduct must be in active state\");\n require(amountToLock >= lockProduct.minimumLockAmount, \"amountToLock must be >= minimumLockAmount\");\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration, \"lockedUntil overflow\");\n\n lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs);\n }\n\n}\n" - } - } - }, - "619ff7809b73aead28176fe6317953c3": { - "latestDeployedAddress": "0xf74c0cb2713214808553cda5c78f92219478863d", - "deployments": { - "0xd3b0d67b30aaf25b5d644df6e8c520b263d3de5b": { - "generatedAt": "2018-06-04T12:49:52.663Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.516Z", - "deployTransactionHash": "0xb4704277ecb75d589191db9593f91a35d3f4f613f1335898e25570d1b345b7f2", - "compiler": { - "name": "solc", - "version": "0.4.24+commit.e67f0147.Emscripten.clang" - }, - "bytecodeHash": "35bfe6d3967590358bfbaec58a8d0b9d", - "deployedBytecodeHash": "91eaf7e42a041ad183952ad5005f63e4", - "sourceHash": "34eafae9de21ece30724243c8e975d86", - "source": "/* contract for tracking locked funds\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n -> self-destruct function?\n\n*/\n\npragma solidity 0.4.24;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n uint public constant CHUNK_SIZE = 100;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n event MonetarySupervisorChanged(MonetarySupervisor newMonetarySupervisor);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"StabilityBoardSignerContract\") {\n\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId, \"lockProduct overflow\");\n emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"StabilityBoardSignerContract\") {\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n\n lockProducts[lockProductId].isActive = isActive;\n emit LockProductActiveChange(lockProductId, isActive);\n\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n uint32 lockProductId = uint32(_lockProductId);\n require(lockProductId == _lockProductId, \"lockProductId overflow\");\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function releaseFunds(uint lockId) external {\n // next line would revert but require to emit reason:\n require(lockId < locks.length, \"invalid lockId\");\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive, \"lock must be in active state\");\n require(now >= lock.lockedUntil, \"current time must be later than lockedUntil\");\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n emit LockReleased(lock.owner, lockId);\n }\n\n function setMonetarySupervisor(MonetarySupervisor newMonetarySupervisor) external restrict(\"StabilityBoardSignerContract\") {\n monetarySupervisor = newMonetarySupervisor;\n emit MonetarySupervisorChanged(newMonetarySupervisor);\n }\n\n function getLockProductCount() external view returns (uint) {\n\n return lockProducts.length;\n\n }\n\n // returns 20 lock products starting from some offset\n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ]\n function getLockProducts(uint offset) external view returns (uint[5][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= lockProducts.length) { break; }\n\n LockProduct storage lockProduct = lockProducts[offset + i];\n\n response[i] = [ lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount,\n monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest),\n lockProduct.isActive ? 1 : 0 ];\n }\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns CHUNK_SIZE locks starting from some offset\n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locks.length) { break; }\n\n Lock storage lock = locks[offset + i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [uint(offset + i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n }\n\n // returns CHUNK_SIZE locks of a given account, starting from some offset\n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset) external view returns (uint[7][CHUNK_SIZE] response) {\n\n uint[] storage locksForAddress = accountLocks[lockOwner];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locksForAddress.length) { break; }\n\n Lock storage lock = locks[locksForAddress[offset + i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [ locksForAddress[offset + i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).div(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal returns(uint lockId) {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive, \"lockProduct must be in active state\");\n require(amountToLock >= lockProduct.minimumLockAmount, \"amountToLock must be >= minimumLockAmount\");\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration, \"lockedUntil overflow\");\n\n lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs);\n }\n\n}\n" - }, - "0x5b94aaf241e8039ed6d3608760ae9fa7186767d7": { - "generatedAt": "2018-06-10T08:34:44.976Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:26.200Z", - "deployTransactionHash": "0x8322da3562ce7b9bc8f6a67318926f53a99631efcc71fd5b772ff780a7022a19", + "0x6d84ab6c385b827e58c358d078ac7b1c61b68821": { + "generatedAt": "2018-10-18T13:35:02.423Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.960Z", + "deployTransactionHash": "0x2d7780b0e0947b2b96a2d3d14bdcec5d6045d619cdd8a94dccfc43e0b36c287a", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "7b257e4c44f08fec5d6d5d2f9b09545b", - "deployedBytecodeHash": "0cfd713f37d912355afd61f1f1f95aaa", - "sourceHash": "786e07d17116d302210e391b40adc6ef", - "source": "/* contract for tracking locked funds\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n -> self-destruct function?\n\n*/\n\npragma solidity 0.4.24;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n uint public constant CHUNK_SIZE = 100;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n event MonetarySupervisorChanged(MonetarySupervisor newMonetarySupervisor);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"StabilityBoard\") {\n\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId, \"lockProduct overflow\");\n emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"StabilityBoard\") {\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n\n lockProducts[lockProductId].isActive = isActive;\n emit LockProductActiveChange(lockProductId, isActive);\n\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n uint32 lockProductId = uint32(_lockProductId);\n require(lockProductId == _lockProductId, \"lockProductId overflow\");\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function releaseFunds(uint lockId) external {\n // next line would revert but require to emit reason:\n require(lockId < locks.length, \"invalid lockId\");\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive, \"lock must be in active state\");\n require(now >= lock.lockedUntil, \"current time must be later than lockedUntil\");\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n emit LockReleased(lock.owner, lockId);\n }\n\n function setMonetarySupervisor(MonetarySupervisor newMonetarySupervisor) external restrict(\"StabilityBoard\") {\n monetarySupervisor = newMonetarySupervisor;\n emit MonetarySupervisorChanged(newMonetarySupervisor);\n }\n\n function getLockProductCount() external view returns (uint) {\n\n return lockProducts.length;\n\n }\n\n // returns 20 lock products starting from some offset\n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ]\n function getLockProducts(uint offset) external view returns (uint[5][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= lockProducts.length) { break; }\n\n LockProduct storage lockProduct = lockProducts[offset + i];\n\n response[i] = [ lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount,\n monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest),\n lockProduct.isActive ? 1 : 0 ];\n }\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns CHUNK_SIZE locks starting from some offset\n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locks.length) { break; }\n\n Lock storage lock = locks[offset + i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [uint(offset + i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n }\n\n // returns CHUNK_SIZE locks of a given account, starting from some offset\n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset) external view returns (uint[7][CHUNK_SIZE] response) {\n\n uint[] storage locksForAddress = accountLocks[lockOwner];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locksForAddress.length) { break; }\n\n Lock storage lock = locks[locksForAddress[offset + i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [ locksForAddress[offset + i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).div(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal returns(uint lockId) {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive, \"lockProduct must be in active state\");\n require(amountToLock >= lockProduct.minimumLockAmount, \"amountToLock must be >= minimumLockAmount\");\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration, \"lockedUntil overflow\");\n\n lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs);\n }\n\n}\n" + "bytecodeHash": "0fe102ad0cf754658fdb075cb2850270", + "deployedBytecodeHash": "211e0b56eb9155bf091df2937a90551d", + "sourceHash": "5fb19771489eecebfa02e95214887146", + "source": "/* contract for tracking locked funds\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n -> self-destruct function?\n\n*/\n\npragma solidity 0.4.24;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n event MonetarySupervisorChanged(MonetarySupervisor newMonetarySupervisor);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"StabilityBoard\") {\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId, \"lockProduct overflow\");\n emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"StabilityBoard\") {\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n\n lockProducts[lockProductId].isActive = isActive;\n emit LockProductActiveChange(lockProductId, isActive);\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n // next line would revert but require to emit reason:\n require(_lockProductId < lockProducts.length, \"invalid lockProductId\");\n uint32 lockProductId = uint32(_lockProductId);\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function releaseFunds(uint lockId) external {\n // next line would revert but require to emit reason:\n require(lockId < locks.length, \"invalid lockId\");\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive, \"lock must be in active state\");\n require(now >= lock.lockedUntil, \"current time must be later than lockedUntil\");\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n emit LockReleased(lock.owner, lockId);\n }\n\n function setMonetarySupervisor(MonetarySupervisor newMonetarySupervisor) external restrict(\"StabilityBoard\") {\n monetarySupervisor = newMonetarySupervisor;\n emit MonetarySupervisorChanged(newMonetarySupervisor);\n }\n\n function getLockProductCount() external view returns (uint) {\n return lockProducts.length;\n }\n\n // returns lock products starting from some \n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ]\n function getLockProducts(uint offset, uint16 chunkSize)\n external view returns (uint[5][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), lockProducts.length);\n uint[5][] memory response = new uint[5][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n LockProduct storage lockProduct = lockProducts[i];\n response[i - offset] = [lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount,\n monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest),\n lockProduct.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns locks starting from some \n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset, uint16 chunkSize)\n external view returns (uint[8][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), locks.length);\n uint[8][] memory response = new uint[8][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n Lock storage lock = locks[i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i - offset] = [uint(i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n return response;\n }\n\n // returns locks of a given account, starting from some \n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset, uint16 chunkSize)\n external view returns (uint[7][]) {\n uint[] storage locksForAddress = accountLocks[lockOwner];\n uint limit = SafeMath.min(offset.add(chunkSize), locksForAddress.length);\n uint[7][] memory response = new uint[7][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n Lock storage lock = locks[locksForAddress[i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i - offset] = [locksForAddress[i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).ceilDiv(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive, \"lockProduct must be in active state\");\n require(amountToLock >= lockProduct.minimumLockAmount, \"amountToLock must be >= minimumLockAmount\");\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration, \"lockedUntil overflow\");\n\n uint lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs);\n }\n}\n" }, - "0xf74c0cb2713214808553cda5c78f92219478863d": { - "generatedAt": "2018-07-04T16:14:32.212Z", - "truffleContractFileUpdatedAt": "2018-07-04T16:09:03.263Z", - "deployTransactionHash": "0xe91c9245554d777018898d909d30a66ffc448733a3e19d8ead91a7a89e29ff01", + "0xc0b97fe5cad0d43d0c974c4e9a00312dc661f8ab": { + "generatedAt": "2018-10-29T15:52:43.317Z", + "truffleContractFileUpdatedAt": "2018-10-19T15:49:10.796Z", + "deployTransactionHash": "0x597c1255ba3af1bc1b00801b54251e4dc7beebae567b927711edb78b23d41578", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "2e46de94e61fb92a9f9c617a78c630a5", - "deployedBytecodeHash": "5cf2a8e6d2fab15963890e142d3d15a3", - "sourceHash": "0bc34f96859842d6cde3876ee878a209", - "source": "/* contract for tracking locked funds\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n -> self-destruct function?\n\n*/\n\npragma solidity 0.4.24;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n uint public constant CHUNK_SIZE = 100;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n event MonetarySupervisorChanged(MonetarySupervisor newMonetarySupervisor);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"StabilityBoard\") {\n\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId, \"lockProduct overflow\");\n emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"StabilityBoard\") {\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n\n lockProducts[lockProductId].isActive = isActive;\n emit LockProductActiveChange(lockProductId, isActive);\n\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n uint32 lockProductId = uint32(_lockProductId);\n require(lockProductId == _lockProductId, \"lockProductId overflow\");\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function releaseFunds(uint lockId) external {\n // next line would revert but require to emit reason:\n require(lockId < locks.length, \"invalid lockId\");\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive, \"lock must be in active state\");\n require(now >= lock.lockedUntil, \"current time must be later than lockedUntil\");\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n emit LockReleased(lock.owner, lockId);\n }\n\n function setMonetarySupervisor(MonetarySupervisor newMonetarySupervisor) external restrict(\"StabilityBoard\") {\n monetarySupervisor = newMonetarySupervisor;\n emit MonetarySupervisorChanged(newMonetarySupervisor);\n }\n\n function getLockProductCount() external view returns (uint) {\n\n return lockProducts.length;\n\n }\n\n // returns 20 lock products starting from some offset\n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ]\n function getLockProducts(uint offset) external view returns (uint[5][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= lockProducts.length) { break; }\n\n LockProduct storage lockProduct = lockProducts[offset + i];\n\n response[i] = [ lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount,\n monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest),\n lockProduct.isActive ? 1 : 0 ];\n }\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns CHUNK_SIZE locks starting from some offset\n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locks.length) { break; }\n\n Lock storage lock = locks[offset + i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [uint(offset + i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n }\n\n // returns CHUNK_SIZE locks of a given account, starting from some offset\n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset) external view returns (uint[7][CHUNK_SIZE] response) {\n\n uint[] storage locksForAddress = accountLocks[lockOwner];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locksForAddress.length) { break; }\n\n Lock storage lock = locks[locksForAddress[offset + i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [ locksForAddress[offset + i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).ceilDiv(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal returns(uint lockId) {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive, \"lockProduct must be in active state\");\n require(amountToLock >= lockProduct.minimumLockAmount, \"amountToLock must be >= minimumLockAmount\");\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration, \"lockedUntil overflow\");\n\n lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs);\n }\n\n}\n" + "bytecodeHash": "0fe102ad0cf754658fdb075cb2850270", + "deployedBytecodeHash": "211e0b56eb9155bf091df2937a90551d", + "sourceHash": "5fb19771489eecebfa02e95214887146", + "source": "/* contract for tracking locked funds\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n -> self-destruct function?\n\n*/\n\npragma solidity 0.4.24;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n event MonetarySupervisorChanged(MonetarySupervisor newMonetarySupervisor);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"StabilityBoard\") {\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId, \"lockProduct overflow\");\n emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"StabilityBoard\") {\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n\n lockProducts[lockProductId].isActive = isActive;\n emit LockProductActiveChange(lockProductId, isActive);\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n // next line would revert but require to emit reason:\n require(_lockProductId < lockProducts.length, \"invalid lockProductId\");\n uint32 lockProductId = uint32(_lockProductId);\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function releaseFunds(uint lockId) external {\n // next line would revert but require to emit reason:\n require(lockId < locks.length, \"invalid lockId\");\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive, \"lock must be in active state\");\n require(now >= lock.lockedUntil, \"current time must be later than lockedUntil\");\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n emit LockReleased(lock.owner, lockId);\n }\n\n function setMonetarySupervisor(MonetarySupervisor newMonetarySupervisor) external restrict(\"StabilityBoard\") {\n monetarySupervisor = newMonetarySupervisor;\n emit MonetarySupervisorChanged(newMonetarySupervisor);\n }\n\n function getLockProductCount() external view returns (uint) {\n return lockProducts.length;\n }\n\n // returns lock products starting from some \n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ]\n function getLockProducts(uint offset, uint16 chunkSize)\n external view returns (uint[5][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), lockProducts.length);\n uint[5][] memory response = new uint[5][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n LockProduct storage lockProduct = lockProducts[i];\n response[i - offset] = [lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount,\n monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest),\n lockProduct.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns locks starting from some \n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset, uint16 chunkSize)\n external view returns (uint[8][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), locks.length);\n uint[8][] memory response = new uint[8][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n Lock storage lock = locks[i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i - offset] = [uint(i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n return response;\n }\n\n // returns locks of a given account, starting from some \n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset, uint16 chunkSize)\n external view returns (uint[7][]) {\n uint[] storage locksForAddress = accountLocks[lockOwner];\n uint limit = SafeMath.min(offset.add(chunkSize), locksForAddress.length);\n uint[7][] memory response = new uint[7][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n Lock storage lock = locks[locksForAddress[i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i - offset] = [locksForAddress[i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).ceilDiv(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive, \"lockProduct must be in active state\");\n require(amountToLock >= lockProduct.minimumLockAmount, \"amountToLock must be >= minimumLockAmount\");\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration, \"lockedUntil overflow\");\n\n uint lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs);\n }\n}\n" } } } diff --git a/abiniser/deployments/4/Migrations_DEPLOYS.json b/abiniser/deployments/4/Migrations_DEPLOYS.json index 83e857c7..ef298878 100644 --- a/abiniser/deployments/4/Migrations_DEPLOYS.json +++ b/abiniser/deployments/4/Migrations_DEPLOYS.json @@ -3,44 +3,20 @@ "latestAbiHash": "78141a323f4a8416891b06a0a2b90065", "deployedAbis": { "78141a323f4a8416891b06a0a2b90065": { - "latestDeployedAddress": "0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5", + "latestDeployedAddress": "0xc9a7258b2b1ea36ce735793e4816ad949532c9fd", "deployments": { - "0xab568f6a378de0443f1e273f79abcaf68dfbd39d": { - "generatedAt": "2018-04-25T12:29:07.436Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:31:03.063Z", + "0xc9a7258b2b1ea36ce735793e4816ad949532c9fd": { + "generatedAt": "2018-10-18T13:35:02.323Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.823Z", + "deployTransactionHash": "0xf529f773b4efda519e62d6dcbb71e5e1fa7a0223599f5db5edf792e85a3f9679", "compiler": { "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" + "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "dafdfde2cb0510d2cf640d9906cf2aa3", - "deployedBytecodeHash": "3daa7b91f2db8b848eb07fe6e3ec1dfb", - "sourceHash": "73453b2f522d50aaa2f4864b97228d70", - "source": "pragma solidity 0.4.19;\n\n\ncontract Migrations {\n address public owner;\n uint public last_completed_migration; // solhint-disable-line var-name-mixedcase\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n function Migrations() public {\n owner = msg.sender;\n }\n\n function setCompleted(uint completed) external restricted {\n last_completed_migration = completed;\n }\n\n function upgrade(address newAddress) external restricted {\n Migrations upgraded = Migrations(newAddress);\n upgraded.setCompleted(last_completed_migration);\n }\n}\n" - }, - "0x0e1503c9426211ff73c35638bca30c833117a263": { - "generatedAt": "2018-04-25T12:30:49.013Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:36:28.116Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "434c4db1e158b1d1d085fc2d317413e8", - "deployedBytecodeHash": "052dae24bbeb4e976a4034fba862226b", - "sourceHash": "73453b2f522d50aaa2f4864b97228d70", - "source": "pragma solidity 0.4.19;\n\n\ncontract Migrations {\n address public owner;\n uint public last_completed_migration; // solhint-disable-line var-name-mixedcase\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n function Migrations() public {\n owner = msg.sender;\n }\n\n function setCompleted(uint completed) external restricted {\n last_completed_migration = completed;\n }\n\n function upgrade(address newAddress) external restricted {\n Migrations upgraded = Migrations(newAddress);\n upgraded.setCompleted(last_completed_migration);\n }\n}\n" - }, - "0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5": { - "generatedAt": "2018-04-25T12:31:28.947Z", - "truffleContractFileUpdatedAt": "2018-04-20T18:26:53.869Z", - "deployTransactionHash": "0xb162c770dea001b3af2422bf30df3a462b1265394648c5e8d7ba2b24c7f20d31", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "9faa7fe7badb75808c09a3daae207bec", - "deployedBytecodeHash": "133cb797c7a10dbc9bd9679de5e56bec", - "sourceHash": "242df4d17574b24bb367e6aa59fadcad", - "source": "pragma solidity ^0.4.23;\n\n\ncontract Migrations {\n address public owner;\n uint public last_completed_migration; // solhint-disable-line var-name-mixedcase\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n constructor() public {\n owner = msg.sender;\n }\n\n function setCompleted(uint completed) external restricted {\n last_completed_migration = completed;\n }\n\n function upgrade(address newAddress) external restricted {\n Migrations upgraded = Migrations(newAddress);\n upgraded.setCompleted(last_completed_migration);\n }\n}\n" + "bytecodeHash": "3bd5779c94259890d586374c5db67f2b", + "deployedBytecodeHash": "f00491b62e24c57c6d12323c73c1037e", + "sourceHash": "16ee1835a27505e14d1b6990cdfa8c2c", + "source": "pragma solidity 0.4.24;\n\n\ncontract Migrations {\n address public owner;\n uint public last_completed_migration; // solhint-disable-line var-name-mixedcase\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n constructor() public {\n owner = msg.sender;\n }\n\n function setCompleted(uint completed) external restricted {\n last_completed_migration = completed;\n }\n\n function upgrade(address newAddress) external restricted {\n Migrations upgraded = Migrations(newAddress);\n upgraded.setCompleted(last_completed_migration);\n }\n}\n" } } } diff --git a/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json b/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json index ddfb5549..81ecca9e 100644 --- a/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json +++ b/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json @@ -1,108 +1,35 @@ { "contractName": "MonetarySupervisor", - "latestAbiHash": "54d27fedd8bf3010ad5509866a42c053", + "latestAbiHash": "7f500b43397413e97de925528187f9cd", "deployedAbis": { - "066c2220b91befd25691fefd91684117": { - "latestDeployedAddress": "0x02a3b0f6ab5998a0c5d756ed01ea2200ea68d763", + "7f500b43397413e97de925528187f9cd": { + "latestDeployedAddress": "0x4a7f6ecbe8b324a55b85adcc45313a412957b8ea", "deployments": { - "0xd0c273bb6023611f166e92105232fb225392013b": { - "generatedAt": "2018-04-25T12:29:07.564Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:29:32.214Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "0c0d7f8840d3267bcc4625b5d0b07c6b", - "deployedBytecodeHash": "2931a2d6f8a22994a9f4ed26ac04aa59", - "sourceHash": "3d16faed337b9adec2d66024be645249", - "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n\n TODO:\n - MonetarySupervisorInterface (and use it everywhere)\n - interestEarnedAccount setter?\n - create and use InterestEarnedAccount interface instead?\n\n*/\n\npragma solidity 0.4.19;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByMonetaryBoard; // supply issued manually by monetary board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /* Parameters Used to ensure totalLoanAmount or totalLockedAmount difference is withing limit and system also works\n when any of those 0 or low. */\n uint public ltdDifferenceLimit; /* allow lock or loan if Loan To Deposut ratio stay within 1 +- this param\n stored as parts per million */\n uint public allowedLtdDifferenceAmount; /* in token - if totalLoan and totalLock difference is less than that\n then allow loan or lock even if ltdDifference limit would go off with it */\n\n event ParamsChanged(uint ltdDifferenceLimit, uint allowedLtdDifferenceAmount);\n\n function MonetarySupervisor(AugmintTokenInterface _augmintToken, AugmintReserves _augmintReserves,\n InterestEarnedAccount _interestEarnedAccount,\n uint _ltdDifferenceLimit, uint _allowedLtdDifferenceAmount) public {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdDifferenceLimit = _ltdDifferenceLimit;\n allowedLtdDifferenceAmount = _allowedLtdDifferenceAmount;\n }\n\n function issueToReserve(uint amount) external restrict(\"MonetaryBoard\") {\n issuedByMonetaryBoard = issuedByMonetaryBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"MonetaryBoard\") {\n issuedByMonetaryBoard = issuedByMonetaryBoard.sub(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n // Locker requesting interest when locking funds\n function requestInterest(uint amountToLock, uint interestAmount) external {\n require(permissions[msg.sender][\"LockerContracts\"]); // only whitelisted LockerContracts\n /* TODO: enforce LTD limits (ltdDifferenceLimit & allowedLtdDifferenceAmount) */\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n require(permissions[msg.sender][\"LockerContracts\"]); // only whitelisted LockerContracts\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n function issueLoan(address borrower, uint loanAmount) external {\n require(permissions[msg.sender][\"LoanManagerContracts\"]); // only whitelisted LoanManager contracts\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n require(permissions[msg.sender][\"LoanManagerContracts\"]); // only whitelisted Lender contracts\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n require(permissions[msg.sender][\"LoanManagerContracts\"]); // only whitelisted Lender contracts\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setParams(uint _ltdDifferenceLimit, uint _allowedLtdDifferenceAmount)\n external restrict(\"MonetaryBoard\") {\n ltdDifferenceLimit = _ltdDifferenceLimit;\n allowedLtdDifferenceAmount = _allowedLtdDifferenceAmount;\n\n ParamsChanged(ltdDifferenceLimit, allowedLtdDifferenceAmount);\n }\n\n // helper function for FrontEnd to reduce calls\n function getParams() external view returns(uint[2]) {\n return [ltdDifferenceLimit, allowedLtdDifferenceAmount];\n }\n\n}\n" - }, - "0x02a3b0f6ab5998a0c5d756ed01ea2200ea68d763": { - "generatedAt": "2018-04-25T12:30:49.339Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:36:28.104Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "aaa00593c08a52c6bbce73d97d28e20a", - "deployedBytecodeHash": "6a662f2eb12115963b51303c0a7a0912", - "sourceHash": "3d16faed337b9adec2d66024be645249", - "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n\n TODO:\n - MonetarySupervisorInterface (and use it everywhere)\n - interestEarnedAccount setter?\n - create and use InterestEarnedAccount interface instead?\n\n*/\n\npragma solidity 0.4.19;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByMonetaryBoard; // supply issued manually by monetary board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /* Parameters Used to ensure totalLoanAmount or totalLockedAmount difference is withing limit and system also works\n when any of those 0 or low. */\n uint public ltdDifferenceLimit; /* allow lock or loan if Loan To Deposut ratio stay within 1 +- this param\n stored as parts per million */\n uint public allowedLtdDifferenceAmount; /* in token - if totalLoan and totalLock difference is less than that\n then allow loan or lock even if ltdDifference limit would go off with it */\n\n event ParamsChanged(uint ltdDifferenceLimit, uint allowedLtdDifferenceAmount);\n\n function MonetarySupervisor(AugmintTokenInterface _augmintToken, AugmintReserves _augmintReserves,\n InterestEarnedAccount _interestEarnedAccount,\n uint _ltdDifferenceLimit, uint _allowedLtdDifferenceAmount) public {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdDifferenceLimit = _ltdDifferenceLimit;\n allowedLtdDifferenceAmount = _allowedLtdDifferenceAmount;\n }\n\n function issueToReserve(uint amount) external restrict(\"MonetaryBoard\") {\n issuedByMonetaryBoard = issuedByMonetaryBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"MonetaryBoard\") {\n issuedByMonetaryBoard = issuedByMonetaryBoard.sub(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n // Locker requesting interest when locking funds\n function requestInterest(uint amountToLock, uint interestAmount) external {\n require(permissions[msg.sender][\"LockerContracts\"]); // only whitelisted LockerContracts\n /* TODO: enforce LTD limits (ltdDifferenceLimit & allowedLtdDifferenceAmount) */\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n require(permissions[msg.sender][\"LockerContracts\"]); // only whitelisted LockerContracts\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n function issueLoan(address borrower, uint loanAmount) external {\n require(permissions[msg.sender][\"LoanManagerContracts\"]); // only whitelisted LoanManager contracts\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n require(permissions[msg.sender][\"LoanManagerContracts\"]); // only whitelisted Lender contracts\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n require(permissions[msg.sender][\"LoanManagerContracts\"]); // only whitelisted Lender contracts\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setParams(uint _ltdDifferenceLimit, uint _allowedLtdDifferenceAmount)\n external restrict(\"MonetaryBoard\") {\n ltdDifferenceLimit = _ltdDifferenceLimit;\n allowedLtdDifferenceAmount = _allowedLtdDifferenceAmount;\n\n ParamsChanged(ltdDifferenceLimit, allowedLtdDifferenceAmount);\n }\n\n // helper function for FrontEnd to reduce calls\n function getParams() external view returns(uint[2]) {\n return [ltdDifferenceLimit, allowedLtdDifferenceAmount];\n }\n\n}\n" - } - } - }, - "a552ee1f90ae83cb91d07311ae8eab1e": { - "latestDeployedAddress": "0xc19a45f5cbfa93be512ef07177feb3f7b3ae4518", - "deployments": { - "0x2e8b07a973f8e136aa39922dff21ad187a6e8e7d": { - "generatedAt": "2018-04-25T12:31:29.126Z", - "truffleContractFileUpdatedAt": "2018-04-20T18:26:53.540Z", - "deployTransactionHash": "0x7f8049914c355bcc0f9ac0e3dd381b0e2fc90cc077769511a34aac136c0d08d5", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "c245a44ab31d54b7b6cde54eb3d96a7c", - "deployedBytecodeHash": "83c21b4ee2d4acec62a24c09234c3a1d", - "sourceHash": "5c1b006109344523977cb1bf8fd493d8", - "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n - Converts older versions of AugmintTokens in 1:1 to new\n\n TODO:\n - Mcreate and use MonetarySupervisorInterface?\n - create and use InterestEarnedAccount interface ?\n\n*/\n\npragma solidity ^0.4.23;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n uint public constant PERCENT_100 = 1000000;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByMonetaryBoard; // supply issued manually by monetary board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /**********\n Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works\n when total loan or lock amounts are low.\n for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0\n **********/\n struct LtdParams {\n uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above\n (1 - lockDifferenceLimit) with new lock. Stored as parts per million */\n uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above\n (1 + loanDifferenceLimit) with new loan. Stored as parts per million */\n /* allowedDifferenceAmount param is to ensure the system is not \"freezing\" when totalLoanAmount or\n totalLockAmount is low.\n It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above\n lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */\n uint allowedDifferenceAmount;\n }\n\n LtdParams public ltdParams;\n\n /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() )\n NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */\n mapping(address => bool) public acceptedLegacyAugmintTokens;\n\n event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount);\n\n event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState);\n\n event LegacyTokenConverted(address oldTokenAddress, address account, uint amount);\n\n event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment);\n\n event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves);\n\n constructor(AugmintTokenInterface _augmintToken, AugmintReserves _augmintReserves,\n InterestEarnedAccount _interestEarnedAccount,\n uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount) public {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n function issueToReserve(uint amount) external restrict(\"MonetaryBoard\") {\n issuedByMonetaryBoard = issuedByMonetaryBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"MonetaryBoard\") {\n issuedByMonetaryBoard = issuedByMonetaryBoard.sub(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function requestInterest(uint amountToLock, uint interestAmount) external {\n // only whitelisted LockerContracts\n require(permissions[msg.sender][\"LockerContracts\"], \"msg.sender must have LockerContracts permission\");\n require(amountToLock <= getMaxLockAmountAllowedByLtd(), \"amountToLock must be <= maxLockAmountAllowedByLtd\");\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n // next line would revert but require to emit reason:\n require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount,\n \"interestEarnedAccount balance must be >= interestAmount\");\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n // only whitelisted LockerContracts\n require(permissions[msg.sender][\"LockerContracts\"], \"msg.sender must have LockerContracts permission\");\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n /* Issue loan if LTD stays within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function issueLoan(address borrower, uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n require(loanAmount <= getMaxLoanAmountAllowedByLtd(), \"loanAmount must be <= maxLoanAmountAllowedByLtd\");\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState)\n external restrict(\"MonetaryBoard\") {\n acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState;\n emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState);\n }\n\n function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n external restrict(\"MonetaryBoard\") {\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n\n emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract\n when it's upgraded.\n Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */\n function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment)\n external restrict(\"MonetaryBoard\") {\n totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment);\n totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment);\n\n emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment);\n }\n\n /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */\n function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves)\n external restrict(\"MonetaryBoard\") {\n interestEarnedAccount = newInterestEarnedAccount;\n augmintReserves = newAugmintReserves;\n emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves);\n }\n\n /* User can request to convert their tokens from older AugmintToken versions in 1:1\n transferNotification is called from AugmintToken's transferAndNotify\n Flow for converting old tokens:\n 1) user calls old token contract's transferAndNotify with the amount to convert,\n addressing the new MonetarySupervisor Contract\n 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address\n 3) transferAndNotify calls MonetarySupervisor.transferNotification\n 4) MonetarySupervisor checks if old AugmintToken is permitted\n 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken\n 6) MonetarySupervisor burns old tokens from own balance\n */\n function transferNotification(address from, uint amount, uint /* data, not used */ ) external {\n AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender);\n require(acceptedLegacyAugmintTokens[legacyToken], \"msg.sender must be allowed in acceptedLegacyAugmintTokens\");\n\n legacyToken.burn(amount);\n augmintToken.issueTo(from, amount);\n emit LegacyTokenConverted(msg.sender, from, amount);\n }\n\n function getLoanToDepositRatio() external view returns (uint loanToDepositRatio) {\n loanToDepositRatio = totalLockedAmount == 0 ? 0 : totalLockedAmount.mul(PERCENT_100).div(totalLoanAmount);\n }\n\n /* Helper function for UI.\n Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */\n function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) {\n uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt);\n uint allowedByLtd = getMaxLockAmountAllowedByLtd();\n maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd;\n maxLock = maxLock < minLockAmount ? 0 : maxLock;\n }\n\n /* Helper function for UI.\n Returns max loan amount based on minLoanAmont using LTD params */\n function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) {\n uint allowedByLtd = getMaxLoanAmountAllowedByLtd();\n maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd;\n }\n\n /* returns maximum lockable token amount allowed by LTD params. */\n function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) {\n uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100\n .sub(ltdParams.lockDifferenceLimit));\n allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLockedAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount > totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount);\n\n maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n /* returns maximum borrowable token amount allowed by LTD params */\n function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) {\n uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100))\n .div(PERCENT_100);\n allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLoanAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount > totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount);\n\n maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n}\n" - }, - "0xa00a5d1882c3f690e3d0d975ebe378120b70ae87": { - "generatedAt": "2018-04-27T00:06:09.883Z", - "truffleContractFileUpdatedAt": "2018-04-27T00:02:50.106Z", - "deployTransactionHash": "0x00c619309e8bada11d4cdc415c460799d1455f020a57bea5a2df5f636d506351", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "c41181b91537cc751d880d79baf095dd", - "deployedBytecodeHash": "afc07e949d0fc0522760e21001e6442e", - "sourceHash": "cbd67b35e74bbbc9ef5a78c3180eb002", - "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n - Converts older versions of AugmintTokens in 1:1 to new\n\n TODO:\n - Mcreate and use MonetarySupervisorInterface?\n - create and use InterestEarnedAccount interface ?\n\n*/\n\npragma solidity ^0.4.23;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n uint public constant PERCENT_100 = 1000000;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByMonetaryBoard; // supply issued manually by monetary board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /**********\n Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works\n when total loan or lock amounts are low.\n for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0\n **********/\n struct LtdParams {\n uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above\n (1 - lockDifferenceLimit) with new lock. Stored as parts per million */\n uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above\n (1 + loanDifferenceLimit) with new loan. Stored as parts per million */\n /* allowedDifferenceAmount param is to ensure the system is not \"freezing\" when totalLoanAmount or\n totalLockAmount is low.\n It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above\n lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */\n uint allowedDifferenceAmount;\n }\n\n LtdParams public ltdParams;\n\n /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() )\n NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */\n mapping(address => bool) public acceptedLegacyAugmintTokens;\n\n event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount);\n\n event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState);\n\n event LegacyTokenConverted(address oldTokenAddress, address account, uint amount);\n\n event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment);\n\n event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves);\n\n constructor(AugmintTokenInterface _augmintToken, AugmintReserves _augmintReserves,\n InterestEarnedAccount _interestEarnedAccount,\n uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount) public {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n function issueToReserve(uint amount) external restrict(\"MonetaryBoard\") {\n issuedByMonetaryBoard = issuedByMonetaryBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"MonetaryBoard\") {\n issuedByMonetaryBoard = issuedByMonetaryBoard.sub(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function requestInterest(uint amountToLock, uint interestAmount) external {\n // only whitelisted LockerContracts\n require(permissions[msg.sender][\"LockerContracts\"], \"msg.sender must have LockerContracts permission\");\n require(amountToLock <= getMaxLockAmountAllowedByLtd(), \"amountToLock must be <= maxLockAmountAllowedByLtd\");\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n // next line would revert but require to emit reason:\n require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount,\n \"interestEarnedAccount balance must be >= interestAmount\");\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n // only whitelisted LockerContracts\n require(permissions[msg.sender][\"LockerContracts\"], \"msg.sender must have LockerContracts permission\");\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n /* Issue loan if LTD stays within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function issueLoan(address borrower, uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n require(loanAmount <= getMaxLoanAmountAllowedByLtd(), \"loanAmount must be <= maxLoanAmountAllowedByLtd\");\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState)\n external restrict(\"MonetaryBoard\") {\n acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState;\n emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState);\n }\n\n function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n external restrict(\"MonetaryBoard\") {\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n\n emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract\n when it's upgraded.\n Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */\n function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment)\n external restrict(\"MonetaryBoard\") {\n totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment);\n totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment);\n\n emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment);\n }\n\n /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */\n function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves)\n external restrict(\"MonetaryBoard\") {\n interestEarnedAccount = newInterestEarnedAccount;\n augmintReserves = newAugmintReserves;\n emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves);\n }\n\n /* User can request to convert their tokens from older AugmintToken versions in 1:1\n transferNotification is called from AugmintToken's transferAndNotify\n Flow for converting old tokens:\n 1) user calls old token contract's transferAndNotify with the amount to convert,\n addressing the new MonetarySupervisor Contract\n 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address\n 3) transferAndNotify calls MonetarySupervisor.transferNotification\n 4) MonetarySupervisor checks if old AugmintToken is permitted\n 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken\n 6) MonetarySupervisor burns old tokens from own balance\n */\n function transferNotification(address from, uint amount, uint /* data, not used */ ) external {\n AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender);\n require(acceptedLegacyAugmintTokens[legacyToken], \"msg.sender must be allowed in acceptedLegacyAugmintTokens\");\n\n legacyToken.burn(amount);\n augmintToken.issueTo(from, amount);\n emit LegacyTokenConverted(msg.sender, from, amount);\n }\n\n function getLoanToDepositRatio() external view returns (uint loanToDepositRatio) {\n loanToDepositRatio = totalLockedAmount == 0 ? 0 : totalLockedAmount.mul(PERCENT_100).div(totalLoanAmount);\n }\n\n /* Helper function for UI.\n Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */\n function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) {\n uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt);\n uint allowedByLtd = getMaxLockAmountAllowedByLtd();\n maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd;\n maxLock = maxLock < minLockAmount ? 0 : maxLock;\n }\n\n /* Helper function for UI.\n Returns max loan amount based on minLoanAmont using LTD params */\n function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) {\n uint allowedByLtd = getMaxLoanAmountAllowedByLtd();\n maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd;\n }\n\n /* returns maximum lockable token amount allowed by LTD params. */\n function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) {\n uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100\n .sub(ltdParams.lockDifferenceLimit));\n allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLockedAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLockedAmount >= totalLoanAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount);\n\n maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n /* returns maximum borrowable token amount allowed by LTD params */\n function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) {\n uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100))\n .div(PERCENT_100);\n allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLoanAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount >= totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount);\n\n maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n}\n" - }, - "0xc19a45f5cbfa93be512ef07177feb3f7b3ae4518": { - "generatedAt": "2018-05-12T01:34:38.474Z", - "truffleContractFileUpdatedAt": "2018-05-12T01:30:50.663Z", - "deployTransactionHash": "0x1dc6702b64f4edcba0201b1c4e49c47fbbbbaab7788ed37ee104e6bb3df3b21c", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "83f4ac731042d988dad02af18401f3f3", - "deployedBytecodeHash": "6356e4110fb4cbff5b57908614a63219", - "sourceHash": "cbd67b35e74bbbc9ef5a78c3180eb002", - "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n - Converts older versions of AugmintTokens in 1:1 to new\n\n TODO:\n - Mcreate and use MonetarySupervisorInterface?\n - create and use InterestEarnedAccount interface ?\n\n*/\n\npragma solidity ^0.4.23;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n uint public constant PERCENT_100 = 1000000;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByMonetaryBoard; // supply issued manually by monetary board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /**********\n Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works\n when total loan or lock amounts are low.\n for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0\n **********/\n struct LtdParams {\n uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above\n (1 - lockDifferenceLimit) with new lock. Stored as parts per million */\n uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above\n (1 + loanDifferenceLimit) with new loan. Stored as parts per million */\n /* allowedDifferenceAmount param is to ensure the system is not \"freezing\" when totalLoanAmount or\n totalLockAmount is low.\n It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above\n lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */\n uint allowedDifferenceAmount;\n }\n\n LtdParams public ltdParams;\n\n /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() )\n NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */\n mapping(address => bool) public acceptedLegacyAugmintTokens;\n\n event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount);\n\n event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState);\n\n event LegacyTokenConverted(address oldTokenAddress, address account, uint amount);\n\n event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment);\n\n event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves);\n\n constructor(AugmintTokenInterface _augmintToken, AugmintReserves _augmintReserves,\n InterestEarnedAccount _interestEarnedAccount,\n uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount) public {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n function issueToReserve(uint amount) external restrict(\"MonetaryBoard\") {\n issuedByMonetaryBoard = issuedByMonetaryBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"MonetaryBoard\") {\n issuedByMonetaryBoard = issuedByMonetaryBoard.sub(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function requestInterest(uint amountToLock, uint interestAmount) external {\n // only whitelisted LockerContracts\n require(permissions[msg.sender][\"LockerContracts\"], \"msg.sender must have LockerContracts permission\");\n require(amountToLock <= getMaxLockAmountAllowedByLtd(), \"amountToLock must be <= maxLockAmountAllowedByLtd\");\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n // next line would revert but require to emit reason:\n require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount,\n \"interestEarnedAccount balance must be >= interestAmount\");\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n // only whitelisted LockerContracts\n require(permissions[msg.sender][\"LockerContracts\"], \"msg.sender must have LockerContracts permission\");\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n /* Issue loan if LTD stays within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function issueLoan(address borrower, uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n require(loanAmount <= getMaxLoanAmountAllowedByLtd(), \"loanAmount must be <= maxLoanAmountAllowedByLtd\");\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState)\n external restrict(\"MonetaryBoard\") {\n acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState;\n emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState);\n }\n\n function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n external restrict(\"MonetaryBoard\") {\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n\n emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract\n when it's upgraded.\n Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */\n function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment)\n external restrict(\"MonetaryBoard\") {\n totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment);\n totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment);\n\n emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment);\n }\n\n /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */\n function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves)\n external restrict(\"MonetaryBoard\") {\n interestEarnedAccount = newInterestEarnedAccount;\n augmintReserves = newAugmintReserves;\n emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves);\n }\n\n /* User can request to convert their tokens from older AugmintToken versions in 1:1\n transferNotification is called from AugmintToken's transferAndNotify\n Flow for converting old tokens:\n 1) user calls old token contract's transferAndNotify with the amount to convert,\n addressing the new MonetarySupervisor Contract\n 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address\n 3) transferAndNotify calls MonetarySupervisor.transferNotification\n 4) MonetarySupervisor checks if old AugmintToken is permitted\n 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken\n 6) MonetarySupervisor burns old tokens from own balance\n */\n function transferNotification(address from, uint amount, uint /* data, not used */ ) external {\n AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender);\n require(acceptedLegacyAugmintTokens[legacyToken], \"msg.sender must be allowed in acceptedLegacyAugmintTokens\");\n\n legacyToken.burn(amount);\n augmintToken.issueTo(from, amount);\n emit LegacyTokenConverted(msg.sender, from, amount);\n }\n\n function getLoanToDepositRatio() external view returns (uint loanToDepositRatio) {\n loanToDepositRatio = totalLockedAmount == 0 ? 0 : totalLockedAmount.mul(PERCENT_100).div(totalLoanAmount);\n }\n\n /* Helper function for UI.\n Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */\n function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) {\n uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt);\n uint allowedByLtd = getMaxLockAmountAllowedByLtd();\n maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd;\n maxLock = maxLock < minLockAmount ? 0 : maxLock;\n }\n\n /* Helper function for UI.\n Returns max loan amount based on minLoanAmont using LTD params */\n function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) {\n uint allowedByLtd = getMaxLoanAmountAllowedByLtd();\n maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd;\n }\n\n /* returns maximum lockable token amount allowed by LTD params. */\n function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) {\n uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100\n .sub(ltdParams.lockDifferenceLimit));\n allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLockedAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLockedAmount >= totalLoanAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount);\n\n maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n /* returns maximum borrowable token amount allowed by LTD params */\n function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) {\n uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100))\n .div(PERCENT_100);\n allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLoanAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount >= totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount);\n\n maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n}\n" - } - } - }, - "54d27fedd8bf3010ad5509866a42c053": { - "latestDeployedAddress": "0x01844c9bade08a8ffdb09ad9f1fece2c83a6e6a8", - "deployments": { - "0xa14e0c0e39f00ef051df516f80e76208b716b0eb": { - "generatedAt": "2018-06-04T12:49:52.570Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.466Z", - "deployTransactionHash": "0xc03ce373b7d345b9c5ad6c5408a8a99c88dea63b8079315402326db8343e5d3e", + "0xcec3574eca89409b15a8a72a6e737c4171457871": { + "generatedAt": "2018-10-18T13:35:02.380Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.944Z", + "deployTransactionHash": "0x19fbec82a3e2c548de1e2ecdf4b849da6e0d72688505cd3b570ecbc373ee0b9e", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "26accaea67047f4b179269c17b148db5", - "deployedBytecodeHash": "c1b4e29d1c25524993d61fef36eca8be", - "sourceHash": "c85d698187fe21fecfb040a1078b50af", - "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n - Converts older versions of AugmintTokens in 1:1 to new\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n uint public constant PERCENT_100 = 1000000;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByStabilityBoard; // token issued by Stability Board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /**********\n Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works\n when total loan or lock amounts are low.\n for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0\n **********/\n struct LtdParams {\n uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above\n (1 - lockDifferenceLimit) with new lock. Stored as parts per million */\n uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above\n (1 + loanDifferenceLimit) with new loan. Stored as parts per million */\n /* allowedDifferenceAmount param is to ensure the system is not \"freezing\" when totalLoanAmount or\n totalLockAmount is low.\n It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above\n lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */\n uint allowedDifferenceAmount;\n }\n\n LtdParams public ltdParams;\n\n /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() )\n NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */\n mapping(address => bool) public acceptedLegacyAugmintTokens;\n\n event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount);\n\n event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState);\n\n event LegacyTokenConverted(address oldTokenAddress, address account, uint amount);\n\n event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment);\n\n event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, AugmintReserves _augmintReserves,\n InterestEarnedAccount _interestEarnedAccount,\n uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n function issueToReserve(uint amount) external restrict(\"StabilityBoardSignerContract\") {\n issuedByStabilityBoard = issuedByStabilityBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"StabilityBoardSignerContract\") {\n issuedByStabilityBoard = issuedByStabilityBoard.sub(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function requestInterest(uint amountToLock, uint interestAmount) external {\n // only whitelisted LockerContracts\n require(permissions[msg.sender][\"LockerContracts\"], \"msg.sender must have LockerContracts permission\");\n require(amountToLock <= getMaxLockAmountAllowedByLtd(), \"amountToLock must be <= maxLockAmountAllowedByLtd\");\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n // next line would revert but require to emit reason:\n require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount,\n \"interestEarnedAccount balance must be >= interestAmount\");\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n // only whitelisted LockerContracts\n require(permissions[msg.sender][\"LockerContracts\"], \"msg.sender must have LockerContracts permission\");\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n /* Issue loan if LTD stays within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function issueLoan(address borrower, uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n require(loanAmount <= getMaxLoanAmountAllowedByLtd(), \"loanAmount must be <= maxLoanAmountAllowedByLtd\");\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManagerContracts\"],\n \"msg.sender must have LoanManagerContracts permission\");\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState)\n external restrict(\"StabilityBoardSignerContract\") {\n acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState;\n emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState);\n }\n\n function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n external restrict(\"StabilityBoardSignerContract\") {\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n\n emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract\n when it's upgraded.\n Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */\n function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment)\n external restrict(\"StabilityBoardSignerContract\") {\n totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment);\n totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment);\n\n emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment);\n }\n\n /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */\n function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves)\n external restrict(\"StabilityBoardSignerContract\") {\n interestEarnedAccount = newInterestEarnedAccount;\n augmintReserves = newAugmintReserves;\n emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves);\n }\n\n /* User can request to convert their tokens from older AugmintToken versions in 1:1\n transferNotification is called from AugmintToken's transferAndNotify\n Flow for converting old tokens:\n 1) user calls old token contract's transferAndNotify with the amount to convert,\n addressing the new MonetarySupervisor Contract\n 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address\n 3) transferAndNotify calls MonetarySupervisor.transferNotification\n 4) MonetarySupervisor checks if old AugmintToken is permitted\n 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken\n 6) MonetarySupervisor burns old tokens from own balance\n */\n function transferNotification(address from, uint amount, uint /* data, not used */ ) external {\n AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender);\n require(acceptedLegacyAugmintTokens[legacyToken], \"msg.sender must be allowed in acceptedLegacyAugmintTokens\");\n\n legacyToken.burn(amount);\n augmintToken.issueTo(from, amount);\n emit LegacyTokenConverted(msg.sender, from, amount);\n }\n\n function getLoanToDepositRatio() external view returns (uint loanToDepositRatio) {\n loanToDepositRatio = totalLockedAmount == 0 ? 0 : totalLockedAmount.mul(PERCENT_100).div(totalLoanAmount);\n }\n\n /* Helper function for UI.\n Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */\n function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) {\n uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt);\n uint allowedByLtd = getMaxLockAmountAllowedByLtd();\n maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd;\n maxLock = maxLock < minLockAmount ? 0 : maxLock;\n }\n\n /* Helper function for UI.\n Returns max loan amount based on minLoanAmont using LTD params */\n function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) {\n uint allowedByLtd = getMaxLoanAmountAllowedByLtd();\n maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd;\n }\n\n /* returns maximum lockable token amount allowed by LTD params. */\n function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) {\n uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100\n .sub(ltdParams.lockDifferenceLimit));\n allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLockedAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLockedAmount >= totalLoanAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount);\n\n maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n /* returns maximum borrowable token amount allowed by LTD params */\n function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) {\n uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100))\n .div(PERCENT_100);\n allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLoanAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount >= totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount);\n\n maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n}\n" + "bytecodeHash": "fa3e6bca24f24d5945b149c05701b69c", + "deployedBytecodeHash": "422b205eb739ddcf33fadad8edf32d7e", + "sourceHash": "62748c793556775f9ac607b991886bfb", + "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n - Converts older versions of AugmintTokens in 1:1 to new\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n uint public constant PERCENT_100 = 1000000;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByStabilityBoard; // token issued by Stability Board\n uint public burnedByStabilityBoard; // token burned by Stability Board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /**********\n Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works\n when total loan or lock amounts are low.\n for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0\n **********/\n struct LtdParams {\n uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above\n (1 - lockDifferenceLimit) with new lock. Stored as parts per million */\n uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above\n (1 + loanDifferenceLimit) with new loan. Stored as parts per million */\n /* allowedDifferenceAmount param is to ensure the system is not \"freezing\" when totalLoanAmount or\n totalLockAmount is low.\n It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above\n lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */\n uint allowedDifferenceAmount;\n }\n\n LtdParams public ltdParams;\n\n /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() )\n NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */\n mapping(address => bool) public acceptedLegacyAugmintTokens;\n\n event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount);\n\n event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState);\n\n event LegacyTokenConverted(address oldTokenAddress, address account, uint amount);\n\n event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment);\n\n event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n AugmintReserves _augmintReserves, InterestEarnedAccount _interestEarnedAccount,\n uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n function issueToReserve(uint amount) external restrict(\"StabilityBoard\") {\n issuedByStabilityBoard = issuedByStabilityBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"StabilityBoard\") {\n burnedByStabilityBoard = burnedByStabilityBoard.add(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function requestInterest(uint amountToLock, uint interestAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n require(amountToLock <= getMaxLockAmountAllowedByLtd(), \"amountToLock must be <= maxLockAmountAllowedByLtd\");\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n // next line would revert but require to emit reason:\n require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount,\n \"interestEarnedAccount balance must be >= interestAmount\");\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n /* Issue loan if LTD stays within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function issueLoan(address borrower, uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n require(loanAmount <= getMaxLoanAmountAllowedByLtd(), \"loanAmount must be <= maxLoanAmountAllowedByLtd\");\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState)\n external restrict(\"StabilityBoard\") {\n acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState;\n emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState);\n }\n\n function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n external restrict(\"StabilityBoard\") {\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract\n when it's upgraded.\n Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */\n function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment)\n external restrict(\"StabilityBoard\") {\n totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment);\n totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment);\n emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment);\n }\n\n /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */\n function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves)\n external restrict(\"StabilityBoard\") {\n interestEarnedAccount = newInterestEarnedAccount;\n augmintReserves = newAugmintReserves;\n emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves);\n }\n\n /* User can request to convert their tokens from older AugmintToken versions in 1:1\n transferNotification is called from AugmintToken's transferAndNotify\n Flow for converting old tokens:\n 1) user calls old token contract's transferAndNotify with the amount to convert,\n addressing the new MonetarySupervisor Contract\n 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address\n 3) transferAndNotify calls MonetarySupervisor.transferNotification\n 4) MonetarySupervisor checks if old AugmintToken is permitted\n 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken\n 6) MonetarySupervisor burns old tokens from own balance\n */\n function transferNotification(address from, uint amount, uint /* data, not used */ ) external {\n AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender);\n require(acceptedLegacyAugmintTokens[legacyToken], \"msg.sender must be allowed in acceptedLegacyAugmintTokens\");\n\n legacyToken.burn(amount);\n augmintToken.issueTo(from, amount);\n emit LegacyTokenConverted(msg.sender, from, amount);\n }\n\n /* Helper function for UI.\n Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */\n function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) {\n uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt);\n uint allowedByLtd = getMaxLockAmountAllowedByLtd();\n maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd;\n maxLock = maxLock < minLockAmount ? 0 : maxLock;\n }\n\n /* Helper function for UI.\n Returns max loan amount based on minLoanAmont using LTD params */\n function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) {\n uint allowedByLtd = getMaxLoanAmountAllowedByLtd();\n maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd;\n }\n\n /* returns maximum lockable token amount allowed by LTD params. */\n function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) {\n uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100\n .sub(ltdParams.lockDifferenceLimit));\n allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLockedAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLockedAmount >= totalLoanAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount);\n\n maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n /* returns maximum borrowable token amount allowed by LTD params */\n function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) {\n uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100))\n .div(PERCENT_100);\n allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLoanAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount >= totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount);\n\n maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n}\n" }, - "0x01844c9bade08a8ffdb09ad9f1fece2c83a6e6a8": { - "generatedAt": "2018-06-10T08:34:44.882Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.905Z", - "deployTransactionHash": "0x021a2770fe912a7969c1acffc9b2a3b9a46791f99259c9a66ae5973da18b2b4f", + "0x4a7f6ecbe8b324a55b85adcc45313a412957b8ea": { + "generatedAt": "2018-10-29T15:52:43.281Z", + "truffleContractFileUpdatedAt": "2018-10-19T15:49:10.781Z", + "deployTransactionHash": "0x0baf8768f7981c779245386e877c955ef4617ab1c04e35d1e449c77c35c34e6c", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "448d933f9032a207e9d955e79a3c27d0", - "deployedBytecodeHash": "4391d4ad0219048ed4665e3646b7a52f", - "sourceHash": "9bbc8e70067c1c5e61086cd06ed79ac7", - "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n - Converts older versions of AugmintTokens in 1:1 to new\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n uint public constant PERCENT_100 = 1000000;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByStabilityBoard; // token issued by Stability Board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /**********\n Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works\n when total loan or lock amounts are low.\n for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0\n **********/\n struct LtdParams {\n uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above\n (1 - lockDifferenceLimit) with new lock. Stored as parts per million */\n uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above\n (1 + loanDifferenceLimit) with new loan. Stored as parts per million */\n /* allowedDifferenceAmount param is to ensure the system is not \"freezing\" when totalLoanAmount or\n totalLockAmount is low.\n It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above\n lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */\n uint allowedDifferenceAmount;\n }\n\n LtdParams public ltdParams;\n\n /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() )\n NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */\n mapping(address => bool) public acceptedLegacyAugmintTokens;\n\n event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount);\n\n event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState);\n\n event LegacyTokenConverted(address oldTokenAddress, address account, uint amount);\n\n event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment);\n\n event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, AugmintReserves _augmintReserves,\n InterestEarnedAccount _interestEarnedAccount,\n uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n function issueToReserve(uint amount) external restrict(\"StabilityBoard\") {\n issuedByStabilityBoard = issuedByStabilityBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"StabilityBoard\") {\n issuedByStabilityBoard = issuedByStabilityBoard.sub(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function requestInterest(uint amountToLock, uint interestAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n require(amountToLock <= getMaxLockAmountAllowedByLtd(), \"amountToLock must be <= maxLockAmountAllowedByLtd\");\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n // next line would revert but require to emit reason:\n require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount,\n \"interestEarnedAccount balance must be >= interestAmount\");\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n /* Issue loan if LTD stays within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function issueLoan(address borrower, uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n require(loanAmount <= getMaxLoanAmountAllowedByLtd(), \"loanAmount must be <= maxLoanAmountAllowedByLtd\");\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState)\n external restrict(\"StabilityBoard\") {\n acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState;\n emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState);\n }\n\n function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n external restrict(\"StabilityBoard\") {\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n\n emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract\n when it's upgraded.\n Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */\n function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment)\n external restrict(\"StabilityBoard\") {\n totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment);\n totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment);\n\n emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment);\n }\n\n /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */\n function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves)\n external restrict(\"StabilityBoard\") {\n interestEarnedAccount = newInterestEarnedAccount;\n augmintReserves = newAugmintReserves;\n emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves);\n }\n\n /* User can request to convert their tokens from older AugmintToken versions in 1:1\n transferNotification is called from AugmintToken's transferAndNotify\n Flow for converting old tokens:\n 1) user calls old token contract's transferAndNotify with the amount to convert,\n addressing the new MonetarySupervisor Contract\n 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address\n 3) transferAndNotify calls MonetarySupervisor.transferNotification\n 4) MonetarySupervisor checks if old AugmintToken is permitted\n 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken\n 6) MonetarySupervisor burns old tokens from own balance\n */\n function transferNotification(address from, uint amount, uint /* data, not used */ ) external {\n AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender);\n require(acceptedLegacyAugmintTokens[legacyToken], \"msg.sender must be allowed in acceptedLegacyAugmintTokens\");\n\n legacyToken.burn(amount);\n augmintToken.issueTo(from, amount);\n emit LegacyTokenConverted(msg.sender, from, amount);\n }\n\n function getLoanToDepositRatio() external view returns (uint loanToDepositRatio) {\n loanToDepositRatio = totalLockedAmount == 0 ? 0 : totalLockedAmount.mul(PERCENT_100).div(totalLoanAmount);\n }\n\n /* Helper function for UI.\n Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */\n function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) {\n uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt);\n uint allowedByLtd = getMaxLockAmountAllowedByLtd();\n maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd;\n maxLock = maxLock < minLockAmount ? 0 : maxLock;\n }\n\n /* Helper function for UI.\n Returns max loan amount based on minLoanAmont using LTD params */\n function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) {\n uint allowedByLtd = getMaxLoanAmountAllowedByLtd();\n maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd;\n }\n\n /* returns maximum lockable token amount allowed by LTD params. */\n function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) {\n uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100\n .sub(ltdParams.lockDifferenceLimit));\n allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLockedAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLockedAmount >= totalLoanAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount);\n\n maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n /* returns maximum borrowable token amount allowed by LTD params */\n function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) {\n uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100))\n .div(PERCENT_100);\n allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLoanAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount >= totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount);\n\n maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n}\n" + "bytecodeHash": "fa3e6bca24f24d5945b149c05701b69c", + "deployedBytecodeHash": "422b205eb739ddcf33fadad8edf32d7e", + "sourceHash": "62748c793556775f9ac607b991886bfb", + "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n - Converts older versions of AugmintTokens in 1:1 to new\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n uint public constant PERCENT_100 = 1000000;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByStabilityBoard; // token issued by Stability Board\n uint public burnedByStabilityBoard; // token burned by Stability Board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /**********\n Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works\n when total loan or lock amounts are low.\n for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0\n **********/\n struct LtdParams {\n uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above\n (1 - lockDifferenceLimit) with new lock. Stored as parts per million */\n uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above\n (1 + loanDifferenceLimit) with new loan. Stored as parts per million */\n /* allowedDifferenceAmount param is to ensure the system is not \"freezing\" when totalLoanAmount or\n totalLockAmount is low.\n It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above\n lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */\n uint allowedDifferenceAmount;\n }\n\n LtdParams public ltdParams;\n\n /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() )\n NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */\n mapping(address => bool) public acceptedLegacyAugmintTokens;\n\n event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount);\n\n event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState);\n\n event LegacyTokenConverted(address oldTokenAddress, address account, uint amount);\n\n event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment);\n\n event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n AugmintReserves _augmintReserves, InterestEarnedAccount _interestEarnedAccount,\n uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n function issueToReserve(uint amount) external restrict(\"StabilityBoard\") {\n issuedByStabilityBoard = issuedByStabilityBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"StabilityBoard\") {\n burnedByStabilityBoard = burnedByStabilityBoard.add(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function requestInterest(uint amountToLock, uint interestAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n require(amountToLock <= getMaxLockAmountAllowedByLtd(), \"amountToLock must be <= maxLockAmountAllowedByLtd\");\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n // next line would revert but require to emit reason:\n require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount,\n \"interestEarnedAccount balance must be >= interestAmount\");\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n /* Issue loan if LTD stays within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function issueLoan(address borrower, uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n require(loanAmount <= getMaxLoanAmountAllowedByLtd(), \"loanAmount must be <= maxLoanAmountAllowedByLtd\");\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState)\n external restrict(\"StabilityBoard\") {\n acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState;\n emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState);\n }\n\n function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n external restrict(\"StabilityBoard\") {\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract\n when it's upgraded.\n Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */\n function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment)\n external restrict(\"StabilityBoard\") {\n totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment);\n totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment);\n emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment);\n }\n\n /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */\n function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves)\n external restrict(\"StabilityBoard\") {\n interestEarnedAccount = newInterestEarnedAccount;\n augmintReserves = newAugmintReserves;\n emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves);\n }\n\n /* User can request to convert their tokens from older AugmintToken versions in 1:1\n transferNotification is called from AugmintToken's transferAndNotify\n Flow for converting old tokens:\n 1) user calls old token contract's transferAndNotify with the amount to convert,\n addressing the new MonetarySupervisor Contract\n 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address\n 3) transferAndNotify calls MonetarySupervisor.transferNotification\n 4) MonetarySupervisor checks if old AugmintToken is permitted\n 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken\n 6) MonetarySupervisor burns old tokens from own balance\n */\n function transferNotification(address from, uint amount, uint /* data, not used */ ) external {\n AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender);\n require(acceptedLegacyAugmintTokens[legacyToken], \"msg.sender must be allowed in acceptedLegacyAugmintTokens\");\n\n legacyToken.burn(amount);\n augmintToken.issueTo(from, amount);\n emit LegacyTokenConverted(msg.sender, from, amount);\n }\n\n /* Helper function for UI.\n Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */\n function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) {\n uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt);\n uint allowedByLtd = getMaxLockAmountAllowedByLtd();\n maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd;\n maxLock = maxLock < minLockAmount ? 0 : maxLock;\n }\n\n /* Helper function for UI.\n Returns max loan amount based on minLoanAmont using LTD params */\n function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) {\n uint allowedByLtd = getMaxLoanAmountAllowedByLtd();\n maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd;\n }\n\n /* returns maximum lockable token amount allowed by LTD params. */\n function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) {\n uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100\n .sub(ltdParams.lockDifferenceLimit));\n allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLockedAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLockedAmount >= totalLoanAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount);\n\n maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n /* returns maximum borrowable token amount allowed by LTD params */\n function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) {\n uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100))\n .div(PERCENT_100);\n allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLoanAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount >= totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount);\n\n maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n}\n" } } } diff --git a/abiniser/deployments/4/PreTokenProxy_DEPLOYS.json b/abiniser/deployments/4/PreTokenProxy_DEPLOYS.json index 11c4d5d6..09bbd813 100644 --- a/abiniser/deployments/4/PreTokenProxy_DEPLOYS.json +++ b/abiniser/deployments/4/PreTokenProxy_DEPLOYS.json @@ -1,20 +1,20 @@ { "contractName": "PreTokenProxy", - "latestAbiHash": "19ab69b650e28b2dd211d3851893f91f", + "latestAbiHash": "dd40c0d39ea8bad8a388522667a84687", "deployedAbis": { - "19ab69b650e28b2dd211d3851893f91f": { - "latestDeployedAddress": "0x0775465245e523b45cc3b41477d44f908e22fede", + "dd40c0d39ea8bad8a388522667a84687": { + "latestDeployedAddress": "0xb7cae2c48f3f34b9696fd290001dea16b299498a", "deployments": { - "0x0775465245e523b45cc3b41477d44f908e22fede": { - "generatedAt": "2018-06-10T08:34:45.034Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.091Z", - "deployTransactionHash": "0xe447e2f5055b6229d9b00d09f55f4153cdcde40a031c3a233e077e2147b19ace", + "0xb7cae2c48f3f34b9696fd290001dea16b299498a": { + "generatedAt": "2018-10-18T13:35:02.452Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.836Z", + "deployTransactionHash": "0x0999dfd76266fbe0226af6d4f62f9b440b3b9098af17193df1d47a9e63ef028a", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "9fd82afe11a8ff7af3e815e243d31647", - "deployedBytecodeHash": "1846d508980d6136e1e81708c995e572", + "bytecodeHash": "5007bce3d0997985a9357d5b1a97103b", + "deployedBytecodeHash": "b5a32ad0b8570f3cd6b7efaef3655911", "sourceHash": "2d172fe41d2b97c827d6dca816138047", "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract PreTokenProxy is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" } diff --git a/abiniser/deployments/4/PreToken_DEPLOYS.json b/abiniser/deployments/4/PreToken_DEPLOYS.json index 845a870b..f363ad3b 100644 --- a/abiniser/deployments/4/PreToken_DEPLOYS.json +++ b/abiniser/deployments/4/PreToken_DEPLOYS.json @@ -1,22 +1,22 @@ { "contractName": "PreToken", - "latestAbiHash": "10eebbb51a771cfd3473475169a569f1", + "latestAbiHash": "7f69e33e7b345c780ac9e43f391437d9", "deployedAbis": { - "10eebbb51a771cfd3473475169a569f1": { - "latestDeployedAddress": "0xfc69b4f2a7de7c68c46a8230ecdf0cff49eb8f1f", + "7f69e33e7b345c780ac9e43f391437d9": { + "latestDeployedAddress": "0xa7b67e7e3e7f1e76e8d799a690f675abeb85c788", "deployments": { - "0xfc69b4f2a7de7c68c46a8230ecdf0cff49eb8f1f": { - "generatedAt": "2018-06-10T08:34:45.077Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.164Z", - "deployTransactionHash": "0xd744577c7abd7c4a6c3b83aec61516c2149a399016fd61a1c1df6ff19d035861", + "0xa7b67e7e3e7f1e76e8d799a690f675abeb85c788": { + "generatedAt": "2018-10-18T13:35:02.470Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.930Z", + "deployTransactionHash": "0x972002c7374514d61b63f0e3bd1e72a3bfca440e2e0dcc58d0fbc96fdcdf83b8", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "1a1d2eee97db1fda81f02d5a4693cccc", - "deployedBytecodeHash": "39ecab521022215d08af346c490a4773", - "sourceHash": "652361fe32b441561edaf8ebd7f70277", - "source": "/* Augmint pretoken contract to record agreements and tokens allocated based on the agreement.\n\n Important: this is NOT an ERC20 token!\n\n PreTokens are non-fungible: agreements can have different conditions (valuationCap and discount)\n and pretokens are not tradable.\n\n Ownership can be transferred if owner wants to change wallet but the whole agreement and\n the total pretoken amount is moved to a new account\n\n PreTokenSigner can (via MultiSig):\n - add agreements and issue pretokens to an agreement\n - change owner of any agreement to handle if an owner lost a private keys\n - burn pretokens from any agreement to fix potential erroneous issuance\n These are known compromises on trustlessness hence all these tokens distributed based on signed agreements and\n preTokens are issued only to a closed group of contributors / team members.\n If despite these something goes wrong then as a last resort a new pretoken contract can be recreated from agreements.\n\n Some ERC20 functions are implemented so agreement owners can see their balances and use transfer in standard wallets.\n Restrictions:\n - only total balance can be transfered - effectively ERC20 transfer used to transfer agreement ownership\n - only agreement holders can transfer\n (i.e. can't transfer 0 amount if have no agreement to avoid polluting logs with Transfer events)\n - transfer is only allowed to accounts without an agreement yet\n - no approval and transferFrom ERC20 functions\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract PreToken is Restricted {\n using SafeMath for uint256;\n\n uint public constant CHUNK_SIZE = 100;\n\n string constant public name = \"Augmint pretokens\"; // solhint-disable-line const-name-snakecase\n string constant public symbol = \"APRE\"; // solhint-disable-line const-name-snakecase\n uint8 constant public decimals = 0; // solhint-disable-line const-name-snakecase\n\n uint public totalSupply;\n\n struct Agreement {\n address owner;\n uint balance;\n uint32 discount; // discountRate in parts per million , ie. 10,000 = 1%\n uint32 valuationCap; // in USD (no decimals)\n }\n\n /* Agreement hash is the SHA-2 (SHA-256) hash of signed agreement document.\n To generate:\n OSX: shasum -a 256 agreement.pdf\n Windows: certUtil -hashfile agreement.pdf SHA256 */\n mapping(address => bytes32) public agreementOwners; // to lookup agrement by owner\n mapping(bytes32 => Agreement) public agreements;\n\n bytes32[] public allAgreements; // all agreements to able to iterate over\n\n event Transfer(address indexed from, address indexed to, uint amount);\n\n event NewAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap);\n\n constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function addAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap)\n external restrict(\"PreTokenSigner\") {\n require(owner != address(0), \"owner must not be 0x0\");\n require(agreementOwners[owner] == 0x0, \"owner must not have an aggrement yet\");\n require(agreementHash != 0x0, \"agreementHash must not be 0x0\");\n require(discount > 0, \"discount must be > 0\");\n require(agreements[agreementHash].discount == 0, \"agreement must not exist yet\");\n\n agreements[agreementHash] = Agreement(owner, 0, discount, valuationCap);\n agreementOwners[owner] = agreementHash;\n allAgreements.push(agreementHash);\n\n emit NewAgreement(owner, agreementHash, discount, valuationCap);\n }\n\n function issueTo(bytes32 agreementHash, uint amount) external restrict(\"PreTokenSigner\") {\n Agreement storage agreement = agreements[agreementHash];\n require(agreement.discount > 0, \"agreement must exist\");\n\n agreement.balance = agreement.balance.add(amount);\n totalSupply = totalSupply.add(amount);\n\n emit Transfer(0x0, agreement.owner, amount);\n }\n\n /* Restricted function to allow pretoken signers to fix incorrect issuance */\n function burnFrom(bytes32 agreementHash, uint amount)\n public restrict(\"PreTokenSigner\") returns (bool) {\n Agreement storage agreement = agreements[agreementHash];\n require(agreement.discount > 0, \"agreement must exist\"); // this is redundant b/c of next requires but be explicit\n require(amount > 0, \"burn amount must be > 0\");\n require(agreement.balance >= amount, \"must not burn more than balance\"); // .sub would revert anyways but emit reason\n\n agreement.balance = agreement.balance.sub(amount);\n totalSupply = totalSupply.sub(amount);\n\n emit Transfer(agreement.owner, 0x0, amount);\n return true;\n }\n\n function balanceOf(address owner) public view returns (uint) {\n return agreements[agreementOwners[owner]].balance;\n }\n\n /* function to transfer agreement ownership to other wallet by owner\n it's in ERC20 form so owners can use standard ERC20 wallet just need to pass full balance as value */\n function transfer(address to, uint amount) public returns (bool) { // solhint-disable-line no-simple-event-func-name\n require(amount == agreements[agreementOwners[msg.sender]].balance, \"must transfer full balance\");\n _transfer(msg.sender, to);\n return true;\n }\n\n /* Restricted function to allow pretoken signers to fix if pretoken owner lost keys */\n function transferAgreement(bytes32 agreementHash, address to)\n public restrict(\"PreTokenSigner\") returns (bool) {\n _transfer(agreements[agreementHash].owner, to);\n return true;\n }\n\n /* private function used by transferAgreement & transfer */\n function _transfer(address from, address to) private {\n Agreement storage agreement = agreements[agreementOwners[from]];\n require(agreementOwners[from] != 0x0, \"from agreement must exists\");\n require(agreementOwners[to] == 0, \"to must not have an agreement\");\n require(to != 0x0, \"must not transfer to 0x0\");\n\n agreement.owner = to;\n\n agreementOwners[to] = agreementOwners[from];\n agreementOwners[from] = 0x0;\n\n emit Transfer(from, to, agreement.balance);\n }\n\n function getAgreementsCount() external view returns (uint agreementsCount) {\n return allAgreements.length;\n }\n\n // UI helper fx - Returns all agreements from offset as\n // [index in allAgreements, account address as uint, balance, agreementHash as uint,\n // discount as uint, valuationCap as uint ]\n function getAllAgreements(uint offset) external view returns(uint[6][CHUNK_SIZE] agreementsResult) {\n\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < allAgreements.length; i++) {\n bytes32 agreementHash = allAgreements[i + offset];\n Agreement storage agreement = agreements[agreementHash];\n\n agreementsResult[i] = [ i + offset, uint(agreement.owner), agreement.balance,\n uint(agreementHash), uint(agreement.discount), uint(agreement.valuationCap)];\n }\n }\n}\n" + "bytecodeHash": "8d7e449258facd1c6fab22b402de6aee", + "deployedBytecodeHash": "bf64976158eb4f8696efd994652e7f49", + "sourceHash": "6cace117c42478e4f5c8cf116bec9a62", + "source": "/* Augmint pretoken contract to record agreements and tokens allocated based on the agreement.\n\n Important: this is NOT an ERC20 token!\n\n PreTokens are non-fungible: agreements can have different conditions (valuationCap and discount)\n and pretokens are not tradable.\n\n Ownership can be transferred if owner wants to change wallet but the whole agreement and\n the total pretoken amount is moved to a new account\n\n PreTokenSigner can (via MultiSig):\n - add agreements and issue pretokens to an agreement\n - change owner of any agreement to handle if an owner lost a private keys\n - burn pretokens from any agreement to fix potential erroneous issuance\n These are known compromises on trustlessness hence all these tokens distributed based on signed agreements and\n preTokens are issued only to a closed group of contributors / team members.\n If despite these something goes wrong then as a last resort a new pretoken contract can be recreated from agreements.\n\n Some ERC20 functions are implemented so agreement owners can see their balances and use transfer in standard wallets.\n Restrictions:\n - only total balance can be transfered - effectively ERC20 transfer used to transfer agreement ownership\n - only agreement holders can transfer\n (i.e. can't transfer 0 amount if have no agreement to avoid polluting logs with Transfer events)\n - transfer is only allowed to accounts without an agreement yet\n - no approval and transferFrom ERC20 functions\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract PreToken is Restricted {\n using SafeMath for uint256;\n\n string constant public name = \"Augmint pretokens\"; // solhint-disable-line const-name-snakecase\n string constant public symbol = \"APRE\"; // solhint-disable-line const-name-snakecase\n uint8 constant public decimals = 0; // solhint-disable-line const-name-snakecase\n\n uint public totalSupply;\n\n struct Agreement {\n address owner;\n uint balance;\n uint32 discount; // discountRate in parts per million , ie. 10,000 = 1%\n uint32 valuationCap; // in USD (no decimals)\n }\n\n /* Agreement hash is the SHA-2 (SHA-256) hash of signed agreement document.\n To generate:\n OSX: shasum -a 256 agreement.pdf\n Windows: certUtil -hashfile agreement.pdf SHA256 */\n mapping(address => bytes32) public agreementOwners; // to lookup agrement by owner\n mapping(bytes32 => Agreement) public agreements;\n\n bytes32[] public allAgreements; // all agreements to able to iterate over\n\n event Transfer(address indexed from, address indexed to, uint amount);\n\n event NewAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap);\n\n constructor(address permissionGranterContract)\n public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function addAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap)\n external restrict(\"PreTokenSigner\") {\n require(owner != address(0), \"owner must not be 0x0\");\n require(agreementOwners[owner] == 0x0, \"owner must not have an aggrement yet\");\n require(agreementHash != 0x0, \"agreementHash must not be 0x0\");\n require(discount > 0, \"discount must be > 0\");\n require(agreements[agreementHash].discount == 0, \"agreement must not exist yet\");\n\n agreements[agreementHash] = Agreement(owner, 0, discount, valuationCap);\n agreementOwners[owner] = agreementHash;\n allAgreements.push(agreementHash);\n\n emit NewAgreement(owner, agreementHash, discount, valuationCap);\n }\n\n function issueTo(bytes32 agreementHash, uint amount) external restrict(\"PreTokenSigner\") {\n Agreement storage agreement = agreements[agreementHash];\n require(agreement.discount > 0, \"agreement must exist\");\n\n agreement.balance = agreement.balance.add(amount);\n totalSupply = totalSupply.add(amount);\n\n emit Transfer(0x0, agreement.owner, amount);\n }\n\n /* Restricted function to allow pretoken signers to fix incorrect issuance */\n function burnFrom(bytes32 agreementHash, uint amount)\n public restrict(\"PreTokenSigner\") returns (bool) {\n Agreement storage agreement = agreements[agreementHash];\n // this is redundant b/c of next requires but be explicit\n require(agreement.discount > 0, \"agreement must exist\");\n require(amount > 0, \"burn amount must be > 0\");\n // .sub would revert anyways but emit reason\n require(agreement.balance >= amount, \"must not burn more than balance\");\n\n agreement.balance = agreement.balance.sub(amount);\n totalSupply = totalSupply.sub(amount);\n\n emit Transfer(agreement.owner, 0x0, amount);\n return true;\n }\n\n function balanceOf(address owner) public view returns (uint) {\n return agreements[agreementOwners[owner]].balance;\n }\n\n /* function to transfer agreement ownership to other wallet by owner\n it's in ERC20 form so owners can use standard ERC20 wallet just need to pass full balance as value */\n function transfer(address to, uint amount) public returns (bool) { // solhint-disable-line no-simple-event-func-name\n require(amount == agreements[agreementOwners[msg.sender]].balance, \"must transfer full balance\");\n _transfer(msg.sender, to);\n return true;\n }\n\n /* Restricted function to allow pretoken signers to fix if pretoken owner lost keys */\n function transferAgreement(bytes32 agreementHash, address to)\n public restrict(\"PreTokenSigner\") returns (bool) {\n _transfer(agreements[agreementHash].owner, to);\n return true;\n }\n\n /* private function used by transferAgreement & transfer */\n function _transfer(address from, address to) private {\n Agreement storage agreement = agreements[agreementOwners[from]];\n require(agreementOwners[from] != 0x0, \"from agreement must exists\");\n require(agreementOwners[to] == 0, \"to must not have an agreement\");\n require(to != 0x0, \"must not transfer to 0x0\");\n\n agreement.owner = to;\n\n agreementOwners[to] = agreementOwners[from];\n agreementOwners[from] = 0x0;\n\n emit Transfer(from, to, agreement.balance);\n }\n\n function getAgreementsCount() external view returns (uint agreementsCount) {\n return allAgreements.length;\n }\n\n // UI helper fx - Returns agreements from as\n // [index in allAgreements, account address as uint, balance, agreementHash as uint,\n // discount as uint, valuationCap as uint ]\n function getAgreements(uint offset, uint16 chunkSize)\n external view returns(uint[6][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), allAgreements.length);\n uint[6][] memory response = new uint[6][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n bytes32 agreementHash = allAgreements[i];\n Agreement storage agreement = agreements[agreementHash];\n\n response[i - offset] = [i, uint(agreement.owner), agreement.balance,\n uint(agreementHash), uint(agreement.discount), uint(agreement.valuationCap)];\n }\n return response;\n }\n}\n" } } } diff --git a/abiniser/deployments/4/Rates_DEPLOYS.json b/abiniser/deployments/4/Rates_DEPLOYS.json index 14330ecc..09818490 100644 --- a/abiniser/deployments/4/Rates_DEPLOYS.json +++ b/abiniser/deployments/4/Rates_DEPLOYS.json @@ -2,81 +2,34 @@ "contractName": "Rates", "latestAbiHash": "73a17ebb0acc71773371c6a8e1c8e6ce", "deployedAbis": { - "aad689098442fe73d35b427a36786f06": { - "latestDeployedAddress": "0x283456269eb05d7c9f4555bc2225fbb300375382", - "deployments": { - "0x591fb852bc42a710afdcdaf622064570deea66d2": { - "generatedAt": "2018-04-25T12:29:07.453Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:28:03.092Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "2c309dbef5cc7635eb4f12dc105f644c", - "deployedBytecodeHash": "f617816c8be26392a73fe690de438219", - "sourceHash": "6aba5d7c578a7c3d328066fa72de1429", - "source": "/*\n Generic symbol / WEI rates contract.\n only callable by trusted price oracles.\n Being regularly called by a price oracle\n TODO: trustless/decentrilezed price Oracle\n TODO: shall we use blockNumber instead of now for lastUpdated?\n TODO: consider if we need storing rates with variable decimals instead of fixed 4\n TODO: could we emit 1 RateChanged event from setMultipleRates (symbols and newrates arrays)?\n*/\npragma solidity 0.4.19;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract Rates is Restricted {\n using SafeMath for uint256;\n\n struct RateInfo {\n uint rate; // how much 1 WEI worth 1 unit , i.e. symbol/ETH rate\n // 0 rate means no rate info available\n uint lastUpdated;\n }\n\n // mapping currency symbol => rate. all rates are stored with 4 decimals. i.e. ETH/EUR = 989.12 then rate = 989,1200\n mapping(bytes32 => RateInfo) public rates;\n\n event RateChanged(bytes32 symbol, uint newRate);\n\n function setRate(bytes32 symbol, uint newRate) external restrict(\"setRate\") {\n rates[symbol] = RateInfo(newRate, now);\n RateChanged(symbol, newRate);\n }\n\n function setMultipleRates(bytes32[] symbols, uint[] newRates) external restrict(\"setRate\") {\n require(symbols.length == newRates.length);\n for (uint256 i = 0; i < symbols.length; i++) {\n rates[symbols[i]] = RateInfo(newRates[i], now);\n RateChanged(symbols[i], newRates[i]);\n }\n }\n\n function convertFromWei(bytes32 bSymbol, uint weiValue) external view returns(uint value) {\n require(rates[bSymbol].rate > 0);\n return weiValue.mul(rates[bSymbol].rate).roundedDiv(1000000000000000000);\n }\n\n function convertToWei(bytes32 bSymbol, uint value) external view returns(uint weiValue) {\n // no require(rates[symbol].rate > 0) needed b/c it will revert with div by zero\n /* TODO: can we make this not loosing max scale? */\n return value.mul(1000000000000000000).roundedDiv(rates[bSymbol].rate);\n }\n\n}\n" - }, - "0x283456269eb05d7c9f4555bc2225fbb300375382": { - "generatedAt": "2018-04-25T12:30:49.023Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:31:58.107Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "b072f2ac9f39bd4e54ec18306443b251", - "deployedBytecodeHash": "94217efb3293a39e7ccfaf54347d3bfe", - "sourceHash": "6aba5d7c578a7c3d328066fa72de1429", - "source": "/*\n Generic symbol / WEI rates contract.\n only callable by trusted price oracles.\n Being regularly called by a price oracle\n TODO: trustless/decentrilezed price Oracle\n TODO: shall we use blockNumber instead of now for lastUpdated?\n TODO: consider if we need storing rates with variable decimals instead of fixed 4\n TODO: could we emit 1 RateChanged event from setMultipleRates (symbols and newrates arrays)?\n*/\npragma solidity 0.4.19;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract Rates is Restricted {\n using SafeMath for uint256;\n\n struct RateInfo {\n uint rate; // how much 1 WEI worth 1 unit , i.e. symbol/ETH rate\n // 0 rate means no rate info available\n uint lastUpdated;\n }\n\n // mapping currency symbol => rate. all rates are stored with 4 decimals. i.e. ETH/EUR = 989.12 then rate = 989,1200\n mapping(bytes32 => RateInfo) public rates;\n\n event RateChanged(bytes32 symbol, uint newRate);\n\n function setRate(bytes32 symbol, uint newRate) external restrict(\"setRate\") {\n rates[symbol] = RateInfo(newRate, now);\n RateChanged(symbol, newRate);\n }\n\n function setMultipleRates(bytes32[] symbols, uint[] newRates) external restrict(\"setRate\") {\n require(symbols.length == newRates.length);\n for (uint256 i = 0; i < symbols.length; i++) {\n rates[symbols[i]] = RateInfo(newRates[i], now);\n RateChanged(symbols[i], newRates[i]);\n }\n }\n\n function convertFromWei(bytes32 bSymbol, uint weiValue) external view returns(uint value) {\n require(rates[bSymbol].rate > 0);\n return weiValue.mul(rates[bSymbol].rate).roundedDiv(1000000000000000000);\n }\n\n function convertToWei(bytes32 bSymbol, uint value) external view returns(uint weiValue) {\n // no require(rates[symbol].rate > 0) needed b/c it will revert with div by zero\n /* TODO: can we make this not loosing max scale? */\n return value.mul(1000000000000000000).roundedDiv(rates[bSymbol].rate);\n }\n\n}\n" - } - } - }, - "cc8bc64cd780f047eca819e6cd3b8af9": { - "latestDeployedAddress": "0xca8100fccb479516a5b30f8bc5daea09fb7a7473", - "deployments": { - "0xca8100fccb479516a5b30f8bc5daea09fb7a7473": { - "generatedAt": "2018-04-25T12:31:28.978Z", - "truffleContractFileUpdatedAt": "2018-04-20T18:21:38.645Z", - "deployTransactionHash": "0x50401a2e7d1292cd9360f11d38f10453233bba4e3e89b20b94f4e108759ca610", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "7b3cb84bdbfbe54d0c253744ccc86bd9", - "deployedBytecodeHash": "36714b840505a1bedac90a82a36e514c", - "sourceHash": "e9dda67ca678fd3a4700e8970b50acd3", - "source": "/*\n Generic symbol / WEI rates contract.\n only callable by trusted price oracles.\n Being regularly called by a price oracle\n TODO: trustless/decentrilezed price Oracle\n TODO: shall we use blockNumber instead of now for lastUpdated?\n TODO: consider if we need storing rates with variable decimals instead of fixed 4\n TODO: could we emit 1 RateChanged event from setMultipleRates (symbols and newrates arrays)?\n*/\npragma solidity ^0.4.23;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract Rates is Restricted {\n using SafeMath for uint256;\n\n struct RateInfo {\n uint rate; // how much 1 WEI worth 1 unit , i.e. symbol/ETH rate\n // 0 rate means no rate info available\n uint lastUpdated;\n }\n\n // mapping currency symbol => rate. all rates are stored with 4 decimals. i.e. ETH/EUR = 989.12 then rate = 989,1200\n mapping(bytes32 => RateInfo) public rates;\n\n event RateChanged(bytes32 symbol, uint newRate);\n\n function setRate(bytes32 symbol, uint newRate) external restrict(\"setRate\") {\n rates[symbol] = RateInfo(newRate, now);\n emit RateChanged(symbol, newRate);\n }\n\n function setMultipleRates(bytes32[] symbols, uint[] newRates) external restrict(\"setRate\") {\n require(symbols.length == newRates.length, \"symobls and newRates lengths must be equal\");\n for (uint256 i = 0; i < symbols.length; i++) {\n rates[symbols[i]] = RateInfo(newRates[i], now);\n emit RateChanged(symbols[i], newRates[i]);\n }\n }\n\n function convertFromWei(bytes32 bSymbol, uint weiValue) external view returns(uint value) {\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n return weiValue.mul(rates[bSymbol].rate).roundedDiv(1000000000000000000);\n }\n\n function convertToWei(bytes32 bSymbol, uint value) external view returns(uint weiValue) {\n // next line would revert with div by zero but require to emit reason\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n /* TODO: can we make this not loosing max scale? */\n return value.mul(1000000000000000000).roundedDiv(rates[bSymbol].rate);\n }\n\n}\n" - } - } - }, "73a17ebb0acc71773371c6a8e1c8e6ce": { - "latestDeployedAddress": "0xf25638c7d37fca0cbc124b3925ece156a20e1f03", + "latestDeployedAddress": "0xee8c7a3e99945a5207dca026504d67527125da9c", "deployments": { - "0x582971c64de4b5e6db2d95cf8103cff7f0fdff31": { - "generatedAt": "2018-06-04T12:49:52.468Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.436Z", - "deployTransactionHash": "0x429aef23ff41e040ef4f75eb4c97a276c652a15e17987d9ddff4ebaa132bf529", + "0xdfa3a0aeb9645a55b684cb3ace8c42d018405bda": { + "generatedAt": "2018-10-18T13:35:02.334Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.909Z", + "deployTransactionHash": "0xcdfc636cb95b245a8e7fb30a8d5a2be26fc2f781f73cd0ef33d82f271b684613", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "d2d57b85d6be010ac9d10779e3ebcd99", - "deployedBytecodeHash": "06c97777691fda8c2f11cb9e87babf8e", - "sourceHash": "391baf71d15b5346000e16e5785100cd", - "source": "/*\n Generic symbol / WEI rates contract.\n only callable by trusted price oracles.\n Being regularly called by a price oracle\n TODO: trustless/decentrilezed price Oracle\n TODO: shall we use blockNumber instead of now for lastUpdated?\n TODO: consider if we need storing rates with variable decimals instead of fixed 4\n TODO: could we emit 1 RateChanged event from setMultipleRates (symbols and newrates arrays)?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract Rates is Restricted {\n using SafeMath for uint256;\n\n struct RateInfo {\n uint rate; // how much 1 WEI worth 1 unit , i.e. symbol/ETH rate\n // 0 rate means no rate info available\n uint lastUpdated;\n }\n\n // mapping currency symbol => rate. all rates are stored with 4 decimals. i.e. ETH/EUR = 989.12 then rate = 989,1200\n mapping(bytes32 => RateInfo) public rates;\n\n event RateChanged(bytes32 symbol, uint newRate);\n\n constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function setRate(bytes32 symbol, uint newRate) external restrict(\"setRate\") {\n rates[symbol] = RateInfo(newRate, now);\n emit RateChanged(symbol, newRate);\n }\n\n function setMultipleRates(bytes32[] symbols, uint[] newRates) external restrict(\"setRate\") {\n require(symbols.length == newRates.length, \"symobls and newRates lengths must be equal\");\n for (uint256 i = 0; i < symbols.length; i++) {\n rates[symbols[i]] = RateInfo(newRates[i], now);\n emit RateChanged(symbols[i], newRates[i]);\n }\n }\n\n function convertFromWei(bytes32 bSymbol, uint weiValue) external view returns(uint value) {\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n return weiValue.mul(rates[bSymbol].rate).roundedDiv(1000000000000000000);\n }\n\n function convertToWei(bytes32 bSymbol, uint value) external view returns(uint weiValue) {\n // next line would revert with div by zero but require to emit reason\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n /* TODO: can we make this not loosing max scale? */\n return value.mul(1000000000000000000).roundedDiv(rates[bSymbol].rate);\n }\n\n}\n" + "bytecodeHash": "be17116585b9b88d60fbe06a5499b6dc", + "deployedBytecodeHash": "0f403183577dac202159e32b1c8c9f44", + "sourceHash": "c65f6945fead6118910fccc8bca7494c", + "source": "/*\n Generic symbol / WEI rates contract.\n only callable by trusted price oracles.\n Being regularly called by a price oracle\n TODO: trustless/decentrilezed price Oracle\n TODO: shall we use blockNumber instead of now for lastUpdated?\n TODO: consider if we need storing rates with variable decimals instead of fixed 4\n TODO: could we emit 1 RateChanged event from setMultipleRates (symbols and newrates arrays)?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract Rates is Restricted {\n using SafeMath for uint256;\n\n struct RateInfo {\n uint rate; // how much 1 WEI worth 1 unit , i.e. symbol/ETH rate\n // 0 rate means no rate info available\n uint lastUpdated;\n }\n\n // mapping currency symbol => rate. all rates are stored with 2 decimals. i.e. EUR/ETH = 989.12 then rate = 98912\n mapping(bytes32 => RateInfo) public rates;\n\n event RateChanged(bytes32 symbol, uint newRate);\n\n constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function setRate(bytes32 symbol, uint newRate) external restrict(\"RatesFeeder\") {\n rates[symbol] = RateInfo(newRate, now);\n emit RateChanged(symbol, newRate);\n }\n\n function setMultipleRates(bytes32[] symbols, uint[] newRates) external restrict(\"RatesFeeder\") {\n require(symbols.length == newRates.length, \"symobls and newRates lengths must be equal\");\n for (uint256 i = 0; i < symbols.length; i++) {\n rates[symbols[i]] = RateInfo(newRates[i], now);\n emit RateChanged(symbols[i], newRates[i]);\n }\n }\n\n function convertFromWei(bytes32 bSymbol, uint weiValue) external view returns(uint value) {\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n return weiValue.mul(rates[bSymbol].rate).roundedDiv(1000000000000000000);\n }\n\n function convertToWei(bytes32 bSymbol, uint value) external view returns(uint weiValue) {\n // next line would revert with div by zero but require to emit reason\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n /* TODO: can we make this not loosing max scale? */\n return value.mul(1000000000000000000).roundedDiv(rates[bSymbol].rate);\n }\n\n}\n" }, - "0xf25638c7d37fca0cbc124b3925ece156a20e1f03": { - "generatedAt": "2018-06-10T08:34:44.799Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.109Z", - "deployTransactionHash": "0x5539d4225ad5c452185ed1541e2c018bfc1d938a4ebf49f184c9da7ee2411395", + "0xee8c7a3e99945a5207dca026504d67527125da9c": { + "generatedAt": "2018-10-29T15:52:43.242Z", + "truffleContractFileUpdatedAt": "2018-10-19T15:49:10.755Z", + "deployTransactionHash": "0x300a82bb283510c9a429d6ce81e22586f0c42c9caf9445633a72e2424968967f", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "b2bf3f97147e9144c7103442be20e58a", - "deployedBytecodeHash": "6a3a4ec8c050710692adaa9f97d09bb6", - "sourceHash": "d71ec203e7ee6ed376feeb17e5df7966", - "source": "/*\n Generic symbol / WEI rates contract.\n only callable by trusted price oracles.\n Being regularly called by a price oracle\n TODO: trustless/decentrilezed price Oracle\n TODO: shall we use blockNumber instead of now for lastUpdated?\n TODO: consider if we need storing rates with variable decimals instead of fixed 4\n TODO: could we emit 1 RateChanged event from setMultipleRates (symbols and newrates arrays)?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract Rates is Restricted {\n using SafeMath for uint256;\n\n struct RateInfo {\n uint rate; // how much 1 WEI worth 1 unit , i.e. symbol/ETH rate\n // 0 rate means no rate info available\n uint lastUpdated;\n }\n\n // mapping currency symbol => rate. all rates are stored with 4 decimals. i.e. ETH/EUR = 989.12 then rate = 989,1200\n mapping(bytes32 => RateInfo) public rates;\n\n event RateChanged(bytes32 symbol, uint newRate);\n\n constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function setRate(bytes32 symbol, uint newRate) external restrict(\"RatesFeeder\") {\n rates[symbol] = RateInfo(newRate, now);\n emit RateChanged(symbol, newRate);\n }\n\n function setMultipleRates(bytes32[] symbols, uint[] newRates) external restrict(\"RatesFeeder\") {\n require(symbols.length == newRates.length, \"symobls and newRates lengths must be equal\");\n for (uint256 i = 0; i < symbols.length; i++) {\n rates[symbols[i]] = RateInfo(newRates[i], now);\n emit RateChanged(symbols[i], newRates[i]);\n }\n }\n\n function convertFromWei(bytes32 bSymbol, uint weiValue) external view returns(uint value) {\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n return weiValue.mul(rates[bSymbol].rate).roundedDiv(1000000000000000000);\n }\n\n function convertToWei(bytes32 bSymbol, uint value) external view returns(uint weiValue) {\n // next line would revert with div by zero but require to emit reason\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n /* TODO: can we make this not loosing max scale? */\n return value.mul(1000000000000000000).roundedDiv(rates[bSymbol].rate);\n }\n\n}\n" + "bytecodeHash": "be17116585b9b88d60fbe06a5499b6dc", + "deployedBytecodeHash": "0f403183577dac202159e32b1c8c9f44", + "sourceHash": "c65f6945fead6118910fccc8bca7494c", + "source": "/*\n Generic symbol / WEI rates contract.\n only callable by trusted price oracles.\n Being regularly called by a price oracle\n TODO: trustless/decentrilezed price Oracle\n TODO: shall we use blockNumber instead of now for lastUpdated?\n TODO: consider if we need storing rates with variable decimals instead of fixed 4\n TODO: could we emit 1 RateChanged event from setMultipleRates (symbols and newrates arrays)?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract Rates is Restricted {\n using SafeMath for uint256;\n\n struct RateInfo {\n uint rate; // how much 1 WEI worth 1 unit , i.e. symbol/ETH rate\n // 0 rate means no rate info available\n uint lastUpdated;\n }\n\n // mapping currency symbol => rate. all rates are stored with 2 decimals. i.e. EUR/ETH = 989.12 then rate = 98912\n mapping(bytes32 => RateInfo) public rates;\n\n event RateChanged(bytes32 symbol, uint newRate);\n\n constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function setRate(bytes32 symbol, uint newRate) external restrict(\"RatesFeeder\") {\n rates[symbol] = RateInfo(newRate, now);\n emit RateChanged(symbol, newRate);\n }\n\n function setMultipleRates(bytes32[] symbols, uint[] newRates) external restrict(\"RatesFeeder\") {\n require(symbols.length == newRates.length, \"symobls and newRates lengths must be equal\");\n for (uint256 i = 0; i < symbols.length; i++) {\n rates[symbols[i]] = RateInfo(newRates[i], now);\n emit RateChanged(symbols[i], newRates[i]);\n }\n }\n\n function convertFromWei(bytes32 bSymbol, uint weiValue) external view returns(uint value) {\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n return weiValue.mul(rates[bSymbol].rate).roundedDiv(1000000000000000000);\n }\n\n function convertToWei(bytes32 bSymbol, uint value) external view returns(uint weiValue) {\n // next line would revert with div by zero but require to emit reason\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n /* TODO: can we make this not loosing max scale? */\n return value.mul(1000000000000000000).roundedDiv(rates[bSymbol].rate);\n }\n\n}\n" } } } diff --git a/abiniser/deployments/4/SafeMath_DEPLOYS.json b/abiniser/deployments/4/SafeMath_DEPLOYS.json deleted file mode 100644 index 039e7f86..00000000 --- a/abiniser/deployments/4/SafeMath_DEPLOYS.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "contractName": "SafeMath", - "latestAbiHash": "d751713988987e9331980363e24189ce", - "deployedAbis": { - "d751713988987e9331980363e24189ce": { - "latestDeployedAddress": "0x1a2b65efd1e45ad49b6d5c5c48089ebb6d987c05", - "deployments": { - "0x0cbd4a1475b62fa5b1def3c864d031b0001e3c5b": { - "generatedAt": "2018-04-25T12:29:07.427Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:31:03.068Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "f9302c2a25cd095142e68aae6ff44cd5", - "deployedBytecodeHash": "e2996d9682fd6b73836fbcf2be0c44bd", - "sourceHash": "494c9e0684ae0df336dbb0f1daa07b27", - "source": "/**\n* @title SafeMath\n* @dev Math operations with safety checks that throw on error\n\n TODO: check against ds-math: https://blog.dapphub.com/ds-math/\n TODO: move roundedDiv to a sep lib? (eg. Math.sol)\n*/\npragma solidity 0.4.19;\n\n\nlibrary SafeMath {\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a * b;\n require(a == 0 || c / a == b);\n return c;\n }\n\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n // require(b > 0); // Solidity automatically throws when dividing by 0\n uint256 c = a / b;\n // require(a == b * c + a % b); // There is no case in which this doesn't hold\n return c;\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a);\n return a - b;\n }\n\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a);\n return c;\n }\n\n function roundedDiv(uint a, uint b) internal pure returns (uint256) {\n // require(b > 0); // Solidity automatically throws when dividing by 0\n uint256 z = a / b;\n if (a % b >= b / 2) {\n z++; // no need for safe add b/c it can happen only if we divided the input\n }\n return z;\n }\n}\n" - }, - "0x0485aa36d1743a7e8c2d04421c9d5c7d401d5795": { - "generatedAt": "2018-04-25T12:30:49.008Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:35:58.096Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "d0ddb0ad1c84ed0576cb1f397cc5aac6", - "deployedBytecodeHash": "01962f146b796909675e431df6fb1dbb", - "sourceHash": "494c9e0684ae0df336dbb0f1daa07b27", - "source": "/**\n* @title SafeMath\n* @dev Math operations with safety checks that throw on error\n\n TODO: check against ds-math: https://blog.dapphub.com/ds-math/\n TODO: move roundedDiv to a sep lib? (eg. Math.sol)\n*/\npragma solidity 0.4.19;\n\n\nlibrary SafeMath {\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a * b;\n require(a == 0 || c / a == b);\n return c;\n }\n\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n // require(b > 0); // Solidity automatically throws when dividing by 0\n uint256 c = a / b;\n // require(a == b * c + a % b); // There is no case in which this doesn't hold\n return c;\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a);\n return a - b;\n }\n\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a);\n return c;\n }\n\n function roundedDiv(uint a, uint b) internal pure returns (uint256) {\n // require(b > 0); // Solidity automatically throws when dividing by 0\n uint256 z = a / b;\n if (a % b >= b / 2) {\n z++; // no need for safe add b/c it can happen only if we divided the input\n }\n return z;\n }\n}\n" - }, - "0x1a2b65efd1e45ad49b6d5c5c48089ebb6d987c05": { - "generatedAt": "2018-04-25T12:31:28.938Z", - "truffleContractFileUpdatedAt": "2018-04-20T18:25:08.412Z", - "deployTransactionHash": "0x9e9532fc955991639331472822eb35b7f46537de2025bfc363c7fb86f1d65c13", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "5c02a412ee11dc181e23608b85b249b9", - "deployedBytecodeHash": "d808bf41b73524260974a832a9735da9", - "sourceHash": "f07bc306764da6ef496a297a30a18531", - "source": "/**\n* @title SafeMath\n* @dev Math operations with safety checks that throw on error\n\n TODO: check against ds-math: https://blog.dapphub.com/ds-math/\n TODO: move roundedDiv to a sep lib? (eg. Math.sol)\n*/\npragma solidity ^0.4.23;\n\n\nlibrary SafeMath {\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a * b;\n require(a == 0 || c / a == b, \"mul overflow\");\n return c;\n }\n\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"div by 0\"); // Solidity automatically throws for div by 0 but require to emit reason\n uint256 c = a / b;\n // require(a == b * c + a % b); // There is no case in which this doesn't hold\n return c;\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"sub underflow\");\n return a - b;\n }\n\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"add overflow\");\n return c;\n }\n\n function roundedDiv(uint a, uint b) internal pure returns (uint256) {\n require(b > 0, \"div by 0\"); // Solidity automatically throws for div by 0 but require to emit reason\n uint256 z = a / b;\n if (a % b >= b / 2) {\n z++; // no need for safe add b/c it can happen only if we divided the input\n }\n return z;\n }\n}\n" - } - } - } - } -} \ No newline at end of file diff --git a/abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json b/abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json index 9df93a3a..b720d02d 100644 --- a/abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json +++ b/abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json @@ -1,20 +1,33 @@ { "contractName": "StabilityBoardProxy", - "latestAbiHash": "19ab69b650e28b2dd211d3851893f91f", + "latestAbiHash": "dd40c0d39ea8bad8a388522667a84687", "deployedAbis": { - "19ab69b650e28b2dd211d3851893f91f": { - "latestDeployedAddress": "0x44022c28766652ec5901790e53ced7a79a19c10a", + "dd40c0d39ea8bad8a388522667a84687": { + "latestDeployedAddress": "0xa612de13b629a1ff790c1f4e41d0422d2bb50a30", "deployments": { - "0x44022c28766652ec5901790e53ced7a79a19c10a": { - "generatedAt": "2018-06-10T08:34:45.025Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.100Z", - "deployTransactionHash": "0x13def497d360e16836ae12d65a5e5cef471778b9378cfab04f7968c2ae90512e", + "0x50d281c28846576eaaf679ab6f3baac52b776e72": { + "generatedAt": "2018-10-18T13:35:02.447Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.835Z", + "deployTransactionHash": "0x3a64beffca962812a3ee1b5abb1eeba7f10d2632ba817195d2727bad6a1e83b0", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "56131f88a46fe46a487da0a9bae573fc", - "deployedBytecodeHash": "2996d609801f2039ae49c17ac8bcad92", + "bytecodeHash": "4f899546765577ad2e325da53c3e7179", + "deployedBytecodeHash": "a5f3dd7878e556db538c1206827e5959", + "sourceHash": "4d60c55b8e4009873db939b37558d9dc", + "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract StabilityBoardProxy is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" + }, + "0xa612de13b629a1ff790c1f4e41d0422d2bb50a30": { + "generatedAt": "2018-10-29T15:52:43.339Z", + "truffleContractFileUpdatedAt": "2018-10-19T15:49:10.704Z", + "deployTransactionHash": "0x845cfad1fef968fa69e03efa40f81b014b7bddaaf6574dd9cc6a9b337b73694c", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "4f899546765577ad2e325da53c3e7179", + "deployedBytecodeHash": "a5f3dd7878e556db538c1206827e5959", "sourceHash": "4d60c55b8e4009873db939b37558d9dc", "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract StabilityBoardProxy is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" } diff --git a/abiniser/deployments/4/StabilityBoardSigner_DEPLOYS.json b/abiniser/deployments/4/StabilityBoardSigner_DEPLOYS.json deleted file mode 100644 index a9beea8b..00000000 --- a/abiniser/deployments/4/StabilityBoardSigner_DEPLOYS.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "contractName": "StabilityBoardSigner", - "latestAbiHash": "19ab69b650e28b2dd211d3851893f91f", - "deployedAbis": { - "19ab69b650e28b2dd211d3851893f91f": { - "latestDeployedAddress": "0xe733dde64ce5b9930dff8f97e5615635fd4095fb", - "deployments": { - "0xe733dde64ce5b9930dff8f97e5615635fd4095fb": { - "generatedAt": "2018-06-04T12:49:52.718Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.418Z", - "deployTransactionHash": "0x41c284c979b043d91bbc9caebd5defd6bb6a08bca796b7077cb74d5fe25c1657", - "compiler": { - "name": "solc", - "version": "0.4.24+commit.e67f0147.Emscripten.clang" - }, - "bytecodeHash": "0e2f8e783790013f07705a1cecd5f703", - "deployedBytecodeHash": "9a38fc566f79a4d2fd6e6fa64b406b1b", - "sourceHash": "1c9e1e3dd1979663773a97ac32a067c0", - "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract StabilityBoardSigner is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" - } - } - } - } -} \ No newline at end of file diff --git a/abiniser/deployments/4/TokenAEur_DEPLOYS.json b/abiniser/deployments/4/TokenAEur_DEPLOYS.json index 7fc8540f..11b5c3c0 100644 --- a/abiniser/deployments/4/TokenAEur_DEPLOYS.json +++ b/abiniser/deployments/4/TokenAEur_DEPLOYS.json @@ -1,110 +1,35 @@ { "contractName": "TokenAEur", - "latestAbiHash": "9aa81519ec45a52d3f8f1a1a83d25c74", + "latestAbiHash": "2ea91d34a7bfefc8f38ef0e8a5ae24a5", "deployedAbis": { - "27721a2c77dc40da7639abd46791c3d7": { - "latestDeployedAddress": "0x95aa79d7410eb60f49bfd570b445836d402bd7b1", + "2ea91d34a7bfefc8f38ef0e8a5ae24a5": { + "latestDeployedAddress": "0x79065a165ec09e6a89d584a14872802717fe12a3", "deployments": { - "0x95aa79d7410eb60f49bfd570b445836d402bd7b1": { - "generatedAt": "2018-04-25T12:29:07.543Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:31:03.067Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "9c7803268a74b93337c591b93c5df7cd", - "deployedBytecodeHash": "4c8e7c0e4eceb0cf659bdffd7cb68f48", - "sourceHash": "f8f534b0f0f4314bb7c994451860d3ae", - "source": "/* Augmint Crypto Euro token (ACE) implementation */\npragma solidity 0.4.19;\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n function TokenAEur(address _feeAccount, uint _transferFeePt, uint _transferFeeMin, uint _transferFeeMax)\n public AugmintToken(\"Augmint Crypto Euro\", \"A-EUR\", \"EUR\", 4, _feeAccount,\n _transferFeePt, _transferFeeMin, _transferFeeMax )\n {} // solhint-disable-line no-empty-blocks\n\n}\n" - } - } - }, - "1d30184837b8c27bcac847509ab146a1": { - "latestDeployedAddress": "0xa35d9de06895a3a2e7ecae26654b88fe71c179ea", - "deployments": { - "0xa35d9de06895a3a2e7ecae26654b88fe71c179ea": { - "generatedAt": "2018-04-25T12:30:49.280Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:36:28.112Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "6d5fefd571498d9dee8ed2325f0f25de", - "deployedBytecodeHash": "e6d94e42be358d534f5c0d5d4b9b2d60", - "sourceHash": "8fdbab94c89af22962cf36a54a5c9c33", - "source": "/* Augmint Crypto Euro token (ACE) implementation */\npragma solidity 0.4.19;\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n function TokenAEur(address _feeAccount, uint _transferFeePt, uint _transferFeeMin, uint _transferFeeMax)\n public AugmintToken(\"Augmint Crypto Euro\", \"AEUR\", \"EUR\", 2, _feeAccount,\n _transferFeePt, _transferFeeMin, _transferFeeMax )\n {} // solhint-disable-line no-empty-blocks\n\n}\n" - } - } - }, - "d7dd02520f2d92b2ca237f066cf2488d": { - "latestDeployedAddress": "0x135893f1a6b3037bb45182841f18f69327366992", - "deployments": { - "0x135893f1a6b3037bb45182841f18f69327366992": { - "generatedAt": "2018-04-25T12:31:29.087Z", - "truffleContractFileUpdatedAt": "2018-04-20T18:26:53.513Z", - "deployTransactionHash": "0x90def86d4959da24e03584f17817c5c05c6f382e4fc1337f0f9dc79dda50f1b5", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "ced60db09eb71a444fbd40650541230d", - "deployedBytecodeHash": "8df8ab5bffd0bfae417f91cd6256cb15", - "sourceHash": "61dded7836f4431e621382340f32670c", - "source": "/* Augmint Crypto Euro token (ACE) implementation */\npragma solidity ^0.4.23;\nimport \"./interfaces/TransferFeeInterface.sol\";\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n constructor(TransferFeeInterface _feeAccount)\n public AugmintToken(\"Augmint Crypto Euro\", \"AEUR\", \"EUR\", 2, _feeAccount)\n {} // solhint-disable-line no-empty-blocks\n\n}\n" - } - } - }, - "4b49e7e6d1a9a2de81a4d2d088acbc04": { - "latestDeployedAddress": "0x6c90c10d7a33815c2baeed66ee8b848f1d95268e", - "deployments": { - "0x6c90c10d7a33815c2baeed66ee8b848f1d95268e": { - "generatedAt": "2018-05-12T01:34:38.456Z", - "truffleContractFileUpdatedAt": "2018-05-12T01:30:50.031Z", - "deployTransactionHash": "0xf45e9817fca468b5438d7a00a6461fd47e14cf04f1bb4b36ccc7302284ec39c5", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "042675fc70cfed8762b1e7de8d15799f", - "deployedBytecodeHash": "03b0c0d8c49d83af34516ac82bc0b2a9", - "sourceHash": "61dded7836f4431e621382340f32670c", - "source": "/* Augmint Crypto Euro token (ACE) implementation */\npragma solidity ^0.4.23;\nimport \"./interfaces/TransferFeeInterface.sol\";\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n constructor(TransferFeeInterface _feeAccount)\n public AugmintToken(\"Augmint Crypto Euro\", \"AEUR\", \"EUR\", 2, _feeAccount)\n {} // solhint-disable-line no-empty-blocks\n\n}\n" - } - } - }, - "962b41ca272a86b1f556fc47e0f7954f": { - "latestDeployedAddress": "0x0da47c59d0c3166ddc2984d72b8c8fac82275056", - "deployments": { - "0x0da47c59d0c3166ddc2984d72b8c8fac82275056": { - "generatedAt": "2018-06-04T12:49:52.520Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.456Z", - "deployTransactionHash": "0x310e7319d0c6c1809656d2d657c68d12d6231e428d488280410dfc18fd720eca", + "0x0557183334edc23a666201edc6b0aa2787e2ad3f": { + "generatedAt": "2018-10-18T13:35:02.366Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.871Z", + "deployTransactionHash": "0x4d8b7e1eff4e7237355399cf154526e73c7716887173a0cedb81fb0434613507", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "699a73688b7440a29431472c956c52ef", - "deployedBytecodeHash": "dc1bc9565dbd19b63734454b17413e3f", - "sourceHash": "b0939983ed3409574d7f6dfeeaa213c3", - "source": "/* Augmint Crypto Euro token (ACE) implementation */\npragma solidity 0.4.24;\nimport \"./interfaces/TransferFeeInterface.sol\";\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n constructor(address _permissionGranterContract, TransferFeeInterface _feeAccount)\n public AugmintToken(_permissionGranterContract, \"Augmint Crypto Euro\", \"AEUR\", \"EUR\", 2, _feeAccount)\n {} // solhint-disable-line no-empty-blocks\n\n}\n" - } - } - }, - "9aa81519ec45a52d3f8f1a1a83d25c74": { - "latestDeployedAddress": "0xe54f61d6eadf03b658b3354bbd80cf563feca34c", - "deployments": { - "0xe54f61d6eadf03b658b3354bbd80cf563feca34c": { - "generatedAt": "2018-06-10T08:34:44.854Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.548Z", - "deployTransactionHash": "0x6ca8f6dc68d764b67dbfc840eff6fc702551706855ac9873ebc2a97a37a3674c", + "bytecodeHash": "0398a39cdab3b394103910ea6b28eef7", + "deployedBytecodeHash": "2916088286d725e884630bc95fc19dbf", + "sourceHash": "04025a37ea64acbc6f0ea2ec8a6f3e4d", + "source": "/* Augmint Euro token (A-EUR) implementation */\npragma solidity 0.4.24;\nimport \"./interfaces/TransferFeeInterface.sol\";\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n constructor(address _permissionGranterContract, TransferFeeInterface _feeAccount)\n public AugmintToken(_permissionGranterContract, \"Augmint Euro\", \"AEUR\", \"EUR\", 2, _feeAccount)\n {} // solhint-disable-line no-empty-blocks\n\n}\n" + }, + "0x79065a165ec09e6a89d584a14872802717fe12a3": { + "generatedAt": "2018-10-29T15:52:43.268Z", + "truffleContractFileUpdatedAt": "2018-10-19T15:49:10.721Z", + "deployTransactionHash": "0x81e6c73a51dfcff2ca2424db2f08c13692416bb52f028de012ac631e97d0b631", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "3abfdb182b58136a9dcb25c1ece5ed54", - "deployedBytecodeHash": "c3636b199ceefdd5deb396f099915a87", - "sourceHash": "20cc69065a6935fc7519147f3fc5fa2c", - "source": "/* Augmint Crypto Euro token (A-EUR) implementation */\npragma solidity 0.4.24;\nimport \"./interfaces/TransferFeeInterface.sol\";\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n constructor(address _permissionGranterContract, TransferFeeInterface _feeAccount)\n public AugmintToken(_permissionGranterContract, \"Augmint Crypto Euro\", \"AEUR\", \"EUR\", 2, _feeAccount)\n {} // solhint-disable-line no-empty-blocks\n\n}\n" + "bytecodeHash": "0398a39cdab3b394103910ea6b28eef7", + "deployedBytecodeHash": "2916088286d725e884630bc95fc19dbf", + "sourceHash": "04025a37ea64acbc6f0ea2ec8a6f3e4d", + "source": "/* Augmint Euro token (A-EUR) implementation */\npragma solidity 0.4.24;\nimport \"./interfaces/TransferFeeInterface.sol\";\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n constructor(address _permissionGranterContract, TransferFeeInterface _feeAccount)\n public AugmintToken(_permissionGranterContract, \"Augmint Euro\", \"AEUR\", \"EUR\", 2, _feeAccount)\n {} // solhint-disable-line no-empty-blocks\n\n}\n" } } } diff --git a/abiniser/deployments/999/AugmintReserves_DEPLOYS.json b/abiniser/deployments/999/AugmintReserves_DEPLOYS.json index e8fae047..e5c7fb7b 100644 --- a/abiniser/deployments/999/AugmintReserves_DEPLOYS.json +++ b/abiniser/deployments/999/AugmintReserves_DEPLOYS.json @@ -1,83 +1,22 @@ { "contractName": "AugmintReserves", - "latestAbiHash": "fe74b7986dafb00f221486e790fc70ec", + "latestAbiHash": "024b81d1a1f75241167a8a0f6e62326f", "deployedAbis": { - "dfbca9f4d0da7a3517b2832dc1c04d9a": { - "latestDeployedAddress": "0xb0a2a8e846b66c7384f52635cecef5280f766c8b", - "deployments": { - "0xb0a2a8e846b66c7384f52635cecef5280f766c8b": { - "generatedAt": "2018-04-25T12:30:49.066Z", - "truffleContractFileUpdatedAt": "2018-02-27T07:25:57.853Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.Emscripten.clang" - }, - "bytecodeHash": "141a9efe96eafc3443a43c64651fccbe", - "deployedBytecodeHash": "efad357d73a7669e916fb1efce5648a4", - "sourceHash": "74ed728bb0a86f1bfb854c62b2c39633", - "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or MonetaryBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.19;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is SystemAccount {\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n function burn(AugmintTokenInterface augmintToken, uint amount) external restrict(\"MonetarySupervisorContract\") {\n augmintToken.burn(amount);\n }\n\n}\n" - } - } - }, - "33995f203f6c629e9916d82dd78e875f": { - "latestDeployedAddress": "0x3e04292890afb91585d5ebfc1d7b43443e780122", - "deployments": { - "0x56ad79460db45ac29cb672b1914e30c5ffa4e38e": { - "generatedAt": "2018-04-26T01:54:21.104Z", - "truffleContractFileUpdatedAt": "2018-04-26T01:54:07.621Z", - "deployTransactionHash": "0xe2ce1261d55f43164e99807cb981e7c9043787c02606a0020d70080708ff367f", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "87789807f6218a256d40b300869a717e", - "deployedBytecodeHash": "b8d26b4b6589916289f69078a09536aa", - "sourceHash": "c3fd200d4510ea1b3d7c6c7ae04683b9", - "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or MonetaryBoard or MonetarySupervisor)\n\n */\n\npragma solidity ^0.4.23;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is SystemAccount {\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n function burn(AugmintTokenInterface augmintToken, uint amount) external restrict(\"MonetarySupervisorContract\") {\n augmintToken.burn(amount);\n }\n\n}\n" - }, - "0xf4ab8fd7af56fb99e7bf5e5edc0b407da530a4f4": { - "generatedAt": "2018-05-12T00:22:15.136Z", - "truffleContractFileUpdatedAt": "2018-05-12T00:22:05.945Z", - "deployTransactionHash": "0xfd91f3b00fe09f5c641919e0de3dac8645d5e460fa53f4151458fe3fa540d864", - "compiler": { - "name": "solc", - "version": "0.4.23+commit.124ca40d.Emscripten.clang" - }, - "bytecodeHash": "380f5b0d9fdbaed55c151dfd0f5f78c4", - "deployedBytecodeHash": "a707a4a1296cb1140d4610935ad58f8c", - "sourceHash": "c3fd200d4510ea1b3d7c6c7ae04683b9", - "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or MonetaryBoard or MonetarySupervisor)\n\n */\n\npragma solidity ^0.4.23;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is SystemAccount {\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n function burn(AugmintTokenInterface augmintToken, uint amount) external restrict(\"MonetarySupervisorContract\") {\n augmintToken.burn(amount);\n }\n\n}\n" - }, - "0x3e04292890afb91585d5ebfc1d7b43443e780122": { - "generatedAt": "2018-05-31T23:56:48.461Z", - "truffleContractFileUpdatedAt": "2018-05-31T23:54:26.407Z", - "deployTransactionHash": "0xe3bcaec04db23280e83f52488e1d8e67e717bbed22a559cfa8a5f764f34aa07a", - "compiler": { - "name": "solc", - "version": "0.4.24+commit.e67f0147.Emscripten.clang" - }, - "bytecodeHash": "c9c15e1d092a37c1a88d3fe8924be8a5", - "deployedBytecodeHash": "4d15213d404f3c6c0c9a0de65c2c3996", - "sourceHash": "42d045116a6fe58114854813024e7ba6", - "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or MonetaryBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is SystemAccount {\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n function burn(AugmintTokenInterface augmintToken, uint amount) external restrict(\"MonetarySupervisorContract\") {\n augmintToken.burn(amount);\n }\n\n}\n" - } - } - }, - "fe74b7986dafb00f221486e790fc70ec": { + "024b81d1a1f75241167a8a0f6e62326f": { "latestDeployedAddress": "0x1b9441428f9e682bab4f9cc70fdf50adcc3411f4", "deployments": { "0x1b9441428f9e682bab4f9cc70fdf50adcc3411f4": { - "generatedAt": "2018-08-14T19:51:18.010Z", - "truffleContractFileUpdatedAt": "2018-08-14T19:50:56.846Z", - "deployTransactionHash": "0x5e29c445328b0a15af223d0e3c551a2bbe5bf9fb4f69078aac8c9ee2c486787c", + "generatedAt": "2018-10-18T13:35:02.347Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.845Z", + "deployTransactionHash": "0x856ac4754df0c03bfe83966e71225b02c97363a09cabc370aafba56ad4a016f2", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "d7c3fae717169f479dc6cb5fbad4819d", - "deployedBytecodeHash": "e5371ee78a44dcf0a1cf4e902035e415", - "sourceHash": "d5753af67c3f621da910f47d3d749db3", - "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or StabilityBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is SystemAccount {\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function burn(AugmintTokenInterface augmintToken, uint amount) external restrict(\"MonetarySupervisor\") {\n augmintToken.burn(amount);\n }\n\n}\n" + "bytecodeHash": "5bf4ede2aaad5b0b112f7b1ebf420fd2", + "deployedBytecodeHash": "3720667df6506876043fba53c540acb6", + "sourceHash": "b9d84f5f6153164ba581845190291c88", + "source": "/* Contract to hold Augmint reserves (ETH & Token)\n - ETH as regular ETH balance of the contract\n - ERC20 token reserve (stored as regular Token balance under the contract address)\n\nNB: reserves are held under the contract address, therefore any transaction on the reserve is limited to the\n tx-s defined here (i.e. transfer is not allowed even by the contract owner or StabilityBoard or MonetarySupervisor)\n\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract AugmintReserves is Restricted {\n\n event ReserveMigration(address to, uint weiAmount);\n\n constructor(address permissionGranterContract)\n public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function () external payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into reserve (from defaulted loan's collateral )\n }\n\n function burn(AugmintTokenInterface augmintToken, uint amount)\n external restrict(\"MonetarySupervisor\") {\n augmintToken.burn(amount);\n }\n\n function migrate(address to, uint weiAmount)\n external restrict(\"StabilityBoard\") {\n if (weiAmount > 0) {\n to.transfer(weiAmount);\n }\n emit ReserveMigration(to, weiAmount);\n }\n}\n" } } } diff --git a/abiniser/deployments/999/Exchange_DEPLOYS.json b/abiniser/deployments/999/Exchange_DEPLOYS.json index c07634c9..2da239ef 100644 --- a/abiniser/deployments/999/Exchange_DEPLOYS.json +++ b/abiniser/deployments/999/Exchange_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "Exchange", - "latestAbiHash": "c28de2392aea85ef2aa1b108fce6568c", + "latestAbiHash": "d3e7f8a261b756f9c40da097608b21cd", "deployedAbis": { "3aa2aedd2972391a12570ba4bfca2f72": { "latestDeployedAddress": "0x367f6272f3c4146f045f19be8774d97fd0966af5", @@ -159,6 +159,24 @@ "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n uint public constant CHUNK_SIZE = 100;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"buy order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"sell order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price is the price of the maker (the order placed earlier)\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n require(_fillOrder(buyTokenId, sellTokenId), \"fill order failed\");\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Reverts if any match is invalid (e.g sell price > buy price)\n Skips match if any of the matched orders is removed / already filled (i.e. amount = 0)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n if(_fillOrder(buyTokenIds[i], sellTokenIds[i])) {\n matchCount++;\n }\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns CHUNK_SIZE orders starting from offset\n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) {\n uint64 orderId = activeBuyOrders[offset + i];\n Order storage order = buyTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) {\n uint64 orderId = activeSellOrders[offset + i];\n Order storage order = sellTokenOrders[orderId];\n response[i] = [orderId, uint(order.maker), order.price, order.amount];\n }\n }\n\n uint private constant E12 = 1000000000000;\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private returns(bool success) {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n if( buy.amount == 0 || sell.amount == 0 ) {\n return false; // one order is already filled and removed.\n // we let matchMultiple continue, indivudal match will revert\n }\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n // fillRate = publishedRate * 1000000 / price\n\n uint sellWei = sell.amount.mul(uint(price)).mul(E12).roundedDiv(publishedRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(publishedRate).roundedDiv(uint(price).mul(E12));\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, tradedWei, tradedTokens);\n\n return true;\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n _removeOrder(activeBuyOrders, order.index);\n }\n\n function _removeSellOrder(Order storage order) private {\n _removeOrder(activeSellOrders, order.index);\n }\n\n function _removeOrder(uint64[] storage orders, uint64 index) private {\n if (index < orders.length - 1) {\n orders[index] = orders[orders.length - 1];\n }\n orders.length--;\n }\n\n}\n" } } + }, + "d3e7f8a261b756f9c40da097608b21cd": { + "latestDeployedAddress": "0xfacea53a04befcc6c9246eb3951814cfee2a1415", + "deployments": { + "0xfacea53a04befcc6c9246eb3951814cfee2a1415": { + "generatedAt": "2018-10-18T13:35:02.438Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.980Z", + "deployTransactionHash": "0xe209afd86747757d7e1538dec4967fa6ec924b4d588c9b2a85091e6eb62ccacb", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "5a731d45c1595b7ffeb40bae693ef88d", + "deployedBytecodeHash": "136e48f6880df5153792c846d87ddede", + "sourceHash": "d6ff57acb1b45199b5dd08357978d8c2", + "source": "/* Augmint's Internal Exchange\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/exchangeFlow.png\n\n TODO:\n - change to wihtdrawal pattern, see: https://github.com/Augmint/augmint-contracts/issues/17\n - deduct fee\n - consider take funcs (frequent rate changes with takeBuyToken? send more and send back remainder?)\n - use Rates interface?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./Rates.sol\";\n\n\ncontract Exchange is Restricted {\n using SafeMath for uint256;\n\n AugmintTokenInterface public augmintToken;\n Rates public rates;\n\n struct Order {\n uint64 index;\n address maker;\n\n // % of published current peggedSymbol/ETH rates published by Rates contract. Stored as parts per million\n // I.e. 1,000,000 = 100% (parity), 990,000 = 1% below parity\n uint32 price;\n\n // buy order: amount in wei\n // sell order: token amount\n uint amount;\n }\n\n uint64 public orderCount;\n mapping(uint64 => Order) public buyTokenOrders;\n mapping(uint64 => Order) public sellTokenOrders;\n\n uint64[] private activeBuyOrders;\n uint64[] private activeSellOrders;\n\n /* used to stop executing matchMultiple when running out of gas.\n actual is much less, just leaving enough matchMultipleOrders() to finish TODO: fine tune & test it*/\n uint32 private constant ORDER_MATCH_WORST_GAS = 100000;\n\n event NewOrder(uint64 indexed orderId, address indexed maker, uint32 price, uint tokenAmount, uint weiAmount);\n\n event OrderFill(address indexed tokenBuyer, address indexed tokenSeller, uint64 buyTokenOrderId,\n uint64 sellTokenOrderId, uint publishedRate, uint32 price, uint weiAmount, uint tokenAmount);\n\n event CancelledOrder(uint64 indexed orderId, address indexed maker, uint tokenAmount, uint weiAmount);\n\n event RatesContractChanged(Rates newRatesContract);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n rates = _rates;\n }\n\n /* to allow upgrade of Rates contract */\n function setRatesContract(Rates newRatesContract)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n emit RatesContractChanged(newRatesContract);\n }\n\n function placeBuyTokenOrder(uint32 price) external payable returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(msg.value > 0, \"msg.value must be > 0\");\n\n orderId = ++orderCount;\n buyTokenOrders[orderId] = Order(uint64(activeBuyOrders.length), msg.sender, price, msg.value);\n activeBuyOrders.push(orderId);\n\n emit NewOrder(orderId, msg.sender, price, 0, msg.value);\n }\n\n /* this function requires previous approval to transfer tokens */\n function placeSellTokenOrder(uint32 price, uint tokenAmount) external returns (uint orderId) {\n augmintToken.transferFrom(msg.sender, this, tokenAmount);\n return _placeSellTokenOrder(msg.sender, price, tokenAmount);\n }\n\n /* place sell token order called from AugmintToken's transferAndNotify\n Flow:\n 1) user calls token contract's transferAndNotify price passed in data arg\n 2) transferAndNotify transfers tokens to the Exchange contract\n 3) transferAndNotify calls Exchange.transferNotification with lockProductId\n */\n function transferNotification(address maker, uint tokenAmount, uint price) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n _placeSellTokenOrder(maker, uint32(price), tokenAmount);\n }\n\n function cancelBuyTokenOrder(uint64 buyTokenId) external {\n Order storage order = buyTokenOrders[buyTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"buy order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeBuyOrder(order);\n\n msg.sender.transfer(amount);\n\n emit CancelledOrder(buyTokenId, msg.sender, 0, amount);\n }\n\n function cancelSellTokenOrder(uint64 sellTokenId) external {\n Order storage order = sellTokenOrders[sellTokenId];\n require(order.maker == msg.sender, \"msg.sender must be order.maker\");\n require(order.amount > 0, \"sell order already removed\");\n\n uint amount = order.amount;\n order.amount = 0;\n _removeSellOrder(order);\n\n augmintToken.transferWithNarrative(msg.sender, amount, \"Sell token order cancelled\");\n\n emit CancelledOrder(sellTokenId, msg.sender, amount, 0);\n }\n\n /* matches any two orders if the sell price >= buy price\n trade price is the price of the maker (the order placed earlier)\n reverts if any of the orders have been removed\n */\n function matchOrders(uint64 buyTokenId, uint64 sellTokenId) external {\n require(_fillOrder(buyTokenId, sellTokenId), \"fill order failed\");\n }\n\n /* matches as many orders as possible from the passed orders\n Runs as long as gas is available for the call.\n Reverts if any match is invalid (e.g sell price > buy price)\n Skips match if any of the matched orders is removed / already filled (i.e. amount = 0)\n */\n function matchMultipleOrders(uint64[] buyTokenIds, uint64[] sellTokenIds) external returns(uint matchCount) {\n uint len = buyTokenIds.length;\n require(len == sellTokenIds.length, \"buyTokenIds and sellTokenIds lengths must be equal\");\n\n for (uint i = 0; i < len && gasleft() > ORDER_MATCH_WORST_GAS; i++) {\n if(_fillOrder(buyTokenIds[i], sellTokenIds[i])) {\n matchCount++;\n }\n }\n }\n\n function getActiveOrderCounts() external view returns(uint buyTokenOrderCount, uint sellTokenOrderCount) {\n return(activeBuyOrders.length, activeSellOrders.length);\n }\n\n // returns active buy orders starting from \n // orders are encoded as [id, maker, price, amount]\n function getActiveBuyOrders(uint offset, uint16 chunkSize)\n external view returns (uint[4][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), activeBuyOrders.length);\n uint[4][] memory response = new uint[4][](limit.sub(offset));\n for (uint i = offset; i < limit; i++) {\n uint64 orderId = activeBuyOrders[i];\n Order storage order = buyTokenOrders[orderId];\n response[i - offset] = [orderId, uint(order.maker), order.price, order.amount];\n }\n return response;\n }\n\n // returns active sell orders starting from \n // orders are encoded as [id, maker, price, amount]\n function getActiveSellOrders(uint offset, uint16 chunkSize)\n external view returns (uint[4][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), activeSellOrders.length);\n uint[4][] memory response = new uint[4][](limit.sub(offset));\n for (uint i = offset; i < limit; i++) {\n uint64 orderId = activeSellOrders[i];\n Order storage order = sellTokenOrders[orderId];\n response[i - offset] = [orderId, uint(order.maker), order.price, order.amount];\n }\n return response;\n }\n\n uint private constant E12 = 1000000000000;\n\n function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private returns(bool success) {\n Order storage buy = buyTokenOrders[buyTokenId];\n Order storage sell = sellTokenOrders[sellTokenId];\n if( buy.amount == 0 || sell.amount == 0 ) {\n return false; // one order is already filled and removed.\n // we let matchMultiple continue, indivudal match will revert\n }\n\n require(buy.price >= sell.price, \"buy price must be >= sell price\");\n\n // pick maker's price (whoever placed order sooner considered as maker)\n uint32 price = buyTokenId > sellTokenId ? sell.price : buy.price;\n\n uint publishedRate;\n (publishedRate, ) = rates.rates(augmintToken.peggedSymbol());\n // fillRate = publishedRate * 1000000 / price\n\n uint sellWei = sell.amount.mul(uint(price)).mul(E12).roundedDiv(publishedRate);\n\n uint tradedWei;\n uint tradedTokens;\n if (sellWei <= buy.amount) {\n tradedWei = sellWei;\n tradedTokens = sell.amount;\n } else {\n tradedWei = buy.amount;\n tradedTokens = buy.amount.mul(publishedRate).roundedDiv(uint(price).mul(E12));\n }\n\n buy.amount = buy.amount.sub(tradedWei);\n if (buy.amount == 0) {\n _removeBuyOrder(buy);\n }\n\n sell.amount = sell.amount.sub(tradedTokens);\n if (sell.amount == 0) {\n _removeSellOrder(sell);\n }\n\n augmintToken.transferWithNarrative(buy.maker, tradedTokens, \"Buy token order fill\");\n sell.maker.transfer(tradedWei);\n\n emit OrderFill(buy.maker, sell.maker, buyTokenId,\n sellTokenId, publishedRate, price, tradedWei, tradedTokens);\n\n return true;\n }\n\n function _placeSellTokenOrder(address maker, uint32 price, uint tokenAmount)\n private returns (uint64 orderId) {\n require(price > 0, \"price must be > 0\");\n require(tokenAmount > 0, \"tokenAmount must be > 0\");\n\n orderId = ++orderCount;\n sellTokenOrders[orderId] = Order(uint64(activeSellOrders.length), maker, price, tokenAmount);\n activeSellOrders.push(orderId);\n\n emit NewOrder(orderId, maker, price, tokenAmount, 0);\n }\n\n function _removeBuyOrder(Order storage order) private {\n uint lastIndex = activeBuyOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeBuyOrders[lastIndex];\n activeBuyOrders[order.index] = movedOrderId;\n buyTokenOrders[movedOrderId].index = order.index;\n }\n activeBuyOrders.length--;\n }\n\n function _removeSellOrder(Order storage order) private {\n uint lastIndex = activeSellOrders.length - 1;\n if (order.index < lastIndex) {\n uint64 movedOrderId = activeSellOrders[lastIndex];\n activeSellOrders[order.index] = movedOrderId;\n sellTokenOrders[movedOrderId].index = order.index;\n }\n activeSellOrders.length--;\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/999/FeeAccount_DEPLOYS.json b/abiniser/deployments/999/FeeAccount_DEPLOYS.json index 950a0e35..c0a50597 100644 --- a/abiniser/deployments/999/FeeAccount_DEPLOYS.json +++ b/abiniser/deployments/999/FeeAccount_DEPLOYS.json @@ -67,17 +67,17 @@ "latestDeployedAddress": "0xf5efcaa78f5656f7ddc971bc5d51a08b5f161573", "deployments": { "0xf5efcaa78f5656f7ddc971bc5d51a08b5f161573": { - "generatedAt": "2018-08-14T19:51:18.023Z", - "truffleContractFileUpdatedAt": "2018-08-14T19:50:59.286Z", - "deployTransactionHash": "0x34a5cce6c5e78d70887eb6658ed381b0a2178220abf5fd95b9a9af164974eb5e", + "generatedAt": "2018-10-18T13:35:02.354Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.893Z", + "deployTransactionHash": "0x8f20ad1a0464acd457877feb774cc3b6fabb1d3db7a49cb12fa8bc8a494b0db2", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "aa7f93b0eef01da2ddd9b45c2d7bca53", - "deployedBytecodeHash": "0893c45b2a47e121a3372bc41cd36c8c", - "sourceHash": "653a2a034144713dc046880dafd503c9", - "source": "/* Contract to collect fees from system\n TODO: calculateExchangeFee + Exchange params and setters\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/TransferFeeInterface.sol\";\n\n\ncontract FeeAccount is SystemAccount, TransferFeeInterface {\n\n using SafeMath for uint256;\n\n struct TransferFee {\n uint pt; // in parts per million (ppm) , ie. 2,000 = 0.2%\n uint min; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n uint max; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n }\n\n TransferFee public transferFee;\n\n event TransferFeesChanged(uint transferFeePt, uint transferFeeMin, uint transferFeeMax);\n\n constructor(address permissionGranterContract, uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n public SystemAccount(permissionGranterContract) {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function () public payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into feeAccount (defaulting fee in ETH )\n }\n\n function setTransferFees(uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n external restrict(\"StabilityBoard\") {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n emit TransferFeesChanged(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function calculateTransferFee(address from, address to, uint amount) external view returns (uint256 fee) {\n if (!permissions[from][\"NoTransferFee\"] && !permissions[to][\"NoTransferFee\"]) {\n fee = amount.mul(transferFee.pt).div(1000000);\n if (fee > transferFee.max) {\n fee = transferFee.max;\n } else if (fee < transferFee.min) {\n fee = transferFee.min;\n }\n }\n return fee;\n }\n\n function calculateExchangeFee(uint weiAmount) external view returns (uint256 weiFee) {\n /* TODO: to be implemented and use in Exchange.sol. always revert for now */\n require(weiAmount != weiAmount, \"not yet implemented\");\n weiFee = transferFee.max; // to silence compiler warnings until it's implemented\n }\n\n}\n" + "bytecodeHash": "7f27e332912911a33f3a5831a478a40e", + "deployedBytecodeHash": "62169a6a5b1bc79360f85c7d6b7cbadf", + "sourceHash": "d8975a5e1941ad79313f4b7bb0be9f95", + "source": "/* Contract to collect fees from system\n TODO: calculateExchangeFee + Exchange params and setters\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/TransferFeeInterface.sol\";\n\n\ncontract FeeAccount is SystemAccount, TransferFeeInterface {\n\n using SafeMath for uint256;\n\n struct TransferFee {\n uint pt; // in parts per million (ppm) , ie. 2,000 = 0.2%\n uint min; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n uint max; // with base unit of augmint token, eg. 2 decimals for token, eg. 310 = 3.1 ACE\n }\n\n TransferFee public transferFee;\n\n event TransferFeesChanged(uint transferFeePt, uint transferFeeMin, uint transferFeeMax);\n\n constructor(address permissionGranterContract, uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n public SystemAccount(permissionGranterContract) {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function () external payable { // solhint-disable-line no-empty-blocks\n // to accept ETH sent into feeAccount (defaulting fee in ETH )\n }\n\n function setTransferFees(uint transferFeePt, uint transferFeeMin, uint transferFeeMax)\n external restrict(\"StabilityBoard\") {\n transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax);\n emit TransferFeesChanged(transferFeePt, transferFeeMin, transferFeeMax);\n }\n\n function calculateTransferFee(address from, address to, uint amount) external view returns (uint256 fee) {\n if (!permissions[from][\"NoTransferFee\"] && !permissions[to][\"NoTransferFee\"]) {\n fee = amount.mul(transferFee.pt).div(1000000);\n if (fee > transferFee.max) {\n fee = transferFee.max;\n } else if (fee < transferFee.min) {\n fee = transferFee.min;\n }\n }\n return fee;\n }\n\n function calculateExchangeFee(uint weiAmount) external view returns (uint256 weiFee) {\n /* TODO: to be implemented and use in Exchange.sol. always revert for now */\n require(weiAmount != weiAmount, \"not yet implemented\");\n weiFee = transferFee.max; // to silence compiler warnings until it's implemented\n }\n\n}\n" } } } diff --git a/abiniser/deployments/999/InterestEarnedAccount_DEPLOYS.json b/abiniser/deployments/999/InterestEarnedAccount_DEPLOYS.json index 5ab88d59..5f80f51b 100644 --- a/abiniser/deployments/999/InterestEarnedAccount_DEPLOYS.json +++ b/abiniser/deployments/999/InterestEarnedAccount_DEPLOYS.json @@ -79,15 +79,15 @@ "latestDeployedAddress": "0x1efb52b6aacc403cc9d762282b2aec1b066931c5", "deployments": { "0x1efb52b6aacc403cc9d762282b2aec1b066931c5": { - "generatedAt": "2018-08-14T19:51:18.028Z", - "truffleContractFileUpdatedAt": "2018-08-14T19:50:56.847Z", - "deployTransactionHash": "0xacf14fb064dcef5fe0f0852bb245f2beadc02a91ebc33b9e9e1515c46924e77e", + "generatedAt": "2018-10-18T13:35:02.360Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.821Z", + "deployTransactionHash": "0x5e3f2463c5ec4fcc56eb8210b534253f58e5b77d4190d013ec8a85dd662cbd4c", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "3310d17fffd84a10e23a063d4b5b6779", - "deployedBytecodeHash": "7dc6ed41dd07e55de72759c380252b54", + "bytecodeHash": "3994e47ec4faf784d97e783d6e3de64d", + "deployedBytecodeHash": "9b8b05d9a455663e6bc0b4aa953ef26e", "sourceHash": "3ae3310cda808efba999807e54bf8c9b", "source": "/* Contract to hold earned interest from loans repaid\n premiums for locks are being accrued (i.e. transferred) to Locker */\n\npragma solidity 0.4.24;\nimport \"./generic/SystemAccount.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\n\n\ncontract InterestEarnedAccount is SystemAccount {\n\n constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function transferInterest(AugmintTokenInterface augmintToken, address locker, uint interestAmount)\n external restrict(\"MonetarySupervisor\") {\n augmintToken.transfer(locker, interestAmount);\n }\n\n}\n" } diff --git a/abiniser/deployments/999/LoanManager_DEPLOYS.json b/abiniser/deployments/999/LoanManager_DEPLOYS.json index e3acbf2e..518d51d8 100644 --- a/abiniser/deployments/999/LoanManager_DEPLOYS.json +++ b/abiniser/deployments/999/LoanManager_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "LoanManager", - "latestAbiHash": "ec709c3341045caa3a75374b8cfc7286", + "latestAbiHash": "fdf5fde95aa940c6dbfb8353c572c5fb", "deployedAbis": { "dd8d5ec97e0a22b6f9e63b04d4e11e09": { "latestDeployedAddress": "0x72ab340874d8189778d5b4def3eaabc9069da7f2", @@ -110,6 +110,24 @@ "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - make collect() run as long as gas provided allows\n*/\npragma solidity 0.4.24;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted {\n using SafeMath for uint256;\n\n uint16 public constant CHUNK_SIZE = 100;\n\n enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate\n\n struct LoanProduct {\n uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals\n uint32 term; // 1\n uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1%\n uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */\n struct LoanData {\n uint collateralAmount; // 0\n uint repaymentAmount; // 1\n address borrower; // 2\n uint32 productId; // 3\n LoanState state; // 4\n uint40 maturity; // 5\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n\n event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount, uint40 maturity);\n\n event LoanProductActiveStateChanged(uint32 productId, bool newState);\n\n event LoanProductAdded(uint32 productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n event SystemContractsChanged(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n }\n\n function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount,\n uint32 defaultingFeePt, bool isActive)\n external restrict(\"StabilityBoard\") {\n\n uint _newProductId = products.push(\n LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive)\n ) - 1;\n\n uint32 newProductId = uint32(_newProductId);\n require(newProductId == _newProductId, \"productId overflow\");\n\n emit LoanProductAdded(newProductId);\n }\n\n function setLoanProductActiveState(uint32 productId, bool newState)\n external restrict (\"StabilityBoard\") {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n products[productId].isActive = false;\n emit LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint32 productId) external payable {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n LoanProduct storage product = products[productId];\n require(product.isActive, \"product must be in active state\"); // valid product\n\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000);\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, repaymentAmount);\n\n require(loanAmount >= product.minDisbursedAmount, \"loanAmount must be >= minDisbursedAmount\");\n\n uint expiration = now.add(product.term);\n uint40 maturity = uint40(expiration);\n require(maturity == expiration, \"maturity overflow\");\n\n // Create new loan\n uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender,\n productId, LoanState.Open, maturity)) - 1;\n\n // Store ref to new loan\n accountLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n emit NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity);\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n\n _repayLoan(loanId, repaymentAmount);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n uint totalDefaultingFee;\n for (uint i = 0; i < loanIds.length; i++) {\n require(i < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanIds[i]];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(now >= loan.maturity, \"current time must be later than maturity\");\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount);\n\n loan.state = LoanState.Collected;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(),\n loan.repaymentAmount).add(defaultingFee);\n\n uint releasedCollateral;\n if (targetCollection < loan.collateralAmount) {\n releasedCollateral = loan.collateralAmount.sub(targetCollection);\n loan.borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral);\n if (defaultingFee >= collateralToCollect) {\n defaultingFee = collateralToCollect;\n collateralToCollect = 0;\n } else {\n collateralToCollect = collateralToCollect.sub(defaultingFee);\n }\n totalDefaultingFee = totalDefaultingFee.add(defaultingFee);\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee), releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect);\n }\n\n if (totalDefaultingFee > 0){\n address(augmintToken.feeAccount()).transfer(totalDefaultingFee);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n /* to allow upgrade of Rates and MonetarySupervisor contracts */\n function setSystemContracts(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n monetarySupervisor = newMonetarySupervisor;\n emit SystemContractsChanged(newRatesContract, newMonetarySupervisor);\n }\n\n function getProductCount() external view returns (uint ct) {\n return products.length;\n }\n\n // returns CHUNK_SIZE loan products starting from some offset:\n // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ]\n function getProducts(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= products.length) { break; }\n\n LoanProduct storage product = products[offset + i];\n\n response[i] = [offset + i, product.minDisbursedAmount, product.term, product.discountRate,\n product.collateralRatio, product.defaultingFeePt,\n monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ];\n }\n }\n\n function getLoanCount() external view returns (uint ct) {\n return loans.length;\n }\n\n /* returns CHUNK_SIZE loans starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoans(uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loans.length) { break; }\n\n response[i] = getLoanTuple(offset + i);\n }\n }\n\n function getLoanCountForAddress(address borrower) external view returns (uint) {\n return accountLoans[borrower].length;\n }\n\n /* returns CHUNK_SIZE loans of a given account, starting from some offset. Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoansForAddress(address borrower, uint offset) external view returns (uint[10][CHUNK_SIZE] response) {\n\n uint[] storage loansForAddress = accountLoans[borrower];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= loansForAddress.length) { break; }\n\n response[i] = getLoanTuple(loansForAddress[offset + i]);\n }\n }\n\n function getLoanTuple(uint loanId) public view returns (uint[10] result) {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n uint disbursementTime = loan.maturity - product.term;\n\n LoanState loanState =\n loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state;\n\n result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower),\n loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount];\n }\n\n function calculateLoanValues(LoanProduct storage product, uint repaymentAmount)\n internal view returns (uint loanAmount, uint interestAmount) {\n // calculate loan values based on repayment amount\n loanAmount = repaymentAmount.mul(product.discountRate).div(1000000);\n interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(repaymentAmount == loan.repaymentAmount, \"repaymentAmount must be equal to tokens sent\");\n require(now <= loan.maturity, \"current time must be earlier than maturity\");\n\n LoanProduct storage product = products[loan.productId];\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n\n loans[loanId].state = LoanState.Repaid;\n\n if (interestAmount > 0) {\n augmintToken.transfer(monetarySupervisor.interestEarnedAccount(), interestAmount);\n augmintToken.burn(loanAmount);\n } else {\n // negative or zero interest (i.e. discountRate >= 0)\n augmintToken.burn(repaymentAmount);\n }\n\n monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs\n\n loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral\n\n emit LoanRepayed(loanId, loan.borrower);\n }\n\n}\n" } } + }, + "fdf5fde95aa940c6dbfb8353c572c5fb": { + "latestDeployedAddress": "0x213135c85437c23bc529a2ee9c2980646c332fcb", + "deployments": { + "0x213135c85437c23bc529a2ee9c2980646c332fcb": { + "generatedAt": "2018-10-18T13:35:02.404Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:37.002Z", + "deployTransactionHash": "0xb22fb6501cdcc6b9bfe2ee1ca2e111047085674e2f9dd120a8dde83ffeaf872e", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "591f565c201032e0df4b9f7798e7ec85", + "deployedBytecodeHash": "e93edcccad1eb8f9142f6c257bb23bdd", + "sourceHash": "234fd5848af85ca2444c888fd6ba61aa", + "source": "/*\n Contract to manage Augmint token loan contracts backed by ETH\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/loanFlow.png\n\n TODO:\n - create MonetarySupervisor interface and use it instead?\n - make data arg generic bytes?\n - make collect() run as long as gas provided allows\n*/\npragma solidity 0.4.24;\n\nimport \"./Rates.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\n\n\ncontract LoanManager is Restricted, TokenReceiver {\n using SafeMath for uint256;\n\n enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate\n\n struct LoanProduct {\n uint minDisbursedAmount; // 0: with decimals set in AugmintToken.decimals\n uint32 term; // 1\n uint32 discountRate; // 2: discountRate in parts per million , ie. 10,000 = 1%\n uint32 collateralRatio; // 3: loan token amount / colleteral pegged ccy value\n // in parts per million , ie. 10,000 = 1%\n uint32 defaultingFeePt; // 4: % of collateral in parts per million , ie. 50,000 = 5%\n bool isActive; // 5\n }\n\n /* NB: we don't need to store loan parameters because loan products can't be altered (only disabled/enabled) */\n struct LoanData {\n uint collateralAmount; // 0\n uint repaymentAmount; // 1\n address borrower; // 2\n uint32 productId; // 3\n LoanState state; // 4\n uint40 maturity; // 5\n }\n\n LoanProduct[] public products;\n\n LoanData[] public loans;\n mapping(address => uint[]) public accountLoans; // owner account address => array of loan Ids\n\n Rates public rates; // instance of ETH/pegged currency rate provider contract\n AugmintTokenInterface public augmintToken; // instance of token contract\n MonetarySupervisor public monetarySupervisor;\n\n event NewLoan(uint32 productId, uint loanId, address indexed borrower, uint collateralAmount, uint loanAmount,\n uint repaymentAmount, uint40 maturity);\n\n event LoanProductActiveStateChanged(uint32 productId, bool newState);\n\n event LoanProductAdded(uint32 productId);\n\n event LoanRepayed(uint loanId, address borrower);\n\n event LoanCollected(uint loanId, address indexed borrower, uint collectedCollateral,\n uint releasedCollateral, uint defaultingFee);\n\n event SystemContractsChanged(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor, Rates _rates)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n rates = _rates;\n }\n\n function addLoanProduct(uint32 term, uint32 discountRate, uint32 collateralRatio, uint minDisbursedAmount,\n uint32 defaultingFeePt, bool isActive)\n external restrict(\"StabilityBoard\") {\n\n uint _newProductId = products.push(\n LoanProduct(minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, isActive)\n ) - 1;\n\n uint32 newProductId = uint32(_newProductId);\n require(newProductId == _newProductId, \"productId overflow\");\n\n emit LoanProductAdded(newProductId);\n }\n\n function setLoanProductActiveState(uint32 productId, bool newState)\n external restrict (\"StabilityBoard\") {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n products[productId].isActive = newState;\n emit LoanProductActiveStateChanged(productId, newState);\n }\n\n function newEthBackedLoan(uint32 productId) external payable {\n require(productId < products.length, \"invalid productId\"); // next line would revert but require to emit reason\n LoanProduct storage product = products[productId];\n require(product.isActive, \"product must be in active state\"); // valid product\n\n\n // calculate loan values based on ETH sent in with Tx\n uint tokenValue = rates.convertFromWei(augmintToken.peggedSymbol(), msg.value);\n uint repaymentAmount = tokenValue.mul(product.collateralRatio).div(1000000);\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, repaymentAmount);\n\n require(loanAmount >= product.minDisbursedAmount, \"loanAmount must be >= minDisbursedAmount\");\n\n uint expiration = now.add(product.term);\n uint40 maturity = uint40(expiration);\n require(maturity == expiration, \"maturity overflow\");\n\n // Create new loan\n uint loanId = loans.push(LoanData(msg.value, repaymentAmount, msg.sender,\n productId, LoanState.Open, maturity)) - 1;\n\n // Store ref to new loan\n accountLoans[msg.sender].push(loanId);\n\n // Issue tokens and send to borrower\n monetarySupervisor.issueLoan(msg.sender, loanAmount);\n\n emit NewLoan(productId, loanId, msg.sender, msg.value, loanAmount, repaymentAmount, maturity);\n }\n\n /* repay loan, called from AugmintToken's transferAndNotify\n Flow for repaying loan:\n 1) user calls token contract's transferAndNotify loanId passed in data arg\n 2) transferAndNotify transfers tokens to the Lender contract\n 3) transferAndNotify calls Lender.transferNotification with lockProductId\n */\n // from arg is not used as we allow anyone to repay a loan:\n function transferNotification(address, uint repaymentAmount, uint loanId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n\n _repayLoan(loanId, repaymentAmount);\n }\n\n function collect(uint[] loanIds) external {\n /* when there are a lots of loans to be collected then\n the client need to call it in batches to make sure tx won't exceed block gas limit.\n Anyone can call it - can't cause harm as it only allows to collect loans which they are defaulted\n TODO: optimise defaulting fee calculations\n */\n uint totalLoanAmountCollected;\n uint totalCollateralToCollect;\n uint totalDefaultingFee;\n for (uint i = 0; i < loanIds.length; i++) {\n require(loanIds[i] < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanIds[i]];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(now >= loan.maturity, \"current time must be later than maturity\");\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n (loanAmount, ) = calculateLoanValues(product, loan.repaymentAmount);\n\n totalLoanAmountCollected = totalLoanAmountCollected.add(loanAmount);\n\n loan.state = LoanState.Collected;\n\n // send ETH collateral to augmintToken reserve\n uint defaultingFeeInToken = loan.repaymentAmount.mul(product.defaultingFeePt).div(1000000);\n uint defaultingFee = rates.convertToWei(augmintToken.peggedSymbol(), defaultingFeeInToken);\n uint targetCollection = rates.convertToWei(augmintToken.peggedSymbol(),\n loan.repaymentAmount).add(defaultingFee);\n\n uint releasedCollateral;\n if (targetCollection < loan.collateralAmount) {\n releasedCollateral = loan.collateralAmount.sub(targetCollection);\n loan.borrower.transfer(releasedCollateral);\n }\n uint collateralToCollect = loan.collateralAmount.sub(releasedCollateral);\n if (defaultingFee >= collateralToCollect) {\n defaultingFee = collateralToCollect;\n collateralToCollect = 0;\n } else {\n collateralToCollect = collateralToCollect.sub(defaultingFee);\n }\n totalDefaultingFee = totalDefaultingFee.add(defaultingFee);\n\n totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect);\n\n emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee),\n releasedCollateral, defaultingFee);\n }\n\n if (totalCollateralToCollect > 0) {\n address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect);\n }\n\n if (totalDefaultingFee > 0) {\n address(augmintToken.feeAccount()).transfer(totalDefaultingFee);\n }\n\n monetarySupervisor.loanCollectionNotification(totalLoanAmountCollected);// update KPIs\n\n }\n\n /* to allow upgrade of Rates and MonetarySupervisor contracts */\n function setSystemContracts(Rates newRatesContract, MonetarySupervisor newMonetarySupervisor)\n external restrict(\"StabilityBoard\") {\n rates = newRatesContract;\n monetarySupervisor = newMonetarySupervisor;\n emit SystemContractsChanged(newRatesContract, newMonetarySupervisor);\n }\n\n function getProductCount() external view returns (uint) {\n return products.length;\n }\n\n // returns loan products starting from some :\n // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ]\n function getProducts(uint offset, uint16 chunkSize)\n external view returns (uint[8][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), products.length);\n uint[8][] memory response = new uint[8][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n LoanProduct storage product = products[i];\n response[i - offset] = [i, product.minDisbursedAmount, product.term, product.discountRate,\n product.collateralRatio, product.defaultingFeePt,\n monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function getLoanCount() external view returns (uint) {\n return loans.length;\n }\n\n /* returns loans starting from some . Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId,\n state, maturity, disbursementTime, loanAmount, interestAmount] */\n function getLoans(uint offset, uint16 chunkSize)\n external view returns (uint[10][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), loans.length);\n uint[10][] memory response = new uint[10][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n response[i - offset] = getLoanTuple(i);\n }\n return response;\n }\n\n function getLoanCountForAddress(address borrower) external view returns (uint) {\n return accountLoans[borrower].length;\n }\n\n /* returns loans of a given account, starting from some . Loans data encoded as:\n [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime,\n loanAmount, interestAmount ] */\n function getLoansForAddress(address borrower, uint offset, uint16 chunkSize)\n external view returns (uint[10][]) {\n uint[] storage loansForAddress = accountLoans[borrower];\n uint limit = SafeMath.min(offset.add(chunkSize), loansForAddress.length);\n uint[10][] memory response = new uint[10][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n response[i - offset] = getLoanTuple(loansForAddress[i]);\n }\n return response;\n }\n\n function getLoanTuple(uint loanId) public view returns (uint[10] result) {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n LoanProduct storage product = products[loan.productId];\n\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n uint disbursementTime = loan.maturity - product.term;\n\n LoanState loanState =\n loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state;\n\n result = [loanId, loan.collateralAmount, loan.repaymentAmount, uint(loan.borrower),\n loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount];\n }\n\n function calculateLoanValues(LoanProduct storage product, uint repaymentAmount)\n internal view returns (uint loanAmount, uint interestAmount) {\n // calculate loan values based on repayment amount\n loanAmount = repaymentAmount.mul(product.discountRate).div(1000000);\n interestAmount = loanAmount > repaymentAmount ? 0 : repaymentAmount.sub(loanAmount);\n }\n\n /* internal function, assuming repayment amount already transfered */\n function _repayLoan(uint loanId, uint repaymentAmount) internal {\n require(loanId < loans.length, \"invalid loanId\"); // next line would revert but require to emit reason\n LoanData storage loan = loans[loanId];\n require(loan.state == LoanState.Open, \"loan state must be Open\");\n require(repaymentAmount == loan.repaymentAmount, \"repaymentAmount must be equal to tokens sent\");\n require(now <= loan.maturity, \"current time must be earlier than maturity\");\n\n LoanProduct storage product = products[loan.productId];\n uint loanAmount;\n uint interestAmount;\n (loanAmount, interestAmount) = calculateLoanValues(product, loan.repaymentAmount);\n\n loans[loanId].state = LoanState.Repaid;\n\n if (interestAmount > 0) {\n augmintToken.transfer(monetarySupervisor.interestEarnedAccount(), interestAmount);\n augmintToken.burn(loanAmount);\n } else {\n // negative or zero interest (i.e. discountRate >= 0)\n augmintToken.burn(repaymentAmount);\n }\n\n monetarySupervisor.loanRepaymentNotification(loanAmount); // update KPIs\n\n loan.borrower.transfer(loan.collateralAmount); // send back ETH collateral\n\n emit LoanRepayed(loanId, loan.borrower);\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/999/Locker_DEPLOYS.json b/abiniser/deployments/999/Locker_DEPLOYS.json index 1391037f..13f9b037 100644 --- a/abiniser/deployments/999/Locker_DEPLOYS.json +++ b/abiniser/deployments/999/Locker_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "Locker", - "latestAbiHash": "619ff7809b73aead28176fe6317953c3", + "latestAbiHash": "f59526398823aef0f0c1454d0b6b4eac", "deployedAbis": { "6055e2cba8c8e9cb7e04b10e4c56ab9a": { "latestDeployedAddress": "0x8fd4d02f46ec6c92924780d2bf35ae31078db9c5", @@ -110,6 +110,24 @@ "source": "/* contract for tracking locked funds\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n -> self-destruct function?\n\n*/\n\npragma solidity 0.4.24;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n uint public constant CHUNK_SIZE = 100;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n event MonetarySupervisorChanged(MonetarySupervisor newMonetarySupervisor);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"StabilityBoard\") {\n\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId, \"lockProduct overflow\");\n emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"StabilityBoard\") {\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n\n lockProducts[lockProductId].isActive = isActive;\n emit LockProductActiveChange(lockProductId, isActive);\n\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n uint32 lockProductId = uint32(_lockProductId);\n require(lockProductId == _lockProductId, \"lockProductId overflow\");\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function releaseFunds(uint lockId) external {\n // next line would revert but require to emit reason:\n require(lockId < locks.length, \"invalid lockId\");\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive, \"lock must be in active state\");\n require(now >= lock.lockedUntil, \"current time must be later than lockedUntil\");\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n emit LockReleased(lock.owner, lockId);\n }\n\n function setMonetarySupervisor(MonetarySupervisor newMonetarySupervisor) external restrict(\"StabilityBoard\") {\n monetarySupervisor = newMonetarySupervisor;\n emit MonetarySupervisorChanged(newMonetarySupervisor);\n }\n\n function getLockProductCount() external view returns (uint) {\n\n return lockProducts.length;\n\n }\n\n // returns 20 lock products starting from some offset\n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ]\n function getLockProducts(uint offset) external view returns (uint[5][CHUNK_SIZE] response) {\n for (uint8 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= lockProducts.length) { break; }\n\n LockProduct storage lockProduct = lockProducts[offset + i];\n\n response[i] = [ lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount,\n monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest),\n lockProduct.isActive ? 1 : 0 ];\n }\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns CHUNK_SIZE locks starting from some offset\n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset) external view returns (uint[8][CHUNK_SIZE] response) {\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locks.length) { break; }\n\n Lock storage lock = locks[offset + i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [uint(offset + i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n }\n\n // returns CHUNK_SIZE locks of a given account, starting from some offset\n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset) external view returns (uint[7][CHUNK_SIZE] response) {\n\n uint[] storage locksForAddress = accountLocks[lockOwner];\n\n for (uint16 i = 0; i < CHUNK_SIZE; i++) {\n\n if (offset + i >= locksForAddress.length) { break; }\n\n Lock storage lock = locks[locksForAddress[offset + i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i] = [ locksForAddress[offset + i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).ceilDiv(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal returns(uint lockId) {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive, \"lockProduct must be in active state\");\n require(amountToLock >= lockProduct.minimumLockAmount, \"amountToLock must be >= minimumLockAmount\");\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration, \"lockedUntil overflow\");\n\n lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs);\n }\n\n}\n" } } + }, + "f59526398823aef0f0c1454d0b6b4eac": { + "latestDeployedAddress": "0x26b4ababb98fcadd579f28e9c30931bbbe66fc88", + "deployments": { + "0x26b4ababb98fcadd579f28e9c30931bbbe66fc88": { + "generatedAt": "2018-10-18T13:35:02.423Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.960Z", + "deployTransactionHash": "0xc7c614d66a755c9a7e1046a3eb03fb9caa64606d726368532dfea3de500bf2ba", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "0fe102ad0cf754658fdb075cb2850270", + "deployedBytecodeHash": "211e0b56eb9155bf091df2937a90551d", + "sourceHash": "5fb19771489eecebfa02e95214887146", + "source": "/* contract for tracking locked funds\n\n requirements\n -> lock funds\n -> unlock funds\n -> index locks by address\n\n For flows see: https://github.com/Augmint/augmint-contracts/blob/master/docs/lockFlow.png\n\n TODO / think about:\n -> self-destruct function?\n\n*/\n\npragma solidity 0.4.24;\n\nimport \"./generic/Restricted.sol\";\nimport \"./generic/SafeMath.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./MonetarySupervisor.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\n\n\ncontract Locker is Restricted, TokenReceiver {\n\n using SafeMath for uint256;\n\n event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs,\n uint32 minimumLockAmount, bool isActive);\n\n event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState);\n\n // NB: amountLocked includes the original amount, plus interest\n event NewLock(address indexed lockOwner, uint lockId, uint amountLocked, uint interestEarned,\n uint40 lockedUntil, uint32 perTermInterest, uint32 durationInSecs);\n\n event LockReleased(address indexed lockOwner, uint lockId);\n\n event MonetarySupervisorChanged(MonetarySupervisor newMonetarySupervisor);\n\n struct LockProduct {\n // perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n uint32 perTermInterest;\n uint32 durationInSecs;\n uint32 minimumLockAmount;\n bool isActive;\n }\n\n /* NB: we don't need to store lock parameters because lockProducts can't be altered (only disabled/enabled) */\n struct Lock {\n uint amountLocked;\n address owner;\n uint32 productId;\n uint40 lockedUntil;\n bool isActive;\n }\n\n AugmintTokenInterface public augmintToken;\n MonetarySupervisor public monetarySupervisor;\n\n LockProduct[] public lockProducts;\n\n Lock[] public locks;\n\n // lock ids for an account\n mapping(address => uint[]) public accountLocks;\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n MonetarySupervisor _monetarySupervisor)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n monetarySupervisor = _monetarySupervisor;\n\n }\n\n function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive)\n external restrict(\"StabilityBoard\") {\n uint _newLockProductId = lockProducts.push(\n LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1;\n uint32 newLockProductId = uint32(_newLockProductId);\n require(newLockProductId == _newLockProductId, \"lockProduct overflow\");\n emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive);\n }\n\n function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict(\"StabilityBoard\") {\n // next line would revert but require to emit reason:\n require(lockProductId < lockProducts.length, \"invalid lockProductId\");\n\n lockProducts[lockProductId].isActive = isActive;\n emit LockProductActiveChange(lockProductId, isActive);\n }\n\n /* lock funds, called from AugmintToken's transferAndNotify\n Flow for locking tokens:\n 1) user calls token contract's transferAndNotify lockProductId passed in data arg\n 2) transferAndNotify transfers tokens to the Lock contract\n 3) transferAndNotify calls Lock.transferNotification with lockProductId\n */\n function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external {\n require(msg.sender == address(augmintToken), \"msg.sender must be augmintToken\");\n // next line would revert but require to emit reason:\n require(_lockProductId < lockProducts.length, \"invalid lockProductId\");\n uint32 lockProductId = uint32(_lockProductId);\n /* TODO: make data arg generic bytes\n uint productId;\n assembly { // solhint-disable-line no-inline-assembly\n productId := mload(data)\n } */\n _createLock(lockProductId, from, amountToLock);\n }\n\n function releaseFunds(uint lockId) external {\n // next line would revert but require to emit reason:\n require(lockId < locks.length, \"invalid lockId\");\n Lock storage lock = locks[lockId];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n require(lock.isActive, \"lock must be in active state\");\n require(now >= lock.lockedUntil, \"current time must be later than lockedUntil\");\n\n lock.isActive = false;\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n monetarySupervisor.releaseFundsNotification(lock.amountLocked); // to maintain totalLockAmount\n augmintToken.transferWithNarrative(lock.owner, lock.amountLocked.add(interestEarned),\n \"Funds released from lock\");\n\n emit LockReleased(lock.owner, lockId);\n }\n\n function setMonetarySupervisor(MonetarySupervisor newMonetarySupervisor) external restrict(\"StabilityBoard\") {\n monetarySupervisor = newMonetarySupervisor;\n emit MonetarySupervisorChanged(newMonetarySupervisor);\n }\n\n function getLockProductCount() external view returns (uint) {\n return lockProducts.length;\n }\n\n // returns lock products starting from some \n // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ]\n function getLockProducts(uint offset, uint16 chunkSize)\n external view returns (uint[5][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), lockProducts.length);\n uint[5][] memory response = new uint[5][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n LockProduct storage lockProduct = lockProducts[i];\n response[i - offset] = [lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount,\n monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest),\n lockProduct.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function getLockCount() external view returns (uint) {\n return locks.length;\n }\n\n function getLockCountForAddress(address lockOwner) external view returns (uint) {\n return accountLocks[lockOwner].length;\n }\n\n // returns locks starting from some \n // lock products are encoded as\n // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%):\n function getLocks(uint offset, uint16 chunkSize)\n external view returns (uint[8][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), locks.length);\n uint[8][] memory response = new uint[8][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n Lock storage lock = locks[i];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i - offset] = [uint(i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0];\n }\n return response;\n }\n\n // returns locks of a given account, starting from some \n // lock products are encoded as\n // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ]\n function getLocksForAddress(address lockOwner, uint offset, uint16 chunkSize)\n external view returns (uint[7][]) {\n uint[] storage locksForAddress = accountLocks[lockOwner];\n uint limit = SafeMath.min(offset.add(chunkSize), locksForAddress.length);\n uint[7][] memory response = new uint[7][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n Lock storage lock = locks[locksForAddress[i]];\n LockProduct storage lockProduct = lockProducts[lock.productId];\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked);\n\n response[i - offset] = [locksForAddress[i], lock.amountLocked, interestEarned, lock.lockedUntil,\n lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ];\n }\n return response;\n }\n\n function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) {\n interestEarned = amountToLock.mul(perTermInterest).ceilDiv(1000000);\n }\n\n // Internal function. assumes amountToLock is already transferred to this Lock contract\n function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal {\n LockProduct storage lockProduct = lockProducts[lockProductId];\n require(lockProduct.isActive, \"lockProduct must be in active state\");\n require(amountToLock >= lockProduct.minimumLockAmount, \"amountToLock must be >= minimumLockAmount\");\n\n uint interestEarned = calculateInterest(lockProduct.perTermInterest, amountToLock);\n uint expiration = now.add(lockProduct.durationInSecs);\n uint40 lockedUntil = uint40(expiration);\n require(lockedUntil == expiration, \"lockedUntil overflow\");\n\n uint lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1;\n accountLocks[lockOwner].push(lockId);\n\n monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here\n\n emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest,\n lockProduct.durationInSecs);\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/999/Migrations_DEPLOYS.json b/abiniser/deployments/999/Migrations_DEPLOYS.json index a42d9c99..134c931d 100644 --- a/abiniser/deployments/999/Migrations_DEPLOYS.json +++ b/abiniser/deployments/999/Migrations_DEPLOYS.json @@ -6,15 +6,15 @@ "latestDeployedAddress": "0xd217ac4354211cda27dd4027b5e223280f885ad3", "deployments": { "0xd217ac4354211cda27dd4027b5e223280f885ad3": { - "generatedAt": "2018-08-14T19:51:17.977Z", - "truffleContractFileUpdatedAt": "2018-08-14T19:50:59.878Z", - "deployTransactionHash": "0x737edaecbaa92d4dcb7750dddd1bfa65a080dce09e88de3c7c09148136c72c23", + "generatedAt": "2018-10-18T13:35:02.323Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.823Z", + "deployTransactionHash": "0x844cbb39556551447a6dc5bc8a9298949e75f395a11329e133244ea06297133e", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "f0557c3c790f279d198ef1d54ea5f550", - "deployedBytecodeHash": "1c74c56a535b7d558a79121649239bdf", + "bytecodeHash": "3bd5779c94259890d586374c5db67f2b", + "deployedBytecodeHash": "f00491b62e24c57c6d12323c73c1037e", "sourceHash": "16ee1835a27505e14d1b6990cdfa8c2c", "source": "pragma solidity 0.4.24;\n\n\ncontract Migrations {\n address public owner;\n uint public last_completed_migration; // solhint-disable-line var-name-mixedcase\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n constructor() public {\n owner = msg.sender;\n }\n\n function setCompleted(uint completed) external restricted {\n last_completed_migration = completed;\n }\n\n function upgrade(address newAddress) external restricted {\n Migrations upgraded = Migrations(newAddress);\n upgraded.setCompleted(last_completed_migration);\n }\n}\n" }, diff --git a/abiniser/deployments/999/MonetarySupervisor_DEPLOYS.json b/abiniser/deployments/999/MonetarySupervisor_DEPLOYS.json index 0e99980a..fd7ad419 100644 --- a/abiniser/deployments/999/MonetarySupervisor_DEPLOYS.json +++ b/abiniser/deployments/999/MonetarySupervisor_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "MonetarySupervisor", - "latestAbiHash": "54d27fedd8bf3010ad5509866a42c053", + "latestAbiHash": "7f500b43397413e97de925528187f9cd", "deployedAbis": { "066c2220b91befd25691fefd91684117": { "latestDeployedAddress": "0x88166fdc3c3e6768c375488fa45c90f1b904a767", @@ -105,6 +105,24 @@ "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n - Converts older versions of AugmintTokens in 1:1 to new\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n uint public constant PERCENT_100 = 1000000;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByStabilityBoard; // token issued by Stability Board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /**********\n Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works\n when total loan or lock amounts are low.\n for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0\n **********/\n struct LtdParams {\n uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above\n (1 - lockDifferenceLimit) with new lock. Stored as parts per million */\n uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above\n (1 + loanDifferenceLimit) with new loan. Stored as parts per million */\n /* allowedDifferenceAmount param is to ensure the system is not \"freezing\" when totalLoanAmount or\n totalLockAmount is low.\n It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above\n lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */\n uint allowedDifferenceAmount;\n }\n\n LtdParams public ltdParams;\n\n /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() )\n NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */\n mapping(address => bool) public acceptedLegacyAugmintTokens;\n\n event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount);\n\n event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState);\n\n event LegacyTokenConverted(address oldTokenAddress, address account, uint amount);\n\n event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment);\n\n event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, AugmintReserves _augmintReserves,\n InterestEarnedAccount _interestEarnedAccount,\n uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n function issueToReserve(uint amount) external restrict(\"StabilityBoard\") {\n issuedByStabilityBoard = issuedByStabilityBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"StabilityBoard\") {\n issuedByStabilityBoard = issuedByStabilityBoard.sub(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function requestInterest(uint amountToLock, uint interestAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n require(amountToLock <= getMaxLockAmountAllowedByLtd(), \"amountToLock must be <= maxLockAmountAllowedByLtd\");\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n // next line would revert but require to emit reason:\n require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount,\n \"interestEarnedAccount balance must be >= interestAmount\");\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n /* Issue loan if LTD stays within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function issueLoan(address borrower, uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n require(loanAmount <= getMaxLoanAmountAllowedByLtd(), \"loanAmount must be <= maxLoanAmountAllowedByLtd\");\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState)\n external restrict(\"StabilityBoard\") {\n acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState;\n emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState);\n }\n\n function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n external restrict(\"StabilityBoard\") {\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n\n emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract\n when it's upgraded.\n Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */\n function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment)\n external restrict(\"StabilityBoard\") {\n totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment);\n totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment);\n\n emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment);\n }\n\n /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */\n function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves)\n external restrict(\"StabilityBoard\") {\n interestEarnedAccount = newInterestEarnedAccount;\n augmintReserves = newAugmintReserves;\n emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves);\n }\n\n /* User can request to convert their tokens from older AugmintToken versions in 1:1\n transferNotification is called from AugmintToken's transferAndNotify\n Flow for converting old tokens:\n 1) user calls old token contract's transferAndNotify with the amount to convert,\n addressing the new MonetarySupervisor Contract\n 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address\n 3) transferAndNotify calls MonetarySupervisor.transferNotification\n 4) MonetarySupervisor checks if old AugmintToken is permitted\n 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken\n 6) MonetarySupervisor burns old tokens from own balance\n */\n function transferNotification(address from, uint amount, uint /* data, not used */ ) external {\n AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender);\n require(acceptedLegacyAugmintTokens[legacyToken], \"msg.sender must be allowed in acceptedLegacyAugmintTokens\");\n\n legacyToken.burn(amount);\n augmintToken.issueTo(from, amount);\n emit LegacyTokenConverted(msg.sender, from, amount);\n }\n\n function getLoanToDepositRatio() external view returns (uint loanToDepositRatio) {\n loanToDepositRatio = totalLockedAmount == 0 ? 0 : totalLockedAmount.mul(PERCENT_100).div(totalLoanAmount);\n }\n\n /* Helper function for UI.\n Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */\n function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) {\n uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt);\n uint allowedByLtd = getMaxLockAmountAllowedByLtd();\n maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd;\n maxLock = maxLock < minLockAmount ? 0 : maxLock;\n }\n\n /* Helper function for UI.\n Returns max loan amount based on minLoanAmont using LTD params */\n function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) {\n uint allowedByLtd = getMaxLoanAmountAllowedByLtd();\n maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd;\n }\n\n /* returns maximum lockable token amount allowed by LTD params. */\n function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) {\n uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100\n .sub(ltdParams.lockDifferenceLimit));\n allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLockedAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLockedAmount >= totalLoanAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount);\n\n maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n /* returns maximum borrowable token amount allowed by LTD params */\n function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) {\n uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100))\n .div(PERCENT_100);\n allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLoanAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount >= totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount);\n\n maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n}\n" } } + }, + "7f500b43397413e97de925528187f9cd": { + "latestDeployedAddress": "0x1555469d4a6c063a13ff1e12ca4ab00f5f1b7320", + "deployments": { + "0x1555469d4a6c063a13ff1e12ca4ab00f5f1b7320": { + "generatedAt": "2018-10-18T13:35:02.380Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.944Z", + "deployTransactionHash": "0xb223be3763733e04d2188b04764e06c50bc9dd51bf7ac414e5d44a117631d7e1", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "fa3e6bca24f24d5945b149c05701b69c", + "deployedBytecodeHash": "422b205eb739ddcf33fadad8edf32d7e", + "sourceHash": "62748c793556775f9ac607b991886bfb", + "source": "/* MonetarySupervisor\n - maintains system wide KPIs (eg totalLockAmount, totalLoanAmount)\n - holds system wide parameters/limits\n - enforces system wide limits\n - burns and issues to AugmintReserves\n - Send funds from reserve to exchange when intervening (not implemented yet)\n - Converts older versions of AugmintTokens in 1:1 to new\n*/\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\nimport \"./interfaces/AugmintTokenInterface.sol\";\nimport \"./interfaces/TokenReceiver.sol\";\nimport \"./InterestEarnedAccount.sol\";\nimport \"./AugmintReserves.sol\";\n\n\ncontract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-line no-empty-blocks\n using SafeMath for uint256;\n\n uint public constant PERCENT_100 = 1000000;\n\n AugmintTokenInterface public augmintToken;\n InterestEarnedAccount public interestEarnedAccount;\n AugmintReserves public augmintReserves;\n\n uint public issuedByStabilityBoard; // token issued by Stability Board\n uint public burnedByStabilityBoard; // token burned by Stability Board\n\n uint public totalLoanAmount; // total amount of all loans without interest, in token\n uint public totalLockedAmount; // total amount of all locks without premium, in token\n\n /**********\n Parameters to ensure totalLoanAmount or totalLockedAmount difference is within limits and system also works\n when total loan or lock amounts are low.\n for test calculations: https://docs.google.com/spreadsheets/d/1MeWYPYZRIm1n9lzpvbq8kLfQg1hhvk5oJY6NrR401S0\n **********/\n struct LtdParams {\n uint lockDifferenceLimit; /* only allow a new lock if Loan To Deposit ratio would stay above\n (1 - lockDifferenceLimit) with new lock. Stored as parts per million */\n uint loanDifferenceLimit; /* only allow a new loan if Loan To Deposit ratio would stay above\n (1 + loanDifferenceLimit) with new loan. Stored as parts per million */\n /* allowedDifferenceAmount param is to ensure the system is not \"freezing\" when totalLoanAmount or\n totalLockAmount is low.\n It allows a new loan or lock (up to an amount to reach this difference) even if LTD will go below / above\n lockDifferenceLimit / loanDifferenceLimit with the new lock/loan */\n uint allowedDifferenceAmount;\n }\n\n LtdParams public ltdParams;\n\n /* Previously deployed AugmintTokens which are accepted for conversion (see transferNotification() )\n NB: it's not iterable so old version addresses needs to be added for UI manually after each deploy */\n mapping(address => bool) public acceptedLegacyAugmintTokens;\n\n event LtdParamsChanged(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount);\n\n event AcceptedLegacyAugmintTokenChanged(address augmintTokenAddress, bool newAcceptedState);\n\n event LegacyTokenConverted(address oldTokenAddress, address account, uint amount);\n\n event KPIsAdjusted(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment);\n\n event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves);\n\n constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken,\n AugmintReserves _augmintReserves, InterestEarnedAccount _interestEarnedAccount,\n uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n public Restricted(permissionGranterContract) {\n augmintToken = _augmintToken;\n augmintReserves = _augmintReserves;\n interestEarnedAccount = _interestEarnedAccount;\n\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n function issueToReserve(uint amount) external restrict(\"StabilityBoard\") {\n issuedByStabilityBoard = issuedByStabilityBoard.add(amount);\n augmintToken.issueTo(augmintReserves, amount);\n }\n\n function burnFromReserve(uint amount) external restrict(\"StabilityBoard\") {\n burnedByStabilityBoard = burnedByStabilityBoard.add(amount);\n augmintReserves.burn(augmintToken, amount);\n }\n\n /* Locker requesting interest when locking funds. Enforcing LTD to stay within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function requestInterest(uint amountToLock, uint interestAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n require(amountToLock <= getMaxLockAmountAllowedByLtd(), \"amountToLock must be <= maxLockAmountAllowedByLtd\");\n\n totalLockedAmount = totalLockedAmount.add(amountToLock);\n // next line would revert but require to emit reason:\n require(augmintToken.balanceOf(address(interestEarnedAccount)) >= interestAmount,\n \"interestEarnedAccount balance must be >= interestAmount\");\n interestEarnedAccount.transferInterest(augmintToken, msg.sender, interestAmount); // transfer interest to Locker\n }\n\n // Locker notifying when releasing funds to update KPIs\n function releaseFundsNotification(uint lockedAmount) external {\n // only whitelisted Locker\n require(permissions[msg.sender][\"Locker\"], \"msg.sender must have Locker permission\");\n totalLockedAmount = totalLockedAmount.sub(lockedAmount);\n }\n\n /* Issue loan if LTD stays within range allowed by LTD params\n NB: it does not know about min loan amount, it's the loan contract's responsibility to enforce it */\n function issueLoan(address borrower, uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n require(loanAmount <= getMaxLoanAmountAllowedByLtd(), \"loanAmount must be <= maxLoanAmountAllowedByLtd\");\n totalLoanAmount = totalLoanAmount.add(loanAmount);\n augmintToken.issueTo(borrower, loanAmount);\n }\n\n function loanRepaymentNotification(uint loanAmount) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(loanAmount);\n }\n\n // NB: this is called by Lender contract with the sum of all loans collected in batch\n function loanCollectionNotification(uint totalLoanAmountCollected) external {\n // only whitelisted LoanManager contracts\n require(permissions[msg.sender][\"LoanManager\"],\n \"msg.sender must have LoanManager permission\");\n totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected);\n }\n\n function setAcceptedLegacyAugmintToken(address legacyAugmintTokenAddress, bool newAcceptedState)\n external restrict(\"StabilityBoard\") {\n acceptedLegacyAugmintTokens[legacyAugmintTokenAddress] = newAcceptedState;\n emit AcceptedLegacyAugmintTokenChanged(legacyAugmintTokenAddress, newAcceptedState);\n }\n\n function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount)\n external restrict(\"StabilityBoard\") {\n ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount);\n }\n\n /* function to migrate old totalLoanAmount and totalLockedAmount from old monetarySupervisor contract\n when it's upgraded.\n Set new monetarySupervisor contract in all locker and loanManager contracts before executing this */\n function adjustKPIs(uint totalLoanAmountAdjustment, uint totalLockedAmountAdjustment)\n external restrict(\"StabilityBoard\") {\n totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment);\n totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment);\n emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment);\n }\n\n /* to allow upgrades of InterestEarnedAccount and AugmintReserves contracts. */\n function setSystemContracts(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves)\n external restrict(\"StabilityBoard\") {\n interestEarnedAccount = newInterestEarnedAccount;\n augmintReserves = newAugmintReserves;\n emit SystemContractsChanged(newInterestEarnedAccount, newAugmintReserves);\n }\n\n /* User can request to convert their tokens from older AugmintToken versions in 1:1\n transferNotification is called from AugmintToken's transferAndNotify\n Flow for converting old tokens:\n 1) user calls old token contract's transferAndNotify with the amount to convert,\n addressing the new MonetarySupervisor Contract\n 2) transferAndNotify transfers user's old tokens to the current MonetarySupervisor contract's address\n 3) transferAndNotify calls MonetarySupervisor.transferNotification\n 4) MonetarySupervisor checks if old AugmintToken is permitted\n 5) MonetarySupervisor issues new tokens to user's account in current AugmintToken\n 6) MonetarySupervisor burns old tokens from own balance\n */\n function transferNotification(address from, uint amount, uint /* data, not used */ ) external {\n AugmintTokenInterface legacyToken = AugmintTokenInterface(msg.sender);\n require(acceptedLegacyAugmintTokens[legacyToken], \"msg.sender must be allowed in acceptedLegacyAugmintTokens\");\n\n legacyToken.burn(amount);\n augmintToken.issueTo(from, amount);\n emit LegacyTokenConverted(msg.sender, from, amount);\n }\n\n /* Helper function for UI.\n Returns max lock amount based on minLockAmount, interestPt, using LTD params & interestEarnedAccount balance */\n function getMaxLockAmount(uint minLockAmount, uint interestPt) external view returns (uint maxLock) {\n uint allowedByEarning = augmintToken.balanceOf(address(interestEarnedAccount)).mul(PERCENT_100).div(interestPt);\n uint allowedByLtd = getMaxLockAmountAllowedByLtd();\n maxLock = allowedByEarning < allowedByLtd ? allowedByEarning : allowedByLtd;\n maxLock = maxLock < minLockAmount ? 0 : maxLock;\n }\n\n /* Helper function for UI.\n Returns max loan amount based on minLoanAmont using LTD params */\n function getMaxLoanAmount(uint minLoanAmount) external view returns (uint maxLoan) {\n uint allowedByLtd = getMaxLoanAmountAllowedByLtd();\n maxLoan = allowedByLtd < minLoanAmount ? 0 : allowedByLtd;\n }\n\n /* returns maximum lockable token amount allowed by LTD params. */\n function getMaxLockAmountAllowedByLtd() public view returns(uint maxLockByLtd) {\n uint allowedByLtdDifferencePt = totalLoanAmount.mul(PERCENT_100).div(PERCENT_100\n .sub(ltdParams.lockDifferenceLimit));\n allowedByLtdDifferencePt = totalLockedAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLockedAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLockedAmount >= totalLoanAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLoanAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLockedAmount);\n\n maxLockByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n\n /* returns maximum borrowable token amount allowed by LTD params */\n function getMaxLoanAmountAllowedByLtd() public view returns(uint maxLoanByLtd) {\n uint allowedByLtdDifferencePt = totalLockedAmount.mul(ltdParams.loanDifferenceLimit.add(PERCENT_100))\n .div(PERCENT_100);\n allowedByLtdDifferencePt = totalLoanAmount >= allowedByLtdDifferencePt ?\n 0 : allowedByLtdDifferencePt.sub(totalLoanAmount);\n\n uint allowedByLtdDifferenceAmount =\n totalLoanAmount >= totalLockedAmount.add(ltdParams.allowedDifferenceAmount) ?\n 0 : totalLockedAmount.add(ltdParams.allowedDifferenceAmount).sub(totalLoanAmount);\n\n maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ?\n allowedByLtdDifferencePt : allowedByLtdDifferenceAmount;\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/999/PreTokenProxy_DEPLOYS.json b/abiniser/deployments/999/PreTokenProxy_DEPLOYS.json index 44035ae0..56fa4398 100644 --- a/abiniser/deployments/999/PreTokenProxy_DEPLOYS.json +++ b/abiniser/deployments/999/PreTokenProxy_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "PreTokenProxy", - "latestAbiHash": "19ab69b650e28b2dd211d3851893f91f", + "latestAbiHash": "dd40c0d39ea8bad8a388522667a84687", "deployedAbis": { "19ab69b650e28b2dd211d3851893f91f": { "latestDeployedAddress": "0x8b639dc72f3e640c0d6bc19497fbc7b5160d0463", @@ -19,6 +19,24 @@ "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract PreTokenProxy is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" } } + }, + "dd40c0d39ea8bad8a388522667a84687": { + "latestDeployedAddress": "0x8b639dc72f3e640c0d6bc19497fbc7b5160d0463", + "deployments": { + "0x8b639dc72f3e640c0d6bc19497fbc7b5160d0463": { + "generatedAt": "2018-10-18T13:35:02.452Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.836Z", + "deployTransactionHash": "0xca9e92624b1c86721a4e6804e793b8b87606564f302d28ddefb2f560158e9415", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "5007bce3d0997985a9357d5b1a97103b", + "deployedBytecodeHash": "b5a32ad0b8570f3cd6b7efaef3655911", + "sourceHash": "2d172fe41d2b97c827d6dca816138047", + "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract PreTokenProxy is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/999/PreToken_DEPLOYS.json b/abiniser/deployments/999/PreToken_DEPLOYS.json index e5aeb423..63f25753 100644 --- a/abiniser/deployments/999/PreToken_DEPLOYS.json +++ b/abiniser/deployments/999/PreToken_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "PreToken", - "latestAbiHash": "10eebbb51a771cfd3473475169a569f1", + "latestAbiHash": "7f69e33e7b345c780ac9e43f391437d9", "deployedAbis": { "771887af92db4b4330d700538df6e490": { "latestDeployedAddress": "0xbed57eb0b4232da0cddd3c9c27490fc0759e0a01", @@ -37,6 +37,24 @@ "source": "/* Augmint pretoken contract to record agreements and tokens allocated based on the agreement.\n\n Important: this is NOT an ERC20 token!\n\n PreTokens are non-fungible: agreements can have different conditions (valuationCap and discount)\n and pretokens are not tradable.\n\n Ownership can be transferred if owner wants to change wallet but the whole agreement and\n the total pretoken amount is moved to a new account\n\n PreTokenSigner can (via MultiSig):\n - add agreements and issue pretokens to an agreement\n - change owner of any agreement to handle if an owner lost a private keys\n - burn pretokens from any agreement to fix potential erroneous issuance\n These are known compromises on trustlessness hence all these tokens distributed based on signed agreements and\n preTokens are issued only to a closed group of contributors / team members.\n If despite these something goes wrong then as a last resort a new pretoken contract can be recreated from agreements.\n\n Some ERC20 functions are implemented so agreement owners can see their balances and use transfer in standard wallets.\n Restrictions:\n - only total balance can be transfered - effectively ERC20 transfer used to transfer agreement ownership\n - only agreement holders can transfer\n (i.e. can't transfer 0 amount if have no agreement to avoid polluting logs with Transfer events)\n - transfer is only allowed to accounts without an agreement yet\n - no approval and transferFrom ERC20 functions\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract PreToken is Restricted {\n using SafeMath for uint256;\n\n uint public constant CHUNK_SIZE = 100;\n\n string constant public name = \"Augmint pretokens\"; // solhint-disable-line const-name-snakecase\n string constant public symbol = \"APRE\"; // solhint-disable-line const-name-snakecase\n uint8 constant public decimals = 0; // solhint-disable-line const-name-snakecase\n\n uint public totalSupply;\n\n struct Agreement {\n address owner;\n uint balance;\n uint32 discount; // discountRate in parts per million , ie. 10,000 = 1%\n uint32 valuationCap; // in USD (no decimals)\n }\n\n /* Agreement hash is the SHA-2 (SHA-256) hash of signed agreement document.\n To generate:\n OSX: shasum -a 256 agreement.pdf\n Windows: certUtil -hashfile agreement.pdf SHA256 */\n mapping(address => bytes32) public agreementOwners; // to lookup agrement by owner\n mapping(bytes32 => Agreement) public agreements;\n\n bytes32[] public allAgreements; // all agreements to able to iterate over\n\n event Transfer(address indexed from, address indexed to, uint amount);\n\n event NewAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap);\n\n constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function addAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap)\n external restrict(\"PreTokenSigner\") {\n require(owner != address(0), \"owner must not be 0x0\");\n require(agreementOwners[owner] == 0x0, \"owner must not have an aggrement yet\");\n require(agreementHash != 0x0, \"agreementHash must not be 0x0\");\n require(discount > 0, \"discount must be > 0\");\n require(agreements[agreementHash].discount == 0, \"agreement must not exist yet\");\n\n agreements[agreementHash] = Agreement(owner, 0, discount, valuationCap);\n agreementOwners[owner] = agreementHash;\n allAgreements.push(agreementHash);\n\n emit NewAgreement(owner, agreementHash, discount, valuationCap);\n }\n\n function issueTo(bytes32 agreementHash, uint amount) external restrict(\"PreTokenSigner\") {\n Agreement storage agreement = agreements[agreementHash];\n require(agreement.discount > 0, \"agreement must exist\");\n\n agreement.balance = agreement.balance.add(amount);\n totalSupply = totalSupply.add(amount);\n\n emit Transfer(0x0, agreement.owner, amount);\n }\n\n /* Restricted function to allow pretoken signers to fix incorrect issuance */\n function burnFrom(bytes32 agreementHash, uint amount)\n public restrict(\"PreTokenSigner\") returns (bool) {\n Agreement storage agreement = agreements[agreementHash];\n require(agreement.discount > 0, \"agreement must exist\"); // this is redundant b/c of next requires but be explicit\n require(amount > 0, \"burn amount must be > 0\");\n require(agreement.balance >= amount, \"must not burn more than balance\"); // .sub would revert anyways but emit reason\n\n agreement.balance = agreement.balance.sub(amount);\n totalSupply = totalSupply.sub(amount);\n\n emit Transfer(agreement.owner, 0x0, amount);\n return true;\n }\n\n function balanceOf(address owner) public view returns (uint) {\n return agreements[agreementOwners[owner]].balance;\n }\n\n /* function to transfer agreement ownership to other wallet by owner\n it's in ERC20 form so owners can use standard ERC20 wallet just need to pass full balance as value */\n function transfer(address to, uint amount) public returns (bool) { // solhint-disable-line no-simple-event-func-name\n require(amount == agreements[agreementOwners[msg.sender]].balance, \"must transfer full balance\");\n _transfer(msg.sender, to);\n return true;\n }\n\n /* Restricted function to allow pretoken signers to fix if pretoken owner lost keys */\n function transferAgreement(bytes32 agreementHash, address to)\n public restrict(\"PreTokenSigner\") returns (bool) {\n _transfer(agreements[agreementHash].owner, to);\n return true;\n }\n\n /* private function used by transferAgreement & transfer */\n function _transfer(address from, address to) private {\n Agreement storage agreement = agreements[agreementOwners[from]];\n require(agreementOwners[from] != 0x0, \"from agreement must exists\");\n require(agreementOwners[to] == 0, \"to must not have an agreement\");\n require(to != 0x0, \"must not transfer to 0x0\");\n\n agreement.owner = to;\n\n agreementOwners[to] = agreementOwners[from];\n agreementOwners[from] = 0x0;\n\n emit Transfer(from, to, agreement.balance);\n }\n\n function getAgreementsCount() external view returns (uint agreementsCount) {\n return allAgreements.length;\n }\n\n // UI helper fx - Returns all agreements from offset as\n // [index in allAgreements, account address as uint, balance, agreementHash as uint,\n // discount as uint, valuationCap as uint ]\n function getAllAgreements(uint offset) external view returns(uint[6][CHUNK_SIZE] agreementsResult) {\n\n for (uint8 i = 0; i < CHUNK_SIZE && i + offset < allAgreements.length; i++) {\n bytes32 agreementHash = allAgreements[i + offset];\n Agreement storage agreement = agreements[agreementHash];\n\n agreementsResult[i] = [ i + offset, uint(agreement.owner), agreement.balance,\n uint(agreementHash), uint(agreement.discount), uint(agreement.valuationCap)];\n }\n }\n}\n" } } + }, + "7f69e33e7b345c780ac9e43f391437d9": { + "latestDeployedAddress": "0xbed57eb0b4232da0cddd3c9c27490fc0759e0a01", + "deployments": { + "0xbed57eb0b4232da0cddd3c9c27490fc0759e0a01": { + "generatedAt": "2018-10-18T13:35:02.470Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.930Z", + "deployTransactionHash": "0x1ece2c264ca1d3e1252bf27f7aea6598218bf72007b66f965338a63f92642306", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "8d7e449258facd1c6fab22b402de6aee", + "deployedBytecodeHash": "bf64976158eb4f8696efd994652e7f49", + "sourceHash": "6cace117c42478e4f5c8cf116bec9a62", + "source": "/* Augmint pretoken contract to record agreements and tokens allocated based on the agreement.\n\n Important: this is NOT an ERC20 token!\n\n PreTokens are non-fungible: agreements can have different conditions (valuationCap and discount)\n and pretokens are not tradable.\n\n Ownership can be transferred if owner wants to change wallet but the whole agreement and\n the total pretoken amount is moved to a new account\n\n PreTokenSigner can (via MultiSig):\n - add agreements and issue pretokens to an agreement\n - change owner of any agreement to handle if an owner lost a private keys\n - burn pretokens from any agreement to fix potential erroneous issuance\n These are known compromises on trustlessness hence all these tokens distributed based on signed agreements and\n preTokens are issued only to a closed group of contributors / team members.\n If despite these something goes wrong then as a last resort a new pretoken contract can be recreated from agreements.\n\n Some ERC20 functions are implemented so agreement owners can see their balances and use transfer in standard wallets.\n Restrictions:\n - only total balance can be transfered - effectively ERC20 transfer used to transfer agreement ownership\n - only agreement holders can transfer\n (i.e. can't transfer 0 amount if have no agreement to avoid polluting logs with Transfer events)\n - transfer is only allowed to accounts without an agreement yet\n - no approval and transferFrom ERC20 functions\n */\n\npragma solidity 0.4.24;\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract PreToken is Restricted {\n using SafeMath for uint256;\n\n string constant public name = \"Augmint pretokens\"; // solhint-disable-line const-name-snakecase\n string constant public symbol = \"APRE\"; // solhint-disable-line const-name-snakecase\n uint8 constant public decimals = 0; // solhint-disable-line const-name-snakecase\n\n uint public totalSupply;\n\n struct Agreement {\n address owner;\n uint balance;\n uint32 discount; // discountRate in parts per million , ie. 10,000 = 1%\n uint32 valuationCap; // in USD (no decimals)\n }\n\n /* Agreement hash is the SHA-2 (SHA-256) hash of signed agreement document.\n To generate:\n OSX: shasum -a 256 agreement.pdf\n Windows: certUtil -hashfile agreement.pdf SHA256 */\n mapping(address => bytes32) public agreementOwners; // to lookup agrement by owner\n mapping(bytes32 => Agreement) public agreements;\n\n bytes32[] public allAgreements; // all agreements to able to iterate over\n\n event Transfer(address indexed from, address indexed to, uint amount);\n\n event NewAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap);\n\n constructor(address permissionGranterContract)\n public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function addAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap)\n external restrict(\"PreTokenSigner\") {\n require(owner != address(0), \"owner must not be 0x0\");\n require(agreementOwners[owner] == 0x0, \"owner must not have an aggrement yet\");\n require(agreementHash != 0x0, \"agreementHash must not be 0x0\");\n require(discount > 0, \"discount must be > 0\");\n require(agreements[agreementHash].discount == 0, \"agreement must not exist yet\");\n\n agreements[agreementHash] = Agreement(owner, 0, discount, valuationCap);\n agreementOwners[owner] = agreementHash;\n allAgreements.push(agreementHash);\n\n emit NewAgreement(owner, agreementHash, discount, valuationCap);\n }\n\n function issueTo(bytes32 agreementHash, uint amount) external restrict(\"PreTokenSigner\") {\n Agreement storage agreement = agreements[agreementHash];\n require(agreement.discount > 0, \"agreement must exist\");\n\n agreement.balance = agreement.balance.add(amount);\n totalSupply = totalSupply.add(amount);\n\n emit Transfer(0x0, agreement.owner, amount);\n }\n\n /* Restricted function to allow pretoken signers to fix incorrect issuance */\n function burnFrom(bytes32 agreementHash, uint amount)\n public restrict(\"PreTokenSigner\") returns (bool) {\n Agreement storage agreement = agreements[agreementHash];\n // this is redundant b/c of next requires but be explicit\n require(agreement.discount > 0, \"agreement must exist\");\n require(amount > 0, \"burn amount must be > 0\");\n // .sub would revert anyways but emit reason\n require(agreement.balance >= amount, \"must not burn more than balance\");\n\n agreement.balance = agreement.balance.sub(amount);\n totalSupply = totalSupply.sub(amount);\n\n emit Transfer(agreement.owner, 0x0, amount);\n return true;\n }\n\n function balanceOf(address owner) public view returns (uint) {\n return agreements[agreementOwners[owner]].balance;\n }\n\n /* function to transfer agreement ownership to other wallet by owner\n it's in ERC20 form so owners can use standard ERC20 wallet just need to pass full balance as value */\n function transfer(address to, uint amount) public returns (bool) { // solhint-disable-line no-simple-event-func-name\n require(amount == agreements[agreementOwners[msg.sender]].balance, \"must transfer full balance\");\n _transfer(msg.sender, to);\n return true;\n }\n\n /* Restricted function to allow pretoken signers to fix if pretoken owner lost keys */\n function transferAgreement(bytes32 agreementHash, address to)\n public restrict(\"PreTokenSigner\") returns (bool) {\n _transfer(agreements[agreementHash].owner, to);\n return true;\n }\n\n /* private function used by transferAgreement & transfer */\n function _transfer(address from, address to) private {\n Agreement storage agreement = agreements[agreementOwners[from]];\n require(agreementOwners[from] != 0x0, \"from agreement must exists\");\n require(agreementOwners[to] == 0, \"to must not have an agreement\");\n require(to != 0x0, \"must not transfer to 0x0\");\n\n agreement.owner = to;\n\n agreementOwners[to] = agreementOwners[from];\n agreementOwners[from] = 0x0;\n\n emit Transfer(from, to, agreement.balance);\n }\n\n function getAgreementsCount() external view returns (uint agreementsCount) {\n return allAgreements.length;\n }\n\n // UI helper fx - Returns agreements from as\n // [index in allAgreements, account address as uint, balance, agreementHash as uint,\n // discount as uint, valuationCap as uint ]\n function getAgreements(uint offset, uint16 chunkSize)\n external view returns(uint[6][]) {\n uint limit = SafeMath.min(offset.add(chunkSize), allAgreements.length);\n uint[6][] memory response = new uint[6][](limit.sub(offset));\n\n for (uint i = offset; i < limit; i++) {\n bytes32 agreementHash = allAgreements[i];\n Agreement storage agreement = agreements[agreementHash];\n\n response[i - offset] = [i, uint(agreement.owner), agreement.balance,\n uint(agreementHash), uint(agreement.discount), uint(agreement.valuationCap)];\n }\n return response;\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/999/Rates_DEPLOYS.json b/abiniser/deployments/999/Rates_DEPLOYS.json index ae809bcd..d55d7560 100644 --- a/abiniser/deployments/999/Rates_DEPLOYS.json +++ b/abiniser/deployments/999/Rates_DEPLOYS.json @@ -67,15 +67,15 @@ "latestDeployedAddress": "0xb0a2a8e846b66c7384f52635cecef5280f766c8b", "deployments": { "0xb0a2a8e846b66c7384f52635cecef5280f766c8b": { - "generatedAt": "2018-08-14T19:51:17.990Z", - "truffleContractFileUpdatedAt": "2018-08-14T19:50:59.288Z", - "deployTransactionHash": "0xd7b28efa9d325c552fbfc7f8ae1a7e0dca8e6c5a949cda73affa543510a80c7d", + "generatedAt": "2018-10-18T13:35:02.334Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.909Z", + "deployTransactionHash": "0x5c42470dba96ffc854c98239f1488b3698d35fb6acd9f425bcb305244d26bc48", "compiler": { "name": "solc", "version": "0.4.24+commit.e67f0147.Emscripten.clang" }, - "bytecodeHash": "04689dd6b3c8ee975398922d6224ae2e", - "deployedBytecodeHash": "f1694ef92f80df34281111e87816e07a", + "bytecodeHash": "be17116585b9b88d60fbe06a5499b6dc", + "deployedBytecodeHash": "0f403183577dac202159e32b1c8c9f44", "sourceHash": "c65f6945fead6118910fccc8bca7494c", "source": "/*\n Generic symbol / WEI rates contract.\n only callable by trusted price oracles.\n Being regularly called by a price oracle\n TODO: trustless/decentrilezed price Oracle\n TODO: shall we use blockNumber instead of now for lastUpdated?\n TODO: consider if we need storing rates with variable decimals instead of fixed 4\n TODO: could we emit 1 RateChanged event from setMultipleRates (symbols and newrates arrays)?\n*/\npragma solidity 0.4.24;\n\nimport \"./generic/SafeMath.sol\";\nimport \"./generic/Restricted.sol\";\n\n\ncontract Rates is Restricted {\n using SafeMath for uint256;\n\n struct RateInfo {\n uint rate; // how much 1 WEI worth 1 unit , i.e. symbol/ETH rate\n // 0 rate means no rate info available\n uint lastUpdated;\n }\n\n // mapping currency symbol => rate. all rates are stored with 2 decimals. i.e. EUR/ETH = 989.12 then rate = 98912\n mapping(bytes32 => RateInfo) public rates;\n\n event RateChanged(bytes32 symbol, uint newRate);\n\n constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks\n\n function setRate(bytes32 symbol, uint newRate) external restrict(\"RatesFeeder\") {\n rates[symbol] = RateInfo(newRate, now);\n emit RateChanged(symbol, newRate);\n }\n\n function setMultipleRates(bytes32[] symbols, uint[] newRates) external restrict(\"RatesFeeder\") {\n require(symbols.length == newRates.length, \"symobls and newRates lengths must be equal\");\n for (uint256 i = 0; i < symbols.length; i++) {\n rates[symbols[i]] = RateInfo(newRates[i], now);\n emit RateChanged(symbols[i], newRates[i]);\n }\n }\n\n function convertFromWei(bytes32 bSymbol, uint weiValue) external view returns(uint value) {\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n return weiValue.mul(rates[bSymbol].rate).roundedDiv(1000000000000000000);\n }\n\n function convertToWei(bytes32 bSymbol, uint value) external view returns(uint weiValue) {\n // next line would revert with div by zero but require to emit reason\n require(rates[bSymbol].rate > 0, \"rates[bSymbol] must be > 0\");\n /* TODO: can we make this not loosing max scale? */\n return value.mul(1000000000000000000).roundedDiv(rates[bSymbol].rate);\n }\n\n}\n" } diff --git a/abiniser/deployments/999/StabilityBoardProxy_DEPLOYS.json b/abiniser/deployments/999/StabilityBoardProxy_DEPLOYS.json index 1fdfa90b..aecf092f 100644 --- a/abiniser/deployments/999/StabilityBoardProxy_DEPLOYS.json +++ b/abiniser/deployments/999/StabilityBoardProxy_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "StabilityBoardProxy", - "latestAbiHash": "19ab69b650e28b2dd211d3851893f91f", + "latestAbiHash": "dd40c0d39ea8bad8a388522667a84687", "deployedAbis": { "19ab69b650e28b2dd211d3851893f91f": { "latestDeployedAddress": "0xd3ef19679c2dbbf3b8e2077c61b88f5e9c6178eb", @@ -19,6 +19,24 @@ "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract StabilityBoardProxy is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" } } + }, + "dd40c0d39ea8bad8a388522667a84687": { + "latestDeployedAddress": "0xd3ef19679c2dbbf3b8e2077c61b88f5e9c6178eb", + "deployments": { + "0xd3ef19679c2dbbf3b8e2077c61b88f5e9c6178eb": { + "generatedAt": "2018-10-18T13:35:02.447Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.835Z", + "deployTransactionHash": "0xa45d84e1ac026dae6366bd54454b85972921e5931e159c71da19d65a64ab4ad5", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "4f899546765577ad2e325da53c3e7179", + "deployedBytecodeHash": "a5f3dd7878e556db538c1206827e5959", + "sourceHash": "4d60c55b8e4009873db939b37558d9dc", + "source": "/* allows tx to execute if 50% +1 vote of active signers signed */\npragma solidity 0.4.24;\nimport \"./generic/MultiSig.sol\";\n\n\ncontract StabilityBoardProxy is MultiSig {\n\n function checkQuorum(uint signersCount) internal view returns(bool isQuorum) {\n isQuorum = signersCount > activeSignersCount / 2 ;\n }\n}\n" + } + } } } } \ No newline at end of file diff --git a/abiniser/deployments/999/TokenAEur_DEPLOYS.json b/abiniser/deployments/999/TokenAEur_DEPLOYS.json index 3b2fefb0..561f9f39 100644 --- a/abiniser/deployments/999/TokenAEur_DEPLOYS.json +++ b/abiniser/deployments/999/TokenAEur_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "TokenAEur", - "latestAbiHash": "d96bcadc59c7b9c8b1db01a11a021eef", + "latestAbiHash": "2ea91d34a7bfefc8f38ef0e8a5ae24a5", "deployedAbis": { "27721a2c77dc40da7639abd46791c3d7": { "latestDeployedAddress": "0x1b9441428f9e682bab4f9cc70fdf50adcc3411f4", @@ -179,6 +179,24 @@ "source": "/* Augmint Euro token (A-EUR) implementation */\npragma solidity 0.4.24;\nimport \"./interfaces/TransferFeeInterface.sol\";\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n constructor(address _permissionGranterContract, TransferFeeInterface _feeAccount)\n public AugmintToken(_permissionGranterContract, \"Augmint Euro\", \"AEUR\", \"EUR\", 2, _feeAccount)\n {} // solhint-disable-line no-empty-blocks\n\n}\n" } } + }, + "2ea91d34a7bfefc8f38ef0e8a5ae24a5": { + "latestDeployedAddress": "0xbbecff5db2f9cccc936895121802fc15053344c6", + "deployments": { + "0xbbecff5db2f9cccc936895121802fc15053344c6": { + "generatedAt": "2018-10-18T13:35:02.366Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.871Z", + "deployTransactionHash": "0x59d1c589b1714ab43380156a86e422e54a6bb846b51a588e60f2e44f700c6d9f", + "compiler": { + "name": "solc", + "version": "0.4.24+commit.e67f0147.Emscripten.clang" + }, + "bytecodeHash": "0398a39cdab3b394103910ea6b28eef7", + "deployedBytecodeHash": "2916088286d725e884630bc95fc19dbf", + "sourceHash": "04025a37ea64acbc6f0ea2ec8a6f3e4d", + "source": "/* Augmint Euro token (A-EUR) implementation */\npragma solidity 0.4.24;\nimport \"./interfaces/TransferFeeInterface.sol\";\nimport \"./generic/AugmintToken.sol\";\n\n\ncontract TokenAEur is AugmintToken {\n constructor(address _permissionGranterContract, TransferFeeInterface _feeAccount)\n public AugmintToken(_permissionGranterContract, \"Augmint Euro\", \"AEUR\", \"EUR\", 2, _feeAccount)\n {} // solhint-disable-line no-empty-blocks\n\n}\n" + } + } } } } \ No newline at end of file diff --git a/contracts/AugmintReserves.sol b/contracts/AugmintReserves.sol index b45886e1..ae478689 100644 --- a/contracts/AugmintReserves.sol +++ b/contracts/AugmintReserves.sol @@ -12,16 +12,27 @@ import "./generic/SystemAccount.sol"; import "./interfaces/AugmintTokenInterface.sol"; -contract AugmintReserves is SystemAccount { +contract AugmintReserves is Restricted { - function () public payable { // solhint-disable-line no-empty-blocks + 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 ) } - constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks - - function burn(AugmintTokenInterface augmintToken, uint amount) external restrict("MonetarySupervisor") { + 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); + } } diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index 9ba5d1a2..5b5e0046 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -22,8 +22,6 @@ contract Exchange is Restricted { AugmintTokenInterface public augmintToken; Rates public rates; - uint public constant CHUNK_SIZE = 100; - struct Order { uint64 index; address maker; @@ -154,22 +152,32 @@ contract Exchange is Restricted { return(activeBuyOrders.length, activeSellOrders.length); } - // returns CHUNK_SIZE orders starting from offset + // returns active buy orders starting from // orders are encoded as [id, maker, price, amount] - function getActiveBuyOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) { - for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeBuyOrders.length; i++) { - uint64 orderId = activeBuyOrders[offset + i]; + function getActiveBuyOrders(uint offset, uint16 chunkSize) + external view returns (uint[4][]) { + uint limit = SafeMath.min(offset.add(chunkSize), activeBuyOrders.length); + uint[4][] memory response = new uint[4][](limit.sub(offset)); + for (uint i = offset; i < limit; i++) { + uint64 orderId = activeBuyOrders[i]; Order storage order = buyTokenOrders[orderId]; - response[i] = [orderId, uint(order.maker), order.price, order.amount]; + response[i - offset] = [orderId, uint(order.maker), order.price, order.amount]; } + return response; } - function getActiveSellOrders(uint offset) external view returns (uint[4][CHUNK_SIZE] response) { - for (uint8 i = 0; i < CHUNK_SIZE && i + offset < activeSellOrders.length; i++) { - uint64 orderId = activeSellOrders[offset + i]; + // returns active sell orders starting from + // orders are encoded as [id, maker, price, amount] + function getActiveSellOrders(uint offset, uint16 chunkSize) + external view returns (uint[4][]) { + uint limit = SafeMath.min(offset.add(chunkSize), activeSellOrders.length); + uint[4][] memory response = new uint[4][](limit.sub(offset)); + for (uint i = offset; i < limit; i++) { + uint64 orderId = activeSellOrders[i]; Order storage order = sellTokenOrders[orderId]; - response[i] = [orderId, uint(order.maker), order.price, order.amount]; + response[i - offset] = [orderId, uint(order.maker), order.price, order.amount]; } + return response; } uint private constant E12 = 1000000000000; diff --git a/contracts/FeeAccount.sol b/contracts/FeeAccount.sol index 7b96c4f1..49ec2a46 100644 --- a/contracts/FeeAccount.sol +++ b/contracts/FeeAccount.sol @@ -27,7 +27,7 @@ contract FeeAccount is SystemAccount, TransferFeeInterface { transferFee = TransferFee(transferFeePt, transferFeeMin, transferFeeMax); } - function () public payable { // solhint-disable-line no-empty-blocks + function () external payable { // solhint-disable-line no-empty-blocks // to accept ETH sent into feeAccount (defaulting fee in ETH ) } diff --git a/contracts/LoanManager.sol b/contracts/LoanManager.sol index f0d907d6..a384e655 100644 --- a/contracts/LoanManager.sol +++ b/contracts/LoanManager.sol @@ -16,11 +16,9 @@ import "./interfaces/AugmintTokenInterface.sol"; import "./MonetarySupervisor.sol"; -contract LoanManager is Restricted { +contract LoanManager is Restricted, TokenReceiver { using SafeMath for uint256; - uint16 public constant CHUNK_SIZE = 100; - enum LoanState { Open, Repaid, Defaulted, Collected } // NB: Defaulted state is not stored, only getters calculate struct LoanProduct { @@ -91,7 +89,7 @@ contract LoanManager is Restricted { 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 = false; + products[productId].isActive = newState; emit LoanProductActiveStateChanged(productId, newState); } @@ -150,7 +148,7 @@ contract LoanManager is Restricted { uint totalCollateralToCollect; uint totalDefaultingFee; for (uint i = 0; i < loanIds.length; i++) { - require(i < loans.length, "invalid loanId"); // next line would revert but require to emit reason + 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"); @@ -167,7 +165,7 @@ contract LoanManager is Restricted { 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); + loan.repaymentAmount).add(defaultingFee); uint releasedCollateral; if (targetCollection < loan.collateralAmount) { @@ -185,14 +183,15 @@ contract LoanManager is Restricted { totalCollateralToCollect = totalCollateralToCollect.add(collateralToCollect); - emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee), releasedCollateral, defaultingFee); + emit LoanCollected(loanIds[i], loan.borrower, collateralToCollect.add(defaultingFee), + releasedCollateral, defaultingFee); } if (totalCollateralToCollect > 0) { address(monetarySupervisor.augmintReserves()).transfer(totalCollateralToCollect); } - if (totalDefaultingFee > 0){ + if (totalDefaultingFee > 0) { address(augmintToken.feeAccount()).transfer(totalDefaultingFee); } @@ -208,60 +207,61 @@ contract LoanManager is Restricted { emit SystemContractsChanged(newRatesContract, newMonetarySupervisor); } - function getProductCount() external view returns (uint ct) { + function getProductCount() external view returns (uint) { return products.length; } - // returns CHUNK_SIZE loan products starting from some offset: + // returns loan products starting from some : // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ] - function getProducts(uint offset) external view returns (uint[8][CHUNK_SIZE] response) { - - for (uint16 i = 0; i < CHUNK_SIZE; i++) { - - if (offset + i >= products.length) { break; } - - LoanProduct storage product = products[offset + i]; - - response[i] = [offset + i, product.minDisbursedAmount, product.term, product.discountRate, - product.collateralRatio, product.defaultingFeePt, - monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ]; + 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 ct) { + function getLoanCount() external view returns (uint) { return loans.length; } - /* returns CHUNK_SIZE loans starting from some offset. Loans data encoded as: - [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime, - loanAmount, interestAmount ] */ - function getLoans(uint offset) external view returns (uint[10][CHUNK_SIZE] response) { - - for (uint16 i = 0; i < CHUNK_SIZE; i++) { - - if (offset + i >= loans.length) { break; } + /* returns loans starting from some . 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)); - response[i] = getLoanTuple(offset + i); + 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 CHUNK_SIZE loans of a given account, starting from some offset. Loans data encoded as: + /* returns loans of a given account, starting from some . Loans data encoded as: [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime, loanAmount, interestAmount ] */ - function getLoansForAddress(address borrower, uint offset) external view returns (uint[10][CHUNK_SIZE] response) { - + 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 (uint16 i = 0; i < CHUNK_SIZE; i++) { - - if (offset + i >= loansForAddress.length) { break; } - - response[i] = getLoanTuple(loansForAddress[offset + i]); + 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) { @@ -275,10 +275,10 @@ contract LoanManager is Restricted { uint disbursementTime = loan.maturity - product.term; LoanState loanState = - loan.state == LoanState.Open && now >= loan.maturity ? LoanState.Defaulted : loan.state; + 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]; + loan.productId, uint(loanState), loan.maturity, disbursementTime, loanAmount, interestAmount]; } function calculateLoanValues(LoanProduct storage product, uint repaymentAmount) @@ -317,5 +317,4 @@ contract LoanManager is Restricted { emit LoanRepayed(loanId, loan.borrower); } - } diff --git a/contracts/Locker.sol b/contracts/Locker.sol index 8668ec41..a812255c 100644 --- a/contracts/Locker.sol +++ b/contracts/Locker.sol @@ -25,10 +25,8 @@ contract Locker is Restricted, TokenReceiver { using SafeMath for uint256; - uint public constant CHUNK_SIZE = 100; - event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs, - uint32 minimumLockAmount, bool isActive); + uint32 minimumLockAmount, bool isActive); event LockProductActiveChange(uint32 indexed lockProductId, bool newActiveState); @@ -77,13 +75,11 @@ contract Locker is Restricted, TokenReceiver { function addLockProduct(uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive) external restrict("StabilityBoard") { - uint _newLockProductId = lockProducts.push( LockProduct(perTermInterest, durationInSecs, minimumLockAmount, isActive)) - 1; uint32 newLockProductId = uint32(_newLockProductId); require(newLockProductId == _newLockProductId, "lockProduct overflow"); emit NewLockProduct(newLockProductId, perTermInterest, durationInSecs, minimumLockAmount, isActive); - } function setLockProductActiveState(uint32 lockProductId, bool isActive) external restrict("StabilityBoard") { @@ -92,7 +88,6 @@ contract Locker is Restricted, TokenReceiver { lockProducts[lockProductId].isActive = isActive; emit LockProductActiveChange(lockProductId, isActive); - } /* lock funds, called from AugmintToken's transferAndNotify @@ -104,9 +99,8 @@ contract Locker is Restricted, TokenReceiver { function transferNotification(address from, uint256 amountToLock, uint _lockProductId) external { require(msg.sender == address(augmintToken), "msg.sender must be augmintToken"); // next line would revert but require to emit reason: - require(lockProductId < lockProducts.length, "invalid lockProductId"); + require(_lockProductId < lockProducts.length, "invalid lockProductId"); uint32 lockProductId = uint32(_lockProductId); - require(lockProductId == _lockProductId, "lockProductId overflow"); /* TODO: make data arg generic bytes uint productId; assembly { // solhint-disable-line no-inline-assembly @@ -141,24 +135,23 @@ contract Locker is Restricted, TokenReceiver { } function getLockProductCount() external view returns (uint) { - return lockProducts.length; - } - // returns 20 lock products starting from some offset + // returns lock products starting from some // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ] - function getLockProducts(uint offset) external view returns (uint[5][CHUNK_SIZE] response) { - for (uint8 i = 0; i < CHUNK_SIZE; i++) { - - if (offset + i >= lockProducts.length) { break; } - - LockProduct storage lockProduct = lockProducts[offset + i]; - - response[i] = [ lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount, + function getLockProducts(uint offset, uint16 chunkSize) + external view returns (uint[5][]) { + uint limit = SafeMath.min(offset.add(chunkSize), lockProducts.length); + uint[5][] memory response = new uint[5][](limit.sub(offset)); + + for (uint i = offset; i < limit; i++) { + LockProduct storage lockProduct = lockProducts[i]; + response[i - offset] = [lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount, monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest), lockProduct.isActive ? 1 : 0 ]; } + return response; } function getLockCount() external view returns (uint) { @@ -169,45 +162,45 @@ contract Locker is Restricted, TokenReceiver { return accountLocks[lockOwner].length; } - // returns CHUNK_SIZE locks starting from some offset + // returns locks starting from some // lock products are encoded as // [lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ] // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%): - function getLocks(uint offset) external view returns (uint[8][CHUNK_SIZE] response) { - - for (uint16 i = 0; i < CHUNK_SIZE; i++) { + function getLocks(uint offset, uint16 chunkSize) + external view returns (uint[8][]) { + uint limit = SafeMath.min(offset.add(chunkSize), locks.length); + uint[8][] memory response = new uint[8][](limit.sub(offset)); - if (offset + i >= locks.length) { break; } - - Lock storage lock = locks[offset + i]; + for (uint i = offset; i < limit; i++) { + Lock storage lock = locks[i]; LockProduct storage lockProduct = lockProducts[lock.productId]; - uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked); - response[i] = [uint(offset + i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil, - lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0]; + response[i - offset] = [uint(i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil, + lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0]; } + return response; } - // returns CHUNK_SIZE locks of a given account, starting from some offset + // returns locks of a given account, starting from some // lock products are encoded as // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ] - function getLocksForAddress(address lockOwner, uint offset) external view returns (uint[7][CHUNK_SIZE] response) { - + function getLocksForAddress(address lockOwner, uint offset, uint16 chunkSize) + external view returns (uint[7][]) { uint[] storage locksForAddress = accountLocks[lockOwner]; + uint limit = SafeMath.min(offset.add(chunkSize), locksForAddress.length); + uint[7][] memory response = new uint[7][](limit.sub(offset)); - for (uint16 i = 0; i < CHUNK_SIZE; i++) { - - if (offset + i >= locksForAddress.length) { break; } - - Lock storage lock = locks[locksForAddress[offset + i]]; + for (uint i = offset; i < limit; i++) { + Lock storage lock = locks[locksForAddress[i]]; LockProduct storage lockProduct = lockProducts[lock.productId]; uint interestEarned = calculateInterest(lockProduct.perTermInterest, lock.amountLocked); - response[i] = [ locksForAddress[offset + i], lock.amountLocked, interestEarned, lock.lockedUntil, - lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ]; + response[i - offset] = [locksForAddress[i], lock.amountLocked, interestEarned, lock.lockedUntil, + lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ]; } + return response; } function calculateInterest(uint32 perTermInterest, uint amountToLock) public pure returns (uint interestEarned) { @@ -215,7 +208,7 @@ contract Locker is Restricted, TokenReceiver { } // Internal function. assumes amountToLock is already transferred to this Lock contract - function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal returns(uint lockId) { + function _createLock(uint32 lockProductId, address lockOwner, uint amountToLock) internal { LockProduct storage lockProduct = lockProducts[lockProductId]; require(lockProduct.isActive, "lockProduct must be in active state"); require(amountToLock >= lockProduct.minimumLockAmount, "amountToLock must be >= minimumLockAmount"); @@ -225,7 +218,7 @@ contract Locker is Restricted, TokenReceiver { uint40 lockedUntil = uint40(expiration); require(lockedUntil == expiration, "lockedUntil overflow"); - lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1; + uint lockId = locks.push(Lock(amountToLock, lockOwner, lockProductId, lockedUntil, true)) - 1; accountLocks[lockOwner].push(lockId); monetarySupervisor.requestInterest(amountToLock, interestEarned); // update KPIs & transfer interest here @@ -233,5 +226,4 @@ contract Locker is Restricted, TokenReceiver { emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest, lockProduct.durationInSecs); } - } diff --git a/contracts/MonetarySupervisor.sol b/contracts/MonetarySupervisor.sol index 0d2e785f..0b973e9f 100644 --- a/contracts/MonetarySupervisor.sol +++ b/contracts/MonetarySupervisor.sol @@ -25,7 +25,8 @@ contract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-li InterestEarnedAccount public interestEarnedAccount; AugmintReserves public augmintReserves; - uint public issuedByStabilityBoard; // token issued by Stability Board + 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 @@ -63,8 +64,8 @@ contract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-li event SystemContractsChanged(InterestEarnedAccount newInterestEarnedAccount, AugmintReserves newAugmintReserves); - constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, AugmintReserves _augmintReserves, - InterestEarnedAccount _interestEarnedAccount, + constructor(address permissionGranterContract, AugmintTokenInterface _augmintToken, + AugmintReserves _augmintReserves, InterestEarnedAccount _interestEarnedAccount, uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount) public Restricted(permissionGranterContract) { augmintToken = _augmintToken; @@ -80,7 +81,7 @@ contract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-li } function burnFromReserve(uint amount) external restrict("StabilityBoard") { - issuedByStabilityBoard = issuedByStabilityBoard.sub(amount); + burnedByStabilityBoard = burnedByStabilityBoard.add(amount); augmintReserves.burn(augmintToken, amount); } @@ -118,16 +119,16 @@ contract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-li function loanRepaymentNotification(uint loanAmount) external { // only whitelisted LoanManager contracts - require(permissions[msg.sender]["LoanManager"], - "msg.sender must have LoanManager permission"); + 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"); + require(permissions[msg.sender]["LoanManager"], + "msg.sender must have LoanManager permission"); totalLoanAmount = totalLoanAmount.sub(totalLoanAmountCollected); } @@ -140,7 +141,6 @@ contract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-li function setLtdParams(uint lockDifferenceLimit, uint loanDifferenceLimit, uint allowedDifferenceAmount) external restrict("StabilityBoard") { ltdParams = LtdParams(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount); - emit LtdParamsChanged(lockDifferenceLimit, loanDifferenceLimit, allowedDifferenceAmount); } @@ -151,7 +151,6 @@ contract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-li external restrict("StabilityBoard") { totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment); totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment); - emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment); } @@ -183,10 +182,6 @@ contract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-li emit LegacyTokenConverted(msg.sender, from, amount); } - function getLoanToDepositRatio() external view returns (uint loanToDepositRatio) { - loanToDepositRatio = totalLockedAmount == 0 ? 0 : totalLockedAmount.mul(PERCENT_100).div(totalLoanAmount); - } - /* 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) { @@ -232,5 +227,4 @@ contract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-li maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ? allowedByLtdDifferencePt : allowedByLtdDifferenceAmount; } - } diff --git a/contracts/PreToken.sol b/contracts/PreToken.sol index 8072aaf0..fd0d1e47 100644 --- a/contracts/PreToken.sol +++ b/contracts/PreToken.sol @@ -33,8 +33,6 @@ import "./generic/Restricted.sol"; contract PreToken is Restricted { using SafeMath for uint256; - uint public constant CHUNK_SIZE = 100; - string constant public name = "Augmint pretokens"; // solhint-disable-line const-name-snakecase string constant public symbol = "APRE"; // solhint-disable-line const-name-snakecase uint8 constant public decimals = 0; // solhint-disable-line const-name-snakecase @@ -61,7 +59,8 @@ contract PreToken is Restricted { event NewAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap); - constructor(address permissionGranterContract) public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks + constructor(address permissionGranterContract) + public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks function addAgreement(address owner, bytes32 agreementHash, uint32 discount, uint32 valuationCap) external restrict("PreTokenSigner") { @@ -92,9 +91,11 @@ contract PreToken is Restricted { function burnFrom(bytes32 agreementHash, uint amount) public restrict("PreTokenSigner") returns (bool) { Agreement storage agreement = agreements[agreementHash]; - require(agreement.discount > 0, "agreement must exist"); // this is redundant b/c of next requires but be explicit + // this is redundant b/c of next requires but be explicit + require(agreement.discount > 0, "agreement must exist"); require(amount > 0, "burn amount must be > 0"); - require(agreement.balance >= amount, "must not burn more than balance"); // .sub would revert anyways but emit reason + // .sub would revert anyways but emit reason + require(agreement.balance >= amount, "must not burn more than balance"); agreement.balance = agreement.balance.sub(amount); totalSupply = totalSupply.sub(amount); @@ -141,17 +142,21 @@ contract PreToken is Restricted { return allAgreements.length; } - // UI helper fx - Returns all agreements from offset as + // UI helper fx - Returns agreements from as // [index in allAgreements, account address as uint, balance, agreementHash as uint, // discount as uint, valuationCap as uint ] - function getAllAgreements(uint offset) external view returns(uint[6][CHUNK_SIZE] agreementsResult) { + function getAgreements(uint offset, uint16 chunkSize) + external view returns(uint[6][]) { + uint limit = SafeMath.min(offset.add(chunkSize), allAgreements.length); + uint[6][] memory response = new uint[6][](limit.sub(offset)); - for (uint8 i = 0; i < CHUNK_SIZE && i + offset < allAgreements.length; i++) { - bytes32 agreementHash = allAgreements[i + offset]; + for (uint i = offset; i < limit; i++) { + bytes32 agreementHash = allAgreements[i]; Agreement storage agreement = agreements[agreementHash]; - agreementsResult[i] = [ i + offset, uint(agreement.owner), agreement.balance, + response[i - offset] = [i, uint(agreement.owner), agreement.balance, uint(agreementHash), uint(agreement.discount), uint(agreement.valuationCap)]; } + return response; } } diff --git a/contracts/SB_scripts/localTest/localTest_initialSetup.sol b/contracts/SB_scripts/localTest/localTest_initialSetup.sol index 53b0c781..d553b125 100644 --- a/contracts/SB_scripts/localTest/localTest_initialSetup.sol +++ b/contracts/SB_scripts/localTest/localTest_initialSetup.sol @@ -16,6 +16,7 @@ import "../../MonetarySupervisor.sol"; import "../../LoanManager.sol"; import "../../Locker.sol"; import "../../Exchange.sol"; +import "../../test/SafeMathTester.sol"; contract localTest_initialSetup { @@ -29,6 +30,7 @@ contract localTest_initialSetup { LoanManager public loanManager; Locker public locker; Exchange public exchange; + SafeMathTester public safeMathTester; constructor(Rates _rates, FeeAccount _feeAccount, @@ -38,7 +40,8 @@ contract localTest_initialSetup { MonetarySupervisor _monetarySupervisor, LoanManager _loanManager, Locker _locker, - Exchange _exchange ) public { + Exchange _exchange, + SafeMathTester _safeMathTester) public { rates = _rates; feeAccount = _feeAccount; augmintReserves = _augmintReserves; @@ -48,6 +51,7 @@ contract localTest_initialSetup { loanManager = _loanManager; locker = _locker; exchange = _exchange; + safeMathTester = _safeMathTester; } function execute(localTest_initialSetup self) external { diff --git a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol new file mode 100644 index 00000000..1c47c115 --- /dev/null +++ b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol @@ -0,0 +1,122 @@ +/* Set up new contracts */ + +pragma solidity 0.4.24; + +import "../../AugmintReserves.sol"; +import "../../Exchange.sol"; +import "../../FeeAccount.sol"; +import "../../InterestEarnedAccount.sol"; +import "../../LoanManager.sol"; +import "../../Locker.sol"; +import "../../MonetarySupervisor.sol"; +import "../../Rates.sol"; +import "../../TokenAEur.sol"; +import "../../StabilityBoardProxy.sol"; +import "../../PreToken.sol"; +import "../../PreTokenProxy.sol"; + +contract Main0014_initNewContracts { + + /****************************************************************************** + * External dependencies + ******************************************************************************/ + address public constant RATES_FEEDER_ACCOUNT = 0x8C58187a978979947b88824DCdA5Cb5fD4410387; + + /****************************************************************************** + * New contracts + ******************************************************************************/ + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dCBefFdfd3C7b89fCed7A9F84); + AugmintReserves public constant AUGMINT_RESERVES = AugmintReserves(0x65F30f8DD20c707C1938CcAd7416c7381E6eB9C8); + Exchange public constant EXCHANGE = Exchange(0xc670FFBfa21c37481FB4EF2eA2249B9B78D2B073); + FeeAccount public constant FEE_ACCOUNT = FeeAccount(0xE3ED84A163b9EeaF4f69B4890ae45cC52171Aa7E); + InterestEarnedAccount public constant INTEREST_EARNED_ACCOUNT = InterestEarnedAccount(0xf23e0AF0e41341127Bb4e7b203aebCA0185f9EbD); + LoanManager public constant LOAN_MANAGER = LoanManager(0x1cABc34618ecf2949F0405A86353e7705E01C38b); + Locker public constant LOCKER = Locker(0x5Cc161482E82f20840A4AAEB582beCBCC4b539D7); + MonetarySupervisor public constant MONETARY_SUPERVISOR = MonetarySupervisor(0x27484AFe9e6c332fB07F21Fac82d442EBe1D22c3); + Rates public constant RATES = Rates(0x4272dB2EB82068E898588C3D6e4B5D55c3848793); + TokenAEur public constant TOKEN_AEUR = TokenAEur(0xc994a2dEb02543Db1f48688438b9903c4b305ce3); + PreToken public constant PRE_TOKEN = PreToken(0x97ea02179801FA94227DB5fC1d13Ac4277d40920); + PreTokenProxy public constant PRE_TOKEN_PROXY = PreTokenProxy(0x8a69cf9d1D85bC150F69FeB80cC34c552F5fbea9); + + function execute(Main0014_initNewContracts /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + /****************************************************************************** + * Set up permissions + ******************************************************************************/ + + // StabilityBoard permission + AUGMINT_RESERVES.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + EXCHANGE.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + FEE_ACCOUNT.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + INTEREST_EARNED_ACCOUNT.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + LOAN_MANAGER.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + LOCKER.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + MONETARY_SUPERVISOR.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + RATES.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + TOKEN_AEUR.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + + // RatesFeeder permission (allows calling setRate) + RATES.grantPermission(address(RATES_FEEDER_ACCOUNT), "RatesFeeder"); + + // NoTransferFee permission + FEE_ACCOUNT.grantPermission(address(AUGMINT_RESERVES), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(EXCHANGE), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(FEE_ACCOUNT), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(INTEREST_EARNED_ACCOUNT), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(LOAN_MANAGER), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(LOCKER), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(MONETARY_SUPERVISOR), "NoTransferFee"); + + // MonetarySupervisor permission + AUGMINT_RESERVES.grantPermission(address(MONETARY_SUPERVISOR), "MonetarySupervisor"); + INTEREST_EARNED_ACCOUNT.grantPermission(address(MONETARY_SUPERVISOR), "MonetarySupervisor"); + TOKEN_AEUR.grantPermission(address(MONETARY_SUPERVISOR), "MonetarySupervisor"); + + // LoanManager permission + MONETARY_SUPERVISOR.grantPermission(address(LOAN_MANAGER), "LoanManager"); + + // Locker permission + MONETARY_SUPERVISOR.grantPermission(address(LOCKER), "Locker"); + + + // PreToken permissions + PRE_TOKEN.grantPermission(address(PRE_TOKEN_PROXY), "PreTokenSigner"); + PRE_TOKEN.grantPermission(address(PRE_TOKEN_PROXY), "PermissionGranter"); + PRE_TOKEN.revokePermission(address(STABILITY_BOARD_PROXY), "PermissionGranter"); + + + // StabilityBoard signers in new StabilityBoardProxy on Mainnet + address[] memory stabilityProxySigners = new address[](3); + stabilityProxySigners[0] = 0x53DBF6E8fe46307C7536eAbb0D90CADA3e732716; // Sz.V. + stabilityProxySigners[1] = 0xAE162e28575Ba898dc08D283f2Be10AE8b4114A2; // Sz.K. + stabilityProxySigners[2] = 0x9de3F6E7caCbb7e1c2489dFCe21abbB0ecEE6213; // P.P. + STABILITY_BOARD_PROXY.addSigners(stabilityProxySigners); + + + /****************************************************************************** + * Add loan products + ******************************************************************************/ + // term (in sec), discountRate, loanCoverageRatio, minDisbursedAmount (w/ 4 decimals), defaultingFeePt, isActive + LOAN_MANAGER.addLoanProduct(365 days, 953288, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(180 days, 976405, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(90 days, 988062, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(30 days, 995988, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(14 days, 998124, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(7 days, 999062, 600000, 800, 100000, true); // 4.9% p.a. + + + /****************************************************************************** + * Add lock products + ******************************************************************************/ + // (perTermInterest, durationInSecs, minimumLockAmount, isActive) + LOCKER.addLockProduct(45000, 365 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(22192, 180 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(11096, 90 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(3699, 30 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(1727, 14 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(864, 7 days, 1000, true); // 4.5% p.a. + + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol b/contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol new file mode 100644 index 00000000..8c3b43e8 --- /dev/null +++ b/contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol @@ -0,0 +1,110 @@ +/* Migrate legacy contracts to the new StabilityBoardProxy */ + +pragma solidity 0.4.24; + +import "../../AugmintReserves.sol"; +import "../../Exchange.sol"; +import "../../FeeAccount.sol"; +import "../../InterestEarnedAccount.sol"; +import "../../LoanManager.sol"; +import "../../Locker.sol"; +import "../../MonetarySupervisor.sol"; +import "../../Rates.sol"; +import "../../TokenAEur.sol"; +import "../../StabilityBoardProxy.sol"; + +contract Main0015_migrateLegacyContracts { + + /****************************************************************************** + * StabilityBoardProxies + ******************************************************************************/ + StabilityBoardProxy public constant OLD_STABILITY_BOARD_PROXY = StabilityBoardProxy(0x4686f017D456331ed2C1de66e134D8d05B24413D); + StabilityBoardProxy public constant NEW_STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dCBefFdfd3C7b89fCed7A9F84); + + /****************************************************************************** + * Legacy contracts + ******************************************************************************/ + AugmintReserves public constant AUGMINT_RESERVES = AugmintReserves(0x633cb544b2EF1bd9269B2111fD2B66fC05cd3477); + Exchange public constant EXCHANGE_1 = Exchange(0x8b52b019d237d0bbe8Baedf219132D5254e0690b); + Exchange public constant EXCHANGE_2 = Exchange(0xEAe7D30bCD44F27d58985b56ADD007FceE254AbD); + Exchange public constant EXCHANGE_3 = Exchange(0xaFEA54baDf7A68F93C2235B5F4cC8F02a2b55Edd); + FeeAccount public constant FEE_ACCOUNT = FeeAccount(0xF6B541E1B5e001DCc11827C1A16232759aeA730a); + InterestEarnedAccount public constant INTEREST_EARNED_ACCOUNT = InterestEarnedAccount(0x5C1a44E07541203474D92BDD03f803ea74f6947c); + LoanManager public constant LOAN_MANAGER = LoanManager(0xCBeFaF199b800DEeB9EAd61f358EE46E06c54070); + Locker public constant LOCKER_1 = Locker(0x095c0F071Fd75875a6b5a1dEf3f3a993F591080c); + Locker public constant LOCKER_2 = Locker(0x26438D7c52cE617dFc75A2F02eE816557f01e5Bb); + MonetarySupervisor public constant MONETARY_SUPERVISOR = MonetarySupervisor(0x1Ca4F9d261707aF8A856020a4909B777da218868); + Rates public constant RATES = Rates(0x4babbe57453e2b6AF125B4e304256fCBDf744480); + TokenAEur public constant TOKEN_AEUR = TokenAEur(0x86A635EccEFFfA70Ff8A6DB29DA9C8DB288E40D0); + + function execute(Main0015_migrateLegacyContracts /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(OLD_STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + /****************************************************************************** + * Grant permissions for new proxy + ******************************************************************************/ + + // StabilityBoard permission + AUGMINT_RESERVES.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + EXCHANGE_1.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + EXCHANGE_2.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + EXCHANGE_3.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + FEE_ACCOUNT.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + INTEREST_EARNED_ACCOUNT.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + LOAN_MANAGER.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + LOCKER_1.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + LOCKER_2.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + MONETARY_SUPERVISOR.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + RATES.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + TOKEN_AEUR.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + + // PermissionGranter permission + AUGMINT_RESERVES.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + EXCHANGE_1.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + EXCHANGE_2.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + EXCHANGE_3.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + FEE_ACCOUNT.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + INTEREST_EARNED_ACCOUNT.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + LOAN_MANAGER.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + LOCKER_1.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + LOCKER_2.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + MONETARY_SUPERVISOR.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + RATES.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + TOKEN_AEUR.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + + + /****************************************************************************** + * Revoke permissions for old proxy + ******************************************************************************/ + + // StabilityBoard permission + AUGMINT_RESERVES.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + EXCHANGE_1.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + EXCHANGE_2.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + EXCHANGE_3.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + FEE_ACCOUNT.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + INTEREST_EARNED_ACCOUNT.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + LOAN_MANAGER.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + LOCKER_1.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + LOCKER_2.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + MONETARY_SUPERVISOR.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + RATES.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + TOKEN_AEUR.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + + // PermissionGranter permission + AUGMINT_RESERVES.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + EXCHANGE_1.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + EXCHANGE_2.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + EXCHANGE_3.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + FEE_ACCOUNT.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + INTEREST_EARNED_ACCOUNT.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + LOAN_MANAGER.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + LOCKER_1.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + LOCKER_2.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + MONETARY_SUPERVISOR.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + RATES.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + TOKEN_AEUR.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol b/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol new file mode 100644 index 00000000..4d9d7fbe --- /dev/null +++ b/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol @@ -0,0 +1,61 @@ +/* Setup new and legacy contract dependencies */ + +pragma solidity 0.4.24; + +import "../../AugmintReserves.sol"; +import "../../Exchange.sol"; +import "../../FeeAccount.sol"; +import "../../InterestEarnedAccount.sol"; +import "../../LoanManager.sol"; +import "../../Locker.sol"; +import "../../MonetarySupervisor.sol"; +import "../../Rates.sol"; +import "../../TokenAEur.sol"; +import "../../StabilityBoardProxy.sol"; + +contract Main0016_setupLegacy { + + /****************************************************************************** + * StabilityBoardProxy + ******************************************************************************/ + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dCBefFdfd3C7b89fCed7A9F84); + + /****************************************************************************** + * New contracts + ******************************************************************************/ + MonetarySupervisor public constant NEW_MONETARY_SUPERVISOR = MonetarySupervisor(0x27484AFe9e6c332fB07F21Fac82d442EBe1D22c3); + + /****************************************************************************** + * Legacy contracts + ******************************************************************************/ + FeeAccount public constant OLD_FEE_ACCOUNT = FeeAccount(0xF6B541E1B5e001DCc11827C1A16232759aeA730a); + LoanManager public constant OLD_LOAN_MANAGER = LoanManager(0xCBeFaF199b800DEeB9EAd61f358EE46E06c54070); + Locker public constant OLD_LOCKER_1 = Locker(0x095c0F071Fd75875a6b5a1dEf3f3a993F591080c); + Locker public constant OLD_LOCKER_2 = Locker(0x26438D7c52cE617dFc75A2F02eE816557f01e5Bb); + TokenAEur public constant OLD_TOKEN_AEUR = TokenAEur(0x86A635EccEFFfA70Ff8A6DB29DA9C8DB288E40D0); + + function execute(Main0016_setupLegacy /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + + /****************************************************************************** + * Setup permissions in new contracts for legacy contracts + ******************************************************************************/ + NEW_MONETARY_SUPERVISOR.grantPermission(address(OLD_LOAN_MANAGER), "LoanManager"); + NEW_MONETARY_SUPERVISOR.grantPermission(address(OLD_LOCKER_1), "Locker"); + NEW_MONETARY_SUPERVISOR.grantPermission(address(OLD_LOCKER_2), "Locker"); + + /****************************************************************************** + * Accept legacy tokens + ******************************************************************************/ + NEW_MONETARY_SUPERVISOR.setAcceptedLegacyAugmintToken(OLD_TOKEN_AEUR, true); + + + /****************************************************************************** + * Setup permissions in legacy contracts for new contracts + ******************************************************************************/ + OLD_FEE_ACCOUNT.grantPermission(address(NEW_MONETARY_SUPERVISOR), "NoTransferFee"); + + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol b/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol new file mode 100644 index 00000000..4f461809 --- /dev/null +++ b/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol @@ -0,0 +1,92 @@ +/* Setup new and legacy contract dependencies */ + +pragma solidity 0.4.24; + +import "../../AugmintReserves.sol"; +import "../../Exchange.sol"; +import "../../FeeAccount.sol"; +import "../../InterestEarnedAccount.sol"; +import "../../LoanManager.sol"; +import "../../Locker.sol"; +import "../../MonetarySupervisor.sol"; +import "../../Rates.sol"; +import "../../TokenAEur.sol"; +import "../../StabilityBoardProxy.sol"; + +contract Main0017_postDeploySetup { + + /****************************************************************************** + * StabilityBoardProxy + ******************************************************************************/ + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dCBefFdfd3C7b89fCed7A9F84); + + /****************************************************************************** + * New contracts + ******************************************************************************/ + MonetarySupervisor public constant NEW_MONETARY_SUPERVISOR = MonetarySupervisor(0x27484AFe9e6c332fB07F21Fac82d442EBe1D22c3); + Rates public constant NEW_RATES = Rates(0x4272dB2EB82068E898588C3D6e4B5D55c3848793); + + /****************************************************************************** + * Legacy contracts + ******************************************************************************/ + Exchange public constant OLD_EXCHANGE_1 = Exchange(0x8b52b019d237d0bbe8Baedf219132D5254e0690b); + Exchange public constant OLD_EXCHANGE_2 = Exchange(0xEAe7D30bCD44F27d58985b56ADD007FceE254AbD); + Exchange public constant OLD_EXCHANGE_3 = Exchange(0xaFEA54baDf7A68F93C2235B5F4cC8F02a2b55Edd); + LoanManager public constant OLD_LOAN_MANAGER = LoanManager(0xCBeFaF199b800DEeB9EAd61f358EE46E06c54070); + Locker public constant OLD_LOCKER_1 = Locker(0x095c0F071Fd75875a6b5a1dEf3f3a993F591080c); + Locker public constant OLD_LOCKER_2 = Locker(0x26438D7c52cE617dFc75A2F02eE816557f01e5Bb); + MonetarySupervisor public constant OLD_MONETARY_SUPERVISOR = MonetarySupervisor(0x1Ca4F9d261707aF8A856020a4909B777da218868); + + function execute(Main0017_postDeploySetup /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + + /****************************************************************************** + * Migrate KPIs from old MonetarySupervisor + ******************************************************************************/ + uint oldTotalLoan = OLD_MONETARY_SUPERVISOR.totalLoanAmount(); + uint oldTotalLock = OLD_MONETARY_SUPERVISOR.totalLockedAmount(); + NEW_MONETARY_SUPERVISOR.adjustKPIs(oldTotalLoan, oldTotalLock); + + + /****************************************************************************** + * Set new MonetarySupervisor in old Locker + ******************************************************************************/ + OLD_LOCKER_1.setMonetarySupervisor(NEW_MONETARY_SUPERVISOR); + OLD_LOCKER_2.setMonetarySupervisor(NEW_MONETARY_SUPERVISOR); + + /****************************************************************************** + * Set new Rates and MonetarySupervisor in old LoanManager + ******************************************************************************/ + OLD_LOAN_MANAGER.setSystemContracts(NEW_RATES, NEW_MONETARY_SUPERVISOR); + + /****************************************************************************** + * Set new Rates in old Exchange + ******************************************************************************/ + OLD_EXCHANGE_1.setRatesContract(NEW_RATES); + OLD_EXCHANGE_2.setRatesContract(NEW_RATES); + OLD_EXCHANGE_3.setRatesContract(NEW_RATES); + + + /****************************************************************************** + * Disable old loan products + ******************************************************************************/ + OLD_LOAN_MANAGER.setLoanProductActiveState(9, false); + OLD_LOAN_MANAGER.setLoanProductActiveState(10, false); + OLD_LOAN_MANAGER.setLoanProductActiveState(11, false); + OLD_LOAN_MANAGER.setLoanProductActiveState(12, false); + OLD_LOAN_MANAGER.setLoanProductActiveState(13, false); + OLD_LOAN_MANAGER.setLoanProductActiveState(14, false); + + /****************************************************************************** + * Disable old lock products + ******************************************************************************/ + OLD_LOCKER_2.setLockProductActiveState(5, false); + OLD_LOCKER_2.setLockProductActiveState(6, false); + OLD_LOCKER_2.setLockProductActiveState(7, false); + OLD_LOCKER_2.setLockProductActiveState(8, false); + OLD_LOCKER_2.setLockProductActiveState(9, false); + OLD_LOCKER_2.setLockProductActiveState(10, false); + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/mainnet/Main0018_preTokenSigners.sol b/contracts/SB_scripts/mainnet/Main0018_preTokenSigners.sol new file mode 100644 index 00000000..46bd1a2b --- /dev/null +++ b/contracts/SB_scripts/mainnet/Main0018_preTokenSigners.sol @@ -0,0 +1,23 @@ +/* Add pretoken signers */ + +pragma solidity 0.4.24; + +import "../../PreToken.sol"; +import "../../PreTokenProxy.sol"; + +contract Main0018_preTokenSigners { + + PreToken public constant PRE_TOKEN = PreToken(0x97ea02179801FA94227DB5fC1d13Ac4277d40920); + PreTokenProxy public constant PRE_TOKEN_PROXY = PreTokenProxy(0x8a69cf9d1D85bC150F69FeB80cC34c552F5fbea9); + + function execute(Main0018_preTokenSigners /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(PRE_TOKEN_PROXY), "only execute via PreTokenProxy"); + + // PreToken signers + address[] memory preTokenSigners = new address[](2); + preTokenSigners[0] = 0xd8203A652452906586F2E6cB6e31f6f7fed094D4; // Sz.K. + preTokenSigners[1] = 0xf9ea0E2857405C859bb8647ECB11f931D1259753; // P.P. + PRE_TOKEN_PROXY.addSigners(preTokenSigners); + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/mainnet/Main0019_noTransferFee.sol b/contracts/SB_scripts/mainnet/Main0019_noTransferFee.sol new file mode 100644 index 00000000..78f8f090 --- /dev/null +++ b/contracts/SB_scripts/mainnet/Main0019_noTransferFee.sol @@ -0,0 +1,19 @@ +/* Eliminate transfer fee */ + +pragma solidity 0.4.24; + +import "../../StabilityBoardProxy.sol"; +import "../../FeeAccount.sol"; + +contract Main0019_noTransferFee { + + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dCBefFdfd3C7b89fCed7A9F84); + FeeAccount public constant FEE_ACCOUNT = FeeAccount(0xE3ED84A163b9EeaF4f69B4890ae45cC52171Aa7E); + + function execute(Main0019_noTransferFee /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + FEE_ACCOUNT.setTransferFees(0, 0, 0); + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/mainnet/Main0020_removeSigner.sol b/contracts/SB_scripts/mainnet/Main0020_removeSigner.sol new file mode 100644 index 00000000..0d430dc0 --- /dev/null +++ b/contracts/SB_scripts/mainnet/Main0020_removeSigner.sol @@ -0,0 +1,21 @@ +/* Remove deployer account from mainnet signers */ + +pragma solidity 0.4.24; + +import "../../generic/MultiSig.sol"; +import "../../StabilityBoardProxy.sol"; + +contract Main0020_removeSigner { + + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dCBefFdfd3C7b89fCed7A9F84); + + function execute(Main0020_removeSigner /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + // revoke deployer account signer rights + address[] memory signersToRemove = new address[](1); // dynamic array needed for addSigners() & removeSigners() + signersToRemove[0] = 0x23445fFDDA92567a4c6168D376C35d93AcB96e01; // treer deployer account + STABILITY_BOARD_PROXY.removeSigners(signersToRemove); + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/rinkeby/Rink0001_initNewContracts.sol b/contracts/SB_scripts/rinkeby/Rink0001_initNewContracts.sol deleted file mode 100644 index e5411edc..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0001_initNewContracts.sol +++ /dev/null @@ -1,145 +0,0 @@ -/* script to setup contracts after full redeploy on Rinkeby. - called via StabilityBoardProxy (MultiSig) but deployer account is the only signer yet because - these working on the new contracts only. - Stability Board and pretoken signers will be added and deployer will be removed when setup is successful. -*/ - -pragma solidity 0.4.24; - -import "../../generic/MultiSig.sol"; -import "../../PreToken.sol"; -import "../../Rates.sol"; -import "../../FeeAccount.sol"; -import "../../AugmintReserves.sol"; -import "../../InterestEarnedAccount.sol"; -import "../../TokenAEur.sol"; -import "../../MonetarySupervisor.sol"; -import "../../LoanManager.sol"; -import "../../Locker.sol"; -import "../../Exchange.sol"; - - -contract Rink0001_initNewContracts { - address constant RATES_FEEDER_ACCOUNT = 0x8C58187a978979947b88824DCdA5Cb5fD4410387; - - // new contracts - address constant preTokenProxyAddress = 0x0775465245e523b45Cc3b41477d44F908e22feDE; - address constant stabilityBoardProxyAddress = 0x44022C28766652EC5901790E53CEd7A79a19c10A; - - PreToken constant preToken = PreToken(0xFc69b4F2A7de7c68c46A8230eCDF0cff49Eb8f1F); - Rates constant rates = Rates(0xf25638C7d37fCa0cBc124b3925eCe156a20e1f03); - FeeAccount constant feeAccount = FeeAccount(0x0F5983a6d760BF6E385339af0e67e87420d413EC); - AugmintReserves constant augmintReserves = AugmintReserves(0x6386F25d2029ea3164838BF6494Ed85C01fC1B03); - InterestEarnedAccount constant interestEarnedAccount = InterestEarnedAccount(0xdf8c338A89f827A6D62804905ed415B6a382f92E); - TokenAEur constant tokenAEur = TokenAEur(0xe54f61d6EaDF03b658b3354BbD80cF563fEca34c); - MonetarySupervisor constant monetarySupervisor = MonetarySupervisor(0x01844c9bade08A8ffdB09aD9f1fecE2C83a6E6a8); - LoanManager constant loanManager = LoanManager(0x3b5DD323534659655EEccc642c3e338AAbD0B219); - Locker constant locker = Locker(0x5B94AaF241E8039ed6d3608760AE9fA7186767d7); - Exchange constant exchange = Exchange(0x5e2Be81aB4237c7c08d929c42b9F13cF4f9040D2); - - // Legacy contracts - /* Dropped support for very old tokens: - TokenAEur constant oldToken1 = TokenAEur(0x95AA79D7410Eb60f49bfD570b445836d402Bd7b1); - TokenAEur constant oldToken2 = TokenAEur(0xA35D9de06895a3A2E7eCaE26654b88Fe71C179eA); */ - TokenAEur constant oldToken3 = TokenAEur(0x135893F1A6B3037BB45182841f18F69327366992); - TokenAEur constant oldToken4 = TokenAEur(0x6C90c10D7A33815C2BaeeD66eE8b848F1D95268e); - - Locker constant oldLocker1 = Locker(0xf98AE1fb568B267A7632BF54579A153C892E2ec2); - Locker constant oldLocker2 = Locker(0xd0B6136C2E35c288A903E836feB9535954E4A9e9); - - LoanManager constant oldLoanManager1 = LoanManager(0xBdb02f82d7Ad574f9F549895caf41E23a8981b07); - LoanManager constant oldLoanManager2 = LoanManager(0x214919Abe3f2b7CA7a43a799C4FC7132bBf78e8A); - - - function execute(Rink0001_initNewContracts /* self, not used */) external { - // called via StabilityBoardProxy - require(address(this) == stabilityBoardProxyAddress, "only deploy via stabilityboardsigner"); - - /****************************************************************************** - * Set up permissions - ******************************************************************************/ - // preToken Permissions - bytes32[] memory preTokenPermissions = new bytes32[](2); // dynamic array needed for grantMultiplePermissions() - preTokenPermissions[0] = "PreTokenSigner"; - preTokenPermissions[1] = "PermissionGranter"; - preToken.grantMultiplePermissions(preTokenProxyAddress, preTokenPermissions); - // deploy script temporarly granted PermissionGranter to this script in order to run this script - // now we can remove it as we add grant it to preTokenProxy - preToken.revokePermission(stabilityBoardProxyAddress, "PermissionGranter"); - - // StabilityBoard - rates.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - feeAccount.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - interestEarnedAccount.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - tokenAEur.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - augmintReserves.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - monetarySupervisor.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - loanManager.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - locker.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - exchange.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - - // RatesFeeder permissions to allow calling setRate() - rates.grantPermission(RATES_FEEDER_ACCOUNT, "RatesFeeder"); - - // set NoTransferFee permissions - feeAccount.grantPermission(feeAccount, "NoTransferFee"); - feeAccount.grantPermission(augmintReserves, "NoTransferFee"); - feeAccount.grantPermission(interestEarnedAccount, "NoTransferFee"); - feeAccount.grantPermission(monetarySupervisor, "NoTransferFee"); - feeAccount.grantPermission(loanManager, "NoTransferFee"); - feeAccount.grantPermission(locker, "NoTransferFee"); - feeAccount.grantPermission(exchange, "NoTransferFee"); - - // set MonetarySupervisor permissions - interestEarnedAccount.grantPermission(monetarySupervisor, "MonetarySupervisor"); - tokenAEur.grantPermission(monetarySupervisor, "MonetarySupervisor"); - augmintReserves.grantPermission(monetarySupervisor, "MonetarySupervisor"); - - // set LoanManager permissions - monetarySupervisor.grantPermission(loanManager, "LoanManager"); - - // set Locker permissions - monetarySupervisor.grantPermission(locker, "Locker"); - - /****************************************************************************** - * Setup permissions for legacy contracts - ******************************************************************************/ - - monetarySupervisor.grantPermission(oldLocker1, "Locker"); - monetarySupervisor.grantPermission(oldLocker2, "Locker"); - - monetarySupervisor.grantPermission(oldLoanManager1, "LoanManager"); - monetarySupervisor.grantPermission(oldLoanManager2, "LoanManager"); - - monetarySupervisor.setAcceptedLegacyAugmintToken(oldToken3, true); - monetarySupervisor.setAcceptedLegacyAugmintToken(oldToken4, true); - - /* NB: to allow token conversion w/o fee (oldToken.transferAndNotify transfers to MonetarySupervisor) - new MonetarySupervisor requires NoTransferFee permission on old feeAccount. - It's not in this script b/c old feeAccount wasn't multisig (it's granted by deployer acc) - This permission will need to be granted via Multisg in future token redeploys */ - - /****************************************************************************** - * Add loan products - ******************************************************************************/ - // term (in sec), discountRate, loanCoverageRatio, minDisbursedAmount (w/ 4 decimals), defaultingFeePt, isActive - loanManager.addLoanProduct(30 days, 990641, 600000, 1000, 50000, true); // 12% p.a. - loanManager.addLoanProduct(14 days, 996337, 600000, 1000, 50000, true); // 10% p.a. - loanManager.addLoanProduct(7 days, 998170, 600000, 1000, 50000, true); // 10% p.a. - - loanManager.addLoanProduct(1 hours, 999989, 980000, 2000, 50000, true); // due in 1hr for testing repayments ? p.a. - loanManager.addLoanProduct(1 seconds, 999999, 990000, 3000, 50000, true); // defaults in 1 secs for testing ? p.a. - - /****************************************************************************** - * Add lock products - ******************************************************************************/ - // (perTermInterest, durationInSecs, minimumLockAmount, isActive) - locker.addLockProduct(4019, 30 days, 1000, true); // 5% p.a. - locker.addLockProduct(1506, 14 days, 1000, true); // 4% p.a. - locker.addLockProduct(568, 7 days, 1000, true); // 3% p.a. - - locker.addLockProduct(3, 1 hours, 2000, true); // for testing, ~2.66% p.a. - locker.addLockProduct(1 , 1 minutes, 3000, true); // for testing, ~69.15% p.a. - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0002_setupPreTokenSigners.sol b/contracts/SB_scripts/rinkeby/Rink0002_setupPreTokenSigners.sol deleted file mode 100644 index 34c70927..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0002_setupPreTokenSigners.sol +++ /dev/null @@ -1,36 +0,0 @@ -/* script to add preToken Signers and remove deployer account as signer - must be executed via PreTokenProxy -*/ - -pragma solidity 0.4.24; - -import "../../generic/MultiSig.sol"; -import "../../PreTokenProxy.sol"; - - -contract Rink0002_setupPreTokenSigners { - address constant SZERT_ADDRESS = 0x9aaf197F25d207ecE17DfBeb20780095f7623A23; - address constant KROSZA_ADDRESS = 0x14A9dc091053fCbA9474c5734078238ff9904364; - - address constant DEPLOYER_ADDRESS = 0xae653250B4220835050B75D3bC91433246903A95; - - PreTokenProxy constant - preTokenProxy = PreTokenProxy(0x0775465245e523b45Cc3b41477d44F908e22feDE); - - function execute(Rink0002_setupPreTokenSigners /* self (not used) */) external { - /****************************************************************************** - * Set up PretokenSigners - ******************************************************************************/ - - address[] memory signersToAdd = new address[](2); // dynamic array needed for addSigners() & removeSigners() - signersToAdd[0] = SZERT_ADDRESS; - signersToAdd[1] = KROSZA_ADDRESS; - preTokenProxy.addSigners(signersToAdd); - - // revoke deployer account signer rights - address[] memory signersToRemove = new address[](1); // dynamic array needed for addSigners() & removeSigners() - signersToRemove[0] = DEPLOYER_ADDRESS; - preTokenProxy.removeSigners(signersToRemove); - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0003_setupSBSigners.sol b/contracts/SB_scripts/rinkeby/Rink0003_setupSBSigners.sol deleted file mode 100644 index 3ed0b345..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0003_setupSBSigners.sol +++ /dev/null @@ -1,37 +0,0 @@ -/* script to add StabilityBoard Signers and remove deployer account as signer - must be executed via StabilityBoardProxy -*/ - -pragma solidity 0.4.24; - -import "../../generic/MultiSig.sol"; -import "../../StabilityBoardProxy.sol"; - - -contract Rink0003_setupSBSigners { - address constant SZERT_ADDRESS = 0x9aaf197F25d207ecE17DfBeb20780095f7623A23; - address constant KROSZA_ADDRESS = 0x14A9dc091053fCbA9474c5734078238ff9904364; - address constant PHRAKTLE_ADDRESS = 0xe71E9636e31B838aF0A3c38B3f3449cdC2b7aa87; - - address constant DEPLOYER_ADDRESS = 0xae653250B4220835050B75D3bC91433246903A95; - - StabilityBoardProxy constant - stabilityBoardProxy = StabilityBoardProxy(0x44022C28766652EC5901790E53CEd7A79a19c10A); - - function execute(Rink0003_setupSBSigners /* self (not used)*/ ) external { - /****************************************************************************** - * Set up StabilityBoard Signers - ******************************************************************************/ - address[] memory signersToAdd = new address[](3); // dynamic array needed for addSigners() & removeSigners() - signersToAdd[0] = SZERT_ADDRESS; - signersToAdd[1] = KROSZA_ADDRESS; - signersToAdd[2] = PHRAKTLE_ADDRESS; - stabilityBoardProxy.addSigners(signersToAdd); - - // revoke deployer account signer rights - address[] memory signersToRemove = new address[](1); // dynamic array needed for addSigners() & removeSigners() - signersToRemove[0] = DEPLOYER_ADDRESS; - stabilityBoardProxy.removeSigners(signersToRemove); - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0004_adjustInterest.sol b/contracts/SB_scripts/rinkeby/Rink0004_adjustInterest.sol deleted file mode 100644 index 6c0189c1..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0004_adjustInterest.sol +++ /dev/null @@ -1,52 +0,0 @@ -/* adjust interest rates -*/ - -pragma solidity 0.4.24; - -import "../../generic/MultiSig.sol"; -import "../../LoanManager.sol"; -import "../../Locker.sol"; - - -contract Rink0004_adjustInterest { - - LoanManager constant loanManager = LoanManager(0x3b5DD323534659655EEccc642c3e338AAbD0B219); - Locker constant locker = Locker(0x5B94AaF241E8039ed6d3608760AE9fA7186767d7); - - function execute(Rink0004_adjustInterest /* self (not used)*/ ) external { - /****************************************************************************** - * Disable old and add new LOAN products - ******************************************************************************/ - loanManager.setLoanProductActiveState(0, false); - loanManager.setLoanProductActiveState(1, false); - loanManager.setLoanProductActiveState(2, false); - loanManager.setLoanProductActiveState(3, false); - loanManager.setLoanProductActiveState(4, false); - - // term (in sec), discountRate, loanCoverageRatio, minDisbursedAmount (w/ 4 decimals), defaultingFeePt, isActive - loanManager.addLoanProduct(30 days, 986219, 600000, 1000, 50000, true); // 17% p.a. - loanManager.addLoanProduct(14 days, 993900, 600000, 1000, 50000, true); // 16% p.a. - loanManager.addLoanProduct(7 days, 997132, 600000, 1000, 50000, true); // 15% p.a. - - loanManager.addLoanProduct(1 hours, 999998, 980000, 2000, 50000, true); // due in 1hr for testing repayments ? p.a. - loanManager.addLoanProduct(1 seconds, 999999, 990000, 3000, 50000, true); // defaults in 1 secs for testing ? p.a. - - /****************************************************************************** - * Disable old and add new LOCK products - ******************************************************************************/ - locker.setLockProductActiveState(0, false); - locker.setLockProductActiveState(1, false); - locker.setLockProductActiveState(2, false); - locker.setLockProductActiveState(3, false); - locker.setLockProductActiveState(4, false); - - // (perTermInterest, durationInSecs, minimumLockAmount, isActive) - locker.addLockProduct(9864, 30 days, 1000, true); // 12% p.a. - locker.addLockProduct(4220, 14 days, 1000, true); // 11% p.a. - locker.addLockProduct(1918, 7 days, 1000, true); // 10% p.a. - - locker.addLockProduct(100, 1 hours, 2000, true); // for testing, ~87.60% p.a. - locker.addLockProduct(2 , 1 minutes, 3000, true); // for testing, ~105.12% p.a. - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0004_migrate_MSv0_5_0.sol b/contracts/SB_scripts/rinkeby/Rink0004_migrate_MSv0_5_0.sol deleted file mode 100644 index df5f31db..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0004_migrate_MSv0_5_0.sol +++ /dev/null @@ -1,61 +0,0 @@ -/* script to switch over to latest MonetarySupervisor contract - must be executed via StabilityBoardProxy - NB: additional updates of old contracts are not part of this script but executed from deployer account - because old contracts didn't have MultiSig -*/ - -pragma solidity 0.4.24; - -import "../../generic/MultiSig.sol"; -import "../../TokenAEur.sol"; -import "../../MonetarySupervisor.sol"; - - -contract Rink0004_migrate_MSv0_5_0 { - - // latest contract - MonetarySupervisor constant monetarySupervisor = MonetarySupervisor(0x01844c9bade08A8ffdB09aD9f1fecE2C83a6E6a8); - - // Legacy contract - MonetarySupervisor constant oldMonetarySupervisor1 = MonetarySupervisor(0xC19a45F5CbfA93Be512ef07177feB3f7b3ae4518); - - function execute(Rink0004_migrate_MSv0_5_0 /* self (not used)*/ ) external { - /****************************************************************************** - * Migrate KPIs from old MonetarySupervisor - ******************************************************************************/ - uint oldTotalLoan = oldMonetarySupervisor1.totalLoanAmount(); - uint oldTotalLock = oldMonetarySupervisor1.totalLockedAmount(); - monetarySupervisor.adjustKPIs(oldTotalLoan, oldTotalLock); - - /* NB: These below are for future reminder and intentionally commented out. - Exchange, Locker and LoanManager contracts are multiSig from now on so - these must be set from a migration script in the future migrations. - Prior versions are set from deployer account */ - /****************************************************************************** - * Set new Rates in old Exchange - ******************************************************************************/ - // oldExchange.setRatesContract(rates.address); - - /****************************************************************************** - * Set new MonetarySupervisor in old Lockers - ******************************************************************************/ - // oldLocker.setMonetarySupervisor(monetarySupervisor.address); - - /****************************************************************************** - * Set new Rates and MonetarySupervisor in old LoanManager - ******************************************************************************/ - // oldLoanManager.setSystemContracts(rates.address, monetarySupervisor.address); - - /****************************************************************************** - * NB on old System Accounts: - * - feeAccount: still have balance in old A-EUR and will get more b/c old A-EUR will be transfered - * - interestEarnedAccount: still have balance in old A-EUR and will get more as old loans will be repaid. - * - augmintReserves: still have balances in old A-EUR and will have debit/credits as operations might happen on ethereum - * - * These balances should be transfered (ETH) and converted (from old A-EUR to new) or burnt - * when all locks/loans are repaid/collected/released in legacy contracts - ******************************************************************************/ - - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0005_initNewLocker.sol b/contracts/SB_scripts/rinkeby/Rink0005_initNewLocker.sol deleted file mode 100644 index 4760eec5..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0005_initNewLocker.sol +++ /dev/null @@ -1,38 +0,0 @@ -/* grant permissions & add lock products to new locker contract -*/ - -pragma solidity 0.4.24; - -import "../../generic/MultiSig.sol"; -import "../../LoanManager.sol"; -import "../../Locker.sol"; -import "../../FeeAccount.sol"; -import "../../MonetarySupervisor.sol"; - - -contract Rink0005_initNewLocker { - - LoanManager constant loanManager = LoanManager(0x3b5DD323534659655EEccc642c3e338AAbD0B219); - Locker constant locker = Locker(0x5B94AaF241E8039ed6d3608760AE9fA7186767d7); - FeeAccount constant feeAccount = FeeAccount(0x0F5983a6d760BF6E385339af0e67e87420d413EC); - MonetarySupervisor constant monetarySupervisor = MonetarySupervisor(0x01844c9bade08A8ffdB09aD9f1fecE2C83a6E6a8); - - address constant stabilityBoardProxyAddress = 0x44022C28766652EC5901790E53CEd7A79a19c10A; - - function execute(Rink0005_initNewLocker /* self (not used)*/ ) external { - - locker.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - feeAccount.grantPermission(locker, "NoTransferFee"); - monetarySupervisor.grantPermission(locker, "Locker"); - - // (perTermInterest, durationInSecs, minimumLockAmount, isActive) - locker.addLockProduct(9864, 30 days, 1000, true); // 12% p.a. - locker.addLockProduct(4220, 14 days, 1000, true); // 11% p.a. - locker.addLockProduct(1918, 7 days, 1000, true); // 10% p.a. - - locker.addLockProduct(100, 1 hours, 2000, true); // for testing, ~87.60% p.a. - locker.addLockProduct(2 , 1 minutes, 3000, true); // for testing, ~105.12% p.a. - - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0006_fixInitNewLocker.sol b/contracts/SB_scripts/rinkeby/Rink0006_fixInitNewLocker.sol deleted file mode 100644 index 4ab19756..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0006_fixInitNewLocker.sol +++ /dev/null @@ -1,48 +0,0 @@ -/* -Fix previous Rink0005_initNewLocker script where new lock products wrongly added to old locker contract: -- disable producs (duplicate) in oldLocker added by Rink0005_initNewLocker -- grant permissions & add lock products to new locker contract -*/ - -pragma solidity 0.4.24; - -import "../../generic/MultiSig.sol"; -import "../../LoanManager.sol"; -import "../../Locker.sol"; -import "../../FeeAccount.sol"; -import "../../MonetarySupervisor.sol"; - - -contract Rink0006_fixInitNewLocker { - - LoanManager constant loanManager = LoanManager(0x3b5DD323534659655EEccc642c3e338AAbD0B219); - Locker constant oldLocker = Locker(0x5B94AaF241E8039ed6d3608760AE9fA7186767d7); - Locker constant newLocker = Locker(0xF74c0CB2713214808553CDA5C78f92219478863d); - FeeAccount constant feeAccount = FeeAccount(0x0F5983a6d760BF6E385339af0e67e87420d413EC); - MonetarySupervisor constant monetarySupervisor = MonetarySupervisor(0x01844c9bade08A8ffdB09aD9f1fecE2C83a6E6a8); - - address constant stabilityBoardProxyAddress = 0x44022C28766652EC5901790E53CEd7A79a19c10A; - - function execute(Rink0006_fixInitNewLocker /* self (not used)*/ ) external { - - oldLocker.setLockProductActiveState(10, false); - oldLocker.setLockProductActiveState(11, false); - oldLocker.setLockProductActiveState(12, false); - oldLocker.setLockProductActiveState(13, false); - oldLocker.setLockProductActiveState(14, false); - - newLocker.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - feeAccount.grantPermission(newLocker, "NoTransferFee"); - monetarySupervisor.grantPermission(newLocker, "Locker"); - - // (perTermInterest, durationInSecs, minimumLockAmount, isActive) - newLocker.addLockProduct(9864, 30 days, 1000, true); // 12% p.a. - newLocker.addLockProduct(4220, 14 days, 1000, true); // 11% p.a. - newLocker.addLockProduct(1918, 7 days, 1000, true); // 10% p.a. - - newLocker.addLockProduct(100, 1 hours, 2000, true); // for testing, ~87.60% p.a. - newLocker.addLockProduct(2 , 1 minutes, 3000, true); // for testing, ~105.12% p.a. - - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0007_initNewExchange.sol b/contracts/SB_scripts/rinkeby/Rink0007_initNewExchange.sol deleted file mode 100644 index eb55e119..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0007_initNewExchange.sol +++ /dev/null @@ -1,34 +0,0 @@ -/* Set up new Exchange contract with required permissions - This script was deployed but failed to execute. Unknow if it was because it is a library or - not enough gas was provided for execute. - Rink0008 was created as a contract, redeployed and sucessfully executed. -*/ - -pragma solidity 0.4.24; - -import "../../FeeAccount.sol"; -import "../../Exchange.sol"; - - -library Rink0007_initNewExchange { - address constant stabilityBoardProxyAddress = 0x44022C28766652EC5901790E53CEd7A79a19c10A; - - FeeAccount constant feeAccount = FeeAccount(0x0F5983a6d760BF6E385339af0e67e87420d413EC); - Exchange constant newExchange = Exchange(0x5C35162DBf91C794F1569C5fe1649f0c5283d2f6); - - function execute(Rink0007_initNewExchange /* self, not used */) external { - // called via StabilityBoardProxy - require(address(this) == stabilityBoardProxyAddress, "only deploy via stabilityboardsigner"); - - /****************************************************************************** - * Set up permissions - ******************************************************************************/ - // StabilityBoard - newExchange.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - - // set NoTransferFee permissions - feeAccount.grantPermission(address(newExchange), "NoTransferFee"); - - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0008_initNewExchange2.sol b/contracts/SB_scripts/rinkeby/Rink0008_initNewExchange2.sol deleted file mode 100644 index 416a1682..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0008_initNewExchange2.sol +++ /dev/null @@ -1,31 +0,0 @@ -/* Rink0007 failed, next attempt with the same code but as contract instead of library. -Set up new Exchange contract with required permissions */ - -pragma solidity 0.4.24; - -import "../../FeeAccount.sol"; -import "../../Exchange.sol"; - - -contract Rink0008_initNewExchange2 { - address constant stabilityBoardProxyAddress = 0x44022C28766652EC5901790E53CEd7A79a19c10A; - - FeeAccount constant feeAccount = FeeAccount(0x0F5983a6d760BF6E385339af0e67e87420d413EC); - Exchange constant newExchange = Exchange(0x5C35162DBf91C794F1569C5fe1649f0c5283d2f6); - - function execute(Rink0008_initNewExchange2 /* self, not used */) external { - // called via StabilityBoardProxy - require(address(this) == stabilityBoardProxyAddress, "only deploy via stabilityboardsigner"); - - /****************************************************************************** - * Set up permissions - ******************************************************************************/ - // StabilityBoard - newExchange.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - - // set NoTransferFee permissions - feeAccount.grantPermission(address(newExchange), "NoTransferFee"); - - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0009_changeSBSigners.sol b/contracts/SB_scripts/rinkeby/Rink0009_changeSBSigners.sol deleted file mode 100644 index afd7e2f4..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0009_changeSBSigners.sol +++ /dev/null @@ -1,35 +0,0 @@ -/* revoke Krosza and add Treer as StabilityBoard signer on rinkeby for faster testing */ - -pragma solidity 0.4.24; - -import "../../generic/MultiSig.sol"; -import "../../StabilityBoardProxy.sol"; - - -contract Rink0009_changeSBSigners { - address constant TREER_ADDRESS = 0x1A5F89a7E641e02922dbdc6490c47909deCEe592; - address constant KROSZA_ADDRESS = 0x14A9dc091053fCbA9474c5734078238ff9904364; - address constant INCORRECT_SCRIPT = 0x17913EBe915349caACBE9192Bfd5aB3D45839E1a; - - StabilityBoardProxy constant - stabilityBoardProxy = StabilityBoardProxy(0x44022C28766652EC5901790E53CEd7A79a19c10A); - - function execute(Rink0009_changeSBSigners /* self, not used */) external { - - // cancel same script deployed but with incorrect address for TREER. (sogned but not executed yet) - stabilityBoardProxy.cancelScript(INCORRECT_SCRIPT); - - /****************************************************************************** - * Add Treer as StabilityBoard Signers - ******************************************************************************/ - address[] memory signersToAdd = new address[](1); // dynamic array needed for addSigners() & removeSigners() - signersToAdd[0] = TREER_ADDRESS; - stabilityBoardProxy.addSigners(signersToAdd); - - // revoke SZERT so we 2 from 3 is enough to sign - address[] memory signersToRemove = new address[](1); // dynamic array needed for addSigners() & removeSigners() - signersToRemove[0] = KROSZA_ADDRESS; - stabilityBoardProxy.removeSigners(signersToRemove); - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0010_changeDefaultingFee.sol b/contracts/SB_scripts/rinkeby/Rink0010_changeDefaultingFee.sol deleted file mode 100644 index c1aa1087..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0010_changeDefaultingFee.sol +++ /dev/null @@ -1,39 +0,0 @@ -/* set defaulting fee from 5% to 10% */ - -pragma solidity 0.4.24; - -import "../../LoanManager.sol"; - - -contract Rink0010_changeDefaultingFee { - address constant stabilityBoardProxyAddress = 0x44022C28766652EC5901790E53CEd7A79a19c10A; - - LoanManager constant loanManager = LoanManager(0x3b5DD323534659655EEccc642c3e338AAbD0B219); - - function execute(Rink0010_changeDefaultingFee /* self, not used */) external { - // called via StabilityBoardProxy - require(address(this) == stabilityBoardProxyAddress, "execute only via StabilityBoardProxy"); - - /****************************************************************************** - * Add new loan products with 10% defaulting fee - ******************************************************************************/ - // term (in sec), discountRate, loanCoverageRatio, minDisbursedAmount (w/ 4 decimals), defaultingFeePt, isActive - loanManager.addLoanProduct(30 days, 990641, 600000, 1000, 100000, true); // 12% p.a. - loanManager.addLoanProduct(14 days, 996337, 600000, 1000, 100000, true); // 10% p.a. - loanManager.addLoanProduct(7 days, 998170, 600000, 1000, 100000, true); // 10% p.a. - - loanManager.addLoanProduct(1 hours, 999989, 980000, 2000, 100000, true); // due in 1hr for testing repayments ? p.a. - loanManager.addLoanProduct(1 seconds, 999999, 990000, 3000, 100000, true); // defaults in 1 secs for testing ? p.a. - - /****************************************************************************** - * Disable old loan products - ******************************************************************************/ - loanManager.setLoanProductActiveState(5, false); - loanManager.setLoanProductActiveState(6, false); - loanManager.setLoanProductActiveState(7, false); - loanManager.setLoanProductActiveState(8, false); - loanManager.setLoanProductActiveState(9, false); - - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0011_adjustInterest.sol b/contracts/SB_scripts/rinkeby/Rink0011_adjustInterest.sol deleted file mode 100644 index 01afdb04..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0011_adjustInterest.sol +++ /dev/null @@ -1,68 +0,0 @@ -/* adjust lock & loan interest rates, increase allowedLtdDifferenceAmount */ - -pragma solidity 0.4.24; - -import "../../LoanManager.sol"; -import "../../Locker.sol"; -import "../../MonetarySupervisor.sol"; - - -contract Rink0011_adjustInterest { - - LoanManager constant loanManager = LoanManager(0x3b5DD323534659655EEccc642c3e338AAbD0B219); - Locker constant locker = Locker(0xF74c0CB2713214808553CDA5C78f92219478863d); - MonetarySupervisor constant monetarySupervisor = MonetarySupervisor(0x01844c9bade08A8ffdB09aD9f1fecE2C83a6E6a8); - - function execute(Rink0011_adjustInterest /* self (not used)*/ ) external { - /****************************************************************************** - * Disable old and add new LOAN products - ******************************************************************************/ - loanManager.setLoanProductActiveState(10, false); - loanManager.setLoanProductActiveState(11, false); - loanManager.setLoanProductActiveState(12, false); - loanManager.setLoanProductActiveState(13, false); - loanManager.setLoanProductActiveState(14, false); - - // term (in sec), discountRate, loanCoverageRatio, minDisbursedAmount (w/ 4 decimals), defaultingFeePt, isActive - loanManager.addLoanProduct(365 days, 953288, 600000, 800, 100000, true); // 4.9% p.a. - loanManager.addLoanProduct(180 days, 976405, 600000, 800, 100000, true); // 4.9% p.a. - loanManager.addLoanProduct(90 days, 988062, 600000, 800, 100000, true); // 4.9% p.a. - loanManager.addLoanProduct(30 days, 995988, 600000, 800, 100000, true); // 4.9% p.a. - loanManager.addLoanProduct(14 days, 998124, 600000, 800, 100000, true); // 4.9% p.a. - loanManager.addLoanProduct(7 days, 999062, 600000, 800, 100000, true); // 4.9% p.a. - - loanManager.addLoanProduct(1 hours, 999989, 980000, 2000, 50000, true); // due in 1hr for testing repayments ? p.a. - loanManager.addLoanProduct(1 minutes, 999999, 990000, 3000, 50000, true); // defaults in 1 secs for testing ? p.a. - - /****************************************************************************** - * Disable old and add new LOCK products - ******************************************************************************/ - locker.setLockProductActiveState(0, false); - locker.setLockProductActiveState(1, false); - locker.setLockProductActiveState(2, false); - locker.setLockProductActiveState(3, false); - locker.setLockProductActiveState(4, false); - - // (perTermInterest, durationInSecs, minimumLockAmount, isActive) - locker.addLockProduct(45000, 365 days, 1000, true); // 4.5% p.a. - locker.addLockProduct(22192, 180 days, 1000, true); // 4.5% p.a. - locker.addLockProduct(11096, 90 days, 1000, true); // 4.5% p.a. - locker.addLockProduct(3699, 30 days, 1000, true); // 4.5% p.a. - locker.addLockProduct(1727, 14 days, 1000, true); // 4.5% p.a. - locker.addLockProduct(864, 7 days, 1000, true); // 4.5% p.a. - - locker.addLockProduct(100, 1 hours, 2000, true); // for testing, ~87.60% p.a. - locker.addLockProduct(2 , 1 minutes, 3000, true); // for testing, ~105.12% p.a. - - - monetarySupervisor.setLtdParams( - 200000 /* ltdLockDifferenceLimit = 20% allow lock if Loan To Deposit ratio stays within 1 - this param - stored as parts per million */, - 200000 /* ltdLoanDifferenceLimit = 20% allow loan if Loan To Deposit ratio stays within 1 + this param - stored as parts per million */, - 1000000 /* allowedLtdDifferenceAmount = 10,000 A-EUR if totalLoan and totalLock difference is less than that - then allow loan or lock even if ltdDifference limit would go off with it */ - ); - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rink0012_initNewExchange.sol b/contracts/SB_scripts/rinkeby/Rink0012_initNewExchange.sol deleted file mode 100644 index cf773574..00000000 --- a/contracts/SB_scripts/rinkeby/Rink0012_initNewExchange.sol +++ /dev/null @@ -1,30 +0,0 @@ -/* Set up new Exchange contract with required permissions */ - -pragma solidity 0.4.24; - -import "../../FeeAccount.sol"; -import "../../Exchange.sol"; - - -contract Rink0012_initNewExchange { - address constant stabilityBoardProxyAddress = 0x44022C28766652EC5901790E53CEd7A79a19c10A; - - FeeAccount constant feeAccount = FeeAccount(0x0F5983a6d760BF6E385339af0e67e87420d413EC); - Exchange constant newExchange = Exchange(0x554817688D096ae89fDacCf52E76f629B9Db8f53); - - function execute(Rink0012_initNewExchange /* self, not used */) external { - // called via StabilityBoardProxy - require(address(this) == stabilityBoardProxyAddress, "only deploy via stabilityboardsigner"); - - /****************************************************************************** - * Set up permissions - ******************************************************************************/ - // StabilityBoard - newExchange.grantPermission(stabilityBoardProxyAddress, "StabilityBoard"); - - // set NoTransferFee permissions - feeAccount.grantPermission(address(newExchange), "NoTransferFee"); - - } - -} diff --git a/contracts/SB_scripts/rinkeby/Rinkeby_0001_initAll.sol b/contracts/SB_scripts/rinkeby/Rinkeby_0001_initAll.sol new file mode 100644 index 00000000..b4cb3954 --- /dev/null +++ b/contracts/SB_scripts/rinkeby/Rinkeby_0001_initAll.sol @@ -0,0 +1,118 @@ +/* Set up new contracts */ + +pragma solidity 0.4.24; + +import "../../AugmintReserves.sol"; +import "../../Exchange.sol"; +import "../../FeeAccount.sol"; +import "../../InterestEarnedAccount.sol"; +import "../../LoanManager.sol"; +import "../../Locker.sol"; +import "../../MonetarySupervisor.sol"; +import "../../Rates.sol"; +import "../../TokenAEur.sol"; +import "../../StabilityBoardProxy.sol"; +import "../../PreToken.sol"; +import "../../PreTokenProxy.sol"; + +contract Rinkeby_0001_initAll { + + /****************************************************************************** + * External dependencies + ******************************************************************************/ + address public constant RATES_FEEDER_ACCOUNT = 0x8C58187a978979947b88824DCdA5Cb5fD4410387; + + /****************************************************************************** + * New contracts + ******************************************************************************/ + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0x50d281C28846576EAaf679Ab6F3BaaC52b776e72); + AugmintReserves public constant AUGMINT_RESERVES = AugmintReserves(0xC036a1DD59Ac55e2fB6b3D7416cb4ECC44605834); + Exchange public constant EXCHANGE = Exchange(0xDF47D51028DafF13424F42523FdAc73079ab901b); + FeeAccount public constant FEE_ACCOUNT = FeeAccount(0xB77F9cDdA72eEC47a57793Be088C7b523f6b5014); + InterestEarnedAccount public constant INTEREST_EARNED_ACCOUNT = InterestEarnedAccount(0x489cbf1674b575e6dFcFF0A4F2BBc74f7e9DDe28); + LoanManager public constant LOAN_MANAGER = LoanManager(0x6CB7731c78E677f85942B5f1D646b3485E5820c1); + Locker public constant LOCKER = Locker(0x6d84aB6c385B827E58c358D078AC7b1C61b68821); + MonetarySupervisor public constant MONETARY_SUPERVISOR = MonetarySupervisor(0xCeC3574ECa89409b15a8A72A6E737C4171457871); + Rates public constant RATES = Rates(0xDfA3a0aEb9645a55b684CB3aCE8C42D018405bDa); + TokenAEur public constant TOKEN_AEUR = TokenAEur(0x0557183334Edc23a666201EDC6b0AA2787e2ad3F); + PreToken public constant PRE_TOKEN = PreToken(0xA7B67E7E3E7f1e76E8d799A690F675abeB85c788); + PreTokenProxy public constant PRE_TOKEN_PROXY = PreTokenProxy(0xB7CAe2C48F3F34b9696FD290001deA16B299498A); + + function execute(Rinkeby_0001_initAll /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + /****************************************************************************** + * Set up permissions + ******************************************************************************/ + + // StabilityBoard permission + AUGMINT_RESERVES.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + EXCHANGE.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + FEE_ACCOUNT.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + INTEREST_EARNED_ACCOUNT.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + LOAN_MANAGER.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + LOCKER.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + MONETARY_SUPERVISOR.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + RATES.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + TOKEN_AEUR.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + + // RatesFeeder permission (allows calling setRate) + RATES.grantPermission(address(RATES_FEEDER_ACCOUNT), "RatesFeeder"); + + // NoTransferFee permission + FEE_ACCOUNT.grantPermission(address(AUGMINT_RESERVES), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(EXCHANGE), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(FEE_ACCOUNT), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(INTEREST_EARNED_ACCOUNT), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(LOAN_MANAGER), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(LOCKER), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(MONETARY_SUPERVISOR), "NoTransferFee"); + + // MonetarySupervisor permission + AUGMINT_RESERVES.grantPermission(address(MONETARY_SUPERVISOR), "MonetarySupervisor"); + INTEREST_EARNED_ACCOUNT.grantPermission(address(MONETARY_SUPERVISOR), "MonetarySupervisor"); + TOKEN_AEUR.grantPermission(address(MONETARY_SUPERVISOR), "MonetarySupervisor"); + + // LoanManager permission + MONETARY_SUPERVISOR.grantPermission(address(LOAN_MANAGER), "LoanManager"); + + // Locker permission + MONETARY_SUPERVISOR.grantPermission(address(LOCKER), "Locker"); + + + // PreToken permissions + PRE_TOKEN.grantPermission(address(PRE_TOKEN_PROXY), "PreTokenSigner"); + PRE_TOKEN.grantPermission(address(PRE_TOKEN_PROXY), "PermissionGranter"); + PRE_TOKEN.revokePermission(address(STABILITY_BOARD_PROXY), "PermissionGranter"); + + + /****************************************************************************** + * Add loan products + ******************************************************************************/ + // term (in sec), discountRate, loanCoverageRatio, minDisbursedAmount (w/ 4 decimals), defaultingFeePt, isActive + LOAN_MANAGER.addLoanProduct(365 days, 953288, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(180 days, 976405, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(90 days, 988062, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(30 days, 995988, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(14 days, 998124, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(7 days, 999062, 600000, 800, 100000, true); // 4.9% p.a. + + LOAN_MANAGER.addLoanProduct(1 hours, 999989, 980000, 2000, 50000, true); // due in 1hr for testing repayments ? p.a. + LOAN_MANAGER.addLoanProduct(1 minutes, 999999, 990000, 3000, 50000, true); // defaults in 1 secs for testing ? p.a. + + /****************************************************************************** + * Add lock products + ******************************************************************************/ + // (perTermInterest, durationInSecs, minimumLockAmount, isActive) + LOCKER.addLockProduct(45000, 365 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(22192, 180 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(11096, 90 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(3699, 30 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(1727, 14 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(864, 7 days, 1000, true); // 4.5% p.a. + + LOCKER.addLockProduct(100, 1 hours, 2000, true); // for testing, ~87.60% p.a. + LOCKER.addLockProduct(2, 1 minutes, 3000, true); // for testing, ~105.12% p.a. + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/rinkeby/Rinkeby_0002_redeployInitAll.sol b/contracts/SB_scripts/rinkeby/Rinkeby_0002_redeployInitAll.sol new file mode 100644 index 00000000..cde93516 --- /dev/null +++ b/contracts/SB_scripts/rinkeby/Rinkeby_0002_redeployInitAll.sol @@ -0,0 +1,108 @@ +/* Set up new contracts */ + +pragma solidity 0.4.24; + +import "../../AugmintReserves.sol"; +import "../../Exchange.sol"; +import "../../FeeAccount.sol"; +import "../../InterestEarnedAccount.sol"; +import "../../LoanManager.sol"; +import "../../Locker.sol"; +import "../../MonetarySupervisor.sol"; +import "../../Rates.sol"; +import "../../TokenAEur.sol"; +import "../../StabilityBoardProxy.sol"; + +contract Rinkeby_0002_redeployInitAll { + + /****************************************************************************** + * External dependencies + ******************************************************************************/ + address public constant RATES_FEEDER_ACCOUNT = 0x8C58187a978979947b88824DCdA5Cb5fD4410387; + + /****************************************************************************** + * New contracts + ******************************************************************************/ + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xa612de13B629a1FF790c1f4E41d0422d2bB50a30); + AugmintReserves public constant AUGMINT_RESERVES = AugmintReserves(0x33Bec125657470e53887400666BdeeD360b2168A); + Exchange public constant EXCHANGE = Exchange(0xe5d6D0c107eaE79d2D30798F252Ac6FF5ECAd459); + FeeAccount public constant FEE_ACCOUNT = FeeAccount(0xaa16EdE9093BB4140e2715ED9a1E41cdFD9D9c29); + InterestEarnedAccount public constant INTEREST_EARNED_ACCOUNT = InterestEarnedAccount(0xDD96979697b76787b5062084eEA60BF929ddD844); + LoanManager public constant LOAN_MANAGER = LoanManager(0x3792c5a5077DacfE331B81837ef73bC0Ea721d90); + Locker public constant LOCKER = Locker(0xc0B97fE5CAD0d43D0c974C4E9A00312dc661f8Ab); + MonetarySupervisor public constant MONETARY_SUPERVISOR = MonetarySupervisor(0x4A7F6EcbE8B324A55b85adcc45313A412957B8ea); + Rates public constant RATES = Rates(0xEE8C7a3e99945A5207Dca026504d67527125Da9C); + TokenAEur public constant TOKEN_AEUR = TokenAEur(0x79065a165Ec09E6A89D584a14872802717FE12a3); + + function execute(Rinkeby_0002_redeployInitAll /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + /****************************************************************************** + * Set up permissions + ******************************************************************************/ + + // StabilityBoard permission + AUGMINT_RESERVES.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + EXCHANGE.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + FEE_ACCOUNT.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + INTEREST_EARNED_ACCOUNT.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + LOAN_MANAGER.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + LOCKER.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + MONETARY_SUPERVISOR.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + RATES.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + TOKEN_AEUR.grantPermission(address(STABILITY_BOARD_PROXY), "StabilityBoard"); + + // RatesFeeder permission (allows calling setRate) + RATES.grantPermission(address(RATES_FEEDER_ACCOUNT), "RatesFeeder"); + + // NoTransferFee permission + FEE_ACCOUNT.grantPermission(address(AUGMINT_RESERVES), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(EXCHANGE), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(FEE_ACCOUNT), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(INTEREST_EARNED_ACCOUNT), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(LOAN_MANAGER), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(LOCKER), "NoTransferFee"); + FEE_ACCOUNT.grantPermission(address(MONETARY_SUPERVISOR), "NoTransferFee"); + + // MonetarySupervisor permission + AUGMINT_RESERVES.grantPermission(address(MONETARY_SUPERVISOR), "MonetarySupervisor"); + INTEREST_EARNED_ACCOUNT.grantPermission(address(MONETARY_SUPERVISOR), "MonetarySupervisor"); + TOKEN_AEUR.grantPermission(address(MONETARY_SUPERVISOR), "MonetarySupervisor"); + + // LoanManager permission + MONETARY_SUPERVISOR.grantPermission(address(LOAN_MANAGER), "LoanManager"); + + // Locker permission + MONETARY_SUPERVISOR.grantPermission(address(LOCKER), "Locker"); + + + /****************************************************************************** + * Add loan products + ******************************************************************************/ + // term (in sec), discountRate, loanCoverageRatio, minDisbursedAmount (w/ 4 decimals), defaultingFeePt, isActive + LOAN_MANAGER.addLoanProduct(365 days, 953288, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(180 days, 976405, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(90 days, 988062, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(30 days, 995988, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(14 days, 998124, 600000, 800, 100000, true); // 4.9% p.a. + LOAN_MANAGER.addLoanProduct(7 days, 999062, 600000, 800, 100000, true); // 4.9% p.a. + + LOAN_MANAGER.addLoanProduct(1 hours, 999989, 980000, 2000, 50000, true); // due in 1hr for testing repayments ? p.a. + LOAN_MANAGER.addLoanProduct(1 minutes, 999999, 990000, 3000, 50000, true); // defaults in 1 secs for testing ? p.a. + + /****************************************************************************** + * Add lock products + ******************************************************************************/ + // (perTermInterest, durationInSecs, minimumLockAmount, isActive) + LOCKER.addLockProduct(45000, 365 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(22192, 180 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(11096, 90 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(3699, 30 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(1727, 14 days, 1000, true); // 4.5% p.a. + LOCKER.addLockProduct(864, 7 days, 1000, true); // 4.5% p.a. + + LOCKER.addLockProduct(100, 1 hours, 2000, true); // for testing, ~87.60% p.a. + LOCKER.addLockProduct(2, 1 minutes, 3000, true); // for testing, ~105.12% p.a. + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/rinkeby/Rinkeby_0003_migrateLegacy.sol b/contracts/SB_scripts/rinkeby/Rinkeby_0003_migrateLegacy.sol new file mode 100644 index 00000000..5b629773 --- /dev/null +++ b/contracts/SB_scripts/rinkeby/Rinkeby_0003_migrateLegacy.sol @@ -0,0 +1,95 @@ +/* Migrate legacy contracts to the new StabilityBoardProxy */ + +pragma solidity 0.4.24; + +import "../../AugmintReserves.sol"; +import "../../Exchange.sol"; +import "../../FeeAccount.sol"; +import "../../InterestEarnedAccount.sol"; +import "../../LoanManager.sol"; +import "../../Locker.sol"; +import "../../MonetarySupervisor.sol"; +import "../../Rates.sol"; +import "../../TokenAEur.sol"; +import "../../StabilityBoardProxy.sol"; + +contract Rinkeby_0003_migrateLegacy { + + /****************************************************************************** + * StabilityBoardProxies + ******************************************************************************/ + StabilityBoardProxy public constant OLD_STABILITY_BOARD_PROXY = StabilityBoardProxy(0x50d281C28846576EAaf679Ab6F3BaaC52b776e72); + StabilityBoardProxy public constant NEW_STABILITY_BOARD_PROXY = StabilityBoardProxy(0xa612de13B629a1FF790c1f4E41d0422d2bB50a30); + + /****************************************************************************** + * Legacy contracts + ******************************************************************************/ + AugmintReserves public constant AUGMINT_RESERVES = AugmintReserves(0xC036a1DD59Ac55e2fB6b3D7416cb4ECC44605834); + Exchange public constant EXCHANGE = Exchange(0xDF47D51028DafF13424F42523FdAc73079ab901b); + FeeAccount public constant FEE_ACCOUNT = FeeAccount(0xB77F9cDdA72eEC47a57793Be088C7b523f6b5014); + InterestEarnedAccount public constant INTEREST_EARNED_ACCOUNT = InterestEarnedAccount(0x489cbf1674b575e6dFcFF0A4F2BBc74f7e9DDe28); + LoanManager public constant LOAN_MANAGER = LoanManager(0x6CB7731c78E677f85942B5f1D646b3485E5820c1); + Locker public constant LOCKER = Locker(0x6d84aB6c385B827E58c358D078AC7b1C61b68821); + MonetarySupervisor public constant MONETARY_SUPERVISOR = MonetarySupervisor(0xCeC3574ECa89409b15a8A72A6E737C4171457871); + Rates public constant RATES = Rates(0xDfA3a0aEb9645a55b684CB3aCE8C42D018405bDa); + TokenAEur public constant TOKEN_AEUR = TokenAEur(0x0557183334Edc23a666201EDC6b0AA2787e2ad3F); + + function execute(Rinkeby_0003_migrateLegacy /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(OLD_STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + /****************************************************************************** + * Grant permissions for new proxy + ******************************************************************************/ + + // StabilityBoard permission + AUGMINT_RESERVES.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + EXCHANGE.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + FEE_ACCOUNT.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + INTEREST_EARNED_ACCOUNT.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + LOAN_MANAGER.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + LOCKER.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + MONETARY_SUPERVISOR.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + RATES.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + TOKEN_AEUR.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "StabilityBoard"); + + // PermissionGranter permission + AUGMINT_RESERVES.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + EXCHANGE.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + FEE_ACCOUNT.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + INTEREST_EARNED_ACCOUNT.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + LOAN_MANAGER.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + LOCKER.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + MONETARY_SUPERVISOR.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + RATES.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + TOKEN_AEUR.grantPermission(address(NEW_STABILITY_BOARD_PROXY), "PermissionGranter"); + + + /****************************************************************************** + * Revoke permissions for old proxy + ******************************************************************************/ + + // StabilityBoard permission + AUGMINT_RESERVES.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + EXCHANGE.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + FEE_ACCOUNT.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + INTEREST_EARNED_ACCOUNT.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + LOAN_MANAGER.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + LOCKER.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + MONETARY_SUPERVISOR.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + RATES.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + TOKEN_AEUR.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "StabilityBoard"); + + // PermissionGranter permission + AUGMINT_RESERVES.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + EXCHANGE.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + FEE_ACCOUNT.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + INTEREST_EARNED_ACCOUNT.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + LOAN_MANAGER.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + LOCKER.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + MONETARY_SUPERVISOR.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + RATES.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + TOKEN_AEUR.revokePermission(address(OLD_STABILITY_BOARD_PROXY), "PermissionGranter"); + + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol b/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol new file mode 100644 index 00000000..c7ed11f0 --- /dev/null +++ b/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol @@ -0,0 +1,78 @@ +/* Setup new and legacy contract dependencies */ + +pragma solidity 0.4.24; + +import "../../AugmintReserves.sol"; +import "../../Exchange.sol"; +import "../../FeeAccount.sol"; +import "../../InterestEarnedAccount.sol"; +import "../../LoanManager.sol"; +import "../../Locker.sol"; +import "../../MonetarySupervisor.sol"; +import "../../Rates.sol"; +import "../../TokenAEur.sol"; +import "../../StabilityBoardProxy.sol"; + +contract Rinkeby_0004_setupLegacy { + + /****************************************************************************** + * StabilityBoardProxy + ******************************************************************************/ + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xa612de13B629a1FF790c1f4E41d0422d2bB50a30); + + /****************************************************************************** + * New contracts + ******************************************************************************/ + AugmintReserves public constant NEW_AUGMINT_RESERVES = AugmintReserves(0x33Bec125657470e53887400666BdeeD360b2168A); + Exchange public constant NEW_EXCHANGE = Exchange(0xe5d6D0c107eaE79d2D30798F252Ac6FF5ECAd459); + FeeAccount public constant NEW_FEE_ACCOUNT = FeeAccount(0xaa16EdE9093BB4140e2715ED9a1E41cdFD9D9c29); + InterestEarnedAccount public constant NEW_INTEREST_EARNED_ACCOUNT = InterestEarnedAccount(0xDD96979697b76787b5062084eEA60BF929ddD844); + LoanManager public constant NEW_LOAN_MANAGER = LoanManager(0x3792c5a5077DacfE331B81837ef73bC0Ea721d90); + Locker public constant NEW_LOCKER = Locker(0xc0B97fE5CAD0d43D0c974C4E9A00312dc661f8Ab); + MonetarySupervisor public constant NEW_MONETARY_SUPERVISOR = MonetarySupervisor(0x4A7F6EcbE8B324A55b85adcc45313A412957B8ea); + Rates public constant NEW_RATES = Rates(0xEE8C7a3e99945A5207Dca026504d67527125Da9C); + TokenAEur public constant NEW_TOKEN_AEUR = TokenAEur(0x79065a165Ec09E6A89D584a14872802717FE12a3); + + /****************************************************************************** + * Legacy contracts + ******************************************************************************/ + AugmintReserves public constant OLD_AUGMINT_RESERVES = AugmintReserves(0xC036a1DD59Ac55e2fB6b3D7416cb4ECC44605834); + Exchange public constant OLD_EXCHANGE = Exchange(0xDF47D51028DafF13424F42523FdAc73079ab901b); + FeeAccount public constant OLD_FEE_ACCOUNT = FeeAccount(0xB77F9cDdA72eEC47a57793Be088C7b523f6b5014); + InterestEarnedAccount public constant OLD_INTEREST_EARNED_ACCOUNT = InterestEarnedAccount(0x489cbf1674b575e6dFcFF0A4F2BBc74f7e9DDe28); + LoanManager public constant OLD_LOAN_MANAGER = LoanManager(0x6CB7731c78E677f85942B5f1D646b3485E5820c1); + Locker public constant OLD_LOCKER = Locker(0x6d84aB6c385B827E58c358D078AC7b1C61b68821); + MonetarySupervisor public constant OLD_MONETARY_SUPERVISOR = MonetarySupervisor(0xCeC3574ECa89409b15a8A72A6E737C4171457871); + Rates public constant OLD_RATES = Rates(0xDfA3a0aEb9645a55b684CB3aCE8C42D018405bDa); + TokenAEur public constant OLD_TOKEN_AEUR = TokenAEur(0x0557183334Edc23a666201EDC6b0AA2787e2ad3F); + + function execute(Rinkeby_0004_setupLegacy /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + + /****************************************************************************** + * Setup permissions in new contracts for legacy contracts + ******************************************************************************/ + NEW_MONETARY_SUPERVISOR.grantPermission(address(OLD_LOAN_MANAGER), "LoanManager"); + NEW_MONETARY_SUPERVISOR.grantPermission(address(OLD_LOCKER), "Locker"); + + /****************************************************************************** + * Accept legacy tokens + ******************************************************************************/ + NEW_MONETARY_SUPERVISOR.setAcceptedLegacyAugmintToken(OLD_TOKEN_AEUR, true); + + + /****************************************************************************** + * Setup permissions in legacy contracts for new contracts + ******************************************************************************/ + OLD_FEE_ACCOUNT.grantPermission(address(NEW_MONETARY_SUPERVISOR), "NoTransferFee"); + + /****************************************************************************** + * Set new Rates in old Exchange + ******************************************************************************/ + // Note: this step should have been moved to Rinkeby_0006_postDeploySetup! + OLD_EXCHANGE.setRatesContract(NEW_RATES); + + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/rinkeby/Rinkeby_0005_setupSigners.sol b/contracts/SB_scripts/rinkeby/Rinkeby_0005_setupSigners.sol new file mode 100644 index 00000000..fe8c882f --- /dev/null +++ b/contracts/SB_scripts/rinkeby/Rinkeby_0005_setupSigners.sol @@ -0,0 +1,22 @@ +/* setup StabilityBoard signers in new StabilityBoardProxy on Rinkeby */ + +pragma solidity 0.4.24; + +import "../../generic/MultiSig.sol"; +import "../../StabilityBoardProxy.sol"; + + +contract Rinkeby_0005_setupSigners { + + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xa612de13B629a1FF790c1f4E41d0422d2bB50a30); + + function execute(Rinkeby_0005_setupSigners /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + address[] memory signersToAdd = new address[](2); // dynamic array needed for addSigners() & removeSigners() + signersToAdd[0] = 0xe71E9636e31B838aF0A3c38B3f3449cdC2b7aa87; // phraktle + signersToAdd[1] = 0x9aaf197F25d207ecE17DfBeb20780095f7623A23; // petro + STABILITY_BOARD_PROXY.addSigners(signersToAdd); + } +} \ No newline at end of file diff --git a/contracts/SB_scripts/rinkeby/Rinkeby_0006_postDeploySetup.sol b/contracts/SB_scripts/rinkeby/Rinkeby_0006_postDeploySetup.sol new file mode 100644 index 00000000..9bffe7d0 --- /dev/null +++ b/contracts/SB_scripts/rinkeby/Rinkeby_0006_postDeploySetup.sol @@ -0,0 +1,99 @@ +/* Setup new and legacy contract dependencies */ + +pragma solidity 0.4.24; + +import "../../AugmintReserves.sol"; +import "../../Exchange.sol"; +import "../../FeeAccount.sol"; +import "../../InterestEarnedAccount.sol"; +import "../../LoanManager.sol"; +import "../../Locker.sol"; +import "../../MonetarySupervisor.sol"; +import "../../Rates.sol"; +import "../../TokenAEur.sol"; +import "../../StabilityBoardProxy.sol"; + +contract Rinkeby_0006_postDeploySetup { + + /****************************************************************************** + * StabilityBoardProxy + ******************************************************************************/ + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xa612de13B629a1FF790c1f4E41d0422d2bB50a30); + + /****************************************************************************** + * New contracts + ******************************************************************************/ + AugmintReserves public constant NEW_AUGMINT_RESERVES = AugmintReserves(0x33Bec125657470e53887400666BdeeD360b2168A); + Exchange public constant NEW_EXCHANGE = Exchange(0xe5d6D0c107eaE79d2D30798F252Ac6FF5ECAd459); + FeeAccount public constant NEW_FEE_ACCOUNT = FeeAccount(0xaa16EdE9093BB4140e2715ED9a1E41cdFD9D9c29); + InterestEarnedAccount public constant NEW_INTEREST_EARNED_ACCOUNT = InterestEarnedAccount(0xDD96979697b76787b5062084eEA60BF929ddD844); + LoanManager public constant NEW_LOAN_MANAGER = LoanManager(0x3792c5a5077DacfE331B81837ef73bC0Ea721d90); + Locker public constant NEW_LOCKER = Locker(0xc0B97fE5CAD0d43D0c974C4E9A00312dc661f8Ab); + MonetarySupervisor public constant NEW_MONETARY_SUPERVISOR = MonetarySupervisor(0x4A7F6EcbE8B324A55b85adcc45313A412957B8ea); + Rates public constant NEW_RATES = Rates(0xEE8C7a3e99945A5207Dca026504d67527125Da9C); + TokenAEur public constant NEW_TOKEN_AEUR = TokenAEur(0x79065a165Ec09E6A89D584a14872802717FE12a3); + + /****************************************************************************** + * Legacy contracts + ******************************************************************************/ + AugmintReserves public constant OLD_AUGMINT_RESERVES = AugmintReserves(0xC036a1DD59Ac55e2fB6b3D7416cb4ECC44605834); + Exchange public constant OLD_EXCHANGE = Exchange(0xDF47D51028DafF13424F42523FdAc73079ab901b); + FeeAccount public constant OLD_FEE_ACCOUNT = FeeAccount(0xB77F9cDdA72eEC47a57793Be088C7b523f6b5014); + InterestEarnedAccount public constant OLD_INTEREST_EARNED_ACCOUNT = InterestEarnedAccount(0x489cbf1674b575e6dFcFF0A4F2BBc74f7e9DDe28); + LoanManager public constant OLD_LOAN_MANAGER = LoanManager(0x6CB7731c78E677f85942B5f1D646b3485E5820c1); + Locker public constant OLD_LOCKER = Locker(0x6d84aB6c385B827E58c358D078AC7b1C61b68821); + MonetarySupervisor public constant OLD_MONETARY_SUPERVISOR = MonetarySupervisor(0xCeC3574ECa89409b15a8A72A6E737C4171457871); + Rates public constant OLD_RATES = Rates(0xDfA3a0aEb9645a55b684CB3aCE8C42D018405bDa); + TokenAEur public constant OLD_TOKEN_AEUR = TokenAEur(0x0557183334Edc23a666201EDC6b0AA2787e2ad3F); + + function execute(Rinkeby_0006_postDeploySetup /* self, not used */) external { + // called via StabilityBoardProxy + require(address(this) == address(STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); + + + /****************************************************************************** + * Migrate KPIs from old MonetarySupervisor + ******************************************************************************/ + uint oldTotalLoan = OLD_MONETARY_SUPERVISOR.totalLoanAmount(); + uint oldTotalLock = OLD_MONETARY_SUPERVISOR.totalLockedAmount(); + NEW_MONETARY_SUPERVISOR.adjustKPIs(oldTotalLoan, oldTotalLock); + + + /****************************************************************************** + * Set new MonetarySupervisor in old Locker + ******************************************************************************/ + OLD_LOCKER.setMonetarySupervisor(NEW_MONETARY_SUPERVISOR); + + /****************************************************************************** + * Set new Rates and MonetarySupervisor in old LoanManager + ******************************************************************************/ + OLD_LOAN_MANAGER.setSystemContracts(NEW_RATES, NEW_MONETARY_SUPERVISOR); + + + /****************************************************************************** + * Disable old loan products + ******************************************************************************/ + OLD_LOAN_MANAGER.setLoanProductActiveState(0, false); + OLD_LOAN_MANAGER.setLoanProductActiveState(1, false); + OLD_LOAN_MANAGER.setLoanProductActiveState(2, false); + OLD_LOAN_MANAGER.setLoanProductActiveState(3, false); + OLD_LOAN_MANAGER.setLoanProductActiveState(4, false); + OLD_LOAN_MANAGER.setLoanProductActiveState(5, false); + + OLD_LOAN_MANAGER.setLoanProductActiveState(6, false); + OLD_LOAN_MANAGER.setLoanProductActiveState(7, false); + + /****************************************************************************** + * Disable old lock products + ******************************************************************************/ + OLD_LOCKER.setLockProductActiveState(0, false); + OLD_LOCKER.setLockProductActiveState(1, false); + OLD_LOCKER.setLockProductActiveState(2, false); + OLD_LOCKER.setLockProductActiveState(3, false); + OLD_LOCKER.setLockProductActiveState(4, false); + OLD_LOCKER.setLockProductActiveState(5, false); + + OLD_LOCKER.setLockProductActiveState(6, false); + OLD_LOCKER.setLockProductActiveState(7, false); + } +} \ No newline at end of file diff --git a/contracts/generic/AugmintToken.sol b/contracts/generic/AugmintToken.sol index 89a0cd9e..267f968f 100644 --- a/contracts/generic/AugmintToken.sol +++ b/contracts/generic/AugmintToken.sol @@ -34,6 +34,7 @@ contract AugmintToken is AugmintTokenInterface { feeAccount = _feeAccount; } + function transfer(address to, uint256 amount) external returns (bool) { _transfer(msg.sender, to, amount, ""); return true; @@ -67,11 +68,16 @@ contract AugmintToken is AugmintTokenInterface { 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 returns (bool) { - return _increaseApproval(msg.sender, _spender, _addedValue); + 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 returns (bool) { + 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; @@ -79,7 +85,6 @@ contract AugmintToken is AugmintTokenInterface { allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); } emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); - return true; } function transferFrom(address from, address to, uint256 amount) external returns (bool) { @@ -188,27 +193,22 @@ contract AugmintToken is AugmintTokenInterface { _transfer(signer, msg.sender, requestedExecutorFeeInToken, "Delegated transfer fee", 0); } - function _increaseApproval(address _approver, address _spender, uint _addedValue) private returns (bool) { - allowed[_approver][_spender] = allowed[_approver][_spender].add(_addedValue); - emit Approval(_approver, _spender, allowed[_approver][_spender]); - } - function _transferFrom(address from, address to, uint256 amount, string narrative) private { - require(balances[from] >= amount, "balance must >= amount"); - require(allowed[from][msg.sender] >= amount, "allowance must be >= amount"); - // don't allow 0 transferFrom if no approval: - require(allowed[from][msg.sender] > 0, "allowance must be >= 0 even with 0 amount"); + uint fee = feeAccount.calculateTransferFee(from, to, amount); + uint amountWithFee = amount.add(fee); - /* NB: fee is deducted from owner. It can result that transferFrom of amount x to fail - when x + fee is not availale on owner balance */ - _transfer(from, to, amount, narrative); + /* 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(amount); + 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); } @@ -230,5 +230,4 @@ contract AugmintToken is AugmintTokenInterface { emit AugmintTransfer(from, to, transferAmount, narrative, fee); } - } diff --git a/contracts/generic/MultiSig.sol b/contracts/generic/MultiSig.sol index e6c1634d..c4abfd8a 100644 --- a/contracts/generic/MultiSig.sol +++ b/contracts/generic/MultiSig.sol @@ -18,8 +18,6 @@ import "./SafeMath.sol"; contract MultiSig { using SafeMath for uint256; - uint public constant CHUNK_SIZE = 100; - mapping(address => bool) public isSigner; address[] public allSigners; // all signers, even the disabled ones // NB: it can contain duplicates when a signer is added, removed then readded again @@ -63,18 +61,18 @@ contract MultiSig { "script state must be New or Approved"); require(!script.signedBy[msg.sender], "script must not be signed by signer yet"); - if(script.allSigners.length == 0) { + if (script.allSigners.length == 0) { // first sign of a new script scriptAddresses.push(scriptAddress); } script.allSigners.push(msg.sender); - script.signedBy[msg.sender] = true; + script.signedBy[msg.sender] = true; script.signCount = script.signCount.add(1); emit ScriptSigned(scriptAddress, msg.sender); - if(checkQuorum(script.signCount)){ + if (checkQuorum(script.signCount)) { script.state = ScriptState.Approved; emit ScriptApproved(scriptAddress); } @@ -86,18 +84,13 @@ contract MultiSig { Script storage script = scripts[scriptAddress]; require(script.state == ScriptState.Approved, "script state must be Approved"); - /* init to failed because if delegatecall rans out of gas we won't have enough left to set it. - NB: delegatecall leaves 63/64 part of gasLimit for the caller. - Therefore the execute might revert with out of gas, leaving script in Approved state - when execute() is called with small gas limits. - */ - script.state = ScriptState.Failed; - // passing scriptAddress to allow called script access its own public fx-s if needed - if(scriptAddress.delegatecall(bytes4(keccak256("execute(address)")), scriptAddress)) { + if (scriptAddress.delegatecall.gas(gasleft() - 23000) + (abi.encodeWithSignature("execute(address)", scriptAddress))) { script.state = ScriptState.Done; result = true; } else { + script.state = ScriptState.Failed; result = false; } emit ScriptExecuted(scriptAddress, result); @@ -109,7 +102,7 @@ contract MultiSig { require(script.state == ScriptState.Approved || script.state == ScriptState.New, "script state must be New or Approved"); - script.state= ScriptState.Cancelled; + script.state = ScriptState.Cancelled; emit ScriptCancelled(scriptAddress); } @@ -149,11 +142,15 @@ contract MultiSig { } // UI helper fx - Returns signers from offset as [signer id (index in allSigners), address as uint, isActive 0 or 1] - function getAllSigners(uint offset) external view returns(uint[3][CHUNK_SIZE] signersResult) { - for (uint8 i = 0; i < CHUNK_SIZE && i + offset < allSigners.length; i++) { - address signerAddress = allSigners[i + offset]; - signersResult[i] = [ i + offset, uint(signerAddress), isSigner[signerAddress] ? 1 : 0 ]; + function getSigners(uint offset, uint16 chunkSize) + external view returns(uint[3][]) { + uint limit = SafeMath.min(offset.add(chunkSize), allSigners.length); + uint[3][] memory response = new uint[3][](limit.sub(offset)); + for (uint i = offset; i < limit; i++) { + address signerAddress = allSigners[i]; + response[i - offset] = [i, uint(signerAddress), isSigner[signerAddress] ? 1 : 0]; } + return response; } function getScriptsCount() view external returns (uint scriptsCount) { @@ -162,12 +159,15 @@ contract MultiSig { // UI helper fx - Returns scripts from offset as // [scriptId (index in scriptAddresses[]), address as uint, state, signCount] - function getAllScripts(uint offset) external view returns(uint[4][CHUNK_SIZE] scriptsResult) { - for (uint8 i = 0; i < CHUNK_SIZE && i + offset < scriptAddresses.length; i++) { - address scriptAddress = scriptAddresses[i + offset]; - scriptsResult[i] = [ i + offset, uint(scriptAddress), uint(scripts[scriptAddress].state), - scripts[scriptAddress].signCount ]; + function getScripts(uint offset, uint16 chunkSize) + external view returns(uint[4][]) { + uint limit = SafeMath.min(offset.add(chunkSize), scriptAddresses.length); + uint[4][] memory response = new uint[4][](limit.sub(offset)); + for (uint i = offset; i < limit; i++) { + address scriptAddress = scriptAddresses[i]; + response[i - offset] = [i, uint(scriptAddress), + uint(scripts[scriptAddress].state), scripts[scriptAddress].signCount]; } + return response; } - } diff --git a/contracts/generic/SystemAccount.sol b/contracts/generic/SystemAccount.sol index a10e6310..6ff142d0 100644 --- a/contracts/generic/SystemAccount.sol +++ b/contracts/generic/SystemAccount.sol @@ -8,18 +8,15 @@ 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 + constructor(address permissionGranterContract) + public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks - /* TODO: this is only for first pilots to avoid funds stuck in contract due to bugs. - remove this function for higher volume pilots */ 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); } - } diff --git a/contracts/interfaces/AugmintTokenInterface.sol b/contracts/interfaces/AugmintTokenInterface.sol index 021c9cb7..ff3abf81 100644 --- a/contracts/interfaces/AugmintTokenInterface.sol +++ b/contracts/interfaces/AugmintTokenInterface.sol @@ -55,8 +55,8 @@ contract AugmintTokenInterface is Restricted, ERC20Interface { uint requestedExecutorFeeInToken /* the executor can decide to request lower fee */ ) external; - function increaseApproval(address spender, uint addedValue) external returns (bool); - function decreaseApproval(address spender, uint subtractedValue) external returns (bool); + 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; diff --git a/contracts/test/SafeMathTester.sol b/contracts/test/SafeMathTester.sol new file mode 100644 index 00000000..c3a32c94 --- /dev/null +++ b/contracts/test/SafeMathTester.sol @@ -0,0 +1,33 @@ +pragma solidity 0.4.24; + +import "../generic/SafeMath.sol"; + + +contract SafeMathTester { + + using SafeMath for uint256; + + function mul(uint256 a, uint256 b) public pure returns (uint256) { + return a.mul(b); + } + + function div(uint256 a, uint256 b) public pure returns (uint256) { + return a.div(b); + } + + function sub(uint256 a, uint256 b) public pure returns (uint256) { + return a.sub(b); + } + + function add(uint256 a, uint256 b) public pure returns (uint256) { + return a.add(b); + } + + function roundedDiv(uint256 a, uint256 b) public pure returns (uint256) { + return a.roundedDiv(b); + } + + function ceilDiv(uint256 a, uint256 b) public pure returns (uint256) { + return a.ceilDiv(b); + } +} \ No newline at end of file diff --git a/mainnet_migrations/30_deploy_all_contracts.js b/mainnet_migrations/30_deploy_all_contracts.js new file mode 100644 index 00000000..f65e117c --- /dev/null +++ b/mainnet_migrations/30_deploy_all_contracts.js @@ -0,0 +1,70 @@ +const AugmintReserves = artifacts.require("./AugmintReserves.sol"); +const Exchange = artifacts.require("./Exchange.sol"); +const FeeAccount = artifacts.require("./FeeAccount.sol"); +const InterestEarnedAccount = artifacts.require("./InterestEarnedAccount.sol"); +const LoanManager = artifacts.require("./LoanManager.sol"); +const Locker = artifacts.require("./Locker.sol"); +const Migrations = artifacts.require("./Migrations.sol"); +const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); +const Rates = artifacts.require("./Rates.sol"); +const TokenAEur = artifacts.require("./TokenAEur.sol"); +const StabilityBoardProxy = artifacts.require("./StabilityBoardProxy.sol"); +const PreTokenProxy = artifacts.require("./PreTokenProxy.sol"); +const PreToken = artifacts.require("./PreToken.sol"); + +const MIGRATION_STEP_NUMBER = 30; + +const FEE_ACCOUNT_TRANSFER_FEE_PT = 2000; +const FEE_ACCOUNT_TRANSFER_FEE_MIN = 2; +const FEE_ACCOUNT_TRANSFER_FEE_MAX = 500; + +const MONETARY_SUPERVISOR_LOCK_DIFF_LIMIT = 200000; +const MONETARY_SUPERVISOR_LOAN_DIFF_LIMIT = 200000; +const MONETARY_SUPERVISOR_ALLOWED_DIFF_AMOUNT = 1000000; + +module.exports = function(deployer) { + deployer.then(async () => { + + // ### StabilityBoardProxy ### + await deployer.deploy(StabilityBoardProxy); + + // ### FeeAccount ### + await deployer.deploy(FeeAccount, StabilityBoardProxy.address, FEE_ACCOUNT_TRANSFER_FEE_PT, FEE_ACCOUNT_TRANSFER_FEE_MIN, FEE_ACCOUNT_TRANSFER_FEE_MAX); + + // ### TokenAEur ### + await deployer.deploy(TokenAEur, StabilityBoardProxy.address, FeeAccount.address); + + // ### Rates ### + await deployer.deploy(Rates, StabilityBoardProxy.address); + + // ### AugmintReserves ### + await deployer.deploy(AugmintReserves, StabilityBoardProxy.address) + + // ### InterestEarnedAccount ### + await deployer.deploy(InterestEarnedAccount, StabilityBoardProxy.address); + + // ### MonetarySupervisor ### + await deployer.deploy(MonetarySupervisor, StabilityBoardProxy.address, TokenAEur.address, AugmintReserves.address, InterestEarnedAccount.address, MONETARY_SUPERVISOR_LOCK_DIFF_LIMIT, MONETARY_SUPERVISOR_LOAN_DIFF_LIMIT, MONETARY_SUPERVISOR_ALLOWED_DIFF_AMOUNT); + + // ### Exchange ### + await deployer.deploy(Exchange, StabilityBoardProxy.address, TokenAEur.address, Rates.address); + + // ### LoanManager ### + await deployer.deploy(LoanManager, StabilityBoardProxy.address, TokenAEur.address, MonetarySupervisor.address, Rates.address); + + // ### Locker ### + await deployer.deploy(Locker, StabilityBoardProxy.address, TokenAEur.address, MonetarySupervisor.address); + + // ### PreTokenProxy ### + await deployer.deploy(PreTokenProxy); + + // ### PreToken ### + await deployer.deploy(PreToken, StabilityBoardProxy.address); // temporary for preToken, init script will change it to preTokenProxy + + // ### Migrations ### + await deployer.deploy(Migrations); + + console.log("Done with migration step " + MIGRATION_STEP_NUMBER); + await Migrations.at(Migrations.address).setCompleted(MIGRATION_STEP_NUMBER); + }); +}; \ No newline at end of file diff --git a/mainnet_migrations/31_deploy_all_scripts.js b/mainnet_migrations/31_deploy_all_scripts.js new file mode 100644 index 00000000..ccbbfea6 --- /dev/null +++ b/mainnet_migrations/31_deploy_all_scripts.js @@ -0,0 +1,32 @@ +const Migrations = artifacts.require("./Migrations.sol"); +const Main0014_initNewContracts = artifacts.require("./Main0014_initNewContracts.sol"); +const Main0015_migrateLegacyContracts = artifacts.require("./Main0015_migrateLegacyContracts.sol"); +const Main0016_setupLegacy = artifacts.require("./Main0016_setupLegacy.sol"); +const Main0017_postDeploySetup = artifacts.require("./Main0017_postDeploySetup.sol"); +const Main0018_preTokenSigners = artifacts.require("./Main0018_preTokenSigners.sol"); + +const MIGRATION_STEP_NUMBER = 31; +const MIGRATIONS_ADDRESS = "0xf01C976E9189BC9ba68Eda0f1Dc9d94b243C78dC"; + +module.exports = function(deployer) { + deployer.then(async () => { + + // script for init new contracts + await deployer.deploy(Main0014_initNewContracts); + + // script for migrate legacy contracts (to be run via old proxy!) + await deployer.deploy(Main0015_migrateLegacyContracts); + + // script for setup legacy contract dependencies + await deployer.deploy(Main0016_setupLegacy); + + // script for post deploy setup + await deployer.deploy(Main0017_postDeploySetup); + + // script for pretoken signers + await deployer.deploy(Main0018_preTokenSigners); + + console.log("Done with migration step " + MIGRATION_STEP_NUMBER); + await Migrations.at(MIGRATIONS_ADDRESS).setCompleted(MIGRATION_STEP_NUMBER); + }); +}; diff --git a/mainnet_migrations/32_deploy_scripts.js b/mainnet_migrations/32_deploy_scripts.js new file mode 100644 index 00000000..59d8c9f4 --- /dev/null +++ b/mainnet_migrations/32_deploy_scripts.js @@ -0,0 +1,20 @@ +const Migrations = artifacts.require("./Migrations.sol"); +const Main0019_noTransferFee = artifacts.require("./Main0019_noTransferFee.sol"); +const Main0020_removeSigner = artifacts.require("./Main0020_removeSigner.sol"); + +const MIGRATION_STEP_NUMBER = 32; +const MIGRATIONS_ADDRESS = "0xf01C976E9189BC9ba68Eda0f1Dc9d94b243C78dC"; + +module.exports = function(deployer) { + deployer.then(async () => { + + // script to eliminate transfer fees + await deployer.deploy(Main0019_noTransferFee); + + // script to remove deployer account from signers + await deployer.deploy(Main0020_removeSigner); + + console.log("Done with migration step " + MIGRATION_STEP_NUMBER); + await Migrations.at(MIGRATIONS_ADDRESS).setCompleted(MIGRATION_STEP_NUMBER); + }); +}; diff --git a/migrations/1000_initialSetup.js b/migrations/1000_initialSetup.js index 2bd2907d..5bfc492e 100644 --- a/migrations/1000_initialSetup.js +++ b/migrations/1000_initialSetup.js @@ -8,6 +8,7 @@ const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); const LoanManager = artifacts.require("./LoanManager.sol"); const Locker = artifacts.require("./Locker.sol"); const Exchange = artifacts.require("./Exchange.sol"); +const SafeMathTester = artifacts.require("./test/SafeMathTester.sol"); const localTest_initialSetup = artifacts.require("./SB_scripts/localTest/localTest_initialSetup.sol"); @@ -23,7 +24,8 @@ module.exports = function(deployer) { MonetarySupervisor.address, LoanManager.address, Locker.address, - Exchange.address + Exchange.address, + SafeMathTester.address ) .then(async initialSetupScript => { // StabilityBoard permissions diff --git a/migrations/14_deploy_SafeMathTester.js b/migrations/14_deploy_SafeMathTester.js new file mode 100644 index 00000000..3be99e78 --- /dev/null +++ b/migrations/14_deploy_SafeMathTester.js @@ -0,0 +1,5 @@ +const SafeMathTester = artifacts.require("./test/SafeMathTester.sol"); + +module.exports = function(deployer, network, accounts) { + deployer.deploy(SafeMathTester, accounts[0]); +}; diff --git a/package.json b/package.json index df42c116..5c97ab89 100644 --- a/package.json +++ b/package.json @@ -21,14 +21,14 @@ "babel-register": "6.26.0", "bignumber.js": "5.0.0", "coveralls": "3.0.1", - "dotenv": "6.0.0", - "ganache-cli": "6.1.6", + "dotenv": "6.2.0", + "ganache-cli": "6.1.8", "moment": "2.22.2", "random-seed": "0.3.0", - "solidity-coverage": "0.5.5", - "stringifier": "1.3.0", - "truffle": "4.1.13", - "truffle-hdwallet-provider": "0.0.5", + "solidity-coverage": "0.5.11", + "stringifier": "2.0.0", + "truffle": "4.1.14", + "truffle-hdwallet-provider": "0.0.6", "web3v1": "npm:web3@1.0.0-beta.34" }, "greenkeeper": { diff --git a/rinkeby_migrations/10_deploy_Locker.js b/rinkeby_migrations/10_deploy_Locker.js deleted file mode 100644 index 5fb2181c..00000000 --- a/rinkeby_migrations/10_deploy_Locker.js +++ /dev/null @@ -1,31 +0,0 @@ -const Locker = artifacts.require("./Locker.sol"); -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); -const SafeMath = artifacts.require("./SafeMath.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); - -module.exports = function(deployer) { - deployer.link(SafeMath, Locker); - deployer.deploy(Locker, TokenAEur.address, MonetarySupervisor.address); - deployer.then(async () => { - const feeAccount = FeeAccount.at(FeeAccount.address); - const monetarySupervisor = MonetarySupervisor.at(MonetarySupervisor.address); - const locker = Locker.at(Locker.address); - await Promise.all([ - feeAccount.grantPermission(Locker.address, "NoFeeTransferContracts"), - monetarySupervisor.grantPermission(Locker.address, "LockerContracts"), - - // (perTermInterest, durationInSecs, minimumLockAmount, isActive) - locker.addLockProduct(80001, 31536000, 1000, true), // 365 days, 8% p.a. - locker.addLockProduct(33929, 15552000, 1000, true), // 180 days, 7% p.a. - - locker.addLockProduct(14472, 7776000, 1000, true), // 90 days 6% p.a. - locker.addLockProduct(4019, 2592000, 1000, true), // 30 days, 5% p.a. - locker.addLockProduct(1506, 1209600, 1000, true), // 14 days, 4% p.a. - locker.addLockProduct(568, 604800, 1000, true), // 7 days, 3% p.a. - - locker.addLockProduct(3, 3600, 2000, true), // 60 minutes for testing, ~2.66% p.a. - locker.addLockProduct(1, 60, 3000, true) // 1 minute for testing, ~69.15% p.a. - ]); - }); -}; diff --git a/rinkeby_migrations/11_deploy_Exchange.js b/rinkeby_migrations/11_deploy_Exchange.js deleted file mode 100644 index 0eb43d8b..00000000 --- a/rinkeby_migrations/11_deploy_Exchange.js +++ /dev/null @@ -1,13 +0,0 @@ -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const SafeMath = artifacts.require("./SafeMath.sol"); -const Exchange = artifacts.require("./Exchange.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); - -module.exports = function(deployer) { - deployer.link(SafeMath, Exchange); - deployer.deploy(Exchange, TokenAEur.address); - deployer.then(async () => { - const feeAccount = FeeAccount.at(FeeAccount.address); - await feeAccount.grantPermission(Exchange.address, "NoFeeTransferContracts"); - }); -}; diff --git a/rinkeby_migrations/12_add_legacyTokens.js b/rinkeby_migrations/12_add_legacyTokens.js deleted file mode 100644 index 8f05cad3..00000000 --- a/rinkeby_migrations/12_add_legacyTokens.js +++ /dev/null @@ -1,18 +0,0 @@ -const FeeAccount = artifacts.require("./FeeAccount.sol"); -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); - -module.exports = async function(deployer, network) { - deployer.then(async () => { - const monetarySupervisor = MonetarySupervisor.at(MonetarySupervisor.address); - const feeAccount = FeeAccount.at(FeeAccount.address); - - const oldToken1 = TokenAEur.at("0xa35d9de06895a3a2e7ecae26654b88fe71c179ea"); - const oldToken2 = TokenAEur.at("0x03fe291f8a30e54cd05459f368d554b40784ca78"); - await Promise.all([ - feeAccount.grantPermission(monetarySupervisor.address, "NoFeeTransferContracts"), - monetarySupervisor.setAcceptedLegacyAugmintToken(oldToken1.address, true), - monetarySupervisor.setAcceptedLegacyAugmintToken(oldToken2.address, true) - ]); - }); -}; diff --git a/rinkeby_migrations/13_authorise_MonetaryBoard.js b/rinkeby_migrations/13_authorise_MonetaryBoard.js deleted file mode 100644 index 18d1cd91..00000000 --- a/rinkeby_migrations/13_authorise_MonetaryBoard.js +++ /dev/null @@ -1,35 +0,0 @@ -/* Authorise all testers on Rinkeby to use MoneteryBoard functions - For non Rinkeby deploys authorise only accounts[0] - NB: this is only for Rinkeby and local testnets. Authorisation process for live deploys TBD. -*/ -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); -const LoanManager = artifacts.require("./LoanManager.sol"); -const Locker = artifacts.require("./Locker.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); - -module.exports = function(deployer, network, accounts) { - deployer.then(async () => { - const feeAccount = FeeAccount.at(FeeAccount.address); - // on Rinkeby testnet - const monetaryBoardAccounts = [ - accounts[0], - "0x14A9dc091053fCbA9474c5734078238ff9904364" /* Krosza */, - "0xe71E9636e31B838aF0A3c38B3f3449cdC2b7aa87" /* Phraktle */ - ]; - - const tokenAEur = TokenAEur.at(TokenAEur.address); - const monetarySupervisor = MonetarySupervisor.at(MonetarySupervisor.address); - const loanManager = LoanManager.at(LoanManager.address); - const locker = Locker.at(Locker.address); - - const grantTxs = monetaryBoardAccounts.map(acc => [ - feeAccount.grantPermission(acc, "MonetaryBoard"), - locker.grantPermission(acc, "MonetaryBoard"), - tokenAEur.grantPermission(acc, "MonetaryBoard"), - loanManager.grantPermission(acc, "MonetaryBoard"), - monetarySupervisor.grantPermission(acc, "MonetaryBoard") - ]); - await Promise.all(grantTxs); - }); -}; diff --git a/rinkeby_migrations/14_deploy_new_MonetarySupervisor.js b/rinkeby_migrations/14_deploy_new_MonetarySupervisor.js deleted file mode 100644 index 78bb9dea..00000000 --- a/rinkeby_migrations/14_deploy_new_MonetarySupervisor.js +++ /dev/null @@ -1,51 +0,0 @@ -/* This step is a new deploy of MonetarySupervisor contract without putting it live yet -It contains a bug fix in maxLockAmount calculation -NB: This migration step is only deploying the new contract and authorising existing contracts. - It's **NOT** switching it live, i.e.: - - not setting new MS in Locker and LoanManager contracts - - not migrating totalLoan and totalLockedAmount from old MS - - not revoking permissions from old MS contract - These steps will be executed after this sucessful deployment and when new artifacts are avialable for FE. -*/ - -const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const InterestEarnedAccount = artifacts.require("./InterestEarnedAccount.sol"); -const AugmintReserves = artifacts.require("./AugmintReserves.sol"); - -module.exports = function(deployer) { - let tokenAEurAddress; - let augmintReservesAddress; - let interestEarnedAccountAddress; - - if (web3.version.network == 4) { - // Truffle artifacts are in unknown state when truffle migrate starts from this step on rinkeby. - // Therefore we can't use addresses from there. - // But this script will be run only ONCE on rinkeby so it's fine to hardcode addresses - tokenAEurAddress = "0x135893f1a6b3037bb45182841f18f69327366992"; - augmintReservesAddress = "0xc70b65e40f877cdc6d8d2ebfd44d63efbeb7fc6d"; - interestEarnedAccountAddress = "0x3a414d7636defb9d3dfb7342984fe3f7b5125df6"; - } else { - // Not rinkeby, we assume it's a private network: scripts in this folder are not intended to run on other networks! - // On private networks we migrate from scratch so contracts just has been deployed and truffle artifacts are available with correct deployment addresses. - tokenAEurAddress = TokenAEur.address; - augmintReservesAddress = AugmintReserves.address; - interestEarnedAccountAddress = InterestEarnedAccount.address; - } - - deployer.deploy( - MonetarySupervisor, - tokenAEurAddress, - augmintReservesAddress, - interestEarnedAccountAddress, - - /* Parameters Used to ensure totalLoanAmount or totalLockedAmount difference is withing limit and system also works - when any of those 0 or low. */ - 200000 /* ltdLockDifferenceLimit = 20% allow lock if Loan To Deposit ratio stays within 1 - this param - stored as parts per million */, - 200000 /* ltdLoanDifferenceLimit = 20% allow loan if Loan To Deposit ratio stays within 1 + this param - stored as parts per million */, - 10000 /* allowedLtdDifferenceAmount = 100 A-EUR - if totalLoan and totalLock difference is less than that - then allow loan or lock even if ltdDifference limit would go off with it */ - ); -}; diff --git a/rinkeby_migrations/15_set_new_MonetarySupervisor_live.js b/rinkeby_migrations/15_set_new_MonetarySupervisor_live.js deleted file mode 100644 index 92f757a9..00000000 --- a/rinkeby_migrations/15_set_new_MonetarySupervisor_live.js +++ /dev/null @@ -1,98 +0,0 @@ -/* set new MonetarySupervisor deployed in prev step. live and adjust new LTD params - It's switching it live, i.e.: - - granting permissions for new MS in deployed contracts and revoking from old MS contract - - setting new MS in Locker and LoanManager contracts - - migrating totalLoan and totalLockedAmount from old MS -*/ -const Migrations = artifacts.require("./Migrations.sol"); -const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const InterestEarnedAccount = artifacts.require("./InterestEarnedAccount.sol"); -const AugmintReserves = artifacts.require("./AugmintReserves.sol"); -const LoanManager = artifacts.require("./LoanManager.sol"); -const Locker = artifacts.require("./Locker.sol"); -const FeeAccount = artifacts.require("./FeeAccount"); - -module.exports = function(deployer, network) { - deployer.then(async () => { - // NB: web3.version.network throws error with truffle migrate --dry-run... - if (network === "rinkeby" || network === "rinkeby-fork") { - // Truffle artifacts are in unknown state when truffle migrate starts from this step on rinkeby. - // Therefore we can't use addresses from there. - // But this script will be run only ONCE on rinkeby so it's fine to hardcode addresses - const ratesAddress = "0xcA8100FCcb479516A5b30f8Bc5dAeA09Fb7a7473"; - const tokenAEur = TokenAEur.at("0x135893f1a6b3037bb45182841f18f69327366992"); - const augmintReserves = AugmintReserves.at("0xc70b65e40f877cdc6d8d2ebfd44d63efbeb7fc6d"); - const interestEarnedAccount = InterestEarnedAccount.at("0x3a414d7636defb9d3dfb7342984fe3f7b5125df6"); - const locker = Locker.at("0xf98AE1fb568B267A7632BF54579A153C892E2ec2"); - const loanManager = LoanManager.at("0xBdb02f82d7Ad574f9F549895caf41E23a8981b07"); - const feeAccount = FeeAccount.at("0xc26667132b0B798ab87864f7c29c0819c887aADB"); - const oldMonetarySupervisor = MonetarySupervisor.at("0x2E8b07A973f8E136Aa39922DFF21AD187a6E8E7d"); - - const oldToken1 = TokenAEur.at("0x95aa79d7410eb60f49bfd570b445836d402bd7b1"); - const oldToken2 = TokenAEur.at("0xa35d9de06895a3a2e7ecae26654b88fe71c179ea"); - - // New MS which has been deployed in prev. step but not live yet - const newMonetarySupervisor = MonetarySupervisor.at("0xa00a5d1882c3f690e3d0d975ebe378120b70ae87"); - - // 1. grant permissions for new MS - await Promise.all([ - interestEarnedAccount.grantPermission(newMonetarySupervisor.address, "MonetarySupervisorContract"), - tokenAEur.grantPermission(newMonetarySupervisor.address, "MonetarySupervisorContract"), - augmintReserves.grantPermission(newMonetarySupervisor.address, "MonetarySupervisorContract"), - feeAccount.grantPermission(newMonetarySupervisor.address, "NoFeeTransferContracts"), - - newMonetarySupervisor.grantPermission(locker.address, "LockerContracts"), - newMonetarySupervisor.grantPermission(loanManager.address, "LoanManagerContracts"), - - newMonetarySupervisor.setAcceptedLegacyAugmintToken(oldToken1.address, true), - newMonetarySupervisor.setAcceptedLegacyAugmintToken(oldToken2.address, true), - - // to allow token conversion w/o fee - // NB: NoFeeTransferContracts was set on the token contract in legacy token version. - // For upcoming versions this permission needs to be set on feeAccount - oldToken1.grantPermission(newMonetarySupervisor.address, "NoFeeTransferContracts"), - oldToken2.grantPermission(newMonetarySupervisor.address, "NoFeeTransferContracts") - ]); - - // 2. switch new MS to live: - await Promise.all([ - locker.setMonetarySupervisor(newMonetarySupervisor.address), - loanManager.setSystemContracts(ratesAddress, newMonetarySupervisor.address) - ]); - - // 3. migrate totals from previous MS (using MS.adjustKPIs) - - const [oldTotalLoan, oldTotalLock] = await Promise.all([ - oldMonetarySupervisor.totalLoanAmount(), - oldMonetarySupervisor.totalLockedAmount() - ]); - console.log( - "Migrating KPIs to new MonetarySupervisor contract. totalLoanAmount:", - oldTotalLoan.toString(), - "totalLockedAmount", - oldTotalLock.toString() - ); - await newMonetarySupervisor.adjustKPIs(oldTotalLoan, oldTotalLock); - - // 4. Revoke permission from old MS - - await Promise.all([ - feeAccount.revokePermission(oldMonetarySupervisor.address, "NoFeeTransferContracts"), - interestEarnedAccount.revokePermission(oldMonetarySupervisor.address, "MonetarySupervisorContract"), - tokenAEur.revokePermission(oldMonetarySupervisor.address, "MonetarySupervisorContract"), - augmintReserves.revokePermission(oldMonetarySupervisor.address, "MonetarySupervisorContract"), - - oldMonetarySupervisor.revokePermission(locker.address, "LockerContracts"), - oldMonetarySupervisor.revokePermission(loanManager.address, "LoanManagerContracts") - ]); - - // 5. update truffle Migrations step manually - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(14); - } else { - // Not rinkeby, we assume it's a private network: scripts in this folder are not intended to run on other networks! - // we don't need to do anything as previous steps deployed latest version of MonetarySupervisor - console.log("On ", network, "not Rinkeby. Not executing anything step 15."); - } - }); -}; diff --git a/rinkeby_migrations/16_deploy_new_Exchange.js b/rinkeby_migrations/16_deploy_new_Exchange.js deleted file mode 100644 index 6b156f2e..00000000 --- a/rinkeby_migrations/16_deploy_new_Exchange.js +++ /dev/null @@ -1,49 +0,0 @@ -/* Deploy new Exchange with publish rate orders */ -const Migrations = artifacts.require("./Migrations.sol"); -const Exchange = artifacts.require("./Exchange.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); - -module.exports = function(deployer, network, accounts) { - let tokenAEurAddress; - let feeAccountAddress; - let ratesAddress; - let monetaryBoardAccounts; - - if (network === "rinkeby" || network === "rinkeby-fork") { - // Truffle artifacts are in unknown state when truffle migrate starts from this step on rinkeby. - // Therefore we can't use addresses from there. - // But this script will be run only ONCE on rinkeby so it's fine to hardcode addresses - tokenAEurAddress = "0x135893f1a6b3037bb45182841f18f69327366992"; - feeAccountAddress = "0xc70b65e40f877cdc6d8d2ebfd44d63efbeb7fc6d"; - ratesAddress = "0xcA8100FCcb479516A5b30f8Bc5dAeA09Fb7a7473"; - - monetaryBoardAccounts = [ - accounts[0], - "0x14A9dc091053fCbA9474c5734078238ff9904364" /* Krosza */, - "0xe71E9636e31B838aF0A3c38B3f3449cdC2b7aa87" /* Phraktle */ - ]; - - const feeAccount = FeeAccount.at(feeAccountAddress); - - deployer.deploy(Exchange, tokenAEurAddress, ratesAddress); - deployer.then(async () => { - console.log("Deployed Exchange at ", Exchange.address); - const newExchange = Exchange.at(Exchange.address); - const grantMonetaryBoardTxs = monetaryBoardAccounts.map(acc => - newExchange.grantPermission(acc, "MonetaryBoard") - ); - - await Promise.all([ - grantMonetaryBoardTxs, - feeAccount.grantPermission(Exchange.address, "NoFeeTransferContracts") - ]); - - // update truffle Migrations step manually - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(16); - }); - } else { - // Not rinkeby, we assume it's a private network: scripts in this folder are not intended to run on other networks! - // we don't need to do anything as previous steps deployed latest version of Exchange - console.log("On ", network, "not Rinkeby. Not executing anything in step 16."); - } -}; diff --git a/rinkeby_migrations/17_new_TokenAEur.js b/rinkeby_migrations/17_new_TokenAEur.js deleted file mode 100644 index db8aa375..00000000 --- a/rinkeby_migrations/17_new_TokenAEur.js +++ /dev/null @@ -1,151 +0,0 @@ -/* deploy new TokenAEur version and all dependent contracts: - - MonetarySupervisor (and switch over to it ) - - Locker - - LoanManager - - Exchange -*/ -const Migrations = artifacts.require("./Migrations.sol"); -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); -const Exchange = artifacts.require("./Exchange.sol"); -const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); -const InterestEarnedAccount = artifacts.require("./InterestEarnedAccount.sol"); -const AugmintReserves = artifacts.require("./AugmintReserves.sol"); -const Locker = artifacts.require("./Locker.sol"); -const LoanManager = artifacts.require("./LoanManager.sol"); - -module.exports = function(deployer, network, accounts) { - const ratesAddress = "0xcA8100FCcb479516A5b30f8Bc5dAeA09Fb7a7473"; - const feeAccount = FeeAccount.at("0xc26667132b0B798ab87864f7c29c0819c887aADB"); - const augmintReserves = AugmintReserves.at("0xc70b65e40f877cdC6d8D2ebFd44d63EfBeb7fc6D"); - const interestEarnedAccount = InterestEarnedAccount.at("0x3a414d7636defb9d3dfb7342984fe3f7b5125df6"); - - const oldToken1 = TokenAEur.at("0x95aa79d7410eb60f49bfd570b445836d402bd7b1"); - const oldToken2 = TokenAEur.at("0xa35d9de06895a3a2e7ecae26654b88fe71c179ea"); - const oldToken3 = TokenAEur.at("0x135893F1A6B3037BB45182841f18F69327366992"); - - const oldLocker1 = Locker.at("0xf98AE1fb568B267A7632BF54579A153C892E2ec2"); - const oldLoanManager1 = LoanManager.at("0xBdb02f82d7Ad574f9F549895caf41E23a8981b07"); - - deployer.deploy(TokenAEur, feeAccount.address); - - deployer.then(async () => { - /************************************************************* - * Deploy new TokenAEur - **************************************************************/ - - const newTokenAEur = TokenAEur.at(TokenAEur.address); - - /************************************************************* - * Deploy new Exchange - **************************************************************/ - await deployer.deploy(Exchange, newTokenAEur.address, ratesAddress); - const newExchange = Exchange.at(Exchange.address); - - await feeAccount.grantPermission(newExchange.address, "NoFeeTransferContracts"); - - /************************************************************* - * Deploy new MonetarySupervisor - **************************************************************/ - await deployer.deploy( - MonetarySupervisor, - newTokenAEur.address, - augmintReserves.address, - interestEarnedAccount.address, - 200000 /* ltdLockDifferenceLimit */, - 200000 /* ltdLoanDifferenceLimit*/, - 50000 /* allowedLtdDifferenceAmount */ - ); - - const newMonetarySupervisor = MonetarySupervisor.at(MonetarySupervisor.address); - - /************************************************************* - * Deploy new Locker, setup lock products and permissions - **************************************************************/ - await deployer.deploy(Locker, TokenAEur.address, MonetarySupervisor.address); - const newLocker = Locker.at(Locker.address); - console.log(" Adding test lockProducts."); - await Promise.all([ - feeAccount.grantPermission(newLocker.address, "NoFeeTransferContracts"), - newMonetarySupervisor.grantPermission(newLocker.address, "LockerContracts"), - - // (perTermInterest, durationInSecs, minimumLockAmount, isActive) - newLocker.addLockProduct(14472, 7776000, 1000, false), // 90 days 6% p.a. - newLocker.addLockProduct(4019, 2592000, 1000, true), // 30 days, 5% p.a. - newLocker.addLockProduct(1506, 1209600, 1000, true), // 14 days, 4% p.a. - newLocker.addLockProduct(568, 604800, 1000, true), // 7 days, 3% p.a. - - newLocker.addLockProduct(3, 3600, 2000, true), // 60 minutes for testing, ~2.66% p.a. - newLocker.addLockProduct(1, 60, 3000, true) // 1 minute for testing, ~69.15% p.a. - ]); - - /************************************************************* - * Deploy new LoanManager, setup loan products and permissions - **************************************************************/ - await deployer.deploy(LoanManager, newTokenAEur.address, newMonetarySupervisor.address, ratesAddress); - const newLoanManager = LoanManager.at(LoanManager.address); - console.log(" Adding test loanProducts."); - await Promise.all([ - feeAccount.grantPermission(newLoanManager.address, "NoFeeTransferContracts"), - newMonetarySupervisor.grantPermission(newLoanManager.address, "LoanManagerContracts"), - - // term (in sec), discountRate, loanCoverageRatio, minDisbursedAmount (w/ 4 decimals), defaultingFeePt, isActive - newLoanManager.addLoanProduct(7776000, 971661, 600000, 1000, 50000, false), // 90d, 12%. p.a. - newLoanManager.addLoanProduct(2592000, 990641, 600000, 1000, 50000, true), // 30d, 12% p.a. - newLoanManager.addLoanProduct(1209600, 996337, 600000, 1000, 50000, true), // 14d, 10% p.a. - newLoanManager.addLoanProduct(604800, 998170, 600000, 1000, 50000, true), // 7d, 10% p.a. - - newLoanManager.addLoanProduct(3600, 999989, 980000, 2000, 50000, true), // due in 1hr for testing repayments ? p.a. - newLoanManager.addLoanProduct(1, 999999, 990000, 3000, 50000, true) // defaults in 1 secs for testing ? p.a. - ]); - - /************************************************************* - * Grant MonetaryBoard permissions to accounts on new contracts - **************************************************************/ - console.log(" Granting MonetaryBoard permissions on new contracts "); - const monetaryBoardAccounts = [ - accounts[0], - "0x14A9dc091053fCbA9474c5734078238ff9904364" /* Krosza */, - "0xe71E9636e31B838aF0A3c38B3f3449cdC2b7aa87" /* Phraktle */ - ]; - const grantMonetaryBoardTxs = monetaryBoardAccounts.map(acc => [ - newExchange.grantPermission(acc, "MonetaryBoard"), - newLocker.grantPermission(acc, "MonetaryBoard"), - newTokenAEur.grantPermission(acc, "MonetaryBoard"), - newLoanManager.grantPermission(acc, "MonetaryBoard"), - newMonetarySupervisor.grantPermission(acc, "MonetaryBoard") - ]); - Promise.all(grantMonetaryBoardTxs); - - /************************************************************* - * Grant permissions to new MonetarySupervisor - **************************************************************/ - console.log(" granting permissions for new MS"); - await Promise.all([ - interestEarnedAccount.grantPermission(newMonetarySupervisor.address, "MonetarySupervisorContract"), - newTokenAEur.grantPermission(newMonetarySupervisor.address, "MonetarySupervisorContract"), - augmintReserves.grantPermission(newMonetarySupervisor.address, "MonetarySupervisorContract"), - feeAccount.grantPermission(newMonetarySupervisor.address, "NoFeeTransferContracts"), - - newMonetarySupervisor.grantPermission(newLocker.address, "LockerContracts"), - newMonetarySupervisor.grantPermission(newLoanManager.address, "LoanManagerContracts"), - newMonetarySupervisor.grantPermission(oldLocker1.address, "LockerContracts"), - newMonetarySupervisor.grantPermission(oldLoanManager1.address, "LoanManagerContracts"), - - newMonetarySupervisor.setAcceptedLegacyAugmintToken(oldToken1.address, true), - newMonetarySupervisor.setAcceptedLegacyAugmintToken(oldToken2.address, true), - newMonetarySupervisor.setAcceptedLegacyAugmintToken(oldToken3.address, true), - - // to allow token conversion w/o fee - // NB: NoFeeTransferContracts was set on the token contract in legacy token version. - // For newer versions this permission needs to be set on feeAccount - oldToken1.grantPermission(newMonetarySupervisor.address, "NoFeeTransferContracts"), - oldToken2.grantPermission(newMonetarySupervisor.address, "NoFeeTransferContracts"), - feeAccount.grantPermission(oldToken3.address, "NoFeeTransferContracts") - ]); - - // NB: don't forget to top up earned interest account with new tokens - console.log(" Done with all migration steps. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(17); - }); -}; diff --git a/rinkeby_migrations/18_set_new_MonetarySupervisor_live.js b/rinkeby_migrations/18_set_new_MonetarySupervisor_live.js deleted file mode 100644 index 709ef6c3..00000000 --- a/rinkeby_migrations/18_set_new_MonetarySupervisor_live.js +++ /dev/null @@ -1,58 +0,0 @@ -/* switch over to new MonetSupervisor version in legacy contracts */ -const Migrations = artifacts.require("./Migrations.sol"); -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); -const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); -const InterestEarnedAccount = artifacts.require("./InterestEarnedAccount.sol"); -const AugmintReserves = artifacts.require("./AugmintReserves.sol"); -const Locker = artifacts.require("./Locker.sol"); -const LoanManager = artifacts.require("./LoanManager.sol"); - -module.exports = function(deployer, network, accounts) { - const ratesAddress = "0xcA8100FCcb479516A5b30f8Bc5dAeA09Fb7a7473"; - const feeAccount = FeeAccount.at("0xc26667132b0B798ab87864f7c29c0819c887aADB"); - const augmintReserves = AugmintReserves.at("0xc70b65e40f877cdC6d8D2ebFd44d63EfBeb7fc6D"); - const interestEarnedAccount = InterestEarnedAccount.at("0x3a414d7636defb9d3dfb7342984fe3f7b5125df6"); - const oldMonetarySupervisor = MonetarySupervisor.at("0xa00a5d1882C3F690E3d0D975ebE378120b70ae87"); - const newMonetarySupervisor = MonetarySupervisor.at("0xC19a45F5CbfA93Be512ef07177feB3f7b3ae4518"); - - const oldToken3 = TokenAEur.at("0x135893F1A6B3037BB45182841f18F69327366992"); - - const oldLocker1 = Locker.at("0xf98AE1fb568B267A7632BF54579A153C892E2ec2"); - const oldLoanManager1 = LoanManager.at("0xBdb02f82d7Ad574f9F549895caf41E23a8981b07"); - - deployer.then(async () => { - console.log(" switching new MS to live"); - await Promise.all([ - oldLocker1.setMonetarySupervisor(newMonetarySupervisor.address), - oldLoanManager1.setSystemContracts(ratesAddress, newMonetarySupervisor.address) - ]); - - // 3. migrate totals from previous MS (using MS.adjustKPIs) - const [oldTotalLoan, oldTotalLock] = await Promise.all([ - oldMonetarySupervisor.totalLoanAmount(), - oldMonetarySupervisor.totalLockedAmount() - ]); - console.log( - "Migrating KPIs to new MonetarySupervisor contract. totalLoanAmount:", - oldTotalLoan.toString(), - "totalLockedAmount", - oldTotalLock.toString() - ); - await newMonetarySupervisor.adjustKPIs(oldTotalLoan, oldTotalLock); - - console.log("Revoking permission from old MS"); - await Promise.all([ - feeAccount.revokePermission(oldMonetarySupervisor.address, "NoFeeTransferContracts"), - interestEarnedAccount.revokePermission(oldMonetarySupervisor.address, "MonetarySupervisorContract"), - oldToken3.revokePermission(oldMonetarySupervisor.address, "MonetarySupervisorContract"), - augmintReserves.revokePermission(oldMonetarySupervisor.address, "MonetarySupervisorContract"), - - oldMonetarySupervisor.revokePermission(oldLocker1.address, "LockerContracts"), - oldMonetarySupervisor.revokePermission(oldLoanManager1.address, "LoanManagerContracts") - ]); - - console.log(" Done with all migration steps. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(18); - }); -}; diff --git a/rinkeby_migrations/19_redeploy.js b/rinkeby_migrations/19_redeploy.js deleted file mode 100644 index ef50aa70..00000000 --- a/rinkeby_migrations/19_redeploy.js +++ /dev/null @@ -1,68 +0,0 @@ -/* full redeploy of latest contracts without setting up anything */ -const Migrations = artifacts.require("./Migrations.sol"); -const StabilityBoardProxy = artifacts.require("./StabilityBoardProxy.sol"); -const PreTokenProxy = artifacts.require("./PreTokenProxy.sol"); -const PreToken = artifacts.require("./PreToken.sol"); -const Rates = artifacts.require("./Rates.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); -const AugmintReserves = artifacts.require("./AugmintReserves.sol"); -const InterestEarnedAccount = artifacts.require("./InterestEarnedAccount.sol"); -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); -const LoanManager = artifacts.require("./LoanManager.sol"); -const Locker = artifacts.require("./Locker.sol"); -const Exchange = artifacts.require("./Exchange.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - const [stabilityBoardProxy, preTokenProxy] = await Promise.all([ - deployer.deploy(StabilityBoardProxy), - deployer.deploy(PreTokenProxy) - ]); - - const [preToken, rates, feeAccount, augmintReserves, interestEarnedAccount] = await Promise.all([ - deployer.deploy(PreToken, stabilityBoardProxy.address), // temporary for preToken, init script will change it to preTokenProxy - deployer.deploy(Rates, stabilityBoardProxy.address), - deployer.deploy( - FeeAccount, - stabilityBoardProxy.address, - 2000, // transferFeePt in parts per million = 0.2% - 2, // min: 0.02 A-EUR - 500 // max fee: 5 A-EUR) - ), - deployer.deploy(AugmintReserves, stabilityBoardProxy.address), - deployer.deploy(InterestEarnedAccount, stabilityBoardProxy.address) - ]); - - const tokenAEur = await deployer.deploy(TokenAEur, stabilityBoardProxy.address, feeAccount.address); - - const monetarySupervisor = await deployer.deploy( - MonetarySupervisor, - stabilityBoardProxy.address, - tokenAEur.address, - augmintReserves.address, - interestEarnedAccount.address, - 200000 /* ltdLockDifferenceLimit */, - 200000 /* ltdLoanDifferenceLimit*/, - 50000 /* allowedLtdDifferenceAmount */ - ); - - /*const [loanManager, locker, exchange] = */ - await Promise.all([ - deployer.deploy( - LoanManager, - stabilityBoardProxy.address, - tokenAEur.address, - monetarySupervisor.address, - rates.address - ), - deployer.deploy(Locker, stabilityBoardProxy.address, TokenAEur.address, MonetarySupervisor.address), - - deployer.deploy(Exchange, stabilityBoardProxy.address, tokenAEur.address, rates.address) - ]); - - // NB: don't forget to top up earned interest account with new tokens - console.log(" Done with migration step 19. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(19); - }); -}; diff --git a/rinkeby_migrations/1_deploy_all.js b/rinkeby_migrations/1_deploy_all.js new file mode 100644 index 00000000..1fbf74ad --- /dev/null +++ b/rinkeby_migrations/1_deploy_all.js @@ -0,0 +1,70 @@ +const AugmintReserves = artifacts.require("./AugmintReserves.sol"); +const Exchange = artifacts.require("./Exchange.sol"); +const FeeAccount = artifacts.require("./FeeAccount.sol"); +const InterestEarnedAccount = artifacts.require("./InterestEarnedAccount.sol"); +const LoanManager = artifacts.require("./LoanManager.sol"); +const Locker = artifacts.require("./Locker.sol"); +const Migrations = artifacts.require("./Migrations.sol"); +const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); +const Rates = artifacts.require("./Rates.sol"); +const TokenAEur = artifacts.require("./TokenAEur.sol"); +const StabilityBoardProxy = artifacts.require("./StabilityBoardProxy.sol"); +const PreTokenProxy = artifacts.require("./PreTokenProxy.sol"); +const PreToken = artifacts.require("./PreToken.sol"); + +const MIGRATION_STEP_NUMBER = 1; + +const FEE_ACCOUNT_TRANSFER_FEE_PT = 2000; +const FEE_ACCOUNT_TRANSFER_FEE_MIN = 2; +const FEE_ACCOUNT_TRANSFER_FEE_MAX = 500; + +const MONETARY_SUPERVISOR_LOCK_DIFF_LIMIT = 200000; +const MONETARY_SUPERVISOR_LOAN_DIFF_LIMIT = 200000; +const MONETARY_SUPERVISOR_ALLOWED_DIFF_AMOUNT = 1000000; + +module.exports = function(deployer) { + deployer.then(async () => { + + // ### StabilityBoardProxy ### + await deployer.deploy(StabilityBoardProxy); + + // ### FeeAccount ### + await deployer.deploy(FeeAccount, StabilityBoardProxy.address, FEE_ACCOUNT_TRANSFER_FEE_PT, FEE_ACCOUNT_TRANSFER_FEE_MIN, FEE_ACCOUNT_TRANSFER_FEE_MAX); + + // ### TokenAEur ### + await deployer.deploy(TokenAEur, StabilityBoardProxy.address, FeeAccount.address); + + // ### Rates ### + await deployer.deploy(Rates, StabilityBoardProxy.address); + + // ### AugmintReserves ### + await deployer.deploy(AugmintReserves, StabilityBoardProxy.address) + + // ### InterestEarnedAccount ### + await deployer.deploy(InterestEarnedAccount, StabilityBoardProxy.address); + + // ### MonetarySupervisor ### + await deployer.deploy(MonetarySupervisor, StabilityBoardProxy.address, TokenAEur.address, AugmintReserves.address, InterestEarnedAccount.address, MONETARY_SUPERVISOR_LOCK_DIFF_LIMIT, MONETARY_SUPERVISOR_LOAN_DIFF_LIMIT, MONETARY_SUPERVISOR_ALLOWED_DIFF_AMOUNT); + + // ### Exchange ### + await deployer.deploy(Exchange, StabilityBoardProxy.address, TokenAEur.address, Rates.address); + + // ### LoanManager ### + await deployer.deploy(LoanManager, StabilityBoardProxy.address, TokenAEur.address, MonetarySupervisor.address, Rates.address); + + // ### Locker ### + await deployer.deploy(Locker, StabilityBoardProxy.address, TokenAEur.address, MonetarySupervisor.address); + + // ### PreTokenProxy ### + await deployer.deploy(PreTokenProxy); + + // ### PreToken ### + await deployer.deploy(PreToken, StabilityBoardProxy.address); // temporary for preToken, init script will change it to preTokenProxy + + // ### Migrations ### + await deployer.deploy(Migrations); + + console.log("Done with migration step " + MIGRATION_STEP_NUMBER); + await Migrations.at(Migrations.address).setCompleted(MIGRATION_STEP_NUMBER); + }); +}; \ No newline at end of file diff --git a/rinkeby_migrations/1_initial_migration.js b/rinkeby_migrations/1_initial_migration.js deleted file mode 100644 index 4d5f3f9b..00000000 --- a/rinkeby_migrations/1_initial_migration.js +++ /dev/null @@ -1,5 +0,0 @@ -var Migrations = artifacts.require("./Migrations.sol"); - -module.exports = function(deployer) { - deployer.deploy(Migrations); -}; diff --git a/rinkeby_migrations/20_init_new_deploy.js b/rinkeby_migrations/20_init_new_deploy.js deleted file mode 100644 index 0b914d3c..00000000 --- a/rinkeby_migrations/20_init_new_deploy.js +++ /dev/null @@ -1,47 +0,0 @@ -/* init preToken and new contracts signed via - Rink0001_initNewContracts.sol - -NB: deployer account can sign these scripts b/c initially the deployer is the sole signer. - if migration succeed the following step will be to add new signers and remove deployer as signer - */ -const Migrations = artifacts.require("./Migrations.sol"); -const StabilityBoardProxy = artifacts.require("./StabilityBoardProxy.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); -const Rink0001_initNewContracts = artifacts.require("./Rink0001_initNewContracts.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - const rink0001_initNewContracts = await deployer.deploy(Rink0001_initNewContracts); - // new MS & feeAccount - const MONETARYSUPERVISOR_ADDRESS = "0x01844c9bade08A8ffdB09aD9f1fecE2C83a6E6a8"; - - // oldToken3 & oldToken4 both using this feeAccount - const oldFeeAccount1 = FeeAccount.at("0xc26667132b0b798ab87864f7c29c0819c887aadb"); - - // run stabilityboard setup scripts. deployer is the only signer yet - // (it's fine, these are new deployments, a script later will add signers and remove deployer) - const stabilityBoardProxy = StabilityBoardProxy.at("0x44022C28766652EC5901790E53CEd7A79a19c10A"); - await Promise.all([ - stabilityBoardProxy.sign(rink0001_initNewContracts.address), - - /* to be able to convert old tokens. As oldFeeAccount1 was permissioned without multiSig, - it can be executed by deployer account. - NB: - 1. This step need to be executed via an authorised StabilityBoardProxy script in the future - (as new deploys are w/ MultiSig) - 2. !!!! On newer FeeAccounts the permission is renamed to NoTransferFee !!!!*/ - oldFeeAccount1.grantPermission(MONETARYSUPERVISOR_ADDRESS, "NoFeeTransferContracts") - ]); - - const tx = await stabilityBoardProxy.execute(rink0001_initNewContracts.address); - - if (!tx.logs[0].args.result) { - throw new Error(`rink0001_initNewContracts execution failed. - Script address: ${rink0001_initNewContracts.address} - Execution hash: ${tx.receipt.transactionHash}\n`); - } - - console.log(" Done with migration step 20. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(20); - }); -}; diff --git a/rinkeby_migrations/21_setup_signers.js b/rinkeby_migrations/21_setup_signers.js deleted file mode 100644 index 376f1344..00000000 --- a/rinkeby_migrations/21_setup_signers.js +++ /dev/null @@ -1,33 +0,0 @@ -/* add preToken and StabilityBoard Signers and remove deployer account as signer - Executes Rink0002_setupPreTokenSigners.sol Rink0003_setupSBSigners scripts -*/ -const Migrations = artifacts.require("./Migrations.sol"); -const StabilityBoardProxy = artifacts.require("./StabilityBoardProxy.sol"); -const PreTokenProxy = artifacts.require("./PreTokenProxy.sol"); -const Rink0002_setupPreTokenSigners = artifacts.require("./Rink0002_setupPreTokenSigners.sol"); -const Rink0003_setupSBSigners = artifacts.require("./Rink0003_setupSBSigners.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - const [rink0002_setupPreTokenSigners, rink0003_setupSBSigners] = await Promise.all([ - deployer.deploy(Rink0002_setupPreTokenSigners), - deployer.deploy(Rink0003_setupSBSigners) - ]); - - const preTokenProxy = PreTokenProxy.at("0x0775465245e523b45Cc3b41477d44F908e22feDE"); - const stabilityBoardProxy = StabilityBoardProxy.at("0x44022C28766652EC5901790E53CEd7A79a19c10A"); - - await Promise.all([ - preTokenProxy.sign(rink0002_setupPreTokenSigners.address), - stabilityBoardProxy.sign(rink0003_setupSBSigners.address) - ]); - - await Promise.all([ - preTokenProxy.execute(rink0002_setupPreTokenSigners.address), - stabilityBoardProxy.execute(rink0003_setupSBSigners.address) - ]); - - console.log(" Done with migration step 21. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(21); - }); -}; diff --git a/rinkeby_migrations/22_deployRink0004_migrate_MSv0_5_0.js b/rinkeby_migrations/22_deployRink0004_migrate_MSv0_5_0.js deleted file mode 100644 index 601c9c8b..00000000 --- a/rinkeby_migrations/22_deployRink0004_migrate_MSv0_5_0.js +++ /dev/null @@ -1,14 +0,0 @@ -/****************************************************************************** - * Deploys StabilityBoard script to migrate KPIs from old MonetarySupervisor - ******************************************************************************/ -const Migrations = artifacts.require("./Migrations.sol"); -const Rink0004_migrate_MSv0_5_0 = artifacts.require("./Rink0004_migrate_MSv0_5_0.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Rink0004_migrate_MSv0_5_0); - - console.log(" Done with migration step 22. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(22); - }); -}; diff --git a/rinkeby_migrations/22_deploy_Rink0004_interest_adjustment.js b/rinkeby_migrations/22_deploy_Rink0004_interest_adjustment.js deleted file mode 100644 index 1e93d43e..00000000 --- a/rinkeby_migrations/22_deploy_Rink0004_interest_adjustment.js +++ /dev/null @@ -1,13 +0,0 @@ -/* Deploy Rink0004Rink0004_adjustInte.sol scripts for Stability Board signature -*/ -const Migrations = artifacts.require("./Migrations.sol"); -const Rink0004_adjustInterest = artifacts.require("./Rink0004_adjustInterest.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Rink0004_adjustInterest); - - console.log(" Done with migration step 22. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(22); - }); -}; diff --git a/rinkeby_migrations/23_executeRink0004_and_revokeOldPermissions.js b/rinkeby_migrations/23_executeRink0004_and_revokeOldPermissions.js deleted file mode 100644 index 65732eda..00000000 --- a/rinkeby_migrations/23_executeRink0004_and_revokeOldPermissions.js +++ /dev/null @@ -1,85 +0,0 @@ -/****************************************************************************** - * Execute Rink0004_migrate_MSv0_5_0.sol (already signed by stability board) - * and switch to new MS and rates contracts and revoke permissions from old contracts - * NB: - * - switch contracts can executed from deployer account for now because old contracts didn't have multiSig. - * From latest deplyed contracts these must be set via StabilityBoardProxy, ie. be part of the migrate script - ******************************************************************************/ -const Migrations = artifacts.require("./Migrations.sol"); -const StabilityBoardProxy = artifacts.require("./StabilityBoardProxy.sol"); -const Rates = artifacts.require("./Rates.sol"); -const AugmintReserves = artifacts.require("./AugmintReserves.sol"); -const InterestEarnedAccount = artifacts.require("./InterestEarnedAccount.sol"); -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); -const LoanManager = artifacts.require("./LoanManager.sol"); -const Locker = artifacts.require("./Locker.sol"); -const Exchange = artifacts.require("./Exchange.sol"); - -module.exports = function(deployer) { - const stabilityBoardProxy = StabilityBoardProxy.at("0x44022C28766652EC5901790E53CEd7A79a19c10A"); - const rates = Rates.at("0xf25638C7d37fCa0cBc124b3925eCe156a20e1f03"); - const monetarySupervisor = MonetarySupervisor.at("0x01844c9bade08A8ffdB09aD9f1fecE2C83a6E6a8"); - const rink0004_migrate_MSv0_5_0Address = "0x4062126c5df423c1f73530367405aced701a2d5c"; - - // Legacy contracts - - const oldMonetarySupervisor1 = MonetarySupervisor.at("0xC19a45F5CbfA93Be512ef07177feB3f7b3ae4518"); - - const oldInterestEarnedAccount1 = InterestEarnedAccount.at("0x3a414d7636defb9d3dfB7342984Fe3F7B5125Df6"); - - const oldAugmintReserves1 = AugmintReserves.at("0xc70b65e40f877cdC6d8D2ebFd44d63EfBeb7fc6D"); - - const oldToken4 = TokenAEur.at("0x6C90c10D7A33815C2BaeeD66eE8b848F1D95268e"); - - const oldLoanManager1 = LoanManager.at("0xBdb02f82d7Ad574f9F549895caf41E23a8981b07"); - const oldLoanManager2 = LoanManager.at("0x214919Abe3f2b7CA7a43a799C4FC7132bBf78e8A"); - - const oldLocker1 = Locker.at("0xf98AE1fb568B267A7632BF54579A153C892E2ec2"); - const oldLocker2 = Locker.at("0xd0B6136C2E35c288A903E836feB9535954E4A9e9"); - - const oldExchange = Exchange.at("0xC5B604f8E046Dff26642Ca544c9eb3064E02EcD9"); - - deployer.then(async () => { - const tx = await stabilityBoardProxy.execute(rink0004_migrate_MSv0_5_0Address); - if (!tx.logs[0].args.result) { - throw new Error(`rink0004_setV0_5_0Live execution failed. - Script address: ${rink0004_migrate_MSv0_5_0Address} - Execution hash: ${tx.receipt.transactionHash}\n`); - } - - /****************************************************************************** - * Set new Rates in old Exchange - ******************************************************************************/ - await oldExchange.setRatesContract(rates.address); - - /****************************************************************************** - * Set new MonetarySupervisor in old Lockers - ******************************************************************************/ - await oldLocker1.setMonetarySupervisor(monetarySupervisor.address); - await oldLocker2.setMonetarySupervisor(monetarySupervisor.address); - - /****************************************************************************** - * Set new Rates and MonetarySupervisor in old LoanManager - ******************************************************************************/ - await oldLoanManager1.setSystemContracts(rates.address, monetarySupervisor.address); - await oldLoanManager2.setSystemContracts(rates.address, monetarySupervisor.address); - - /****************************************************************************** - * Revoke MonetarySupervisor permissions in old contracts - * NB: - * - These permission names have changed in newly deployed contracts, - * in future redeploymnets these revokations must use different names! - * - These revokations are not essential because MonetarySupervisor has been updated - * to latest MS in all of these contracts but don't want unused permissions - ******************************************************************************/ - await oldToken4.revokePermission(oldMonetarySupervisor1.address, "MonetarySupervisorContract"); - await oldInterestEarnedAccount1.revokePermission(oldMonetarySupervisor1.address, "MonetarySupervisorContract"); - await oldAugmintReserves1.revokePermission(oldMonetarySupervisor1.address, "MonetarySupervisorContract"); - await oldMonetarySupervisor1.revokePermission(oldLocker2.address, "LockerContracts"); - await oldMonetarySupervisor1.revokePermission(oldLoanManager2.address, "LoanManagerContracts"); - - console.log(" Done with migration step 23. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(23); - }); -}; diff --git a/rinkeby_migrations/24_deploy_new_Locker.js b/rinkeby_migrations/24_deploy_new_Locker.js deleted file mode 100644 index 08199d2c..00000000 --- a/rinkeby_migrations/24_deploy_new_Locker.js +++ /dev/null @@ -1,18 +0,0 @@ -const Locker = artifacts.require("./Locker.sol"); -const Migrations = artifacts.require("./Migrations.sol"); -const Rink0005_initNewLocker = artifacts.require("./Rink0005_initNewLocker.sol"); - -const STABILITYBOARDPROXY_ADDRESS = "0x44022C28766652EC5901790E53CEd7A79a19c10A"; -const TOKENAEUR_ADDRESS = "0xe54f61d6EaDF03b658b3354BbD80cF563fEca34c"; -const MONETARYSUPERVISOR_ADDRESS = "0x01844c9bade08A8ffdB09aD9f1fecE2C83a6E6a8"; - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Locker, STABILITYBOARDPROXY_ADDRESS, TOKENAEUR_ADDRESS, MONETARYSUPERVISOR_ADDRESS); - - await deployer.deploy(Rink0005_initNewLocker); - - console.log(" Done with migration step 24. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(24); - }); -}; diff --git a/rinkeby_migrations/25_deploy_fixInitNewLocker.js b/rinkeby_migrations/25_deploy_fixInitNewLocker.js deleted file mode 100644 index 79a164b9..00000000 --- a/rinkeby_migrations/25_deploy_fixInitNewLocker.js +++ /dev/null @@ -1,11 +0,0 @@ -const Migrations = artifacts.require("./Migrations.sol"); -const Rink0006_fixInitNewLocker = artifacts.require("./Rink0006_fixInitNewLocker.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Rink0006_fixInitNewLocker); - - console.log(" Done with migration step 25. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(25); - }); -}; diff --git a/rinkeby_migrations/26_deploy_new_Exchange.js b/rinkeby_migrations/26_deploy_new_Exchange.js deleted file mode 100644 index 54681f7e..00000000 --- a/rinkeby_migrations/26_deploy_new_Exchange.js +++ /dev/null @@ -1,15 +0,0 @@ -const Exchange = artifacts.require("./Exchange.sol"); -const Migrations = artifacts.require("./Migrations.sol"); - -const STABILITYBOARDPROXY_ADDRESS = "0x44022C28766652EC5901790E53CEd7A79a19c10A"; -const TOKENAEUR_ADDRESS = "0xe54f61d6EaDF03b658b3354BbD80cF563fEca34c"; -const RATES_ADDRESS = "0xf25638C7d37fCa0cBc124b3925eCe156a20e1f03"; - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Exchange, STABILITYBOARDPROXY_ADDRESS, TOKENAEUR_ADDRESS, RATES_ADDRESS); - - console.log(" Done with migration step 26. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(26); - }); -}; diff --git a/rinkeby_migrations/27_deploy_initNewExchange.js b/rinkeby_migrations/27_deploy_initNewExchange.js deleted file mode 100644 index 44157c6b..00000000 --- a/rinkeby_migrations/27_deploy_initNewExchange.js +++ /dev/null @@ -1,12 +0,0 @@ -/* This migration step was ran but Rink0007_initNewExchange script failed to execute */ -const Migrations = artifacts.require("./Migrations.sol"); -const Rink0007_initNewExchange = artifacts.require("./Rink0007_initNewExchange.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Rink0007_initNewExchange); - - console.log(" Done with migration step 27. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(27); - }); -}; diff --git a/rinkeby_migrations/28_deploy_initNewExchange2.js b/rinkeby_migrations/28_deploy_initNewExchange2.js deleted file mode 100644 index c3eb17f3..00000000 --- a/rinkeby_migrations/28_deploy_initNewExchange2.js +++ /dev/null @@ -1,12 +0,0 @@ -/* This is deploy of a fixed script (Rink0007_initNewExchange) which failed to execute */ -const Migrations = artifacts.require("./Migrations.sol"); -const Rink0008_initNewExchange2 = artifacts.require("./Rink0008_initNewExchange2.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Rink0008_initNewExchange2); - - console.log(" Done with migration step 28. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(28); - }); -}; diff --git a/rinkeby_migrations/29_deploy_changeSBSigners.js b/rinkeby_migrations/29_deploy_changeSBSigners.js deleted file mode 100644 index 4abff8b8..00000000 --- a/rinkeby_migrations/29_deploy_changeSBSigners.js +++ /dev/null @@ -1,11 +0,0 @@ -const Migrations = artifacts.require("./Migrations.sol"); -const Rink0009_changeSBSigners = artifacts.require("./Rink0009_changeSBSigners.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Rink0009_changeSBSigners); - - console.log(" Done with migration step 29. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(29); - }); -}; diff --git a/rinkeby_migrations/2_deploy_Libs.js b/rinkeby_migrations/2_deploy_Libs.js deleted file mode 100644 index 7c39615f..00000000 --- a/rinkeby_migrations/2_deploy_Libs.js +++ /dev/null @@ -1,5 +0,0 @@ -var SafeMath = artifacts.require("./SafeMath.sol"); - -module.exports = function(deployer) { - deployer.deploy(SafeMath); -}; diff --git a/rinkeby_migrations/2_deploy_init_all.js b/rinkeby_migrations/2_deploy_init_all.js new file mode 100644 index 00000000..4cc0fc76 --- /dev/null +++ b/rinkeby_migrations/2_deploy_init_all.js @@ -0,0 +1,16 @@ +const Migrations = artifacts.require("./Migrations.sol"); +const Rinkeby_0001_initAll = artifacts.require("./Rinkeby_0001_initAll.sol"); + +const MIGRATION_STEP_NUMBER = 2; +const MIGRATIONS_ADDRESS = "0xc9a7258b2b1ea36ce735793e4816ad949532c9fd"; + +module.exports = function(deployer) { + deployer.then(async () => { + + // script for init new contracts + await deployer.deploy(Rinkeby_0001_initAll); + + console.log("Done with migration step " + MIGRATION_STEP_NUMBER); + await Migrations.at(MIGRATIONS_ADDRESS).setCompleted(MIGRATION_STEP_NUMBER); + }); +}; \ No newline at end of file diff --git a/rinkeby_migrations/30_deploy_changeDefaultingFee.js b/rinkeby_migrations/30_deploy_changeDefaultingFee.js deleted file mode 100644 index 2fdf9eb8..00000000 --- a/rinkeby_migrations/30_deploy_changeDefaultingFee.js +++ /dev/null @@ -1,11 +0,0 @@ -const Migrations = artifacts.require("./Migrations.sol"); -const Rink0010_changeDefaultingFee = artifacts.require("./Rink0010_changeDefaultingFee.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Rink0010_changeDefaultingFee); - - console.log(" Done with migration step 30. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(30); - }); -}; diff --git a/rinkeby_migrations/31_deploy_adjustInterest.js b/rinkeby_migrations/31_deploy_adjustInterest.js deleted file mode 100644 index 9c148bd7..00000000 --- a/rinkeby_migrations/31_deploy_adjustInterest.js +++ /dev/null @@ -1,11 +0,0 @@ -const Migrations = artifacts.require("./Migrations.sol"); -const Rink0011_adjustInterest = artifacts.require("./Rink0011_adjustInterest.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Rink0011_adjustInterest); - - console.log(" Done with migration step 31. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(31); - }); -}; diff --git a/rinkeby_migrations/32_deploy_new_Exchange.js b/rinkeby_migrations/32_deploy_new_Exchange.js deleted file mode 100644 index 43ff4ce3..00000000 --- a/rinkeby_migrations/32_deploy_new_Exchange.js +++ /dev/null @@ -1,15 +0,0 @@ -const Exchange = artifacts.require("./Exchange.sol"); -const Migrations = artifacts.require("./Migrations.sol"); - -const STABILITYBOARDPROXY_ADDRESS = "0x44022C28766652EC5901790E53CEd7A79a19c10A"; -const TOKENAEUR_ADDRESS = "0xe54f61d6EaDF03b658b3354BbD80cF563fEca34c"; -const RATES_ADDRESS = "0xf25638C7d37fCa0cBc124b3925eCe156a20e1f03"; - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Exchange, STABILITYBOARDPROXY_ADDRESS, TOKENAEUR_ADDRESS, RATES_ADDRESS); - - console.log(" Done with migration step 32. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(32); - }); -}; diff --git a/rinkeby_migrations/33_deploy_initNewExchange.js b/rinkeby_migrations/33_deploy_initNewExchange.js deleted file mode 100644 index 2513a764..00000000 --- a/rinkeby_migrations/33_deploy_initNewExchange.js +++ /dev/null @@ -1,12 +0,0 @@ -/* Init newly deployed Exchange */ -const Migrations = artifacts.require("./Migrations.sol"); -const Rink0012_initNewExchange = artifacts.require("./Rink0012_initNewExchange.sol"); - -module.exports = function(deployer) { - deployer.then(async () => { - await deployer.deploy(Rink0012_initNewExchange); - - console.log(" Done with migration step 33. Updating truffle Migrations step manually"); - await Migrations.at("0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5").setCompleted(33); - }); -}; diff --git a/rinkeby_migrations/3_deploy_Rates.js b/rinkeby_migrations/3_deploy_Rates.js deleted file mode 100644 index 6a8bc645..00000000 --- a/rinkeby_migrations/3_deploy_Rates.js +++ /dev/null @@ -1,20 +0,0 @@ -var Rates = artifacts.require("./Rates.sol"); -var SafeMath = artifacts.require("./SafeMath.sol"); - -module.exports = function(deployer, network, accounts) { - deployer.link(SafeMath, Rates); - - deployer.deploy(Rates); - - deployer.then(async () => { - const rates = Rates.at(Rates.address); - let grantTxs = [rates.grantPermission(accounts[0], "setRate")]; - - grantTxs = grantTxs.concat([ - rates.grantPermission("0x8c58187a978979947b88824dcda5cb5fd4410387", "setRate"), // ratesfeeder account - rates.grantPermission("0xd3D44BCf1F430edD91781AD5a231b999684c2feB", "setRate") // KP's account - ]); - - await Promise.all(grantTxs); - }); -}; diff --git a/rinkeby_migrations/3_redeploy_all.js b/rinkeby_migrations/3_redeploy_all.js new file mode 100644 index 00000000..d415450e --- /dev/null +++ b/rinkeby_migrations/3_redeploy_all.js @@ -0,0 +1,60 @@ +const AugmintReserves = artifacts.require("./AugmintReserves.sol"); +const Exchange = artifacts.require("./Exchange.sol"); +const FeeAccount = artifacts.require("./FeeAccount.sol"); +const InterestEarnedAccount = artifacts.require("./InterestEarnedAccount.sol"); +const LoanManager = artifacts.require("./LoanManager.sol"); +const Locker = artifacts.require("./Locker.sol"); +const Migrations = artifacts.require("./Migrations.sol"); +const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); +const Rates = artifacts.require("./Rates.sol"); +const TokenAEur = artifacts.require("./TokenAEur.sol"); +const StabilityBoardProxy = artifacts.require("./StabilityBoardProxy.sol"); + +const MIGRATION_STEP_NUMBER = 3; +const MIGRATIONS_ADDRESS = "0xc9a7258b2b1ea36ce735793e4816ad949532c9fd"; + +const FEE_ACCOUNT_TRANSFER_FEE_PT = 2000; +const FEE_ACCOUNT_TRANSFER_FEE_MIN = 2; +const FEE_ACCOUNT_TRANSFER_FEE_MAX = 500; + +const MONETARY_SUPERVISOR_LOCK_DIFF_LIMIT = 200000; +const MONETARY_SUPERVISOR_LOAN_DIFF_LIMIT = 200000; +const MONETARY_SUPERVISOR_ALLOWED_DIFF_AMOUNT = 1000000; + +module.exports = function(deployer) { + deployer.then(async () => { + + // ### StabilityBoardProxy ### + await deployer.deploy(StabilityBoardProxy); + + // ### FeeAccount ### + await deployer.deploy(FeeAccount, StabilityBoardProxy.address, FEE_ACCOUNT_TRANSFER_FEE_PT, FEE_ACCOUNT_TRANSFER_FEE_MIN, FEE_ACCOUNT_TRANSFER_FEE_MAX); + + // ### TokenAEur ### + await deployer.deploy(TokenAEur, StabilityBoardProxy.address, FeeAccount.address); + + // ### Rates ### + await deployer.deploy(Rates, StabilityBoardProxy.address); + + // ### AugmintReserves ### + await deployer.deploy(AugmintReserves, StabilityBoardProxy.address) + + // ### InterestEarnedAccount ### + await deployer.deploy(InterestEarnedAccount, StabilityBoardProxy.address); + + // ### MonetarySupervisor ### + await deployer.deploy(MonetarySupervisor, StabilityBoardProxy.address, TokenAEur.address, AugmintReserves.address, InterestEarnedAccount.address, MONETARY_SUPERVISOR_LOCK_DIFF_LIMIT, MONETARY_SUPERVISOR_LOAN_DIFF_LIMIT, MONETARY_SUPERVISOR_ALLOWED_DIFF_AMOUNT); + + // ### Exchange ### + await deployer.deploy(Exchange, StabilityBoardProxy.address, TokenAEur.address, Rates.address); + + // ### LoanManager ### + await deployer.deploy(LoanManager, StabilityBoardProxy.address, TokenAEur.address, MonetarySupervisor.address, Rates.address); + + // ### Locker ### + await deployer.deploy(Locker, StabilityBoardProxy.address, TokenAEur.address, MonetarySupervisor.address); + + console.log("Done with migration step " + MIGRATION_STEP_NUMBER); + await Migrations.at(MIGRATIONS_ADDRESS).setCompleted(MIGRATION_STEP_NUMBER); + }); +}; \ No newline at end of file diff --git a/rinkeby_migrations/4_deploy_FeeAccount.js b/rinkeby_migrations/4_deploy_FeeAccount.js deleted file mode 100644 index ad1af73b..00000000 --- a/rinkeby_migrations/4_deploy_FeeAccount.js +++ /dev/null @@ -1,15 +0,0 @@ -const FeeAccount = artifacts.require("./FeeAccount.sol"); - -module.exports = function(deployer) { - deployer.deploy( - FeeAccount, - 2000, // transferFeePt in parts per million = 0.2% - 2, // min: 0.02 A-EUR - 500 // max fee: 5 A-EUR); - ); - - deployer.then(async () => { - const feeAccount = FeeAccount.at(FeeAccount.address); - await feeAccount.grantPermission(FeeAccount.address, "NoFeeTransferContracts"); - }); -}; diff --git a/rinkeby_migrations/4_deploy_redeploy_init.js b/rinkeby_migrations/4_deploy_redeploy_init.js new file mode 100644 index 00000000..1e9feb48 --- /dev/null +++ b/rinkeby_migrations/4_deploy_redeploy_init.js @@ -0,0 +1,32 @@ +const Migrations = artifacts.require("./Migrations.sol"); +const Rinkeby_0002_redeployInitAll = artifacts.require("./Rinkeby_0002_redeployInitAll.sol"); +const Rinkeby_0003_migrateLegacy = artifacts.require("./Rinkeby_0003_migrateLegacy.sol"); +const Rinkeby_0004_setupLegacy = artifacts.require("./Rinkeby_0004_setupLegacy.sol"); +const Rinkeby_0005_setupSigners = artifacts.require("./Rinkeby_0005_setupSigners.sol"); +const Rinkeby_0006_postDeploySetup = artifacts.require("./Rinkeby_0006_postDeploySetup.sol"); + +const MIGRATION_STEP_NUMBER = 4; +const MIGRATIONS_ADDRESS = "0xc9a7258b2b1ea36ce735793e4816ad949532c9fd"; + +module.exports = function(deployer) { + deployer.then(async () => { + + // script for init new contracts + await deployer.deploy(Rinkeby_0002_redeployInitAll); + + // script for migrate legacy contracts (to be run via old proxy!) + await deployer.deploy(Rinkeby_0003_migrateLegacy); + + // script for setup legacy contract dependencies + await deployer.deploy(Rinkeby_0004_setupLegacy); + + // script for setup StabilityBoard signers + await deployer.deploy(Rinkeby_0005_setupSigners); + + // script for post deploy setup + await deployer.deploy(Rinkeby_0006_postDeploySetup); + + console.log("Done with migration step " + MIGRATION_STEP_NUMBER); + await Migrations.at(MIGRATIONS_ADDRESS).setCompleted(MIGRATION_STEP_NUMBER); + }); +}; \ No newline at end of file diff --git a/rinkeby_migrations/5_deploy_AugmintReserves.js b/rinkeby_migrations/5_deploy_AugmintReserves.js deleted file mode 100644 index c9de30a9..00000000 --- a/rinkeby_migrations/5_deploy_AugmintReserves.js +++ /dev/null @@ -1,11 +0,0 @@ -const AugmintReserves = artifacts.require("./AugmintReserves.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); - -module.exports = function(deployer) { - deployer.deploy(AugmintReserves); - - deployer.then(async () => { - const feeAccount = FeeAccount.at(FeeAccount.address); - await feeAccount.grantPermission(AugmintReserves.address, "NoFeeTransferContracts"); - }); -}; diff --git a/rinkeby_migrations/6_deploy_TokenAEur.js b/rinkeby_migrations/6_deploy_TokenAEur.js deleted file mode 100644 index 87b92baf..00000000 --- a/rinkeby_migrations/6_deploy_TokenAEur.js +++ /dev/null @@ -1,9 +0,0 @@ -const SafeMath = artifacts.require("./SafeMath.sol"); -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); - -module.exports = function(deployer) { - deployer.link(SafeMath, TokenAEur); - - deployer.deploy(TokenAEur, FeeAccount.address); -}; diff --git a/rinkeby_migrations/7_deploy_InterestEarnedAccount.js b/rinkeby_migrations/7_deploy_InterestEarnedAccount.js deleted file mode 100644 index d94115c2..00000000 --- a/rinkeby_migrations/7_deploy_InterestEarnedAccount.js +++ /dev/null @@ -1,11 +0,0 @@ -const InterestEarnedAccount = artifacts.require("./InterestEarnedAccount.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); - -module.exports = function(deployer, network) { - deployer.deploy(InterestEarnedAccount); - - deployer.then(async () => { - const feeAccount = FeeAccount.at(FeeAccount.address); - await feeAccount.grantMultiplePermissions(InterestEarnedAccount.address, ["NoFeeTransferContracts"]); - }); -}; diff --git a/rinkeby_migrations/8_deploy_MonetarySupervisor.js b/rinkeby_migrations/8_deploy_MonetarySupervisor.js deleted file mode 100644 index 01b67f3e..00000000 --- a/rinkeby_migrations/8_deploy_MonetarySupervisor.js +++ /dev/null @@ -1,39 +0,0 @@ -const SafeMath = artifacts.require("./SafeMath.sol"); -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); -const InterestEarnedAccount = artifacts.require("./InterestEarnedAccount.sol"); -const AugmintReserves = artifacts.require("./AugmintReserves.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); - -module.exports = function(deployer) { - deployer.link(SafeMath, MonetarySupervisor); - - deployer.deploy( - MonetarySupervisor, - TokenAEur.address, - AugmintReserves.address, - InterestEarnedAccount.address, - - /* Parameters Used to ensure totalLoanAmount or totalLockedAmount difference is withing limit and system also works - when any of those 0 or low. */ - 300000 /* ltdLockDifferenceLimit = 20% allow lock if Loan To Deposit ratio stays within 1 - this param - stored as parts per million */, - 200000 /* ltdLoanDifferenceLimit = 20% allow loan if Loan To Deposit ratio stays within 1 + this param - stored as parts per million */, - 100000 /* allowedLtdDifferenceAmount = 100 A-EUR - if totalLoan and totalLock difference is less than that - then allow loan or lock even if ltdDifference limit would go off with it */ - ); - - deployer.then(async () => { - const interestEarnedAccount = InterestEarnedAccount.at(InterestEarnedAccount.address); - const feeAccount = FeeAccount.at(FeeAccount.address); - const tokenAEur = TokenAEur.at(TokenAEur.address); - const augmintReserves = AugmintReserves.at(AugmintReserves.address); - await Promise.all([ - interestEarnedAccount.grantPermission(MonetarySupervisor.address, "MonetarySupervisorContract"), - tokenAEur.grantPermission(MonetarySupervisor.address, "MonetarySupervisorContract"), - feeAccount.grantPermission(MonetarySupervisor.address, "NoFeeTransferContracts"), - augmintReserves.grantPermission(MonetarySupervisor.address, "MonetarySupervisorContract") - ]); - }); -}; diff --git a/rinkeby_migrations/9_deploy_LoanManager.js b/rinkeby_migrations/9_deploy_LoanManager.js deleted file mode 100644 index 5e4d4fb6..00000000 --- a/rinkeby_migrations/9_deploy_LoanManager.js +++ /dev/null @@ -1,34 +0,0 @@ -const TokenAEur = artifacts.require("./TokenAEur.sol"); -const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); -const Rates = artifacts.require("./Rates.sol"); -const SafeMath = artifacts.require("./SafeMath.sol"); -const LoanManager = artifacts.require("./LoanManager.sol"); -const FeeAccount = artifacts.require("./FeeAccount.sol"); - -module.exports = function(deployer) { - deployer.link(SafeMath, LoanManager); - deployer.deploy(LoanManager, TokenAEur.address, MonetarySupervisor.address, Rates.address); - deployer.then(async () => { - const lm = LoanManager.at(LoanManager.address); - const feeAccount = FeeAccount.at(FeeAccount.address); - const monetarySupervisor = MonetarySupervisor.at(MonetarySupervisor.address); - - await Promise.all([ - feeAccount.grantPermission(LoanManager.address, "NoFeeTransferContracts"), - monetarySupervisor.grantPermission(LoanManager.address, "LoanManagerContracts") - ]); - - console.log(" Adding test loanProducts. Network id: ", web3.version.network); - // term (in sec), discountRate, loanCoverageRatio, minDisbursedAmount (w/ 4 decimals), defaultingFeePt, isActive - await lm.addLoanProduct(31536000, 860000, 550000, 1000, 50000, true); // 365d, 14% p.a. - await lm.addLoanProduct(15552000, 937874, 550000, 1000, 50000, true); // 180d, 13% p.a. - - await lm.addLoanProduct(7776000, 971661, 600000, 1000, 50000, true); // 90d, 12%. p.a. - await lm.addLoanProduct(2592000, 990641, 600000, 1000, 50000, true); // 30d, 12% p.a. - await lm.addLoanProduct(1209600, 996337, 600000, 1000, 50000, true); // 14d, 10% p.a. - await lm.addLoanProduct(604800, 998170, 600000, 1000, 50000, true); // 7d, 10% p.a. - - await lm.addLoanProduct(3600, 999989, 980000, 2000, 50000, true); // due in 1hr for testing repayments ? p.a. - await lm.addLoanProduct(1, 999999, 990000, 3000, 50000, true); // defaults in 1 secs for testing ? p.a. - }); -}; diff --git a/test/delegatedTransfer.js b/test/delegatedTransfer.js index 0d4573d6..58dc4426 100644 --- a/test/delegatedTransfer.js +++ b/test/delegatedTransfer.js @@ -94,8 +94,7 @@ contract("Delegated Transfers", accounts => { from = accounts[1]; tokenAEur = new global.web3v1.eth.Contract(TokenAEur.abi, TokenAEur.address); - await tokenTestHelpers.issueToReserve(100000); - await tokenTestHelpers.withdrawFromReserve(from, 100000); + await tokenTestHelpers.issueToken(accounts[0], from, 10000); }); it("should transfer when delegatedTransfer is signed", async function() { diff --git a/test/delegatedTransferAndNotify.js b/test/delegatedTransferAndNotify.js index d08bba4e..f2e31e14 100644 --- a/test/delegatedTransferAndNotify.js +++ b/test/delegatedTransferAndNotify.js @@ -88,10 +88,10 @@ contract("Delegated transferAndNotify", accounts => { tokenAEur = new global.web3v1.eth.Contract(TokenAEur.abi, TokenAEur.address); const lockerInstance = Locker.at(Locker.address); - const [product] = await Promise.all([lockerInstance.lockProducts(0), tokenTestHelpers.issueToReserve(100000)]); + const product = await lockerInstance.lockProducts(0); perTermInterest = product[0].toNumber(); - await tokenTestHelpers.withdrawFromReserve(from, 100000); + await tokenTestHelpers.issueToken(accounts[0], from, 10000); }); it("should lock with delegatedTransferAndNotify", async function() { diff --git a/test/exchangeMatching.js b/test/exchangeMatching.js index e0e5c3db..b1d0e787 100644 --- a/test/exchangeMatching.js +++ b/test/exchangeMatching.js @@ -15,10 +15,8 @@ contract("Exchange matching tests", () => { exchange = exchangeTestHelper.exchange; maker = global.accounts[1]; taker = global.accounts[2]; - - await tokenTestHelpers.issueToReserve(10000000); - await tokenTestHelpers.withdrawFromReserve(maker, 1000000); - await tokenTestHelpers.withdrawFromReserve(taker, 1000000); + await tokenTestHelpers.issueToken(global.accounts[0], maker, 1000000); + await tokenTestHelpers.issueToken(global.accounts[0], taker, 1000000); }); beforeEach(async function() { diff --git a/test/exchangeOrders.js b/test/exchangeOrders.js index de1468dd..965ef440 100644 --- a/test/exchangeOrders.js +++ b/test/exchangeOrders.js @@ -5,6 +5,8 @@ const exchangeTestHelpers = require("./helpers/exchangeTestHelpers.js"); const TOKEN_BUY = testHelpers.TOKEN_BUY; const TOKEN_SELL = testHelpers.TOKEN_SELL; +const CHUNK_SIZE = 10; + let makers; let snapshotId; @@ -16,10 +18,7 @@ contract("Exchange orders tests", accounts => { makers = [global.accounts[1], global.accounts[2], global.accounts[3]]; exchange = exchangeTestHelpers.exchange; augmintToken = tokenTestHelpers.augmintToken; - - await tokenTestHelpers.issueToReserve(10000000); - - await Promise.all(makers.map(maker => tokenTestHelpers.withdrawFromReserve(maker, 1000000))); + await Promise.all(makers.map(maker => tokenTestHelpers.issueToken(accounts[0], maker, 1000000))); }); beforeEach(async function() { @@ -141,7 +140,7 @@ contract("Exchange orders tests", accounts => { await exchangeTestHelpers.newOrder(this, orderB); await exchangeTestHelpers.newOrder(this, orderC); - var activeBuys = await exchangeTestHelpers.getActiveBuyOrdersNoFilter(0, 3); + var activeBuys = await exchangeTestHelpers.getActiveBuyOrders(0, 3); assert.equal(activeBuys.length, 3, "length of active orders list is wrong"); assert.equal(activeBuys[0].id, orderA.id, "wrong ID in active orders list"); assert.equal(activeBuys[1].id, orderB.id, "wrong ID in active orders list"); @@ -150,7 +149,7 @@ contract("Exchange orders tests", accounts => { await exchangeTestHelpers.cancelOrder(this, orderA); await exchangeTestHelpers.cancelOrder(this, orderC); - activeBuys = await exchangeTestHelpers.getActiveBuyOrdersNoFilter(0, 1); + activeBuys = await exchangeTestHelpers.getActiveBuyOrders(0, 1); assert.equal(activeBuys.length, 1, "length of active orders list is wrong"); assert.equal(activeBuys[0].id, orderB.id, "wrong ID in active orders list"); }); @@ -179,7 +178,7 @@ contract("Exchange orders tests", accounts => { await exchangeTestHelpers.newOrder(this, orderB); await exchangeTestHelpers.newOrder(this, orderC); - var activeSells = await exchangeTestHelpers.getActiveSellOrdersNoFilter(0, 3); + var activeSells = await exchangeTestHelpers.getActiveSellOrders(0, 3); assert.equal(activeSells.length, 3, "length of active orders list is wrong"); assert.equal(activeSells[0].id, orderA.id, "wrong ID in active orders list"); assert.equal(activeSells[1].id, orderB.id, "wrong ID in active orders list"); @@ -188,7 +187,7 @@ contract("Exchange orders tests", accounts => { await exchangeTestHelpers.cancelOrder(this, orderA); await exchangeTestHelpers.cancelOrder(this, orderC); - activeSells = await exchangeTestHelpers.getActiveSellOrdersNoFilter(0, 1); + activeSells = await exchangeTestHelpers.getActiveSellOrders(0, 1); assert.equal(activeSells.length, 1, "length of active orders list is wrong"); assert.equal(activeSells[0].id, orderB.id, "wrong ID in active orders list"); }); @@ -267,24 +266,24 @@ contract("Exchange orders tests", accounts => { assert(txs.length, orderCount); const orderQueries = [ - exchangeTestHelpers.getActiveBuyOrders(0).then(res => { + exchangeTestHelpers.getActiveBuyOrders(0, CHUNK_SIZE).then(res => { assert.equal( res.length, - Math.min(orderCount, exchangeTestHelpers.CHUNK_SIZE), + Math.min(orderCount, CHUNK_SIZE), "buy orders count when 0 offset" ); }), - exchangeTestHelpers.getActiveBuyOrders(1).then(res => { + exchangeTestHelpers.getActiveBuyOrders(1, CHUNK_SIZE).then(res => { assert.equal( res.length, - Math.min(orderCount - 1, exchangeTestHelpers.CHUNK_SIZE), + Math.min(orderCount - 1, CHUNK_SIZE), "buy count when offset from 1" ); }), - exchangeTestHelpers.getActiveBuyOrders(orderCount - 1).then(res => { + exchangeTestHelpers.getActiveBuyOrders(orderCount - 1, CHUNK_SIZE).then(res => { assert.equal(res.length, 1, "returned buy orders count when offset from last"); }), - exchangeTestHelpers.getActiveBuyOrders(orderCount).then(res => { + exchangeTestHelpers.getActiveBuyOrders(orderCount, CHUNK_SIZE).then(res => { assert.equal(res.length, 0, "returned buy orders count when offset > last"); }) ]; @@ -306,24 +305,24 @@ contract("Exchange orders tests", accounts => { assert(txs.length, orderCount); const orderQueries = [ - exchangeTestHelpers.getActiveSellOrders(0).then(res => { + exchangeTestHelpers.getActiveSellOrders(0, CHUNK_SIZE).then(res => { assert.equal( res.length, - Math.min(orderCount, exchangeTestHelpers.CHUNK_SIZE), + Math.min(orderCount, CHUNK_SIZE), "sell orders count when 0 offset" ); }), - exchangeTestHelpers.getActiveSellOrders(1).then(res => { + exchangeTestHelpers.getActiveSellOrders(1, CHUNK_SIZE).then(res => { assert.equal( res.length, - Math.min(orderCount - 1, exchangeTestHelpers.CHUNK_SIZE), + Math.min(orderCount - 1, CHUNK_SIZE), "sell count when offset from 1" ); }), - exchangeTestHelpers.getActiveSellOrders(orderCount - 1).then(res => { + exchangeTestHelpers.getActiveSellOrders(orderCount - 1, CHUNK_SIZE).then(res => { assert.equal(res.length, 1, "returned sell orders count when offset from last"); }), - exchangeTestHelpers.getActiveSellOrders(orderCount).then(res => { + exchangeTestHelpers.getActiveSellOrders(orderCount, CHUNK_SIZE).then(res => { assert.equal(res.length, 0, "returned sell orders count when offset > last"); }) ]; diff --git a/test/exchangeRandom.js b/test/exchangeRandom.js index 05882587..e13f818c 100644 --- a/test/exchangeRandom.js +++ b/test/exchangeRandom.js @@ -17,7 +17,7 @@ const MIN_TOKEN = 10000; // 100 ACE const MAX_TOKEN = 100000; // 1,000 ACE const TEST_ACCS_CT = 10; // accounts.length; const ACC_INIT_ACE = 1000000; -const CHUNK_SIZE = 100; +const CHUNK_SIZE = 10; const random = new RandomSeed("Have the same test data"); let augmintToken = null; @@ -36,14 +36,14 @@ const getOrderToFill = async () => { buyTokenOrders = []; const buyChunks = Math.ceil(state.buyCount / CHUNK_SIZE); for (let i = 0; i < buyChunks; i++) { - const buys = await exchangeTestHelper.getActiveBuyOrders(i * CHUNK_SIZE); + const buys = await exchangeTestHelper.getActiveBuyOrders(i * CHUNK_SIZE, CHUNK_SIZE); buyTokenOrders = buyTokenOrders.concat(buys); } sellTokenOrders = []; const sellChunks = Math.ceil(state.sellCount / CHUNK_SIZE); for (let i = 0; i < sellChunks; i++) { - const sells = await exchangeTestHelper.getActiveSellOrders(i * CHUNK_SIZE); + const sells = await exchangeTestHelper.getActiveSellOrders(i * CHUNK_SIZE, CHUNK_SIZE); sellTokenOrders = sellTokenOrders.concat(sells); } @@ -71,12 +71,10 @@ contract("Exchange random tests", accounts => { augmintToken = tokenTestHelpers.augmintToken; const rates = Rates.at(Rates.address); - await tokenTestHelpers.issueToReserve(TEST_ACCS_CT * ACC_INIT_ACE); - console.log(`\x1b[2m\t*** Topping up ${TEST_ACCS_CT} accounts each with ${ACC_INIT_ACE / 100} A-EURO\x1b[0m`); await Promise.all([ rates.setRate("EUR", MARKET_EURETH_RATE), - accounts.slice(0, TEST_ACCS_CT).map(acc => tokenTestHelpers.withdrawFromReserve(acc, ACC_INIT_ACE)) + accounts.slice(0, TEST_ACCS_CT).map(acc => tokenTestHelpers.issueToken(accounts[0], acc, ACC_INIT_ACE)) ]); }); @@ -191,12 +189,12 @@ contract("Exchange random tests", accounts => { //await exchangeTestHelper.printOrderBook(10); //const stateBefore = await exchangeTestHelper.getState(); - const buys = await exchangeTestHelper.getActiveBuyOrders(0); + const buys = await exchangeTestHelper.getActiveBuyOrders(0, CHUNK_SIZE); for (let i = 0; i < buys.length; i++) { await exchangeTestHelper.cancelOrder(this, buys[i]); } - const sells = await exchangeTestHelper.getActiveSellOrders(0); + const sells = await exchangeTestHelper.getActiveSellOrders(0, CHUNK_SIZE); for (let i = 0; i < sells.length; i++) { await exchangeTestHelper.cancelOrder(this, sells[i]); } diff --git a/test/feeAccount.js b/test/feeAccount.js index 6999b349..b09afade 100644 --- a/test/feeAccount.js +++ b/test/feeAccount.js @@ -45,9 +45,7 @@ contract("FeeAccount tests", accounts => { }); // top up feeAccount with tokens - await tokenTestHelpers.issueToReserve(tokenAmount); - await tokenTestHelpers.withdrawFromReserve(accounts[0], tokenAmount); - await augmintTokenInstance.transfer(feeAccountInstance.address, tokenAmount); + await tokenTestHelpers.issueToken(accounts[0], feeAccountInstance.address, tokenAmount); const balBefore = await tokenTestHelpers.getAllBalances({ to: accounts[0], diff --git a/test/helpers/exchangeTestHelpers.js b/test/helpers/exchangeTestHelpers.js index 46d92c8d..7a418a00 100644 --- a/test/helpers/exchangeTestHelpers.js +++ b/test/helpers/exchangeTestHelpers.js @@ -11,8 +11,6 @@ const MATCH_ORDER_MAX_GAS = 85000; const PPM_DIV = 1000000; -let CHUNK_SIZE = null; - module.exports = { newOrder, cancelOrder, @@ -22,14 +20,9 @@ module.exports = { getSellTokenOrder, getActiveBuyOrders, getActiveSellOrders, - getActiveBuyOrdersNoFilter, - getActiveSellOrdersNoFilter, printOrderBook, get exchange() { return exchange; - }, - get CHUNK_SIZE() { - return CHUNK_SIZE; } }; @@ -41,7 +34,6 @@ before(async function() { augmintToken = tokenTestHelpers.augmintToken; exchange = Exchange.at(Exchange.address); rates = Rates.at(Rates.address); - CHUNK_SIZE = (await exchange.CHUNK_SIZE()).toNumber(); }); async function newOrder(testInstance, order) { @@ -371,29 +363,19 @@ function parseOrders(orderType, orders) { }); } -async function getActiveBuyOrdersNoFilter(offset, chunkSize) { - const result = await exchange.getActiveBuyOrders(offset); - result.length = chunkSize; +async function getActiveBuyOrders(offset, chunkSize) { + const result = await exchange.getActiveBuyOrders(offset, chunkSize); return parseOrders(testHelpers.TOKEN_BUY, result); } -async function getActiveBuyOrders(offset) { - const result = await exchange.getActiveBuyOrders(offset); - return parseOrders(testHelpers.TOKEN_BUY, result.filter(order => order[3].toNumber() != 0)); -} - -async function getActiveSellOrdersNoFilter(offset, chunkSize) { - const result = await exchange.getActiveSellOrders(offset); - result.length = chunkSize; +async function getActiveSellOrders(offset, chunkSize) { + const result = await exchange.getActiveSellOrders(offset, chunkSize); return parseOrders(testHelpers.TOKEN_SELL, result); } -async function getActiveSellOrders(offset) { - const result = await exchange.getActiveSellOrders(offset); - return parseOrders(testHelpers.TOKEN_SELL, result.filter(order => order[3].toNumber() != 0)); -} - async function printOrderBook(_limit) { + const CHUNK_SIZE = 100; + const state = await getState(); const limit = typeof _limit === "undefined" || _limit > CHUNK_SIZE ? CHUNK_SIZE : _limit; diff --git a/test/helpers/loanTestHelpers.js b/test/helpers/loanTestHelpers.js index 6b34f58a..8d0e9446 100644 --- a/test/helpers/loanTestHelpers.js +++ b/test/helpers/loanTestHelpers.js @@ -11,8 +11,6 @@ const NEWLOAN_MAX_GAS = 220000; const REPAY_MAX_GAS = 120000; const COLLECT_BASE_GAS = 100000; -let CHUNK_SIZE = null; - let augmintToken = null; let monetarySupervisor = null; let loanManager = null; @@ -31,15 +29,11 @@ module.exports = { loanAsserts, get loanManager() { return loanManager; - }, - get CHUNK_SIZE() { - return CHUNK_SIZE; } }; before(async function() { loanManager = LoanManager.at(LoanManager.address); - CHUNK_SIZE = (await loanManager.CHUNK_SIZE()).toNumber(); augmintToken = tokenTestHelpers.augmintToken; monetarySupervisor = tokenTestHelpers.monetarySupervisor; @@ -313,9 +307,9 @@ async function collectLoan(testInstance, loan, collector) { ); } -async function getProductsInfo(offset) { - const products = await loanManager.getProducts(offset); - assert.equal(products.length, CHUNK_SIZE); +async function getProductsInfo(offset, chunkSize) { + const products = await loanManager.getProducts(offset, chunkSize); + assert(products.length <= chunkSize); const result = []; products.map(prod => { const [ @@ -328,26 +322,23 @@ async function getProductsInfo(offset) { maxLoanAmount, isActive ] = prod; - if (term.gt(0)) { - result.push({ - id, - minDisbursedAmount, - term, - discountRate, - collateralRatio, - defaultingFeePt, - maxLoanAmount, - isActive - }); - } + assert(term.gt(0)); + result.push({ + id, + minDisbursedAmount, + term, + discountRate, + collateralRatio, + defaultingFeePt, + maxLoanAmount, + isActive + }); }); - return result; } /* parse array returned by getLoans & getLoansForAddress */ function parseLoansInfo(loans) { - assert.equal(loans.length, CHUNK_SIZE); const result = []; loans.map(loan => { const [ @@ -363,22 +354,20 @@ function parseLoansInfo(loans) { interestAmount ] = loan; - if (maturity.gt(0)) { - result.push({ - id, - collateralAmount, - repaymentAmount, - borrower, - productId, - state, - maturity, - disbursementTime, - loanAmount, - interestAmount - }); - } + assert(maturity.gt(0)); + result.push({ + id, + collateralAmount, + repaymentAmount, + borrower, + productId, + state, + maturity, + disbursementTime, + loanAmount, + interestAmount + }); }); - return result; } diff --git a/test/helpers/tokenTestHelpers.js b/test/helpers/tokenTestHelpers.js index 7547cfb5..aa27d723 100644 --- a/test/helpers/tokenTestHelpers.js +++ b/test/helpers/tokenTestHelpers.js @@ -10,8 +10,7 @@ const FeeAccount = artifacts.require("./FeeAccount.sol"); const TRANSFER_MAX_GAS = 100000; module.exports = { - issueToReserve, - withdrawFromReserve, + issueToken, transferTest, getTransferFee, getAllBalances, @@ -49,7 +48,7 @@ let augmintReserves = null; let monetarySupervisor = null; let peggedSymbol = null; let interestEarnedAccount = null; -let feeAccount; +let feeAccount = null; before(async function() { augmintToken = AugmintToken.at(AugmintToken.address); @@ -63,12 +62,10 @@ before(async function() { peggedSymbol = global.web3v1.utils.toAscii(await augmintToken.peggedSymbol()); }); -async function issueToReserve(amount) { - await monetarySupervisor.issueToReserve(amount); -} - -async function withdrawFromReserve(to, amount) { - await augmintReserves.withdraw(augmintToken.address, to, amount, 0, "withdrawal for tests"); +async function issueToken(sender, to, amount) { + await augmintToken.grantPermission(sender, "MonetarySupervisor"); + await augmintToken.issueTo(to, amount); + await augmintToken.revokePermission(sender, "MonetarySupervisor"); } async function transferTest(testInstance, expTransfer) { @@ -135,6 +132,9 @@ async function transferFromTest(testInstance, expTransfer) { if (!expTransfer.to) { expTransfer.to = expTransfer.spender; } + if (!expTransfer.spender) { + expTransfer.spender = expTransfer.to; + } if (typeof expTransfer.narrative === "undefined") expTransfer.narrative = ""; expTransfer.fee = typeof expTransfer.fee === "undefined" ? await getTransferFee(expTransfer) : expTransfer.fee; @@ -170,9 +170,9 @@ async function transferFromTest(testInstance, expTransfer) { const allowanceAfter = await augmintToken.allowance(expTransfer.from, expTransfer.spender); assert.equal( - allowanceBefore.sub(expTransfer.amount).toString(), + allowanceBefore.sub(expTransfer.amount).sub(expTransfer.fee).toString(), allowanceAfter.toString(), - "allowance should be reduced with transferred amount" + "allowance should be reduced with transferred amount and fee" ); await assertBalances(balBefore, { diff --git a/test/loanCollection.js b/test/loanCollection.js index 544c689f..57f9f99b 100644 --- a/test/loanCollection.js +++ b/test/loanCollection.js @@ -14,7 +14,6 @@ contract("Loans collection tests", accounts => { rates = ratesTestHelpers.rates; monetarySupervisor = tokenTestHelpers.monetarySupervisor; loanManager = loanTestHelpers.loanManager; - await tokenTestHelpers.issueToReserve(1000000000); const [prodCount] = await Promise.all([ loanManager.getProductCount().then(res => res.toNumber()), @@ -35,8 +34,8 @@ contract("Loans collection tests", accounts => { await loanManager.addLoanProduct(1, 990000, 1200000, 2000, 50000, true); // moreCoverage const [newProducts] = await Promise.all([ - loanTestHelpers.getProductsInfo(prodCount), - tokenTestHelpers.withdrawFromReserve(accounts[0], 1000000000) + loanTestHelpers.getProductsInfo(prodCount, 10), + tokenTestHelpers.issueToken(accounts[0], accounts[0], 1000000000) ]); [ products.notDue, diff --git a/test/loanManager.js b/test/loanManager.js index 15169bce..9b49bb28 100644 --- a/test/loanManager.js +++ b/test/loanManager.js @@ -6,6 +6,8 @@ const ratesTestHelpers = require("./helpers/ratesTestHelpers.js"); let loanManager = null; let loanProduct = null; +let CHUNK_SIZE = 20; + contract("loanManager tests", accounts => { before(async function() { loanManager = loanTestHelpers.loanManager; @@ -70,7 +72,7 @@ contract("loanManager tests", accounts => { ); prod.id = res.productId; - const productsInfo = await loanTestHelpers.getProductsInfo(0); + const productsInfo = await loanTestHelpers.getProductsInfo(0, CHUNK_SIZE); const productCount = (await loanManager.getProductCount()).toNumber(); assert.equal(productsInfo.length, productCount); const lastProduct = productsInfo[productCount - 1]; @@ -111,7 +113,7 @@ contract("loanManager tests", accounts => { const productCount = (await loanManager.getProductCount()).toNumber(); prod.id = productCount - 1; - const productsInfo = await loanTestHelpers.getProductsInfo(productCount - 1); + const productsInfo = await loanTestHelpers.getProductsInfo(productCount - 1, CHUNK_SIZE); assert.equal(productsInfo.length, 1); const lastProduct = productsInfo[0]; @@ -140,9 +142,12 @@ contract("loanManager tests", accounts => { assert.equal( tx.logs[0].event, "LoanProductActiveStateChanged", - "LoanProductActiveStateChanged event should be emmitted" + "LoanProductActiveStateChanged event should be emitted" ); - assert(!tx.logs[0].args.newState, "new state should be false"); + assert.equal(tx.logs[0].args.newState, false, "new state should be false (event)"); + + const prod = await loanManager.products(loanProduct.id); + assert.equal(prod[5], false, "new state should be false"); }); it("Should enable loan product", async function() { @@ -151,9 +156,12 @@ contract("loanManager tests", accounts => { assert.equal( tx.logs[0].event, "LoanProductActiveStateChanged", - "LoanProductActiveStateChanged event should be emmitted" + "LoanProductActiveStateChanged event should be emitted" ); - assert(tx.logs[0].args.newState, "new state should be true"); + assert.equal(tx.logs[0].args.newState, true, "new state should be true (event)"); + + const prod = await loanManager.products(loanProduct.id); + assert.equal(prod[5], true, "new state should be true"); }); it("Only allowed should set loan product state", async function() { diff --git a/test/loanToDepositRatioLimits.js b/test/loanToDepositRatioLimits.js index b7425b30..b21a98bf 100644 --- a/test/loanToDepositRatioLimits.js +++ b/test/loanToDepositRatioLimits.js @@ -68,7 +68,6 @@ contract("Loan to Deposit ratio tests", accounts => { const [interestEarnedBalance] = await Promise.all([ augmintToken.balanceOf(InterestEarnedAccount.address), - tokenTestHelpers.issueToReserve(10000000), // term (in sec), discountRate, loanCoverageRatio, minDisbursedAmount, defaultingFeePt, isActive loanManager.addLoanProduct(60, 1000000, 1000000, 500, 5000, true), // (perTermInterest, durationInSecs, minimumLockAmount, isActive) @@ -84,7 +83,7 @@ contract("Loan to Deposit ratio tests", accounts => { loanManager.getProductCount().then(res => res.toNumber() - 1), locker.getLockProductCount().then(res => res.toNumber() - 1), rates.rates("EUR").then(res => res[0]), - tokenTestHelpers.withdrawFromReserve(accounts[0], 10000000), + tokenTestHelpers.issueToken(accounts[0], accounts[0], 10000000), tokenTestHelpers.interestEarnedAccount.withdraw( augmintToken.address, accounts[0], diff --git a/test/loans.js b/test/loans.js index d2b9a6cb..bce7bd2e 100644 --- a/test/loans.js +++ b/test/loans.js @@ -14,6 +14,7 @@ let rates = null; const ltdParams = { lockDifferenceLimit: 300000, loanDifferenceLimit: 200000, allowedDifferenceAmount: 1000000 }; let products = {}; +let CHUNK_SIZE = 10; contract("Loans tests", accounts => { before(async function() { @@ -21,7 +22,6 @@ contract("Loans tests", accounts => { monetarySupervisor = tokenTestHelpers.monetarySupervisor; augmintToken = tokenTestHelpers.augmintToken; loanManager = loanTestHelpers.loanManager; - await tokenTestHelpers.issueToReserve(1000000000); const [prodCount] = await Promise.all([ loanManager.getProductCount().then(res => res.toNumber()), @@ -43,9 +43,8 @@ contract("Loans tests", accounts => { await loanManager.addLoanProduct(60, 990000, 1200000, 2000, 50000, true); // moreCoverage const [newProducts] = await Promise.all([ - loanTestHelpers.getProductsInfo(prodCount), - - tokenTestHelpers.withdrawFromReserve(accounts[0], 1000000000) + loanTestHelpers.getProductsInfo(prodCount, CHUNK_SIZE), + tokenTestHelpers.issueToken(accounts[0], accounts[0], 1000000000) ]); [ products.notDue, @@ -248,9 +247,10 @@ contract("Loans tests", accounts => { await testHelpers.waitForTimeStamp(loan2.maturity); - const loansArray = await loanManager.getLoans(loan1.id); - const loanInfo = loanTestHelpers.parseLoansInfo(loansArray); + const loansArray = await loanManager.getLoans(loan1.id, CHUNK_SIZE); + assert.equal(loansArray.length, 2); + const loanInfo = loanTestHelpers.parseLoansInfo(loansArray); assert.equal(loanInfo.length, 2); // offset was from first loan added const loan1Actual = loanInfo[0]; @@ -290,7 +290,9 @@ contract("Loans tests", accounts => { await testHelpers.waitForTimeStamp(loan2.maturity); - const loansArray = await loanManager.getLoansForAddress(borrower, accountLoanCount - 2); + const loansArray = await loanManager.getLoansForAddress(borrower, accountLoanCount - 2, CHUNK_SIZE); + assert.equal(loansArray.length, 2); + const loanInfo = loanTestHelpers.parseLoansInfo(loansArray); assert.equal(loanInfo.length, 2); // offset was from first loan added for account diff --git a/test/locker.js b/test/locker.js index 4ec71b61..0e4afe90 100644 --- a/test/locker.js +++ b/test/locker.js @@ -12,7 +12,7 @@ let interestEarnedAddress = ""; let lockerInstance = null; let augmintToken = null; let monetarySupervisor = null; -let CHUNK_SIZE = null; +let CHUNK_SIZE = 10; const ltdParams = { lockDifferenceLimit: 300000, loanDifferenceLimit: 200000, allowedDifferenceAmount: 100000 }; @@ -27,19 +27,14 @@ contract("Lock", accounts => { lockerInstance = Locker.at(Locker.address); - [CHUNK_SIZE] = await Promise.all([lockerInstance.CHUNK_SIZE(), monetarySupervisor.issueToReserve(50000)]); - - CHUNK_SIZE = CHUNK_SIZE.toNumber(); - await Promise.all([ monetarySupervisor.setLtdParams( ltdParams.lockDifferenceLimit, ltdParams.loanDifferenceLimit, ltdParams.allowedDifferenceAmount ), - - tokenTestHelpers.withdrawFromReserve(tokenHolder, 40000), - tokenTestHelpers.withdrawFromReserve(interestEarnedAddress, 10000) + tokenTestHelpers.issueToken(accounts[0], tokenHolder, 40000), + tokenTestHelpers.issueToken(accounts[0], interestEarnedAddress, 10000) ]); }); @@ -95,14 +90,12 @@ contract("Lock", accounts => { const tx = await lockerInstance.addLockProduct(100000, 120, 75, true); testHelpers.logGasUse(this, tx, "addLockProduct"); - const [numLocks, products] = await Promise.all([ - lockerInstance.getLockProductCount().then(res => res.toNumber()), - lockerInstance.getLockProducts(0) - ]); + const numLocks = await lockerInstance.getLockProductCount().then(res => res.toNumber()); + const products = await lockerInstance.getLockProducts(0, numLocks); - // getLockProducts should return a 20 element array: + // getLockProducts should return a element array: assert.isArray(products); - assert(products.length === CHUNK_SIZE); + assert(products.length === numLocks); const newestProduct = products[numLocks - 1]; @@ -124,15 +117,14 @@ contract("Lock", accounts => { it("should allow the listing of lock products (non-zero offset)", async function() { const offset = 1; - const products = await lockerInstance.getLockProducts(offset); + const products = await lockerInstance.getLockProducts(offset, CHUNK_SIZE); - // getLockProducts should return a 20 element array: assert.isArray(products); - assert(products.length === CHUNK_SIZE); + assert(products.length <= CHUNK_SIZE); const product = products[0]; - // each product should be a 4 element array + // each product should be a 5 element array assert.isArray(product); assert(product.length === 5); @@ -414,9 +406,9 @@ contract("Lock", accounts => { const lockId3 = lockCount - 1; const offset = lockCount - 2; - const locks = await lockerInstance.getLocks(offset); + const locks = await lockerInstance.getLocks(offset, CHUNK_SIZE); - assert.equal(locks.length, CHUNK_SIZE); + assert(locks.length <= CHUNK_SIZE); const lock2 = locks[0]; // the locks should be [ lockId, owner, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ] @@ -471,11 +463,10 @@ contract("Lock", accounts => { const expectedLockId = (await lockerInstance.getLockCount()) - 1; const expectedAccountLockIndex = (await lockerInstance.getLockCountForAddress(tokenHolder)) - 1; - const accountLocks = await lockerInstance.getLocksForAddress(tokenHolder, expectedAccountLockIndex); + const accountLocks = await lockerInstance.getLocksForAddress(tokenHolder, expectedAccountLockIndex, CHUNK_SIZE); - // getLocksForAddress should return a CHUNK_SIZE element array: assert.isArray(accountLocks); - assert(accountLocks.length === CHUNK_SIZE); + assert(accountLocks.length <= CHUNK_SIZE); const newestLock = accountLocks[0]; @@ -517,11 +508,10 @@ contract("Lock", accounts => { const expectedAccountLockIndex = (await lockerInstance.getLockCountForAddress(tokenHolder)) - 1; - const accountLocks = await lockerInstance.getLocksForAddress(tokenHolder, expectedAccountLockIndex); + const accountLocks = await lockerInstance.getLocksForAddress(tokenHolder, expectedAccountLockIndex, CHUNK_SIZE); - // getLocksForAddress should return a CHUNK_SIZE element array: assert.isArray(accountLocks); - assert(accountLocks.length === CHUNK_SIZE); + assert(accountLocks.length <= CHUNK_SIZE); const lock = accountLocks[0]; diff --git a/test/monetarySupervisor.js b/test/monetarySupervisor.js index f81dd3fa..9d61ef5a 100644 --- a/test/monetarySupervisor.js +++ b/test/monetarySupervisor.js @@ -14,10 +14,11 @@ contract("MonetarySupervisor tests", accounts => { it("should be possible to issue new tokens to reserve", async function() { const amount = 100000; - const [totalSupplyBefore, reserveBalBefore, issuedByStabilityBoardBefore] = await Promise.all([ + const [totalSupplyBefore, reserveBalBefore, issuedByStabilityBoardBefore, burnedByStabilityBoardBefore] = await Promise.all([ augmintToken.totalSupply(), augmintToken.balanceOf(augmintReserves.address), - monetarySupervisor.issuedByStabilityBoard() + monetarySupervisor.issuedByStabilityBoard(), + monetarySupervisor.burnedByStabilityBoard() ]); const tx = await monetarySupervisor.issueToReserve(amount); @@ -29,10 +30,11 @@ contract("MonetarySupervisor tests", accounts => { amount: amount }); - const [totalSupply, issuedByStabilityBoard, reserveBal] = await Promise.all([ + const [totalSupply, reserveBal, issuedByStabilityBoard, burnedByStabilityBoard] = await Promise.all([ augmintToken.totalSupply(), augmintToken.balanceOf(augmintReserves.address), - monetarySupervisor.issuedByStabilityBoard() + monetarySupervisor.issuedByStabilityBoard(), + monetarySupervisor.burnedByStabilityBoard() ]); assert.equal( @@ -45,6 +47,11 @@ contract("MonetarySupervisor tests", accounts => { issuedByStabilityBoardBefore.add(amount).toString(), "issuedByStabilityBoard should be increased with issued amount" ); + assert.equal( + burnedByStabilityBoard.toString(), + burnedByStabilityBoardBefore.toString(), + "burnedByStabilityBoard should not change" + ); assert.equal( reserveBal.toString(), reserveBalBefore.add(amount).toString(), @@ -59,10 +66,11 @@ contract("MonetarySupervisor tests", accounts => { it("should be possible to burn tokens from reserve", async function() { const amount = 9000000; await monetarySupervisor.issueToReserve(amount); - const [totalSupplyBefore, reserveBalBefore, issuedByStabilityBoardBefore] = await Promise.all([ + const [totalSupplyBefore, reserveBalBefore, issuedByStabilityBoardBefore, burnedByStabilityBoardBefore] = await Promise.all([ augmintToken.totalSupply(), augmintToken.balanceOf(augmintReserves.address), - monetarySupervisor.issuedByStabilityBoard() + monetarySupervisor.issuedByStabilityBoard(), + monetarySupervisor.burnedByStabilityBoard() ]); const tx = await monetarySupervisor.burnFromReserve(amount, { from: accounts[0] }); @@ -74,10 +82,11 @@ contract("MonetarySupervisor tests", accounts => { amount: amount }); - const [totalSupply, issuedByStabilityBoard, reserveBal] = await Promise.all([ + const [totalSupply, reserveBal, issuedByStabilityBoard, burnedByStabilityBoard] = await Promise.all([ augmintToken.totalSupply(), augmintToken.balanceOf(augmintReserves.address), - monetarySupervisor.issuedByStabilityBoard() + monetarySupervisor.issuedByStabilityBoard(), + monetarySupervisor.burnedByStabilityBoard() ]); assert.equal( totalSupply.toString(), @@ -86,8 +95,13 @@ contract("MonetarySupervisor tests", accounts => { ); assert.equal( issuedByStabilityBoard.toString(), - issuedByStabilityBoardBefore.sub(amount).toString(), - "issuedByStabilityBoard should be decreased with burnt amount" + issuedByStabilityBoardBefore.toString(), + "issuedByStabilityBoard should not change" + ); + assert.equal( + burnedByStabilityBoard.toString(), + burnedByStabilityBoardBefore.add(amount).toString(), + "burnedByStabilityBoard should be increased with burnt amount" ); assert.equal( reserveBal.toString(), diff --git a/test/preToken.js b/test/preToken.js index 0fdfe2c6..e670f77a 100644 --- a/test/preToken.js +++ b/test/preToken.js @@ -52,7 +52,7 @@ contract("PreToken", accounts => { preToken.getAgreementsCount().then(res => res.toNumber()), preToken.agreements(agreement.hash), preToken.agreementOwners(agreement.owner), - preToken.getAllAgreements(agreementsCountBefore), + preToken.getAgreements(agreementsCountBefore, 1), testHelpers.assertEvent(preToken, "NewAgreement", { owner: agreement.owner, agreementHash: agreement.hash, @@ -111,7 +111,7 @@ contract("PreToken", accounts => { const [agreementsCountAfter, agreementsAfter] = await Promise.all([ preToken.getAgreementsCount().then(res => res.toNumber()), - preToken.getAllAgreements(agreementsCountBefore), + preToken.getAgreements(agreementsCountBefore, 2), testHelpers.assertEvent(preToken, "NewAgreement", { owner: agreement2.owner, agreementHash: agreement2.hash, diff --git a/test/safeMath.js b/test/safeMath.js index cbbf7a90..43e6143e 100644 --- a/test/safeMath.js +++ b/test/safeMath.js @@ -6,15 +6,18 @@ const BigNumber = require("bignumber.js"); const Locker = artifacts.require("./Locker.sol"); const testHelpers = require("./helpers/testHelpers.js"); const MonetarySupervisor = artifacts.require("./MonetarySupervisor.sol"); +const SafeMathTester = artifacts.require("./test/SafeMathTester.sol"); let locker; let monetarySupervisor; +let safeMathTester; const MAX_UINT256 = new BigNumber(2).pow(256).sub(1); contract("SafeMath", () => { before(() => { locker = Locker.at(Locker.address); monetarySupervisor = MonetarySupervisor.at(MonetarySupervisor.address); + safeMathTester = SafeMathTester.at(SafeMathTester.address); }); it("should throw if mul overflows", async function() { @@ -34,7 +37,6 @@ contract("SafeMath", () => { }); it("should round up if not exactly divisible", async function() { - assert.equal(Number(await locker.calculateInterest(1000, 1000)), 1); assert.equal(Number(await locker.calculateInterest(1, 1000000)), 1); assert.equal(Number(await locker.calculateInterest(1000, 1001)), 2); @@ -48,4 +50,43 @@ contract("SafeMath", () => { assert.equal(Number(await locker.calculateInterest(56713, 10000)), 568); assert.equal(Number(await locker.calculateInterest(120000, 10000)), 1200); }); + + it("should round properly when using roundedDiv", async function() { + assert.equal(Number(await safeMathTester.roundedDiv(0, 2)), 0); + assert.equal(Number(await safeMathTester.roundedDiv(1, 2)), 1); + assert.equal(Number(await safeMathTester.roundedDiv(2, 2)), 1); + assert.equal(Number(await safeMathTester.roundedDiv(3, 2)), 2); + + assert.equal(Number(await safeMathTester.roundedDiv(0, 3)), 0); + assert.equal(Number(await safeMathTester.roundedDiv(1, 3)), 0); + assert.equal(Number(await safeMathTester.roundedDiv(2, 3)), 1); + assert.equal(Number(await safeMathTester.roundedDiv(3, 3)), 1); + assert.equal(Number(await safeMathTester.roundedDiv(4, 3)), 1); + assert.equal(Number(await safeMathTester.roundedDiv(5, 3)), 2); + + assert.equal(Number(await safeMathTester.roundedDiv(0, 4)), 0); + assert.equal(Number(await safeMathTester.roundedDiv(1, 4)), 0); + assert.equal(Number(await safeMathTester.roundedDiv(2, 4)), 1); + assert.equal(Number(await safeMathTester.roundedDiv(3, 4)), 1); + assert.equal(Number(await safeMathTester.roundedDiv(4, 4)), 1); + assert.equal(Number(await safeMathTester.roundedDiv(5, 4)), 1); + assert.equal(Number(await safeMathTester.roundedDiv(6, 4)), 2); + + assert.equal(Number(await safeMathTester.roundedDiv(MAX_UINT256, 1)), MAX_UINT256); + assert.equal(Number(await safeMathTester.roundedDiv(MAX_UINT256, MAX_UINT256)), 1); + assert.equal(Number(await safeMathTester.roundedDiv(MAX_UINT256.sub(1), MAX_UINT256)), 1); + assert.equal(Number(await safeMathTester.roundedDiv(MAX_UINT256, MAX_UINT256.sub(1))), 1); + assert.equal(Number(await safeMathTester.roundedDiv(MAX_UINT256, MAX_UINT256.div(2))), 2); + assert.equal(Number(await safeMathTester.roundedDiv(MAX_UINT256, MAX_UINT256.div(3))), 3); + }); + + it("should not divide by zero", async function() { + await testHelpers.expectThrow(safeMathTester.roundedDiv(0, 0)); + await testHelpers.expectThrow(safeMathTester.roundedDiv(1, 0)); + await testHelpers.expectThrow(safeMathTester.roundedDiv(MAX_UINT256, 0)); + + await testHelpers.expectThrow(safeMathTester.ceilDiv(0, 0)); + await testHelpers.expectThrow(safeMathTester.ceilDiv(1, 0)); + await testHelpers.expectThrow(safeMathTester.ceilDiv(MAX_UINT256, 0)); + }); }); diff --git a/test/stabilityBoardProxy.js b/test/stabilityBoardProxy.js index 22cfa4ec..6fd00b1e 100644 --- a/test/stabilityBoardProxy.js +++ b/test/stabilityBoardProxy.js @@ -11,12 +11,13 @@ let snapshotId; let stabilityBoardProxy; let stabilityBoardProxyWeb3Contract; const scriptState = { New: 0, Approved: 1, Done: 2, Cancelled: 3, Failed: 4 }; +const CHUNK_SIZE = 10; async function addSigners(newSigners) { // assuming allSigners are active const [addSignerScript, currentSigners] = await Promise.all([ SB_addSigners.new(newSigners), - stabilityBoardProxy.getAllSigners(0) + stabilityBoardProxy.getSigners(0, CHUNK_SIZE) ]); const signTxs = currentSigners.filter(signerTuple => !signerTuple[1].eq(0)).map(tuple => { @@ -97,7 +98,7 @@ contract("StabilityBoardProxy", accounts => { let [allSignersCountAfter, activeSignersCountAfter, signersAfter, script] = await Promise.all([ stabilityBoardProxy.getAllSignersCount(), stabilityBoardProxy.activeSignersCount(), - stabilityBoardProxy.getAllSigners(0), + stabilityBoardProxy.getSigners(0, CHUNK_SIZE), stabilityBoardProxyWeb3Contract.methods.scripts(addSignerScript.address).call(), testHelpers.assertEvent(stabilityBoardProxy, "SignerAdded", [ { signer: newSigners[0] }, @@ -113,7 +114,7 @@ contract("StabilityBoardProxy", accounts => { assert.equal(signersAfter[0][2].toNumber(), 1, "signer 0 should be active"); assert.equal(signersAfter[1][2].toNumber(), 1, "signer 1 should be active"); assert.equal(signersAfter[2][2].toNumber(), 1, "signer 2 should be active"); - assert.equal(signersAfter[3][1].toNumber(), 0, "signer 3 should not exists (address 0)"); + assert.equal(signersAfter[3], undefined, "signer 3 should not exist"); assert.equal(activeSignersCountAfter.toNumber(), activeSignersCountBefore + newSigners.length); assert.equal(allSignersCountAfter.toNumber(), allSignersCountBefore + newSigners.length); @@ -132,7 +133,7 @@ contract("StabilityBoardProxy", accounts => { [activeSignersCountAfter, signersAfter, script] = await Promise.all([ stabilityBoardProxy.activeSignersCount(), - stabilityBoardProxy.getAllSigners(0), + stabilityBoardProxy.getSigners(0, CHUNK_SIZE), stabilityBoardProxyWeb3Contract.methods.scripts(removeSignerScript.address).call(), testHelpers.assertEvent(stabilityBoardProxy, "SignerRemoved", [ { signer: newSigners[0] }, @@ -148,7 +149,7 @@ contract("StabilityBoardProxy", accounts => { assert.equal(signersAfter[0][2].toNumber(), 1, "signer 0 should be active"); assert.equal(signersAfter[1][2].toNumber(), 0, "signer 1 should be inactive"); assert.equal(signersAfter[2][2].toNumber(), 0, "signer 2 should be inactive"); - assert.equal(signersAfter[3][1].toNumber(), 0, "signer 3 should not exists (address 0)"); + assert.equal(signersAfter[3], undefined, "signer 3 should not exist"); assert.equal(activeSignersCountAfter.toNumber(), activeSignersCountBefore); assert.equal(allSignersCountAfter.toNumber(), allSignersCountBefore + newSigners.length); @@ -189,7 +190,7 @@ contract("StabilityBoardProxy", accounts => { let [allSignersCountAfter, activeSignersCountAfter, signersAfter, script] = await Promise.all([ stabilityBoardProxy.getAllSignersCount(), stabilityBoardProxy.activeSignersCount(), - stabilityBoardProxy.getAllSigners(0), + stabilityBoardProxy.getSigners(0, CHUNK_SIZE), stabilityBoardProxyWeb3Contract.methods.scripts(addSignerScript.address).call(), testHelpers.assertEvent(stabilityBoardProxy, "SignerAdded", [ { signer: expNewSigners[0] }, @@ -206,7 +207,7 @@ contract("StabilityBoardProxy", accounts => { assert.equal(signersAfter[0][2].toNumber(), 0, "signer 0 should be inactive"); assert.equal(signersAfter[1][2].toNumber(), 1, "signer 1 should be active"); assert.equal(signersAfter[2][2].toNumber(), 1, "signer 2 should be active"); - assert.equal(signersAfter[3][1].toNumber(), 0, "signer 3 should not exists (address 0)"); + assert.equal(signersAfter[3], undefined, "signer 3 should not exist"); assert.equal(activeSignersCountAfter.toNumber(), activeSignersCountBefore + expNewSigners.length - 1); assert.equal(allSignersCountAfter.toNumber(), allSignersCountBefore + expNewSigners.length); }); @@ -425,7 +426,7 @@ contract("StabilityBoardProxy", accounts => { const [scriptsCountAfter, scriptsArray] = await Promise.all([ stabilityBoardProxy.getScriptsCount().then(res => res.toNumber()), - stabilityBoardProxy.getAllScripts(scriptCountBefore) + stabilityBoardProxy.getScripts(scriptCountBefore, CHUNK_SIZE) ]); const scripts = scriptsArray.filter(item => !item[1].eq(0)).map(item => { return { diff --git a/test/tokenConversion.js b/test/tokenConversion.js index d9715a45..238887d3 100644 --- a/test/tokenConversion.js +++ b/test/tokenConversion.js @@ -13,10 +13,7 @@ contract("token conversion tests", accounts => { augmintToken = tokenTestHelpers.augmintToken; monetarySupervisor = tokenTestHelpers.monetarySupervisor; - [newToken] = await Promise.all([ - AugmintToken.new(accounts[0], tokenTestHelpers.feeAccount.address), - tokenTestHelpers.issueToReserve(10000000) - ]); + newToken = await AugmintToken.new(accounts[0], tokenTestHelpers.feeAccount.address); newMS = await MonetarySupervisor.new( accounts[0], @@ -75,7 +72,7 @@ contract("token conversion tests", accounts => { const account = accounts[0]; await Promise.all([ - tokenTestHelpers.withdrawFromReserve(account, amount), + tokenTestHelpers.issueToken(accounts[0], account, amount), newMS.setAcceptedLegacyAugmintToken(augmintToken.address, true) ]); @@ -118,7 +115,7 @@ contract("token conversion tests", accounts => { await Promise.all([ newMS.setAcceptedLegacyAugmintToken(augmintToken.address, false), - tokenTestHelpers.withdrawFromReserve(account, amount) + tokenTestHelpers.issueToken(accounts[0], account, amount) ]); await testHelpers.expectThrow(augmintToken.transferAndNotify(newMS.address, amount, 0, { from: account })); diff --git a/test/tokenTransfer.js b/test/tokenTransfer.js index 516c46e0..6fb58261 100644 --- a/test/tokenTransfer.js +++ b/test/tokenTransfer.js @@ -7,10 +7,9 @@ let minFee, maxFee, feePt, minFeeAmount, maxFeeAmount; contract("Transfer Augmint tokens tests", accounts => { before(async function() { augmintToken = tokenTestHelpers.augmintToken; - await tokenTestHelpers.issueToReserve(1000000000); await Promise.all([ - tokenTestHelpers.withdrawFromReserve(accounts[0], 500000000), - tokenTestHelpers.withdrawFromReserve(accounts[1], 500000000) + tokenTestHelpers.issueToken(accounts[0], accounts[0], 500000000), + tokenTestHelpers.issueToken(accounts[0], accounts[1], 500000000) ]); [feePt, minFee, maxFee] = await tokenTestHelpers.feeAccount.transferFee(); minFeeAmount = minFee.div(feePt).mul(1000000); diff --git a/test/tokenTransferFrom.js b/test/tokenTransferFrom.js index 9a7025a4..afc8fe4b 100644 --- a/test/tokenTransferFrom.js +++ b/test/tokenTransferFrom.js @@ -8,35 +8,41 @@ contract("TransferFrom AugmintToken tests", accounts => { before(async function() { augmintToken = tokenTestHelpers.augmintToken; - await tokenTestHelpers.issueToReserve(1000000000); [[, , maxFee], ,] = await Promise.all([ tokenTestHelpers.feeAccount.transferFee(), - tokenTestHelpers.withdrawFromReserve(accounts[0], 500000000), - tokenTestHelpers.withdrawFromReserve(accounts[1], 500000000) + tokenTestHelpers.issueToken(accounts[0], accounts[0], 500000000), + tokenTestHelpers.issueToken(accounts[0], accounts[1], 500000000) ]); }); it("transferFrom", async function() { - let expApprove = { - owner: accounts[1], - spender: accounts[2], - value: 100000 + const from = accounts[1]; + const to = accounts[2]; + + const transfer1 = { + from: from, + to: to, + amount: 75000 }; + const fee1 = await tokenTestHelpers.getTransferFee(transfer1); - await tokenTestHelpers.approveTest(this, expApprove); + const transfer2 = { + from: from, + to: to, + amount: 25000, + narrative: "Test with narrative" + }; + const fee2 = await tokenTestHelpers.getTransferFee(transfer2); - await tokenTestHelpers.transferFromTest(this, { - from: expApprove.owner, - spender: expApprove.spender, - amount: Math.round(expApprove.value / 2) - }); + const expApprove = { + owner: from, + spender: to, + value: transfer1.amount + fee1 + transfer2.amount + fee2 + }; - await tokenTestHelpers.transferFromTest(this, { - from: expApprove.owner, - spender: expApprove.spender, - amount: Math.round(expApprove.value / 2), - narrative: "Test with narrative" - }); + await tokenTestHelpers.approveTest(this, expApprove); + await tokenTestHelpers.transferFromTest(this, transfer1); + await tokenTestHelpers.transferFromTest(this, transfer2); }); it("transferFrom spender to send to different to than itself", async function() { diff --git a/yarn.lock b/yarn.lock index 6b9a3c00..d5cb97c8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,27 +2,6 @@ # yarn lockfile v1 -"@mrmlnc/readdir-enhanced@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" - dependencies: - call-me-maybe "^1.0.1" - glob-to-regexp "^0.3.0" - -"@nodelib/fs.stat@^1.0.1": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz#50c1e2260ac0ed9439a181de3725a0168d59c48a" - -"@samverschueren/stream-to-observable@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" - dependencies: - any-observable "^0.3.0" - -"@sindresorhus/is@^0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" - abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -83,40 +62,14 @@ amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" -ansi-escapes@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - -ansi-escapes@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" - ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - dependencies: - color-convert "^1.9.0" - -ansi-styles@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" - -any-observable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" - any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" @@ -127,54 +80,10 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - dependencies: - arr-flatten "^1.0.1" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - -arr-flatten@^1.0.1, arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - -arrify@^1.0.0, arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -191,18 +100,6 @@ assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - -ast-types@0.10.1: - version "0.10.1" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.10.1.tgz#f52fca9715579a14f841d67d7f8d25432ab6a3dd" - -ast-types@0.11.5: - version "0.11.5" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.5.tgz#9890825d660c03c28339f315e9fa0a360e31ec28" - async-eventemitter@^0.2.2: version "0.2.4" resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" @@ -219,11 +116,11 @@ async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" -async@1.x, async@^1.4.0, async@^1.4.2, async@^1.5.0: +async@1.x, async@^1.4.0, async@^1.4.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.0: +async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" dependencies: @@ -233,10 +130,6 @@ asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" -atob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -290,14 +183,6 @@ babel-generator@^6.26.0: source-map "^0.5.7" trim-right "^1.0.1" -babel-helper-bindify-decorators@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" @@ -332,15 +217,6 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-helper-explode-class@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb" - dependencies: - babel-helper-bindify-decorators "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" @@ -424,55 +300,15 @@ babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" -babel-plugin-syntax-async-generators@^6.5.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" - -babel-plugin-syntax-class-constructor-call@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416" - -babel-plugin-syntax-class-properties@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - -babel-plugin-syntax-decorators@^6.13.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" - -babel-plugin-syntax-dynamic-import@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" - babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" -babel-plugin-syntax-export-extensions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721" - -babel-plugin-syntax-flow@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" - -babel-plugin-syntax-object-rest-spread@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" -babel-plugin-transform-async-generator-functions@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db" - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-generators "^6.5.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async-to-generator@^6.24.1: +babel-plugin-transform-async-to-generator@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" dependencies: @@ -480,33 +316,6 @@ babel-plugin-transform-async-to-generator@^6.22.0, babel-plugin-transform-async- babel-plugin-syntax-async-functions "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-class-constructor-call@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz#80dc285505ac067dcb8d6c65e2f6f11ab7765ef9" - dependencies: - babel-plugin-syntax-class-constructor-call "^6.18.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-class-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - dependencies: - babel-helper-function-name "^6.24.1" - babel-plugin-syntax-class-properties "^6.8.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-decorators@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d" - dependencies: - babel-helper-explode-class "^6.24.1" - babel-plugin-syntax-decorators "^6.13.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-types "^6.24.1" - babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" @@ -519,7 +328,7 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1: +babel-plugin-transform-es2015-block-scoping@^6.23.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" dependencies: @@ -529,7 +338,7 @@ babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es20 babel-types "^6.26.0" lodash "^4.17.4" -babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1: +babel-plugin-transform-es2015-classes@^6.23.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" dependencies: @@ -543,33 +352,33 @@ babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-cla babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: +babel-plugin-transform-es2015-computed-properties@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" dependencies: babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.0: +babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1: +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" dependencies: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0: +babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1: +babel-plugin-transform-es2015-function-name@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" dependencies: @@ -600,7 +409,7 @@ babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-e babel-template "^6.26.0" babel-types "^6.26.0" -babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" dependencies: @@ -608,7 +417,7 @@ babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-e babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: +babel-plugin-transform-es2015-modules-umd@^6.23.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" dependencies: @@ -616,14 +425,14 @@ babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015 babel-runtime "^6.22.0" babel-template "^6.24.1" -babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: +babel-plugin-transform-es2015-object-super@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" dependencies: babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" -babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015-parameters@^6.24.1: +babel-plugin-transform-es2015-parameters@^6.23.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" dependencies: @@ -634,7 +443,7 @@ babel-plugin-transform-es2015-parameters@^6.23.0, babel-plugin-transform-es2015- babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" dependencies: @@ -647,7 +456,7 @@ babel-plugin-transform-es2015-spread@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1: +babel-plugin-transform-es2015-sticky-regex@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" dependencies: @@ -661,13 +470,13 @@ babel-plugin-transform-es2015-template-literals@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0: +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1: +babel-plugin-transform-es2015-unicode-regex@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" dependencies: @@ -675,7 +484,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0, babel-plugin-transform-es20 babel-runtime "^6.22.0" regexpu-core "^2.0.0" -babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.24.1: +babel-plugin-transform-exponentiation-operator@^6.22.0: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" dependencies: @@ -683,28 +492,7 @@ babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-e babel-plugin-syntax-exponentiation-operator "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-export-extensions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653" - dependencies: - babel-plugin-syntax-export-extensions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-flow-strip-types@^6.8.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" - dependencies: - babel-plugin-syntax-flow "^6.18.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-object-rest-spread@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06" - dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.26.0" - -babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: +babel-plugin-transform-regenerator@^6.22.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" dependencies: @@ -752,63 +540,7 @@ babel-preset-env@^1.3.2: invariant "^2.2.2" semver "^5.3.0" -babel-preset-es2015@^6.9.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.24.1" - babel-plugin-transform-es2015-classes "^6.24.1" - babel-plugin-transform-es2015-computed-properties "^6.24.1" - babel-plugin-transform-es2015-destructuring "^6.22.0" - babel-plugin-transform-es2015-duplicate-keys "^6.24.1" - babel-plugin-transform-es2015-for-of "^6.22.0" - babel-plugin-transform-es2015-function-name "^6.24.1" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-plugin-transform-es2015-modules-systemjs "^6.24.1" - babel-plugin-transform-es2015-modules-umd "^6.24.1" - babel-plugin-transform-es2015-object-super "^6.24.1" - babel-plugin-transform-es2015-parameters "^6.24.1" - babel-plugin-transform-es2015-shorthand-properties "^6.24.1" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.24.1" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.22.0" - babel-plugin-transform-es2015-unicode-regex "^6.24.1" - babel-plugin-transform-regenerator "^6.24.1" - -babel-preset-stage-1@^6.5.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz#7692cd7dcd6849907e6ae4a0a85589cfb9e2bfb0" - dependencies: - babel-plugin-transform-class-constructor-call "^6.24.1" - babel-plugin-transform-export-extensions "^6.22.0" - babel-preset-stage-2 "^6.24.1" - -babel-preset-stage-2@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1" - dependencies: - babel-plugin-syntax-dynamic-import "^6.18.0" - babel-plugin-transform-class-properties "^6.24.1" - babel-plugin-transform-decorators "^6.24.1" - babel-preset-stage-3 "^6.24.1" - -babel-preset-stage-3@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395" - dependencies: - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-generator-functions "^6.24.1" - babel-plugin-transform-async-to-generator "^6.24.1" - babel-plugin-transform-exponentiation-operator "^6.24.1" - babel-plugin-transform-object-rest-spread "^6.22.0" - -babel-register@6.26.0, babel-register@^6.26.0, babel-register@^6.9.0: +babel-register@6.26.0, babel-register@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" dependencies: @@ -867,14 +599,10 @@ babelify@^7.3.0: babel-core "^6.0.14" object-assign "^4.0.0" -babylon@^6.17.3, babylon@^6.18.0: +babylon@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" -babylon@^7.0.0-beta.47: - version "7.0.0-beta.47" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.47.tgz#6d1fa44f0abec41ab7c780481e62fd9aafbdea80" - backoff@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" @@ -897,28 +625,12 @@ base64-js@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - bcrypt-pbkdf@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" dependencies: tweetnacl "^0.14.3" -big.js@^3.1.3: - version "3.2.0" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" - bignumber.js@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-5.0.0.tgz#fbce63f09776b3000a83185badcde525daf34833" @@ -927,10 +639,6 @@ bignumber.js@5.0.0: version "2.0.7" resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" -binaryextensions@2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.1.tgz#3209a51ca4a4ad541a3b8d3d6a6d5b83a2485935" - bindings@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" @@ -1017,29 +725,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -braces@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -1178,36 +863,6 @@ bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -cacheable-request@^2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" - dependencies: - clone-response "1.0.2" - get-stream "3.0.0" - http-cache-semantics "3.8.1" - keyv "3.0.0" - lowercase-keys "1.0.0" - normalize-url "2.0.1" - responselike "1.0.2" - -call-me-maybe@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" - camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" @@ -1216,10 +871,6 @@ camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - caniuse-lite@^1.0.30000844: version "1.0.30000852" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000852.tgz#8b7510cec030cac7842e52beca2bf292af65f935" @@ -1235,7 +886,7 @@ center-align@^0.1.1: align-text "^0.1.3" lazy-cache "^1.0.3" -chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -1245,26 +896,6 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f" - dependencies: - ansi-styles "~1.0.0" - has-color "~0.1.0" - strip-ansi "~0.1.0" - -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - charenc@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" @@ -1282,48 +913,6 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -cli-cursor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" - dependencies: - restore-cursor "^1.0.1" - -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - dependencies: - restore-cursor "^2.0.0" - -cli-spinners@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" - -cli-table@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" - dependencies: - colors "1.0.3" - -cli-truncate@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" - dependencies: - slice-ansi "0.0.4" - string-width "^1.0.1" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -1340,48 +929,10 @@ cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" -cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - -clone-response@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - dependencies: - mimic-response "^1.0.0" - -clone-stats@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - -clone@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - clone@^2.0.0, clone@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" -cloneable-readable@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" - dependencies: - inherits "^2.0.1" - process-nextick-args "^2.0.0" - readable-stream "^2.3.5" - co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -1397,31 +948,6 @@ coinstring@^2.0.0: bs58 "^2.0.1" create-hash "^1.1.1" -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0: - version "1.9.2" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" - dependencies: - color-name "1.1.1" - -color-name@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" - -colors@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - -colors@^1.1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.0.tgz#5f20c9fef6945cb1134260aab33bfbdc8295e04e" - combined-stream@1.0.6, combined-stream@~1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" @@ -1442,14 +968,6 @@ commander@~2.8.1: dependencies: graceful-readlink ">= 1.0.0" -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - -component-emitter@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1483,11 +1001,7 @@ cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - -core-js@^2.0.0, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0: +core-js@^2.4.0, core-js@^2.5.0: version "2.5.7" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" @@ -1547,24 +1061,6 @@ cross-fetch@^2.1.0, cross-fetch@^2.1.1: node-fetch "2.1.2" whatwg-fetch "2.0.4" -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - crypt@~0.0.1: version "0.0.2" resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" @@ -1589,35 +1085,23 @@ crypto-js@^3.1.4: version "3.1.8" resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" -dargs@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/dargs/-/dargs-5.1.0.tgz#ec7ea50c78564cd36c9d5ec18f66329fade27829" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" dependencies: assert-plus "^1.0.0" -date-fns@^1.27.2: - version "1.29.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" - -dateformat@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" - death@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" -debug@3.1.0, debug@^3.1.0: +debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: @@ -1689,10 +1173,6 @@ deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" -deep-extend@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f" - deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -1710,25 +1190,6 @@ define-properties@^1.1.2: foreach "^2.0.5" object-keys "^1.0.8" -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - defined@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" @@ -1756,10 +1217,6 @@ destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" -detect-conflict@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/detect-conflict/-/detect-conflict-1.0.1.tgz#088657a66a961c05019db7c4230883b1c6b4176e" - detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" @@ -1770,10 +1227,6 @@ diff@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" -diff@^3.3.1, diff@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -1782,20 +1235,13 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -dir-glob@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" - dependencies: - arrify "^1.0.1" - path-type "^3.0.0" - dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" -dotenv@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.0.0.tgz#24e37c041741c5f4b25324958ebbc34bca965935" +dotenv@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064" drbg.js@^1.0.1: version "1.0.1" @@ -1815,26 +1261,14 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" -editions@^1.3.3: - version "1.3.4" - resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" -ejs@^2.5.9: - version "2.6.1" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" - electron-to-chromium@^1.3.47: version "1.3.48" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz#d3b0d8593814044e092ece2108fc3ac9aea4b900" -elegant-spinner@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" - elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" @@ -1847,10 +1281,6 @@ elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -1867,37 +1297,18 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz#e34a6eaa790f62fccd71d93959f56b2b432db10a" - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.4.0" - tapable "^1.0.0" - -envinfo@^5.7.0: - version "5.10.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-5.10.0.tgz#503a9774ae15b93ea68bdfae2ccd6306624ea6df" - -errno@^0.1.3, errno@~0.1.1: +errno@~0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" dependencies: prr "~1.0.1" -error-ex@^1.2.0, error-ex@^1.3.1: +error-ex@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" dependencies: is-arrayish "^0.2.1" -error@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/error/-/error-7.0.2.tgz#a5f75fff4d9926126ddac0ea5dc38e689153cb02" - dependencies: - string-template "~0.2.1" - xtend "~4.0.0" - es-abstract@^1.5.0: version "1.12.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" @@ -1920,7 +1331,7 @@ escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1939,7 +1350,7 @@ esprima@2.7.x, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" -esprima@^4.0.0, esprima@~4.0.0: +esprima@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" @@ -2093,12 +1504,11 @@ ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0, ether ethereumjs-util "^5.0.0" merkle-patricia-tree "^2.1.2" -ethereumjs-testrpc-sc@6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.2.tgz#bd1d8306abb2d51481f3f01538fa71fb7fd44a4d" +ethereumjs-testrpc-sc@6.1.6: + version "6.1.6" + resolved "https://registry.yarnpkg.com/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.6.tgz#290595380b5182814564d4aa38f35b7788aab070" dependencies: source-map-support "^0.5.3" - webpack-cli "^2.0.9" ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: version "1.3.4" @@ -2161,7 +1571,7 @@ ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4: rustbn.js "~0.1.1" safe-buffer "^5.1.1" -ethereumjs-wallet@^0.6.0: +ethereumjs-wallet@0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz#82763b1697ee7a796be7155da9dfb49b2f98cfdb" dependencies: @@ -2198,52 +1608,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -exit-hook@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - dependencies: - is-posix-bracket "^0.1.0" - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - dependencies: - fill-range "^2.1.0" - -expand-tilde@^2.0.0, expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - dependencies: - homedir-polyfill "^1.0.1" - express@^4.14.0: version "4.16.3" resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" @@ -2279,50 +1643,10 @@ express@^4.14.0: utils-merge "1.0.1" vary "~1.1.2" -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - extend@~3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" -external-editor@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - dependencies: - chardet "^0.4.0" - iconv-lite "^0.4.17" - tmp "^0.0.33" - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - dependencies: - is-extglob "^1.0.0" - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -2341,17 +1665,6 @@ fast-deep-equal@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" -fast-glob@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.2.tgz#71723338ac9b4e0e2fff1d6748a2a13d5ed352bf" - dependencies: - "@mrmlnc/readdir-enhanced" "^2.2.1" - "@nodelib/fs.stat" "^1.0.1" - glob-parent "^3.1.0" - is-glob "^4.0.0" - merge2 "^1.2.1" - micromatch "^3.1.10" - fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -2372,19 +1685,6 @@ fetch-ponyfill@^4.0.0: dependencies: node-fetch "~1.7.1" -figures@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - dependencies: - escape-string-regexp "^1.0.5" - file-type@^3.8.0: version "3.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" @@ -2397,29 +1697,6 @@ file-type@^6.1.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - finalhandler@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" @@ -2439,38 +1716,12 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - dependencies: - locate-path "^2.0.0" - -first-chunk-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz#1bdecdb8e083c0664b91945581577a43a9f31d70" - dependencies: - readable-stream "^2.0.2" - -flow-parser@^0.*: - version "0.74.0" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.74.0.tgz#4acc8f55bdce5fa4da43c72c28ef8a9600ace87c" - for-each@^0.3.2, for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" dependencies: is-callable "^1.1.3" -for-in@^1.0.1, for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - dependencies: - for-in "^1.0.1" - foreach@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" @@ -2491,23 +1742,10 @@ forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - dependencies: - map-cache "^0.2.2" - fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" -from2@^2.1.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.0" - fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" @@ -2559,9 +1797,9 @@ functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" -ganache-cli@6.1.6: - version "6.1.6" - resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.6.tgz#99b500a25f571271a6978ef3f9c9c53e1a3854f0" +ganache-cli@6.1.8: + version "6.1.8" + resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.1.8.tgz#49a8a331683a9652183f82ef1378d17e1814fcd3" dependencies: source-map-support "^0.5.3" @@ -2569,10 +1807,6 @@ get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" -get-stream@3.0.0, get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" @@ -2580,9 +1814,9 @@ get-stream@^2.2.0: object-assign "^4.0.1" pinkie-promise "^2.0.0" -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" getpass@^0.1.1: version "0.1.7" @@ -2590,51 +1824,7 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -gh-got@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/gh-got/-/gh-got-6.0.0.tgz#d74353004c6ec466647520a10bd46f7299d268d0" - dependencies: - got "^7.0.0" - is-plain-obj "^1.1.0" - -github-username@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/github-username/-/github-username-4.1.0.tgz#cbe280041883206da4212ae9e4b5f169c30bf417" - dependencies: - gh-got "^6.0.0" - -glob-all@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.1.0.tgz#8913ddfb5ee1ac7812656241b03d5217c64b02ab" - dependencies: - glob "^7.0.5" - yargs "~1.2.6" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - dependencies: - is-glob "^2.0.0" - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-to-regexp@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" - -glob@7.1.2, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: +glob@7.1.2, glob@^7.0.0, glob@^7.0.5, glob@~7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -2655,24 +1845,6 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -global-modules@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - dependencies: - global-prefix "^1.0.1" - is-windows "^1.0.1" - resolve-dir "^1.0.0" - -global-prefix@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - dependencies: - expand-tilde "^2.0.2" - homedir-polyfill "^1.0.1" - ini "^1.3.4" - is-windows "^1.0.1" - which "^1.2.14" - global@~4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" @@ -2684,19 +1856,7 @@ globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" -globby@^8.0.0, globby@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.1.tgz#b5ad48b8aa80b35b814fc1281ecc851f1d2b5b50" - dependencies: - array-union "^1.0.1" - dir-glob "^2.0.0" - fast-glob "^2.0.2" - glob "^7.1.2" - ignore "^3.3.5" - pify "^3.0.0" - slash "^1.0.0" - -got@7.1.0, got@^7.0.0, got@^7.1.0: +got@7.1.0, got@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" dependencies: @@ -2715,29 +1875,7 @@ got@7.1.0, got@^7.0.0, got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -got@^8.3.1: - version "8.3.1" - resolved "https://registry.yarnpkg.com/got/-/got-8.3.1.tgz#093324403d4d955f5a16a7a8d39955d055ae10ed" - dependencies: - "@sindresorhus/is" "^0.7.0" - cacheable-request "^2.1.1" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - into-stream "^3.1.0" - is-retry-allowed "^1.1.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - mimic-response "^1.0.0" - p-cancelable "^0.4.0" - p-timeout "^2.0.1" - pify "^3.0.0" - safe-buffer "^5.1.1" - timed-out "^4.0.1" - url-parse-lax "^3.0.0" - url-to-options "^1.0.1" - -graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: +graceful-fs@^4.1.10, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -2745,12 +1883,6 @@ graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6 version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" -grouped-queue@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/grouped-queue/-/grouped-queue-0.3.3.tgz#c167d2a5319c5a0e0964ef6a25b7c2df8996c85c" - dependencies: - lodash "^4.17.2" - growl@1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" @@ -2782,10 +1914,6 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" -has-color@~0.1.0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f" - has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" @@ -2794,10 +1922,6 @@ has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - has-symbol-support-x@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" @@ -2808,33 +1932,6 @@ has-to-string-tag-x@^1.2.0: dependencies: has-symbol-support-x "^1.4.1" -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - has@^1.0.1, has@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -2881,20 +1978,10 @@ home-or-tmp@^2.0.0: os-homedir "^1.0.0" os-tmpdir "^1.0.1" -homedir-polyfill@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" - dependencies: - parse-passwd "^1.0.0" - hosted-git-info@^2.1.4: version "2.6.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz#23235b29ab230c576aab0d4f13fc046b0b038222" -http-cache-semantics@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - http-errors@1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" @@ -2929,7 +2016,7 @@ iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" -iconv-lite@0.4.23, iconv-lite@^0.4.17, iconv-lite@~0.4.13: +iconv-lite@0.4.23, iconv-lite@~0.4.13: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" dependencies: @@ -2939,35 +2026,10 @@ ieee754@^1.1.4: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" -ignore@^3.3.5: - version "3.3.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.8.tgz#3f8e9c35d38708a3a7e0e9abb6c73e7ee7707b2b" - immediate@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" -import-local@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" - dependencies: - pkg-dir "^2.0.0" - resolve-cwd "^2.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - dependencies: - repeating "^2.0.0" - -indent-string@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -2979,39 +2041,10 @@ inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, i version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" -ini@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - -inquirer@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-5.2.0.tgz#db350c2b73daca77ff1243962e9f22f099685726" - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.1.0" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^5.5.2" - string-width "^2.1.0" - strip-ansi "^4.0.0" - through "^2.3.6" - -interpret@^1.0.0, interpret@^1.1.0: +interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" -into-stream@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" - dependencies: - from2 "^2.1.1" - p-is-promise "^1.1.0" - invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -3026,18 +2059,6 @@ ipaddr.js@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.6.0.tgz#e3fa357b773da619f26e95f049d055c72796f86b" -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - dependencies: - kind-of "^6.0.0" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -3056,66 +2077,10 @@ is-callable@^1.1.1, is-callable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - dependencies: - kind-of "^6.0.0" - is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" @@ -3132,32 +2097,10 @@ is-fullwidth-code-point@^1.0.0: dependencies: number-is-nan "^1.0.0" -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - is-function@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - dependencies: - is-extglob "^1.0.0" - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" - dependencies: - is-extglob "^2.1.1" - is-hex-prefixed@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" @@ -3166,76 +2109,24 @@ is-natural-number@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - dependencies: - kind-of "^3.0.2" - -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - is-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" -is-observable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" - dependencies: - symbol-observable "^1.1.0" - -is-odd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" - dependencies: - is-number "^4.0.0" - -is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: +is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" -is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - dependencies: - isobject "^3.0.1" - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" dependencies: has "^1.0.1" -is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: +is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" -is-scoped@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-scoped/-/is-scoped-1.0.0.tgz#449ca98299e713038256289ecb2b540dc437cb30" - dependencies: - scoped-regex "^1.0.0" - is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -3252,36 +2143,18 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" -is-windows@^1.0.1, is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: +isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" -isbinaryfile@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621" - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -3305,14 +2178,6 @@ istanbul@^0.4.5: which "^1.1.1" wordwrap "^1.0.0" -istextorbinary@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.2.1.tgz#a5231a08ef6dd22b268d0895084cf8d58b5bec53" - dependencies: - binaryextensions "2" - editions "^1.3.3" - textextensions "2" - isurl@^1.0.0-alpha5: version "1.0.0" resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" @@ -3339,46 +2204,6 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" -jscodeshift@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.4.1.tgz#da91a1c2eccfa03a3387a21d39948e251ced444a" - dependencies: - async "^1.5.0" - babel-plugin-transform-flow-strip-types "^6.8.0" - babel-preset-es2015 "^6.9.0" - babel-preset-stage-1 "^6.5.0" - babel-register "^6.9.0" - babylon "^6.17.3" - colors "^1.1.2" - flow-parser "^0.*" - lodash "^4.13.1" - micromatch "^2.3.7" - node-dir "0.1.8" - nomnom "^1.8.1" - recast "^0.12.5" - temp "^0.8.1" - write-file-atomic "^1.2.0" - -jscodeshift@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.5.1.tgz#4af6a721648be8638ae1464a190342da52960c33" - dependencies: - babel-plugin-transform-flow-strip-types "^6.8.0" - babel-preset-es2015 "^6.9.0" - babel-preset-stage-1 "^6.5.0" - babel-register "^6.9.0" - babylon "^7.0.0-beta.47" - colors "^1.1.2" - flow-parser "^0.*" - lodash "^4.13.1" - micromatch "^2.3.7" - neo-async "^2.5.0" - node-dir "0.1.8" - nomnom "^1.8.1" - recast "^0.15.0" - temp "^0.8.1" - write-file-atomic "^1.2.0" - jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" @@ -3387,14 +2212,6 @@ jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - -json-parse-better-errors@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: version "3.7.3" resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.7.3.tgz#81dcabdb4f1ba5f79f99f04f560d20817908e4b5" @@ -3434,7 +2251,7 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" -json5@^0.5.0, json5@^0.5.1: +json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -3473,32 +2290,12 @@ keccakjs@^0.2.0, keccakjs@^0.2.1: browserify-sha3 "^0.0.1" sha3 "^1.1.0" -keyv@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" - dependencies: - json-buffer "3.0.0" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: +kind-of@^3.0.2: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: is-buffer "^1.1.5" -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - klaw@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" @@ -3570,53 +2367,6 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -listr-silent-renderer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" - -listr-update-renderer@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz#344d980da2ca2e8b145ba305908f32ae3f4cc8a7" - dependencies: - chalk "^1.1.3" - cli-truncate "^0.2.1" - elegant-spinner "^1.0.1" - figures "^1.7.0" - indent-string "^3.0.0" - log-symbols "^1.0.2" - log-update "^1.0.2" - strip-ansi "^3.0.1" - -listr-verbose-renderer@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" - dependencies: - chalk "^1.1.3" - cli-cursor "^1.0.2" - date-fns "^1.27.2" - figures "^1.7.0" - -listr@^0.14.1: - version "0.14.1" - resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.1.tgz#8a7afa4a7135cee4c921d128e0b7dfc6e522d43d" - dependencies: - "@samverschueren/stream-to-observable" "^0.3.0" - cli-truncate "^0.2.1" - figures "^1.7.0" - indent-string "^2.1.0" - is-observable "^1.1.0" - is-promise "^2.1.0" - is-stream "^1.1.0" - listr-silent-renderer "^1.1.1" - listr-update-renderer "^0.4.0" - listr-verbose-renderer "^0.4.0" - log-symbols "^1.0.2" - log-update "^1.0.2" - ora "^0.2.3" - p-map "^1.1.1" - rxjs "^6.1.0" - strip-ansi "^3.0.1" - load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -3627,35 +2377,11 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - -loader-utils@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd" - dependencies: - big.js "^3.1.3" - emojis-list "^2.0.0" - json5 "^0.5.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" -lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.3.0: +lodash@^4.17.10, lodash@^4.17.4: version "4.17.10" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" @@ -3663,25 +2389,6 @@ log-driver@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" -log-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" - dependencies: - chalk "^1.0.0" - -log-symbols@^2.1.0, log-symbols@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - dependencies: - chalk "^2.0.1" - -log-update@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" - dependencies: - ansi-escapes "^1.0.0" - cli-cursor "^1.0.2" - longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" @@ -3692,45 +2399,20 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0" -lowercase-keys@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" - lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" -lru-cache@^4.0.1: - version "4.1.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - ltgt@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" -make-dir@^1.0.0, make-dir@^1.1.0: +make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" dependencies: pify "^3.0.0" -map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - dependencies: - object-visit "^1.0.0" - -math-random@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" - md5.js@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" @@ -3750,36 +2432,6 @@ media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" -mem-fs-editor@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/mem-fs-editor/-/mem-fs-editor-4.0.2.tgz#55a79b1e824da631254c4c95ba6366602c77af90" - dependencies: - commondir "^1.0.1" - deep-extend "^0.5.1" - ejs "^2.5.9" - glob "^7.0.3" - globby "^8.0.0" - isbinaryfile "^3.0.2" - mkdirp "^0.5.0" - multimatch "^2.0.0" - rimraf "^2.2.8" - through2 "^2.0.0" - vinyl "^2.0.1" - -mem-fs@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/mem-fs/-/mem-fs-1.1.3.tgz#b8ae8d2e3fcb6f5d3f9165c12d4551a065d989cc" - dependencies: - through2 "^2.0.0" - vinyl "^1.1.0" - vinyl-file "^2.0.0" - -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - dependencies: - mimic-fn "^1.0.0" - memdown@^1.0.0: version "1.4.1" resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" @@ -3791,13 +2443,6 @@ memdown@^1.0.0: ltgt "~2.2.0" safe-buffer "~5.1.1" -memory-fs@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - memorystream@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" @@ -3806,10 +2451,6 @@ merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" -merge2@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.2.tgz#03212e3da8d86c4d8523cebd6318193414f94e34" - merkle-patricia-tree@^2.1.2: version "2.3.1" resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz#7d4e7263a9c85c1679187cad4a6d71f48d524c71" @@ -3827,42 +2468,6 @@ methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" -micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -micromatch@^3.1.10: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -3884,10 +2489,6 @@ mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - mimic-response@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e" @@ -3906,7 +2507,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -3916,10 +2517,6 @@ minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.1.0.tgz#99df657a52574c21c9057497df742790b2b4c0de" - minimist@^1.2.0, minimist@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -3928,20 +2525,13 @@ minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" -mixin-deep@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - mkdirp-promise@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: @@ -3978,19 +2568,6 @@ ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" -multimatch@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - mz@^2.6.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -4007,39 +2584,10 @@ nano-json-stream-parser@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" -nanomatch@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2" - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-odd "^2.0.0" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" -neo-async@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.1.tgz#acb909e327b1e87ec9ef15f41b8a269512ad41ee" - -nice-try@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" - -node-dir@0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.8.tgz#55fb8deb699070707fb67f91a460f0448294c77d" - node-fetch@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" @@ -4051,13 +2599,6 @@ node-fetch@~1.7.1: encoding "^0.1.11" is-stream "^1.0.1" -nomnom@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.8.1.tgz#2151f722472ba79e50a76fc125bb8c8f2e4dc2a7" - dependencies: - chalk "~0.4.0" - underscore "~1.6.0" - nopt@3.x: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" @@ -4073,26 +2614,6 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-url@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" - dependencies: - prepend-http "^2.0.0" - query-string "^5.0.1" - sort-keys "^2.0.0" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - dependencies: - path-key "^2.0.0" - number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -4112,14 +2633,6 @@ object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1 version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - object-inspect@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" @@ -4132,25 +2645,6 @@ object-keys@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - dependencies: - isobject "^3.0.0" - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - dependencies: - isobject "^3.0.1" - oboe@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" @@ -4169,16 +2663,6 @@ once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^1.0.0: - version "1.1.0" - resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - dependencies: - mimic-fn "^1.0.0" - optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -4197,15 +2681,6 @@ optionator@^0.8.1: type-check "~0.3.2" wordwrap "~1.0.0" -ora@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" - dependencies: - chalk "^1.1.1" - cli-cursor "^1.0.2" - cli-spinners "^0.1.2" - object-assign "^4.0.1" - original-require@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" @@ -4220,15 +2695,7 @@ os-locale@^1.4.0: dependencies: lcid "^1.0.0" -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -4236,64 +2703,16 @@ p-cancelable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" -p-cancelable@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" - -p-each-series@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71" - dependencies: - p-reduce "^1.0.0" - p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" -p-is-promise@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" - -p-lazy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-lazy/-/p-lazy-1.0.0.tgz#ec53c802f2ee3ac28f166cc82d0b2b02de27a835" - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - dependencies: - p-try "^1.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - dependencies: - p-limit "^1.1.0" - -p-map@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" - -p-reduce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" - p-timeout@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" dependencies: p-finally "^1.0.0" -p-timeout@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" - dependencies: - p-finally "^1.0.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - parse-asn1@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" @@ -4304,15 +2723,6 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - parse-headers@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" @@ -4326,47 +2736,20 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - parseurl@~1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" dependencies: pinkie-promise "^2.0.0" -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" @@ -4383,12 +2766,6 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - dependencies: - pify "^3.0.0" - pbkdf2@^3.0.3, pbkdf2@^3.0.9: version "3.0.16" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.16.tgz#7404208ec6b01b62d85bf83853a8064f8d9c2a5c" @@ -4429,16 +2806,6 @@ pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - dependencies: - find-up "^2.1.0" - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - precond@0.2: version "0.2.3" resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" @@ -4451,27 +2818,11 @@ prepend-http@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - -prettier@^1.12.1: - version "1.13.5" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.5.tgz#7ae2076998c8edce79d63834e9b7b09fead6bfd0" - -pretty-bytes@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9" - -private@^0.1.6, private@^0.1.8, private@~0.1.5: +private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" -process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: +process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" @@ -4497,10 +2848,6 @@ prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - public-encrypt@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.2.tgz#46eb9107206bf73489f8b85b69d91334c6610994" @@ -4537,14 +2884,6 @@ random-seed@0.3.0: dependencies: json-stringify-safe "^5.0.1" -randomatic@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.0.0.tgz#d35490030eb4f7578de292ce6dfb04a91a128923" - dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" @@ -4584,13 +2923,6 @@ raw-body@2.3.3: iconv-lite "0.4.23" unpipe "1.0.0" -read-chunk@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-2.1.0.tgz#6a04c0928005ed9d42e1a6ac5600e19cbc7ff655" - dependencies: - pify "^3.0.0" - safe-buffer "^5.1.1" - read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -4598,13 +2930,6 @@ read-pkg-up@^1.0.1: find-up "^1.0.0" read-pkg "^1.0.0" -read-pkg-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" - dependencies: - find-up "^2.0.0" - read-pkg "^3.0.0" - read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -4613,14 +2938,6 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - readable-stream@^1.0.33: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" @@ -4630,7 +2947,7 @@ readable-stream@^1.0.33: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5: +readable-stream@^2.0.0, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: @@ -4651,25 +2968,6 @@ readable-stream@~1.0.15: isarray "0.0.1" string_decoder "~0.10.x" -recast@^0.12.5: - version "0.12.9" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.12.9.tgz#e8e52bdb9691af462ccbd7c15d5a5113647a15f1" - dependencies: - ast-types "0.10.1" - core-js "^2.4.1" - esprima "~4.0.0" - private "~0.1.5" - source-map "~0.6.1" - -recast@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.15.0.tgz#b8c8bfdda245e1580c0a4d9fc25d4e820bf57208" - dependencies: - ast-types "0.11.5" - esprima "~4.0.0" - private "~0.1.5" - source-map "~0.6.1" - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" @@ -4692,19 +2990,6 @@ regenerator-transform@^0.10.0: babel-types "^6.19.0" private "^0.1.6" -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - dependencies: - is-equal-shallow "^0.1.3" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" @@ -4723,15 +3008,7 @@ regjsparser@^0.1.4: dependencies: jsesc "~0.5.0" -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - -repeat-string@^1.5.2, repeat-string@^1.6.1: +repeat-string@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" @@ -4741,14 +3018,6 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - -replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - req-cwd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-1.0.1.tgz#0d73aeae9266e697a78f7976019677e76acf0fff" @@ -4798,31 +3067,10 @@ require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - dependencies: - resolve-from "^3.0.0" - -resolve-dir@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - dependencies: - expand-tilde "^2.0.0" - global-modules "^1.0.0" - resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - resolve@1.1.x: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" @@ -4833,52 +3081,24 @@ resolve@^1.1.6, resolve@~1.7.1: dependencies: path-parse "^1.0.5" -responselike@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - dependencies: - lowercase-keys "^1.0.0" - -restore-cursor@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" - dependencies: - exit-hook "^1.0.0" - onetime "^1.0.0" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - resumer@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" dependencies: through "~2.3.4" -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.6.2: +rimraf@2, rimraf@^2.2.8: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: glob "^7.0.5" -rimraf@~2.2.6: - version "2.2.8" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" - ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -4890,28 +3110,10 @@ rlp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.0.0.tgz#9db384ff4b89a8f61563d92395d8625b18f3afb0" -run-async@^2.0.0, run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - dependencies: - is-promise "^2.1.0" - rustbn.js@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.1.2.tgz#979fa0f9562216dd667c9d2cd179ae5d13830eff" -rxjs@^5.5.2: - version "5.5.11" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.11.tgz#f733027ca43e3bec6b994473be4ab98ad43ced87" - dependencies: - symbol-observable "1.0.1" - -rxjs@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.2.0.tgz#e024d0e180b72756a83c2aaea8f25423751ba978" - dependencies: - tslib "^1.9.0" - safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -4920,20 +3122,10 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - dependencies: - ret "~0.1.10" - "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" -scoped-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-1.0.0.tgz#a346bb1acd4207ae70bd7c0c7ca9e566b6baddb8" - scrypt.js@0.2.0, scrypt.js@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" @@ -4976,7 +3168,7 @@ semaphore@>=1.0.1, semaphore@^1.0.3: version "1.1.0" resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0: +"semver@2 || 3 || 4 || 5", semver@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" @@ -5029,24 +3221,6 @@ set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" -set-value@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.1" - to-object-path "^0.3.0" - -set-value@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -5072,16 +3246,6 @@ sha3@^1.1.0: dependencies: nan "2.10.0" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - shelljs@^0.7.4: version "0.7.8" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" @@ -5090,18 +3254,6 @@ shelljs@^0.7.4: interpret "^1.0.0" rechoir "^0.6.2" -shelljs@^0.8.0: - version "0.8.2" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.2.tgz#345b7df7763f4c2340d584abb532c5f752ca9e35" - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - simple-concat@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" @@ -5118,41 +3270,6 @@ slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - -slide@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - sol-explore@^1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.2.tgz#43ae8c419fd3ac056a05f8a9d1fb1022cd41ecc2" @@ -5167,12 +3284,12 @@ solc@0.4.24, solc@^0.4.2: semver "^5.3.0" yargs "^4.7.1" -solidity-coverage@0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.5.tgz#81a2e3f8fc3e67f645c11796e5cbab0f8f5c355b" +solidity-coverage@0.5.11: + version "0.5.11" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.11.tgz#1ee45f6d98b75a615aadb8f9aa7db4a2b32258e7" dependencies: death "^1.1.0" - ethereumjs-testrpc-sc "6.1.2" + ethereumjs-testrpc-sc "6.1.6" istanbul "^0.4.5" keccakjs "^0.2.1" req-cwd "^1.0.1" @@ -5190,22 +3307,6 @@ solidity-parser-sc@0.4.11: pegjs "^0.10.0" yargs "^4.6.0" -sort-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" - dependencies: - is-plain-obj "^1.0.0" - -source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - source-map-support@^0.4.15: version "0.4.18" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" @@ -5219,10 +3320,6 @@ source-map-support@^0.5.3: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - source-map@^0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" @@ -5233,7 +3330,7 @@ source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" -source-map@^0.6.0, source-map@~0.6.1: +source-map@^0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -5265,12 +3362,6 @@ spdx-license-ids@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - dependencies: - extend-shallow "^3.0.0" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -5290,13 +3381,6 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - "statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" @@ -5309,10 +3393,6 @@ strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" -string-template@~0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" - string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -5321,13 +3401,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - string.prototype.trim@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" @@ -5346,11 +3419,10 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -stringifier@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/stringifier/-/stringifier-1.3.0.tgz#def18342f6933db0f2dbfc9aa02175b448c17959" +stringifier@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stringifier/-/stringifier-2.0.0.tgz#dd1718e0d67e5ee355861ccd4ba2fe0007539c26" dependencies: - core-js "^2.0.0" traverse "^0.6.6" type-name "^2.0.1" @@ -5360,43 +3432,18 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991" - -strip-bom-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz#f87db5ef2613f6968aa545abfe1ec728b6a829ca" - dependencies: - first-chunk-stream "^2.0.0" - strip-bom "^2.0.0" - strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" dependencies: is-utf8 "^0.2.0" -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - strip-dirs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" dependencies: is-natural-number "^4.0.1" -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - strip-hex-prefix@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" @@ -5419,12 +3466,6 @@ supports-color@^3.1.0: dependencies: has-flag "^1.0.0" -supports-color@^5.3.0, supports-color@^5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - dependencies: - has-flag "^3.0.0" - swarm-js@0.1.37: version "0.1.37" resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" @@ -5443,18 +3484,6 @@ swarm-js@0.1.37: tar.gz "^1.0.5" xhr-request-promise "^0.1.2" -symbol-observable@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" - -symbol-observable@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" - -tapable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2" - tape@^4.4.0, tape@^4.6.3, tape@^4.8.0: version "4.9.1" resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.1.tgz#1173d7337e040c76fbf42ec86fcabedc9b3805c9" @@ -5503,21 +3532,6 @@ tar@^2.1.1: fstream "^1.0.2" inherits "2" -temp@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.3.tgz#e0c6bc4d26b903124410e4fed81103014dfc1f59" - dependencies: - os-tmpdir "^1.0.0" - rimraf "~2.2.6" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - -textextensions@2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.2.0.tgz#38ac676151285b658654581987a0ce1a4490d286" - thenify-all@^1.0.0, thenify-all@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" @@ -5530,7 +3544,7 @@ thenify-all@^1.0.0, thenify-all@^1.6.0: dependencies: any-promise "^1.0.0" -through2@^2.0.0, through2@^2.0.3: +through2@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" dependencies: @@ -5545,12 +3559,6 @@ timed-out@^4.0.0, timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - dependencies: - os-tmpdir "~1.0.2" - to-buffer@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" @@ -5559,28 +3567,6 @@ to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - dependencies: - kind-of "^3.0.2" - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - tough-cookie@~2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" @@ -5607,27 +3593,23 @@ trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" -truffle-hdwallet-provider@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-0.0.5.tgz#6e3dc0fb607a40c8bf02312b9a6aa1ce49883902" +truffle-hdwallet-provider@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-0.0.6.tgz#775c677693a94d83a515815d7fd7f0a73f00c3e9" dependencies: bip39 "^2.2.0" - ethereumjs-wallet "^0.6.0" + ethereumjs-wallet "0.6.0" web3 "^0.18.2" web3-provider-engine "^14.0.5" -truffle@4.1.13: - version "4.1.13" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-4.1.13.tgz#bf27586988b4ff84563edfbf32b47941408a76ad" +truffle@4.1.14: + version "4.1.14" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-4.1.14.tgz#8d2c298e29abf9b1e486e44ff9faca6d34bb9030" dependencies: mocha "^4.1.0" original-require "1.0.1" solc "0.4.24" -tslib@^1.9.0: - version "1.9.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.2.tgz#8be0cc9a1f6dc7727c38deb16c2ebd1a2892988e" - tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -5693,19 +3675,6 @@ underscore@1.8.3: version "1.8.3" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" -underscore@~1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" - -union-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^0.4.3" - unorm@^1.3.3: version "1.4.1" resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300" @@ -5714,33 +3683,12 @@ unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -untildify@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.3.tgz#1e7b42b140bcfd922b22e70ca1265bfe3634c7c9" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" dependencies: prepend-http "^1.0.1" -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - dependencies: - prepend-http "^2.0.0" - url-set-query@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" @@ -5749,12 +3697,6 @@ url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" -use@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.0.tgz#14716bf03fdfefd03040aef58d8b4b85f3a7c544" - dependencies: - kind-of "^6.0.2" - utf8@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" @@ -5783,10 +3725,6 @@ uuid@^3.1.0: version "3.2.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" -v8-compile-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz#526492e35fc616864284700b7043e01baee09f0a" - validate-npm-package-license@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" @@ -5806,36 +3744,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -vinyl-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/vinyl-file/-/vinyl-file-2.0.0.tgz#a7ebf5ffbefda1b7d18d140fcb07b223efb6751a" - dependencies: - graceful-fs "^4.1.2" - pify "^2.3.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - strip-bom-stream "^2.0.0" - vinyl "^1.1.0" - -vinyl@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.1.0.tgz#021f9c2cf951d6b939943c89eb5ee5add4fd924c" - dependencies: - clone "^2.1.1" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - web3-bzz@1.0.0-beta.34: version "1.0.0-beta.34" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.34.tgz#068d37777ab65e5c60f8ec8b9a50cfe45277929c" @@ -6091,43 +3999,6 @@ web3@^0.18.2, web3@^0.18.4: web3-shh "1.0.0-beta.34" web3-utils "1.0.0-beta.34" -webpack-addons@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/webpack-addons/-/webpack-addons-1.1.5.tgz#2b178dfe873fb6e75e40a819fa5c26e4a9bc837a" - dependencies: - jscodeshift "^0.4.0" - -webpack-cli@^2.0.9: - version "2.1.5" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-2.1.5.tgz#3081fdeb2f205f0a54aa397986880b0c20a71f7a" - dependencies: - chalk "^2.4.1" - cross-spawn "^6.0.5" - diff "^3.5.0" - enhanced-resolve "^4.0.0" - envinfo "^5.7.0" - glob-all "^3.1.0" - global-modules "^1.0.0" - got "^8.3.1" - import-local "^1.0.0" - inquirer "^5.2.0" - interpret "^1.1.0" - jscodeshift "^0.5.0" - listr "^0.14.1" - loader-utils "^1.1.0" - lodash "^4.17.10" - log-symbols "^2.2.0" - mkdirp "^0.5.1" - p-each-series "^1.0.0" - p-lazy "^1.0.0" - prettier "^1.12.1" - supports-color "^5.4.0" - v8-compile-cache "^2.0.0" - webpack-addons "^1.1.5" - yargs "^11.1.0" - yeoman-environment "^2.1.1" - yeoman-generator "^2.0.5" - "websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": version "1.0.26" resolved "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" @@ -6145,11 +4016,7 @@ which-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - -which@^1.1.1, which@^1.2.14, which@^1.2.9: +which@^1.1.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" dependencies: @@ -6186,14 +4053,6 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -write-file-atomic@^1.2.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - slide "^1.1.5" - ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -6261,10 +4120,6 @@ yaeti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" @@ -6272,29 +4127,6 @@ yargs-parser@^2.4.1: camelcase "^3.0.0" lodash.assign "^4.0.6" -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - dependencies: - camelcase "^4.1.0" - -yargs@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" - yargs@^4.6.0, yargs@^4.7.1: version "4.8.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" @@ -6314,12 +4146,6 @@ yargs@^4.6.0, yargs@^4.7.1: y18n "^3.2.1" yargs-parser "^2.4.1" -yargs@~1.2.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-1.2.6.tgz#9c7b4a82fd5d595b2bf17ab6dcc43135432fe34b" - dependencies: - minimist "^0.1.0" - yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" @@ -6335,53 +4161,3 @@ yauzl@^2.4.2: dependencies: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" - -yeoman-environment@^2.0.5, yeoman-environment@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/yeoman-environment/-/yeoman-environment-2.2.0.tgz#6c0ee93a8d962a9f6dbc5ad4e90ae7ab34875393" - dependencies: - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^3.1.0" - diff "^3.3.1" - escape-string-regexp "^1.0.2" - globby "^8.0.1" - grouped-queue "^0.3.3" - inquirer "^5.2.0" - is-scoped "^1.0.0" - lodash "^4.17.10" - log-symbols "^2.1.0" - mem-fs "^1.1.0" - strip-ansi "^4.0.0" - text-table "^0.2.0" - untildify "^3.0.2" - -yeoman-generator@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/yeoman-generator/-/yeoman-generator-2.0.5.tgz#57b0b3474701293cc9ec965288f3400b00887c81" - dependencies: - async "^2.6.0" - chalk "^2.3.0" - cli-table "^0.3.1" - cross-spawn "^6.0.5" - dargs "^5.1.0" - dateformat "^3.0.3" - debug "^3.1.0" - detect-conflict "^1.0.0" - error "^7.0.2" - find-up "^2.1.0" - github-username "^4.0.0" - istextorbinary "^2.2.1" - lodash "^4.17.10" - make-dir "^1.1.0" - mem-fs-editor "^4.0.0" - minimist "^1.2.0" - pretty-bytes "^4.0.2" - read-chunk "^2.1.0" - read-pkg-up "^3.0.0" - rimraf "^2.6.2" - run-async "^2.0.0" - shelljs "^0.8.0" - text-table "^0.2.0" - through2 "^2.0.0" - yeoman-environment "^2.0.5"