From 27ddf8306516cae4f63aa8abea081aaa80962528 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Thu, 30 Jan 2020 15:36:26 -0600 Subject: [PATCH 01/16] ADd one-time deposit pause and resume --- .../contracts/system/TBTCSystem.sol | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/implementation/contracts/system/TBTCSystem.sol b/implementation/contracts/system/TBTCSystem.sol index 891833dfb..ca65b6690 100644 --- a/implementation/contracts/system/TBTCSystem.sol +++ b/implementation/contracts/system/TBTCSystem.sol @@ -9,9 +9,12 @@ import {IBTCETHPriceFeed} from "../interfaces/IBTCETHPriceFeed.sol"; import {DepositLog} from "../DepositLog.sol"; import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { + using SafeMath for uint256; + event LogLotSizesUpdated(uint256[] _lotSizes); event LogAllowNewDepositsUpdated(bool _allowNewDeposits); event LogSignerFeeDivisorUpdated(uint256 _signerFeeDivisor); @@ -21,6 +24,8 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { ); bool _initialized = false; + uint128 pausedTimestamp; + uint128 pausedDuration = 10 days; uint256 currentDifficulty = 1; uint256 previousDifficulty = 1; @@ -29,7 +34,7 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { address public priceFeed; // Parameters governed by the TBTCSystem owner - bool private allowNewDeposits = true; + bool private allowNewDeposits = false; uint256 private signerFeeDivisor = 200; // 1/200 == 50bps == 0.5% == 0.005 uint128 private undercollateralizedThresholdPercent = 140; // percent uint128 private severelyUndercollateralizedThresholdPercent = 120; // percent @@ -46,6 +51,7 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { keepRegistry = _keepRegistry; _initialized = true; + allowNewDeposits = true; } /// @notice Enables/disables new deposits from being created. @@ -57,9 +63,24 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { emit LogAllowNewDepositsUpdated(_allowNewDeposits); } - /// @notice Gets whether new deposits are allowed. + /// @notice gets whether new deposits are allowed function getAllowNewDeposits() external view returns (bool) { return allowNewDeposits; } + /// @notice One-time-use emergency function to disallow future deposit creation for 10 days. + function emergencyPauseNewDeposits() external onlyOwner returns (bool) { + require(pausedTimestamp == 0, "emergencyPauseNewDeposits can only be called once"); + pausedTimestamp = block.timestamp; + allowNewDeposits = false; + emit LogAllowNewDepositsUpdated(false); + } + + /// @notice Anyone can reactivate deposit creations after the pause duration is over. + function resumeNewDeposits() public { + require(block.timestamp.sub(pausedTimestamp) > pausedDuration, "Deposits are still paused"); + allowNewDeposits = true; + emit LogAllowNewDepositsUpdated(true); + } + /// @notice Set the system signer fee divisor. /// @param _signerFeeDivisor The signer fee divisor. function setSignerFeeDivisor(uint256 _signerFeeDivisor) From 9efde6fdb8724e9347aa80b4ea285c8b627a631e Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Thu, 30 Jan 2020 15:37:53 -0600 Subject: [PATCH 02/16] Remove log prefix from governance events --- .../contracts/system/TBTCSystem.sol | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/implementation/contracts/system/TBTCSystem.sol b/implementation/contracts/system/TBTCSystem.sol index ca65b6690..2aebabd56 100644 --- a/implementation/contracts/system/TBTCSystem.sol +++ b/implementation/contracts/system/TBTCSystem.sol @@ -15,10 +15,10 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { using SafeMath for uint256; - event LogLotSizesUpdated(uint256[] _lotSizes); - event LogAllowNewDepositsUpdated(bool _allowNewDeposits); - event LogSignerFeeDivisorUpdated(uint256 _signerFeeDivisor); - event LogCollateralizationThresholdsUpdated( + event LotSizesUpdated(uint256[] _lotSizes); + event AllowNewDepositsUpdated(bool _allowNewDeposits); + event SignerFeeDivisorUpdated(uint256 _signerFeeDivisor); + event CollateralizationThresholdsUpdated( uint256 _undercollateralizedThresholdPercent, uint256 _severelyUndercollateralizedThresholdPercent ); @@ -60,7 +60,7 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { external onlyOwner { allowNewDeposits = _allowNewDeposits; - emit LogAllowNewDepositsUpdated(_allowNewDeposits); + emit AllowNewDepositsUpdated(_allowNewDeposits); } /// @notice gets whether new deposits are allowed @@ -71,14 +71,14 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { require(pausedTimestamp == 0, "emergencyPauseNewDeposits can only be called once"); pausedTimestamp = block.timestamp; allowNewDeposits = false; - emit LogAllowNewDepositsUpdated(false); + emit AllowNewDepositsUpdated(false); } /// @notice Anyone can reactivate deposit creations after the pause duration is over. function resumeNewDeposits() public { require(block.timestamp.sub(pausedTimestamp) > pausedDuration, "Deposits are still paused"); allowNewDeposits = true; - emit LogAllowNewDepositsUpdated(true); + emit AllowNewDepositsUpdated(true); } /// @notice Set the system signer fee divisor. @@ -88,7 +88,7 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { { require(_signerFeeDivisor > 1, "Signer fee must be lower than 100%"); signerFeeDivisor = _signerFeeDivisor; - emit LogSignerFeeDivisorUpdated(_signerFeeDivisor); + emit SignerFeeDivisorUpdated(_signerFeeDivisor); } /// @notice Gets the system signer fee divisor. @@ -100,7 +100,7 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { /// @param _lotSizes Array of allowed lot sizes. function setLotSizes(uint256[] calldata _lotSizes) external onlyOwner { lotSizesSatoshis = _lotSizes; - emit LogLotSizesUpdated(_lotSizes); + emit LotSizesUpdated(_lotSizes); } /// @notice Gets the allowed lot sizes @@ -134,7 +134,7 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { ); undercollateralizedThresholdPercent = _undercollateralizedThresholdPercent; severelyUndercollateralizedThresholdPercent = _severelyUndercollateralizedThresholdPercent; - emit LogCollateralizationThresholdsUpdated( + emit CollateralizationThresholdsUpdated( _undercollateralizedThresholdPercent, _severelyUndercollateralizedThresholdPercent ); From 9a13b01e795d56766beb5709c3a46a14136b19b1 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Thu, 30 Jan 2020 15:40:20 -0600 Subject: [PATCH 03/16] Timestamp values to uint256 --- implementation/contracts/system/TBTCSystem.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/implementation/contracts/system/TBTCSystem.sol b/implementation/contracts/system/TBTCSystem.sol index 2aebabd56..935441700 100644 --- a/implementation/contracts/system/TBTCSystem.sol +++ b/implementation/contracts/system/TBTCSystem.sol @@ -24,8 +24,8 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { ); bool _initialized = false; - uint128 pausedTimestamp; - uint128 pausedDuration = 10 days; + uint256 pausedTimestamp; + uint256 pausedDuration = 10 days; uint256 currentDifficulty = 1; uint256 previousDifficulty = 1; From 3cdc4f39e777690e6b9434a7151c575e354398ac Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Thu, 30 Jan 2020 17:45:13 -0600 Subject: [PATCH 04/16] Update tests --- implementation/test/DepositFactoryTest.js | 1 + implementation/test/DepositFundingTest.js | 1 + implementation/test/DepositUtilsTest.js | 1 + 3 files changed, 3 insertions(+) diff --git a/implementation/test/DepositFactoryTest.js b/implementation/test/DepositFactoryTest.js index 322b20795..235fc9cf1 100644 --- a/implementation/test/DepositFactoryTest.js +++ b/implementation/test/DepositFactoryTest.js @@ -45,6 +45,7 @@ contract('DepositFactory', (accounts) => { factory = await DepositFactory.new(depositContract.address) tbtcSystemStub = await TBTCSystemStub.new(utils.address0) + tbtcSystemStub.initialize(utils.address0) tbtcToken = await TBTCToken.new(tbtcSystemStub.address) tbtcDepositToken = deployed.TBTCDepositToken diff --git a/implementation/test/DepositFundingTest.js b/implementation/test/DepositFundingTest.js index 648bc7c25..d658933a4 100644 --- a/implementation/test/DepositFundingTest.js +++ b/implementation/test/DepositFundingTest.js @@ -90,6 +90,7 @@ contract('DepositFunding', (accounts) => { deployed = await utils.deploySystem(TEST_DEPOSIT_DEPLOY) tbtcSystemStub = await TBTCSystemStub.new(utils.address0) + tbtcSystemStub.initialize(utils.address0) tbtcToken = await TestToken.new(tbtcSystemStub.address) tbtcDepositToken = deployed.TBTCDepositToken diff --git a/implementation/test/DepositUtilsTest.js b/implementation/test/DepositUtilsTest.js index 3ea9dfb35..46a34da92 100644 --- a/implementation/test/DepositUtilsTest.js +++ b/implementation/test/DepositUtilsTest.js @@ -85,6 +85,7 @@ contract('DepositUtils', (accounts) => { deployed = await utils.deploySystem(TEST_DEPOSIT_UTILS_DEPLOY) tbtcSystemStub = await TBTCSystemStub.new(utils.address0) + tbtcSystemStub.initialize(utils.address0) tbtcToken = await TestToken.new(tbtcSystemStub.address) From 2f54312341afd47ab7ec4689ac11b73770b459c5 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Thu, 30 Jan 2020 17:51:46 -0600 Subject: [PATCH 05/16] Remove setAllowNewDeposits function --- implementation/contracts/system/TBTCSystem.sol | 9 --------- 1 file changed, 9 deletions(-) diff --git a/implementation/contracts/system/TBTCSystem.sol b/implementation/contracts/system/TBTCSystem.sol index 935441700..aa9b7706f 100644 --- a/implementation/contracts/system/TBTCSystem.sol +++ b/implementation/contracts/system/TBTCSystem.sol @@ -54,15 +54,6 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { allowNewDeposits = true; } - /// @notice Enables/disables new deposits from being created. - /// @param _allowNewDeposits Whether to allow new deposits. - function setAllowNewDeposits(bool _allowNewDeposits) - external onlyOwner - { - allowNewDeposits = _allowNewDeposits; - emit AllowNewDepositsUpdated(_allowNewDeposits); - } - /// @notice gets whether new deposits are allowed function getAllowNewDeposits() external view returns (bool) { return allowNewDeposits; } From e8f502712bab358bd58e9f38c0141d5e7b798b21 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Thu, 30 Jan 2020 19:29:08 -0600 Subject: [PATCH 06/16] add getRemainingPauseTerm --- implementation/contracts/system/TBTCSystem.sol | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/implementation/contracts/system/TBTCSystem.sol b/implementation/contracts/system/TBTCSystem.sol index db7661230..9278a128f 100644 --- a/implementation/contracts/system/TBTCSystem.sol +++ b/implementation/contracts/system/TBTCSystem.sol @@ -67,11 +67,19 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { /// @notice Anyone can reactivate deposit creations after the pause duration is over. function resumeNewDeposits() public { - require(block.timestamp.sub(pausedTimestamp) > pausedDuration, "Deposits are still paused"); + require(allowNewDeposits == false, "New deposits are currently allowed"); + require(block.timestamp.sub(pausedTimestamp) >= pausedDuration, "Deposits are still paused"); allowNewDeposits = true; emit AllowNewDepositsUpdated(true); } + function getRemainingPauseTerm() public view returns (uint256) { + require(allowNewDeposits == false, "New deposits are currently allowed"); + return (block.timestamp.sub(pausedTimestamp) >= pausedDuration)? + 0: + pausedDuration.sub(block.timestamp.sub(pausedTimestamp)); + } + /// @notice Set the system signer fee divisor. /// @param _signerFeeDivisor The signer fee divisor. function setSignerFeeDivisor(uint256 _signerFeeDivisor) From 31a7c2497321e5fd6881b26a92d0f30b5bce3af3 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Thu, 30 Jan 2020 19:29:21 -0600 Subject: [PATCH 07/16] test emergencyPauseNewDeposits --- implementation/test/TBTCSystemTest.js | 40 ++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/implementation/test/TBTCSystemTest.js b/implementation/test/TBTCSystemTest.js index 45b3d1532..141bf9f81 100644 --- a/implementation/test/TBTCSystemTest.js +++ b/implementation/test/TBTCSystemTest.js @@ -1,4 +1,9 @@ import expectThrow from './helpers/expectThrow' +import increaseTime from './helpers/increaseTime' +import { + createSnapshot, + restoreSnapshot, +} from './helpers/snapshot' const BN = require('bn.js') const utils = require('./utils') @@ -30,7 +35,7 @@ const TEST_DEPOSIT_DEPLOY = [ { name: 'TestDeposit', contract: TestDeposit }, ] -contract('TBTCSystem', (accounts) => { +contract.only('TBTCSystem', (accounts) => { let tbtcSystem let ecdsaKeepVendor @@ -84,18 +89,39 @@ contract('TBTCSystem', (accounts) => { }) }) - describe('setAllowNewDeposits', async () => { - it('sets allowNewDeposits', async () => { - await tbtcSystem.setAllowNewDeposits(false) + describe('emergencyPauseNewDeposits', async () => { + + beforeEach(async () => { + await createSnapshot() + }) + + afterEach(async () => { + await restoreSnapshot() + }) + + it('pauses new deposit creation', async () => { + await tbtcSystem.emergencyPauseNewDeposits() const allowNewDeposits = await tbtcSystem.getAllowNewDeposits() expect(allowNewDeposits).to.equal(false) }) - it('reverts if msg.sender != owner', async () => { + it('allows new deposit creation after 10 days', async () => { + await tbtcSystem.emergencyPauseNewDeposits() + await increaseTime(new BN(864000)) // 10 days + tbtcSystem.resumeNewDeposits() + const allowNewDeposits = await tbtcSystem.getAllowNewDeposits() + expect(allowNewDeposits).to.equal(true) + }) + + it('reverts if emergencyPauseNewDeposits has already been called', async () => { + await tbtcSystem.emergencyPauseNewDeposits() + await increaseTime(new BN(864000)) // 10 days + tbtcSystem.resumeNewDeposits() + await expectThrow( - tbtcSystem.setAllowNewDeposits(false, { from: accounts[1] }), - '' + tbtcSystem.emergencyPauseNewDeposits(), + 'emergencyPauseNewDeposits can only be called once' ) }) }) From e619851c07456b259905dc0dc90ec7678f6c7a16 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Thu, 30 Jan 2020 19:30:40 -0600 Subject: [PATCH 08/16] remove .only from tests --- implementation/test/TBTCSystemTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/implementation/test/TBTCSystemTest.js b/implementation/test/TBTCSystemTest.js index 141bf9f81..9edf0bb57 100644 --- a/implementation/test/TBTCSystemTest.js +++ b/implementation/test/TBTCSystemTest.js @@ -35,7 +35,7 @@ const TEST_DEPOSIT_DEPLOY = [ { name: 'TestDeposit', contract: TestDeposit }, ] -contract.only('TBTCSystem', (accounts) => { +contract('TBTCSystem', (accounts) => { let tbtcSystem let ecdsaKeepVendor From 63afafeffbcd717275ffbc1f159bf1d9857f63d1 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Thu, 30 Jan 2020 20:04:30 -0600 Subject: [PATCH 09/16] fix js lint error --- implementation/test/TBTCSystemTest.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/implementation/test/TBTCSystemTest.js b/implementation/test/TBTCSystemTest.js index 9edf0bb57..81c02d208 100644 --- a/implementation/test/TBTCSystemTest.js +++ b/implementation/test/TBTCSystemTest.js @@ -35,7 +35,7 @@ const TEST_DEPOSIT_DEPLOY = [ { name: 'TestDeposit', contract: TestDeposit }, ] -contract('TBTCSystem', (accounts) => { +contract.only('TBTCSystem', (accounts) => { let tbtcSystem let ecdsaKeepVendor @@ -90,7 +90,6 @@ contract('TBTCSystem', (accounts) => { }) describe('emergencyPauseNewDeposits', async () => { - beforeEach(async () => { await createSnapshot() }) From c9dc0c8b4c6322cce7ad729e269118848ff8990b Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Thu, 30 Jan 2020 20:29:08 -0600 Subject: [PATCH 10/16] Add test for deposit re-activation before term is over --- implementation/test/TBTCSystemTest.js | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/implementation/test/TBTCSystemTest.js b/implementation/test/TBTCSystemTest.js index 81c02d208..6d9dd9a20 100644 --- a/implementation/test/TBTCSystemTest.js +++ b/implementation/test/TBTCSystemTest.js @@ -35,7 +35,7 @@ const TEST_DEPOSIT_DEPLOY = [ { name: 'TestDeposit', contract: TestDeposit }, ] -contract.only('TBTCSystem', (accounts) => { +contract('TBTCSystem', (accounts) => { let tbtcSystem let ecdsaKeepVendor @@ -90,6 +90,8 @@ contract.only('TBTCSystem', (accounts) => { }) describe('emergencyPauseNewDeposits', async () => { + let term + beforeEach(async () => { await createSnapshot() }) @@ -105,9 +107,23 @@ contract.only('TBTCSystem', (accounts) => { expect(allowNewDeposits).to.equal(false) }) + it('does not allows new deposit re-activation before 10 days', async () => { + await tbtcSystem.emergencyPauseNewDeposits() + term = await tbtcSystem.getRemainingPauseTerm() + + await increaseTime(term.toNumber() - 10) // T-10 seconds. toNumber because increaseTime doesn't support BN + + await expectThrow( + tbtcSystem.resumeNewDeposits(), + 'Deposits are still paused' + ) + }) + it('allows new deposit creation after 10 days', async () => { await tbtcSystem.emergencyPauseNewDeposits() - await increaseTime(new BN(864000)) // 10 days + term = await tbtcSystem.getRemainingPauseTerm() + + await increaseTime(term.toNumber()) // 10 days tbtcSystem.resumeNewDeposits() const allowNewDeposits = await tbtcSystem.getAllowNewDeposits() expect(allowNewDeposits).to.equal(true) @@ -115,7 +131,9 @@ contract.only('TBTCSystem', (accounts) => { it('reverts if emergencyPauseNewDeposits has already been called', async () => { await tbtcSystem.emergencyPauseNewDeposits() - await increaseTime(new BN(864000)) // 10 days + term = await tbtcSystem.getRemainingPauseTerm() + + await increaseTime(term.toNumber()) // 10 days tbtcSystem.resumeNewDeposits() await expectThrow( From f2bd8ccbd56e97f7987507849b53fcc2b239b896 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Thu, 30 Jan 2020 21:00:00 -0600 Subject: [PATCH 11/16] Update createNewDeposit tests use emergencyPauseNewDeposits if a disabled state is required --- implementation/test/DepositFundingTest.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/implementation/test/DepositFundingTest.js b/implementation/test/DepositFundingTest.js index d658933a4..e5ba4efcc 100644 --- a/implementation/test/DepositFundingTest.js +++ b/implementation/test/DepositFundingTest.js @@ -1,4 +1,8 @@ import expectThrow from './helpers/expectThrow' +import { + createSnapshot, + restoreSnapshot, +} from './helpers/snapshot' const BytesLib = artifacts.require('BytesLib') const BTCUtils = artifacts.require('BTCUtils') @@ -108,11 +112,16 @@ contract('DepositFunding', (accounts) => { await tbtcDepositToken.forceMint(accounts[4], web3.utils.toBN(deployed.TestDeposit.address)) beneficiary = accounts[4] + await testInstance.reset() + await testInstance.setKeepAddress(deployed.ECDSAKeepStub.address) }) beforeEach(async () => { - await testInstance.reset() - await testInstance.setKeepAddress(deployed.ECDSAKeepStub.address) + await createSnapshot() + }) + + afterEach(async () => { + await restoreSnapshot() }) describe('createNewDeposit', async () => { @@ -173,7 +182,7 @@ contract('DepositFunding', (accounts) => { }) it('fails if new deposits are disabled', async () => { - await tbtcSystemStub.setAllowNewDeposits(false) + await tbtcSystemStub.emergencyPauseNewDeposits() await expectThrow( testInstance.createNewDeposit.call( @@ -188,8 +197,6 @@ contract('DepositFunding', (accounts) => { ), 'Opening new deposits is currently disabled.' ) - - await tbtcSystemStub.setAllowNewDeposits(true) }) it.skip('stores payment value as funder\'s bond', async () => { From 8402a7134ce5bd03c9a34748cdaa458aee1e5a52 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Fri, 31 Jan 2020 00:51:04 -0600 Subject: [PATCH 12/16] Add owner check for emergencyPauseNewDeposits --- implementation/test/TBTCSystemTest.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/implementation/test/TBTCSystemTest.js b/implementation/test/TBTCSystemTest.js index 6d9dd9a20..68e695618 100644 --- a/implementation/test/TBTCSystemTest.js +++ b/implementation/test/TBTCSystemTest.js @@ -107,6 +107,13 @@ contract('TBTCSystem', (accounts) => { expect(allowNewDeposits).to.equal(false) }) + it('reverts if msg.sender is not owner', async () => { + await expectThrow( + tbtcSystem.emergencyPauseNewDeposits({ from: accounts[1] }), + 'Ownable: caller is not the owner' + ) + }) + it('does not allows new deposit re-activation before 10 days', async () => { await tbtcSystem.emergencyPauseNewDeposits() term = await tbtcSystem.getRemainingPauseTerm() From 1bbf27427b645284e9a20fdafcc6e7dbda426af1 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Fri, 31 Jan 2020 15:02:34 -0600 Subject: [PATCH 13/16] Enfore 1btc lotSize always exists This prevents a forced pause by removing all available lotsizes. --- implementation/contracts/system/TBTCSystem.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/implementation/contracts/system/TBTCSystem.sol b/implementation/contracts/system/TBTCSystem.sol index 9278a128f..5be44882b 100644 --- a/implementation/contracts/system/TBTCSystem.sol +++ b/implementation/contracts/system/TBTCSystem.sol @@ -98,6 +98,7 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { /// @dev Lot sizes should be /// @param _lotSizes Array of allowed lot sizes. function setLotSizes(uint256[] calldata _lotSizes) external onlyOwner { + require(arrayContains(_lotSizes, 10**8), "Lot size array must always contain 1BTC"); lotSizesSatoshis = _lotSizes; emit LotSizesUpdated(_lotSizes); } @@ -108,6 +109,17 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { return lotSizesSatoshis; } + /// @notice Checks if a uint256 value exists in a unt256 array + /// @return true if it exists, false otherwise. + function arrayContains(uint256[] memory _array, uint256 _value) internal pure returns (bool){ + for( uint i = 0; i < _array.length; i++){ + if (_array[i] == _value){ + return true; + } + } + return false; + } + /// @notice Check if a lot size is allowed. /// @param _lotSize Lot size to check. /// @return True if lot size is allowed, false otherwise. From ec0048c8ad9a02058fa0461d5ceebd971d93d840 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Fri, 31 Jan 2020 15:02:47 -0600 Subject: [PATCH 14/16] test setLotSizes --- implementation/test/TBTCSystemTest.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/implementation/test/TBTCSystemTest.js b/implementation/test/TBTCSystemTest.js index 68e695618..9d5961566 100644 --- a/implementation/test/TBTCSystemTest.js +++ b/implementation/test/TBTCSystemTest.js @@ -89,6 +89,26 @@ contract('TBTCSystem', (accounts) => { }) }) + describe('setLotSizes', async () => { + it('sets a different lot size array', async () => { + const blockNumber = await web3.eth.getBlock('latest').number + const lotSizes = [10**8, 10**6] + await tbtcSystem.setLotSizes(lotSizes) + + const eventList = await tbtcSystem.getPastEvents('LotSizesUpdated', { fromBlock: blockNumber, toBlock: 'latest' }) + assert.equal(eventList.length, 1) + expect(eventList[0].returnValues._lotSizes).to.eql(['100000000', '1000000']) // deep equality check + }) + + it('reverts if lot size array does not contain a 1BTC lot size', async () => { + const lotSizes = [] + await expectThrow( + tbtcSystem.setLotSizes(lotSizes), + 'Lot size array must always contain 1BTC' + ) + }) + }) + describe('emergencyPauseNewDeposits', async () => { let term From c300808c3623ed5601ac19f4eb3339ae1fcbfa48 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Fri, 31 Jan 2020 15:43:28 -0600 Subject: [PATCH 15/16] inline value search for setLotSizes No need to have an external function here --- .../contracts/system/TBTCSystem.sol | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/implementation/contracts/system/TBTCSystem.sol b/implementation/contracts/system/TBTCSystem.sol index 5be44882b..1eb3d29b3 100644 --- a/implementation/contracts/system/TBTCSystem.sol +++ b/implementation/contracts/system/TBTCSystem.sol @@ -98,9 +98,14 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { /// @dev Lot sizes should be /// @param _lotSizes Array of allowed lot sizes. function setLotSizes(uint256[] calldata _lotSizes) external onlyOwner { - require(arrayContains(_lotSizes, 10**8), "Lot size array must always contain 1BTC"); - lotSizesSatoshis = _lotSizes; - emit LotSizesUpdated(_lotSizes); + for( uint i = 0; i < _lotSizes.length; i++){ + if (_lotSizes[i] == 10**8){ + lotSizesSatoshis = _lotSizes; + emit LotSizesUpdated(_lotSizes); + return; + } + } + revert("Lot size array must always contain 1BTC"); } /// @notice Gets the allowed lot sizes @@ -109,17 +114,6 @@ contract TBTCSystem is Ownable, ITBTCSystem, DepositLog { return lotSizesSatoshis; } - /// @notice Checks if a uint256 value exists in a unt256 array - /// @return true if it exists, false otherwise. - function arrayContains(uint256[] memory _array, uint256 _value) internal pure returns (bool){ - for( uint i = 0; i < _array.length; i++){ - if (_array[i] == _value){ - return true; - } - } - return false; - } - /// @notice Check if a lot size is allowed. /// @param _lotSize Lot size to check. /// @return True if lot size is allowed, false otherwise. From 7e890ddd12156e4342f4b33f7f38c9f641a6a027 Mon Sep 17 00:00:00 2001 From: NicholasDotSol Date: Fri, 31 Jan 2020 15:43:52 -0600 Subject: [PATCH 16/16] Test setLotSizes with non-empty bad array --- implementation/test/TBTCSystemTest.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/implementation/test/TBTCSystemTest.js b/implementation/test/TBTCSystemTest.js index 9d5961566..5adac8f38 100644 --- a/implementation/test/TBTCSystemTest.js +++ b/implementation/test/TBTCSystemTest.js @@ -100,13 +100,21 @@ contract('TBTCSystem', (accounts) => { expect(eventList[0].returnValues._lotSizes).to.eql(['100000000', '1000000']) // deep equality check }) - it('reverts if lot size array does not contain a 1BTC lot size', async () => { + it('reverts if lot size array is empty', async () => { const lotSizes = [] await expectThrow( tbtcSystem.setLotSizes(lotSizes), 'Lot size array must always contain 1BTC' ) }) + + it('reverts if lot size array does not contain a 1BTC lot size', async () => { + const lotSizes = [10**7] + await expectThrow( + tbtcSystem.setLotSizes(lotSizes), + 'Lot size array must always contain 1BTC' + ) + }) }) describe('emergencyPauseNewDeposits', async () => {