From a4bd5061ca59ef3b4a1854797dd544fa161844b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 19 Jul 2018 17:38:18 +0200 Subject: [PATCH 01/90] fix roundedDiv method --- contracts/generic/SafeMath.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/generic/SafeMath.sol b/contracts/generic/SafeMath.sol index 0d7f0d39..5ce806fb 100644 --- a/contracts/generic/SafeMath.sol +++ b/contracts/generic/SafeMath.sol @@ -36,7 +36,7 @@ library SafeMath { function roundedDiv(uint a, uint b) internal pure returns (uint256) { require(b > 0, "div by 0"); // Solidity automatically throws for div by 0 but require to emit reason uint256 z = a / b; - if (a % b >= b / 2) { + if (a % b * 2 >= b) { z++; // no need for safe add b/c it can happen only if we divided the input } return z; From 09d3ba90ee78fd9f7e302cd2599739a27a474d62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 19 Jul 2018 18:15:57 +0200 Subject: [PATCH 02/90] use mul to protect from overflow in roundedDiv --- contracts/generic/SafeMath.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/generic/SafeMath.sol b/contracts/generic/SafeMath.sol index 5ce806fb..a2b020c4 100644 --- a/contracts/generic/SafeMath.sol +++ b/contracts/generic/SafeMath.sol @@ -36,7 +36,7 @@ library SafeMath { function roundedDiv(uint a, uint b) internal pure returns (uint256) { require(b > 0, "div by 0"); // Solidity automatically throws for div by 0 but require to emit reason uint256 z = a / b; - if (a % b * 2 >= b) { + if (mul(a % b, 2) >= b) { // use mul to protect from overflow z++; // no need for safe add b/c it can happen only if we divided the input } return z; From f980b4cbb7984a7580f3ddc054aebebf71b112d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 20 Jul 2018 15:13:31 +0200 Subject: [PATCH 03/90] add test wrapper for SafeMath, add tests for roundedDiv --- .../localTest/localTest_initialSetup.sol | 6 +++- contracts/test/SafeMathTester.sol | 33 +++++++++++++++++++ migrations/1000_initialSetup.js | 4 ++- migrations/14_deploy_SafeMathTester.js | 5 +++ test/safeMath.js | 33 ++++++++++++++++++- 5 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 contracts/test/SafeMathTester.sol create mode 100644 migrations/14_deploy_SafeMathTester.js diff --git a/contracts/SB_scripts/localTest/localTest_initialSetup.sol b/contracts/SB_scripts/localTest/localTest_initialSetup.sol index 46f6364e..556e82c6 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/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/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/test/safeMath.js b/test/safeMath.js index cbbf7a90..c26ebb3e 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,33 @@ 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); + }); }); From 968f0e9f648b9f224bbf92af82043a0f886f4035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 20 Jul 2018 15:37:04 +0200 Subject: [PATCH 04/90] proper roundedDiv without possible overflow, simplify div operations --- contracts/generic/SafeMath.sol | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/contracts/generic/SafeMath.sol b/contracts/generic/SafeMath.sol index a2b020c4..aec1a2f4 100644 --- a/contracts/generic/SafeMath.sol +++ b/contracts/generic/SafeMath.sol @@ -4,6 +4,7 @@ TODO: check against ds-math: https://blog.dapphub.com/ds-math/ TODO: move roundedDiv to a sep lib? (eg. Math.sol) + TODO: more unit tests! */ pragma solidity 0.4.24; @@ -33,22 +34,16 @@ library SafeMath { return c; } - function roundedDiv(uint a, uint b) internal pure returns (uint256) { + // Division, round to nearest integer, round half up + function roundedDiv(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "div by 0"); // Solidity automatically throws for div by 0 but require to emit reason - uint256 z = a / b; - if (mul(a % b, 2) >= b) { // use mul to protect from overflow - z++; // no need for safe add b/c it can happen only if we divided the input - } - return z; + uint256 halfB = (b % 2 == 0) ? (b / 2) : (b / 2 + 1); + return (a % b >= halfB) ? (a / b + 1) : (a / b); } - // Always rounds up - function ceilDiv(uint a, uint b) internal pure returns (uint256) { + // Division, always rounds up + function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "div by 0"); // Solidity automatically throws for div by 0 but require to emit reason - uint256 z = a / b; - if (a % b != 0) { - z++; // no need for safe add b/c it can happen only if we divided the input - } - return z; + return (a % b != 0) ? (a / b + 1) : (a / b); } } From a9987a509a337ef60d537773de9381b9a981ee65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 20 Jul 2018 17:26:29 +0200 Subject: [PATCH 05/90] add test case for division by zero --- test/safeMath.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/safeMath.js b/test/safeMath.js index c26ebb3e..43e6143e 100644 --- a/test/safeMath.js +++ b/test/safeMath.js @@ -79,4 +79,14 @@ contract("SafeMath", () => { 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)); + }); }); From 94bbc7b197306e15a037efaec1a764baabdef9b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 20 Jul 2018 17:55:10 +0200 Subject: [PATCH 06/90] fix typo in require in Locker.transferNotification --- contracts/Locker.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Locker.sol b/contracts/Locker.sol index 8668ec41..01ec2a3f 100644 --- a/contracts/Locker.sol +++ b/contracts/Locker.sol @@ -104,7 +104,7 @@ 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 From a46a9e9f80b56435862e9f1b06d0ec8f9493a1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 20 Jul 2018 18:02:12 +0200 Subject: [PATCH 07/90] remove unused return value from Locker._createLock --- contracts/Locker.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/Locker.sol b/contracts/Locker.sol index 01ec2a3f..c560ca29 100644 --- a/contracts/Locker.sol +++ b/contracts/Locker.sol @@ -215,7 +215,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 +225,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 From ab181f2cb407aa1e44bcc995125821eefcba9846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 23 Jul 2018 12:44:31 +0200 Subject: [PATCH 08/90] fix misleading comment --- contracts/Locker.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Locker.sol b/contracts/Locker.sol index c560ca29..1ee29b92 100644 --- a/contracts/Locker.sol +++ b/contracts/Locker.sol @@ -146,7 +146,7 @@ contract Locker is Restricted, TokenReceiver { } - // returns 20 lock products starting from some offset + // returns CHUNK_SIZE lock products starting from some offset // 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++) { From 2adcd2d77787a42fc45e95bae72137aef76ff0e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 23 Jul 2018 13:37:51 +0200 Subject: [PATCH 09/90] remove redundant check for lockProductId --- contracts/Locker.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/Locker.sol b/contracts/Locker.sol index 1ee29b92..f2cb8984 100644 --- a/contracts/Locker.sol +++ b/contracts/Locker.sol @@ -106,7 +106,6 @@ contract Locker is Restricted, TokenReceiver { // next line would revert but require to emit reason: 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 From 70daaa0e8bc1ba532938ddb8fb75f156eef7a6cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 23 Jul 2018 13:44:32 +0200 Subject: [PATCH 10/90] make types consistent in chunksize and related loops --- contracts/Locker.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/Locker.sol b/contracts/Locker.sol index f2cb8984..be7f1675 100644 --- a/contracts/Locker.sol +++ b/contracts/Locker.sol @@ -25,7 +25,7 @@ contract Locker is Restricted, TokenReceiver { using SafeMath for uint256; - uint public constant CHUNK_SIZE = 100; + uint16 public constant CHUNK_SIZE = 100; event NewLockProduct(uint32 indexed lockProductId, uint32 perTermInterest, uint32 durationInSecs, uint32 minimumLockAmount, bool isActive); @@ -148,7 +148,7 @@ contract Locker is Restricted, TokenReceiver { // returns CHUNK_SIZE lock products starting from some offset // 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++) { + for (uint16 i = 0; i < CHUNK_SIZE; i++) { if (offset + i >= lockProducts.length) { break; } From 72cdf39798a2989d79156ae94df1ee97547f6120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 23 Jul 2018 15:29:14 +0200 Subject: [PATCH 11/90] remove dummy return values from increase/decrease-approval, merge _increaseApproval into increaseApproval --- contracts/generic/AugmintToken.sol | 13 ++++--------- contracts/interfaces/AugmintTokenInterface.sol | 4 ++-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/contracts/generic/AugmintToken.sol b/contracts/generic/AugmintToken.sol index 89a0cd9e..07131412 100644 --- a/contracts/generic/AugmintToken.sol +++ b/contracts/generic/AugmintToken.sol @@ -67,11 +67,12 @@ 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 { + allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue); + emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); } - function decreaseApproval(address _spender, uint _subtractedValue) external returns (bool) { + function decreaseApproval(address _spender, uint _subtractedValue) external { uint oldValue = allowed[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowed[msg.sender][_spender] = 0; @@ -79,7 +80,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,11 +188,6 @@ 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"); 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; From a36e5cf57924b3972ffb8b89bb9b03a142ba3cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 26 Jul 2018 14:01:35 +0200 Subject: [PATCH 12/90] use abi.encodeWithSignature for delegatecall --- contracts/generic/MultiSig.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/generic/MultiSig.sol b/contracts/generic/MultiSig.sol index e6c1634d..f26d865a 100644 --- a/contracts/generic/MultiSig.sol +++ b/contracts/generic/MultiSig.sol @@ -94,7 +94,7 @@ contract MultiSig { 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(abi.encodeWithSignature("execute(address)", scriptAddress))) { script.state = ScriptState.Done; result = true; } else { From cfcf761dfc5f84b4df933bd1ba9fa93ae3775787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 26 Jul 2018 14:06:12 +0200 Subject: [PATCH 13/90] limit gas amount passed to delegatecall --- contracts/generic/MultiSig.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/generic/MultiSig.sol b/contracts/generic/MultiSig.sol index f26d865a..a3d5ae67 100644 --- a/contracts/generic/MultiSig.sol +++ b/contracts/generic/MultiSig.sol @@ -94,7 +94,9 @@ contract MultiSig { script.state = ScriptState.Failed; // passing scriptAddress to allow called script access its own public fx-s if needed - if (scriptAddress.delegatecall(abi.encodeWithSignature("execute(address)", scriptAddress))) { + // TODO: figure out exactly how much gas we want to retain from delegatecall + if (scriptAddress.delegatecall.gas(gasleft() - 10000) + (abi.encodeWithSignature("execute(address)", scriptAddress))) { script.state = ScriptState.Done; result = true; } else { From 8dde264768cb6edad6fb0a28c608c93210621e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 27 Jul 2018 13:27:53 +0200 Subject: [PATCH 14/90] set gas amount to be retained from delegatecall --- contracts/generic/MultiSig.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/generic/MultiSig.sol b/contracts/generic/MultiSig.sol index a3d5ae67..b8fb9895 100644 --- a/contracts/generic/MultiSig.sol +++ b/contracts/generic/MultiSig.sol @@ -94,8 +94,7 @@ contract MultiSig { script.state = ScriptState.Failed; // passing scriptAddress to allow called script access its own public fx-s if needed - // TODO: figure out exactly how much gas we want to retain from delegatecall - if (scriptAddress.delegatecall.gas(gasleft() - 10000) + if (scriptAddress.delegatecall.gas(gasleft() - 23000) (abi.encodeWithSignature("execute(address)", scriptAddress))) { script.state = ScriptState.Done; result = true; From 7c96313f5b949e9997c00e6094812ccfc31e86a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 27 Jul 2018 15:17:40 +0200 Subject: [PATCH 15/90] remove unnecessary parts (no need to set status preemptively, as we now retain enough gas to set it properly after we have the result) --- contracts/generic/MultiSig.sol | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/contracts/generic/MultiSig.sol b/contracts/generic/MultiSig.sol index b8fb9895..00dcd16c 100644 --- a/contracts/generic/MultiSig.sol +++ b/contracts/generic/MultiSig.sol @@ -86,19 +86,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.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); From 42bf9f9f90f4ea34cbd8c648a4f43897f57abcb8 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 30 Jul 2018 02:52:54 +0000 Subject: [PATCH 16/90] chore(package): update truffle-hdwallet-provider to version 0.0.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index df42c116..5b1b6976 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "solidity-coverage": "0.5.5", "stringifier": "1.3.0", "truffle": "4.1.13", - "truffle-hdwallet-provider": "0.0.5", + "truffle-hdwallet-provider": "0.0.6", "web3v1": "npm:web3@1.0.0-beta.34" }, "greenkeeper": { From f61fb91ac040bbf1e6c3d23c9d81fef1a597ae18 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Mon, 30 Jul 2018 02:55:20 +0000 Subject: [PATCH 17/90] chore(package): update lockfile https://npm.im/greenkeeper-lockfile --- yarn.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6b9a3c00..afa71c71 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2161,7 +2161,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: @@ -5607,12 +5607,12 @@ 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" From 9fbf3f0d668b20f21b725fea6055180b77318407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 30 Jul 2018 14:26:56 +0200 Subject: [PATCH 18/90] optimize: avoid redundant lookups --- contracts/generic/AugmintToken.sol | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/contracts/generic/AugmintToken.sol b/contracts/generic/AugmintToken.sol index 07131412..9b8bae29 100644 --- a/contracts/generic/AugmintToken.sol +++ b/contracts/generic/AugmintToken.sol @@ -68,8 +68,10 @@ contract AugmintToken is AugmintTokenInterface { 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 { - allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue); - emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); + 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 { From 8a1bd05020482086e1d3924df7874f7dbf180d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 30 Jul 2018 14:36:05 +0200 Subject: [PATCH 19/90] add check for missing input parameter to increase/decrease approval methods too --- contracts/generic/AugmintToken.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/generic/AugmintToken.sol b/contracts/generic/AugmintToken.sol index 9b8bae29..98840b38 100644 --- a/contracts/generic/AugmintToken.sol +++ b/contracts/generic/AugmintToken.sol @@ -68,6 +68,7 @@ contract AugmintToken is AugmintTokenInterface { to use this function to avoid 2 calls (and wait until the first transaction is mined) Based on MonolithDAO Token.sol */ function increaseApproval(address _spender, uint _addedValue) external { + require(_spender != 0x0, "spender must be set"); mapping (address => uint256) allowances = allowed[msg.sender]; uint newValue = allowances[_spender].add(_addedValue); allowances[_spender] = newValue; @@ -75,6 +76,7 @@ contract AugmintToken is AugmintTokenInterface { } 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; From 4b17d88650a4d311db02c691715bc3d8f61d1981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 31 Jul 2018 12:43:44 +0200 Subject: [PATCH 20/90] chunkSize parameter in Locker --- contracts/Locker.sol | 48 +++++++++++++++++++++----------------------- test/locker.js | 29 +++++++++++--------------- 2 files changed, 35 insertions(+), 42 deletions(-) diff --git a/contracts/Locker.sol b/contracts/Locker.sol index be7f1675..d399a27c 100644 --- a/contracts/Locker.sol +++ b/contracts/Locker.sol @@ -25,10 +25,8 @@ contract Locker is Restricted, TokenReceiver { using SafeMath for uint256; - uint16 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 @@ -140,24 +135,25 @@ contract Locker is Restricted, TokenReceiver { } function getLockProductCount() external view returns (uint) { - return lockProducts.length; - } - // returns CHUNK_SIZE 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 (uint16 i = 0; i < CHUNK_SIZE; i++) { + function getLockProducts(uint offset, uint16 chunkSize) + external view returns (uint[5][]) { + uint[5][] memory response = new uint[5][](chunkSize); + for (uint16 i = 0; i < chunkSize; i++) { if (offset + i >= lockProducts.length) { break; } LockProduct storage lockProduct = lockProducts[offset + i]; - response[i] = [ lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount, + response[i] = [lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount, monetarySupervisor.getMaxLockAmount(lockProduct.minimumLockAmount, lockProduct.perTermInterest), lockProduct.isActive ? 1 : 0 ]; } + return response; } function getLockCount() external view returns (uint) { @@ -168,14 +164,15 @@ 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[8][] memory response = new uint[8][](chunkSize); + for (uint16 i = 0; i < chunkSize; i++) { if (offset + i >= locks.length) { break; } Lock storage lock = locks[offset + i]; @@ -184,19 +181,20 @@ contract Locker is Restricted, TokenReceiver { 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]; + 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[7][] memory response = new uint[7][](chunkSize); uint[] storage locksForAddress = accountLocks[lockOwner]; - for (uint16 i = 0; i < CHUNK_SIZE; i++) { - + for (uint16 i = 0; i < chunkSize; i++) { if (offset + i >= locksForAddress.length) { break; } Lock storage lock = locks[locksForAddress[offset + i]]; @@ -204,9 +202,10 @@ contract Locker is Restricted, TokenReceiver { 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] = [locksForAddress[offset + 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) { @@ -232,5 +231,4 @@ contract Locker is Restricted, TokenReceiver { emit NewLock(lockOwner, lockId, amountToLock, interestEarned, lockedUntil, lockProduct.perTermInterest, lockProduct.durationInSecs); } - } diff --git a/test/locker.js b/test/locker.js index 4ec71b61..af8da404 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,11 +27,8 @@ 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.issueToReserve(50000), monetarySupervisor.setLtdParams( ltdParams.lockDifferenceLimit, ltdParams.loanDifferenceLimit, @@ -95,14 +92,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 +119,15 @@ 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: + // getLockProducts should return a CHUNK_SIZE element array: assert.isArray(products); 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,7 +409,7 @@ 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); @@ -471,7 +466,7 @@ 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); @@ -517,7 +512,7 @@ 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); From 3b7e94d03f4e49d78493b0c634ef354ebc7fdcce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 31 Jul 2018 13:03:46 +0200 Subject: [PATCH 21/90] fix bug in setLoanProductActiveState --- contracts/LoanManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/LoanManager.sol b/contracts/LoanManager.sol index f0d907d6..6f450f06 100644 --- a/contracts/LoanManager.sol +++ b/contracts/LoanManager.sol @@ -91,7 +91,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); } From 02a2bbb4268af6fd61d3349dd4bd44065e5920a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 31 Jul 2018 13:06:16 +0200 Subject: [PATCH 22/90] remove unused return variable names --- contracts/LoanManager.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/LoanManager.sol b/contracts/LoanManager.sol index 6f450f06..22056759 100644 --- a/contracts/LoanManager.sol +++ b/contracts/LoanManager.sol @@ -208,7 +208,7 @@ contract LoanManager is Restricted { emit SystemContractsChanged(newRatesContract, newMonetarySupervisor); } - function getProductCount() external view returns (uint ct) { + function getProductCount() external view returns (uint) { return products.length; } @@ -228,7 +228,7 @@ contract LoanManager is Restricted { } } - function getLoanCount() external view returns (uint ct) { + function getLoanCount() external view returns (uint) { return loans.length; } From 050cda1711abeeb941fd71a796fa496880a2830a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 31 Jul 2018 13:19:47 +0200 Subject: [PATCH 23/90] fix require for valid loanId-s in collect() --- contracts/LoanManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/LoanManager.sol b/contracts/LoanManager.sol index 22056759..82f3d810 100644 --- a/contracts/LoanManager.sol +++ b/contracts/LoanManager.sol @@ -150,7 +150,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"); From 95ce068243c5e853e887c4e916511941c8ea6a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 31 Jul 2018 16:02:13 +0200 Subject: [PATCH 24/90] chunkSize parameter in LoanManager --- contracts/LoanManager.sol | 42 +++++++++++++++++---------------- test/helpers/loanTestHelpers.js | 13 +++------- test/loanCollection.js | 2 +- test/loanManager.js | 6 +++-- test/loans.js | 12 ++++++---- 5 files changed, 38 insertions(+), 37 deletions(-) diff --git a/contracts/LoanManager.sol b/contracts/LoanManager.sol index f0d907d6..730a87a4 100644 --- a/contracts/LoanManager.sol +++ b/contracts/LoanManager.sol @@ -19,8 +19,6 @@ import "./MonetarySupervisor.sol"; contract LoanManager is Restricted { 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 { @@ -212,56 +210,61 @@ contract LoanManager is Restricted { 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++) { + function getProducts(uint offset, uint16 chunkSize) + external view returns (uint[8][]) { + uint[8][] memory response = new uint[8][](chunkSize); + for (uint16 i = 0; i < chunkSize; 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 ]; + product.collateralRatio, product.defaultingFeePt, + monetarySupervisor.getMaxLoanAmount(product.minDisbursedAmount), product.isActive ? 1 : 0 ]; } + return response; } function getLoanCount() external view returns (uint ct) { return loans.length; } - /* returns CHUNK_SIZE loans starting from some offset. Loans data encoded as: + /* returns loans starting from some . 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++) { + function getLoans(uint offset, uint16 chunkSize) + external view returns (uint[10][]) { + uint[10][] memory response = new uint[10][](chunkSize); + for (uint16 i = 0; i < chunkSize; i++) { if (offset + i >= loans.length) { break; } response[i] = getLoanTuple(offset + 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[10][] memory response = new uint[10][](chunkSize); uint[] storage loansForAddress = accountLoans[borrower]; - for (uint16 i = 0; i < CHUNK_SIZE; i++) { - + for (uint16 i = 0; i < chunkSize; i++) { if (offset + i >= loansForAddress.length) { break; } response[i] = getLoanTuple(loansForAddress[offset + i]); } + return response; } function getLoanTuple(uint loanId) public view returns (uint[10] result) { @@ -275,10 +278,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 +320,4 @@ contract LoanManager is Restricted { emit LoanRepayed(loanId, loan.borrower); } - } diff --git a/test/helpers/loanTestHelpers.js b/test/helpers/loanTestHelpers.js index 6b34f58a..a1db1614 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.equal(products.length, chunkSize); const result = []; products.map(prod => { const [ @@ -347,7 +341,6 @@ async function getProductsInfo(offset) { /* parse array returned by getLoans & getLoansForAddress */ function parseLoansInfo(loans) { - assert.equal(loans.length, CHUNK_SIZE); const result = []; loans.map(loan => { const [ diff --git a/test/loanCollection.js b/test/loanCollection.js index 544c689f..e0dab245 100644 --- a/test/loanCollection.js +++ b/test/loanCollection.js @@ -35,7 +35,7 @@ contract("Loans collection tests", accounts => { await loanManager.addLoanProduct(1, 990000, 1200000, 2000, 50000, true); // moreCoverage const [newProducts] = await Promise.all([ - loanTestHelpers.getProductsInfo(prodCount), + loanTestHelpers.getProductsInfo(prodCount, 10), tokenTestHelpers.withdrawFromReserve(accounts[0], 1000000000) ]); [ diff --git a/test/loanManager.js b/test/loanManager.js index 15169bce..39da02d3 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]; diff --git a/test/loans.js b/test/loans.js index d2b9a6cb..7c612cc8 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() { @@ -43,7 +44,7 @@ contract("Loans tests", accounts => { await loanManager.addLoanProduct(60, 990000, 1200000, 2000, 50000, true); // moreCoverage const [newProducts] = await Promise.all([ - loanTestHelpers.getProductsInfo(prodCount), + loanTestHelpers.getProductsInfo(prodCount, CHUNK_SIZE), tokenTestHelpers.withdrawFromReserve(accounts[0], 1000000000) ]); @@ -248,9 +249,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, CHUNK_SIZE); + const loanInfo = loanTestHelpers.parseLoansInfo(loansArray); assert.equal(loanInfo.length, 2); // offset was from first loan added const loan1Actual = loanInfo[0]; @@ -290,7 +292,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, CHUNK_SIZE); + const loanInfo = loanTestHelpers.parseLoansInfo(loansArray); assert.equal(loanInfo.length, 2); // offset was from first loan added for account From 1ef02eb19c5e6c01165f778c1a20373a960306a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 2 Aug 2018 12:37:09 +0200 Subject: [PATCH 25/90] remove unused method getLoanToDepositRatio --- contracts/MonetarySupervisor.sol | 4 ---- 1 file changed, 4 deletions(-) diff --git a/contracts/MonetarySupervisor.sol b/contracts/MonetarySupervisor.sol index 0d2e785f..c1a57e3c 100644 --- a/contracts/MonetarySupervisor.sol +++ b/contracts/MonetarySupervisor.sol @@ -183,10 +183,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) { From 1a520213afcd0a0ccefc954812898137425778f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 2 Aug 2018 12:48:54 +0200 Subject: [PATCH 26/90] loanmanager implements TokenReceiver interface --- contracts/LoanManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/LoanManager.sol b/contracts/LoanManager.sol index 82f3d810..c2fda8d0 100644 --- a/contracts/LoanManager.sol +++ b/contracts/LoanManager.sol @@ -16,7 +16,7 @@ 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; From 47fa9473d384d3a0c3a409bd6c420852982010dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 2 Aug 2018 16:00:17 +0200 Subject: [PATCH 27/90] extend test for setLoanProductActiveState (actually check the new status) --- test/loanManager.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/loanManager.js b/test/loanManager.js index 15169bce..1d1d0992 100644 --- a/test/loanManager.js +++ b/test/loanManager.js @@ -140,9 +140,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 +154,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() { From 52860ce4ddd5f21c9bdc2872f569629d90e103b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 3 Aug 2018 16:13:22 +0200 Subject: [PATCH 28/90] transferFrom deducts the fee from the allowed amount (fixes some fee problems, especially with zero amount transfers) --- contracts/generic/AugmintToken.sol | 16 ++++++------ test/helpers/tokenTestHelpers.js | 7 ++++-- test/tokenTransferFrom.js | 39 ++++++++++++++++++------------ 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/contracts/generic/AugmintToken.sol b/contracts/generic/AugmintToken.sol index 98840b38..d1484103 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; @@ -193,21 +194,21 @@ contract AugmintToken is AugmintTokenInterface { } 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); + + require(balances[from] >= amountWithFee, "balance must >= amount + fee"); + require(allowed[from][msg.sender] >= amountWithFee, "allowance must be >= amount + 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); + _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); } @@ -229,5 +230,4 @@ contract AugmintToken is AugmintTokenInterface { emit AugmintTransfer(from, to, transferAmount, narrative, fee); } - } diff --git a/test/helpers/tokenTestHelpers.js b/test/helpers/tokenTestHelpers.js index 7547cfb5..77030b77 100644 --- a/test/helpers/tokenTestHelpers.js +++ b/test/helpers/tokenTestHelpers.js @@ -135,6 +135,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 +173,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/tokenTransferFrom.js b/test/tokenTransferFrom.js index 9a7025a4..2ee6f32c 100644 --- a/test/tokenTransferFrom.js +++ b/test/tokenTransferFrom.js @@ -17,26 +17,33 @@ contract("TransferFrom AugmintToken tests", accounts => { }); 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() { From 1c16e04695263763da39a56d8464ae4a9d423d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 6 Aug 2018 13:55:18 +0200 Subject: [PATCH 29/90] improve comment and message --- contracts/generic/AugmintToken.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/generic/AugmintToken.sol b/contracts/generic/AugmintToken.sol index d1484103..267f968f 100644 --- a/contracts/generic/AugmintToken.sol +++ b/contracts/generic/AugmintToken.sol @@ -197,11 +197,11 @@ contract AugmintToken is AugmintTokenInterface { uint fee = feeAccount.calculateTransferFee(from, to, amount); uint amountWithFee = amount.add(fee); - require(balances[from] >= amountWithFee, "balance must >= amount + fee"); + /* NB: fee is deducted from owner, so transferFrom could fail + if amount + fee is not available on owner balance, or allowance */ + require(balances[from] >= amountWithFee, "balance must be >= amount + fee"); require(allowed[from][msg.sender] >= amountWithFee, "allowance must be >= amount + fee"); - /* 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, fee); allowed[from][msg.sender] = allowed[from][msg.sender].sub(amountWithFee); From 0282e40fb83646d08ee80c9111d8cadee1d65857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 6 Aug 2018 14:17:25 +0200 Subject: [PATCH 30/90] fix lint warnings (whitespaces only) --- contracts/MonetarySupervisor.sol | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/contracts/MonetarySupervisor.sol b/contracts/MonetarySupervisor.sol index c1a57e3c..52ca80de 100644 --- a/contracts/MonetarySupervisor.sol +++ b/contracts/MonetarySupervisor.sol @@ -63,8 +63,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; @@ -118,16 +118,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 +140,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 +150,6 @@ contract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-li external restrict("StabilityBoard") { totalLoanAmount = totalLoanAmount.add(totalLoanAmountAdjustment); totalLockedAmount = totalLockedAmount.add(totalLockedAmountAdjustment); - emit KPIsAdjusted(totalLoanAmountAdjustment, totalLockedAmountAdjustment); } @@ -228,5 +226,4 @@ contract MonetarySupervisor is Restricted, TokenReceiver { // solhint-disable-li maxLoanByLtd = allowedByLtdDifferencePt > allowedByLtdDifferenceAmount ? allowedByLtdDifferencePt : allowedByLtdDifferenceAmount; } - } From 90fd29644defa6cf2b97ba5d114fd97f81d4da21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 6 Aug 2018 14:42:16 +0200 Subject: [PATCH 31/90] fix lint warnings (method order, too long lines) --- contracts/AugmintReserves.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/AugmintReserves.sol b/contracts/AugmintReserves.sol index b45886e1..3b081e25 100644 --- a/contracts/AugmintReserves.sol +++ b/contracts/AugmintReserves.sol @@ -14,14 +14,14 @@ import "./interfaces/AugmintTokenInterface.sol"; contract AugmintReserves is SystemAccount { + constructor(address permissionGranterContract) + public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks + function () public 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") { augmintToken.burn(amount); } - } From 6ea3fc763dce0e813f17f5acacd6249527b6ca15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 6 Aug 2018 14:46:05 +0200 Subject: [PATCH 32/90] change fallback method to external --- contracts/AugmintReserves.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/AugmintReserves.sol b/contracts/AugmintReserves.sol index 3b081e25..c8d22bd4 100644 --- a/contracts/AugmintReserves.sol +++ b/contracts/AugmintReserves.sol @@ -17,7 +17,7 @@ contract AugmintReserves is SystemAccount { constructor(address permissionGranterContract) public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks - function () public payable { // 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 ) } From 2afbe2f6ef2b2a68c184b0c4fbd18e85b6d04653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 6 Aug 2018 14:57:12 +0200 Subject: [PATCH 33/90] change fallback method to external in FeeAccount --- contracts/FeeAccount.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ) } From 3033671b4d6888e83c1fe8dc605a0667fd7c4478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 6 Aug 2018 16:22:48 +0200 Subject: [PATCH 34/90] chunkSize parameter in PreToken --- contracts/PreToken.sol | 13 +++++++------ test/preToken.js | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/contracts/PreToken.sol b/contracts/PreToken.sol index 8072aaf0..59ca8fa9 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 @@ -141,17 +139,20 @@ 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[6][] memory response = new uint[6][](chunkSize); - for (uint8 i = 0; i < CHUNK_SIZE && i + offset < allAgreements.length; i++) { + for (uint16 i = 0; i < chunkSize && i + offset < allAgreements.length; i++) { bytes32 agreementHash = allAgreements[i + offset]; Agreement storage agreement = agreements[agreementHash]; - agreementsResult[i] = [ i + offset, uint(agreement.owner), agreement.balance, + response[i] = [i + offset, uint(agreement.owner), agreement.balance, uint(agreementHash), uint(agreement.discount), uint(agreement.valuationCap)]; } + return response; } } 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, From 463e116fa851c24f80dabda8e6371cc52c46c57f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 6 Aug 2018 16:38:33 +0200 Subject: [PATCH 35/90] chunkSize parameter in MultiSig --- contracts/generic/MultiSig.sol | 23 +++++++++++++---------- test/stabilityBoardProxy.js | 11 ++++++----- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/contracts/generic/MultiSig.sol b/contracts/generic/MultiSig.sol index 00dcd16c..2a3fb841 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 @@ -144,11 +142,14 @@ 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++) { + function getSigners(uint offset, uint16 chunkSize) + external view returns(uint[3][]) { + uint[3][] memory response = new uint[3][](chunkSize); + for (uint16 i = 0; i < chunkSize && i + offset < allSigners.length; i++) { address signerAddress = allSigners[i + offset]; - signersResult[i] = [ i + offset, uint(signerAddress), isSigner[signerAddress] ? 1 : 0 ]; + response[i] = [i + offset, uint(signerAddress), isSigner[signerAddress] ? 1 : 0]; } + return response; } function getScriptsCount() view external returns (uint scriptsCount) { @@ -157,12 +158,14 @@ 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++) { + function getScripts(uint offset, uint16 chunkSize) + external view returns(uint[4][]) { + uint[4][] memory response = new uint[4][](chunkSize); + for (uint16 i = 0; i < chunkSize && i + offset < scriptAddresses.length; i++) { address scriptAddress = scriptAddresses[i + offset]; - scriptsResult[i] = [ i + offset, uint(scriptAddress), uint(scripts[scriptAddress].state), - scripts[scriptAddress].signCount ]; + response[i] = [i + offset, uint(scriptAddress), + uint(scripts[scriptAddress].state), scripts[scriptAddress].signCount]; } + return response; } - } diff --git a/test/stabilityBoardProxy.js b/test/stabilityBoardProxy.js index 22cfa4ec..5d63e324 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] }, @@ -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] }, @@ -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] }, @@ -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 { From e5c2f1e38e0a3ece8009564726cc367bd21b151d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 6 Aug 2018 17:14:36 +0200 Subject: [PATCH 36/90] chunkSize parameter in Exchange --- contracts/Exchange.sol | 20 +++++++++++++------- test/exchangeOrders.js | 26 ++++++++++++++------------ test/exchangeRandom.js | 10 +++++----- test/helpers/exchangeTestHelpers.js | 16 ++++++---------- 4 files changed, 38 insertions(+), 34 deletions(-) diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index d20ab337..28199417 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,30 @@ 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++) { + function getActiveBuyOrders(uint offset, uint16 chunkSize) + external view returns (uint[4][]) { + uint[4][] memory response = new uint[4][](chunkSize); + for (uint16 i = 0; i < chunkSize && i + offset < activeBuyOrders.length; i++) { uint64 orderId = activeBuyOrders[offset + i]; Order storage order = buyTokenOrders[orderId]; response[i] = [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++) { + // 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[4][] memory response = new uint[4][](chunkSize); + for (uint16 i = 0; i < chunkSize && i + offset < activeSellOrders.length; i++) { uint64 orderId = activeSellOrders[offset + i]; Order storage order = sellTokenOrders[orderId]; response[i] = [orderId, uint(order.maker), order.price, order.amount]; } + return response; } function _fillOrder(uint64 buyTokenId, uint64 sellTokenId) private returns(bool success) { diff --git a/test/exchangeOrders.js b/test/exchangeOrders.js index 16ed1684..76fe2eca 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; @@ -191,24 +193,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"); }) ]; @@ -230,24 +232,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..f4c25d66 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); } @@ -191,12 +191,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/helpers/exchangeTestHelpers.js b/test/helpers/exchangeTestHelpers.js index 72cc1e55..55e5c7de 100644 --- a/test/helpers/exchangeTestHelpers.js +++ b/test/helpers/exchangeTestHelpers.js @@ -11,8 +11,6 @@ const MATCH_ORDER_MAX_GAS = 80000; const PPM_DIV = 1000000; -let CHUNK_SIZE = null; - module.exports = { newOrder, cancelOrder, @@ -25,9 +23,6 @@ module.exports = { printOrderBook, get exchange() { return exchange; - }, - get CHUNK_SIZE() { - return CHUNK_SIZE; } }; @@ -39,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) { @@ -364,17 +358,19 @@ function parseOrders(orderType, orders) { }); } -async function getActiveBuyOrders(offset) { - const result = await exchange.getActiveBuyOrders(offset); +async function getActiveBuyOrders(offset, chunkSize) { + const result = await exchange.getActiveBuyOrders(offset, chunkSize); return parseOrders(testHelpers.TOKEN_BUY, result); } -async function getActiveSellOrders(offset) { - const result = await exchange.getActiveSellOrders(offset); +async function getActiveSellOrders(offset, chunkSize) { + const result = await exchange.getActiveSellOrders(offset, chunkSize); return parseOrders(testHelpers.TOKEN_SELL, result); } async function printOrderBook(_limit) { + const CHUNK_SIZE = 100; + const state = await getState(); const limit = typeof _limit === "undefined" || _limit > CHUNK_SIZE ? CHUNK_SIZE : _limit; From 9582a9c7679d9b712e66577e9a67e82b15d8375e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 6 Aug 2018 17:25:37 +0200 Subject: [PATCH 37/90] fix some lint warnings (whitespaces, indentation, too long lines) --- contracts/LoanManager.sol | 11 ++++++----- contracts/PreToken.sol | 9 ++++++--- contracts/generic/MultiSig.sol | 8 ++++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/contracts/LoanManager.sol b/contracts/LoanManager.sol index 79ce39c6..23faa2fb 100644 --- a/contracts/LoanManager.sol +++ b/contracts/LoanManager.sol @@ -165,7 +165,7 @@ contract LoanManager is Restricted, TokenReceiver { 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) { @@ -183,14 +183,15 @@ contract LoanManager is Restricted, TokenReceiver { 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); } @@ -232,8 +233,8 @@ contract LoanManager is Restricted, TokenReceiver { } /* returns loans starting from some . Loans data encoded as: - [loanId, collateralAmount, repaymentAmount, borrower, productId, state, maturity, disbursementTime, - loanAmount, interestAmount ] */ + [loanId, collateralAmount, repaymentAmount, borrower, productId, + state, maturity, disbursementTime, loanAmount, interestAmount] */ function getLoans(uint offset, uint16 chunkSize) external view returns (uint[10][]) { uint[10][] memory response = new uint[10][](chunkSize); diff --git a/contracts/PreToken.sol b/contracts/PreToken.sol index 59ca8fa9..a0304308 100644 --- a/contracts/PreToken.sol +++ b/contracts/PreToken.sol @@ -59,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") { @@ -90,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); diff --git a/contracts/generic/MultiSig.sol b/contracts/generic/MultiSig.sol index 2a3fb841..b1e1421f 100644 --- a/contracts/generic/MultiSig.sol +++ b/contracts/generic/MultiSig.sol @@ -61,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); } @@ -102,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); } From f4c1ede695ae89f33623bd3d2aac6bd47247a3e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 7 Aug 2018 17:57:25 +0200 Subject: [PATCH 38/90] optimize chunking loops (iterate on the actual index, precompute limit) --- contracts/Exchange.sol | 14 ++++++++------ contracts/LoanManager.sol | 23 ++++++++++------------- contracts/Locker.sol | 29 ++++++++++++----------------- contracts/PreToken.sol | 7 ++++--- contracts/generic/MultiSig.sol | 14 ++++++++------ contracts/generic/SafeMath.sol | 8 ++++++++ 6 files changed, 50 insertions(+), 45 deletions(-) diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index 28199417..d39f3fc1 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -157,10 +157,11 @@ contract Exchange is Restricted { function getActiveBuyOrders(uint offset, uint16 chunkSize) external view returns (uint[4][]) { uint[4][] memory response = new uint[4][](chunkSize); - for (uint16 i = 0; i < chunkSize && i + offset < activeBuyOrders.length; i++) { - uint64 orderId = activeBuyOrders[offset + i]; + uint limit = SafeMath.min(offset + chunkSize, activeBuyOrders.length); + 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; } @@ -170,10 +171,11 @@ contract Exchange is Restricted { function getActiveSellOrders(uint offset, uint16 chunkSize) external view returns (uint[4][]) { uint[4][] memory response = new uint[4][](chunkSize); - for (uint16 i = 0; i < chunkSize && i + offset < activeSellOrders.length; i++) { - uint64 orderId = activeSellOrders[offset + i]; + uint limit = SafeMath.min(offset + chunkSize, activeSellOrders.length); + 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; } diff --git a/contracts/LoanManager.sol b/contracts/LoanManager.sol index 23faa2fb..61db94e1 100644 --- a/contracts/LoanManager.sol +++ b/contracts/LoanManager.sol @@ -217,11 +217,10 @@ contract LoanManager is Restricted, TokenReceiver { external view returns (uint[8][]) { uint[8][] memory response = new uint[8][](chunkSize); - for (uint16 i = 0; i < chunkSize; i++) { - if (offset + i >= products.length) { break; } - - LoanProduct storage product = products[offset + i]; - response[i] = [offset + i, product.minDisbursedAmount, product.term, product.discountRate, + uint limit = SafeMath.min(offset + chunkSize, products.length); + 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 ]; } @@ -239,10 +238,9 @@ contract LoanManager is Restricted, TokenReceiver { external view returns (uint[10][]) { uint[10][] memory response = new uint[10][](chunkSize); - for (uint16 i = 0; i < chunkSize; i++) { - if (offset + i >= loans.length) { break; } - - response[i] = getLoanTuple(offset + i); + uint limit = SafeMath.min(offset + chunkSize, loans.length); + for (uint i = offset; i < limit; i++) { + response[i - offset] = getLoanTuple(i); } return response; } @@ -260,10 +258,9 @@ contract LoanManager is Restricted, TokenReceiver { uint[] storage loansForAddress = accountLoans[borrower]; - for (uint16 i = 0; i < chunkSize; i++) { - if (offset + i >= loansForAddress.length) { break; } - - response[i] = getLoanTuple(loansForAddress[offset + i]); + uint limit =SafeMath.min(offset + chunkSize, loansForAddress.length); + for (uint i = offset; i < limit; i++) { + response[i - offset] = getLoanTuple(loansForAddress[i]); } return response; } diff --git a/contracts/Locker.sol b/contracts/Locker.sol index d399a27c..d4bae7d9 100644 --- a/contracts/Locker.sol +++ b/contracts/Locker.sol @@ -144,12 +144,10 @@ contract Locker is Restricted, TokenReceiver { external view returns (uint[5][]) { uint[5][] memory response = new uint[5][](chunkSize); - for (uint16 i = 0; i < chunkSize; i++) { - if (offset + i >= lockProducts.length) { break; } - - LockProduct storage lockProduct = lockProducts[offset + i]; - - response[i] = [lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount, + uint limit = SafeMath.min(offset + chunkSize, lockProducts.length); + 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 ]; } @@ -172,15 +170,13 @@ contract Locker is Restricted, TokenReceiver { external view returns (uint[8][]) { uint[8][] memory response = new uint[8][](chunkSize); - for (uint16 i = 0; i < chunkSize; i++) { - if (offset + i >= locks.length) { break; } - - Lock storage lock = locks[offset + i]; + uint limit = SafeMath.min(offset + chunkSize, locks.length); + 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, + response[i - offset] = [uint(i), uint(lock.owner), lock.amountLocked, interestEarned, lock.lockedUntil, lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0]; } return response; @@ -194,15 +190,14 @@ contract Locker is Restricted, TokenReceiver { uint[7][] memory response = new uint[7][](chunkSize); uint[] storage locksForAddress = accountLocks[lockOwner]; - for (uint16 i = 0; i < chunkSize; i++) { - if (offset + i >= locksForAddress.length) { break; } - - Lock storage lock = locks[locksForAddress[offset + i]]; + uint limit = SafeMath.min(offset + chunkSize, locksForAddress.length); + 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, + response[i - offset] = [locksForAddress[i], lock.amountLocked, interestEarned, lock.lockedUntil, lockProduct.perTermInterest, lockProduct.durationInSecs, lock.isActive ? 1 : 0 ]; } return response; diff --git a/contracts/PreToken.sol b/contracts/PreToken.sol index a0304308..6d79393f 100644 --- a/contracts/PreToken.sol +++ b/contracts/PreToken.sol @@ -149,11 +149,12 @@ contract PreToken is Restricted { external view returns(uint[6][]) { uint[6][] memory response = new uint[6][](chunkSize); - for (uint16 i = 0; i < chunkSize && i + offset < allAgreements.length; i++) { - bytes32 agreementHash = allAgreements[i + offset]; + uint limit = SafeMath.min(offset + chunkSize, allAgreements.length); + for (uint i = offset; i < limit; i++) { + bytes32 agreementHash = allAgreements[i]; Agreement storage agreement = agreements[agreementHash]; - response[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/generic/MultiSig.sol b/contracts/generic/MultiSig.sol index b1e1421f..b9a675a2 100644 --- a/contracts/generic/MultiSig.sol +++ b/contracts/generic/MultiSig.sol @@ -145,9 +145,10 @@ contract MultiSig { function getSigners(uint offset, uint16 chunkSize) external view returns(uint[3][]) { uint[3][] memory response = new uint[3][](chunkSize); - for (uint16 i = 0; i < chunkSize && i + offset < allSigners.length; i++) { - address signerAddress = allSigners[i + offset]; - response[i] = [i + offset, uint(signerAddress), isSigner[signerAddress] ? 1 : 0]; + uint limit = SafeMath.min(offset + chunkSize, allSigners.length); + for (uint i = offset; i < limit; i++) { + address signerAddress = allSigners[i]; + response[i - offset] = [i, uint(signerAddress), isSigner[signerAddress] ? 1 : 0]; } return response; } @@ -161,9 +162,10 @@ contract MultiSig { function getScripts(uint offset, uint16 chunkSize) external view returns(uint[4][]) { uint[4][] memory response = new uint[4][](chunkSize); - for (uint16 i = 0; i < chunkSize && i + offset < scriptAddresses.length; i++) { - address scriptAddress = scriptAddresses[i + offset]; - response[i] = [i + offset, uint(scriptAddress), + uint limit = SafeMath.min(offset + chunkSize, scriptAddresses.length); + 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/SafeMath.sol b/contracts/generic/SafeMath.sol index aec1a2f4..2c9bfb7c 100644 --- a/contracts/generic/SafeMath.sol +++ b/contracts/generic/SafeMath.sol @@ -46,4 +46,12 @@ library SafeMath { require(b > 0, "div by 0"); // Solidity automatically throws for div by 0 but require to emit reason return (a % b != 0) ? (a / b + 1) : (a / b); } + + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } + + function max(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? b : a; + } } From 46caef63628cbc2470231517771aca94304e2eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 7 Aug 2018 18:07:52 +0200 Subject: [PATCH 39/90] use safe addition when calculating limit --- contracts/Exchange.sol | 4 ++-- contracts/LoanManager.sol | 6 +++--- contracts/Locker.sol | 6 +++--- contracts/PreToken.sol | 2 +- contracts/generic/MultiSig.sol | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index d39f3fc1..ac9c6f39 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -157,7 +157,7 @@ contract Exchange is Restricted { function getActiveBuyOrders(uint offset, uint16 chunkSize) external view returns (uint[4][]) { uint[4][] memory response = new uint[4][](chunkSize); - uint limit = SafeMath.min(offset + chunkSize, activeBuyOrders.length); + uint limit = SafeMath.min(offset.add(chunkSize), activeBuyOrders.length); for (uint i = offset; i < limit; i++) { uint64 orderId = activeBuyOrders[i]; Order storage order = buyTokenOrders[orderId]; @@ -171,7 +171,7 @@ contract Exchange is Restricted { function getActiveSellOrders(uint offset, uint16 chunkSize) external view returns (uint[4][]) { uint[4][] memory response = new uint[4][](chunkSize); - uint limit = SafeMath.min(offset + chunkSize, activeSellOrders.length); + uint limit = SafeMath.min(offset.add(chunkSize), activeSellOrders.length); for (uint i = offset; i < limit; i++) { uint64 orderId = activeSellOrders[i]; Order storage order = sellTokenOrders[orderId]; diff --git a/contracts/LoanManager.sol b/contracts/LoanManager.sol index 61db94e1..57bf18c1 100644 --- a/contracts/LoanManager.sol +++ b/contracts/LoanManager.sol @@ -217,7 +217,7 @@ contract LoanManager is Restricted, TokenReceiver { external view returns (uint[8][]) { uint[8][] memory response = new uint[8][](chunkSize); - uint limit = SafeMath.min(offset + chunkSize, products.length); + uint limit = SafeMath.min(offset.add(chunkSize), products.length); for (uint i = offset; i < limit; i++) { LoanProduct storage product = products[i]; response[i - offset] = [i, product.minDisbursedAmount, product.term, product.discountRate, @@ -238,7 +238,7 @@ contract LoanManager is Restricted, TokenReceiver { external view returns (uint[10][]) { uint[10][] memory response = new uint[10][](chunkSize); - uint limit = SafeMath.min(offset + chunkSize, loans.length); + uint limit = SafeMath.min(offset.add(chunkSize), loans.length); for (uint i = offset; i < limit; i++) { response[i - offset] = getLoanTuple(i); } @@ -258,7 +258,7 @@ contract LoanManager is Restricted, TokenReceiver { uint[] storage loansForAddress = accountLoans[borrower]; - uint limit =SafeMath.min(offset + chunkSize, loansForAddress.length); + uint limit =SafeMath.min(offset.add(chunkSize), loansForAddress.length); for (uint i = offset; i < limit; i++) { response[i - offset] = getLoanTuple(loansForAddress[i]); } diff --git a/contracts/Locker.sol b/contracts/Locker.sol index d4bae7d9..d77a6b76 100644 --- a/contracts/Locker.sol +++ b/contracts/Locker.sol @@ -144,7 +144,7 @@ contract Locker is Restricted, TokenReceiver { external view returns (uint[5][]) { uint[5][] memory response = new uint[5][](chunkSize); - uint limit = SafeMath.min(offset + chunkSize, lockProducts.length); + uint limit = SafeMath.min(offset.add(chunkSize), lockProducts.length); for (uint i = offset; i < limit; i++) { LockProduct storage lockProduct = lockProducts[i]; response[i - offset] = [lockProduct.perTermInterest, lockProduct.durationInSecs, lockProduct.minimumLockAmount, @@ -170,7 +170,7 @@ contract Locker is Restricted, TokenReceiver { external view returns (uint[8][]) { uint[8][] memory response = new uint[8][](chunkSize); - uint limit = SafeMath.min(offset + chunkSize, locks.length); + uint limit = SafeMath.min(offset.add(chunkSize), locks.length); for (uint i = offset; i < limit; i++) { Lock storage lock = locks[i]; LockProduct storage lockProduct = lockProducts[lock.productId]; @@ -190,7 +190,7 @@ contract Locker is Restricted, TokenReceiver { uint[7][] memory response = new uint[7][](chunkSize); uint[] storage locksForAddress = accountLocks[lockOwner]; - uint limit = SafeMath.min(offset + chunkSize, locksForAddress.length); + uint limit = SafeMath.min(offset.add(chunkSize), locksForAddress.length); for (uint i = offset; i < limit; i++) { Lock storage lock = locks[locksForAddress[i]]; LockProduct storage lockProduct = lockProducts[lock.productId]; diff --git a/contracts/PreToken.sol b/contracts/PreToken.sol index 6d79393f..06700621 100644 --- a/contracts/PreToken.sol +++ b/contracts/PreToken.sol @@ -149,7 +149,7 @@ contract PreToken is Restricted { external view returns(uint[6][]) { uint[6][] memory response = new uint[6][](chunkSize); - uint limit = SafeMath.min(offset + chunkSize, allAgreements.length); + uint limit = SafeMath.min(offset.add(chunkSize), allAgreements.length); for (uint i = offset; i < limit; i++) { bytes32 agreementHash = allAgreements[i]; Agreement storage agreement = agreements[agreementHash]; diff --git a/contracts/generic/MultiSig.sol b/contracts/generic/MultiSig.sol index b9a675a2..e44a8cdd 100644 --- a/contracts/generic/MultiSig.sol +++ b/contracts/generic/MultiSig.sol @@ -145,7 +145,7 @@ contract MultiSig { function getSigners(uint offset, uint16 chunkSize) external view returns(uint[3][]) { uint[3][] memory response = new uint[3][](chunkSize); - uint limit = SafeMath.min(offset + chunkSize, allSigners.length); + uint limit = SafeMath.min(offset.add(chunkSize), allSigners.length); for (uint i = offset; i < limit; i++) { address signerAddress = allSigners[i]; response[i - offset] = [i, uint(signerAddress), isSigner[signerAddress] ? 1 : 0]; @@ -162,7 +162,7 @@ contract MultiSig { function getScripts(uint offset, uint16 chunkSize) external view returns(uint[4][]) { uint[4][] memory response = new uint[4][](chunkSize); - uint limit = SafeMath.min(offset + chunkSize, scriptAddresses.length); + uint limit = SafeMath.min(offset.add(chunkSize), scriptAddresses.length); for (uint i = offset; i < limit; i++) { address scriptAddress = scriptAddresses[i]; response[i - offset] = [i, uint(scriptAddress), From e48c2fe9512cd1d2a9091f76c3024ea173aed6e7 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 8 Aug 2018 05:31:52 +0000 Subject: [PATCH 40/90] chore(package): update solidity-coverage to version 0.5.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5b1b6976..781dab5c 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "ganache-cli": "6.1.6", "moment": "2.22.2", "random-seed": "0.3.0", - "solidity-coverage": "0.5.5", + "solidity-coverage": "0.5.7", "stringifier": "1.3.0", "truffle": "4.1.13", "truffle-hdwallet-provider": "0.0.6", From 52d3957e889a8381efca5e41652be8a7c8703129 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Wed, 8 Aug 2018 05:37:39 +0000 Subject: [PATCH 41/90] chore(package): update lockfile https://npm.im/greenkeeper-lockfile --- yarn.lock | 2353 ++--------------------------------------------------- 1 file changed, 65 insertions(+), 2288 deletions(-) diff --git a/yarn.lock b/yarn.lock index afa71c71..baa6ce33 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.0.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,13 +1235,6 @@ 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" @@ -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" @@ -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" @@ -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" @@ -4324,49 +2734,22 @@ parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" 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" + error-ex "^1.2.0" 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.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.7.tgz#b7eb67678d446ab2702a26c2158ad71b4865a057" 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" @@ -5360,43 +3433,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 +3467,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 +3485,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 +3533,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 +3545,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 +3560,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 +3568,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" @@ -5624,10 +3611,6 @@ truffle@4.1.13: 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 +3676,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 +3684,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 +3698,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 +3726,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 +3745,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 +4000,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 +4017,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 +4054,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 +4121,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 +4128,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 +4147,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 +4162,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" From ff959c9e80caaf17f845968e27085954d70d5338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 13 Aug 2018 17:01:36 +0200 Subject: [PATCH 42/90] optimize chunked queries: initialize response array with real size (do not return zero elements) --- contracts/Exchange.sol | 4 +-- contracts/LoanManager.sol | 13 ++++---- contracts/Locker.sol | 12 ++++---- contracts/PreToken.sol | 4 +-- contracts/generic/MultiSig.sol | 4 +-- test/helpers/loanTestHelpers.js | 54 +++++++++++++++------------------ test/loans.js | 4 +-- test/locker.js | 11 +++---- test/stabilityBoardProxy.js | 6 ++-- 9 files changed, 52 insertions(+), 60 deletions(-) diff --git a/contracts/Exchange.sol b/contracts/Exchange.sol index ac9c6f39..09f02c59 100644 --- a/contracts/Exchange.sol +++ b/contracts/Exchange.sol @@ -156,8 +156,8 @@ contract Exchange is Restricted { // orders are encoded as [id, maker, price, amount] function getActiveBuyOrders(uint offset, uint16 chunkSize) external view returns (uint[4][]) { - uint[4][] memory response = new uint[4][](chunkSize); 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]; @@ -170,8 +170,8 @@ contract Exchange is Restricted { // orders are encoded as [id, maker, price, amount] function getActiveSellOrders(uint offset, uint16 chunkSize) external view returns (uint[4][]) { - uint[4][] memory response = new uint[4][](chunkSize); 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]; diff --git a/contracts/LoanManager.sol b/contracts/LoanManager.sol index 57bf18c1..a384e655 100644 --- a/contracts/LoanManager.sol +++ b/contracts/LoanManager.sol @@ -215,9 +215,9 @@ contract LoanManager is Restricted, TokenReceiver { // [ productId, minDisbursedAmount, term, discountRate, collateralRatio, defaultingFeePt, maxLoanAmount, isActive ] function getProducts(uint offset, uint16 chunkSize) external view returns (uint[8][]) { - uint[8][] memory response = new uint[8][](chunkSize); - 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, @@ -236,9 +236,9 @@ contract LoanManager is Restricted, TokenReceiver { state, maturity, disbursementTime, loanAmount, interestAmount] */ function getLoans(uint offset, uint16 chunkSize) external view returns (uint[10][]) { - uint[10][] memory response = new uint[10][](chunkSize); - uint limit = SafeMath.min(offset.add(chunkSize), loans.length); + uint[10][] memory response = new uint[10][](limit.sub(offset)); + for (uint i = offset; i < limit; i++) { response[i - offset] = getLoanTuple(i); } @@ -254,11 +254,10 @@ contract LoanManager is Restricted, TokenReceiver { loanAmount, interestAmount ] */ function getLoansForAddress(address borrower, uint offset, uint16 chunkSize) external view returns (uint[10][]) { - uint[10][] memory response = new uint[10][](chunkSize); - uint[] storage loansForAddress = accountLoans[borrower]; + uint limit = SafeMath.min(offset.add(chunkSize), loansForAddress.length); + uint[10][] memory response = new uint[10][](limit.sub(offset)); - uint limit =SafeMath.min(offset.add(chunkSize), loansForAddress.length); for (uint i = offset; i < limit; i++) { response[i - offset] = getLoanTuple(loansForAddress[i]); } diff --git a/contracts/Locker.sol b/contracts/Locker.sol index d77a6b76..a812255c 100644 --- a/contracts/Locker.sol +++ b/contracts/Locker.sol @@ -142,9 +142,9 @@ contract Locker is Restricted, TokenReceiver { // lock products are encoded as [ perTermInterest, durationInSecs, minimumLockAmount, maxLockAmount, isActive ] function getLockProducts(uint offset, uint16 chunkSize) external view returns (uint[5][]) { - uint[5][] memory response = new uint[5][](chunkSize); - 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, @@ -168,9 +168,9 @@ contract Locker is Restricted, TokenReceiver { // NB: perTermInterest is in millionths (i.e. 1,000,000 = 100%): function getLocks(uint offset, uint16 chunkSize) external view returns (uint[8][]) { - uint[8][] memory response = new uint[8][](chunkSize); - uint limit = SafeMath.min(offset.add(chunkSize), locks.length); + uint[8][] memory response = new uint[8][](limit.sub(offset)); + for (uint i = offset; i < limit; i++) { Lock storage lock = locks[i]; LockProduct storage lockProduct = lockProducts[lock.productId]; @@ -187,10 +187,10 @@ contract Locker is Restricted, TokenReceiver { // [lockId, amountLocked, interestEarned, lockedUntil, perTermInterest, durationInSecs, isActive ] function getLocksForAddress(address lockOwner, uint offset, uint16 chunkSize) external view returns (uint[7][]) { - uint[7][] memory response = new uint[7][](chunkSize); 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 (uint i = offset; i < limit; i++) { Lock storage lock = locks[locksForAddress[i]]; LockProduct storage lockProduct = lockProducts[lock.productId]; diff --git a/contracts/PreToken.sol b/contracts/PreToken.sol index 06700621..fd0d1e47 100644 --- a/contracts/PreToken.sol +++ b/contracts/PreToken.sol @@ -147,9 +147,9 @@ contract PreToken is Restricted { // discount as uint, valuationCap as uint ] function getAgreements(uint offset, uint16 chunkSize) external view returns(uint[6][]) { - uint[6][] memory response = new uint[6][](chunkSize); - uint limit = SafeMath.min(offset.add(chunkSize), allAgreements.length); + uint[6][] memory response = new uint[6][](limit.sub(offset)); + for (uint i = offset; i < limit; i++) { bytes32 agreementHash = allAgreements[i]; Agreement storage agreement = agreements[agreementHash]; diff --git a/contracts/generic/MultiSig.sol b/contracts/generic/MultiSig.sol index e44a8cdd..c4abfd8a 100644 --- a/contracts/generic/MultiSig.sol +++ b/contracts/generic/MultiSig.sol @@ -144,8 +144,8 @@ contract MultiSig { // UI helper fx - Returns signers from offset as [signer id (index in allSigners), address as uint, isActive 0 or 1] function getSigners(uint offset, uint16 chunkSize) external view returns(uint[3][]) { - uint[3][] memory response = new uint[3][](chunkSize); 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]; @@ -161,8 +161,8 @@ contract MultiSig { // [scriptId (index in scriptAddresses[]), address as uint, state, signCount] function getScripts(uint offset, uint16 chunkSize) external view returns(uint[4][]) { - uint[4][] memory response = new uint[4][](chunkSize); 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), diff --git a/test/helpers/loanTestHelpers.js b/test/helpers/loanTestHelpers.js index a1db1614..8d0e9446 100644 --- a/test/helpers/loanTestHelpers.js +++ b/test/helpers/loanTestHelpers.js @@ -309,7 +309,7 @@ async function collectLoan(testInstance, loan, collector) { async function getProductsInfo(offset, chunkSize) { const products = await loanManager.getProducts(offset, chunkSize); - assert.equal(products.length, chunkSize); + assert(products.length <= chunkSize); const result = []; products.map(prod => { const [ @@ -322,20 +322,18 @@ async function getProductsInfo(offset, chunkSize) { 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; } @@ -356,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/loans.js b/test/loans.js index 7c612cc8..35f474b6 100644 --- a/test/loans.js +++ b/test/loans.js @@ -250,7 +250,7 @@ contract("Loans tests", accounts => { await testHelpers.waitForTimeStamp(loan2.maturity); const loansArray = await loanManager.getLoans(loan1.id, CHUNK_SIZE); - assert.equal(loansArray.length, CHUNK_SIZE); + assert.equal(loansArray.length, 2); const loanInfo = loanTestHelpers.parseLoansInfo(loansArray); assert.equal(loanInfo.length, 2); // offset was from first loan added @@ -293,7 +293,7 @@ contract("Loans tests", accounts => { await testHelpers.waitForTimeStamp(loan2.maturity); const loansArray = await loanManager.getLoansForAddress(borrower, accountLoanCount - 2, CHUNK_SIZE); - assert.equal(loansArray.length, 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 af8da404..6136ef9e 100644 --- a/test/locker.js +++ b/test/locker.js @@ -121,9 +121,8 @@ contract("Lock", accounts => { const products = await lockerInstance.getLockProducts(offset, CHUNK_SIZE); - // getLockProducts should return a CHUNK_SIZE element array: assert.isArray(products); - assert(products.length === CHUNK_SIZE); + assert(products.length <= CHUNK_SIZE); const product = products[0]; @@ -411,7 +410,7 @@ contract("Lock", accounts => { const offset = lockCount - 2; 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 ] @@ -468,9 +467,8 @@ contract("Lock", accounts => { const expectedAccountLockIndex = (await lockerInstance.getLockCountForAddress(tokenHolder)) - 1; 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]; @@ -514,9 +512,8 @@ contract("Lock", accounts => { 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/stabilityBoardProxy.js b/test/stabilityBoardProxy.js index 5d63e324..6fd00b1e 100644 --- a/test/stabilityBoardProxy.js +++ b/test/stabilityBoardProxy.js @@ -114,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); @@ -149,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); @@ -207,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); }); From d770b214370e731ff87a00593d5fd91bfa4b5d91 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Mon, 13 Aug 2018 17:51:51 +0000 Subject: [PATCH 43/90] chore(package): update truffle to version 4.1.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5b1b6976..219f05d7 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "random-seed": "0.3.0", "solidity-coverage": "0.5.5", "stringifier": "1.3.0", - "truffle": "4.1.13", + "truffle": "4.1.14", "truffle-hdwallet-provider": "0.0.6", "web3v1": "npm:web3@1.0.0-beta.34" }, From bae230a039e5232e859249967881a4d57a08c83e Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Mon, 13 Aug 2018 17:54:31 +0000 Subject: [PATCH 44/90] chore(package): update lockfile https://npm.im/greenkeeper-lockfile --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index afa71c71..85e9b454 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5616,9 +5616,9 @@ truffle-hdwallet-provider@0.0.6: 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" From 631d1d71d142fc627ccab8403c9f34777816e22b Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 15 Aug 2018 23:47:20 +0000 Subject: [PATCH 45/90] chore(package): update ganache-cli to version 6.1.8 Closes #143 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 781dab5c..02ed37c9 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "bignumber.js": "5.0.0", "coveralls": "3.0.1", "dotenv": "6.0.0", - "ganache-cli": "6.1.6", + "ganache-cli": "6.1.8", "moment": "2.22.2", "random-seed": "0.3.0", "solidity-coverage": "0.5.7", From 60f537f83d6134e9b50a990645334c6473bf27a2 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Fri, 17 Aug 2018 10:11:16 +0000 Subject: [PATCH 46/90] chore(package): update lockfile https://npm.im/greenkeeper-lockfile --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index baa6ce33..1aa73181 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1797,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" From c3826ecad65e8ea34ad0e36a68c50f98fd0cc38c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 21 Aug 2018 15:24:00 +0200 Subject: [PATCH 47/90] tests: issue test tokens directly instead of via reserve.withdraw --- test/delegatedTransfer.js | 3 +-- test/delegatedTransferAndNotify.js | 4 ++-- test/exchangeMatching.js | 6 ++---- test/exchangeOrders.js | 5 +---- test/exchangeRandom.js | 4 +--- test/feeAccount.js | 4 +--- test/helpers/tokenTestHelpers.js | 15 ++++++--------- test/loanCollection.js | 3 +-- test/loanToDepositRatioLimits.js | 3 +-- test/loans.js | 4 +--- test/locker.js | 6 ++---- test/tokenConversion.js | 9 +++------ test/tokenTransfer.js | 5 ++--- test/tokenTransferFrom.js | 5 ++--- 14 files changed, 26 insertions(+), 50 deletions(-) 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 5ae96fae..91a1f9d6 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 76fe2eca..06d0bf88 100644 --- a/test/exchangeOrders.js +++ b/test/exchangeOrders.js @@ -18,10 +18,7 @@ contract("Exchange orders tests", accounts => { makers = [global.accounts[1], global.accounts[2]]; 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() { diff --git a/test/exchangeRandom.js b/test/exchangeRandom.js index f4c25d66..e13f818c 100644 --- a/test/exchangeRandom.js +++ b/test/exchangeRandom.js @@ -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)) ]); }); 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/tokenTestHelpers.js b/test/helpers/tokenTestHelpers.js index 77030b77..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) { diff --git a/test/loanCollection.js b/test/loanCollection.js index e0dab245..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()), @@ -36,7 +35,7 @@ contract("Loans collection tests", accounts => { const [newProducts] = await Promise.all([ loanTestHelpers.getProductsInfo(prodCount, 10), - tokenTestHelpers.withdrawFromReserve(accounts[0], 1000000000) + tokenTestHelpers.issueToken(accounts[0], accounts[0], 1000000000) ]); [ products.notDue, 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 7c612cc8..04dbd958 100644 --- a/test/loans.js +++ b/test/loans.js @@ -22,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()), @@ -45,8 +44,7 @@ contract("Loans tests", accounts => { const [newProducts] = await Promise.all([ loanTestHelpers.getProductsInfo(prodCount, CHUNK_SIZE), - - tokenTestHelpers.withdrawFromReserve(accounts[0], 1000000000) + tokenTestHelpers.issueToken(accounts[0], accounts[0], 1000000000) ]); [ products.notDue, diff --git a/test/locker.js b/test/locker.js index af8da404..8dd51c78 100644 --- a/test/locker.js +++ b/test/locker.js @@ -28,15 +28,13 @@ contract("Lock", accounts => { lockerInstance = Locker.at(Locker.address); await Promise.all([ - monetarySupervisor.issueToReserve(50000), 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) ]); }); 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 2ee6f32c..afc8fe4b 100644 --- a/test/tokenTransferFrom.js +++ b/test/tokenTransferFrom.js @@ -8,11 +8,10 @@ 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) ]); }); From f6bd567ebc2901d8d7fdac0f10d483428577ceaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 21 Aug 2018 15:50:36 +0200 Subject: [PATCH 48/90] AugmintReserves is no longer a SystemAccount, add simple migrate function instead of withdraw --- contracts/AugmintReserves.sol | 17 ++++++++++++++--- contracts/generic/SystemAccount.sol | 7 ++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/contracts/AugmintReserves.sol b/contracts/AugmintReserves.sol index c8d22bd4..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 { + + event ReserveMigration(address to, uint weiAmount); constructor(address permissionGranterContract) - public SystemAccount(permissionGranterContract) {} // solhint-disable-line no-empty-blocks + public Restricted(permissionGranterContract) {} // solhint-disable-line no-empty-blocks function () external payable { // solhint-disable-line no-empty-blocks // to accept ETH sent into reserve (from defaulted loan's collateral ) } - function burn(AugmintTokenInterface augmintToken, uint amount) external restrict("MonetarySupervisor") { + 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/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); } - } From 085db49ad417782797da400135b67c5f3107ddc9 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Thu, 23 Aug 2018 00:59:46 +0000 Subject: [PATCH 49/90] chore(package): update stringifier to version 1.4.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 54ede2bc..a96eb39f 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "moment": "2.22.2", "random-seed": "0.3.0", "solidity-coverage": "0.5.7", - "stringifier": "1.3.0", + "stringifier": "1.4.0", "truffle": "4.1.14", "truffle-hdwallet-provider": "0.0.6", "web3v1": "npm:web3@1.0.0-beta.34" From 25cfa1c2861b0ab7c760e0b2f8f449fac3c65209 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Thu, 23 Aug 2018 01:02:06 +0000 Subject: [PATCH 50/90] chore(package): update lockfile https://npm.im/greenkeeper-lockfile --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7918c95a..6916de5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3419,9 +3419,9 @@ 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@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/stringifier/-/stringifier-1.4.0.tgz#d704581567f4526265d00ed8ecb354a02c3fec28" dependencies: core-js "^2.0.0" traverse "^0.6.6" From 19c82e498a157c9a2da7e08d993d3cd840512419 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 31 Aug 2018 22:28:22 +0000 Subject: [PATCH 51/90] chore(package): update solidity-coverage to version 0.5.11 Closes #149 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 54ede2bc..7285fe9b 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "ganache-cli": "6.1.8", "moment": "2.22.2", "random-seed": "0.3.0", - "solidity-coverage": "0.5.7", + "solidity-coverage": "0.5.11", "stringifier": "1.3.0", "truffle": "4.1.14", "truffle-hdwallet-provider": "0.0.6", From f84ccd3a3069876ba0f2ae06a00ea3bd712be5d6 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Fri, 31 Aug 2018 22:30:44 +0000 Subject: [PATCH 52/90] chore(package): update lockfile https://npm.im/greenkeeper-lockfile --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7918c95a..c9cec938 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3284,9 +3284,9 @@ solc@0.4.24, solc@^0.4.2: semver "^5.3.0" yargs "^4.7.1" -solidity-coverage@0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.7.tgz#b7eb67678d446ab2702a26c2158ad71b4865a057" +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.6" From 4bd14f944b89410780d9767a1011e99097fae946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 20 Sep 2018 16:02:26 +0200 Subject: [PATCH 53/90] remove temporary methods (chunkSize backward compatibility in test helpers) --- test/exchangeOrders.js | 8 ++++---- test/helpers/exchangeTestHelpers.js | 14 +------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/test/exchangeOrders.js b/test/exchangeOrders.js index c714f735..965ef440 100644 --- a/test/exchangeOrders.js +++ b/test/exchangeOrders.js @@ -140,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"); @@ -149,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"); }); @@ -178,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"); @@ -187,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"); }); diff --git a/test/helpers/exchangeTestHelpers.js b/test/helpers/exchangeTestHelpers.js index d2b19a43..7a418a00 100644 --- a/test/helpers/exchangeTestHelpers.js +++ b/test/helpers/exchangeTestHelpers.js @@ -20,8 +20,6 @@ module.exports = { getSellTokenOrder, getActiveBuyOrders, getActiveSellOrders, - getActiveBuyOrdersNoFilter, - getActiveSellOrdersNoFilter, printOrderBook, get exchange() { return exchange; @@ -366,21 +364,11 @@ function parseOrders(orderType, orders) { } async function getActiveBuyOrders(offset, chunkSize) { - const result = await exchange.getActiveBuyOrders(offset, chunkSize); - return parseOrders(testHelpers.TOKEN_BUY, result.filter(order => order[3].toNumber() != 0)); -} - -async function getActiveSellOrders(offset, chunkSize) { - const result = await exchange.getActiveSellOrders(offset, chunkSize); - return parseOrders(testHelpers.TOKEN_SELL, result.filter(order => order[3].toNumber() != 0)); -} - -async function getActiveBuyOrdersNoFilter(offset, chunkSize) { const result = await exchange.getActiveBuyOrders(offset, chunkSize); return parseOrders(testHelpers.TOKEN_BUY, result); } -async function getActiveSellOrdersNoFilter(offset, chunkSize) { +async function getActiveSellOrders(offset, chunkSize) { const result = await exchange.getActiveSellOrders(offset, chunkSize); return parseOrders(testHelpers.TOKEN_SELL, result); } From e8c38954ac1830b001c0b25b07d200b89f4e4f60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 12 Oct 2018 12:59:56 +0200 Subject: [PATCH 54/90] separate issued and burned amount counters in monetarysupervisor --- contracts/MonetarySupervisor.sol | 5 +++-- test/monetarySupervisor.js | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/contracts/MonetarySupervisor.sol b/contracts/MonetarySupervisor.sol index 52ca80de..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 @@ -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); } diff --git a/test/monetarySupervisor.js b/test/monetarySupervisor.js index f81dd3fa..e57b57ce 100644 --- a/test/monetarySupervisor.js +++ b/test/monetarySupervisor.js @@ -59,10 +59,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 +75,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 +88,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(), From 07db4021f6289a4c9801eba72a79b6b11a8d5766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 12 Oct 2018 13:07:55 +0200 Subject: [PATCH 55/90] test fixes and improvements --- test/monetarySupervisor.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/test/monetarySupervisor.js b/test/monetarySupervisor.js index e57b57ce..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(), From 41f6df0049363e6c9c263574a1eeefd280a636ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 17 Oct 2018 14:14:17 +0200 Subject: [PATCH 56/90] delete old abiniser deployment descriptors (rinkeby) --- .../4/AugmintReserves_DEPLOYS.json | 84 ---------- abiniser/deployments/4/Exchange_DEPLOYS.json | 146 ------------------ .../deployments/4/FeeAccount_DEPLOYS.json | 84 ---------- .../4/InterestEarnedAccount_DEPLOYS.json | 84 ---------- .../deployments/4/LoanManager_DEPLOYS.json | 102 ------------ abiniser/deployments/4/Locker_DEPLOYS.json | 115 -------------- .../deployments/4/Migrations_DEPLOYS.json | 48 ------ .../4/MonetarySupervisor_DEPLOYS.json | 110 ------------- .../deployments/4/PreTokenProxy_DEPLOYS.json | 24 --- abiniser/deployments/4/PreToken_DEPLOYS.json | 24 --- abiniser/deployments/4/Rates_DEPLOYS.json | 84 ---------- abiniser/deployments/4/SafeMath_DEPLOYS.json | 48 ------ .../4/StabilityBoardProxy_DEPLOYS.json | 24 --- .../4/StabilityBoardSigner_DEPLOYS.json | 24 --- abiniser/deployments/4/TokenAEur_DEPLOYS.json | 112 -------------- 15 files changed, 1113 deletions(-) delete mode 100644 abiniser/deployments/4/AugmintReserves_DEPLOYS.json delete mode 100644 abiniser/deployments/4/Exchange_DEPLOYS.json delete mode 100644 abiniser/deployments/4/FeeAccount_DEPLOYS.json delete mode 100644 abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json delete mode 100644 abiniser/deployments/4/LoanManager_DEPLOYS.json delete mode 100644 abiniser/deployments/4/Locker_DEPLOYS.json delete mode 100644 abiniser/deployments/4/Migrations_DEPLOYS.json delete mode 100644 abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json delete mode 100644 abiniser/deployments/4/PreTokenProxy_DEPLOYS.json delete mode 100644 abiniser/deployments/4/PreToken_DEPLOYS.json delete mode 100644 abiniser/deployments/4/Rates_DEPLOYS.json delete mode 100644 abiniser/deployments/4/SafeMath_DEPLOYS.json delete mode 100644 abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json delete mode 100644 abiniser/deployments/4/StabilityBoardSigner_DEPLOYS.json delete mode 100644 abiniser/deployments/4/TokenAEur_DEPLOYS.json diff --git a/abiniser/deployments/4/AugmintReserves_DEPLOYS.json b/abiniser/deployments/4/AugmintReserves_DEPLOYS.json deleted file mode 100644 index 0c99923f..00000000 --- a/abiniser/deployments/4/AugmintReserves_DEPLOYS.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "contractName": "AugmintReserves", - "latestAbiHash": "fe74b7986dafb00f221486e790fc70ec", - "deployedAbis": { - "dfbca9f4d0da7a3517b2832dc1c04d9a": { - "latestDeployedAddress": "0xf1ea22d0d75f0d247a0b43a45423392ee9b1ae86", - "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", - "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" - }, - "0x6386f25d2029ea3164838bf6494ed85c01fc1b03": { - "generatedAt": "2018-06-10T08:34:44.824Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.124Z", - "deployTransactionHash": "0xb8d91b5ead336188b26d421e0f8a77d6daf93c093975f03d051a0633116cc666", - "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" - } - } - } - } -} \ No newline at end of file diff --git a/abiniser/deployments/4/Exchange_DEPLOYS.json b/abiniser/deployments/4/Exchange_DEPLOYS.json deleted file mode 100644 index 6764adb9..00000000 --- a/abiniser/deployments/4/Exchange_DEPLOYS.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "contractName": "Exchange", - "latestAbiHash": "c28de2392aea85ef2aa1b108fce6568c", - "deployedAbis": { - "3aa2aedd2972391a12570ba4bfca2f72": { - "latestDeployedAddress": "0x03fe291f8a30e54cd05459f368d554b40784ca78", - "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", - "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" - }, - "0x554817688d096ae89fdaccf52e76f629b9db8f53": { - "generatedAt": "2018-09-12T12:52:24.541Z", - "truffleContractFileUpdatedAt": "2018-09-12T12:51:02.147Z", - "deployTransactionHash": "0x579ed3f2d914cee820cbdec7a78d777923c4cb63044cb18e78c721ad2651a487", - "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" - } - } - } - } -} \ No newline at end of file diff --git a/abiniser/deployments/4/FeeAccount_DEPLOYS.json b/abiniser/deployments/4/FeeAccount_DEPLOYS.json deleted file mode 100644 index d664b08f..00000000 --- a/abiniser/deployments/4/FeeAccount_DEPLOYS.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "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", - "deployments": { - "0x9b26f801c6078b76690b0d954f7fd662e04be1d1": { - "generatedAt": "2018-06-04T12:49:52.510Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.430Z", - "deployTransactionHash": "0x57679efa8918fd72e9078929b01e7445d46741f193311d0ae4ae91f512f1e9f5", - "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" - }, - "0x0f5983a6d760bf6e385339af0e67e87420d413ec": { - "generatedAt": "2018-06-10T08:34:44.841Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.117Z", - "deployTransactionHash": "0xefc759f1286e57586ef977f85a4810f65525a46fb7754c194bc74f0c53a0da5f", - "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" - } - } - } - } -} \ No newline at end of file diff --git a/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json b/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json deleted file mode 100644 index 1a7ae0d4..00000000 --- a/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "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", - "deployments": { - "0xdd1b8dfd9094e319a0eb83c32b47331946cb761f": { - "generatedAt": "2018-06-04T12:49:52.515Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.439Z", - "deployTransactionHash": "0x2619c360d95a213cd49a6f9b6bd796d19f3b9acdd213d4f07990e353a176277f", - "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" - }, - "0xdf8c338a89f827a6d62804905ed415b6a382f92e": { - "generatedAt": "2018-06-10T08:34:44.848Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.605Z", - "deployTransactionHash": "0x6a303a203866d5f5aef9cbd49cf07bfe98bdd3a10a908923b90b7319b184daaf", - "compiler": { - "name": "solc", - "version": "0.4.24+commit.e67f0147.Emscripten.clang" - }, - "bytecodeHash": "1a57f465af930a1cc7070876d2a6bde3", - "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" - } - } - } - } -} \ No newline at end of file diff --git a/abiniser/deployments/4/LoanManager_DEPLOYS.json b/abiniser/deployments/4/LoanManager_DEPLOYS.json deleted file mode 100644 index 5c796fe0..00000000 --- a/abiniser/deployments/4/LoanManager_DEPLOYS.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "contractName": "LoanManager", - "latestAbiHash": "ec709c3341045caa3a75374b8cfc7286", - "deployedAbis": { - "dd8d5ec97e0a22b6f9e63b04d4e11e09": { - "latestDeployedAddress": "0xfb505462633ae3234760d0ee51c557199ab249df", - "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", - "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" - }, - "0x3b5dd323534659655eeccc642c3e338aabd0b219": { - "generatedAt": "2018-06-10T08:34:44.944Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:26.250Z", - "deployTransactionHash": "0xca9aa185ff4803bbc3834dfdaee4bc48047f90af90b7f12834615f8e90aeaaf1", - "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" - } - } - } - } -} \ No newline at end of file diff --git a/abiniser/deployments/4/Locker_DEPLOYS.json b/abiniser/deployments/4/Locker_DEPLOYS.json deleted file mode 100644 index ac8d6371..00000000 --- a/abiniser/deployments/4/Locker_DEPLOYS.json +++ /dev/null @@ -1,115 +0,0 @@ -{ - "contractName": "Locker", - "latestAbiHash": "619ff7809b73aead28176fe6317953c3", - "deployedAbis": { - "6055e2cba8c8e9cb7e04b10e4c56ab9a": { - "latestDeployedAddress": "0x617cf9ba5c9cbecdd66412bc1d073b002aa26426", - "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", - "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" - }, - "0xf74c0cb2713214808553cda5c78f92219478863d": { - "generatedAt": "2018-07-04T16:14:32.212Z", - "truffleContractFileUpdatedAt": "2018-07-04T16:09:03.263Z", - "deployTransactionHash": "0xe91c9245554d777018898d909d30a66ffc448733a3e19d8ead91a7a89e29ff01", - "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" - } - } - } - } -} \ No newline at end of file diff --git a/abiniser/deployments/4/Migrations_DEPLOYS.json b/abiniser/deployments/4/Migrations_DEPLOYS.json deleted file mode 100644 index 83e857c7..00000000 --- a/abiniser/deployments/4/Migrations_DEPLOYS.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "contractName": "Migrations", - "latestAbiHash": "78141a323f4a8416891b06a0a2b90065", - "deployedAbis": { - "78141a323f4a8416891b06a0a2b90065": { - "latestDeployedAddress": "0xb96f7e79a6b3faf4162e274ff764ca9de598b0c5", - "deployments": { - "0xab568f6a378de0443f1e273f79abcaf68dfbd39d": { - "generatedAt": "2018-04-25T12:29:07.436Z", - "truffleContractFileUpdatedAt": "2018-02-14T23:31:03.063Z", - "compiler": { - "name": "solc", - "version": "0.4.19+commit.c4cbbb05.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" - } - } - } - } -} \ No newline at end of file diff --git a/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json b/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json deleted file mode 100644 index ddfb5549..00000000 --- a/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "contractName": "MonetarySupervisor", - "latestAbiHash": "54d27fedd8bf3010ad5509866a42c053", - "deployedAbis": { - "066c2220b91befd25691fefd91684117": { - "latestDeployedAddress": "0x02a3b0f6ab5998a0c5d756ed01ea2200ea68d763", - "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", - "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" - }, - "0x01844c9bade08a8ffdb09ad9f1fece2c83a6e6a8": { - "generatedAt": "2018-06-10T08:34:44.882Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.905Z", - "deployTransactionHash": "0x021a2770fe912a7969c1acffc9b2a3b9a46791f99259c9a66ae5973da18b2b4f", - "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" - } - } - } - } -} \ No newline at end of file diff --git a/abiniser/deployments/4/PreTokenProxy_DEPLOYS.json b/abiniser/deployments/4/PreTokenProxy_DEPLOYS.json deleted file mode 100644 index 11c4d5d6..00000000 --- a/abiniser/deployments/4/PreTokenProxy_DEPLOYS.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "contractName": "PreTokenProxy", - "latestAbiHash": "19ab69b650e28b2dd211d3851893f91f", - "deployedAbis": { - "19ab69b650e28b2dd211d3851893f91f": { - "latestDeployedAddress": "0x0775465245e523b45cc3b41477d44f908e22fede", - "deployments": { - "0x0775465245e523b45cc3b41477d44f908e22fede": { - "generatedAt": "2018-06-10T08:34:45.034Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.091Z", - "deployTransactionHash": "0xe447e2f5055b6229d9b00d09f55f4153cdcde40a031c3a233e077e2147b19ace", - "compiler": { - "name": "solc", - "version": "0.4.24+commit.e67f0147.Emscripten.clang" - }, - "bytecodeHash": "9fd82afe11a8ff7af3e815e243d31647", - "deployedBytecodeHash": "1846d508980d6136e1e81708c995e572", - "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/4/PreToken_DEPLOYS.json b/abiniser/deployments/4/PreToken_DEPLOYS.json deleted file mode 100644 index 845a870b..00000000 --- a/abiniser/deployments/4/PreToken_DEPLOYS.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "contractName": "PreToken", - "latestAbiHash": "10eebbb51a771cfd3473475169a569f1", - "deployedAbis": { - "10eebbb51a771cfd3473475169a569f1": { - "latestDeployedAddress": "0xfc69b4f2a7de7c68c46a8230ecdf0cff49eb8f1f", - "deployments": { - "0xfc69b4f2a7de7c68c46a8230ecdf0cff49eb8f1f": { - "generatedAt": "2018-06-10T08:34:45.077Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.164Z", - "deployTransactionHash": "0xd744577c7abd7c4a6c3b83aec61516c2149a399016fd61a1c1df6ff19d035861", - "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" - } - } - } - } -} \ No newline at end of file diff --git a/abiniser/deployments/4/Rates_DEPLOYS.json b/abiniser/deployments/4/Rates_DEPLOYS.json deleted file mode 100644 index 14330ecc..00000000 --- a/abiniser/deployments/4/Rates_DEPLOYS.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "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", - "deployments": { - "0x582971c64de4b5e6db2d95cf8103cff7f0fdff31": { - "generatedAt": "2018-06-04T12:49:52.468Z", - "truffleContractFileUpdatedAt": "2018-06-04T12:49:10.436Z", - "deployTransactionHash": "0x429aef23ff41e040ef4f75eb4c97a276c652a15e17987d9ddff4ebaa132bf529", - "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" - }, - "0xf25638c7d37fca0cbc124b3925ece156a20e1f03": { - "generatedAt": "2018-06-10T08:34:44.799Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.109Z", - "deployTransactionHash": "0x5539d4225ad5c452185ed1541e2c018bfc1d938a4ebf49f184c9da7ee2411395", - "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" - } - } - } - } -} \ No newline at end of file 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 deleted file mode 100644 index 9df93a3a..00000000 --- a/abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "contractName": "StabilityBoardProxy", - "latestAbiHash": "19ab69b650e28b2dd211d3851893f91f", - "deployedAbis": { - "19ab69b650e28b2dd211d3851893f91f": { - "latestDeployedAddress": "0x44022c28766652ec5901790e53ced7a79a19c10a", - "deployments": { - "0x44022c28766652ec5901790e53ced7a79a19c10a": { - "generatedAt": "2018-06-10T08:34:45.025Z", - "truffleContractFileUpdatedAt": "2018-06-10T08:33:25.100Z", - "deployTransactionHash": "0x13def497d360e16836ae12d65a5e5cef471778b9378cfab04f7968c2ae90512e", - "compiler": { - "name": "solc", - "version": "0.4.24+commit.e67f0147.Emscripten.clang" - }, - "bytecodeHash": "56131f88a46fe46a487da0a9bae573fc", - "deployedBytecodeHash": "2996d609801f2039ae49c17ac8bcad92", - "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/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 deleted file mode 100644 index 7fc8540f..00000000 --- a/abiniser/deployments/4/TokenAEur_DEPLOYS.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "contractName": "TokenAEur", - "latestAbiHash": "9aa81519ec45a52d3f8f1a1a83d25c74", - "deployedAbis": { - "27721a2c77dc40da7639abd46791c3d7": { - "latestDeployedAddress": "0x95aa79d7410eb60f49bfd570b445836d402bd7b1", - "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", - "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", - "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" - } - } - } - } -} \ No newline at end of file From c21d6f6588038bd2b8e68904da5580f9ddf0ed49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 17 Oct 2018 14:14:59 +0200 Subject: [PATCH 57/90] delete old migration scripts (rinkeby) --- rinkeby_migrations/10_deploy_Locker.js | 31 ---- rinkeby_migrations/11_deploy_Exchange.js | 13 -- rinkeby_migrations/12_add_legacyTokens.js | 18 --- .../13_authorise_MonetaryBoard.js | 35 ---- .../14_deploy_new_MonetarySupervisor.js | 51 ------ .../15_set_new_MonetarySupervisor_live.js | 98 ------------ rinkeby_migrations/16_deploy_new_Exchange.js | 49 ------ rinkeby_migrations/17_new_TokenAEur.js | 151 ------------------ .../18_set_new_MonetarySupervisor_live.js | 58 ------- rinkeby_migrations/19_redeploy.js | 68 -------- rinkeby_migrations/1_initial_migration.js | 5 - rinkeby_migrations/20_init_new_deploy.js | 47 ------ rinkeby_migrations/21_setup_signers.js | 33 ---- .../22_deployRink0004_migrate_MSv0_5_0.js | 14 -- .../22_deploy_Rink0004_interest_adjustment.js | 13 -- ...xecuteRink0004_and_revokeOldPermissions.js | 85 ---------- rinkeby_migrations/24_deploy_new_Locker.js | 18 --- .../25_deploy_fixInitNewLocker.js | 11 -- rinkeby_migrations/26_deploy_new_Exchange.js | 15 -- .../27_deploy_initNewExchange.js | 12 -- .../28_deploy_initNewExchange2.js | 12 -- .../29_deploy_changeSBSigners.js | 11 -- rinkeby_migrations/2_deploy_Libs.js | 5 - .../30_deploy_changeDefaultingFee.js | 11 -- .../31_deploy_adjustInterest.js | 11 -- rinkeby_migrations/32_deploy_new_Exchange.js | 15 -- .../33_deploy_initNewExchange.js | 12 -- rinkeby_migrations/3_deploy_Rates.js | 20 --- rinkeby_migrations/4_deploy_FeeAccount.js | 15 -- .../5_deploy_AugmintReserves.js | 11 -- rinkeby_migrations/6_deploy_TokenAEur.js | 9 -- .../7_deploy_InterestEarnedAccount.js | 11 -- .../8_deploy_MonetarySupervisor.js | 39 ----- rinkeby_migrations/9_deploy_LoanManager.js | 34 ---- 34 files changed, 1041 deletions(-) delete mode 100644 rinkeby_migrations/10_deploy_Locker.js delete mode 100644 rinkeby_migrations/11_deploy_Exchange.js delete mode 100644 rinkeby_migrations/12_add_legacyTokens.js delete mode 100644 rinkeby_migrations/13_authorise_MonetaryBoard.js delete mode 100644 rinkeby_migrations/14_deploy_new_MonetarySupervisor.js delete mode 100644 rinkeby_migrations/15_set_new_MonetarySupervisor_live.js delete mode 100644 rinkeby_migrations/16_deploy_new_Exchange.js delete mode 100644 rinkeby_migrations/17_new_TokenAEur.js delete mode 100644 rinkeby_migrations/18_set_new_MonetarySupervisor_live.js delete mode 100644 rinkeby_migrations/19_redeploy.js delete mode 100644 rinkeby_migrations/1_initial_migration.js delete mode 100644 rinkeby_migrations/20_init_new_deploy.js delete mode 100644 rinkeby_migrations/21_setup_signers.js delete mode 100644 rinkeby_migrations/22_deployRink0004_migrate_MSv0_5_0.js delete mode 100644 rinkeby_migrations/22_deploy_Rink0004_interest_adjustment.js delete mode 100644 rinkeby_migrations/23_executeRink0004_and_revokeOldPermissions.js delete mode 100644 rinkeby_migrations/24_deploy_new_Locker.js delete mode 100644 rinkeby_migrations/25_deploy_fixInitNewLocker.js delete mode 100644 rinkeby_migrations/26_deploy_new_Exchange.js delete mode 100644 rinkeby_migrations/27_deploy_initNewExchange.js delete mode 100644 rinkeby_migrations/28_deploy_initNewExchange2.js delete mode 100644 rinkeby_migrations/29_deploy_changeSBSigners.js delete mode 100644 rinkeby_migrations/2_deploy_Libs.js delete mode 100644 rinkeby_migrations/30_deploy_changeDefaultingFee.js delete mode 100644 rinkeby_migrations/31_deploy_adjustInterest.js delete mode 100644 rinkeby_migrations/32_deploy_new_Exchange.js delete mode 100644 rinkeby_migrations/33_deploy_initNewExchange.js delete mode 100644 rinkeby_migrations/3_deploy_Rates.js delete mode 100644 rinkeby_migrations/4_deploy_FeeAccount.js delete mode 100644 rinkeby_migrations/5_deploy_AugmintReserves.js delete mode 100644 rinkeby_migrations/6_deploy_TokenAEur.js delete mode 100644 rinkeby_migrations/7_deploy_InterestEarnedAccount.js delete mode 100644 rinkeby_migrations/8_deploy_MonetarySupervisor.js delete mode 100644 rinkeby_migrations/9_deploy_LoanManager.js 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_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/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/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/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. - }); -}; From df3355ee73c48f72ce973b8aa0e92427272eb01d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 18 Oct 2018 13:43:59 +0200 Subject: [PATCH 58/90] rinkeby script: deploy all contracts --- rinkeby_migrations/1_deploy_all.js | 70 ++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 rinkeby_migrations/1_deploy_all.js 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 From 040add991bc8a6f5bf64552074263e6cbe00df09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 18 Oct 2018 14:02:58 +0200 Subject: [PATCH 59/90] delete old sb scripts (rinkeby) --- .../rinkeby/Rink0001_initNewContracts.sol | 145 ------------------ .../rinkeby/Rink0002_setupPreTokenSigners.sol | 36 ----- .../rinkeby/Rink0003_setupSBSigners.sol | 37 ----- .../rinkeby/Rink0004_adjustInterest.sol | 52 ------- .../rinkeby/Rink0004_migrate_MSv0_5_0.sol | 61 -------- .../rinkeby/Rink0005_initNewLocker.sol | 38 ----- .../rinkeby/Rink0006_fixInitNewLocker.sol | 48 ------ .../rinkeby/Rink0007_initNewExchange.sol | 34 ---- .../rinkeby/Rink0008_initNewExchange2.sol | 31 ---- .../rinkeby/Rink0009_changeSBSigners.sol | 35 ----- .../rinkeby/Rink0010_changeDefaultingFee.sol | 39 ----- .../rinkeby/Rink0011_adjustInterest.sol | 68 -------- .../rinkeby/Rink0012_initNewExchange.sol | 30 ---- 13 files changed, 654 deletions(-) delete mode 100644 contracts/SB_scripts/rinkeby/Rink0001_initNewContracts.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0002_setupPreTokenSigners.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0003_setupSBSigners.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0004_adjustInterest.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0004_migrate_MSv0_5_0.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0005_initNewLocker.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0006_fixInitNewLocker.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0007_initNewExchange.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0008_initNewExchange2.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0009_changeSBSigners.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0010_changeDefaultingFee.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0011_adjustInterest.sol delete mode 100644 contracts/SB_scripts/rinkeby/Rink0012_initNewExchange.sol 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"); - - } - -} From bee2b4ba98ab55dcb871bcc635fbf878cb6b28f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 18 Oct 2018 15:36:57 +0200 Subject: [PATCH 60/90] abiniser files (new abis, rinkeby deploments) --- ..._ABI_024b81d1a1f75241167a8a0f6e62326f.json | 205 +++++ ..._ABI_d3e7f8a261b756f9c40da097608b21cd.json | 588 +++++++++++++ ..._ABI_fdf5fde95aa940c6dbfb8353c572c5fb.json | 698 +++++++++++++++ ..._ABI_f59526398823aef0f0c1454d0b6b4eac.json | 629 ++++++++++++++ ..._ABI_7f500b43397413e97de925528187f9cd.json | 693 +++++++++++++++ ..._ABI_dd40c0d39ea8bad8a388522667a84687.json | 332 +++++++ ..._ABI_7f69e33e7b345c780ac9e43f391437d9.json | 490 +++++++++++ ..._ABI_dd40c0d39ea8bad8a388522667a84687.json | 332 +++++++ ..._ABI_2ea91d34a7bfefc8f38ef0e8a5ae24a5.json | 809 ++++++++++++++++++ .../4/AugmintReserves_DEPLOYS.json | 24 + abiniser/deployments/4/Exchange_DEPLOYS.json | 24 + .../deployments/4/FeeAccount_DEPLOYS.json | 24 + .../4/InterestEarnedAccount_DEPLOYS.json | 24 + .../deployments/4/LoanManager_DEPLOYS.json | 24 + abiniser/deployments/4/Locker_DEPLOYS.json | 24 + .../deployments/4/Migrations_DEPLOYS.json | 24 + .../4/MonetarySupervisor_DEPLOYS.json | 24 + .../deployments/4/PreTokenProxy_DEPLOYS.json | 24 + abiniser/deployments/4/PreToken_DEPLOYS.json | 24 + abiniser/deployments/4/Rates_DEPLOYS.json | 24 + .../4/StabilityBoardProxy_DEPLOYS.json | 24 + abiniser/deployments/4/TokenAEur_DEPLOYS.json | 24 + 22 files changed, 5088 insertions(+) create mode 100644 abiniser/abis/AugmintReserves_ABI_024b81d1a1f75241167a8a0f6e62326f.json create mode 100644 abiniser/abis/Exchange_ABI_d3e7f8a261b756f9c40da097608b21cd.json create mode 100644 abiniser/abis/LoanManager_ABI_fdf5fde95aa940c6dbfb8353c572c5fb.json create mode 100644 abiniser/abis/Locker_ABI_f59526398823aef0f0c1454d0b6b4eac.json create mode 100644 abiniser/abis/MonetarySupervisor_ABI_7f500b43397413e97de925528187f9cd.json create mode 100644 abiniser/abis/PreTokenProxy_ABI_dd40c0d39ea8bad8a388522667a84687.json create mode 100644 abiniser/abis/PreToken_ABI_7f69e33e7b345c780ac9e43f391437d9.json create mode 100644 abiniser/abis/StabilityBoardProxy_ABI_dd40c0d39ea8bad8a388522667a84687.json create mode 100644 abiniser/abis/TokenAEur_ABI_2ea91d34a7bfefc8f38ef0e8a5ae24a5.json create mode 100644 abiniser/deployments/4/AugmintReserves_DEPLOYS.json create mode 100644 abiniser/deployments/4/Exchange_DEPLOYS.json create mode 100644 abiniser/deployments/4/FeeAccount_DEPLOYS.json create mode 100644 abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json create mode 100644 abiniser/deployments/4/LoanManager_DEPLOYS.json create mode 100644 abiniser/deployments/4/Locker_DEPLOYS.json create mode 100644 abiniser/deployments/4/Migrations_DEPLOYS.json create mode 100644 abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json create mode 100644 abiniser/deployments/4/PreTokenProxy_DEPLOYS.json create mode 100644 abiniser/deployments/4/PreToken_DEPLOYS.json create mode 100644 abiniser/deployments/4/Rates_DEPLOYS.json create mode 100644 abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json create mode 100644 abiniser/deployments/4/TokenAEur_DEPLOYS.json 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/4/AugmintReserves_DEPLOYS.json b/abiniser/deployments/4/AugmintReserves_DEPLOYS.json new file mode 100644 index 00000000..aad16a8a --- /dev/null +++ b/abiniser/deployments/4/AugmintReserves_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "AugmintReserves", + "latestAbiHash": "024b81d1a1f75241167a8a0f6e62326f", + "deployedAbis": { + "024b81d1a1f75241167a8a0f6e62326f": { + "latestDeployedAddress": "0xc036a1dd59ac55e2fb6b3d7416cb4ecc44605834", + "deployments": { + "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": "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/4/Exchange_DEPLOYS.json b/abiniser/deployments/4/Exchange_DEPLOYS.json new file mode 100644 index 00000000..caae3b28 --- /dev/null +++ b/abiniser/deployments/4/Exchange_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "Exchange", + "latestAbiHash": "d3e7f8a261b756f9c40da097608b21cd", + "deployedAbis": { + "d3e7f8a261b756f9c40da097608b21cd": { + "latestDeployedAddress": "0xdf47d51028daff13424f42523fdac73079ab901b", + "deployments": { + "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": "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/4/FeeAccount_DEPLOYS.json b/abiniser/deployments/4/FeeAccount_DEPLOYS.json new file mode 100644 index 00000000..4509930c --- /dev/null +++ b/abiniser/deployments/4/FeeAccount_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "FeeAccount", + "latestAbiHash": "67db260db12738df3cced3511d34c65c", + "deployedAbis": { + "67db260db12738df3cced3511d34c65c": { + "latestDeployedAddress": "0xb77f9cdda72eec47a57793be088c7b523f6b5014", + "deployments": { + "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": "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" + } + } + } + } +} \ No newline at end of file diff --git a/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json b/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json new file mode 100644 index 00000000..37bbb54e --- /dev/null +++ b/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "InterestEarnedAccount", + "latestAbiHash": "11b039ce783db308e1a9b5f46f05824f", + "deployedAbis": { + "11b039ce783db308e1a9b5f46f05824f": { + "latestDeployedAddress": "0x489cbf1674b575e6dfcff0a4f2bbc74f7e9dde28", + "deployments": { + "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": "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" + } + } + } + } +} \ No newline at end of file diff --git a/abiniser/deployments/4/LoanManager_DEPLOYS.json b/abiniser/deployments/4/LoanManager_DEPLOYS.json new file mode 100644 index 00000000..f4b567ff --- /dev/null +++ b/abiniser/deployments/4/LoanManager_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "LoanManager", + "latestAbiHash": "fdf5fde95aa940c6dbfb8353c572c5fb", + "deployedAbis": { + "fdf5fde95aa940c6dbfb8353c572c5fb": { + "latestDeployedAddress": "0x6cb7731c78e677f85942b5f1d646b3485e5820c1", + "deployments": { + "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": "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/4/Locker_DEPLOYS.json b/abiniser/deployments/4/Locker_DEPLOYS.json new file mode 100644 index 00000000..9c66612c --- /dev/null +++ b/abiniser/deployments/4/Locker_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "Locker", + "latestAbiHash": "f59526398823aef0f0c1454d0b6b4eac", + "deployedAbis": { + "f59526398823aef0f0c1454d0b6b4eac": { + "latestDeployedAddress": "0x6d84ab6c385b827e58c358d078ac7b1c61b68821", + "deployments": { + "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": "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/4/Migrations_DEPLOYS.json b/abiniser/deployments/4/Migrations_DEPLOYS.json new file mode 100644 index 00000000..ef298878 --- /dev/null +++ b/abiniser/deployments/4/Migrations_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "Migrations", + "latestAbiHash": "78141a323f4a8416891b06a0a2b90065", + "deployedAbis": { + "78141a323f4a8416891b06a0a2b90065": { + "latestDeployedAddress": "0xc9a7258b2b1ea36ce735793e4816ad949532c9fd", + "deployments": { + "0xc9a7258b2b1ea36ce735793e4816ad949532c9fd": { + "generatedAt": "2018-10-18T13:35:02.323Z", + "truffleContractFileUpdatedAt": "2018-10-18T11:36:36.823Z", + "deployTransactionHash": "0xf529f773b4efda519e62d6dcbb71e5e1fa7a0223599f5db5edf792e85a3f9679", + "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" + } + } + } + } +} \ No newline at end of file diff --git a/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json b/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json new file mode 100644 index 00000000..415bc747 --- /dev/null +++ b/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "MonetarySupervisor", + "latestAbiHash": "7f500b43397413e97de925528187f9cd", + "deployedAbis": { + "7f500b43397413e97de925528187f9cd": { + "latestDeployedAddress": "0xcec3574eca89409b15a8a72a6e737c4171457871", + "deployments": { + "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": "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/4/PreTokenProxy_DEPLOYS.json b/abiniser/deployments/4/PreTokenProxy_DEPLOYS.json new file mode 100644 index 00000000..09bbd813 --- /dev/null +++ b/abiniser/deployments/4/PreTokenProxy_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "PreTokenProxy", + "latestAbiHash": "dd40c0d39ea8bad8a388522667a84687", + "deployedAbis": { + "dd40c0d39ea8bad8a388522667a84687": { + "latestDeployedAddress": "0xb7cae2c48f3f34b9696fd290001dea16b299498a", + "deployments": { + "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": "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/4/PreToken_DEPLOYS.json b/abiniser/deployments/4/PreToken_DEPLOYS.json new file mode 100644 index 00000000..f363ad3b --- /dev/null +++ b/abiniser/deployments/4/PreToken_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "PreToken", + "latestAbiHash": "7f69e33e7b345c780ac9e43f391437d9", + "deployedAbis": { + "7f69e33e7b345c780ac9e43f391437d9": { + "latestDeployedAddress": "0xa7b67e7e3e7f1e76e8d799a690f675abeb85c788", + "deployments": { + "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": "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/4/Rates_DEPLOYS.json b/abiniser/deployments/4/Rates_DEPLOYS.json new file mode 100644 index 00000000..47a19020 --- /dev/null +++ b/abiniser/deployments/4/Rates_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "Rates", + "latestAbiHash": "73a17ebb0acc71773371c6a8e1c8e6ce", + "deployedAbis": { + "73a17ebb0acc71773371c6a8e1c8e6ce": { + "latestDeployedAddress": "0xdfa3a0aeb9645a55b684cb3ace8c42d018405bda", + "deployments": { + "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": "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" + } + } + } + } +} \ No newline at end of file diff --git a/abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json b/abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json new file mode 100644 index 00000000..5a6280c2 --- /dev/null +++ b/abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "StabilityBoardProxy", + "latestAbiHash": "dd40c0d39ea8bad8a388522667a84687", + "deployedAbis": { + "dd40c0d39ea8bad8a388522667a84687": { + "latestDeployedAddress": "0x50d281c28846576eaaf679ab6f3baac52b776e72", + "deployments": { + "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": "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/4/TokenAEur_DEPLOYS.json b/abiniser/deployments/4/TokenAEur_DEPLOYS.json new file mode 100644 index 00000000..a5595c41 --- /dev/null +++ b/abiniser/deployments/4/TokenAEur_DEPLOYS.json @@ -0,0 +1,24 @@ +{ + "contractName": "TokenAEur", + "latestAbiHash": "2ea91d34a7bfefc8f38ef0e8a5ae24a5", + "deployedAbis": { + "2ea91d34a7bfefc8f38ef0e8a5ae24a5": { + "latestDeployedAddress": "0x0557183334edc23a666201edc6b0aa2787e2ad3f", + "deployments": { + "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": "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 From eb0993e1cda2d142fa1225742b3c1fde4f56876d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 18 Oct 2018 16:29:41 +0200 Subject: [PATCH 61/90] rinkeby script: init all contracts --- .../rinkeby/Rinkeby_0001_initAll.sol | 118 ++++++++++++++++++ rinkeby_migrations/2_deploy_init_all.js | 16 +++ 2 files changed, 134 insertions(+) create mode 100644 contracts/SB_scripts/rinkeby/Rinkeby_0001_initAll.sol create mode 100644 rinkeby_migrations/2_deploy_init_all.js 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/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 From 50d94361193ab0fc1e78353a9f43e3bd7749fc2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Thu, 18 Oct 2018 18:15:03 +0200 Subject: [PATCH 62/90] abiniser files (local deployments) --- .../999/AugmintReserves_DEPLOYS.json | 20 ++++++++++++++++++- .../deployments/999/Exchange_DEPLOYS.json | 20 ++++++++++++++++++- .../deployments/999/FeeAccount_DEPLOYS.json | 14 ++++++------- .../999/InterestEarnedAccount_DEPLOYS.json | 10 +++++----- .../deployments/999/LoanManager_DEPLOYS.json | 20 ++++++++++++++++++- abiniser/deployments/999/Locker_DEPLOYS.json | 20 ++++++++++++++++++- .../deployments/999/Migrations_DEPLOYS.json | 10 +++++----- .../999/MonetarySupervisor_DEPLOYS.json | 20 ++++++++++++++++++- .../999/PreTokenProxy_DEPLOYS.json | 20 ++++++++++++++++++- .../deployments/999/PreToken_DEPLOYS.json | 20 ++++++++++++++++++- abiniser/deployments/999/Rates_DEPLOYS.json | 10 +++++----- .../999/StabilityBoardProxy_DEPLOYS.json | 20 ++++++++++++++++++- .../deployments/999/TokenAEur_DEPLOYS.json | 20 ++++++++++++++++++- 13 files changed, 193 insertions(+), 31 deletions(-) diff --git a/abiniser/deployments/999/AugmintReserves_DEPLOYS.json b/abiniser/deployments/999/AugmintReserves_DEPLOYS.json index e8fae047..59b4747d 100644 --- a/abiniser/deployments/999/AugmintReserves_DEPLOYS.json +++ b/abiniser/deployments/999/AugmintReserves_DEPLOYS.json @@ -1,6 +1,6 @@ { "contractName": "AugmintReserves", - "latestAbiHash": "fe74b7986dafb00f221486e790fc70ec", + "latestAbiHash": "024b81d1a1f75241167a8a0f6e62326f", "deployedAbis": { "dfbca9f4d0da7a3517b2832dc1c04d9a": { "latestDeployedAddress": "0xb0a2a8e846b66c7384f52635cecef5280f766c8b", @@ -80,6 +80,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": "0x1b9441428f9e682bab4f9cc70fdf50adcc3411f4", + "deployments": { + "0x1b9441428f9e682bab4f9cc70fdf50adcc3411f4": { + "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": "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/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 From 824dc7a02a91b84cefaf2fdf249207a21100d896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 19 Oct 2018 17:43:14 +0200 Subject: [PATCH 63/90] rinkeby script: redeploy all contracts --- rinkeby_migrations/3_redeploy_all.js | 60 ++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 rinkeby_migrations/3_redeploy_all.js 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 From b69b096d4e98d8d909c9380806279d65b4448951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 29 Oct 2018 17:55:56 +0100 Subject: [PATCH 64/90] abiniser deployment descriptors for second rinkeby deploy --- .../deployments/4/AugmintReserves_DEPLOYS.json | 15 ++++++++++++++- abiniser/deployments/4/Exchange_DEPLOYS.json | 15 ++++++++++++++- abiniser/deployments/4/FeeAccount_DEPLOYS.json | 15 ++++++++++++++- .../4/InterestEarnedAccount_DEPLOYS.json | 15 ++++++++++++++- abiniser/deployments/4/LoanManager_DEPLOYS.json | 15 ++++++++++++++- abiniser/deployments/4/Locker_DEPLOYS.json | 15 ++++++++++++++- .../deployments/4/MonetarySupervisor_DEPLOYS.json | 15 ++++++++++++++- abiniser/deployments/4/Rates_DEPLOYS.json | 15 ++++++++++++++- .../4/StabilityBoardProxy_DEPLOYS.json | 15 ++++++++++++++- abiniser/deployments/4/TokenAEur_DEPLOYS.json | 15 ++++++++++++++- 10 files changed, 140 insertions(+), 10 deletions(-) diff --git a/abiniser/deployments/4/AugmintReserves_DEPLOYS.json b/abiniser/deployments/4/AugmintReserves_DEPLOYS.json index aad16a8a..73e5fc46 100644 --- a/abiniser/deployments/4/AugmintReserves_DEPLOYS.json +++ b/abiniser/deployments/4/AugmintReserves_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "024b81d1a1f75241167a8a0f6e62326f", "deployedAbis": { "024b81d1a1f75241167a8a0f6e62326f": { - "latestDeployedAddress": "0xc036a1dd59ac55e2fb6b3d7416cb4ecc44605834", + "latestDeployedAddress": "0x33bec125657470e53887400666bdeed360b2168a", "deployments": { "0xc036a1dd59ac55e2fb6b3d7416cb4ecc44605834": { "generatedAt": "2018-10-18T13:35:02.347Z", @@ -17,6 +17,19 @@ "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" + }, + "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": "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 caae3b28..a54aa917 100644 --- a/abiniser/deployments/4/Exchange_DEPLOYS.json +++ b/abiniser/deployments/4/Exchange_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "d3e7f8a261b756f9c40da097608b21cd", "deployedAbis": { "d3e7f8a261b756f9c40da097608b21cd": { - "latestDeployedAddress": "0xdf47d51028daff13424f42523fdac73079ab901b", + "latestDeployedAddress": "0xe5d6d0c107eae79d2d30798f252ac6ff5ecad459", "deployments": { "0xdf47d51028daff13424f42523fdac73079ab901b": { "generatedAt": "2018-10-18T13:35:02.438Z", @@ -17,6 +17,19 @@ "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" + }, + "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": "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 4509930c..9c2b2940 100644 --- a/abiniser/deployments/4/FeeAccount_DEPLOYS.json +++ b/abiniser/deployments/4/FeeAccount_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "67db260db12738df3cced3511d34c65c", "deployedAbis": { "67db260db12738df3cced3511d34c65c": { - "latestDeployedAddress": "0xb77f9cdda72eec47a57793be088c7b523f6b5014", + "latestDeployedAddress": "0xaa16ede9093bb4140e2715ed9a1e41cdfd9d9c29", "deployments": { "0xb77f9cdda72eec47a57793be088c7b523f6b5014": { "generatedAt": "2018-10-18T13:35:02.354Z", @@ -17,6 +17,19 @@ "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" + }, + "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": "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 37bbb54e..be5c1f7f 100644 --- a/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json +++ b/abiniser/deployments/4/InterestEarnedAccount_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "11b039ce783db308e1a9b5f46f05824f", "deployedAbis": { "11b039ce783db308e1a9b5f46f05824f": { - "latestDeployedAddress": "0x489cbf1674b575e6dfcff0a4f2bbc74f7e9dde28", + "latestDeployedAddress": "0xdd96979697b76787b5062084eea60bf929ddd844", "deployments": { "0x489cbf1674b575e6dfcff0a4f2bbc74f7e9dde28": { "generatedAt": "2018-10-18T13:35:02.360Z", @@ -17,6 +17,19 @@ "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" + }, + "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": "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 f4b567ff..f3910871 100644 --- a/abiniser/deployments/4/LoanManager_DEPLOYS.json +++ b/abiniser/deployments/4/LoanManager_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "fdf5fde95aa940c6dbfb8353c572c5fb", "deployedAbis": { "fdf5fde95aa940c6dbfb8353c572c5fb": { - "latestDeployedAddress": "0x6cb7731c78e677f85942b5f1d646b3485e5820c1", + "latestDeployedAddress": "0x3792c5a5077dacfe331b81837ef73bc0ea721d90", "deployments": { "0x6cb7731c78e677f85942b5f1d646b3485e5820c1": { "generatedAt": "2018-10-18T13:35:02.404Z", @@ -17,6 +17,19 @@ "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" + }, + "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": "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 9c66612c..8ecd4747 100644 --- a/abiniser/deployments/4/Locker_DEPLOYS.json +++ b/abiniser/deployments/4/Locker_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "f59526398823aef0f0c1454d0b6b4eac", "deployedAbis": { "f59526398823aef0f0c1454d0b6b4eac": { - "latestDeployedAddress": "0x6d84ab6c385b827e58c358d078ac7b1c61b68821", + "latestDeployedAddress": "0xc0b97fe5cad0d43d0c974c4e9a00312dc661f8ab", "deployments": { "0x6d84ab6c385b827e58c358d078ac7b1c61b68821": { "generatedAt": "2018-10-18T13:35:02.423Z", @@ -17,6 +17,19 @@ "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" + }, + "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": "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/MonetarySupervisor_DEPLOYS.json b/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json index 415bc747..81ecca9e 100644 --- a/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json +++ b/abiniser/deployments/4/MonetarySupervisor_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "7f500b43397413e97de925528187f9cd", "deployedAbis": { "7f500b43397413e97de925528187f9cd": { - "latestDeployedAddress": "0xcec3574eca89409b15a8a72a6e737c4171457871", + "latestDeployedAddress": "0x4a7f6ecbe8b324a55b85adcc45313a412957b8ea", "deployments": { "0xcec3574eca89409b15a8a72a6e737c4171457871": { "generatedAt": "2018-10-18T13:35:02.380Z", @@ -17,6 +17,19 @@ "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" + }, + "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": "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/Rates_DEPLOYS.json b/abiniser/deployments/4/Rates_DEPLOYS.json index 47a19020..09818490 100644 --- a/abiniser/deployments/4/Rates_DEPLOYS.json +++ b/abiniser/deployments/4/Rates_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "73a17ebb0acc71773371c6a8e1c8e6ce", "deployedAbis": { "73a17ebb0acc71773371c6a8e1c8e6ce": { - "latestDeployedAddress": "0xdfa3a0aeb9645a55b684cb3ace8c42d018405bda", + "latestDeployedAddress": "0xee8c7a3e99945a5207dca026504d67527125da9c", "deployments": { "0xdfa3a0aeb9645a55b684cb3ace8c42d018405bda": { "generatedAt": "2018-10-18T13:35:02.334Z", @@ -17,6 +17,19 @@ "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" + }, + "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": "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/StabilityBoardProxy_DEPLOYS.json b/abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json index 5a6280c2..b720d02d 100644 --- a/abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json +++ b/abiniser/deployments/4/StabilityBoardProxy_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "dd40c0d39ea8bad8a388522667a84687", "deployedAbis": { "dd40c0d39ea8bad8a388522667a84687": { - "latestDeployedAddress": "0x50d281c28846576eaaf679ab6f3baac52b776e72", + "latestDeployedAddress": "0xa612de13b629a1ff790c1f4e41d0422d2bb50a30", "deployments": { "0x50d281c28846576eaaf679ab6f3baac52b776e72": { "generatedAt": "2018-10-18T13:35:02.447Z", @@ -17,6 +17,19 @@ "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/TokenAEur_DEPLOYS.json b/abiniser/deployments/4/TokenAEur_DEPLOYS.json index a5595c41..11b5c3c0 100644 --- a/abiniser/deployments/4/TokenAEur_DEPLOYS.json +++ b/abiniser/deployments/4/TokenAEur_DEPLOYS.json @@ -3,7 +3,7 @@ "latestAbiHash": "2ea91d34a7bfefc8f38ef0e8a5ae24a5", "deployedAbis": { "2ea91d34a7bfefc8f38ef0e8a5ae24a5": { - "latestDeployedAddress": "0x0557183334edc23a666201edc6b0aa2787e2ad3f", + "latestDeployedAddress": "0x79065a165ec09e6a89d584a14872802717fe12a3", "deployments": { "0x0557183334edc23a666201edc6b0aa2787e2ad3f": { "generatedAt": "2018-10-18T13:35:02.366Z", @@ -17,6 +17,19 @@ "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": "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" } } } From 6156d81cc6178821f41e55d3b40585463fbe01b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 29 Oct 2018 17:58:36 +0100 Subject: [PATCH 65/90] remove duplicate entry from local abiniser deployment descriptor --- .../999/AugmintReserves_DEPLOYS.json | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/abiniser/deployments/999/AugmintReserves_DEPLOYS.json b/abiniser/deployments/999/AugmintReserves_DEPLOYS.json index 59b4747d..e071c11a 100644 --- a/abiniser/deployments/999/AugmintReserves_DEPLOYS.json +++ b/abiniser/deployments/999/AugmintReserves_DEPLOYS.json @@ -63,24 +63,6 @@ } } }, - "fe74b7986dafb00f221486e790fc70ec": { - "latestDeployedAddress": "0x1b9441428f9e682bab4f9cc70fdf50adcc3411f4", - "deployments": { - "0x1b9441428f9e682bab4f9cc70fdf50adcc3411f4": { - "generatedAt": "2018-08-14T19:51:18.010Z", - "truffleContractFileUpdatedAt": "2018-08-14T19:50:56.846Z", - "deployTransactionHash": "0x5e29c445328b0a15af223d0e3c551a2bbe5bf9fb4f69078aac8c9ee2c486787c", - "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" - } - } - }, "024b81d1a1f75241167a8a0f6e62326f": { "latestDeployedAddress": "0x1b9441428f9e682bab4f9cc70fdf50adcc3411f4", "deployments": { From 4ab380b3babd34260c59aa6ff413de2cef3522a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Mon, 29 Oct 2018 18:12:20 +0100 Subject: [PATCH 66/90] clean up local abiniser deployment descriptor for AugmintReserves --- .../999/AugmintReserves_DEPLOYS.json | 61 ------------------- 1 file changed, 61 deletions(-) diff --git a/abiniser/deployments/999/AugmintReserves_DEPLOYS.json b/abiniser/deployments/999/AugmintReserves_DEPLOYS.json index e071c11a..e5c7fb7b 100644 --- a/abiniser/deployments/999/AugmintReserves_DEPLOYS.json +++ b/abiniser/deployments/999/AugmintReserves_DEPLOYS.json @@ -2,67 +2,6 @@ "contractName": "AugmintReserves", "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" - } - } - }, "024b81d1a1f75241167a8a0f6e62326f": { "latestDeployedAddress": "0x1b9441428f9e682bab4f9cc70fdf50adcc3411f4", "deployments": { From 430ccccdc59b3df1e3cd1fa25707f2a469a4bf5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 30 Oct 2018 16:54:37 +0100 Subject: [PATCH 67/90] rinkeby redeploy init scripts --- .../rinkeby/Rinkeby_0002_redeployInitAll.sol | 108 ++++++++++++++++++ .../rinkeby/Rinkeby_0003_migrateLegacy.sol | 95 +++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 contracts/SB_scripts/rinkeby/Rinkeby_0002_redeployInitAll.sol create mode 100644 contracts/SB_scripts/rinkeby/Rinkeby_0003_migrateLegacy.sol 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 From b3895ca5794d88a14d6bfe14fb0ed98283954cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 30 Oct 2018 17:01:49 +0100 Subject: [PATCH 68/90] deploy script for redeploy init scripts --- rinkeby_migrations/4_deploy_redeploy_init.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 rinkeby_migrations/4_deploy_redeploy_init.js diff --git a/rinkeby_migrations/4_deploy_redeploy_init.js b/rinkeby_migrations/4_deploy_redeploy_init.js new file mode 100644 index 00000000..146d09ae --- /dev/null +++ b/rinkeby_migrations/4_deploy_redeploy_init.js @@ -0,0 +1,20 @@ +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 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 + await deployer.deploy(Rinkeby_0003_migrateLegacy); + + console.log("Done with migration step " + MIGRATION_STEP_NUMBER); + await Migrations.at(MIGRATIONS_ADDRESS).setCompleted(MIGRATION_STEP_NUMBER); + }); +}; \ No newline at end of file From 7a41f6bd2a4112fdf9a1aea54738810b31a1c522 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 30 Oct 2018 17:23:28 +0100 Subject: [PATCH 69/90] rinkeby redeploy legacy setup script --- .../rinkeby/Rinkeby_0004_setupLegacy.sol | 94 +++++++++++++++++++ rinkeby_migrations/4_deploy_redeploy_init.js | 4 + 2 files changed, 98 insertions(+) create mode 100644 contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol 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..7a077d95 --- /dev/null +++ b/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol @@ -0,0 +1,94 @@ +/* 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); + + /****************************************************************************** + * Migrate KPIs from old MonetarySupervisor + ******************************************************************************/ + uint oldTotalLoan = OLD_MONETARY_SUPERVISOR.totalLoanAmount(); + uint oldTotalLock = OLD_MONETARY_SUPERVISOR.totalLockedAmount(); + NEW_MONETARY_SUPERVISOR.adjustKPIs(oldTotalLoan, oldTotalLock); + + + /****************************************************************************** + * Setup permissions in legacy contracts for new contracts + ******************************************************************************/ + OLD_FEE_ACCOUNT.grantPermission(address(NEW_MONETARY_SUPERVISOR), "NoTransferFee"); + + /****************************************************************************** + * Set new Rates in old Exchange + ******************************************************************************/ + OLD_EXCHANGE.setRatesContract(NEW_RATES); + + /****************************************************************************** + * 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); + + } +} \ No newline at end of file diff --git a/rinkeby_migrations/4_deploy_redeploy_init.js b/rinkeby_migrations/4_deploy_redeploy_init.js index 146d09ae..8fd82f9a 100644 --- a/rinkeby_migrations/4_deploy_redeploy_init.js +++ b/rinkeby_migrations/4_deploy_redeploy_init.js @@ -1,6 +1,7 @@ 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 MIGRATION_STEP_NUMBER = 4; const MIGRATIONS_ADDRESS = "0xc9a7258b2b1ea36ce735793e4816ad949532c9fd"; @@ -14,6 +15,9 @@ module.exports = function(deployer) { // script for migrate legacy contracts await deployer.deploy(Rinkeby_0003_migrateLegacy); + // script for setup legacy contract dependencies + await deployer.deploy(Rinkeby_0004_setupLegacy); + console.log("Done with migration step " + MIGRATION_STEP_NUMBER); await Migrations.at(MIGRATIONS_ADDRESS).setCompleted(MIGRATION_STEP_NUMBER); }); From c7787da9fa605328bc694a939301d534cbbbde2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 30 Oct 2018 17:28:22 +0100 Subject: [PATCH 70/90] rinkeby scripts: disable old products in legacy contracts --- .../rinkeby/Rinkeby_0004_setupLegacy.sol | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol b/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol index 7a077d95..1c364637 100644 --- a/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol +++ b/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol @@ -90,5 +90,31 @@ contract Rinkeby_0004_setupLegacy { ******************************************************************************/ 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 From 858c7b3bb13b4a81c7489ca3263f3ae9660b92b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 30 Oct 2018 17:35:44 +0100 Subject: [PATCH 71/90] rinkeby scripts: setup SB signers --- .../rinkeby/Rinkeby_0005_setupSigners.sol | 22 +++++++++++++++++++ rinkeby_migrations/4_deploy_redeploy_init.js | 6 ++++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 contracts/SB_scripts/rinkeby/Rinkeby_0005_setupSigners.sol 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/rinkeby_migrations/4_deploy_redeploy_init.js b/rinkeby_migrations/4_deploy_redeploy_init.js index 8fd82f9a..6c75f2b4 100644 --- a/rinkeby_migrations/4_deploy_redeploy_init.js +++ b/rinkeby_migrations/4_deploy_redeploy_init.js @@ -2,6 +2,7 @@ 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 MIGRATION_STEP_NUMBER = 4; const MIGRATIONS_ADDRESS = "0xc9a7258b2b1ea36ce735793e4816ad949532c9fd"; @@ -12,12 +13,15 @@ module.exports = function(deployer) { // script for init new contracts await deployer.deploy(Rinkeby_0002_redeployInitAll); - // script for migrate legacy contracts + // 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); + console.log("Done with migration step " + MIGRATION_STEP_NUMBER); await Migrations.at(MIGRATIONS_ADDRESS).setCompleted(MIGRATION_STEP_NUMBER); }); From 9776cb8fee6430a6592ee70b58dfcee7eea4149e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 30 Oct 2018 18:40:31 +0100 Subject: [PATCH 72/90] rinkeby scripts: post deploy setup --- .../rinkeby/Rinkeby_0004_setupLegacy.sol | 43 -------- .../rinkeby/Rinkeby_0006_postDeploySetup.sol | 99 +++++++++++++++++++ rinkeby_migrations/4_deploy_redeploy_init.js | 4 + 3 files changed, 103 insertions(+), 43 deletions(-) create mode 100644 contracts/SB_scripts/rinkeby/Rinkeby_0006_postDeploySetup.sol diff --git a/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol b/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol index 1c364637..d4a830b0 100644 --- a/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol +++ b/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol @@ -62,13 +62,6 @@ contract Rinkeby_0004_setupLegacy { ******************************************************************************/ NEW_MONETARY_SUPERVISOR.setAcceptedLegacyAugmintToken(OLD_TOKEN_AEUR, true); - /****************************************************************************** - * Migrate KPIs from old MonetarySupervisor - ******************************************************************************/ - uint oldTotalLoan = OLD_MONETARY_SUPERVISOR.totalLoanAmount(); - uint oldTotalLock = OLD_MONETARY_SUPERVISOR.totalLockedAmount(); - NEW_MONETARY_SUPERVISOR.adjustKPIs(oldTotalLoan, oldTotalLock); - /****************************************************************************** * Setup permissions in legacy contracts for new contracts @@ -80,41 +73,5 @@ contract Rinkeby_0004_setupLegacy { ******************************************************************************/ OLD_EXCHANGE.setRatesContract(NEW_RATES); - /****************************************************************************** - * 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/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/rinkeby_migrations/4_deploy_redeploy_init.js b/rinkeby_migrations/4_deploy_redeploy_init.js index 6c75f2b4..1e9feb48 100644 --- a/rinkeby_migrations/4_deploy_redeploy_init.js +++ b/rinkeby_migrations/4_deploy_redeploy_init.js @@ -3,6 +3,7 @@ const Rinkeby_0002_redeployInitAll = artifacts.require("./Rinkeby_0002_redeployI 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"; @@ -22,6 +23,9 @@ module.exports = function(deployer) { // 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); }); From 0b6bbc3bcc6167b406b7a52eaea17a9bddc76836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 7 Nov 2018 16:58:25 +0100 Subject: [PATCH 73/90] add comment about misplaced step in rinkeby init scripts --- contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol b/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol index d4a830b0..c7ed11f0 100644 --- a/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol +++ b/contracts/SB_scripts/rinkeby/Rinkeby_0004_setupLegacy.sol @@ -71,6 +71,7 @@ contract Rinkeby_0004_setupLegacy { /****************************************************************************** * Set new Rates in old Exchange ******************************************************************************/ + // Note: this step should have been moved to Rinkeby_0006_postDeploySetup! OLD_EXCHANGE.setRatesContract(NEW_RATES); } From 9f5446578b0d66841efa7abe856ce34018f53cea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Fri, 9 Nov 2018 17:16:32 +0100 Subject: [PATCH 74/90] mainnet deploy and init scripts --- .../mainnet/Main0014_initNewContracts.sol | 114 ++++++++++++++++++ .../Main0015_migrateLegacyContracts.sol | 110 +++++++++++++++++ .../mainnet/Main0016_setupLegacy.sol | 60 +++++++++ .../mainnet/Main0017_setupSigners.sol | 22 ++++ .../mainnet/Main0018_postDeploySetup.sol | 92 ++++++++++++++ mainnet_migrations/30_deploy_all_contracts.js | 70 +++++++++++ mainnet_migrations/31_deploy_all_scripts.js | 32 +++++ 7 files changed, 500 insertions(+) create mode 100644 contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol create mode 100644 contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol create mode 100644 contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol create mode 100644 contracts/SB_scripts/mainnet/Main0017_setupSigners.sol create mode 100644 contracts/SB_scripts/mainnet/Main0018_postDeploySetup.sol create mode 100644 mainnet_migrations/30_deploy_all_contracts.js create mode 100644 mainnet_migrations/31_deploy_all_scripts.js diff --git a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol new file mode 100644 index 00000000..4f6ddcd6 --- /dev/null +++ b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol @@ -0,0 +1,114 @@ +/* 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 = ; + + /****************************************************************************** + * New contracts + ******************************************************************************/ + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(); + AugmintReserves public constant AUGMINT_RESERVES = AugmintReserves(); + Exchange public constant EXCHANGE = Exchange(); + FeeAccount public constant FEE_ACCOUNT = FeeAccount(); + InterestEarnedAccount public constant INTEREST_EARNED_ACCOUNT = InterestEarnedAccount(); + LoanManager public constant LOAN_MANAGER = LoanManager(); + Locker public constant LOCKER = Locker(); + MonetarySupervisor public constant MONETARY_SUPERVISOR = MonetarySupervisor(); + Rates public constant RATES = Rates(); + TokenAEur public constant TOKEN_AEUR = TokenAEur(); + PreToken public constant PRE_TOKEN = PreToken(); + PreTokenProxy public constant PRE_TOKEN_PROXY = PreTokenProxy(); + + 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"); + + + /****************************************************************************** + * 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..bea463e3 --- /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(); + + /****************************************************************************** + * 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..7789ed9c --- /dev/null +++ b/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol @@ -0,0 +1,60 @@ +/* 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(); + + /****************************************************************************** + * New contracts + ******************************************************************************/ + MonetarySupervisor public constant NEW_MONETARY_SUPERVISOR = MonetarySupervisor(); + + /****************************************************************************** + * 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), "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_setupSigners.sol b/contracts/SB_scripts/mainnet/Main0017_setupSigners.sol new file mode 100644 index 00000000..97fd55bc --- /dev/null +++ b/contracts/SB_scripts/mainnet/Main0017_setupSigners.sol @@ -0,0 +1,22 @@ +/* setup StabilityBoard signers in new StabilityBoardProxy on Mainnet */ + +pragma solidity 0.4.24; + +import "../../generic/MultiSig.sol"; +import "../../StabilityBoardProxy.sol"; + + +contract Main0017_setupSigners { + + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(); + + function execute(Main0017_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/mainnet/Main0018_postDeploySetup.sol b/contracts/SB_scripts/mainnet/Main0018_postDeploySetup.sol new file mode 100644 index 00000000..0e901a92 --- /dev/null +++ b/contracts/SB_scripts/mainnet/Main0018_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 Main0018_postDeploySetup { + + /****************************************************************************** + * StabilityBoardProxy + ******************************************************************************/ + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(); + + /****************************************************************************** + * New contracts + ******************************************************************************/ + MonetarySupervisor public constant NEW_MONETARY_SUPERVISOR = MonetarySupervisor(); + Rates public constant NEW_RATES = Rates(); + + /****************************************************************************** + * 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(Main0018_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/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..948bf2c5 --- /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_setupSigners = artifacts.require("./Main0017_setupSigners.sol"); +const Main0018_postDeploySetup = artifacts.require("./Main0018_postDeploySetup.sol"); + +const MIGRATION_STEP_NUMBER = 31; +const MIGRATIONS_ADDRESS = "???"; + +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 setup StabilityBoard signers + await deployer.deploy(Main0017_setupSigners); + + // script for post deploy setup + await deployer.deploy(Main0018_postDeploySetup); + + console.log("Done with migration step " + MIGRATION_STEP_NUMBER); + await Migrations.at(MIGRATIONS_ADDRESS).setCompleted(MIGRATION_STEP_NUMBER); + }); +}; From 3d1754baa1b3b5b3abfa7923820983a730a3c810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Tue, 13 Nov 2018 16:34:37 +0100 Subject: [PATCH 75/90] mainnet init script changes: add pretoken signers, move stabiproxy signers to first step --- .../mainnet/Main0014_initNewContracts.sol | 17 +++++++++++++- ...Setup.sol => Main0017_postDeploySetup.sol} | 4 ++-- .../mainnet/Main0017_setupSigners.sol | 22 ------------------- mainnet_migrations/31_deploy_all_scripts.js | 8 ++----- 4 files changed, 20 insertions(+), 31 deletions(-) rename contracts/SB_scripts/mainnet/{Main0018_postDeploySetup.sol => Main0017_postDeploySetup.sol} (97%) delete mode 100644 contracts/SB_scripts/mainnet/Main0017_setupSigners.sol diff --git a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol index 4f6ddcd6..7204d5dd 100644 --- a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol +++ b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol @@ -81,12 +81,27 @@ contract Main0014_initNewContracts { MONETARY_SUPERVISOR.grantPermission(address(LOCKER), "Locker"); - // PreToken permissions + // PreToken signers and permissions + + address[] memory preTokenSigners = new address[](3); + preTokenSigners[0] = 0xd8203A652452906586F2E6cB6e31f6f7fed094D4; // Sz.K. + preTokenSigners[1] = 0xf9ea0E2857405C859bb8647ECB11f931D1259753; // P.P. + PRE_TOKEN_PROXY.addSigners(preTokenSigners); + 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[](2); + stabilityProxySigners[0] = 0x53dbf6e8fe46307c7536eabb0d90cada3e732716; // Sz.V. + stabilityProxySigners[1] = 0xae162e28575ba898dc08d283f2be10ae8b4114a2; // Sz.K. + stabilityProxySigners[2] = 0x9de3f6e7cacbb7e1c2489dfce21abbb0ecee6213; // P.P. + STABILITY_BOARD_PROXY.addSigners(stabilityProxySigners); + + /****************************************************************************** * Add loan products ******************************************************************************/ diff --git a/contracts/SB_scripts/mainnet/Main0018_postDeploySetup.sol b/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol similarity index 97% rename from contracts/SB_scripts/mainnet/Main0018_postDeploySetup.sol rename to contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol index 0e901a92..73d027c6 100644 --- a/contracts/SB_scripts/mainnet/Main0018_postDeploySetup.sol +++ b/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol @@ -13,7 +13,7 @@ import "../../Rates.sol"; import "../../TokenAEur.sol"; import "../../StabilityBoardProxy.sol"; -contract Main0018_postDeploySetup { +contract Main0017_postDeploySetup { /****************************************************************************** * StabilityBoardProxy @@ -37,7 +37,7 @@ contract Main0018_postDeploySetup { Locker public constant OLD_LOCKER_2 = Locker(0x26438D7c52cE617dFc75A2F02eE816557f01e5Bb); MonetarySupervisor public constant OLD_MONETARY_SUPERVISOR = MonetarySupervisor(0x1ca4f9d261707af8a856020a4909b777da218868); - function execute(Main0018_postDeploySetup /* self, not used */) external { + function execute(Main0017_postDeploySetup /* self, not used */) external { // called via StabilityBoardProxy require(address(this) == address(STABILITY_BOARD_PROXY), "only execute via StabilityBoardProxy"); diff --git a/contracts/SB_scripts/mainnet/Main0017_setupSigners.sol b/contracts/SB_scripts/mainnet/Main0017_setupSigners.sol deleted file mode 100644 index 97fd55bc..00000000 --- a/contracts/SB_scripts/mainnet/Main0017_setupSigners.sol +++ /dev/null @@ -1,22 +0,0 @@ -/* setup StabilityBoard signers in new StabilityBoardProxy on Mainnet */ - -pragma solidity 0.4.24; - -import "../../generic/MultiSig.sol"; -import "../../StabilityBoardProxy.sol"; - - -contract Main0017_setupSigners { - - StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(); - - function execute(Main0017_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/mainnet_migrations/31_deploy_all_scripts.js b/mainnet_migrations/31_deploy_all_scripts.js index 948bf2c5..231056ee 100644 --- a/mainnet_migrations/31_deploy_all_scripts.js +++ b/mainnet_migrations/31_deploy_all_scripts.js @@ -2,8 +2,7 @@ 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_setupSigners = artifacts.require("./Main0017_setupSigners.sol"); -const Main0018_postDeploySetup = artifacts.require("./Main0018_postDeploySetup.sol"); +const Main0017_postDeploySetup = artifacts.require("./Main0017_postDeploySetup.sol"); const MIGRATION_STEP_NUMBER = 31; const MIGRATIONS_ADDRESS = "???"; @@ -20,11 +19,8 @@ module.exports = function(deployer) { // script for setup legacy contract dependencies await deployer.deploy(Main0016_setupLegacy); - // script for setup StabilityBoard signers - await deployer.deploy(Main0017_setupSigners); - // script for post deploy setup - await deployer.deploy(Main0018_postDeploySetup); + await deployer.deploy(Main0017_postDeploySetup); console.log("Done with migration step " + MIGRATION_STEP_NUMBER); await Migrations.at(MIGRATIONS_ADDRESS).setCompleted(MIGRATION_STEP_NUMBER); From 6f46761b503ddd834d2a684149267d66b07389c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 14 Nov 2018 13:53:18 +0100 Subject: [PATCH 76/90] abiniser deployment descriptors for mainnet --- .../1/AugmintReserves_DEPLOYS.json | 20 ++++++++++++++++++- abiniser/deployments/1/Exchange_DEPLOYS.json | 20 ++++++++++++++++++- .../deployments/1/FeeAccount_DEPLOYS.json | 15 +++++++++++++- .../1/InterestEarnedAccount_DEPLOYS.json | 15 +++++++++++++- .../deployments/1/LoanManager_DEPLOYS.json | 20 ++++++++++++++++++- abiniser/deployments/1/Locker_DEPLOYS.json | 20 ++++++++++++++++++- .../deployments/1/Migrations_DEPLOYS.json | 15 +++++++++++++- .../1/MonetarySupervisor_DEPLOYS.json | 20 ++++++++++++++++++- .../deployments/1/PreTokenProxy_DEPLOYS.json | 20 ++++++++++++++++++- abiniser/deployments/1/PreToken_DEPLOYS.json | 20 ++++++++++++++++++- abiniser/deployments/1/Rates_DEPLOYS.json | 15 +++++++++++++- .../1/StabilityBoardProxy_DEPLOYS.json | 20 ++++++++++++++++++- abiniser/deployments/1/TokenAEur_DEPLOYS.json | 20 ++++++++++++++++++- 13 files changed, 227 insertions(+), 13 deletions(-) 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 From bc140b0083a34da537cc9f4a9e3aa91a66fbeb71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 14 Nov 2018 14:03:07 +0100 Subject: [PATCH 77/90] add new contract addresses to init scripts --- .../mainnet/Main0014_initNewContracts.sol | 26 +++++++++---------- .../Main0015_migrateLegacyContracts.sol | 2 +- .../mainnet/Main0016_setupLegacy.sol | 4 +-- .../mainnet/Main0017_postDeploySetup.sol | 6 ++--- mainnet_migrations/31_deploy_all_scripts.js | 2 +- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol index 7204d5dd..3a66a5e1 100644 --- a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol +++ b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol @@ -20,23 +20,23 @@ contract Main0014_initNewContracts { /****************************************************************************** * External dependencies ******************************************************************************/ - address public constant RATES_FEEDER_ACCOUNT = ; + address public constant RATES_FEEDER_ACCOUNT = 0x8C58187a978979947b88824DCdA5Cb5fD4410387; /****************************************************************************** * New contracts ******************************************************************************/ - StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(); - AugmintReserves public constant AUGMINT_RESERVES = AugmintReserves(); - Exchange public constant EXCHANGE = Exchange(); - FeeAccount public constant FEE_ACCOUNT = FeeAccount(); - InterestEarnedAccount public constant INTEREST_EARNED_ACCOUNT = InterestEarnedAccount(); - LoanManager public constant LOAN_MANAGER = LoanManager(); - Locker public constant LOCKER = Locker(); - MonetarySupervisor public constant MONETARY_SUPERVISOR = MonetarySupervisor(); - Rates public constant RATES = Rates(); - TokenAEur public constant TOKEN_AEUR = TokenAEur(); - PreToken public constant PRE_TOKEN = PreToken(); - PreTokenProxy public constant PRE_TOKEN_PROXY = PreTokenProxy(); + 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 diff --git a/contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol b/contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol index bea463e3..cebd5e95 100644 --- a/contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol +++ b/contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol @@ -19,7 +19,7 @@ contract Main0015_migrateLegacyContracts { * StabilityBoardProxies ******************************************************************************/ StabilityBoardProxy public constant OLD_STABILITY_BOARD_PROXY = StabilityBoardProxy(0x4686f017d456331ed2c1de66e134d8d05b24413d); - StabilityBoardProxy public constant NEW_STABILITY_BOARD_PROXY = StabilityBoardProxy(); + StabilityBoardProxy public constant NEW_STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dcbeffdfd3c7b89fced7a9f84); /****************************************************************************** * Legacy contracts diff --git a/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol b/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol index 7789ed9c..9fd63383 100644 --- a/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol +++ b/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol @@ -18,12 +18,12 @@ contract Main0016_setupLegacy { /****************************************************************************** * StabilityBoardProxy ******************************************************************************/ - StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(); + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dcbeffdfd3c7b89fced7a9f84); /****************************************************************************** * New contracts ******************************************************************************/ - MonetarySupervisor public constant NEW_MONETARY_SUPERVISOR = MonetarySupervisor(); + MonetarySupervisor public constant NEW_MONETARY_SUPERVISOR = MonetarySupervisor(0x27484AFe9e6c332fB07F21Fac82d442EBe1D22c3); /****************************************************************************** * Legacy contracts diff --git a/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol b/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol index 73d027c6..0ae0ddbc 100644 --- a/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol +++ b/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol @@ -18,13 +18,13 @@ contract Main0017_postDeploySetup { /****************************************************************************** * StabilityBoardProxy ******************************************************************************/ - StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(); + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dcbeffdfd3c7b89fced7a9f84); /****************************************************************************** * New contracts ******************************************************************************/ - MonetarySupervisor public constant NEW_MONETARY_SUPERVISOR = MonetarySupervisor(); - Rates public constant NEW_RATES = Rates(); + MonetarySupervisor public constant NEW_MONETARY_SUPERVISOR = MonetarySupervisor(0x27484AFe9e6c332fB07F21Fac82d442EBe1D22c3); + Rates public constant NEW_RATES = Rates(0x4272dB2EB82068E898588C3D6e4B5D55c3848793); /****************************************************************************** * Legacy contracts diff --git a/mainnet_migrations/31_deploy_all_scripts.js b/mainnet_migrations/31_deploy_all_scripts.js index 231056ee..16ac95f3 100644 --- a/mainnet_migrations/31_deploy_all_scripts.js +++ b/mainnet_migrations/31_deploy_all_scripts.js @@ -5,7 +5,7 @@ const Main0016_setupLegacy = artifacts.require("./Main0016_setupLegacy.sol"); const Main0017_postDeploySetup = artifacts.require("./Main0017_postDeploySetup.sol"); const MIGRATION_STEP_NUMBER = 31; -const MIGRATIONS_ADDRESS = "???"; +const MIGRATIONS_ADDRESS = "0xf01C976E9189BC9ba68Eda0f1Dc9d94b243C78dC"; module.exports = function(deployer) { deployer.then(async () => { From 48d3069e9b8e94868c23619744ff46a224d7994e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 14 Nov 2018 14:05:42 +0100 Subject: [PATCH 78/90] fix legacy setup script --- contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol b/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol index 9fd63383..2b2aec67 100644 --- a/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol +++ b/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol @@ -43,7 +43,8 @@ contract Main0016_setupLegacy { * 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"); + NEW_MONETARY_SUPERVISOR.grantPermission(address(OLD_LOCKER_1), "Locker"); + NEW_MONETARY_SUPERVISOR.grantPermission(address(OLD_LOCKER_2), "Locker"); /****************************************************************************** * Accept legacy tokens From 5e74903c887ec6a681eeb4097a7ee8433dbbfb7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 14 Nov 2018 14:16:40 +0100 Subject: [PATCH 79/90] replace addresses with funny camelcase versions (to avoid compiler warnings) --- .../mainnet/Main0014_initNewContracts.sol | 26 +++++++++---------- .../Main0015_migrateLegacyContracts.sol | 26 +++++++++---------- .../mainnet/Main0016_setupLegacy.sol | 10 +++---- .../mainnet/Main0017_postDeploySetup.sol | 14 +++++----- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol index 3a66a5e1..16244593 100644 --- a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol +++ b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol @@ -25,18 +25,18 @@ contract Main0014_initNewContracts { /****************************************************************************** * 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); + 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); + 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 @@ -96,9 +96,9 @@ contract Main0014_initNewContracts { // StabilityBoard signers in new StabilityBoardProxy on Mainnet address[] memory stabilityProxySigners = new address[](2); - stabilityProxySigners[0] = 0x53dbf6e8fe46307c7536eabb0d90cada3e732716; // Sz.V. - stabilityProxySigners[1] = 0xae162e28575ba898dc08d283f2be10ae8b4114a2; // Sz.K. - stabilityProxySigners[2] = 0x9de3f6e7cacbb7e1c2489dfce21abbb0ecee6213; // P.P. + stabilityProxySigners[0] = 0x53DBF6E8fe46307C7536eAbb0D90CADA3e732716; // Sz.V. + stabilityProxySigners[1] = 0xAE162e28575Ba898dc08D283f2Be10AE8b4114A2; // Sz.K. + stabilityProxySigners[2] = 0x9de3F6E7caCbb7e1c2489dFCe21abbB0ecEE6213; // P.P. STABILITY_BOARD_PROXY.addSigners(stabilityProxySigners); diff --git a/contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol b/contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol index cebd5e95..8c3b43e8 100644 --- a/contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol +++ b/contracts/SB_scripts/mainnet/Main0015_migrateLegacyContracts.sol @@ -18,24 +18,24 @@ contract Main0015_migrateLegacyContracts { /****************************************************************************** * StabilityBoardProxies ******************************************************************************/ - StabilityBoardProxy public constant OLD_STABILITY_BOARD_PROXY = StabilityBoardProxy(0x4686f017d456331ed2c1de66e134d8d05b24413d); - StabilityBoardProxy public constant NEW_STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dcbeffdfd3c7b89fced7a9f84); + 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); + 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); + 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 diff --git a/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol b/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol index 2b2aec67..4d9d7fbe 100644 --- a/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol +++ b/contracts/SB_scripts/mainnet/Main0016_setupLegacy.sol @@ -18,7 +18,7 @@ contract Main0016_setupLegacy { /****************************************************************************** * StabilityBoardProxy ******************************************************************************/ - StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dcbeffdfd3c7b89fced7a9f84); + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dCBefFdfd3C7b89fCed7A9F84); /****************************************************************************** * New contracts @@ -28,11 +28,11 @@ contract Main0016_setupLegacy { /****************************************************************************** * 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); + 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); + TokenAEur public constant OLD_TOKEN_AEUR = TokenAEur(0x86A635EccEFFfA70Ff8A6DB29DA9C8DB288E40D0); function execute(Main0016_setupLegacy /* self, not used */) external { // called via StabilityBoardProxy diff --git a/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol b/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol index 0ae0ddbc..4f461809 100644 --- a/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol +++ b/contracts/SB_scripts/mainnet/Main0017_postDeploySetup.sol @@ -18,7 +18,7 @@ contract Main0017_postDeploySetup { /****************************************************************************** * StabilityBoardProxy ******************************************************************************/ - StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dcbeffdfd3c7b89fced7a9f84); + StabilityBoardProxy public constant STABILITY_BOARD_PROXY = StabilityBoardProxy(0xde36a8773531406dCBefFdfd3C7b89fCed7A9F84); /****************************************************************************** * New contracts @@ -29,13 +29,13 @@ contract Main0017_postDeploySetup { /****************************************************************************** * 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); + 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); + MonetarySupervisor public constant OLD_MONETARY_SUPERVISOR = MonetarySupervisor(0x1Ca4F9d261707aF8A856020a4909B777da218868); function execute(Main0017_postDeploySetup /* self, not used */) external { // called via StabilityBoardProxy From 8a001f0008d5b15af42bea2adfa02ca12a4b90d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 14 Nov 2018 15:42:07 +0100 Subject: [PATCH 80/90] remove adding pretoken signers from init script --- .../mainnet/Main0014_initNewContracts.sol | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol index 16244593..851ef470 100644 --- a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol +++ b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol @@ -83,14 +83,14 @@ contract Main0014_initNewContracts { // PreToken signers and permissions - address[] memory preTokenSigners = new address[](3); - preTokenSigners[0] = 0xd8203A652452906586F2E6cB6e31f6f7fed094D4; // Sz.K. - preTokenSigners[1] = 0xf9ea0E2857405C859bb8647ECB11f931D1259753; // P.P. - PRE_TOKEN_PROXY.addSigners(preTokenSigners); - - PRE_TOKEN.grantPermission(address(PRE_TOKEN_PROXY), "PreTokenSigner"); - PRE_TOKEN.grantPermission(address(PRE_TOKEN_PROXY), "PermissionGranter"); - PRE_TOKEN.revokePermission(address(STABILITY_BOARD_PROXY), "PermissionGranter"); + // address[] memory preTokenSigners = new address[](3); + // preTokenSigners[0] = 0xd8203A652452906586F2E6cB6e31f6f7fed094D4; // Sz.K. + // preTokenSigners[1] = 0xf9ea0E2857405C859bb8647ECB11f931D1259753; // P.P. + // PRE_TOKEN_PROXY.addSigners(preTokenSigners); + + // 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 From c622194d3d59417563bca80227c8b5962b9f8e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 14 Nov 2018 15:50:26 +0100 Subject: [PATCH 81/90] move adding pretoken signers to separate script, fix typo --- .../mainnet/Main0014_initNewContracts.sol | 17 ++++---------- .../mainnet/Main0018_preTokenSigners.sol | 23 +++++++++++++++++++ 2 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 contracts/SB_scripts/mainnet/Main0018_preTokenSigners.sol diff --git a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol index 851ef470..1c47c115 100644 --- a/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol +++ b/contracts/SB_scripts/mainnet/Main0014_initNewContracts.sol @@ -81,21 +81,14 @@ contract Main0014_initNewContracts { MONETARY_SUPERVISOR.grantPermission(address(LOCKER), "Locker"); - // PreToken signers and permissions - - // address[] memory preTokenSigners = new address[](3); - // preTokenSigners[0] = 0xd8203A652452906586F2E6cB6e31f6f7fed094D4; // Sz.K. - // preTokenSigners[1] = 0xf9ea0E2857405C859bb8647ECB11f931D1259753; // P.P. - // PRE_TOKEN_PROXY.addSigners(preTokenSigners); - - // PRE_TOKEN.grantPermission(address(PRE_TOKEN_PROXY), "PreTokenSigner"); - // PRE_TOKEN.grantPermission(address(PRE_TOKEN_PROXY), "PermissionGranter"); - // PRE_TOKEN.revokePermission(address(STABILITY_BOARD_PROXY), "PermissionGranter"); + // 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[](2); + address[] memory stabilityProxySigners = new address[](3); stabilityProxySigners[0] = 0x53DBF6E8fe46307C7536eAbb0D90CADA3e732716; // Sz.V. stabilityProxySigners[1] = 0xAE162e28575Ba898dc08D283f2Be10AE8b4114A2; // Sz.K. stabilityProxySigners[2] = 0x9de3F6E7caCbb7e1c2489dFCe21abbB0ecEE6213; // P.P. 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 From 8f4b2037fc720532c7f7fb70b754546a6f708134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 14 Nov 2018 16:51:58 +0100 Subject: [PATCH 82/90] add pretoken signer script to script deploy script --- mainnet_migrations/31_deploy_all_scripts.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mainnet_migrations/31_deploy_all_scripts.js b/mainnet_migrations/31_deploy_all_scripts.js index 16ac95f3..ccbbfea6 100644 --- a/mainnet_migrations/31_deploy_all_scripts.js +++ b/mainnet_migrations/31_deploy_all_scripts.js @@ -3,6 +3,7 @@ const Main0014_initNewContracts = artifacts.require("./Main0014_initNewContracts 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"; @@ -22,6 +23,9 @@ module.exports = function(deployer) { // 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); }); From 4026f3f40dd0b658d9118a892f6d2e46d022399e Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 23 Nov 2018 01:46:05 +0000 Subject: [PATCH 83/90] chore(package): update stringifier to version 2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f96eda5..5a8317c9 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "moment": "2.22.2", "random-seed": "0.3.0", "solidity-coverage": "0.5.11", - "stringifier": "1.4.0", + "stringifier": "2.0.0", "truffle": "4.1.14", "truffle-hdwallet-provider": "0.0.6", "web3v1": "npm:web3@1.0.0-beta.34" From 21a05ea489a00eae122ffc429654358b56833be8 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 23 Nov 2018 01:46:09 +0000 Subject: [PATCH 84/90] chore(package): update lockfile yarn.lock --- yarn.lock | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1078b909..87fa9f72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1001,7 +1001,7 @@ cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" -core-js@^2.0.0, core-js@^2.4.0, 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" @@ -3419,11 +3419,10 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -stringifier@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/stringifier/-/stringifier-1.4.0.tgz#d704581567f4526265d00ed8ecb354a02c3fec28" +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" From 56b62074f6758b7dd42ac22b99a58c8aa2040697 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Wed, 5 Dec 2018 18:33:28 +0000 Subject: [PATCH 85/90] chore(package): update dotenv to version 6.2.0 Closes #157 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f96eda5..85d1c684 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "babel-register": "6.26.0", "bignumber.js": "5.0.0", "coveralls": "3.0.1", - "dotenv": "6.0.0", + "dotenv": "6.2.0", "ganache-cli": "6.1.8", "moment": "2.22.2", "random-seed": "0.3.0", From 6751c84331670a0f29e3c8aeabee2cee89244f04 Mon Sep 17 00:00:00 2001 From: greenkeeperio-bot Date: Wed, 5 Dec 2018 18:35:40 +0000 Subject: [PATCH 86/90] chore(package): update lockfile https://npm.im/greenkeeper-lockfile --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1078b909..3046e27e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1239,9 +1239,9 @@ 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" From c977c8788b0b7cfd524d7faeef29a2eea214e570 Mon Sep 17 00:00:00 2001 From: szerintedmi Date: Fri, 7 Dec 2018 13:19:39 +0000 Subject: [PATCH 87/90] update to node 8.14.0 --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 641c7df3..18e0a5e2 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v8.9.4 +v8.14.0 From d1faf93d9b454ef89261f8c8625a468a20410f9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 2 Jan 2019 15:19:27 +0100 Subject: [PATCH 88/90] script to eliminate transfer fees (mainnet) --- .../mainnet/Main0019_noTransferFee.sol | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 contracts/SB_scripts/mainnet/Main0019_noTransferFee.sol 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 From ed47368c5b0dca2dc3943ce238c0793f6aeb6086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 2 Jan 2019 15:29:58 +0100 Subject: [PATCH 89/90] script to remove deployer account from signers (mainnet) --- .../mainnet/Main0020_removeSigner.sol | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 contracts/SB_scripts/mainnet/Main0020_removeSigner.sol 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 From 8b1a054620f762ff4c797a28a6f27952cfac09ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Treer=20Zolt=C3=A1n?= Date: Wed, 2 Jan 2019 15:35:14 +0100 Subject: [PATCH 90/90] script to deploy scripts (mainnet) --- mainnet_migrations/32_deploy_scripts.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 mainnet_migrations/32_deploy_scripts.js 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); + }); +};