From e63faebb7a002b33dca4b9259adff1a6932df0fb Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 17 Jun 2020 17:08:13 +0200 Subject: [PATCH 01/57] ETH bonding contract The contract is used for ETH only bonding. It defined withdraw function that is different from the one defined in KeepBonding contract as there is no grantee role. Other parts of the code are common for token bonding and eth bonding. --- solidity/contracts/ETHBonding.sol | 70 +++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 solidity/contracts/ETHBonding.sol diff --git a/solidity/contracts/ETHBonding.sol b/solidity/contracts/ETHBonding.sol new file mode 100644 index 000000000..a445955ca --- /dev/null +++ b/solidity/contracts/ETHBonding.sol @@ -0,0 +1,70 @@ +/** +▓▓▌ ▓▓ ▐▓▓ ▓▓▓▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▄ +▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ + ▓▓▓▓▓▓ ▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓ ▐▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓ ▐▓▓▓▓▓▌ ▐▓▓▓▓▓▓ + ▓▓▓▓▓▓▄▄▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓▄▄▄▄ ▓▓▓▓▓▓▄▄▄▄ ▐▓▓▓▓▓▌ ▐▓▓▓▓▓▓ + ▓▓▓▓▓▓▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▌ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ + ▓▓▓▓▓▓▀▀▓▓▓▓▓▓▄ ▐▓▓▓▓▓▓▀▀▀▀ ▓▓▓▓▓▓▀▀▀▀ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▀ + ▓▓▓▓▓▓ ▀▓▓▓▓▓▓▄ ▐▓▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓ ▐▓▓▓▓▓▌ +▓▓▓▓▓▓▓▓▓▓ █▓▓▓▓▓▓▓▓▓ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ + + Trust math, not hardware. +*/ + +pragma solidity 0.5.17; + +import "./AbstractBonding.sol"; +import "./ETHStaking.sol"; + +/// @title ETH Bonding +/// @notice Contract holding deposits from keeps' operators. +contract ETHBonding is AbstractBonding { + ETHStaking ethStaking; + + /// @notice Initializes Keep Bonding contract. + /// @param registryAddress Keep registry contract address. + /// @param ethStakingAddress ETH Staking contract address. + constructor(address registryAddress, address ethStakingAddress) + public + AbstractBonding(registryAddress) + { + ethStaking = ETHStaking(ethStakingAddress); + } + + /// @notice Withdraws amount from operator's value available for bonding. + /// This function can be called only by: + /// - operator, + /// - owner of the stake. + /// + /// @param amount Value to withdraw in wei. + /// @param operator Address of the operator. + function withdraw(uint256 amount, address operator) public { + require( + msg.sender == operator || + msg.sender == ethStaking.ownerOf(operator), + "Only operator or the owner is allowed to withdraw bond" + ); + + withdrawBond(amount, operator); + } + + function isAuthorizedForOperator( + address _operator, + address _operatorContract + ) internal view returns (bool) { + return ethStaking.isAuthorizedForOperator(_operator, _operatorContract); + } + + function authorizerOf(address _operator) internal view returns (address) { + return ethStaking.authorizerOf(_operator); + } + + function beneficiaryOf(address _operator) + internal + view + returns (address payable) + { + return ethStaking.beneficiaryOf(_operator); + } +} From 32ee0d4f4f601b58d6fa81982713754abb475401 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 17 Jun 2020 17:14:48 +0200 Subject: [PATCH 02/57] ETH staking contract The contract is used to delegate stake in ETH to the specific operator with authorizer and beneficiary. --- solidity/contracts/ETHStaking.sol | 64 +++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 solidity/contracts/ETHStaking.sol diff --git a/solidity/contracts/ETHStaking.sol b/solidity/contracts/ETHStaking.sol new file mode 100644 index 000000000..7e9584e71 --- /dev/null +++ b/solidity/contracts/ETHStaking.sol @@ -0,0 +1,64 @@ +/** +▓▓▌ ▓▓ ▐▓▓ ▓▓▓▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▄ +▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ + ▓▓▓▓▓▓ ▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓ ▐▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓ ▐▓▓▓▓▓▌ ▐▓▓▓▓▓▓ + ▓▓▓▓▓▓▄▄▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓▄▄▄▄ ▓▓▓▓▓▓▄▄▄▄ ▐▓▓▓▓▓▌ ▐▓▓▓▓▓▓ + ▓▓▓▓▓▓▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▌ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ + ▓▓▓▓▓▓▀▀▓▓▓▓▓▓▄ ▐▓▓▓▓▓▓▀▀▀▀ ▓▓▓▓▓▓▀▀▀▀ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▀ + ▓▓▓▓▓▓ ▀▓▓▓▓▓▓▄ ▐▓▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓ ▐▓▓▓▓▓▌ +▓▓▓▓▓▓▓▓▓▓ █▓▓▓▓▓▓▓▓▓ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ + + Trust math, not hardware. +*/ + +pragma solidity 0.5.17; + +import "@keep-network/keep-core/contracts/KeepRegistry.sol"; +import "@keep-network/keep-core/contracts/Authorizations.sol"; +import "@keep-network/keep-core/contracts/StakeDelegatable.sol"; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/// @title ETH Staking +/// @notice A staking contract for ETH staking. An owner of the ETH can delegate +/// ETH as a stake to an operator. The value of ETH the owner is willing to stake +/// should be deposited in `ETHBonding` contract for the given operator. +contract ETHStaking is Authorizations, StakeDelegatable { + constructor(KeepRegistry keepRegistry) + public + Authorizations(keepRegistry) + {} + + event Staked( + address owner, + address indexed operator, + address indexed beneficiary, + address indexed authorizer + ); + + /// @notice Registers stake details. The function is used to register + /// addresses of operator, beneficiary and authorizer for a stake from the + /// caller. + /// @param operator Address of the operator. + /// @param beneficiary Address of the beneficiary. + /// @param authorizer Address of the authorizer. + function stake( + address operator, + address payable beneficiary, + address authorizer + ) external payable { + // TODO: Do we need to verify the caller in any way? + address _from = msg.sender; + + require( + operators[operator].owner == address(0), + "Operator already in use" + ); + + operators[operator] = Operator(0, _from, beneficiary, authorizer); + ownerOperators[_from].push(operator); + + emit Staked(_from, operator, beneficiary, authorizer); + } +} From 48f2384f4076bcf5cd3cf7666a71b7f943327f36 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 7 Aug 2020 16:40:15 +0200 Subject: [PATCH 03/57] Added tests for ETH bonding and staking contracts --- solidity/test/ETHBondingTest.js | 164 ++++++++++++++++++++++++++++++++ solidity/test/ETHStakingTest.js | 120 +++++++++++++++++++++++ 2 files changed, 284 insertions(+) create mode 100644 solidity/test/ETHBondingTest.js create mode 100644 solidity/test/ETHStakingTest.js diff --git a/solidity/test/ETHBondingTest.js b/solidity/test/ETHBondingTest.js new file mode 100644 index 000000000..f4a3690d2 --- /dev/null +++ b/solidity/test/ETHBondingTest.js @@ -0,0 +1,164 @@ +const {accounts, contract, web3} = require("@openzeppelin/test-environment") +const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot") + +const KeepRegistry = contract.fromArtifact("KeepRegistry") +const ETHStaking = contract.fromArtifact("ETHStaking") +const ETHBonding = contract.fromArtifact("ETHBonding") +const TestEtherReceiver = contract.fromArtifact("TestEtherReceiver") + +const {expectEvent, expectRevert} = require("@openzeppelin/test-helpers") + +const BN = web3.utils.BN + +const chai = require("chai") +chai.use(require("bn-chai")(BN)) +const expect = chai.expect + +describe("ETHBonding", function () { + let registry + let ethStaking + let ethBonding + let etherReceiver + + let operator + let authorizer + let beneficiary + let stakeOwner + let bondCreator + let sortitionPool + + before(async () => { + operator = accounts[1] + authorizer = accounts[2] + beneficiary = accounts[3] + stakeOwner = accounts[4] + bondCreator = accounts[5] + sortitionPool = accounts[6] + + registry = await KeepRegistry.new() + ethStaking = await ETHStaking.new(registry.address) + ethBonding = await ETHBonding.new(registry.address, ethStaking.address) + etherReceiver = await TestEtherReceiver.new() + + await registry.approveOperatorContract(bondCreator) + + await ethStaking.stake(operator, beneficiary, authorizer, { + from: stakeOwner, + }) + + await ethStaking.authorizeOperatorContract(operator, bondCreator, { + from: authorizer, + }) + }) + + beforeEach(async () => { + await createSnapshot() + }) + + afterEach(async () => { + await restoreSnapshot() + }) + + describe("withdraw", async () => { + const value = new BN(1000) + + beforeEach(async () => { + await ethBonding.deposit(operator, {value: value}) + }) + + it("can be called by operator", async () => { + await ethBonding.withdraw(value, operator, {from: operator}) + // ok, no reverts + }) + + it("can be called by stake owner", async () => { + await ethBonding.withdraw(value, operator, {from: stakeOwner}) + // ok, no reverts + }) + + it("cannot be called by authorizer", async () => { + await expectRevert( + ethBonding.withdraw(value, operator, {from: authorizer}), + "Only operator or the owner is allowed to withdraw bond" + ) + }) + + it("cannot be called by beneficiary", async () => { + await expectRevert( + ethBonding.withdraw(value, operator, {from: beneficiary}), + "Only operator or the owner is allowed to withdraw bond" + ) + }) + + it("cannot be called by third party", async () => { + const thirdParty = accounts[7] + + await expectRevert( + ethBonding.withdraw(value, operator, {from: thirdParty}), + "Only operator or the owner is allowed to withdraw bond" + ) + }) + + it("transfers unbonded value to beneficiary", async () => { + const expectedUnbonded = 0 + + const expectedBeneficiaryBalance = web3.utils + .toBN(await web3.eth.getBalance(beneficiary)) + .add(value) + + await ethBonding.withdraw(value, operator, {from: operator}) + + const unbonded = await ethBonding.availableUnbondedValue( + operator, + bondCreator, + sortitionPool + ) + expect(unbonded).to.eq.BN(expectedUnbonded, "invalid unbonded value") + + const actualBeneficiaryBalance = await web3.eth.getBalance(beneficiary) + expect(actualBeneficiaryBalance).to.eq.BN( + expectedBeneficiaryBalance, + "invalid beneficiary balance" + ) + }) + + it("emits event", async () => { + const value = new BN(90) + + const receipt = await ethBonding.withdraw(value, operator, { + from: operator, + }) + expectEvent(receipt, "UnbondedValueWithdrawn", { + operator: operator, + beneficiary: beneficiary, + amount: value, + }) + }) + + it("reverts if insufficient unbonded value", async () => { + const invalidValue = value.add(new BN(1)) + + await expectRevert( + ethBonding.withdraw(invalidValue, operator, {from: operator}), + "Insufficient unbonded value" + ) + }) + + it("reverts if transfer fails", async () => { + const operator2 = accounts[7] + + await etherReceiver.setShouldFail(true) + + await ethStaking.stake(operator2, etherReceiver.address, authorizer, { + from: stakeOwner, + }) + + await ethBonding.deposit(operator2, {value: value}) + + await expectRevert( + ethBonding.withdraw(value, operator2, {from: operator2}), + "Transfer failed" + ) + }) + }) +}) diff --git a/solidity/test/ETHStakingTest.js b/solidity/test/ETHStakingTest.js new file mode 100644 index 000000000..6dddb884d --- /dev/null +++ b/solidity/test/ETHStakingTest.js @@ -0,0 +1,120 @@ +const {accounts, contract, web3} = require("@openzeppelin/test-environment") +const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot") + +const KeepRegistry = contract.fromArtifact("KeepRegistry") +const ETHStaking = contract.fromArtifact("ETHStaking") + +const {expectEvent, expectRevert} = require("@openzeppelin/test-helpers") + +const BN = web3.utils.BN + +const chai = require("chai") +chai.use(require("bn-chai")(BN)) +const expect = chai.expect +const assert = chai.assert + +describe("ETHStaking", function () { + let registry + let ethStaking + + let operator + let authorizer + let beneficiary + let stakeOwner + + before(async () => { + operator = accounts[1] + authorizer = accounts[2] + beneficiary = accounts[3] + stakeOwner = accounts[4] + + registry = await KeepRegistry.new() + ethStaking = await ETHStaking.new(registry.address) + }) + + beforeEach(async () => { + await createSnapshot() + }) + + afterEach(async () => { + await restoreSnapshot() + }) + + describe("stake", async () => { + it("registers stake", async () => { + await ethStaking.stake(operator, beneficiary, authorizer, { + from: stakeOwner, + }) + + assert.equal( + await ethStaking.ownerOf(operator), + stakeOwner, + "incorrect stake owner address" + ) + + assert.equal( + await ethStaking.beneficiaryOf(operator), + beneficiary, + "incorrect beneficiary address" + ) + + assert.equal( + await ethStaking.authorizerOf(operator), + authorizer, + "incorrect authorizer address" + ) + + expect(await ethStaking.balanceOf(operator)).to.eq.BN( + 0, + "incorrect stake balance" + ) + }) + + it("emits event", async () => { + const receipt = await ethStaking.stake( + operator, + beneficiary, + authorizer, + { + from: stakeOwner, + } + ) + + await expectEvent(receipt, "Staked", { + owner: stakeOwner, + operator: operator, + beneficiary: beneficiary, + authorizer: authorizer, + }) + }) + + it("registers multiple operators for the same owner", async () => { + const operator2 = accounts[5] + + await ethStaking.stake(operator, beneficiary, authorizer, { + from: stakeOwner, + }) + + await ethStaking.stake(operator2, beneficiary, authorizer, { + from: stakeOwner, + }) + + assert.deepEqual( + await ethStaking.operatorsOf(stakeOwner), + [operator, operator2], + "incorrect operators for owner" + ) + }) + + it("reverts if operator is already in use", async () => { + await ethStaking.stake(operator, beneficiary, authorizer, { + from: stakeOwner, + }) + + await expectRevert( + ethStaking.stake(operator, accounts[5], accounts[5]), + "Operator already in use" + ) + }) + }) +}) From 865b0a48e45729f8b6d6289c16099374c642d233 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Tue, 11 Aug 2020 22:43:01 +0200 Subject: [PATCH 04/57] Added todo about initialization period --- solidity/contracts/ETHStaking.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/solidity/contracts/ETHStaking.sol b/solidity/contracts/ETHStaking.sol index 7e9584e71..1ffb8d8fb 100644 --- a/solidity/contracts/ETHStaking.sol +++ b/solidity/contracts/ETHStaking.sol @@ -59,6 +59,8 @@ contract ETHStaking is Authorizations, StakeDelegatable { operators[operator] = Operator(0, _from, beneficiary, authorizer); ownerOperators[_from].push(operator); + // TODO: Add initialization period as per https://github.com/keep-network/keep-ecdsa/pull/483#discussion_r468628872 + emit Staked(_from, operator, beneficiary, authorizer); } } From d6ae3f797167257341abff9ce020c92a99c306df Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 19 Aug 2020 12:43:34 +0200 Subject: [PATCH 05/57] Updated visibility to match abstract contract --- solidity/contracts/ETHBonding.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solidity/contracts/ETHBonding.sol b/solidity/contracts/ETHBonding.sol index a445955ca..2ba369a7c 100644 --- a/solidity/contracts/ETHBonding.sol +++ b/solidity/contracts/ETHBonding.sol @@ -52,16 +52,16 @@ contract ETHBonding is AbstractBonding { function isAuthorizedForOperator( address _operator, address _operatorContract - ) internal view returns (bool) { + ) public view returns (bool) { return ethStaking.isAuthorizedForOperator(_operator, _operatorContract); } - function authorizerOf(address _operator) internal view returns (address) { + function authorizerOf(address _operator) public view returns (address) { return ethStaking.authorizerOf(_operator); } function beneficiaryOf(address _operator) - internal + public view returns (address payable) { From 531690b7f6dd2b5dec2be9c2a7cb42766608b2fe Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 19 Aug 2020 12:44:42 +0200 Subject: [PATCH 06/57] Updated events emitted on ETH stake Updated events emitted on stake call to match changes introduced in keep-network/keep-core#1990. It also removed ownerOperators structure. --- solidity/contracts/ETHStaking.sol | 17 +++++++++-------- solidity/test/ETHStakingTest.js | 16 +++++++--------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/solidity/contracts/ETHStaking.sol b/solidity/contracts/ETHStaking.sol index 1ffb8d8fb..5ba17a60e 100644 --- a/solidity/contracts/ETHStaking.sol +++ b/solidity/contracts/ETHStaking.sol @@ -25,18 +25,19 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /// ETH as a stake to an operator. The value of ETH the owner is willing to stake /// should be deposited in `ETHBonding` contract for the given operator. contract ETHStaking is Authorizations, StakeDelegatable { - constructor(KeepRegistry keepRegistry) - public - Authorizations(keepRegistry) - {} + event Delegated(address indexed owner, address indexed operator); - event Staked( - address owner, + event OperatorDelegated( address indexed operator, address indexed beneficiary, address indexed authorizer ); + constructor(KeepRegistry keepRegistry) + public + Authorizations(keepRegistry) + {} + /// @notice Registers stake details. The function is used to register /// addresses of operator, beneficiary and authorizer for a stake from the /// caller. @@ -57,10 +58,10 @@ contract ETHStaking is Authorizations, StakeDelegatable { ); operators[operator] = Operator(0, _from, beneficiary, authorizer); - ownerOperators[_from].push(operator); // TODO: Add initialization period as per https://github.com/keep-network/keep-ecdsa/pull/483#discussion_r468628872 - emit Staked(_from, operator, beneficiary, authorizer); + emit Delegated(_from, operator); + emit OperatorDelegated(operator, beneficiary, authorizer); } } diff --git a/solidity/test/ETHStakingTest.js b/solidity/test/ETHStakingTest.js index 6dddb884d..715b4702f 100644 --- a/solidity/test/ETHStakingTest.js +++ b/solidity/test/ETHStakingTest.js @@ -70,7 +70,7 @@ describe("ETHStaking", function () { ) }) - it("emits event", async () => { + it("emits events", async () => { const receipt = await ethStaking.stake( operator, beneficiary, @@ -80,15 +80,19 @@ describe("ETHStaking", function () { } ) - await expectEvent(receipt, "Staked", { + await expectEvent(receipt, "Delegated", { owner: stakeOwner, operator: operator, + }) + + await expectEvent(receipt, "OperatorDelegated", { + operator: operator, beneficiary: beneficiary, authorizer: authorizer, }) }) - it("registers multiple operators for the same owner", async () => { + it("allows multiple operators for the same owner", async () => { const operator2 = accounts[5] await ethStaking.stake(operator, beneficiary, authorizer, { @@ -98,12 +102,6 @@ describe("ETHStaking", function () { await ethStaking.stake(operator2, beneficiary, authorizer, { from: stakeOwner, }) - - assert.deepEqual( - await ethStaking.operatorsOf(stakeOwner), - [operator, operator2], - "incorrect operators for owner" - ) }) it("reverts if operator is already in use", async () => { From 4112c0568960b5cfe73dbbf842906535f7657ed2 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 19 Aug 2020 13:17:47 +0200 Subject: [PATCH 07/57] Renamed ETHBonding to EthBonding Renamed contract to be consistent with naming of `KeepBonding`. --- solidity/contracts/ETHStaking.sol | 2 +- solidity/contracts/{ETHBonding.sol => EthBonding.sol} | 4 ++-- solidity/test/{ETHBondingTest.js => EthBondingTest.js} | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) rename solidity/contracts/{ETHBonding.sol => EthBonding.sol} (96%) rename solidity/test/{ETHBondingTest.js => EthBondingTest.js} (96%) diff --git a/solidity/contracts/ETHStaking.sol b/solidity/contracts/ETHStaking.sol index 5ba17a60e..8f30bc637 100644 --- a/solidity/contracts/ETHStaking.sol +++ b/solidity/contracts/ETHStaking.sol @@ -23,7 +23,7 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /// @title ETH Staking /// @notice A staking contract for ETH staking. An owner of the ETH can delegate /// ETH as a stake to an operator. The value of ETH the owner is willing to stake -/// should be deposited in `ETHBonding` contract for the given operator. +/// should be deposited in `EthBonding` contract for the given operator. contract ETHStaking is Authorizations, StakeDelegatable { event Delegated(address indexed owner, address indexed operator); diff --git a/solidity/contracts/ETHBonding.sol b/solidity/contracts/EthBonding.sol similarity index 96% rename from solidity/contracts/ETHBonding.sol rename to solidity/contracts/EthBonding.sol index 2ba369a7c..b17b0b787 100644 --- a/solidity/contracts/ETHBonding.sol +++ b/solidity/contracts/EthBonding.sol @@ -18,8 +18,8 @@ import "./AbstractBonding.sol"; import "./ETHStaking.sol"; /// @title ETH Bonding -/// @notice Contract holding deposits from keeps' operators. -contract ETHBonding is AbstractBonding { +/// @notice Contract holding deposits from ETH-only keeps' operators. +contract EthBonding is AbstractBonding { ETHStaking ethStaking; /// @notice Initializes Keep Bonding contract. diff --git a/solidity/test/ETHBondingTest.js b/solidity/test/EthBondingTest.js similarity index 96% rename from solidity/test/ETHBondingTest.js rename to solidity/test/EthBondingTest.js index f4a3690d2..f06b0041a 100644 --- a/solidity/test/ETHBondingTest.js +++ b/solidity/test/EthBondingTest.js @@ -3,7 +3,7 @@ const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot") const KeepRegistry = contract.fromArtifact("KeepRegistry") const ETHStaking = contract.fromArtifact("ETHStaking") -const ETHBonding = contract.fromArtifact("ETHBonding") +const EthBonding = contract.fromArtifact("EthBonding") const TestEtherReceiver = contract.fromArtifact("TestEtherReceiver") const {expectEvent, expectRevert} = require("@openzeppelin/test-helpers") @@ -14,7 +14,7 @@ const chai = require("chai") chai.use(require("bn-chai")(BN)) const expect = chai.expect -describe("ETHBonding", function () { +describe("EthBonding", function () { let registry let ethStaking let ethBonding @@ -37,7 +37,7 @@ describe("ETHBonding", function () { registry = await KeepRegistry.new() ethStaking = await ETHStaking.new(registry.address) - ethBonding = await ETHBonding.new(registry.address, ethStaking.address) + ethBonding = await EthBonding.new(registry.address, ethStaking.address) etherReceiver = await TestEtherReceiver.new() await registry.approveOperatorContract(bondCreator) From 3a5636c3916f7623f8490e62af3d65a12261affe Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 19 Aug 2020 13:41:55 +0200 Subject: [PATCH 08/57] Renamed ETHStaking to EthDelegating Renamed the contract as we're not really talking about staking in, it's delegation of ETH from owner to the operator. --- solidity/contracts/EthBonding.sol | 19 +++++++------ .../{ETHStaking.sol => EthDelegating.sol} | 8 +++--- solidity/test/EthBondingTest.js | 14 +++++----- ...ETHStakingTest.js => EthDelegatingTest.js} | 28 +++++++++---------- 4 files changed, 35 insertions(+), 34 deletions(-) rename solidity/contracts/{ETHStaking.sol => EthDelegating.sol} (93%) rename solidity/test/{ETHStakingTest.js => EthDelegatingTest.js} (72%) diff --git a/solidity/contracts/EthBonding.sol b/solidity/contracts/EthBonding.sol index b17b0b787..31e857b3e 100644 --- a/solidity/contracts/EthBonding.sol +++ b/solidity/contracts/EthBonding.sol @@ -15,21 +15,21 @@ pragma solidity 0.5.17; import "./AbstractBonding.sol"; -import "./ETHStaking.sol"; +import "./EthDelegating.sol"; /// @title ETH Bonding /// @notice Contract holding deposits from ETH-only keeps' operators. contract EthBonding is AbstractBonding { - ETHStaking ethStaking; + EthDelegating ethDelegating; /// @notice Initializes Keep Bonding contract. /// @param registryAddress Keep registry contract address. - /// @param ethStakingAddress ETH Staking contract address. - constructor(address registryAddress, address ethStakingAddress) + /// @param ethDelegatingAddress ETH Staking contract address. + constructor(address registryAddress, address ethDelegatingAddress) public AbstractBonding(registryAddress) { - ethStaking = ETHStaking(ethStakingAddress); + ethDelegating = EthDelegating(ethDelegatingAddress); } /// @notice Withdraws amount from operator's value available for bonding. @@ -42,7 +42,7 @@ contract EthBonding is AbstractBonding { function withdraw(uint256 amount, address operator) public { require( msg.sender == operator || - msg.sender == ethStaking.ownerOf(operator), + msg.sender == ethDelegating.ownerOf(operator), "Only operator or the owner is allowed to withdraw bond" ); @@ -53,11 +53,12 @@ contract EthBonding is AbstractBonding { address _operator, address _operatorContract ) public view returns (bool) { - return ethStaking.isAuthorizedForOperator(_operator, _operatorContract); + return + ethDelegating.isAuthorizedForOperator(_operator, _operatorContract); } function authorizerOf(address _operator) public view returns (address) { - return ethStaking.authorizerOf(_operator); + return ethDelegating.authorizerOf(_operator); } function beneficiaryOf(address _operator) @@ -65,6 +66,6 @@ contract EthBonding is AbstractBonding { view returns (address payable) { - return ethStaking.beneficiaryOf(_operator); + return ethDelegating.beneficiaryOf(_operator); } } diff --git a/solidity/contracts/ETHStaking.sol b/solidity/contracts/EthDelegating.sol similarity index 93% rename from solidity/contracts/ETHStaking.sol rename to solidity/contracts/EthDelegating.sol index 8f30bc637..0d19184b8 100644 --- a/solidity/contracts/ETHStaking.sol +++ b/solidity/contracts/EthDelegating.sol @@ -20,11 +20,11 @@ import "@keep-network/keep-core/contracts/StakeDelegatable.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; -/// @title ETH Staking -/// @notice A staking contract for ETH staking. An owner of the ETH can delegate -/// ETH as a stake to an operator. The value of ETH the owner is willing to stake +/// @title ETH Delegating +/// @notice A contract for ETH delegating. An owner of the ETH can delegate +/// ETH as to an operator. The value of ETH the owner is willing to delegate /// should be deposited in `EthBonding` contract for the given operator. -contract ETHStaking is Authorizations, StakeDelegatable { +contract EthDelegating is Authorizations, StakeDelegatable { event Delegated(address indexed owner, address indexed operator); event OperatorDelegated( diff --git a/solidity/test/EthBondingTest.js b/solidity/test/EthBondingTest.js index f06b0041a..d24eab685 100644 --- a/solidity/test/EthBondingTest.js +++ b/solidity/test/EthBondingTest.js @@ -2,7 +2,7 @@ const {accounts, contract, web3} = require("@openzeppelin/test-environment") const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot") const KeepRegistry = contract.fromArtifact("KeepRegistry") -const ETHStaking = contract.fromArtifact("ETHStaking") +const EthDelegating = contract.fromArtifact("EthDelegating") const EthBonding = contract.fromArtifact("EthBonding") const TestEtherReceiver = contract.fromArtifact("TestEtherReceiver") @@ -16,7 +16,7 @@ const expect = chai.expect describe("EthBonding", function () { let registry - let ethStaking + let ethDelegating let ethBonding let etherReceiver @@ -36,17 +36,17 @@ describe("EthBonding", function () { sortitionPool = accounts[6] registry = await KeepRegistry.new() - ethStaking = await ETHStaking.new(registry.address) - ethBonding = await EthBonding.new(registry.address, ethStaking.address) + ethDelegating = await EthDelegating.new(registry.address) + ethBonding = await EthBonding.new(registry.address, ethDelegating.address) etherReceiver = await TestEtherReceiver.new() await registry.approveOperatorContract(bondCreator) - await ethStaking.stake(operator, beneficiary, authorizer, { + await ethDelegating.stake(operator, beneficiary, authorizer, { from: stakeOwner, }) - await ethStaking.authorizeOperatorContract(operator, bondCreator, { + await ethDelegating.authorizeOperatorContract(operator, bondCreator, { from: authorizer, }) }) @@ -149,7 +149,7 @@ describe("EthBonding", function () { await etherReceiver.setShouldFail(true) - await ethStaking.stake(operator2, etherReceiver.address, authorizer, { + await ethDelegating.stake(operator2, etherReceiver.address, authorizer, { from: stakeOwner, }) diff --git a/solidity/test/ETHStakingTest.js b/solidity/test/EthDelegatingTest.js similarity index 72% rename from solidity/test/ETHStakingTest.js rename to solidity/test/EthDelegatingTest.js index 715b4702f..278d0ce6d 100644 --- a/solidity/test/ETHStakingTest.js +++ b/solidity/test/EthDelegatingTest.js @@ -2,7 +2,7 @@ const {accounts, contract, web3} = require("@openzeppelin/test-environment") const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot") const KeepRegistry = contract.fromArtifact("KeepRegistry") -const ETHStaking = contract.fromArtifact("ETHStaking") +const EthDelegating = contract.fromArtifact("EthDelegating") const {expectEvent, expectRevert} = require("@openzeppelin/test-helpers") @@ -13,9 +13,9 @@ chai.use(require("bn-chai")(BN)) const expect = chai.expect const assert = chai.assert -describe("ETHStaking", function () { +describe("EthDelegating", function () { let registry - let ethStaking + let ethDelegating let operator let authorizer @@ -29,7 +29,7 @@ describe("ETHStaking", function () { stakeOwner = accounts[4] registry = await KeepRegistry.new() - ethStaking = await ETHStaking.new(registry.address) + ethDelegating = await EthDelegating.new(registry.address) }) beforeEach(async () => { @@ -42,36 +42,36 @@ describe("ETHStaking", function () { describe("stake", async () => { it("registers stake", async () => { - await ethStaking.stake(operator, beneficiary, authorizer, { + await ethDelegating.stake(operator, beneficiary, authorizer, { from: stakeOwner, }) assert.equal( - await ethStaking.ownerOf(operator), + await ethDelegating.ownerOf(operator), stakeOwner, "incorrect stake owner address" ) assert.equal( - await ethStaking.beneficiaryOf(operator), + await ethDelegating.beneficiaryOf(operator), beneficiary, "incorrect beneficiary address" ) assert.equal( - await ethStaking.authorizerOf(operator), + await ethDelegating.authorizerOf(operator), authorizer, "incorrect authorizer address" ) - expect(await ethStaking.balanceOf(operator)).to.eq.BN( + expect(await ethDelegating.balanceOf(operator)).to.eq.BN( 0, "incorrect stake balance" ) }) it("emits events", async () => { - const receipt = await ethStaking.stake( + const receipt = await ethDelegating.stake( operator, beneficiary, authorizer, @@ -95,22 +95,22 @@ describe("ETHStaking", function () { it("allows multiple operators for the same owner", async () => { const operator2 = accounts[5] - await ethStaking.stake(operator, beneficiary, authorizer, { + await ethDelegating.stake(operator, beneficiary, authorizer, { from: stakeOwner, }) - await ethStaking.stake(operator2, beneficiary, authorizer, { + await ethDelegating.stake(operator2, beneficiary, authorizer, { from: stakeOwner, }) }) it("reverts if operator is already in use", async () => { - await ethStaking.stake(operator, beneficiary, authorizer, { + await ethDelegating.stake(operator, beneficiary, authorizer, { from: stakeOwner, }) await expectRevert( - ethStaking.stake(operator, accounts[5], accounts[5]), + ethDelegating.stake(operator, accounts[5], accounts[5]), "Operator already in use" ) }) From f252f4f0e538b8ca4ae48265dc27779ec9a62c95 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 19 Aug 2020 13:48:09 +0200 Subject: [PATCH 09/57] Renamed stake to delegate Renamed the function name as we are not talking about staking but delegating eth. --- solidity/contracts/EthDelegating.sol | 8 +++--- solidity/test/EthBondingTest.js | 23 ++++++++++------- solidity/test/EthDelegatingTest.js | 38 ++++++++++++++-------------- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/solidity/contracts/EthDelegating.sol b/solidity/contracts/EthDelegating.sol index 0d19184b8..d2124a9ff 100644 --- a/solidity/contracts/EthDelegating.sol +++ b/solidity/contracts/EthDelegating.sol @@ -38,13 +38,13 @@ contract EthDelegating is Authorizations, StakeDelegatable { Authorizations(keepRegistry) {} - /// @notice Registers stake details. The function is used to register - /// addresses of operator, beneficiary and authorizer for a stake from the - /// caller. + /// @notice Registers delegation details. The function is used to register + /// addresses of operator, beneficiary and authorizer for a delegation from + /// the caller. /// @param operator Address of the operator. /// @param beneficiary Address of the beneficiary. /// @param authorizer Address of the authorizer. - function stake( + function delegate( address operator, address payable beneficiary, address authorizer diff --git a/solidity/test/EthBondingTest.js b/solidity/test/EthBondingTest.js index d24eab685..143292b62 100644 --- a/solidity/test/EthBondingTest.js +++ b/solidity/test/EthBondingTest.js @@ -23,7 +23,7 @@ describe("EthBonding", function () { let operator let authorizer let beneficiary - let stakeOwner + let owner let bondCreator let sortitionPool @@ -31,7 +31,7 @@ describe("EthBonding", function () { operator = accounts[1] authorizer = accounts[2] beneficiary = accounts[3] - stakeOwner = accounts[4] + owner = accounts[4] bondCreator = accounts[5] sortitionPool = accounts[6] @@ -42,8 +42,8 @@ describe("EthBonding", function () { await registry.approveOperatorContract(bondCreator) - await ethDelegating.stake(operator, beneficiary, authorizer, { - from: stakeOwner, + await ethDelegating.delegate(operator, beneficiary, authorizer, { + from: owner, }) await ethDelegating.authorizeOperatorContract(operator, bondCreator, { @@ -71,8 +71,8 @@ describe("EthBonding", function () { // ok, no reverts }) - it("can be called by stake owner", async () => { - await ethBonding.withdraw(value, operator, {from: stakeOwner}) + it("can be called by delegation owner", async () => { + await ethBonding.withdraw(value, operator, {from: owner}) // ok, no reverts }) @@ -149,9 +149,14 @@ describe("EthBonding", function () { await etherReceiver.setShouldFail(true) - await ethDelegating.stake(operator2, etherReceiver.address, authorizer, { - from: stakeOwner, - }) + await ethDelegating.delegate( + operator2, + etherReceiver.address, + authorizer, + { + from: owner, + } + ) await ethBonding.deposit(operator2, {value: value}) diff --git a/solidity/test/EthDelegatingTest.js b/solidity/test/EthDelegatingTest.js index 278d0ce6d..f41b9a6a0 100644 --- a/solidity/test/EthDelegatingTest.js +++ b/solidity/test/EthDelegatingTest.js @@ -20,13 +20,13 @@ describe("EthDelegating", function () { let operator let authorizer let beneficiary - let stakeOwner + let owner before(async () => { operator = accounts[1] authorizer = accounts[2] beneficiary = accounts[3] - stakeOwner = accounts[4] + owner = accounts[4] registry = await KeepRegistry.new() ethDelegating = await EthDelegating.new(registry.address) @@ -40,16 +40,16 @@ describe("EthDelegating", function () { await restoreSnapshot() }) - describe("stake", async () => { - it("registers stake", async () => { - await ethDelegating.stake(operator, beneficiary, authorizer, { - from: stakeOwner, + describe("delegate", async () => { + it("registers delegate", async () => { + await ethDelegating.delegate(operator, beneficiary, authorizer, { + from: owner, }) assert.equal( await ethDelegating.ownerOf(operator), - stakeOwner, - "incorrect stake owner address" + owner, + "incorrect owner address" ) assert.equal( @@ -66,22 +66,22 @@ describe("EthDelegating", function () { expect(await ethDelegating.balanceOf(operator)).to.eq.BN( 0, - "incorrect stake balance" + "incorrect delegation balance" ) }) it("emits events", async () => { - const receipt = await ethDelegating.stake( + const receipt = await ethDelegating.delegate( operator, beneficiary, authorizer, { - from: stakeOwner, + from: owner, } ) await expectEvent(receipt, "Delegated", { - owner: stakeOwner, + owner: owner, operator: operator, }) @@ -95,22 +95,22 @@ describe("EthDelegating", function () { it("allows multiple operators for the same owner", async () => { const operator2 = accounts[5] - await ethDelegating.stake(operator, beneficiary, authorizer, { - from: stakeOwner, + await ethDelegating.delegate(operator, beneficiary, authorizer, { + from: owner, }) - await ethDelegating.stake(operator2, beneficiary, authorizer, { - from: stakeOwner, + await ethDelegating.delegate(operator2, beneficiary, authorizer, { + from: owner, }) }) it("reverts if operator is already in use", async () => { - await ethDelegating.stake(operator, beneficiary, authorizer, { - from: stakeOwner, + await ethDelegating.delegate(operator, beneficiary, authorizer, { + from: owner, }) await expectRevert( - ethDelegating.stake(operator, accounts[5], accounts[5]), + ethDelegating.delegate(operator, accounts[5], accounts[5]), "Operator already in use" ) }) From 6c71ceaa0253b7db178db265f8bb7e52ea037e67 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 19 Aug 2020 13:50:54 +0200 Subject: [PATCH 10/57] Renamed _from to owner --- solidity/contracts/EthDelegating.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/solidity/contracts/EthDelegating.sol b/solidity/contracts/EthDelegating.sol index d2124a9ff..a63b1dddd 100644 --- a/solidity/contracts/EthDelegating.sol +++ b/solidity/contracts/EthDelegating.sol @@ -50,18 +50,18 @@ contract EthDelegating is Authorizations, StakeDelegatable { address authorizer ) external payable { // TODO: Do we need to verify the caller in any way? - address _from = msg.sender; + address owner = msg.sender; require( operators[operator].owner == address(0), "Operator already in use" ); - operators[operator] = Operator(0, _from, beneficiary, authorizer); + operators[operator] = Operator(0, owner, beneficiary, authorizer); // TODO: Add initialization period as per https://github.com/keep-network/keep-ecdsa/pull/483#discussion_r468628872 - emit Delegated(_from, operator); + emit Delegated(owner, operator); emit OperatorDelegated(operator, beneficiary, authorizer); } } From 24797782173abcbbec9d71ba163efc1d992eb9f1 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 19 Aug 2020 14:04:43 +0200 Subject: [PATCH 11/57] Expect contract typed addresses in constructors We know which specific implementation we expect to be passed to constructors so we can define them as parameters types. --- solidity/contracts/AbstractBonding.sol | 6 +++--- solidity/contracts/EthBonding.sol | 10 +++++----- solidity/contracts/KeepBonding.sol | 18 +++++++++--------- .../contracts/test/AbstractBondingStub.sol | 8 +++++--- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/solidity/contracts/AbstractBonding.sol b/solidity/contracts/AbstractBonding.sol index 44efdc9cd..d296079ea 100644 --- a/solidity/contracts/AbstractBonding.sol +++ b/solidity/contracts/AbstractBonding.sol @@ -71,9 +71,9 @@ contract AbstractBonding is IBondingManagement { ); /// @notice Initializes Keep Bonding contract. - /// @param registryAddress Keep registry contract address. - constructor(address registryAddress) public { - registry = KeepRegistry(registryAddress); + /// @param _keepRegistry Keep Registry contract address. + constructor(KeepRegistry _keepRegistry) public { + registry = _keepRegistry; } /// @notice Add the provided value to operator's pool available for bonding. diff --git a/solidity/contracts/EthBonding.sol b/solidity/contracts/EthBonding.sol index 31e857b3e..a2e096d55 100644 --- a/solidity/contracts/EthBonding.sol +++ b/solidity/contracts/EthBonding.sol @@ -23,13 +23,13 @@ contract EthBonding is AbstractBonding { EthDelegating ethDelegating; /// @notice Initializes Keep Bonding contract. - /// @param registryAddress Keep registry contract address. - /// @param ethDelegatingAddress ETH Staking contract address. - constructor(address registryAddress, address ethDelegatingAddress) + /// @param _keepRegistry Keep Registry contract address. + /// @param _ethDelegating ETH Delegating contract address. + constructor(KeepRegistry _keepRegistry, EthDelegating _ethDelegating) public - AbstractBonding(registryAddress) + AbstractBonding(_keepRegistry) { - ethDelegating = EthDelegating(ethDelegatingAddress); + ethDelegating = _ethDelegating; } /// @notice Withdraws amount from operator's value available for bonding. diff --git a/solidity/contracts/KeepBonding.sol b/solidity/contracts/KeepBonding.sol index 2042ef070..c313d3ffa 100644 --- a/solidity/contracts/KeepBonding.sol +++ b/solidity/contracts/KeepBonding.sol @@ -31,16 +31,16 @@ contract KeepBonding is AbstractBonding { TokenGrant internal tokenGrant; /// @notice Initializes Keep Bonding contract. - /// @param registryAddress Keep registry contract address. - /// @param tokenStakingAddress KEEP token staking contract address. - /// @param tokenGrantAddress KEEP token grant contract address. + /// @param _keepRegistry Keep Registry contract address. + /// @param _tokenStaking KEEP token staking contract address. + /// @param _tokenGrant KEEP token grant contract address. constructor( - address registryAddress, - address tokenStakingAddress, - address tokenGrantAddress - ) public AbstractBonding(registryAddress) { - tokenStaking = TokenStaking(tokenStakingAddress); - tokenGrant = TokenGrant(tokenGrantAddress); + KeepRegistry _keepRegistry, + TokenStaking _tokenStaking, + TokenGrant _tokenGrant + ) public AbstractBonding(_keepRegistry) { + tokenStaking = _tokenStaking; + tokenGrant = _tokenGrant; } /// @notice Withdraws amount from operator's value available for bonding. diff --git a/solidity/contracts/test/AbstractBondingStub.sol b/solidity/contracts/test/AbstractBondingStub.sol index 7fd083881..aa2f71cbb 100644 --- a/solidity/contracts/test/AbstractBondingStub.sol +++ b/solidity/contracts/test/AbstractBondingStub.sol @@ -4,14 +4,16 @@ import "../../contracts/AbstractBonding.sol"; import "./StakingInfoStub.sol"; +import "@keep-network/keep-core/contracts/KeepRegistry.sol"; + contract AbstractBondingStub is AbstractBonding { StakingInfoStub stakingInfoStub; - constructor(address registryAddress, address stakingInfoAddress) + constructor(KeepRegistry _keepRegistry, StakingInfoStub _stakingInfoStub) public - AbstractBonding(registryAddress) + AbstractBonding(_keepRegistry) { - stakingInfoStub = StakingInfoStub(stakingInfoAddress); + stakingInfoStub = _stakingInfoStub; } function withdraw(uint256 amount, address operator) public { From c61e18c39c6f991f13c022c2628fc61dab4e31fa Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 19 Aug 2020 15:31:41 +0200 Subject: [PATCH 12/57] Combined EthDelegating into EthBonding Moved pieces of EthDelegating contract into EthBonding contract. It's enough to have just one contract holding all the things around ETH bonding and delegation details. --- solidity/contracts/EthBonding.sol | 77 ++++++++++------- solidity/contracts/EthDelegating.sol | 67 --------------- solidity/test/EthBondingTest.js | 109 ++++++++++++++++++++----- solidity/test/EthDelegatingTest.js | 118 --------------------------- 4 files changed, 136 insertions(+), 235 deletions(-) delete mode 100644 solidity/contracts/EthDelegating.sol delete mode 100644 solidity/test/EthDelegatingTest.js diff --git a/solidity/contracts/EthBonding.sol b/solidity/contracts/EthBonding.sol index a2e096d55..b2cca7fba 100644 --- a/solidity/contracts/EthBonding.sol +++ b/solidity/contracts/EthBonding.sol @@ -15,21 +15,59 @@ pragma solidity 0.5.17; import "./AbstractBonding.sol"; -import "./EthDelegating.sol"; + +import "@keep-network/keep-core/contracts/Authorizations.sol"; +import "@keep-network/keep-core/contracts/KeepRegistry.sol"; +import "@keep-network/keep-core/contracts/StakeDelegatable.sol"; /// @title ETH Bonding -/// @notice Contract holding deposits from ETH-only keeps' operators. -contract EthBonding is AbstractBonding { - EthDelegating ethDelegating; +/// @notice Contract holding deposits and delegations for ETH-only keeps' +/// operators. An owner of the ETH can delegate ETH to an operator. The value +/// of ETH the owner is willing to delegate should be deposited for the given +/// operator. +contract EthBonding is AbstractBonding, Authorizations, StakeDelegatable { + event Delegated(address indexed owner, address indexed operator); + + event OperatorDelegated( + address indexed operator, + address indexed beneficiary, + address indexed authorizer + ); /// @notice Initializes Keep Bonding contract. /// @param _keepRegistry Keep Registry contract address. - /// @param _ethDelegating ETH Delegating contract address. - constructor(KeepRegistry _keepRegistry, EthDelegating _ethDelegating) + constructor(KeepRegistry _keepRegistry) public AbstractBonding(_keepRegistry) - { - ethDelegating = _ethDelegating; + Authorizations(_keepRegistry) + {} + + /// @notice Registers delegation details. The function is used to register + /// addresses of operator, beneficiary and authorizer for a delegation from + /// the caller. + /// @param operator Address of the operator. + /// @param beneficiary Address of the beneficiary. + /// @param authorizer Address of the authorizer. + function delegate( + address operator, + address payable beneficiary, + address authorizer + ) external payable { + // check value passed with delegation + + address owner = msg.sender; + + require( + operators[operator].owner == address(0), + "Operator already in use" + ); + + operators[operator] = Operator(0, owner, beneficiary, authorizer); + + // TODO: Add initialization period as per https://github.com/keep-network/keep-ecdsa/pull/483#discussion_r468628872 + + emit Delegated(owner, operator); + emit OperatorDelegated(operator, beneficiary, authorizer); } /// @notice Withdraws amount from operator's value available for bonding. @@ -41,31 +79,10 @@ contract EthBonding is AbstractBonding { /// @param operator Address of the operator. function withdraw(uint256 amount, address operator) public { require( - msg.sender == operator || - msg.sender == ethDelegating.ownerOf(operator), + msg.sender == operator || msg.sender == ownerOf(operator), "Only operator or the owner is allowed to withdraw bond" ); withdrawBond(amount, operator); } - - function isAuthorizedForOperator( - address _operator, - address _operatorContract - ) public view returns (bool) { - return - ethDelegating.isAuthorizedForOperator(_operator, _operatorContract); - } - - function authorizerOf(address _operator) public view returns (address) { - return ethDelegating.authorizerOf(_operator); - } - - function beneficiaryOf(address _operator) - public - view - returns (address payable) - { - return ethDelegating.beneficiaryOf(_operator); - } } diff --git a/solidity/contracts/EthDelegating.sol b/solidity/contracts/EthDelegating.sol deleted file mode 100644 index a63b1dddd..000000000 --- a/solidity/contracts/EthDelegating.sol +++ /dev/null @@ -1,67 +0,0 @@ -/** -▓▓▌ ▓▓ ▐▓▓ ▓▓▓▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▄ -▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - ▓▓▓▓▓▓ ▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓ ▐▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓ ▐▓▓▓▓▓▌ ▐▓▓▓▓▓▓ - ▓▓▓▓▓▓▄▄▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓▄▄▄▄ ▓▓▓▓▓▓▄▄▄▄ ▐▓▓▓▓▓▌ ▐▓▓▓▓▓▓ - ▓▓▓▓▓▓▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▌ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - ▓▓▓▓▓▓▀▀▓▓▓▓▓▓▄ ▐▓▓▓▓▓▓▀▀▀▀ ▓▓▓▓▓▓▀▀▀▀ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▀ - ▓▓▓▓▓▓ ▀▓▓▓▓▓▓▄ ▐▓▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓ ▐▓▓▓▓▓▌ -▓▓▓▓▓▓▓▓▓▓ █▓▓▓▓▓▓▓▓▓ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ -▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ - - Trust math, not hardware. -*/ - -pragma solidity 0.5.17; - -import "@keep-network/keep-core/contracts/KeepRegistry.sol"; -import "@keep-network/keep-core/contracts/Authorizations.sol"; -import "@keep-network/keep-core/contracts/StakeDelegatable.sol"; - -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -/// @title ETH Delegating -/// @notice A contract for ETH delegating. An owner of the ETH can delegate -/// ETH as to an operator. The value of ETH the owner is willing to delegate -/// should be deposited in `EthBonding` contract for the given operator. -contract EthDelegating is Authorizations, StakeDelegatable { - event Delegated(address indexed owner, address indexed operator); - - event OperatorDelegated( - address indexed operator, - address indexed beneficiary, - address indexed authorizer - ); - - constructor(KeepRegistry keepRegistry) - public - Authorizations(keepRegistry) - {} - - /// @notice Registers delegation details. The function is used to register - /// addresses of operator, beneficiary and authorizer for a delegation from - /// the caller. - /// @param operator Address of the operator. - /// @param beneficiary Address of the beneficiary. - /// @param authorizer Address of the authorizer. - function delegate( - address operator, - address payable beneficiary, - address authorizer - ) external payable { - // TODO: Do we need to verify the caller in any way? - address owner = msg.sender; - - require( - operators[operator].owner == address(0), - "Operator already in use" - ); - - operators[operator] = Operator(0, owner, beneficiary, authorizer); - - // TODO: Add initialization period as per https://github.com/keep-network/keep-ecdsa/pull/483#discussion_r468628872 - - emit Delegated(owner, operator); - emit OperatorDelegated(operator, beneficiary, authorizer); - } -} diff --git a/solidity/test/EthBondingTest.js b/solidity/test/EthBondingTest.js index 143292b62..65edd55c2 100644 --- a/solidity/test/EthBondingTest.js +++ b/solidity/test/EthBondingTest.js @@ -2,7 +2,6 @@ const {accounts, contract, web3} = require("@openzeppelin/test-environment") const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot") const KeepRegistry = contract.fromArtifact("KeepRegistry") -const EthDelegating = contract.fromArtifact("EthDelegating") const EthBonding = contract.fromArtifact("EthBonding") const TestEtherReceiver = contract.fromArtifact("TestEtherReceiver") @@ -13,10 +12,10 @@ const BN = web3.utils.BN const chai = require("chai") chai.use(require("bn-chai")(BN)) const expect = chai.expect +const assert = chai.assert describe("EthBonding", function () { let registry - let ethDelegating let ethBonding let etherReceiver @@ -36,19 +35,10 @@ describe("EthBonding", function () { sortitionPool = accounts[6] registry = await KeepRegistry.new() - ethDelegating = await EthDelegating.new(registry.address) - ethBonding = await EthBonding.new(registry.address, ethDelegating.address) + ethBonding = await EthBonding.new(registry.address) etherReceiver = await TestEtherReceiver.new() await registry.approveOperatorContract(bondCreator) - - await ethDelegating.delegate(operator, beneficiary, authorizer, { - from: owner, - }) - - await ethDelegating.authorizeOperatorContract(operator, bondCreator, { - from: authorizer, - }) }) beforeEach(async () => { @@ -59,11 +49,95 @@ describe("EthBonding", function () { await restoreSnapshot() }) + describe("delegate", async () => { + it("registers delegate", async () => { + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + }) + + assert.equal( + await ethBonding.ownerOf(operator), + owner, + "incorrect owner address" + ) + + assert.equal( + await ethBonding.beneficiaryOf(operator), + beneficiary, + "incorrect beneficiary address" + ) + + assert.equal( + await ethBonding.authorizerOf(operator), + authorizer, + "incorrect authorizer address" + ) + + expect(await ethBonding.balanceOf(operator)).to.eq.BN( + 0, + "incorrect delegation balance" + ) + }) + + it("emits events", async () => { + const receipt = await ethBonding.delegate( + operator, + beneficiary, + authorizer, + { + from: owner, + } + ) + + await expectEvent(receipt, "Delegated", { + owner: owner, + operator: operator, + }) + + await expectEvent(receipt, "OperatorDelegated", { + operator: operator, + beneficiary: beneficiary, + authorizer: authorizer, + }) + }) + + it("allows multiple operators for the same owner", async () => { + const operator2 = accounts[5] + + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + }) + + await ethBonding.delegate(operator2, beneficiary, authorizer, { + from: owner, + }) + }) + + it("reverts if operator is already in use", async () => { + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + }) + + await expectRevert( + ethBonding.delegate(operator, accounts[5], accounts[5]), + "Operator already in use" + ) + }) + }) + describe("withdraw", async () => { const value = new BN(1000) beforeEach(async () => { + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + }) + await ethBonding.deposit(operator, {value: value}) + + await ethBonding.authorizeOperatorContract(operator, bondCreator, { + from: authorizer, + }) }) it("can be called by operator", async () => { @@ -149,14 +223,9 @@ describe("EthBonding", function () { await etherReceiver.setShouldFail(true) - await ethDelegating.delegate( - operator2, - etherReceiver.address, - authorizer, - { - from: owner, - } - ) + await ethBonding.delegate(operator2, etherReceiver.address, authorizer, { + from: owner, + }) await ethBonding.deposit(operator2, {value: value}) diff --git a/solidity/test/EthDelegatingTest.js b/solidity/test/EthDelegatingTest.js deleted file mode 100644 index f41b9a6a0..000000000 --- a/solidity/test/EthDelegatingTest.js +++ /dev/null @@ -1,118 +0,0 @@ -const {accounts, contract, web3} = require("@openzeppelin/test-environment") -const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot") - -const KeepRegistry = contract.fromArtifact("KeepRegistry") -const EthDelegating = contract.fromArtifact("EthDelegating") - -const {expectEvent, expectRevert} = require("@openzeppelin/test-helpers") - -const BN = web3.utils.BN - -const chai = require("chai") -chai.use(require("bn-chai")(BN)) -const expect = chai.expect -const assert = chai.assert - -describe("EthDelegating", function () { - let registry - let ethDelegating - - let operator - let authorizer - let beneficiary - let owner - - before(async () => { - operator = accounts[1] - authorizer = accounts[2] - beneficiary = accounts[3] - owner = accounts[4] - - registry = await KeepRegistry.new() - ethDelegating = await EthDelegating.new(registry.address) - }) - - beforeEach(async () => { - await createSnapshot() - }) - - afterEach(async () => { - await restoreSnapshot() - }) - - describe("delegate", async () => { - it("registers delegate", async () => { - await ethDelegating.delegate(operator, beneficiary, authorizer, { - from: owner, - }) - - assert.equal( - await ethDelegating.ownerOf(operator), - owner, - "incorrect owner address" - ) - - assert.equal( - await ethDelegating.beneficiaryOf(operator), - beneficiary, - "incorrect beneficiary address" - ) - - assert.equal( - await ethDelegating.authorizerOf(operator), - authorizer, - "incorrect authorizer address" - ) - - expect(await ethDelegating.balanceOf(operator)).to.eq.BN( - 0, - "incorrect delegation balance" - ) - }) - - it("emits events", async () => { - const receipt = await ethDelegating.delegate( - operator, - beneficiary, - authorizer, - { - from: owner, - } - ) - - await expectEvent(receipt, "Delegated", { - owner: owner, - operator: operator, - }) - - await expectEvent(receipt, "OperatorDelegated", { - operator: operator, - beneficiary: beneficiary, - authorizer: authorizer, - }) - }) - - it("allows multiple operators for the same owner", async () => { - const operator2 = accounts[5] - - await ethDelegating.delegate(operator, beneficiary, authorizer, { - from: owner, - }) - - await ethDelegating.delegate(operator2, beneficiary, authorizer, { - from: owner, - }) - }) - - it("reverts if operator is already in use", async () => { - await ethDelegating.delegate(operator, beneficiary, authorizer, { - from: owner, - }) - - await expectRevert( - ethDelegating.delegate(operator, accounts[5], accounts[5]), - "Operator already in use" - ) - }) - }) -}) From 07e5ddb6196d57902d56f9740d2748b17e0067e2 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Wed, 19 Aug 2020 15:37:52 +0200 Subject: [PATCH 13/57] Added EthBonding to deployment script --- solidity/migrations/2_deploy_contracts.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/solidity/migrations/2_deploy_contracts.js b/solidity/migrations/2_deploy_contracts.js index 81b65c9f7..48b6d91a3 100644 --- a/solidity/migrations/2_deploy_contracts.js +++ b/solidity/migrations/2_deploy_contracts.js @@ -1,4 +1,5 @@ const KeepRegistry = artifacts.require("KeepRegistry") + const KeepBonding = artifacts.require("KeepBonding") const BondedECDSAKeep = artifacts.require("BondedECDSAKeep") const BondedECDSAKeepFactory = artifacts.require("BondedECDSAKeepFactory") @@ -7,6 +8,8 @@ const BondedECDSAKeepVendorImplV1 = artifacts.require( "BondedECDSAKeepVendorImplV1" ) +const EthBonding = artifacts.require("EthBonding") + const { deployBondedSortitionPoolFactory, } = require("@keep-network/sortition-pools/migrations/scripts/deployContracts") @@ -37,6 +40,7 @@ module.exports = async function (deployer) { RegistryAddress = (await deployer.deploy(KeepRegistry)).address } + // KEEP and ETH backed bonding await deployer.deploy( KeepBonding, RegistryAddress, @@ -68,4 +72,7 @@ module.exports = async function (deployer) { BondedECDSAKeepVendorImplV1.address, implInitializeCallData ) + + // ETH-only backed bonding + await deployer.deploy(EthBonding, RegistryAddress) } From a8f4489422165ec57fbe511cf4cd14b1c399f2cc Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 20 Aug 2020 19:54:20 +0200 Subject: [PATCH 14/57] Initialization period for ETH-only delegation Added initialization period that is used to protect from attacks on group selection. After delegation the operator has to wait the specific period of time before being eligible to be selected to a group. The function isInitialized is exposed by an interface required by the FullyBackedSortitionPool for communciation with the bonding contract. Begining of the initialiation period is the moment of delegation receival. The `isInitialized` functions checks if the initialiation period has passed and if the bond creator contract has been authorized for the given operator. --- solidity/contracts/EthBonding.sol | 58 +++++++++++++++++++++--- solidity/test/EthBondingTest.js | 73 +++++++++++++++++++++++++++++-- 2 files changed, 122 insertions(+), 9 deletions(-) diff --git a/solidity/contracts/EthBonding.sol b/solidity/contracts/EthBonding.sol index b2cca7fba..82108e726 100644 --- a/solidity/contracts/EthBonding.sol +++ b/solidity/contracts/EthBonding.sol @@ -20,12 +20,19 @@ import "@keep-network/keep-core/contracts/Authorizations.sol"; import "@keep-network/keep-core/contracts/KeepRegistry.sol"; import "@keep-network/keep-core/contracts/StakeDelegatable.sol"; +import "@keep-network/sortition-pools/contracts/api/IFullyBackedBonding.sol"; + /// @title ETH Bonding /// @notice Contract holding deposits and delegations for ETH-only keeps' /// operators. An owner of the ETH can delegate ETH to an operator. The value /// of ETH the owner is willing to delegate should be deposited for the given /// operator. -contract EthBonding is AbstractBonding, Authorizations, StakeDelegatable { +contract EthBonding is + AbstractBonding, + Authorizations, + StakeDelegatable, + IFullyBackedBonding +{ event Delegated(address indexed owner, address indexed operator); event OperatorDelegated( @@ -34,13 +41,20 @@ contract EthBonding is AbstractBonding, Authorizations, StakeDelegatable { address indexed authorizer ); + uint256 public initializationPeriod; + /// @notice Initializes Keep Bonding contract. /// @param _keepRegistry Keep Registry contract address. - constructor(KeepRegistry _keepRegistry) + /// @param _initializationPeriod To avoid certain attacks on group selection, + /// recently delegated operators must wait for a specific period of time + /// before being eligible for group selection. + constructor(KeepRegistry _keepRegistry, uint256 _initializationPeriod) public AbstractBonding(_keepRegistry) Authorizations(_keepRegistry) - {} + { + initializationPeriod = _initializationPeriod; + } /// @notice Registers delegation details. The function is used to register /// addresses of operator, beneficiary and authorizer for a delegation from @@ -62,14 +76,35 @@ contract EthBonding is AbstractBonding, Authorizations, StakeDelegatable { "Operator already in use" ); - operators[operator] = Operator(0, owner, beneficiary, authorizer); - - // TODO: Add initialization period as per https://github.com/keep-network/keep-ecdsa/pull/483#discussion_r468628872 + operators[operator] = Operator( + OperatorParams.pack(0, block.timestamp, 0), + owner, + beneficiary, + authorizer + ); emit Delegated(owner, operator); emit OperatorDelegated(operator, beneficiary, authorizer); } + /// @notice Checks if the operator for the given bond creator contract + /// has passed the initialization period. + /// @param operator The operator address. + /// @param bondCreator The bond creator contract address. + /// @return True if operator has passed initialization period for given + /// bond creator contract, false otherwise. + function isInitialized(address operator, address bondCreator) + public + view + returns (bool) + { + uint256 operatorParams = operators[operator].packedParams; + + return + isAuthorizedForOperator(operator, bondCreator) && + _isInitialized(operatorParams); + } + /// @notice Withdraws amount from operator's value available for bonding. /// This function can be called only by: /// - operator, @@ -85,4 +120,15 @@ contract EthBonding is AbstractBonding, Authorizations, StakeDelegatable { withdrawBond(amount, operator); } + + /// @notice Is the operator with the given params initialized + function _isInitialized(uint256 operatorParams) + internal + view + returns (bool) + { + return + block.timestamp > + operatorParams.getCreationTimestamp().add(initializationPeriod); + } } diff --git a/solidity/test/EthBondingTest.js b/solidity/test/EthBondingTest.js index 65edd55c2..37bd177fd 100644 --- a/solidity/test/EthBondingTest.js +++ b/solidity/test/EthBondingTest.js @@ -5,7 +5,7 @@ const KeepRegistry = contract.fromArtifact("KeepRegistry") const EthBonding = contract.fromArtifact("EthBonding") const TestEtherReceiver = contract.fromArtifact("TestEtherReceiver") -const {expectEvent, expectRevert} = require("@openzeppelin/test-helpers") +const {expectEvent, expectRevert, time} = require("@openzeppelin/test-helpers") const BN = web3.utils.BN @@ -15,6 +15,8 @@ const expect = chai.expect const assert = chai.assert describe("EthBonding", function () { + const initializationPeriod = new BN(60) + let registry let ethBonding let etherReceiver @@ -25,6 +27,7 @@ describe("EthBonding", function () { let owner let bondCreator let sortitionPool + let thirdParty before(async () => { operator = accounts[1] @@ -33,9 +36,10 @@ describe("EthBonding", function () { owner = accounts[4] bondCreator = accounts[5] sortitionPool = accounts[6] + thirdParty = accounts[7] registry = await KeepRegistry.new() - ethBonding = await EthBonding.new(registry.address) + ethBonding = await EthBonding.new(registry.address, initializationPeriod) etherReceiver = await TestEtherReceiver.new() await registry.approveOperatorContract(bondCreator) @@ -50,7 +54,7 @@ describe("EthBonding", function () { }) describe("delegate", async () => { - it("registers delegate", async () => { + it("registers delegation", async () => { await ethBonding.delegate(operator, beneficiary, authorizer, { from: owner, }) @@ -235,4 +239,67 @@ describe("EthBonding", function () { ) }) }) + + describe("isInitialized", async () => { + it("returns true when authorized and initialization period passed", async () => { + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + }) + + await ethBonding.authorizeOperatorContract(operator, bondCreator, { + from: authorizer, + }) + + await time.increase(initializationPeriod.addn(1)) + + assert.isTrue(await ethBonding.isInitialized(operator, bondCreator)) + }) + + it("returns false when authorized but initialization period not passed yet", async () => { + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + }) + + await ethBonding.authorizeOperatorContract(operator, bondCreator, { + from: authorizer, + }) + + await time.increase(initializationPeriod) + + assert.isFalse(await ethBonding.isInitialized(operator, bondCreator)) + }) + + it("returns false when initialization period passed but not authorized", async () => { + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + }) + + await time.increase(initializationPeriod.addn(1)) + + assert.isFalse(await ethBonding.isInitialized(operator, bondCreator)) + }) + + it("returns false when not authorized and initialization period not passed", async () => { + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + }) + + assert.isFalse(await ethBonding.isInitialized(operator, bondCreator)) + }) + + it("returns false when initialization period passed but other contract authorized", async () => { + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + }) + + await registry.approveOperatorContract(thirdParty) + await ethBonding.authorizeOperatorContract(operator, thirdParty, { + from: authorizer, + }) + + await time.increase(initializationPeriod.addn(1)) + + assert.isFalse(await ethBonding.isInitialized(operator, bondCreator)) + }) + }) }) From aab2b897d2af4880aa326f8a0718f7516ae7f7e6 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 20 Aug 2020 21:14:26 +0200 Subject: [PATCH 15/57] Require minimum ETH value passed on delegation To protect the delegation process from an attacks when an adversary wants to block operator's account with a fake delegation before the real owner delegates. The protection is a requirement to provide some ETH with a call. The complete value is deposited in the contract as unbonded value that can be used later for bonding by the operator. This commit contains some stub value definition that should be changed to proper value for mainnet. --- solidity/contracts/EthBonding.sol | 16 +++- solidity/test/EthBondingTest.js | 125 +++++++++++++++++++++++++++--- 2 files changed, 128 insertions(+), 13 deletions(-) diff --git a/solidity/contracts/EthBonding.sol b/solidity/contracts/EthBonding.sol index 82108e726..a80cbcd14 100644 --- a/solidity/contracts/EthBonding.sol +++ b/solidity/contracts/EthBonding.sol @@ -41,6 +41,9 @@ contract EthBonding is address indexed authorizer ); + // TODO: Decide on the final value and if we want a setter for it. + uint256 public constant MINIMUM_DELEGATION_DEPOSIT = 12345; + uint256 public initializationPeriod; /// @notice Initializes Keep Bonding contract. @@ -59,6 +62,10 @@ contract EthBonding is /// @notice Registers delegation details. The function is used to register /// addresses of operator, beneficiary and authorizer for a delegation from /// the caller. + /// The function requires ETH to be submitted in the call as a protection + /// against attacks blocking operators. The value should be at least equal + /// to the minimum delegation deposit. Whole amount is deposited as operator's + /// unbonded value for the future bonding. /// @param operator Address of the operator. /// @param beneficiary Address of the beneficiary. /// @param authorizer Address of the authorizer. @@ -67,8 +74,6 @@ contract EthBonding is address payable beneficiary, address authorizer ) external payable { - // check value passed with delegation - address owner = msg.sender; require( @@ -76,6 +81,11 @@ contract EthBonding is "Operator already in use" ); + require( + msg.value >= MINIMUM_DELEGATION_DEPOSIT, + "Insufficient delegation value" + ); + operators[operator] = Operator( OperatorParams.pack(0, block.timestamp, 0), owner, @@ -83,6 +93,8 @@ contract EthBonding is authorizer ); + deposit(operator); + emit Delegated(owner, operator); emit OperatorDelegated(operator, beneficiary, authorizer); } diff --git a/solidity/test/EthBondingTest.js b/solidity/test/EthBondingTest.js index 37bd177fd..eb68758f4 100644 --- a/solidity/test/EthBondingTest.js +++ b/solidity/test/EthBondingTest.js @@ -17,6 +17,8 @@ const assert = chai.assert describe("EthBonding", function () { const initializationPeriod = new BN(60) + let minimumDelegationValue + let registry let ethBonding let etherReceiver @@ -42,6 +44,8 @@ describe("EthBonding", function () { ethBonding = await EthBonding.new(registry.address, initializationPeriod) etherReceiver = await TestEtherReceiver.new() + minimumDelegationValue = await ethBonding.MINIMUM_DELEGATION_DEPOSIT() + await registry.approveOperatorContract(bondCreator) }) @@ -57,6 +61,7 @@ describe("EthBonding", function () { it("registers delegation", async () => { await ethBonding.delegate(operator, beneficiary, authorizer, { from: owner, + value: minimumDelegationValue, }) assert.equal( @@ -90,6 +95,7 @@ describe("EthBonding", function () { authorizer, { from: owner, + value: minimumDelegationValue, } ) @@ -105,21 +111,66 @@ describe("EthBonding", function () { }) }) + it("deposits passed value as unbonded value", async () => { + const value = minimumDelegationValue + + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + value: value, + }) + + expect(await ethBonding.unbondedValue(operator)).to.eq.BN( + value, + "invalid unbonded value" + ) + + await ethBonding.authorizeOperatorContract(operator, bondCreator, { + from: authorizer, + }) + + await ethBonding.authorizeSortitionPoolContract(operator, sortitionPool, { + from: authorizer, + }) + + expect( + await ethBonding.availableUnbondedValue( + operator, + bondCreator, + sortitionPool + ) + ).to.eq.BN(value, "invalid available unbonded value") + }) + + it("reverts if insufficient value passed", async () => { + const value = minimumDelegationValue.subn(1) + + await expectRevert( + ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + value: value, + }), + "Insufficient delegation value" + ) + }) + it("allows multiple operators for the same owner", async () => { const operator2 = accounts[5] await ethBonding.delegate(operator, beneficiary, authorizer, { from: owner, + value: minimumDelegationValue, }) await ethBonding.delegate(operator2, beneficiary, authorizer, { from: owner, + value: minimumDelegationValue, }) }) it("reverts if operator is already in use", async () => { await ethBonding.delegate(operator, beneficiary, authorizer, { from: owner, + value: minimumDelegationValue, }) await expectRevert( @@ -129,16 +180,61 @@ describe("EthBonding", function () { }) }) + describe("deposit", async () => { + it("adds value to deposited on delegation", async () => { + const initialDeposit = minimumDelegationValue + const value = new BN(123) + const expectedFinalBalance = initialDeposit.add(value) + + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + value: initialDeposit, + }) + + expect(await ethBonding.unbondedValue(operator)).to.eq.BN( + initialDeposit, + "invalid initial unbonded value" + ) + + await ethBonding.deposit(operator, { + value: value, + }) + + expect(await ethBonding.unbondedValue(operator)).to.eq.BN( + expectedFinalBalance, + "invalid final unbonded value" + ) + + await ethBonding.authorizeOperatorContract(operator, bondCreator, { + from: authorizer, + }) + + await ethBonding.authorizeSortitionPoolContract(operator, sortitionPool, { + from: authorizer, + }) + + expect( + await ethBonding.availableUnbondedValue( + operator, + bondCreator, + sortitionPool + ) + ).to.eq.BN(expectedFinalBalance, "invalid final available unbonded value") + }) + }) + describe("withdraw", async () => { + let initialDeposit const value = new BN(1000) beforeEach(async () => { + initialDeposit = minimumDelegationValue + await ethBonding.delegate(operator, beneficiary, authorizer, { from: owner, + value: initialDeposit, }) - await ethBonding.deposit(operator, {value: value}) - await ethBonding.authorizeOperatorContract(operator, bondCreator, { from: authorizer, }) @@ -178,20 +274,23 @@ describe("EthBonding", function () { }) it("transfers unbonded value to beneficiary", async () => { - const expectedUnbonded = 0 + const expectedUnbonded = initialDeposit.sub(value) const expectedBeneficiaryBalance = web3.utils .toBN(await web3.eth.getBalance(beneficiary)) .add(value) + expect(await ethBonding.unbondedValue(operator)).to.eq.BN( + initialDeposit, + "invalid unbonded value" + ) + await ethBonding.withdraw(value, operator, {from: operator}) - const unbonded = await ethBonding.availableUnbondedValue( - operator, - bondCreator, - sortitionPool + expect(await ethBonding.unbondedValue(operator)).to.eq.BN( + expectedUnbonded, + "invalid unbonded value" ) - expect(unbonded).to.eq.BN(expectedUnbonded, "invalid unbonded value") const actualBeneficiaryBalance = await web3.eth.getBalance(beneficiary) expect(actualBeneficiaryBalance).to.eq.BN( @@ -214,7 +313,7 @@ describe("EthBonding", function () { }) it("reverts if insufficient unbonded value", async () => { - const invalidValue = value.add(new BN(1)) + const invalidValue = initialDeposit.addn(1) await expectRevert( ethBonding.withdraw(invalidValue, operator, {from: operator}), @@ -229,10 +328,9 @@ describe("EthBonding", function () { await ethBonding.delegate(operator2, etherReceiver.address, authorizer, { from: owner, + value: initialDeposit, }) - await ethBonding.deposit(operator2, {value: value}) - await expectRevert( ethBonding.withdraw(value, operator2, {from: operator2}), "Transfer failed" @@ -244,6 +342,7 @@ describe("EthBonding", function () { it("returns true when authorized and initialization period passed", async () => { await ethBonding.delegate(operator, beneficiary, authorizer, { from: owner, + value: minimumDelegationValue, }) await ethBonding.authorizeOperatorContract(operator, bondCreator, { @@ -258,6 +357,7 @@ describe("EthBonding", function () { it("returns false when authorized but initialization period not passed yet", async () => { await ethBonding.delegate(operator, beneficiary, authorizer, { from: owner, + value: minimumDelegationValue, }) await ethBonding.authorizeOperatorContract(operator, bondCreator, { @@ -272,6 +372,7 @@ describe("EthBonding", function () { it("returns false when initialization period passed but not authorized", async () => { await ethBonding.delegate(operator, beneficiary, authorizer, { from: owner, + value: minimumDelegationValue, }) await time.increase(initializationPeriod.addn(1)) @@ -282,6 +383,7 @@ describe("EthBonding", function () { it("returns false when not authorized and initialization period not passed", async () => { await ethBonding.delegate(operator, beneficiary, authorizer, { from: owner, + value: minimumDelegationValue, }) assert.isFalse(await ethBonding.isInitialized(operator, bondCreator)) @@ -290,6 +392,7 @@ describe("EthBonding", function () { it("returns false when initialization period passed but other contract authorized", async () => { await ethBonding.delegate(operator, beneficiary, authorizer, { from: owner, + value: minimumDelegationValue, }) await registry.approveOperatorContract(thirdParty) From 4a75c112eb8490b8a64b71874fe1d0f9cccd6080 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 20 Aug 2020 22:05:21 +0200 Subject: [PATCH 16/57] Added getDelegationInfo Added getDelegationInfo function that will be used by the dashboard to obtain details of the delegation. For now only createdAt value is being set on delegation to the timestamp of the delegation. --- solidity/contracts/EthBonding.sol | 18 ++++++++++++++++++ solidity/test/EthBondingTest.js | 13 +++++++++++++ 2 files changed, 31 insertions(+) diff --git a/solidity/contracts/EthBonding.sol b/solidity/contracts/EthBonding.sol index a80cbcd14..3c2fa26fc 100644 --- a/solidity/contracts/EthBonding.sol +++ b/solidity/contracts/EthBonding.sol @@ -133,6 +133,24 @@ contract EthBonding is withdrawBond(amount, operator); } + /// @notice Gets delegation info for the given operator. + /// @param operator Address of the operator. + /// @return createdAt The time when the delegation was created. + /// @return undelegatedAt The time when undelegation has been requested. + /// If undelegation has not been requested, 0 is returned. + function getDelegationInfo(address operator) + public + view + returns (uint256 createdAt, uint256 undelegatedAt) + { + uint256 operatorParams = operators[operator].packedParams; + + return ( + operatorParams.getCreationTimestamp(), + operatorParams.getUndelegationTimestamp() + ); + } + /// @notice Is the operator with the given params initialized function _isInitialized(uint256 operatorParams) internal diff --git a/solidity/test/EthBondingTest.js b/solidity/test/EthBondingTest.js index eb68758f4..800f6882b 100644 --- a/solidity/test/EthBondingTest.js +++ b/solidity/test/EthBondingTest.js @@ -404,5 +404,18 @@ describe("EthBonding", function () { assert.isFalse(await ethBonding.isInitialized(operator, bondCreator)) }) + + describe("getDelegationInfo", async () => { + it("returns delegation details", async () => { + await ethBonding.delegate(operator, beneficiary, authorizer, { + from: owner, + value: minimumDelegationValue, + }) + + const delegationInfo = await ethBonding.getDelegationInfo(operator) + expect(delegationInfo.createdAt).to.eq.BN(await time.latest()) + expect(delegationInfo.undelegatedAt).to.eq.BN(0) + }) + }) }) }) From b98050ad8c18a1b06365d9b075b01df000e693dc Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 24 Sep 2020 12:07:18 +0200 Subject: [PATCH 17/57] Renamed EthBonding to FullyBackedBonding --- .../{EthBonding.sol => FullyBackedBonding.sol} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename solidity/contracts/{EthBonding.sol => FullyBackedBonding.sol} (97%) diff --git a/solidity/contracts/EthBonding.sol b/solidity/contracts/FullyBackedBonding.sol similarity index 97% rename from solidity/contracts/EthBonding.sol rename to solidity/contracts/FullyBackedBonding.sol index 3c2fa26fc..1cfe96c4a 100644 --- a/solidity/contracts/EthBonding.sol +++ b/solidity/contracts/FullyBackedBonding.sol @@ -22,16 +22,16 @@ import "@keep-network/keep-core/contracts/StakeDelegatable.sol"; import "@keep-network/sortition-pools/contracts/api/IFullyBackedBonding.sol"; -/// @title ETH Bonding +/// @title Fully Backed Bonding /// @notice Contract holding deposits and delegations for ETH-only keeps' /// operators. An owner of the ETH can delegate ETH to an operator. The value /// of ETH the owner is willing to delegate should be deposited for the given /// operator. -contract EthBonding is +contract FullyBackedBonding is + IFullyBackedBonding, AbstractBonding, Authorizations, - StakeDelegatable, - IFullyBackedBonding + StakeDelegatable { event Delegated(address indexed owner, address indexed operator); @@ -46,7 +46,7 @@ contract EthBonding is uint256 public initializationPeriod; - /// @notice Initializes Keep Bonding contract. + /// @notice Initializes Fully Backed Bonding contract. /// @param _keepRegistry Keep Registry contract address. /// @param _initializationPeriod To avoid certain attacks on group selection, /// recently delegated operators must wait for a specific period of time From fd9945912c5e10564246313834dbc3ef263cc9de Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 24 Sep 2020 12:09:35 +0200 Subject: [PATCH 18/57] Updated order of imports --- solidity/contracts/FullyBackedBonding.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solidity/contracts/FullyBackedBonding.sol b/solidity/contracts/FullyBackedBonding.sol index 1cfe96c4a..0de6556cc 100644 --- a/solidity/contracts/FullyBackedBonding.sol +++ b/solidity/contracts/FullyBackedBonding.sol @@ -17,8 +17,8 @@ pragma solidity 0.5.17; import "./AbstractBonding.sol"; import "@keep-network/keep-core/contracts/Authorizations.sol"; -import "@keep-network/keep-core/contracts/KeepRegistry.sol"; import "@keep-network/keep-core/contracts/StakeDelegatable.sol"; +import "@keep-network/keep-core/contracts/KeepRegistry.sol"; import "@keep-network/sortition-pools/contracts/api/IFullyBackedBonding.sol"; From 6bf2f6a71627d6a94d19ba424d163dcdb66ba351 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 24 Sep 2020 12:10:49 +0200 Subject: [PATCH 19/57] Moved FullyBackedBonding contract to dedicated directory --- solidity/contracts/{ => fully-backed}/FullyBackedBonding.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename solidity/contracts/{ => fully-backed}/FullyBackedBonding.sol (99%) diff --git a/solidity/contracts/FullyBackedBonding.sol b/solidity/contracts/fully-backed/FullyBackedBonding.sol similarity index 99% rename from solidity/contracts/FullyBackedBonding.sol rename to solidity/contracts/fully-backed/FullyBackedBonding.sol index 0de6556cc..cd258e5ef 100644 --- a/solidity/contracts/FullyBackedBonding.sol +++ b/solidity/contracts/fully-backed/FullyBackedBonding.sol @@ -14,7 +14,7 @@ pragma solidity 0.5.17; -import "./AbstractBonding.sol"; +import "../AbstractBonding.sol"; import "@keep-network/keep-core/contracts/Authorizations.sol"; import "@keep-network/keep-core/contracts/StakeDelegatable.sol"; From 04c8d25087b7cf30d5f7ce7c3800741b548041f5 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 24 Sep 2020 12:13:40 +0200 Subject: [PATCH 20/57] Initial version of FullyBackedBondedECDSAKeep The contract is a Bonded ECDSA Keep that is backed only by ETH. There is no requirement for operators to stake any KEEP tokens. --- .../FullyBackedBondedECDSAKeep.sol | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol diff --git a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol new file mode 100644 index 000000000..5eb5dd514 --- /dev/null +++ b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol @@ -0,0 +1,69 @@ +/** +▓▓▌ ▓▓ ▐▓▓ ▓▓▓▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▄ +▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ + ▓▓▓▓▓▓ ▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓ ▐▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓ ▐▓▓▓▓▓▌ ▐▓▓▓▓▓▓ + ▓▓▓▓▓▓▄▄▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓▄▄▄▄ ▓▓▓▓▓▓▄▄▄▄ ▐▓▓▓▓▓▌ ▐▓▓▓▓▓▓ + ▓▓▓▓▓▓▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▌ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ + ▓▓▓▓▓▓▀▀▓▓▓▓▓▓▄ ▐▓▓▓▓▓▓▀▀▀▀ ▓▓▓▓▓▓▀▀▀▀ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▀ + ▓▓▓▓▓▓ ▀▓▓▓▓▓▓▄ ▐▓▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓ ▐▓▓▓▓▓▌ +▓▓▓▓▓▓▓▓▓▓ █▓▓▓▓▓▓▓▓▓ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ + + Trust math, not hardware. +*/ + +pragma solidity 0.5.17; + +import "../AbstractBondedECDSAKeep.sol"; +import "./FullyBackedBonding.sol"; +import "./FullyBackedBondedECDSAKeepFactory.sol"; + +/// @title Fully Backed Bonded ECDSA Keep +/// @notice ECDSA keep with additional signer bond requirement that is fully backed +/// by ETH only. +/// @dev This contract is used as a master contract for clone factory in +/// BondedECDSAKeepFactory as per EIP-1167. It should never be removed after +/// initial deployment as this will break functionality for all created clones. +contract FullyBackedBondedECDSAKeep is AbstractBondedECDSAKeep { + FullyBackedBonding bonding; + FullyBackedBondedECDSAKeepFactory keepFactory; + + /// @notice Initialization function. + /// @dev We use clone factory to create new keep. That is why this contract + /// doesn't have a constructor. We provide keep parameters for each instance + /// function after cloning instances from the master contract. + /// @param _owner Address of the keep owner. + /// @param _members Addresses of the keep members. + /// @param _honestThreshold Minimum number of honest keep members. + /// @param _bonding Address of the Bonding contract. + /// @param _keepFactory Address of the BondedECDSAKeepFactory that created + /// this keep. + function initialize( + address _owner, + address[] memory _members, + uint256 _honestThreshold, + address _bonding, + address payable _keepFactory + ) public { + super.initialize(_owner, _members, _honestThreshold, _bonding); + + bonding = FullyBackedBonding(_bonding); + keepFactory = FullyBackedBondedECDSAKeepFactory(_keepFactory); + } + + function slashForSignatureFraud() internal { + // TODO: We don't need to do anything as keep owner is able to seize the bonds + // TODO: Ban members (remove from sortition pool and don't let to rejoin) + } + + /// @notice Gets the beneficiary for the specified member address. + /// @param _member Member address. + /// @return Beneficiary address. + function beneficiaryOf(address _member) + internal + view + returns (address payable) + { + return bonding.beneficiaryOf(_member); + } +} From 7533b4abdcdbd0aa1f774571343fcce8a7a95fe4 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 24 Sep 2020 12:15:00 +0200 Subject: [PATCH 21/57] Initial version of FullyBackedBondedECDSAKeepFactory The contract is a factory for Bonded ECDSA Keep that is backed only by ETH. There is no requirement for operators to stake any KEEP tokens. --- .../FullyBackedBondedECDSAKeepFactory.sol | 249 ++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol diff --git a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol new file mode 100644 index 000000000..8af387020 --- /dev/null +++ b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol @@ -0,0 +1,249 @@ +/** +▓▓▌ ▓▓ ▐▓▓ ▓▓▓▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▄ +▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▌▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ + ▓▓▓▓▓▓ ▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓ ▐▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓ ▐▓▓▓▓▓▌ ▐▓▓▓▓▓▓ + ▓▓▓▓▓▓▄▄▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓▄▄▄▄ ▓▓▓▓▓▓▄▄▄▄ ▐▓▓▓▓▓▌ ▐▓▓▓▓▓▓ + ▓▓▓▓▓▓▓▓▓▓▓▓▓▀ ▐▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▌ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ + ▓▓▓▓▓▓▀▀▓▓▓▓▓▓▄ ▐▓▓▓▓▓▓▀▀▀▀ ▓▓▓▓▓▓▀▀▀▀ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▀ + ▓▓▓▓▓▓ ▀▓▓▓▓▓▓▄ ▐▓▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓ ▐▓▓▓▓▓▌ +▓▓▓▓▓▓▓▓▓▓ █▓▓▓▓▓▓▓▓▓ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ + + Trust math, not hardware. +*/ + +pragma solidity 0.5.17; + +import "./FullyBackedBondedECDSAKeep.sol"; + +import "./FullyBackedBonding.sol"; +import "../api/IBondedECDSAKeepFactory.sol"; +import "../KeepCreator.sol"; +import "../GroupSelectionSeed.sol"; +import "../CandidatesPools.sol"; + +import "@keep-network/sortition-pools/contracts/api/IFullyBackedBonding.sol"; +import "@keep-network/sortition-pools/contracts/FullyBackedSortitionPoolFactory.sol"; +import "@keep-network/sortition-pools/contracts/FullyBackedSortitionPool.sol"; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/// @title Fully Backed Bonded ECDSA Keep Factory +/// @notice Contract creating bonded ECDSA keeps that are fully backed by ETH. +/// @dev We avoid redeployment of bonded ECDSA keep contract by using the clone factory. +/// Proxy delegates calls to sortition pool and therefore does not affect contract's +/// state. This means that we only need to deploy the bonded ECDSA keep contract +/// once. The factory provides clean state for every new bonded ECDSA keep clone. +contract FullyBackedBondedECDSAKeepFactory is + IBondedECDSAKeepFactory, + KeepCreator, + AuthorityDelegator, + GroupSelectionSeed, + CandidatesPools +{ + FullyBackedSortitionPoolFactory sortitionPoolFactory; + FullyBackedBonding bonding; + + using SafeMath for uint256; + + // Sortition pool is created with a minimum bond of 20 ETH to avoid + // small operators joining and griefing future selections before the + // minimum bond is set to the right value by the application. + // + // Anyone can create a sortition pool for an application with the default + // minimum bond value but the application can change this value later, at + // any point. + uint256 public constant minimumBond = 20e18; // 20 ETH // TODO: Decide on value + + // Signer candidates in bonded sortition pool are weighted by their eligible + // stake divided by a constant divisor. The divisor is set to 1 KEEP so that + // all KEEPs in eligible stake matter when calculating operator's eligible + // weight for signer selection. + uint256 public constant bondWeightDivisor = 1e18; // 1 ETH // TODO: Decide on value + + // Notification that a new keep has been created. + event FullyBackedBondedECDSAKeepCreated( + address indexed keepAddress, + address[] members, + address indexed owner, + address indexed application, + uint256 honestThreshold + ); + + constructor( + address _masterKeepAddress, + address _sortitionPoolFactoryAddress, + address _bondingAddress, + address _randomBeaconAddress + ) + public + KeepCreator(_masterKeepAddress) + GroupSelectionSeed(_randomBeaconAddress) + { + sortitionPoolFactory = FullyBackedSortitionPoolFactory( + _sortitionPoolFactoryAddress + ); + + bonding = FullyBackedBonding(_bondingAddress); + } + + /// @notice Sets the minimum bondable value required from the operator to + /// join the sortition pool of the given application. It is up to the + /// application to specify a reasonable minimum bond for operators trying to + /// join the pool to prevent griefing by operators joining without enough + /// bondable value. + /// @param _minimumBondableValue The minimum bond value the application + /// requires from a single keep. + /// @param _groupSize Number of signers in the keep. + /// @param _honestThreshold Minimum number of honest keep signers. + function setMinimumBondableValue( + uint256 _minimumBondableValue, + uint256 _groupSize, + uint256 _honestThreshold + ) external { + uint256 memberBond = bondPerMember(_minimumBondableValue, _groupSize); + FullyBackedSortitionPool(getSortitionPool(msg.sender)) + .setMinimumBondableValue(memberBond); + } + + /// @notice Opens a new ECDSA keep. + /// @dev Selects a list of signers for the keep based on provided parameters. + /// A caller of this function is expected to be an application for which + /// member candidates were registered in a pool. + /// @param _groupSize Number of signers in the keep. + /// @param _honestThreshold Minimum number of honest keep signers. + /// @param _owner Address of the keep owner. + /// @param _bond Value of ETH bond required from the keep in wei. + /// @param _stakeLockDuration Stake lock duration in seconds. + /// @return Created keep address. + function openKeep( + uint256 _groupSize, + uint256 _honestThreshold, + address _owner, + uint256 _bond, + uint256 _stakeLockDuration + ) external payable nonReentrant returns (address keepAddress) { + require(_groupSize > 0, "Minimum signing group size is 1"); + require(_groupSize <= 16, "Maximum signing group size is 16"); + require( + _honestThreshold > 0, + "Honest threshold must be greater than 0" + ); + require( + _honestThreshold <= _groupSize, + "Honest threshold must be less or equal the group size" + ); + + address application = msg.sender; + address pool = getSortitionPool(application); + + uint256 memberBond = bondPerMember(_bond, _groupSize); + require(memberBond > 0, "Bond per member must be greater than zero"); + + require( + msg.value >= openKeepFeeEstimate(), + "Insufficient payment for opening a new keep" + ); + + address[] memory members = FullyBackedSortitionPool(pool) + .selectSetGroup( + _groupSize, + bytes32(groupSelectionSeed), + memberBond + ); + + newGroupSelectionSeed(); + + // createKeep sets keepOpenedTimestamp value for newly created keep which + // is required to be set before calling `keep.initialize` function as it + // is used to determine token staking delegation authority recognition + // in `__isRecognized` function. + keepAddress = createKeep(); + + FullyBackedBondedECDSAKeep(keepAddress).initialize( + _owner, + members, + _honestThreshold, + address(bonding), + address(this) + ); + + for (uint256 i = 0; i < _groupSize; i++) { + bonding.createBond( + members[i], + keepAddress, + uint256(keepAddress), + memberBond, + pool + ); + } + + emit FullyBackedBondedECDSAKeepCreated( + keepAddress, + members, + _owner, + application, + _honestThreshold + ); + } + + /// @notice Verifies if delegates authority recipient is valid address recognized + /// by the factory for token staking authority delegation. + /// @param _delegatedAuthorityRecipient Address of the delegated authority + /// recipient. + /// @return True if provided address is recognized delegated token staking + /// authority for this factory contract. + function __isRecognized(address _delegatedAuthorityRecipient) + external + returns (bool) + { + return keepOpenedTimestamp[_delegatedAuthorityRecipient] > 0; + } + + /// @notice Gets a fee estimate for opening a new keep. + /// @return Uint256 estimate. + function openKeepFeeEstimate() public view returns (uint256) { + return newEntryFeeEstimate(); + } + + /// @notice Checks if the factory has the authorization to operate on stake + /// represented by the provided operator. + /// + /// @param _operator operator's address + /// @return True if the factory has access to the staked token balance of + /// the provided operator and can slash that stake. False otherwise. + function isOperatorAuthorized(address _operator) + public + view + returns (bool) + { + return bonding.isAuthorizedForOperator(_operator, address(this)); + } + + function newSortitionPool(address _application) internal returns (address) { + return + sortitionPoolFactory.createSortitionPool( + IFullyBackedBonding(address(bonding)), + minimumBond, + bondWeightDivisor + ); + } + + /// @notice Calculates bond requirement per member performing the necessary + /// rounding. + /// @param _keepBond The bond required from a keep. + /// @param _groupSize Number of signers in the keep. + /// @return Bond value required from each keep member. + function bondPerMember(uint256 _keepBond, uint256 _groupSize) + internal + pure + returns (uint256) + { + // In Solidity, division rounds towards zero (down) and dividing + // '_bond' by '_groupSize' can leave a remainder. Even though, a remainder + // is very small, we want to avoid this from happening and memberBond is + // rounded up by: `(bond + groupSize - 1 ) / groupSize` + // Ex. (100 + 3 - 1) / 3 = 34 + return (_keepBond.add(_groupSize).sub(1)).div(_groupSize); + } +} From 20c375e8750fbee905a63b16e1096c6566bdb2f9 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 24 Sep 2020 12:24:45 +0200 Subject: [PATCH 22/57] Renamed EthBondingTest.js --- ...ndingTest.js => FullyBackedBondingTest.js} | 117 +++++++++--------- 1 file changed, 60 insertions(+), 57 deletions(-) rename solidity/test/{EthBondingTest.js => FullyBackedBondingTest.js} (68%) diff --git a/solidity/test/EthBondingTest.js b/solidity/test/FullyBackedBondingTest.js similarity index 68% rename from solidity/test/EthBondingTest.js rename to solidity/test/FullyBackedBondingTest.js index 800f6882b..2f3491a33 100644 --- a/solidity/test/EthBondingTest.js +++ b/solidity/test/FullyBackedBondingTest.js @@ -2,7 +2,7 @@ const {accounts, contract, web3} = require("@openzeppelin/test-environment") const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot") const KeepRegistry = contract.fromArtifact("KeepRegistry") -const EthBonding = contract.fromArtifact("EthBonding") +const FullyBackedBonding = contract.fromArtifact("FullyBackedBonding") const TestEtherReceiver = contract.fromArtifact("TestEtherReceiver") const {expectEvent, expectRevert, time} = require("@openzeppelin/test-helpers") @@ -14,13 +14,13 @@ chai.use(require("bn-chai")(BN)) const expect = chai.expect const assert = chai.assert -describe("EthBonding", function () { +describe("FullyBackedBonding", function () { const initializationPeriod = new BN(60) let minimumDelegationValue let registry - let ethBonding + let bonding let etherReceiver let operator @@ -41,10 +41,13 @@ describe("EthBonding", function () { thirdParty = accounts[7] registry = await KeepRegistry.new() - ethBonding = await EthBonding.new(registry.address, initializationPeriod) + bonding = await FullyBackedBonding.new( + registry.address, + initializationPeriod + ) etherReceiver = await TestEtherReceiver.new() - minimumDelegationValue = await ethBonding.MINIMUM_DELEGATION_DEPOSIT() + minimumDelegationValue = await bonding.MINIMUM_DELEGATION_DEPOSIT() await registry.approveOperatorContract(bondCreator) }) @@ -59,37 +62,37 @@ describe("EthBonding", function () { describe("delegate", async () => { it("registers delegation", async () => { - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: minimumDelegationValue, }) assert.equal( - await ethBonding.ownerOf(operator), + await bonding.ownerOf(operator), owner, "incorrect owner address" ) assert.equal( - await ethBonding.beneficiaryOf(operator), + await bonding.beneficiaryOf(operator), beneficiary, "incorrect beneficiary address" ) assert.equal( - await ethBonding.authorizerOf(operator), + await bonding.authorizerOf(operator), authorizer, "incorrect authorizer address" ) - expect(await ethBonding.balanceOf(operator)).to.eq.BN( + expect(await bonding.balanceOf(operator)).to.eq.BN( 0, "incorrect delegation balance" ) }) it("emits events", async () => { - const receipt = await ethBonding.delegate( + const receipt = await bonding.delegate( operator, beneficiary, authorizer, @@ -114,26 +117,26 @@ describe("EthBonding", function () { it("deposits passed value as unbonded value", async () => { const value = minimumDelegationValue - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: value, }) - expect(await ethBonding.unbondedValue(operator)).to.eq.BN( + expect(await bonding.unbondedValue(operator)).to.eq.BN( value, "invalid unbonded value" ) - await ethBonding.authorizeOperatorContract(operator, bondCreator, { + await bonding.authorizeOperatorContract(operator, bondCreator, { from: authorizer, }) - await ethBonding.authorizeSortitionPoolContract(operator, sortitionPool, { + await bonding.authorizeSortitionPoolContract(operator, sortitionPool, { from: authorizer, }) expect( - await ethBonding.availableUnbondedValue( + await bonding.availableUnbondedValue( operator, bondCreator, sortitionPool @@ -145,7 +148,7 @@ describe("EthBonding", function () { const value = minimumDelegationValue.subn(1) await expectRevert( - ethBonding.delegate(operator, beneficiary, authorizer, { + bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: value, }), @@ -156,25 +159,25 @@ describe("EthBonding", function () { it("allows multiple operators for the same owner", async () => { const operator2 = accounts[5] - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: minimumDelegationValue, }) - await ethBonding.delegate(operator2, beneficiary, authorizer, { + await bonding.delegate(operator2, beneficiary, authorizer, { from: owner, value: minimumDelegationValue, }) }) it("reverts if operator is already in use", async () => { - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: minimumDelegationValue, }) await expectRevert( - ethBonding.delegate(operator, accounts[5], accounts[5]), + bonding.delegate(operator, accounts[5], accounts[5]), "Operator already in use" ) }) @@ -186,35 +189,35 @@ describe("EthBonding", function () { const value = new BN(123) const expectedFinalBalance = initialDeposit.add(value) - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: initialDeposit, }) - expect(await ethBonding.unbondedValue(operator)).to.eq.BN( + expect(await bonding.unbondedValue(operator)).to.eq.BN( initialDeposit, "invalid initial unbonded value" ) - await ethBonding.deposit(operator, { + await bonding.deposit(operator, { value: value, }) - expect(await ethBonding.unbondedValue(operator)).to.eq.BN( + expect(await bonding.unbondedValue(operator)).to.eq.BN( expectedFinalBalance, "invalid final unbonded value" ) - await ethBonding.authorizeOperatorContract(operator, bondCreator, { + await bonding.authorizeOperatorContract(operator, bondCreator, { from: authorizer, }) - await ethBonding.authorizeSortitionPoolContract(operator, sortitionPool, { + await bonding.authorizeSortitionPoolContract(operator, sortitionPool, { from: authorizer, }) expect( - await ethBonding.availableUnbondedValue( + await bonding.availableUnbondedValue( operator, bondCreator, sortitionPool @@ -230,36 +233,36 @@ describe("EthBonding", function () { beforeEach(async () => { initialDeposit = minimumDelegationValue - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: initialDeposit, }) - await ethBonding.authorizeOperatorContract(operator, bondCreator, { + await bonding.authorizeOperatorContract(operator, bondCreator, { from: authorizer, }) }) it("can be called by operator", async () => { - await ethBonding.withdraw(value, operator, {from: operator}) + await bonding.withdraw(value, operator, {from: operator}) // ok, no reverts }) it("can be called by delegation owner", async () => { - await ethBonding.withdraw(value, operator, {from: owner}) + await bonding.withdraw(value, operator, {from: owner}) // ok, no reverts }) it("cannot be called by authorizer", async () => { await expectRevert( - ethBonding.withdraw(value, operator, {from: authorizer}), + bonding.withdraw(value, operator, {from: authorizer}), "Only operator or the owner is allowed to withdraw bond" ) }) it("cannot be called by beneficiary", async () => { await expectRevert( - ethBonding.withdraw(value, operator, {from: beneficiary}), + bonding.withdraw(value, operator, {from: beneficiary}), "Only operator or the owner is allowed to withdraw bond" ) }) @@ -268,7 +271,7 @@ describe("EthBonding", function () { const thirdParty = accounts[7] await expectRevert( - ethBonding.withdraw(value, operator, {from: thirdParty}), + bonding.withdraw(value, operator, {from: thirdParty}), "Only operator or the owner is allowed to withdraw bond" ) }) @@ -280,14 +283,14 @@ describe("EthBonding", function () { .toBN(await web3.eth.getBalance(beneficiary)) .add(value) - expect(await ethBonding.unbondedValue(operator)).to.eq.BN( + expect(await bonding.unbondedValue(operator)).to.eq.BN( initialDeposit, "invalid unbonded value" ) - await ethBonding.withdraw(value, operator, {from: operator}) + await bonding.withdraw(value, operator, {from: operator}) - expect(await ethBonding.unbondedValue(operator)).to.eq.BN( + expect(await bonding.unbondedValue(operator)).to.eq.BN( expectedUnbonded, "invalid unbonded value" ) @@ -302,7 +305,7 @@ describe("EthBonding", function () { it("emits event", async () => { const value = new BN(90) - const receipt = await ethBonding.withdraw(value, operator, { + const receipt = await bonding.withdraw(value, operator, { from: operator, }) expectEvent(receipt, "UnbondedValueWithdrawn", { @@ -316,7 +319,7 @@ describe("EthBonding", function () { const invalidValue = initialDeposit.addn(1) await expectRevert( - ethBonding.withdraw(invalidValue, operator, {from: operator}), + bonding.withdraw(invalidValue, operator, {from: operator}), "Insufficient unbonded value" ) }) @@ -326,13 +329,13 @@ describe("EthBonding", function () { await etherReceiver.setShouldFail(true) - await ethBonding.delegate(operator2, etherReceiver.address, authorizer, { + await bonding.delegate(operator2, etherReceiver.address, authorizer, { from: owner, value: initialDeposit, }) await expectRevert( - ethBonding.withdraw(value, operator2, {from: operator2}), + bonding.withdraw(value, operator2, {from: operator2}), "Transfer failed" ) }) @@ -340,79 +343,79 @@ describe("EthBonding", function () { describe("isInitialized", async () => { it("returns true when authorized and initialization period passed", async () => { - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: minimumDelegationValue, }) - await ethBonding.authorizeOperatorContract(operator, bondCreator, { + await bonding.authorizeOperatorContract(operator, bondCreator, { from: authorizer, }) await time.increase(initializationPeriod.addn(1)) - assert.isTrue(await ethBonding.isInitialized(operator, bondCreator)) + assert.isTrue(await bonding.isInitialized(operator, bondCreator)) }) it("returns false when authorized but initialization period not passed yet", async () => { - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: minimumDelegationValue, }) - await ethBonding.authorizeOperatorContract(operator, bondCreator, { + await bonding.authorizeOperatorContract(operator, bondCreator, { from: authorizer, }) await time.increase(initializationPeriod) - assert.isFalse(await ethBonding.isInitialized(operator, bondCreator)) + assert.isFalse(await bonding.isInitialized(operator, bondCreator)) }) it("returns false when initialization period passed but not authorized", async () => { - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: minimumDelegationValue, }) await time.increase(initializationPeriod.addn(1)) - assert.isFalse(await ethBonding.isInitialized(operator, bondCreator)) + assert.isFalse(await bonding.isInitialized(operator, bondCreator)) }) it("returns false when not authorized and initialization period not passed", async () => { - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: minimumDelegationValue, }) - assert.isFalse(await ethBonding.isInitialized(operator, bondCreator)) + assert.isFalse(await bonding.isInitialized(operator, bondCreator)) }) it("returns false when initialization period passed but other contract authorized", async () => { - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: minimumDelegationValue, }) await registry.approveOperatorContract(thirdParty) - await ethBonding.authorizeOperatorContract(operator, thirdParty, { + await bonding.authorizeOperatorContract(operator, thirdParty, { from: authorizer, }) await time.increase(initializationPeriod.addn(1)) - assert.isFalse(await ethBonding.isInitialized(operator, bondCreator)) + assert.isFalse(await bonding.isInitialized(operator, bondCreator)) }) describe("getDelegationInfo", async () => { it("returns delegation details", async () => { - await ethBonding.delegate(operator, beneficiary, authorizer, { + await bonding.delegate(operator, beneficiary, authorizer, { from: owner, value: minimumDelegationValue, }) - const delegationInfo = await ethBonding.getDelegationInfo(operator) + const delegationInfo = await bonding.getDelegationInfo(operator) expect(delegationInfo.createdAt).to.eq.BN(await time.latest()) expect(delegationInfo.undelegatedAt).to.eq.BN(0) }) From 81be402782b04d54451e30eb38d090922da5d3d1 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 25 Sep 2020 10:08:06 +0200 Subject: [PATCH 23/57] Added unit tests for FullyBacked keep and bonding --- ...yBackedBondedECDSAKeepCloneFactoryStub.sol | 54 + .../FullyBackedBondedECDSAKeepFactoryStub.sol | 38 + .../test/FullyBackedBondedECDSAKeepStub.sol | 23 + .../contracts/test/FullyBackedBondingStub.sol | 23 + .../FullyBackedBondedECDSAKeepFactoryTest.js | 1632 ++++++++++++++++ .../test/FullyBackedBondedECDSAKeepTest.js | 1719 +++++++++++++++++ 6 files changed, 3489 insertions(+) create mode 100644 solidity/contracts/test/FullyBackedBondedECDSAKeepCloneFactoryStub.sol create mode 100644 solidity/contracts/test/FullyBackedBondedECDSAKeepFactoryStub.sol create mode 100644 solidity/contracts/test/FullyBackedBondedECDSAKeepStub.sol create mode 100644 solidity/contracts/test/FullyBackedBondingStub.sol create mode 100644 solidity/test/FullyBackedBondedECDSAKeepFactoryTest.js create mode 100644 solidity/test/FullyBackedBondedECDSAKeepTest.js diff --git a/solidity/contracts/test/FullyBackedBondedECDSAKeepCloneFactoryStub.sol b/solidity/contracts/test/FullyBackedBondedECDSAKeepCloneFactoryStub.sol new file mode 100644 index 000000000..1668f5a3f --- /dev/null +++ b/solidity/contracts/test/FullyBackedBondedECDSAKeepCloneFactoryStub.sol @@ -0,0 +1,54 @@ +pragma solidity 0.5.17; + +import "../../contracts/fully-backed/FullyBackedBondedECDSAKeep.sol"; +import "../../contracts/CloneFactory.sol"; + +import { + AuthorityDelegator +} from "@keep-network/keep-core/contracts/Authorizations.sol"; + +/// @title Fully Backed Bonded ECDSA Keep Factory Stub using clone factory. +/// @dev This contract is for testing purposes only. +contract FullyBackedBondedECDSAKeepCloneFactoryStub is + CloneFactory, + AuthorityDelegator +{ + address public masterKeepAddress; + + constructor(address _masterKeepAddress) public { + masterKeepAddress = _masterKeepAddress; + } + + event FullyBackedBondedECDSAKeepCreated(address keepAddress); + + function newKeep( + address _owner, + address[] calldata _members, + uint256 _honestThreshold, + address _keepBonding, + address payable _keepFactory + ) external payable returns (address keepAddress) { + keepAddress = createClone(masterKeepAddress); + assert(isClone(masterKeepAddress, keepAddress)); + + FullyBackedBondedECDSAKeep keep = FullyBackedBondedECDSAKeep( + keepAddress + ); + keep.initialize( + _owner, + _members, + _honestThreshold, + _keepBonding, + _keepFactory + ); + + emit FullyBackedBondedECDSAKeepCreated(keepAddress); + } + + function __isRecognized(address _delegatedAuthorityRecipient) + external + returns (bool) + { + return true; + } +} diff --git a/solidity/contracts/test/FullyBackedBondedECDSAKeepFactoryStub.sol b/solidity/contracts/test/FullyBackedBondedECDSAKeepFactoryStub.sol new file mode 100644 index 000000000..e80464bd4 --- /dev/null +++ b/solidity/contracts/test/FullyBackedBondedECDSAKeepFactoryStub.sol @@ -0,0 +1,38 @@ +pragma solidity 0.5.17; + +import "../../contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol"; + +/// @title Fully Backed Bonded ECDSA Keep Factory Stub +/// @dev This contract is for testing purposes only. +contract FullyBackedBondedECDSAKeepFactoryStub is + FullyBackedBondedECDSAKeepFactory +{ + constructor( + address _masterKeepAddress, + address _sortitionPoolFactoryAddress, + address _bondingAddress, + address _randomBeaconAddress + ) + public + FullyBackedBondedECDSAKeepFactory( + _masterKeepAddress, + _sortitionPoolFactoryAddress, + _bondingAddress, + _randomBeaconAddress + ) + {} + + function initialGroupSelectionSeed(uint256 _groupSelectionSeed) public { + groupSelectionSeed = _groupSelectionSeed; + } + + function getGroupSelectionSeed() public view returns (uint256) { + return groupSelectionSeed; + } + + function addKeep(address keep) public { + keeps.push(keep); + /* solium-disable-next-line security/no-block-members*/ + keepOpenedTimestamp[keep] = block.timestamp; + } +} diff --git a/solidity/contracts/test/FullyBackedBondedECDSAKeepStub.sol b/solidity/contracts/test/FullyBackedBondedECDSAKeepStub.sol new file mode 100644 index 000000000..3f5a2119b --- /dev/null +++ b/solidity/contracts/test/FullyBackedBondedECDSAKeepStub.sol @@ -0,0 +1,23 @@ +pragma solidity 0.5.17; + +import "../../contracts/fully-backed/FullyBackedBondedECDSAKeep.sol"; + +/// @title Fully Backed Bonded ECDSA Keep Stub +/// @dev This contract is for testing purposes only. +contract FullyBackedBondedECDSAKeepStub is FullyBackedBondedECDSAKeep { + function publicMarkAsClosed() public { + markAsClosed(); + } + + function publicMarkAsTerminated() public { + markAsTerminated(); + } + + function isFradulentPreimageSet(bytes memory preimage) + public + view + returns (bool) + { + return fraudulentPreimages[preimage]; + } +} diff --git a/solidity/contracts/test/FullyBackedBondingStub.sol b/solidity/contracts/test/FullyBackedBondingStub.sol new file mode 100644 index 000000000..479632d71 --- /dev/null +++ b/solidity/contracts/test/FullyBackedBondingStub.sol @@ -0,0 +1,23 @@ +pragma solidity 0.5.17; + +import "../fully-backed/FullyBackedBonding.sol"; + +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/// @title Fully Backed Bonding Stub +/// @dev This contract is for testing purposes only. +contract FullyBackedBondingStub is FullyBackedBonding { + // using SafeMath for uint256; + // // address public delegatedAuthority; + // bool slashingShouldFail; + constructor(KeepRegistry _keepRegistry, uint256 _initializationPeriod) + public + FullyBackedBonding(_keepRegistry, _initializationPeriod) + {} + + function setBeneficiary(address _operator, address payable _beneficiary) + public + { + operators[_operator].beneficiary = _beneficiary; + } +} diff --git a/solidity/test/FullyBackedBondedECDSAKeepFactoryTest.js b/solidity/test/FullyBackedBondedECDSAKeepFactoryTest.js new file mode 100644 index 000000000..c71be0590 --- /dev/null +++ b/solidity/test/FullyBackedBondedECDSAKeepFactoryTest.js @@ -0,0 +1,1632 @@ +const {accounts, contract, web3} = require("@openzeppelin/test-environment") +const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot") + +const {expectRevert, time} = require("@openzeppelin/test-helpers") + +const {mineBlocks} = require("./helpers/mineBlocks") + +const truffleAssert = require("truffle-assertions") + +const StackLib = contract.fromArtifact("StackLib") +const KeepRegistry = contract.fromArtifact("KeepRegistry") +const FullyBackedBondedECDSAKeepFactoryStub = contract.fromArtifact( + "FullyBackedBondedECDSAKeepFactoryStub" +) +const FullyBackedBonding = contract.fromArtifact("FullyBackedBonding") +const FullyBackedSortitionPool = contract.fromArtifact( + "FullyBackedSortitionPool" +) +const FullyBackedSortitionPoolFactory = contract.fromArtifact( + "FullyBackedSortitionPoolFactory" +) +const RandomBeaconStub = contract.fromArtifact("RandomBeaconStub") +const FullyBackedBondedECDSAKeep = contract.fromArtifact( + "FullyBackedBondedECDSAKeep" +) + +const BN = web3.utils.BN + +const chai = require("chai") +chai.use(require("bn-chai")(BN)) +const expect = chai.expect +const assert = chai.assert + +describe("FullyBackedBondedECDSAKeepFactory", function () { + let registry + let keepFactory + let sortitionPoolFactory + let bonding + let randomBeacon + let signerPool + let minimumDelegationDeposit + + const application = accounts[1] + const members = [accounts[2], accounts[3], accounts[4]] + const authorizers = [members[0], members[1], members[2]] + const notMember = accounts[5] + + const keepOwner = accounts[6] + const beneficiary = accounts[7] + + const groupSize = new BN(members.length) + const threshold = new BN(groupSize - 1) + + const singleBond = web3.utils.toWei(new BN(20)) + const bond = singleBond.mul(groupSize) + + const stakeLockDuration = 0 // parameter is ignored by FullyBackedBondedECDSAKeepFactory implementation + const delegationInitPeriod = time.duration.hours(12) + + before(async () => { + await FullyBackedSortitionPoolFactory.detectNetwork() + await FullyBackedSortitionPoolFactory.link( + "StackLib", + (await StackLib.new()).address + ) + }) + + beforeEach(async () => { + await createSnapshot() + }) + + afterEach(async () => { + await restoreSnapshot() + }) + + describe("registerMemberCandidate", async () => { + let minimumBondableValue + let bondWeightDivisor + let pool + + before(async () => { + await initializeNewFactory() + await initializeMemberCandidates() + + pool = await FullyBackedSortitionPool.at(signerPool) + minimumBondableValue = await pool.getMinimumBondableValue() + + bondWeightDivisor = await keepFactory.bondWeightDivisor.call() + }) + + it("reverts for unknown application", async () => { + const unknownApplication = "0xCfd27747D1583feb1eCbD7c4e66C848Db0aA82FB" + await expectRevert( + keepFactory.registerMemberCandidate(unknownApplication, { + from: members[0], + }), + "No pool found for the application" + ) + }) + + it("inserts operator with the correct unbonded value available", async () => { + const unbondedValue = await bonding.unbondedValue(members[0]) + + const pool = await FullyBackedSortitionPool.at(signerPool) + + const expectedWeight = unbondedValue.div(bondWeightDivisor) + + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + + expect(await pool.getPoolWeight(members[0])).to.eq.BN( + expectedWeight, + "invalid staking weight" + ) + }) + + it("inserts operators to the same pool", async () => { + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + await keepFactory.registerMemberCandidate(application, { + from: members[1], + }) + + const pool = await FullyBackedSortitionPool.at(signerPool) + assert.isTrue( + await pool.isOperatorInPool(members[0]), + "operator 1 is not in the pool" + ) + assert.isTrue( + await pool.isOperatorInPool(members[1]), + "operator 2 is not in the pool" + ) + }) + + it("does not add an operator to the pool if it is already there", async () => { + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + + const pool = await FullyBackedSortitionPool.at(signerPool) + + assert.isTrue( + await pool.isOperatorInPool(members[0]), + "operator is not in the pool" + ) + + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + + assert.isTrue( + await pool.isOperatorInPool(members[0]), + "operator is not in the pool" + ) + }) + + it("does not add an operator to the pool if it does not have a minimum bond", async () => { + await setUnbondedValue(members[0], minimumBondableValue.sub(new BN(1))) + + await expectRevert( + keepFactory.registerMemberCandidate(application, {from: members[0]}), + "Operator not eligible" + ) + }) + + it("inserts operators to different pools", async () => { + const application1 = "0x0000000000000000000000000000000000000001" + const application2 = "0x0000000000000000000000000000000000000002" + + const signerPool1Address = await keepFactory.createSortitionPool.call( + application1 + ) + await keepFactory.createSortitionPool(application1) + const signerPool2Address = await keepFactory.createSortitionPool.call( + application2 + ) + await keepFactory.createSortitionPool(application2) + + await bonding.authorizeSortitionPoolContract( + members[0], + signerPool1Address, + {from: authorizers[0]} + ) + await bonding.authorizeSortitionPoolContract( + members[1], + signerPool2Address, + {from: authorizers[1]} + ) + + await keepFactory.registerMemberCandidate(application1, { + from: members[0], + }) + await keepFactory.registerMemberCandidate(application2, { + from: members[1], + }) + + const signerPool1 = await FullyBackedSortitionPool.at(signerPool1Address) + + assert.isTrue( + await signerPool1.isOperatorInPool(members[0]), + "operator 1 is not in the pool" + ) + assert.isFalse( + await signerPool1.isOperatorInPool(members[1]), + "operator 2 is in the pool" + ) + + const signerPool2 = await FullyBackedSortitionPool.at(signerPool2Address) + + assert.isFalse( + await signerPool2.isOperatorInPool(members[0]), + "operator 1 is in the pool" + ) + assert.isTrue( + await signerPool2.isOperatorInPool(members[1]), + "operator 2 is not in the pool" + ) + }) + + it("reverts if delegation initialization period has not passed", async () => { + await initializeNewFactory() + + signerPool = await keepFactory.createSortitionPool.call(application) + await keepFactory.createSortitionPool(application) + const pool = await FullyBackedSortitionPool.at(signerPool) + + await delegate( + members[0], + members[0], + authorizers[0], + minimumBondableValue + ) + + await time.increase(delegationInitPeriod.subn(1)) + + await expectRevert( + keepFactory.registerMemberCandidate(application, { + from: members[0], + }), + "Operator not eligible" + ) + + await time.increase(2) + + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + + assert.isTrue( + await pool.isOperatorInPool(members[0]), + "operator is not in the pool after initialization period" + ) + }) + }) + + describe("createSortitionPool", async () => { + before(async () => { + await initializeNewFactory() + }) + + it("creates new sortition pool and emits an event", async () => { + const sortitionPoolAddress = await keepFactory.createSortitionPool.call( + application + ) + + const res = await keepFactory.createSortitionPool(application) + truffleAssert.eventEmitted(res, "SortitionPoolCreated", { + application: application, + sortitionPool: sortitionPoolAddress, + }) + }) + + it("reverts when sortition pool already exists", async () => { + await keepFactory.createSortitionPool(application) + + await expectRevert( + keepFactory.createSortitionPool(application), + "Sortition pool already exists" + ) + }) + }) + + describe("getSortitionPool", async () => { + before(async () => { + await initializeNewFactory() + }) + + it("returns address of sortition pool", async () => { + const sortitionPoolAddress = await keepFactory.createSortitionPool.call( + application + ) + await keepFactory.createSortitionPool(application) + + const result = await keepFactory.getSortitionPool(application) + assert.equal( + result, + sortitionPoolAddress, + "incorrect sortition pool address" + ) + }) + + it("reverts if sortition pool does not exist", async () => { + await expectRevert( + keepFactory.getSortitionPool(application), + "No pool found for the application" + ) + }) + }) + + describe("isOperatorRegistered", async () => { + before(async () => { + await initializeNewFactory() + await initializeMemberCandidates() + }) + + it("returns true if the operator is registered for the application", async () => { + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + + assert.isTrue( + await keepFactory.isOperatorRegistered(members[0], application) + ) + }) + + it("returns false if the operator is registered for another application", async () => { + const application2 = "0x0000000000000000000000000000000000000002" + + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + + assert.isFalse( + await keepFactory.isOperatorRegistered(members[0], application2) + ) + }) + + it("returns false if the operator is not registered for any application", async () => { + assert.isFalse( + await keepFactory.isOperatorRegistered(members[0], application) + ) + }) + }) + + describe("isOperatorUpToDate", async () => { + const precision = new BN("1000000000000000000") // 1 ETH + + let minimumBondableValue + + before(async () => { + await initializeNewFactory() + await initializeMemberCandidates() + + const pool = await FullyBackedSortitionPool.at(signerPool) + minimumBondableValue = await pool.getMinimumBondableValue() + }) + + // TODO: Add a case to check if operator is initialized + // github.com/keep-network/sortition-pools/blob/413abd66536032ee757f190a29fda2705c7b70cf/contracts/FullyBackedSortitionPool.sol#L155 + + it("returns true if the operator is up to date for the application", async () => { + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + + assert.isTrue( + await keepFactory.isOperatorUpToDate(members[0], application) + ) + }) + + it("returns false if the operator bonding value dropped", async () => { + const unbondedValue = minimumBondableValue.muln(10) // (20 * 10^18) * 10 + await setUnbondedValue(members[0], unbondedValue) + + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + + await setUnbondedValue(members[0], unbondedValue.subn(1)) // 200 - 1 = 199 + + // Precision (bond weight divisor) is 10^18 + // (20 * 10^18 * 10) / 10^18 = 200 + // ((20 * 10^18 * 10) - 1) / 10^18 =~ 199.99 + // Ethereum uint256 division performs implicit floor: + // The weight went down from 200 to 199 + assert.isFalse( + await keepFactory.isOperatorUpToDate(members[0], application) + ) + }) + + it("returns false if the operator bonding value increased", async () => { + const unbondedValue = minimumBondableValue.muln(10) // (20 * 10^18) * 10 + await setUnbondedValue(members[0], unbondedValue) + + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + + await setUnbondedValue(members[0], unbondedValue.add(precision)) // ((20 * 10^18) * 10) + 10^18 + + // Precision (bond weight divisor) is 10^18 + // (20 * 10^18 * 10) / 10^18 = 200 + // ((20 * 10^18 * 10) + 10^18) / 10^18 = 201 + // The weight went up from 200 to 201 + assert.isFalse( + await keepFactory.isOperatorUpToDate(members[0], application) + ) + }) + + it("returns true if the operator bonding value increase is below weight precision", async () => { + const unbondedValue = minimumBondableValue.muln(10) // (20 * 10^18) * 10 + await setUnbondedValue(members[0], unbondedValue) + + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + + await setUnbondedValue(members[0], unbondedValue.add(precision).subn(1)) // ((20 * 10^18) * 10) + 10^18 - 1 + + // Precision (pool weight divisor) is 10^18 + // (20 * 10^18 * 10) / 10^18 = 200 + // ((20 * 10^18 * 10) + (10^18 - 1)) / 10^18 =~ 200.99 + // Ethereum uint256 division performs implicit floor: + // The weight dit not change: 200 == floor(200.99) + assert.isTrue( + await keepFactory.isOperatorUpToDate(members[0], application) + ) + }) + + it("returns false if the operator stake dropped below minimum", async () => { + await keepFactory.registerMemberCandidate(application, { + from: members[0], + }) + + await setUnbondedValue(members[0], minimumBondableValue.subn(1)) + + assert.isFalse( + await keepFactory.isOperatorUpToDate(members[0], application) + ) + }) + + it("reverts if the operator is not registered for the application", async () => { + await initializeNewFactory() + await initializeMemberCandidates() + + await expectRevert( + keepFactory.isOperatorUpToDate(members[0], application), + "Operator not registered for the application" + ) + }) + }) + + describe("updateOperatorStatus", async () => { + before(async () => { + await initializeNewFactory() + await initializeMemberCandidates() + await registerMemberCandidates() + }) + + it("revers if operator is up to date", async () => { + await expectRevert( + keepFactory.updateOperatorStatus(members[0], application), + "Operator already up to date" + ) + }) + + it("removes operator if bonding value has changed below minimum", async () => { + bonding.withdraw(new BN(1), members[0], {from: members[0]}) + assert.isFalse( + await keepFactory.isOperatorUpToDate(members[0], application), + "unexpected status of the operator after bonding value change" + ) + + await keepFactory.updateOperatorStatus(members[0], application) + + await expectRevert( + keepFactory.isOperatorUpToDate(members[0], application), + "Operator not registered for the application" + ) + }) + + it("updates operator if bonding value has changed above minimum", async () => { + bonding.deposit(members[0], {value: new BN(1)}) + assert.isTrue( + await keepFactory.isOperatorUpToDate(members[0], application), + "unexpected status of the operator after bonding value change" + ) + + await expectRevert( + keepFactory.updateOperatorStatus(members[0], application), + "Operator already up to date" + ) + }) + + it("reverts if the operator is not registered for the application", async () => { + await initializeNewFactory() + await initializeMemberCandidates() + + await expectRevert( + keepFactory.updateOperatorStatus(members[0], application), + "Operator not registered for the application" + ) + }) + }) + + describe("openKeep", async () => { + let feeEstimate + let minimumBondableValue + + before(async () => { + await initializeNewFactory() + await initializeMemberCandidates() + await registerMemberCandidates() + + feeEstimate = await keepFactory.openKeepFeeEstimate() + + const pool = await FullyBackedSortitionPool.at(signerPool) + minimumBondableValue = await pool.getMinimumBondableValue() + }) + + it("reverts if no member candidates are registered", async () => { + await expectRevert( + keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + value: feeEstimate, + } + ), + "No pool found for the application" + ) + }) + + it("reverts if bond equals zero", async () => { + const bond = 0 + + await expectRevert( + keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ), + "Bond per member must be greater than zero" + ) + }) + + it("reverts if value is less than the required fee estimate", async () => { + const insufficientFee = feeEstimate.subn(1) + + await expectRevert( + keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + fee: insufficientFee, + } + ), + "Insufficient payment for opening a new keep" + ) + }) + + it("opens keep with multiple members and emits event", async () => { + const blockNumber = await web3.eth.getBlockNumber() + + const keepAddress = await keepFactory.openKeep.call( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ) + + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ) + + const eventList = await keepFactory.getPastEvents( + "FullyBackedBondedECDSAKeepCreated", + { + fromBlock: blockNumber, + toBlock: "latest", + } + ) + + assert.equal(eventList.length, 1, "incorrect number of emitted events") + + const ev = eventList[0].returnValues + + assert.equal(ev.keepAddress, keepAddress, "incorrect keep address") + assert.equal(ev.owner, keepOwner, "incorrect keep owner") + assert.equal(ev.application, application, "incorrect application") + + assert.sameMembers( + ev.members, + [members[0], members[1], members[2]], + "incorrect keep members" + ) + + expect(ev.honestThreshold).to.eq.BN(threshold, "incorrect threshold") + }) + + it("opens bonds for keep", async () => { + const blockNumber = await web3.eth.getBlockNumber() + + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ) + + const eventList = await keepFactory.getPastEvents( + "FullyBackedBondedECDSAKeepCreated", + { + fromBlock: blockNumber, + toBlock: "latest", + } + ) + + const keepAddress = eventList[0].returnValues.keepAddress + + expect( + await bonding.bondAmount(members[0], keepAddress, keepAddress) + ).to.eq.BN(singleBond, "invalid bond value for members[0]") + + expect( + await bonding.bondAmount(members[1], keepAddress, keepAddress) + ).to.eq.BN(singleBond, "invalid bond value for members[1]") + + expect( + await bonding.bondAmount(members[2], keepAddress, keepAddress) + ).to.eq.BN(singleBond, "invalid bond value for members[2]") + }) + + it("rounds up members bonds", async () => { + const requestedBond = bond.add(new BN(1)) + const unbondedAmount = singleBond.add(new BN(1)) + const expectedMemberBond = singleBond.add(new BN(1)) + + await depositMemberCandidates(unbondedAmount) + + const blockNumber = await web3.eth.getBlockNumber() + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + requestedBond, + stakeLockDuration, + {from: application, value: feeEstimate} + ) + + const eventList = await keepFactory.getPastEvents( + "FullyBackedBondedECDSAKeepCreated", + { + fromBlock: blockNumber, + toBlock: "latest", + } + ) + + const keepAddress = eventList[0].returnValues.keepAddress + + expect( + await bonding.bondAmount(members[0], keepAddress, keepAddress), + "invalid bond value for members[0]" + ).to.eq.BN(expectedMemberBond) + + expect( + await bonding.bondAmount(members[1], keepAddress, keepAddress), + "invalid bond value for members[1]" + ).to.eq.BN(expectedMemberBond) + + expect( + await bonding.bondAmount(members[2], keepAddress, keepAddress), + "invalid bond value for members[2]" + ).to.eq.BN(expectedMemberBond) + }) + + it("rounds up members bonds when calculated bond per member equals zero", async () => { + const requestedBond = new BN(groupSize).sub(new BN(1)) + const expectedMemberBond = new BN(1) + + await depositMemberCandidates(minimumBondableValue) + + const blockNumber = await web3.eth.getBlockNumber() + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + requestedBond, + stakeLockDuration, + {from: application, value: feeEstimate} + ) + + const eventList = await keepFactory.getPastEvents( + "FullyBackedBondedECDSAKeepCreated", + { + fromBlock: blockNumber, + toBlock: "latest", + } + ) + + const keepAddress = eventList[0].returnValues.keepAddress + + expect( + await bonding.bondAmount(members[0], keepAddress, keepAddress), + "invalid bond value for members[0]" + ).to.eq.BN(expectedMemberBond) + + expect( + await bonding.bondAmount(members[1], keepAddress, keepAddress), + "invalid bond value for members[1]" + ).to.eq.BN(expectedMemberBond) + + expect( + await bonding.bondAmount(members[2], keepAddress, keepAddress), + "invalid bond value for members[2]" + ).to.eq.BN(expectedMemberBond) + }) + + it("reverts if not enough member candidates are registered", async () => { + const requestedGroupSize = groupSize.addn(1) + + await expectRevert( + keepFactory.openKeep( + requestedGroupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ), + "Not enough operators in pool" + ) + }) + + it("reverts if one member has insufficient unbonded value", async () => { + const minimumBond = await keepFactory.minimumBond.call() + const availableUnbonded = await bonding.availableUnbondedValue( + members[2], + keepFactory.address, + signerPool + ) + const withdrawValue = availableUnbonded.sub(minimumBond).add(new BN(1)) + await bonding.withdraw(withdrawValue, members[2], { + from: members[2], + }) + + await expectRevert( + keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ), + "Not enough operators in pool" + ) + }) + + it("opens keep with multiple members and emits an event", async () => { + const blockNumber = await web3.eth.getBlockNumber() + + const keep = await openKeep() + + const eventList = await keepFactory.getPastEvents( + "FullyBackedBondedECDSAKeepCreated", + { + fromBlock: blockNumber, + toBlock: "latest", + } + ) + + assert.isTrue( + web3.utils.isAddress(keep.address), + `keep address ${keep.address} is not a valid address` + ) + + assert.equal(eventList.length, 1, "incorrect number of emitted events") + + assert.equal( + eventList[0].returnValues.keepAddress, + keep.address, + "incorrect keep address in emitted event" + ) + + assert.sameMembers( + eventList[0].returnValues.members, + [members[0], members[1], members[2]], + "incorrect keep member in emitted event" + ) + + assert.equal( + eventList[0].returnValues.owner, + keepOwner, + "incorrect keep owner in emitted event" + ) + }) + + it("requests new random group selection seed from random beacon", async () => { + const expectedNewEntry = new BN(789) + + await randomBeacon.setEntry(expectedNewEntry) + + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ) + + assert.equal( + await randomBeacon.requestCount.call(), + 1, + "incorrect number of beacon calls" + ) + + expect(await keepFactory.getGroupSelectionSeed()).to.eq.BN( + expectedNewEntry, + "incorrect new group selection seed" + ) + }) + + it("calculates new group selection seed", async () => { + // Set entry to `0` so the beacon stub won't execute the callback. + await randomBeacon.setEntry(0) + + const groupSelectionSeed = new BN(12) + await keepFactory.initialGroupSelectionSeed(groupSelectionSeed) + + const expectedNewGroupSelectionSeed = web3.utils.toBN( + web3.utils.soliditySha3(groupSelectionSeed, keepFactory.address) + ) + + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ) + + expect(await keepFactory.getGroupSelectionSeed()).to.eq.BN( + expectedNewGroupSelectionSeed, + "incorrect new group selection seed" + ) + }) + + it("ignores beacon request relay entry failure", async () => { + await randomBeacon.setShouldFail(true) + + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ) + + // TODO: Add verification of what we will do in case of the failure. + }) + + it("forwards payment to random beacon", async () => { + const value = new BN(150) + + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: value, + } + ) + + expect(await web3.eth.getBalance(randomBeacon.address)).to.eq.BN( + value, + "incorrect random beacon balance" + ) + }) + + it("reverts when honest threshold is greater than the group size", async () => { + const honestThreshold = 4 + const groupSize = 3 + + await expectRevert( + keepFactory.openKeep( + groupSize, + honestThreshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ), + "Honest threshold must be less or equal the group size" + ) + }) + + it("reverts when honest threshold is 0", async () => { + const honestThreshold = 0 + + await expectRevert( + keepFactory.openKeep( + groupSize, + honestThreshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ), + "Honest threshold must be greater than 0" + ) + }) + + it("works when honest threshold is equal to the group size", async () => { + const honestThreshold = 3 + const groupSize = honestThreshold + + const blockNumber = await web3.eth.getBlockNumber() + + await keepFactory.openKeep( + groupSize, + honestThreshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ) + + const eventList = await keepFactory.getPastEvents( + "FullyBackedBondedECDSAKeepCreated", + { + fromBlock: blockNumber, + toBlock: "latest", + } + ) + + assert.equal(eventList.length, 1, "incorrect number of emitted events") + }) + + it("records the keep address and opening time", async () => { + const preKeepCount = await keepFactory.getKeepCount() + + const keepAddress = await keepFactory.openKeep.call( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + {from: application, value: feeEstimate} + ) + + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ) + const recordedKeepAddress = await keepFactory.getKeepAtIndex(preKeepCount) + const keep = await FullyBackedBondedECDSAKeep.at(keepAddress) + const keepOpenedTime = await keep.getOpenedTimestamp() + const factoryKeepOpenedTime = await keepFactory.getKeepOpenedTimestamp( + keepAddress + ) + + assert.equal( + recordedKeepAddress, + keepAddress, + "address recorded in factory differs from returned keep address" + ) + + expect(factoryKeepOpenedTime).to.eq.BN( + keepOpenedTime, + "opened time in factory differs from opened time in keep" + ) + }) + + it("produces active keeps", async () => { + const keepAddress = await keepFactory.openKeep.call( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + {from: application, value: feeEstimate} + ) + + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ) + + const keep = await FullyBackedBondedECDSAKeep.at(keepAddress) + + assert.isTrue(await keep.isActive(), "keep should be active") + }) + + it("allows to use a group of 16 signers", async () => { + const groupSize = 16 + + // create and authorize enough operators to perform the test; + // we need more than the default 10 accounts + await createDepositAndRegisterMembers(groupSize, singleBond) + + const blockNumber = await web3.eth.getBlockNumber() + + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ) + + const eventList = await keepFactory.getPastEvents( + "FullyBackedBondedECDSAKeepCreated", + { + fromBlock: blockNumber, + toBlock: "latest", + } + ) + + assert.equal(eventList.length, 1, "incorrect number of emitted events") + assert.equal( + eventList[0].returnValues.members.length, + groupSize, + "incorrect number of members" + ) + }) + + it("reverts when trying to use a group of 17 signers", async () => { + const groupSize = 17 + + await expectRevert( + keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ), + "Maximum signing group size is 16" + ) + }) + + it("reverts when trying to use a group of 0 signers", async () => { + const groupSize = 0 + + await expectRevert( + keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ), + "Minimum signing group size is 1" + ) + }) + + async function createDepositAndRegisterMembers( + memberCount, + unbondedAmount + ) { + const operators = [] + + for (let i = 0; i < memberCount; i++) { + const operator = await web3.eth.personal.newAccount("pass") + const authorizer = operator + await web3.eth.personal.unlockAccount(operator, "pass", 5000) // 5 sec unlock + + web3.eth.sendTransaction({ + from: accounts[0], + to: operator, + value: web3.utils.toWei("21", "ether"), + }) + + await delegate(operator, beneficiary, authorizer, unbondedAmount) + + operators[i] = operator + } + + await time.increase(delegationInitPeriod.addn(1)) + + for (let i = 0; i < operators.length; i++) { + await keepFactory.registerMemberCandidate(application, { + from: operators[i], + }) + } + + const pool = await FullyBackedSortitionPool.at(signerPool) + await mineBlocks((await pool.operatorInitBlocks()).add(new BN(1))) + } + }) + + describe("__beaconCallback", async () => { + const newRelayEntry = new BN(2345675) + + before(async () => { + registry = await KeepRegistry.new() + sortitionPoolFactory = await FullyBackedSortitionPoolFactory.new() + bonding = await FullyBackedBonding.new( + registry.address, + delegationInitPeriod + ) + randomBeacon = accounts[1] + const keepMasterContract = await FullyBackedBondedECDSAKeep.new() + keepFactory = await FullyBackedBondedECDSAKeepFactoryStub.new( + keepMasterContract.address, + sortitionPoolFactory.address, + bonding.address, + randomBeacon + ) + }) + + it("sets group selection seed", async () => { + await keepFactory.__beaconCallback(newRelayEntry, { + from: randomBeacon, + }) + + expect(await keepFactory.getGroupSelectionSeed()).to.eq.BN( + newRelayEntry, + "incorrect new group selection seed" + ) + }) + + it("reverts if called not by the random beacon", async () => { + await expectRevert( + keepFactory.__beaconCallback(newRelayEntry, { + from: accounts[2], + }), + "Caller is not the random beacon" + ) + }) + }) + + describe("newGroupSelectionSeedFee", async () => { + let newEntryFee + + before(async () => { + await initializeNewFactory() + + const callbackGas = await keepFactory.callbackGas() + newEntryFee = await randomBeacon.entryFeeEstimate(callbackGas) + }) + + it("evaluates reseed fee for empty pool", async () => { + const reseedFee = await keepFactory.newGroupSelectionSeedFee() + expect(reseedFee).to.eq.BN( + newEntryFee, + "reseed fee should equal new entry fee" + ) + }) + + it("evaluates reseed fee for non-empty pool", async () => { + const poolValue = new BN(15) + web3.eth.sendTransaction({ + from: accounts[0], + to: keepFactory.address, + value: poolValue, + }) + + const reseedFee = await keepFactory.newGroupSelectionSeedFee() + expect(reseedFee).to.eq.BN( + newEntryFee.sub(poolValue), + "reseed fee should equal new entry fee minus pool value" + ) + }) + + it("should reseed for free if has enough funds in the pool", async () => { + web3.eth.sendTransaction({ + from: accounts[0], + to: keepFactory.address, + value: newEntryFee, + }) + + const reseedFee = await keepFactory.newGroupSelectionSeedFee() + expect(reseedFee).to.eq.BN(0, "reseed fee should be zero") + }) + + it("should reseed for free if has more than needed funds in the pool", async () => { + web3.eth.sendTransaction({ + from: accounts[0], + to: keepFactory.address, + value: newEntryFee.addn(1), + }) + + const reseedFee = await keepFactory.newGroupSelectionSeedFee() + expect(reseedFee).to.eq.BN(0, "reseed fee should be zero") + }) + }) + + describe("requestNewGroupSelectionSeed", async () => { + let newEntryFee + + before(async () => { + await initializeNewFactory() + const callbackGas = await keepFactory.callbackGas() + newEntryFee = await randomBeacon.entryFeeEstimate(callbackGas) + }) + + it("requests new relay entry from the beacon and reseeds factory", async () => { + const expectedNewEntry = new BN(1337) + await randomBeacon.setEntry(expectedNewEntry) + + const reseedFee = await keepFactory.newGroupSelectionSeedFee() + await keepFactory.requestNewGroupSelectionSeed({value: reseedFee}) + + assert.equal( + await randomBeacon.requestCount.call(), + 1, + "incorrect number of beacon calls" + ) + + expect(await keepFactory.getGroupSelectionSeed()).to.eq.BN( + expectedNewEntry, + "incorrect new group selection seed" + ) + }) + + it("allows to reseed for free if the pool is full", async () => { + const expectedNewEntry = new BN(997) + await randomBeacon.setEntry(expectedNewEntry) + + const poolValue = newEntryFee + web3.eth.sendTransaction({ + from: accounts[0], + to: keepFactory.address, + value: poolValue, + }) + + await keepFactory.requestNewGroupSelectionSeed({value: 0}) + + assert.equal( + await randomBeacon.requestCount.call(), + 1, + "incorrect number of beacon calls" + ) + + expect(await keepFactory.getGroupSelectionSeed()).to.eq.BN( + expectedNewEntry, + "incorrect new group selection seed" + ) + }) + + it("updates pool after reseeding", async () => { + await randomBeacon.setEntry(new BN(1337)) + + const poolValue = newEntryFee.muln(15) + web3.eth.sendTransaction({ + from: accounts[0], + to: keepFactory.address, + value: poolValue, + }) + + await keepFactory.requestNewGroupSelectionSeed({value: 0}) + + const expectedPoolValue = poolValue.sub(newEntryFee) + expect(await keepFactory.reseedPool()).to.eq.BN( + expectedPoolValue, + "unexpected reseed pool value" + ) + }) + + it("updates pool after reseeding with value", async () => { + await randomBeacon.setEntry(new BN(1337)) + + const poolValue = newEntryFee.muln(15) + web3.eth.sendTransaction({ + from: accounts[0], + to: keepFactory.address, + value: poolValue, + }) + + const valueSent = new BN(10) + await keepFactory.requestNewGroupSelectionSeed({value: 10}) + + const expectedPoolValue = poolValue.sub(newEntryFee).add(valueSent) + expect(await keepFactory.reseedPool()).to.eq.BN( + expectedPoolValue, + "unexpected reseed pool value" + ) + }) + + it("reverts if the provided payment is not sufficient", async () => { + const poolValue = newEntryFee.subn(2) + web3.eth.sendTransaction({ + from: accounts[0], + to: keepFactory.address, + value: poolValue, + }) + + await expectRevert( + keepFactory.requestNewGroupSelectionSeed({value: 1}), + "Not enough funds to trigger reseed" + ) + }) + + it("reverts if beacon is busy", async () => { + await randomBeacon.setShouldFail(true) + + const reseedFee = await keepFactory.newGroupSelectionSeedFee() + await expectRevert( + keepFactory.requestNewGroupSelectionSeed({value: reseedFee}), + "request relay entry failed" + ) + }) + }) + + describe("getKeepAtIndex", async () => { + before(async () => { + await initializeNewFactory() + const minimumBond = await keepFactory.minimumBond.call() + const memberBond = minimumBond.muln(2) // want to be able to open 2 keeps + await initializeMemberCandidates(memberBond) + await registerMemberCandidates() + }) + + it("reverts when there are no keeps", async () => { + await expectRevert(keepFactory.getKeepAtIndex(0), "Out of bounds") + }) + + it("reverts for out of bond index", async () => { + await openKeep() + + await expectRevert(keepFactory.getKeepAtIndex(1), "Out of bounds") + }) + + it("returns keep at index", async () => { + const keep0 = await openKeep() + const keep1 = await openKeep() + + const atIndex0 = await keepFactory.getKeepAtIndex(0) + const atIndex1 = await keepFactory.getKeepAtIndex(1) + + assert.equal( + keep0.address, + atIndex0, + "incorrect keep address returned for index 0" + ) + assert.equal( + keep1.address, + atIndex1, + "incorrect keep address returned for index 1" + ) + }) + }) + + describe("isOperatorAuthorized", async () => { + before(async () => { + await initializeNewFactory() + await initializeMemberCandidates() + }) + + it("returns true if operator is authorized for the factory", async () => { + assert.isTrue( + await keepFactory.isOperatorAuthorized(members[0]), + "the operator is authorized for the factory" + ) + }) + + it("returns false if operator is not authorized for the factory", async () => { + assert.isFalse( + await keepFactory.isOperatorAuthorized(notMember), + "the operator is not authorized for the factory" + ) + }) + }) + + describe("getSortitionPoolWeight", async () => { + before(async () => { + await initializeNewFactory() + }) + + it("returns pool weight if pool exists for application", async () => { + await initializeMemberCandidates() + await registerMemberCandidates() + + const poolAddress = await keepFactory.getSortitionPool(application) + const pool = await FullyBackedSortitionPool.at(poolAddress) + + const poolWeight = await keepFactory.getSortitionPoolWeight(application) + + const expectedPoolWeight = (await pool.getMinimumBondableValue()) + .div(await keepFactory.bondWeightDivisor.call()) + .muln(3) + expect(poolWeight).to.eq.BN( + expectedPoolWeight, + "incorrect sortition pool weight" + ) + }) + + it("reverts when pool doesn't exist for application", async () => { + await expectRevert( + keepFactory.getSortitionPoolWeight(application), + "No pool found for the application" + ) + }) + }) + + describe("setMinimumBondableValue", async () => { + before(async () => { + await initializeNewFactory() + await initializeMemberCandidates() + }) + + it("reverts for unknown application", async () => { + await expectRevert( + keepFactory.setMinimumBondableValue(10, 3, 3), + "No pool found for the application" + ) + }) + + it("sets the minimum bond value for the application", async () => { + await keepFactory.setMinimumBondableValue(12, 3, 3, {from: application}) + const poolAddress = await keepFactory.getSortitionPool(application) + const pool = await FullyBackedSortitionPool.at(poolAddress) + expect(await pool.getMinimumBondableValue()).to.eq.BN(4) + }) + + it("rounds up member bonds", async () => { + await keepFactory.setMinimumBondableValue(10, 3, 3, {from: application}) + const poolAddress = await keepFactory.getSortitionPool(application) + const pool = await FullyBackedSortitionPool.at(poolAddress) + expect(await pool.getMinimumBondableValue()).to.eq.BN(4) + }) + + it("rounds up members bonds when calculated bond per member equals zero", async () => { + await keepFactory.setMinimumBondableValue(2, 3, 3, {from: application}) + const poolAddress = await keepFactory.getSortitionPool(application) + const pool = await FullyBackedSortitionPool.at(poolAddress) + expect(await pool.getMinimumBondableValue()).to.eq.BN(1) + }) + }) + + async function initializeNewFactory() { + registry = await KeepRegistry.new() + sortitionPoolFactory = await FullyBackedSortitionPoolFactory.new() + bonding = await FullyBackedBonding.new( + registry.address, + delegationInitPeriod + ) + randomBeacon = await RandomBeaconStub.new() + const keepMasterContract = await FullyBackedBondedECDSAKeep.new() + keepFactory = await FullyBackedBondedECDSAKeepFactoryStub.new( + keepMasterContract.address, + sortitionPoolFactory.address, + bonding.address, + randomBeacon.address + ) + + minimumDelegationDeposit = await bonding.MINIMUM_DELEGATION_DEPOSIT.call() + + await registry.approveOperatorContract(keepFactory.address) + } + + async function initializeMemberCandidates(unbondedValue) { + const minimumBond = await keepFactory.minimumBond.call() + + signerPool = await keepFactory.createSortitionPool.call(application) + await keepFactory.createSortitionPool(application) + + for (let i = 0; i < members.length; i++) { + await delegate( + members[i], + members[i], + authorizers[i], + unbondedValue || minimumBond + ) + } + + await time.increase(delegationInitPeriod.addn(1)) + } + + async function delegate(operator, beneficiary, authorizer, unbondedValue) { + await bonding.delegate(operator, beneficiary, authorizer, { + value: unbondedValue || minimumDelegationDeposit, + }) + + await bonding.authorizeOperatorContract(operator, keepFactory.address, { + from: authorizer, + }) + await bonding.authorizeSortitionPoolContract(operator, signerPool, { + from: authorizer, + }) + } + + async function setUnbondedValue(operator, unbondedValue) { + const initialUnbondedValue = await bonding.unbondedValue(operator) + + if (initialUnbondedValue.eq(unbondedValue)) { + return + } else if (initialUnbondedValue.gt(unbondedValue)) { + await bonding.withdraw(initialUnbondedValue.sub(unbondedValue), operator) + } else { + await bonding.deposit(operator, { + value: unbondedValue.sub(initialUnbondedValue), + }) + } + } + + async function depositMemberCandidates(unbondedValue) { + for (let i = 0; i < members.length; i++) { + await setUnbondedValue(members[i], unbondedValue) + } + } + + async function registerMemberCandidates() { + for (let i = 0; i < members.length; i++) { + await keepFactory.registerMemberCandidate(application, { + from: members[i], + }) + } + + const pool = await FullyBackedSortitionPool.at(signerPool) + const poolInitBlocks = await pool.operatorInitBlocks() + await mineBlocks(poolInitBlocks.add(new BN(1))) + } + + async function openKeep() { + const feeEstimate = await keepFactory.openKeepFeeEstimate() + + const keepAddress = await keepFactory.openKeep.call( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + {from: application, value: feeEstimate} + ) + + await keepFactory.openKeep( + groupSize, + threshold, + keepOwner, + bond, + stakeLockDuration, + { + from: application, + value: feeEstimate, + } + ) + + return await FullyBackedBondedECDSAKeep.at(keepAddress) + } +}) diff --git a/solidity/test/FullyBackedBondedECDSAKeepTest.js b/solidity/test/FullyBackedBondedECDSAKeepTest.js new file mode 100644 index 000000000..09b28d8db --- /dev/null +++ b/solidity/test/FullyBackedBondedECDSAKeepTest.js @@ -0,0 +1,1719 @@ +const {accounts, contract, web3} = require("@openzeppelin/test-environment") +const { + getETHBalancesFromList, + getERC20BalancesFromList, + addToBalances, +} = require("./helpers/listBalanceUtils") + +const {mineBlocks} = require("./helpers/mineBlocks") +const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot") + +const {expectRevert, time} = require("@openzeppelin/test-helpers") + +const KeepRegistry = contract.fromArtifact("KeepRegistry") +const FullyBackedBondedECDSAKeep = contract.fromArtifact( + "FullyBackedBondedECDSAKeep" +) +const FullyBackedBondedECDSAKeepStub = contract.fromArtifact( + "FullyBackedBondedECDSAKeepStub" +) +const TestToken = contract.fromArtifact("TestToken") +const FullyBackedBondingStub = contract.fromArtifact("FullyBackedBondingStub") +const TestEtherReceiver = contract.fromArtifact("TestEtherReceiver") +const FullyBackedBondedECDSAKeepCloneFactoryStub = contract.fromArtifact( + "FullyBackedBondedECDSAKeepCloneFactoryStub" +) + +const truffleAssert = require("truffle-assertions") + +const BN = web3.utils.BN + +const chai = require("chai") +chai.use(require("bn-chai")(BN)) +const expect = chai.expect +const assert = chai.assert + +describe("FullyBackedBondedECDSAKeep", function () { + const bondCreator = accounts[0] + const owner = accounts[1] + const nonOwner = accounts[2] + const members = [accounts[2], accounts[3], accounts[4]] + const beneficiaries = [accounts[7], accounts[8], accounts[9]] + const authorizers = [accounts[2], accounts[3], accounts[4]] + const signingPool = accounts[5] + const honestThreshold = 1 + + const delegationInitPeriod = time.duration.hours(12) + + let registry + let bonding + let keepStubMaster + let keep + let factoryStub + + async function newKeep( + owner, + members, + honestThreshold, + bonding, + keepFactory + ) { + const startBlock = await web3.eth.getBlockNumber() + + await factoryStub.newKeep( + owner, + members, + honestThreshold, + bonding, + keepFactory + ) + + const events = await factoryStub.getPastEvents( + "FullyBackedBondedECDSAKeepCreated", + { + fromBlock: startBlock, + toBlock: "latest", + } + ) + assert.lengthOf( + events, + 1, + "unexpected length of FullyBackedBondedECDSAKeepCreated events" + ) + const keepAddress = events[0].returnValues.keepAddress + + return await FullyBackedBondedECDSAKeepStub.at(keepAddress) + } + + before(async () => { + registry = await KeepRegistry.new() + bonding = await FullyBackedBondingStub.new( + registry.address, + delegationInitPeriod + ) + keepStubMaster = await FullyBackedBondedECDSAKeepStub.new() + factoryStub = await FullyBackedBondedECDSAKeepCloneFactoryStub.new( + keepStubMaster.address + ) + + await registry.approveOperatorContract(bondCreator) + await registry.approveOperatorContract(factoryStub.address) + + await delegateOperators() + }) + + beforeEach(async () => { + await createSnapshot() + + keep = await newKeep( + owner, + members, + honestThreshold, + bonding.address, + factoryStub.address + ) + }) + + afterEach(async () => { + await restoreSnapshot() + }) + + describe("initialize", async () => { + it("succeeds", async () => { + keep = await FullyBackedBondedECDSAKeepStub.new() + await keep.initialize( + owner, + members, + honestThreshold, + bonding.address, + factoryStub.address + ) + }) + + it("claims bonding delegated authority", async () => { + keep = await FullyBackedBondedECDSAKeepStub.new() + await keep.initialize( + owner, + members, + honestThreshold, + bonding.address, + factoryStub.address + ) + + assert.equal( + await bonding.getAuthoritySource(keep.address), + factoryStub.address, + "incorrect bonding delegated authority" + ) + }) + + it("reverts if called for the second time", async () => { + // first call was a part of beforeEach + await expectRevert( + keep.initialize( + owner, + members, + honestThreshold, + bonding.address, + factoryStub.address + ), + "Contract already initialized" + ) + }) + }) + + describe("sign", async () => { + const publicKey = + "0x657282135ed640b0f5a280874c7e7ade110b5c3db362e0552e6b7fff2cc8459328850039b734db7629c31567d7fc5677536b7fc504e967dc11f3f2289d3d4051" + const digest = + "0xca071ca92644f1f2c4ae1bf71b6032e5eff4f78f3aa632b27cbc5f84104a32da" + + it("reverts if public key was not set", async () => { + await expectRevert( + keep.sign(digest, {from: owner}), + "Public key was not set yet" + ) + }) + + it("emits event", async () => { + await submitMembersPublicKeys(publicKey) + + const res = await keep.sign(digest, {from: owner}) + truffleAssert.eventEmitted(res, "SignatureRequested", (ev) => { + return ev.digest == digest + }) + }) + + it("sets block number for digest", async () => { + await submitMembersPublicKeys(publicKey) + + const signTx = await keep.sign(digest, {from: owner}) + + const blockNumber = await keep.digests.call(digest) + + expect(blockNumber, "incorrect block number").to.eq.BN( + signTx.receipt.blockNumber + ) + }) + + it("cannot be requested if keep is closed", async () => { + await createMembersBonds(keep) + + await keep.closeKeep({from: owner}) + + await expectRevert(keep.sign(digest, {from: owner}), "Keep is not active") + }) + + it("cannot be called by non-owner", async () => { + await expectRevert(keep.sign(digest), "Caller is not the keep owner") + }) + + it("cannot be called by non-owner member", async () => { + await expectRevert( + keep.sign(digest, {from: members[0]}), + "Caller is not the keep owner" + ) + }) + + it("cannot be requested if already in progress", async () => { + await submitMembersPublicKeys(publicKey) + + await keep.sign(digest, {from: owner}) + + await expectRevert(keep.sign("0x02", {from: owner}), "Signer is busy") + }) + }) + + describe("isAwaitingSignature", async () => { + const digest1 = + "0x54a6483b8aca55c9df2a35baf71d9965ddfd623468d81d51229bd5eb7d1e1c1b" + const publicKey = + "0x657282135ed640b0f5a280874c7e7ade110b5c3db362e0552e6b7fff2cc8459328850039b734db7629c31567d7fc5677536b7fc504e967dc11f3f2289d3d4051" + const signatureR = + "0x9b32c3623b6a16e87b4d3a56cd67c666c9897751e24a51518136185403b1cba2" + const signatureS = + "0x6f7c776efde1e382f2ecc99ec0db13534a70ee86bd91d7b3a4059bccbed5d70c" + const signatureRecoveryID = 1 + + const digest2 = + "0xca071ca92644f1f2c4ae1bf71b6032e5eff4f78f3aa632b27cbc5f84104a32da" + + beforeEach(async () => { + await submitMembersPublicKeys(publicKey) + }) + + it("returns false if signing was not requested", async () => { + assert.isFalse(await keep.isAwaitingSignature(digest1)) + }) + + it("returns true if signing was requested for the digest", async () => { + await keep.sign(digest1, {from: owner}) + + assert.isTrue(await keep.isAwaitingSignature(digest1)) + }) + + it("returns false if signing was requested for other digest", async () => { + await keep.sign(digest2, {from: owner}) + + assert.isFalse(await keep.isAwaitingSignature(digest1)) + }) + + it("returns false if valid signature has been already submitted", async () => { + await keep.sign(digest1, {from: owner}) + + await keep.submitSignature(signatureR, signatureS, signatureRecoveryID, { + from: members[0], + }) + + assert.isFalse(await keep.isAwaitingSignature(digest1)) + }) + + it("returns true if invalid signature was submitted before", async () => { + await keep.sign(digest1, {from: owner}) + + await expectRevert( + keep.submitSignature(signatureR, signatureS, 0, {from: members[0]}), + "Invalid signature" + ) + + assert.isTrue(await keep.isAwaitingSignature(digest1)) + }) + }) + + describe("public key submission gas cost", async () => { + const publicKey = + "0x657282135ed640b0f5a280874c7e7ade110b5c3db362e0552e6b7fff2cc8459328850039b734db7629c31567d7fc5677536b7fc504e967dc11f3f2289d3d4051" + const anotherPublicKey = + "0x699282135ed640b0f5a280874c7e7ade110b5c3db362e0552e6b7fff2cc8459328850039b734db7629c31567d7fc5677536b7fc504e967dc11f3f2289d3d4052" + + const sixteenSigners = [...Array(16).keys()].map((i) => accounts[i]) + + let keepWith16Signers + + beforeEach(async () => { + const keepAddress = await factoryStub.newKeep.call( + owner, + sixteenSigners, + sixteenSigners.length, + bonding.address, + factoryStub.address + ) + + await factoryStub.newKeep( + owner, + sixteenSigners, + sixteenSigners.length, + bonding.address, + factoryStub.address + ) + + keepWith16Signers = await FullyBackedBondedECDSAKeep.at(keepAddress) + }) + + it("should be less than 350k if all submitted keys match", async () => { + const maxExpectedCost = web3.utils.toBN(350000) + for (let i = 0; i < sixteenSigners.length; i++) { + const tx = await keepWith16Signers.submitPublicKey(publicKey, { + from: sixteenSigners[i], + }) + + const gasUsed = web3.utils.toBN(tx.receipt.gasUsed) + expect(gasUsed).to.be.lte.BN(maxExpectedCost) + } + }) + + it("should be less than 350k if the last submitted key does not match", async () => { + const maxExpectedCost = web3.utils.toBN(350000) + for (let i = 0; i < sixteenSigners.length - 1; i++) { + await keepWith16Signers.submitPublicKey(publicKey, { + from: sixteenSigners[i], + }) + } + + const tx = await keepWith16Signers.submitPublicKey(anotherPublicKey, { + from: sixteenSigners[15], + }) + + const gasUsed = web3.utils.toBN(tx.receipt.gasUsed) + expect(gasUsed).to.be.lte.BN(maxExpectedCost) + }) + }) + + describe("public key", () => { + const publicKey0 = + "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + const publicKey1 = + "0xa899b9539de2a6345dc2ebd14010fe6bcd5d38db9ed75cef4afc6fc68a4c45a4901970bbff307e69048b4d6edf960a6dd7bc5ba9b1cf1b4e0a1e319f68e0741a" + const publicKey2 = + "0x999999539de2a6345dc2ebd14010fe6bcd5d38db9ed75cef4afc6fc68a4c45a4901970bbff307e69048b4d6edf960a6dd7bc5ba9b1cf1b4e0a1e319f68e0741a" + const publicKey3 = + "0x657282135ed640b0f5a280874c7e7ade110b5c3db362e0552e6b7fff2cc8459328850039b734db7629c31567d7fc5677536b7fc504e967dc11f3f2289d3d4051" + + it("get public key before it is set", async () => { + const publicKey = await keep.getPublicKey.call() + + assert.equal(publicKey, undefined, "public key should not be set") + }) + + it("get the public key when all members submitted", async () => { + await submitMembersPublicKeys(publicKey1) + + const publicKey = await keep.getPublicKey.call() + + assert.equal(publicKey, publicKey1, "incorrect public key") + }) + + describe("submitPublicKey", async () => { + it("does not emit an event nor sets the key when keys were not submitted by all members", async () => { + const res = await keep.submitPublicKey(publicKey1, {from: members[1]}) + truffleAssert.eventNotEmitted(res, "PublicKeyPublished") + + const publicKey = await keep.getPublicKey.call() + assert.equal(publicKey, null, "incorrect public key") + }) + + it("does not emit an event nor sets the key when inconsistent keys were submitted by all members", async () => { + const startBlock = await web3.eth.getBlockNumber() + + await keep.submitPublicKey(publicKey1, {from: members[0]}) + await keep.submitPublicKey(publicKey2, {from: members[1]}) + await keep.submitPublicKey(publicKey3, {from: members[2]}) + + assert.isNull(await keep.getPublicKey(), "incorrect public key") + + assert.isEmpty( + await keep.getPastEvents("PublicKeyPublished", { + fromBlock: startBlock, + toBlock: "latest", + }), + "unexpected events emitted" + ) + }) + + it("does not emit an event nor sets the key when just one inconsistent key was submitted", async () => { + const startBlock = await web3.eth.getBlockNumber() + + await keep.submitPublicKey(publicKey1, {from: members[0]}) + await keep.submitPublicKey(publicKey2, {from: members[1]}) + await keep.submitPublicKey(publicKey1, {from: members[2]}) + + assert.isNull(await keep.getPublicKey(), "incorrect public key") + + assert.isEmpty( + await keep.getPastEvents("PublicKeyPublished", { + fromBlock: startBlock, + toBlock: "latest", + }), + "unexpected events emitted" + ) + }) + + it("emits event and sets a key when all submitted keys are the same", async () => { + let res = await keep.submitPublicKey(publicKey1, {from: members[2]}) + truffleAssert.eventNotEmitted(res, "PublicKeyPublished") + + res = await keep.submitPublicKey(publicKey1, {from: members[0]}) + truffleAssert.eventNotEmitted(res, "PublicKeyPublished") + + const actualPublicKey = await keep.getPublicKey() + assert.isNull(actualPublicKey, "incorrect public key") + + res = await keep.submitPublicKey(publicKey1, {from: members[1]}) + truffleAssert.eventEmitted(res, "PublicKeyPublished", { + publicKey: publicKey1, + }) + + assert.equal( + await keep.getPublicKey(), + publicKey1, + "incorrect public key" + ) + }) + + it("does not allow submitting public key more than once", async () => { + await keep.submitPublicKey(publicKey0, {from: members[0]}) + + await expectRevert( + keep.submitPublicKey(publicKey1, {from: members[0]}), + "Member already submitted a public key" + ) + }) + + it("does not emit conflict event for first all zero key ", async () => { + // Event should not be emitted as other keys are not yet submitted. + const res = await keep.submitPublicKey(publicKey0, {from: members[2]}) + truffleAssert.eventNotEmitted(res, "ConflictingPublicKeySubmitted") + + // One event should be emitted as just one other key is submitted. + const startBlock = await web3.eth.getBlockNumber() + await keep.submitPublicKey(publicKey1, {from: members[0]}) + assert.lengthOf( + await keep.getPastEvents("ConflictingPublicKeySubmitted", { + fromBlock: startBlock, + toBlock: "latest", + }), + 1, + "unexpected events" + ) + }) + + it("emits conflict events for submitted values", async () => { + // In this test it's important that members don't submit in the same order + // as they are registered in the keep. We want to stress this scenario + // and confirm that logic works correctly in such sophisticated scenario. + + // First member submits a public key, there are not conflicts. + let startBlock = await web3.eth.getBlockNumber() + await keep.submitPublicKey(publicKey1, {from: members[2]}) + assert.lengthOf( + await keep.getPastEvents("ConflictingPublicKeySubmitted", { + fromBlock: startBlock, + toBlock: "latest", + }), + 0, + "unexpected events for the first submitted key" + ) + await mineBlocks(1) + + // Second member submits another public key, there is one conflict. + startBlock = await web3.eth.getBlockNumber() + await keep.submitPublicKey(publicKey2, {from: members[1]}) + assert.lengthOf( + await keep.getPastEvents("ConflictingPublicKeySubmitted", { + fromBlock: startBlock, + toBlock: "latest", + }), + 1, + "unexpected events for the second submitted key" + ) + await mineBlocks(1) + + // Third member submits yet another public key, there are two conflicts. + startBlock = await web3.eth.getBlockNumber() + await keep.submitPublicKey(publicKey3, {from: members[0]}) + assert.lengthOf( + await keep.getPastEvents("ConflictingPublicKeySubmitted", { + fromBlock: startBlock, + toBlock: "latest", + }), + 2, + "unexpected events for the third submitted key" + ) + + assert.isNull(await keep.getPublicKey(), "incorrect public key") + }) + + it("reverts when public key already set", async () => { + await submitMembersPublicKeys(publicKey1) + + await expectRevert( + keep.submitPublicKey(publicKey1, {from: members[0]}), + "Member already submitted a public key" + ) + }) + + it("cannot be called by non-member", async () => { + await expectRevert( + keep.submitPublicKey(publicKey1), + "Caller is not the keep member" + ) + }) + + it("cannot be called by non-member owner", async () => { + await expectRevert( + keep.submitPublicKey(publicKey1, {from: owner}), + "Caller is not the keep member" + ) + }) + + it("cannot be different than 64 bytes", async () => { + const badPublicKey = + "0x9b9539de2a6345dc2ebd14010fe6bcd5d38db9ed75cef4afc6fc68a4c45a4901970bbff307e69048b4d6edf960a6dd7bc5ba9b1cf1b4e0a1e319f68e0741a" + await keep.submitPublicKey(publicKey1, {from: members[1]}) + await expectRevert( + keep.submitPublicKey(badPublicKey, {from: members[2]}), + "Public key must be 64 bytes long" + ) + }) + }) + }) + + describe("checkBondAmount", () => { + it("should return bond amount", async () => { + const expectedBondsSum = await createMembersBonds(keep) + + const actual = await keep.checkBondAmount.call() + + expect(actual).to.eq.BN(expectedBondsSum, "incorrect bond amount") + }) + }) + + describe("seizeSignerBonds", () => { + const digest = + "0xca071ca92644f1f2c4ae1bf71b6032e5eff4f78f3aa632b27cbc5f84104a32da" + const publicKey = + "0xa899b9539de2a6345dc2ebd14010fe6bcd5d38db9ed75cef4afc6fc68a4c45a4901970bbff307e69048b4d6edf960a6dd7bc5ba9b1cf1b4e0a1e319f68e0741a" + + let initialBondsSum + + beforeEach(async () => { + await submitMembersPublicKeys(publicKey) + initialBondsSum = await createMembersBonds(keep) + }) + + it("should seize signer bond", async () => { + const expectedBondsSum = initialBondsSum + const ownerBalanceBefore = await web3.eth.getBalance(owner) + + expect(await keep.checkBondAmount()).to.eq.BN( + expectedBondsSum, + "incorrect bond amount before seizure" + ) + + const gasPrice = await web3.eth.getGasPrice() + + const txHash = await keep.seizeSignerBonds({from: owner}) + const seizedSignerBondsFee = new BN(txHash.receipt.gasUsed).mul( + new BN(gasPrice) + ) + const ownerBalanceDiff = new BN(await web3.eth.getBalance(owner)) + .add(seizedSignerBondsFee) + .sub(new BN(ownerBalanceBefore)) + + expect(ownerBalanceDiff).to.eq.BN( + expectedBondsSum, + "incorrect owner balance" + ) + + expect(await keep.checkBondAmount()).to.eq.BN( + 0, + "should zero all the bonds" + ) + }) + + it("terminates a keep", async () => { + await keep.seizeSignerBonds({from: owner}) + assert.isTrue(await keep.isTerminated(), "keep should be terminated") + assert.isFalse(await keep.isActive(), "keep should no longer be active") + assert.isFalse(await keep.isClosed(), "keep should not be closed") + }) + + it("emits an event", async () => { + truffleAssert.eventEmitted( + await keep.seizeSignerBonds({from: owner}), + "KeepTerminated" + ) + }) + + it("can be called only by owner", async () => { + await expectRevert( + keep.seizeSignerBonds({from: nonOwner}), + "Caller is not the keep owner" + ) + }) + + it("succeeds when signing is in progress", async () => { + keep.sign(digest, {from: owner}) + + await keep.seizeSignerBonds({from: owner}) + }) + it("reverts when already seized", async () => { + await keep.seizeSignerBonds({from: owner}) + + await expectRevert( + keep.seizeSignerBonds({from: owner}), + "Keep is not active" + ) + }) + + it("reverts when already closed", async () => { + await keep.closeKeep({from: owner}) + + await expectRevert( + keep.seizeSignerBonds({from: owner}), + "Keep is not active" + ) + }) + }) + + describe("checkSignatureFraud", () => { + // Private key: 0x937FFE93CFC943D1A8FC0CB8BAD44A978090A4623DA81EEFDFF5380D0A290B41 + // Public key: + // Curve: secp256k1 + // X: 0x9A0544440CC47779235CCB76D669590C2CD20C7E431F97E17A1093FAF03291C4 + // Y: 0x73E661A208A8A565CA1E384059BD2FF7FF6886DF081FF1229250099D388C83DF + + // TODO: Extract test data to a test data file and use them consistently across other tests. + + const publicKey1 = + "0x9a0544440cc47779235ccb76d669590c2cd20c7e431f97e17a1093faf03291c473e661a208a8a565ca1e384059bd2ff7ff6886df081ff1229250099d388c83df" + const preimage1 = + "0xfdaf2feee2e37c24f2f8d15ad5814b49ba04b450e67b859976cbf25c13ea90d8" + // hash256Digest1 = sha256(preimage1) + const hash256Digest1 = + "0x8bacaa8f02ef807f2f61ae8e00a5bfa4528148e0ae73b2bd54b71b8abe61268e" + + const signature1 = { + R: "0xedc074a86380cc7e2e4702eaf1bec87843bc0eb7ebd490f5bdd7f02493149170", + S: "0x3f5005a26eb6f065ea9faea543e5ddb657d13892db2656499a43dfebd6e12efc", + V: 28, + } + + const hash256Digest2 = + "0x14a6483b8aca55c9df2a35baf71d9965ddfd623468d81d51229bd5eb7d1e1c1b" + const preimage2 = "0x1111636820506f7a6e616e" + + it("reverts if public key was not set", async () => { + await expectRevert( + keep.checkSignatureFraud.call( + signature1.V, + signature1.R, + signature1.S, + hash256Digest1, + preimage1 + ), + "Public key was not set yet" + ) + }) + + it("should return true when signature is valid but was not requested", async () => { + await submitMembersPublicKeys(publicKey1) + + await keep.sign(hash256Digest2, {from: owner}) + + const res = await keep.checkSignatureFraud.call( + signature1.V, + signature1.R, + signature1.S, + hash256Digest1, + preimage1 + ) + + assert.isTrue( + res, + "Signature is fraudulent because is valid but was not requested." + ) + }) + + it("should return an error when preimage does not match digest", async () => { + await submitMembersPublicKeys(publicKey1) + + await keep.sign(hash256Digest2, {from: owner}) + + await expectRevert( + keep.checkSignatureFraud.call( + signature1.V, + signature1.R, + signature1.S, + hash256Digest1, + preimage2 + ), + "Signed digest does not match sha256 hash of the preimage" + ) + }) + + it("should return false when signature is invalid and was requested", async () => { + await submitMembersPublicKeys(publicKey1) + + const badSignatureR = + "0x1112c3623b6a16e87b4d3a56cd67c666c9897751e24a51518136185403b1cba2" + + assert.isFalse( + await keep.checkSignatureFraud.call( + signature1.V, + badSignatureR, + signature1.S, + hash256Digest1, + preimage1 + ), + "signature is not fraudulent" + ) + }) + + it("should return false when signature is invalid and was not requested", async () => { + await submitMembersPublicKeys(publicKey1) + + await keep.sign(hash256Digest2, {from: owner}) + const badSignatureR = + "0x1112c3623b6a16e87b4d3a56cd67c666c9897751e24a51518136185403b1cba2" + + assert.isFalse( + await keep.checkSignatureFraud.call( + signature1.V, + badSignatureR, + signature1.S, + hash256Digest1, + preimage1 + ), + "signature is not fraudulent" + ) + }) + + it("should return false when signature is valid and was requested", async () => { + await submitMembersPublicKeys(publicKey1) + + await keep.sign(hash256Digest1, {from: owner}) + + assert.isFalse( + await keep.checkSignatureFraud.call( + signature1.V, + signature1.R, + signature1.S, + hash256Digest1, + preimage1 + ), + "signature is not fraudulent" + ) + }) + + it("should return false when signature is valid, was requested and was submitted", async () => { + await submitMembersPublicKeys(publicKey1) + + await keep.sign(hash256Digest1, {from: owner}) + await keep.submitSignature( + signature1.R, + signature1.S, + signature1.V - 27, + { + from: members[0], + } + ) + + assert.isFalse( + await keep.checkSignatureFraud.call( + signature1.V, + signature1.R, + signature1.S, + hash256Digest1, + preimage1 + ), + "signature is not fraudulent" + ) + }) + }) + + describe("submitSignatureFraud", () => { + // Private key: 0x937FFE93CFC943D1A8FC0CB8BAD44A978090A4623DA81EEFDFF5380D0A290B41 + // Public key: + // Curve: secp256k1 + // X: 0x9A0544440CC47779235CCB76D669590C2CD20C7E431F97E17A1093FAF03291C4 + // Y: 0x73E661A208A8A565CA1E384059BD2FF7FF6886DF081FF1229250099D388C83DF + + // TODO: Extract test data to a test data file and use them consistently across other tests. + + const publicKey1 = + "0x9a0544440cc47779235ccb76d669590c2cd20c7e431f97e17a1093faf03291c473e661a208a8a565ca1e384059bd2ff7ff6886df081ff1229250099d388c83df" + const preimage1 = + "0xfdaf2feee2e37c24f2f8d15ad5814b49ba04b450e67b859976cbf25c13ea90d8" + // hash256Digest1 = sha256(preimage1) + const hash256Digest1 = + "0x8bacaa8f02ef807f2f61ae8e00a5bfa4528148e0ae73b2bd54b71b8abe61268e" + + const signature1 = { + R: "0xedc074a86380cc7e2e4702eaf1bec87843bc0eb7ebd490f5bdd7f02493149170", + S: "0x3f5005a26eb6f065ea9faea543e5ddb657d13892db2656499a43dfebd6e12efc", + V: 28, + } + + it("should return true and slash members when the signature is fraudulent", async () => { + await submitMembersPublicKeys(publicKey1) + + const res = await keep.submitSignatureFraud.call( + signature1.V, + signature1.R, + signature1.S, + hash256Digest1, + preimage1 + ) + + await keep.submitSignatureFraud( + signature1.V, + signature1.R, + signature1.S, + hash256Digest1, + preimage1 + ) + + assert.isTrue(res, "incorrect returned result") + + // TODO: Verify that member is banned + }) + + // TODO: Modify this case after adding banning functionality. + // it("should prevent from slashing members multiple times for the same fradulent preimage", async () => { + // await submitMembersPublicKeys(publicKey1) + + // const memberStake = web3.utils.toBN("100000000000000000000000") + // // setting a value other then the min stake for testing purposes + // await keep.setMemberStake(memberStake) + + // assert.isFalse( + // await keep.isFradulentPreimageSet(preimage1), + // "fradulent preimage should not have been set" + // ) + + // await keep.submitSignatureFraud( + // signature1.V, + // signature1.R, + // signature1.S, + // hash256Digest1, + // preimage1 + // ) + + // assert.isTrue( + // await keep.isFradulentPreimageSet(preimage1), + // "fradulent preimage should have been set" + // ) + + // await keep.submitSignatureFraud( + // signature1.V, + // signature1.R, + // signature1.S, + // hash256Digest1, + // preimage1 + // ) + + // for (let i = 0; i < members.length; i++) { + // const actualStake = await tokenStaking.eligibleStake( + // members[i], + // constants.ZERO_ADDRESS + // ) + // expect(actualStake).to.eq.BN( + // minimumStake.sub(memberStake), + // `incorrect stake for member ${i}` + // ) + // } + // }) + + it("should revert when the signature is not fraudulent", async () => { + await submitMembersPublicKeys(publicKey1) + + await keep.sign(hash256Digest1, {from: owner}) + + await expectRevert( + keep.submitSignatureFraud( + signature1.V, + signature1.R, + signature1.S, + hash256Digest1, + preimage1 + ), + "Signature is not fraudulent" + ) + + // TODO: Verify that member has not been banned + }) + + it("reverts if called for closed keep", async () => { + await keep.publicMarkAsClosed() + + await expectRevert( + keep.submitSignatureFraud( + signature1.V, + signature1.R, + signature1.S, + hash256Digest1, + preimage1 + ), + "Keep is not active" + ) + }) + + it("reverts if called for terminated keep", async () => { + await keep.publicMarkAsTerminated() + + await expectRevert( + keep.submitSignatureFraud( + signature1.V, + signature1.R, + signature1.S, + hash256Digest1, + preimage1 + ), + "Keep is not active" + ) + }) + }) + + describe("submitSignature", () => { + const digest = + "0x54a6483b8aca55c9df2a35baf71d9965ddfd623468d81d51229bd5eb7d1e1c1b" + const publicKey = + "0x657282135ed640b0f5a280874c7e7ade110b5c3db362e0552e6b7fff2cc8459328850039b734db7629c31567d7fc5677536b7fc504e967dc11f3f2289d3d4051" + const signatureR = + "0x9b32c3623b6a16e87b4d3a56cd67c666c9897751e24a51518136185403b1cba2" + const signatureS = + "0x6f7c776efde1e382f2ecc99ec0db13534a70ee86bd91d7b3a4059bccbed5d70c" + const signatureRecoveryID = 1 + + // This malleable signature details corresponds to the signature above but + // it's calculated that `S` is in the higher half of curve's order. We use + // this to check malleability. + // `malleableS = secp256k1.N - signatureS` + // To read more see [EIP-2](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.md). + const malleableS = + "0x90838891021e1c7d0d1336613f24ecab703dee5ff1b6c8881bccc2c011606a35" + const malleableRecoveryID = 0 + + beforeEach(async () => { + await submitMembersPublicKeys(publicKey) + }) + + it("emits an event", async () => { + await keep.sign(digest, {from: owner}) + + const res = await keep.submitSignature( + signatureR, + signatureS, + signatureRecoveryID, + {from: members[0]} + ) + + truffleAssert.eventEmitted(res, "SignatureSubmitted", (ev) => { + return ( + ev.digest == digest && + ev.r == signatureR && + ev.s == signatureS && + ev.recoveryID == signatureRecoveryID + ) + }) + }) + + it("clears signing lock after submission", async () => { + await keep.sign(digest, {from: owner}) + + await keep.submitSignature(signatureR, signatureS, signatureRecoveryID, { + from: members[0], + }) + + await keep.sign(digest, {from: owner}) + }) + + it("cannot be submitted if signing was not requested", async () => { + await expectRevert( + keep.submitSignature(signatureR, signatureS, signatureRecoveryID, { + from: members[0], + }), + "Not awaiting a signature" + ) + }) + + describe("validates signature", async () => { + beforeEach(async () => { + await keep.sign(digest, {from: owner}) + }) + + it("rejects recovery ID out of allowed range", async () => { + await expectRevert( + keep.submitSignature(signatureR, signatureS, 4, {from: members[0]}), + "Recovery ID must be one of {0, 1, 2, 3}" + ) + }) + + it("rejects invalid signature", async () => { + await expectRevert( + keep.submitSignature(signatureR, signatureS, 0, {from: members[0]}), + "Invalid signature" + ) + }) + + it("rejects malleable signature", async () => { + try { + await keep.submitSignature( + signatureR, + malleableS, + malleableRecoveryID, + {from: members[0]} + ) + assert(false, "Test call did not error as expected") + } catch (e) { + assert.include( + e.message, + "Malleable signature - s should be in the low half of secp256k1 curve's order" + ) + } + }) + }) + + it("cannot be called by non-member", async () => { + await keep.sign(digest, {from: owner}) + + await expectRevert( + keep.submitSignature(signatureR, signatureS, signatureRecoveryID), + "Caller is not the keep member" + ) + }) + + it("cannot be called by non-member owner", async () => { + await keep.sign(digest, {from: owner}) + + await expectRevert( + keep.submitSignature(signatureR, signatureS, signatureRecoveryID, { + from: owner, + }), + "Caller is not the keep member" + ) + }) + }) + + describe("closeKeep", () => { + const digest = + "0xca071ca92644f1f2c4ae1bf71b6032e5eff4f78f3aa632b27cbc5f84104a32da" + const publicKey = + "0xa899b9539de2a6345dc2ebd14010fe6bcd5d38db9ed75cef4afc6fc68a4c45a4901970bbff307e69048b4d6edf960a6dd7bc5ba9b1cf1b4e0a1e319f68e0741a" + + const bondValue0 = new BN(10) + const bondValue1 = new BN(20) + const bondValue2 = new BN(20) + + beforeEach(async () => { + await createMembersBonds(keep, bondValue0, bondValue1, bondValue2) + await submitMembersPublicKeys(publicKey) + }) + + it("emits an event", async () => { + truffleAssert.eventEmitted( + await keep.closeKeep({from: owner}), + "KeepClosed" + ) + }) + + it("marks keep as closed", async () => { + await keep.closeKeep({from: owner}) + assert.isTrue(await keep.isClosed(), "keep should be closed") + assert.isFalse(await keep.isActive(), "keep should no longer be active") + assert.isFalse(await keep.isTerminated(), "keep should not be terminated") + }) + + it("frees members bonds", async () => { + await keep.closeKeep({from: owner}) + + expect(await keep.checkBondAmount()).to.eq.BN( + 0, + "incorrect bond amount for keep" + ) + + expect( + await bonding.availableUnbondedValue( + members[0], + bondCreator, + signingPool + ) + ).to.eq.BN(bondValue0, "incorrect unbonded amount for member 0") + + expect( + await bonding.availableUnbondedValue( + members[1], + bondCreator, + signingPool + ) + ).to.eq.BN(bondValue1, "incorrect unbonded amount for member 1") + + expect( + await bonding.availableUnbondedValue( + members[2], + bondCreator, + signingPool + ) + ).to.eq.BN(bondValue2, "incorrect unbonded amount for member 2") + }) + + it("succeeds when signing is in progress", async () => { + keep.sign(digest, {from: owner}) + + await keep.closeKeep({from: owner}) + }) + + it("cannot be called by non-owner", async () => { + await expectRevert(keep.closeKeep(), "Caller is not the keep owner") + }) + + it("reverts when already closed", async () => { + await keep.closeKeep({from: owner}) + + await expectRevert(keep.closeKeep({from: owner}), "Keep is not active") + }) + + it("reverts when already seized", async () => { + await keep.seizeSignerBonds({from: owner}) + + await expectRevert(keep.closeKeep({from: owner}), "Keep is not active") + }) + }) + + describe("returnPartialSignerBonds", async () => { + const singleReturnedBondValue = new BN(2000) + const allReturnedBondsValue = singleReturnedBondValue.mul( + new BN(members.length) + ) + + const member1Unbonded = new BN(100) + const member2Unbounded = new BN(200) + const member3Unbounded = new BN(700) + + beforeEach(async () => { + await depositForBonding( + member1Unbonded, + member2Unbounded, + member3Unbounded + ) + }) + + it("correctly distributes ETH", async () => { + await keep.returnPartialSignerBonds({value: allReturnedBondsValue}) + + const member1UnbondedAfter = await bonding.availableUnbondedValue( + members[0], + bondCreator, + signingPool + ) + const member2UnbondedAfter = await bonding.availableUnbondedValue( + members[1], + bondCreator, + signingPool + ) + const member3UnbondedAfter = await bonding.availableUnbondedValue( + members[2], + bondCreator, + signingPool + ) + + expect( + member1UnbondedAfter, + "incorrect unbounded balance for member 1" + ).to.eq.BN(2100) // 2000 + 100 + expect( + member2UnbondedAfter, + "incorrect unbounded balance for member 2" + ).to.eq.BN(2200) // 2000 + 200 + expect( + member3UnbondedAfter, + "incorrect unbounded balance for member 3" + ).to.eq.BN(2700) // 2000 + 700 + }) + + it("correctly handles remainder", async () => { + const remainder = new BN(2) + + await keep.returnPartialSignerBonds({ + value: allReturnedBondsValue.add(remainder), + }) + + const member1UnbondedAfter = await bonding.availableUnbondedValue( + members[0], + bondCreator, + signingPool + ) + const member2UnbondedAfter = await bonding.availableUnbondedValue( + members[1], + bondCreator, + signingPool + ) + const member3UnbondedAfter = await bonding.availableUnbondedValue( + members[2], + bondCreator, + signingPool + ) + + expect( + member1UnbondedAfter, + "incorrect unbounded balance for member 1" + ).to.eq.BN(2100) // 2000 + 100 + expect( + member2UnbondedAfter, + "incorrect unbounded balance for member 2" + ).to.eq.BN(2200) // 2000 + 200 + expect( + member3UnbondedAfter, + "incorrect unbounded balance for member 3" + ).to.eq.BN(2702) // 2000 + 700 + 2 + }) + + it("reverts with zero value", async () => { + await expectRevert( + keep.returnPartialSignerBonds({value: 0}), + "Partial signer bond must be non-zero" + ) + }) + + it("reverts with zero value per member", async () => { + await expectRevert( + keep.returnPartialSignerBonds({value: members.length - 1}), + "Partial signer bond must be non-zero" + ) + }) + }) + + describe("distributeETHReward", async () => { + const singleValue = new BN(1000) + const ethValue = singleValue.mul(new BN(members.length)) + + it("emits event", async () => { + const startBlock = await web3.eth.getBlockNumber() + + const res = await keep.distributeETHReward({value: ethValue}) + truffleAssert.eventEmitted(res, "ETHRewardDistributed", (event) => { + return web3.utils.toBN(event.amount).eq(ethValue) + }) + + assert.lengthOf( + await keep.getPastEvents("ETHRewardDistributed", { + fromBlock: startBlock, + toBlock: "latest", + }), + 1, + "unexpected events emitted" + ) + }) + + it("correctly distributes ETH", async () => { + const initialBalances = await getETHBalancesFromList(members) + + await keep.distributeETHReward({value: ethValue}) + + const newBalances = await getETHBalancesFromList(members) + + assert.deepEqual(newBalances, initialBalances) + + expect( + await web3.eth.getBalance(keep.address), + "incorrect keep balance" + ).to.eq.BN(ethValue) + + expect( + await keep.getMemberETHBalance(members[0]), + "incorrect member 0 balance" + ).to.eq.BN(singleValue) + + expect( + await keep.getMemberETHBalance(members[1]), + "incorrect member 1 balance" + ).to.eq.BN(singleValue) + + expect( + await keep.getMemberETHBalance(members[2]), + "incorrect member 2 balance" + ).to.eq.BN(singleValue) + }) + + it("correctly handles unused remainder", async () => { + const expectedRemainder = new BN(members.length - 1) + const valueWithRemainder = ethValue.add(expectedRemainder) + + await keep.distributeETHReward({value: valueWithRemainder}) + + expect( + await web3.eth.getBalance(keep.address), + "incorrect keep balance" + ).to.eq.BN(valueWithRemainder) + + expect( + await keep.getMemberETHBalance(members[0]), + "incorrect member 0 balance" + ).to.eq.BN(singleValue) + + expect( + await keep.getMemberETHBalance(members[1]), + "incorrect member 1 balance" + ).to.eq.BN(singleValue) + + expect( + await keep.getMemberETHBalance(members[2]), + "incorrect member 2 balance" + ).to.eq.BN(singleValue.add(expectedRemainder)) + }) + + it("reverts with zero value", async () => { + await expectRevert( + keep.distributeETHReward(), + "Dividend value must be non-zero" + ) + }) + + it("reverts with zero dividend", async () => { + const msgValue = members.length - 1 + await expectRevert( + keep.distributeETHReward({value: msgValue}), + "Dividend value must be non-zero" + ) + }) + }) + + describe("withdraw", async () => { + const singleValue = new BN(1000) + const ethValue = singleValue.mul(new BN(members.length)) + + beforeEach(async () => { + await keep.distributeETHReward({value: ethValue}) + }) + + it("correctly transfers value", async () => { + const initialMemberBalance = new BN( + await web3.eth.getBalance(beneficiaries[0]) + ) + + await keep.withdraw(members[0]) + + expect( + await web3.eth.getBalance(keep.address), + "incorrect keep balance" + ).to.eq.BN(ethValue.sub(singleValue)) + + expect( + await keep.getMemberETHBalance(members[0]), + "incorrect member balance" + ).to.eq.BN(0) + + expect( + await web3.eth.getBalance(beneficiaries[0]), + "incorrect member account balance" + ).to.eq.BN(initialMemberBalance.add(singleValue)) + }) + + it("sends ETH to beneficiary", async () => { + const valueWithRemainder = ethValue.add(new BN(1)) + const expectedMember1Reward = ethValue.divn(2) + const expectedMember2Reward = valueWithRemainder.sub( + expectedMember1Reward + ) + + const member1 = members[0] + const member2 = members[1] + + const testMembers = [member1, member2] + + const accountsInTest = [ + member1, + member2, + beneficiaries[0], + beneficiaries[1], + ] + const expectedBalances = [ + new BN(await web3.eth.getBalance(member1)), + new BN(await web3.eth.getBalance(member2)), + new BN(await web3.eth.getBalance(beneficiaries[0])).add( + expectedMember1Reward + ), + new BN(await web3.eth.getBalance(beneficiaries[1])).add( + expectedMember2Reward + ), + ] + + const keep = await newKeep( + owner, + testMembers, + honestThreshold, + bonding.address, + factoryStub.address + ) + + await keep.distributeETHReward({value: valueWithRemainder}) + + await keep.withdraw(member1) + expect( + await keep.getMemberETHBalance(member1), + "incorrect member 1 balance" + ).to.eq.BN(0) + + await keep.withdraw(member2) + expect( + await keep.getMemberETHBalance(member2), + "incorrect member 2 balance" + ).to.eq.BN(0) + + // Check balances of all keep members' and beneficiary. + const newBalances = await getETHBalancesFromList(accountsInTest) + assert.deepEqual(newBalances, expectedBalances) + }) + + it("reverts in case of zero balance", async () => { + const member = members[0] + + const keep = await newKeep( + owner, + [member], + honestThreshold, + bonding.address, + factoryStub.address + ) + + await expectRevert(keep.withdraw(member), "No funds to withdraw") + }) + + it("reverts in case of transfer failure", async () => { + const etherReceiver = await TestEtherReceiver.new() + await etherReceiver.setShouldFail(true) + + const member = members[0] + await bonding.setBeneficiary(member, etherReceiver.address) // a receiver which we expect to reject the transfer + + const keep = await newKeep( + owner, + [member], + honestThreshold, + bonding.address, + factoryStub.address + ) + + await keep.distributeETHReward({value: ethValue}) + + await expectRevert(keep.withdraw(member), "Transfer failed") + + // Check balances of keep members's beneficiary account. + expect( + await web3.eth.getBalance(etherReceiver.address), + "incorrect member's account balance" + ).to.eq.BN(0) + + // Check that value which failed transfer remained in the keep contract. + expect( + await web3.eth.getBalance(keep.address), + "incorrect keep's account balance" + ).to.eq.BN(ethValue) + }) + }) + + describe("distributeERC20Reward", async () => { + const erc20Value = new BN(2000).mul(new BN(members.length)) + let token + + beforeEach(async () => { + token = await TestToken.new() + }) + + it("correctly distributes ERC20", async () => { + await initializeTokens(token, keep, accounts[0], erc20Value) + + const expectedBalances = addToBalances( + await getERC20BalancesFromList(beneficiaries, token), + erc20Value / members.length + ) + + await keep.distributeERC20Reward(token.address, erc20Value, { + from: accounts[0], + }) + + const newBalances = await getERC20BalancesFromList(beneficiaries, token) + + assert.equal(newBalances.toString(), expectedBalances.toString()) + }) + + it("emits an event", async () => { + await initializeTokens(token, keep, accounts[0], erc20Value) + + const startBlock = await web3.eth.getBlockNumber() + + const res = await keep.distributeERC20Reward(token.address, erc20Value, { + from: accounts[0], + }) + truffleAssert.eventEmitted(res, "ERC20RewardDistributed", (event) => { + return ( + token.address == event.token && + web3.utils.toBN(event.amount).eq(erc20Value) + ) + }) + + assert.lengthOf( + await keep.getPastEvents("ERC20RewardDistributed", { + fromBlock: startBlock, + toBlock: "latest", + }), + 1, + "unexpected events emitted" + ) + }) + + it("correctly handles remainder", async () => { + const expectedRemainder = new BN(members.length - 1) + const valueWithRemainder = erc20Value.add(expectedRemainder) + + await initializeTokens(token, keep, accounts[0], valueWithRemainder) + + const expectedBalances = addToBalances( + await getERC20BalancesFromList(beneficiaries, token), + erc20Value / members.length + ) + + const lastMemberIndex = members.length - 1 + expectedBalances[lastMemberIndex] = expectedBalances[lastMemberIndex].add( + expectedRemainder + ) + + await keep.distributeERC20Reward(token.address, valueWithRemainder, { + from: accounts[0], + }) + + const newBalances = await getERC20BalancesFromList(beneficiaries, token) + + assert.equal(newBalances.toString(), expectedBalances.toString()) + + expect(await token.balanceOf(keep.address)).to.eq.BN( + 0, + "incorrect keep balance" + ) + }) + + it("fails with insufficient approval", async () => { + await expectRevert( + keep.distributeERC20Reward(token.address, erc20Value), + "SafeERC20: low-level call failed" + ) + }) + + it("fails with zero value", async () => { + await expectRevert( + keep.distributeERC20Reward(token.address, 0), + "Dividend value must be non-zero" + ) + }) + + it("reverts with zero dividend", async () => { + const value = members.length - 1 + + await initializeTokens(token, keep, accounts[0], value) + + await expectRevert( + keep.distributeERC20Reward(token.address, value), + "Dividend value must be non-zero" + ) + }) + + it("sends ERC20 to beneficiary", async () => { + const valueWithRemainder = erc20Value.add(new BN(1)) + const expectedMember1Reward = erc20Value.divn(2) + const expectedMember2Reward = valueWithRemainder.sub( + expectedMember1Reward + ) + + const member1 = accounts[2] + const member2 = accounts[3] + + const testMembers = [member1, member2] + + const accountsInTest = [ + member1, + member2, + beneficiaries[0], + beneficiaries[1], + ] + const expectedBalances = [ + new BN(await token.balanceOf(member1)), + new BN(await token.balanceOf(member2)), + new BN(await token.balanceOf(beneficiaries[0])).add( + expectedMember1Reward + ), + new BN(await token.balanceOf(beneficiaries[1])).add( + expectedMember2Reward + ), + ] + + keep = await newKeep( + owner, + testMembers, + honestThreshold, + bonding.address, + factoryStub.address + ) + + await initializeTokens(token, keep, accounts[0], valueWithRemainder) + + await keep.distributeERC20Reward(token.address, valueWithRemainder, { + from: accounts[0], + }) + + // Check balances of all keep members' and beneficiary. + const newBalances = await getERC20BalancesFromList(accountsInTest, token) + assert.equal(newBalances.toString(), expectedBalances.toString()) + }) + + async function initializeTokens(token, keep, account, amount) { + await token.mint(account, amount, {from: account}) + await token.approve(keep.address, amount, {from: account}) + } + }) + + async function submitMembersPublicKeys(publicKey) { + await keep.submitPublicKey(publicKey, {from: members[0]}) + await keep.submitPublicKey(publicKey, {from: members[1]}) + await keep.submitPublicKey(publicKey, {from: members[2]}) + } + + async function delegateOperators() { + await delegate(members[0], beneficiaries[0], authorizers[0]) + await delegate(members[1], beneficiaries[1], authorizers[1]) + await delegate(members[2], beneficiaries[2], authorizers[2]) + } + + async function delegate(operator, beneficiary, authorizer, unbondedValue) { + const minimumDelegationDeposit = await bonding.MINIMUM_DELEGATION_DEPOSIT.call() + + await bonding.delegate(operator, beneficiary, authorizer, { + value: unbondedValue || minimumDelegationDeposit, + }) + + await bonding.authorizeOperatorContract(operator, bondCreator, { + from: authorizer, + }) + + await bonding.authorizeSortitionPoolContract(operator, signingPool, { + from: authorizer, + }) + } + + async function setUnbondedValue(operator, unbondedValue) { + const initialUnbondedValue = await bonding.unbondedValue(operator) + + if (initialUnbondedValue.eq(unbondedValue)) { + return + } else if (initialUnbondedValue.gt(unbondedValue)) { + await bonding.withdraw(initialUnbondedValue.sub(unbondedValue), operator) + } else { + await bonding.deposit(operator, { + value: unbondedValue.sub(initialUnbondedValue), + }) + } + } + + async function depositForBonding(member1Value, member2Value, member3Value) { + await setUnbondedValue(members[0], member1Value) + await setUnbondedValue(members[1], member2Value) + await setUnbondedValue(members[2], member3Value) + } + + async function createMembersBonds(keep, bond1, bond2, bond3) { + const bondValue1 = bond1 || new BN(100) + const bondValue2 = bond2 || new BN(200) + const bondValue3 = bond3 || new BN(300) + + const referenceID = web3.utils.toBN(web3.utils.padLeft(keep.address, 32)) + + await depositForBonding(bondValue1, bondValue2, bondValue3) + + await bonding.createBond( + members[0], + keep.address, + referenceID, + bondValue1, + signingPool, + {from: bondCreator} + ) + await bonding.createBond( + members[1], + keep.address, + referenceID, + bondValue2, + signingPool, + {from: bondCreator} + ) + await bonding.createBond( + members[2], + keep.address, + referenceID, + bondValue3, + signingPool, + {from: bondCreator} + ) + + return bondValue1.add(bondValue2).add(bondValue3) + } +}) From 7c3d0aaf80a2b71aa4fcff6bebe213914fcfc47b Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 25 Sep 2020 10:09:56 +0200 Subject: [PATCH 24/57] Added fully backed contracts to migrations scripts --- solidity/migrations/2_deploy_contracts.js | 26 +++++++++++++++++++++++ solidity/migrations/3_initialize.js | 13 +++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/solidity/migrations/2_deploy_contracts.js b/solidity/migrations/2_deploy_contracts.js index 48b6d91a3..ae504a835 100644 --- a/solidity/migrations/2_deploy_contracts.js +++ b/solidity/migrations/2_deploy_contracts.js @@ -8,14 +8,26 @@ const BondedECDSAKeepVendorImplV1 = artifacts.require( "BondedECDSAKeepVendorImplV1" ) +const FullyBackedBonding = artifacts.require("FullyBackedBonding") +const FullyBackedBondedECDSAKeep = artifacts.require( + "FullyBackedBondedECDSAKeep" +) +const FullyBackedBondedECDSAKeepFactory = artifacts.require( + "FullyBackedBondedECDSAKeepFactory" +) + const EthBonding = artifacts.require("EthBonding") const { deployBondedSortitionPoolFactory, + deployFullyBackedSortitionPoolFactory, } = require("@keep-network/sortition-pools/migrations/scripts/deployContracts") const BondedSortitionPoolFactory = artifacts.require( "BondedSortitionPoolFactory" ) +const FullyBackedSortitionPoolFactory = artifacts.require( + "FullyBackedSortitionPoolFactory" +) let { RandomBeaconAddress, @@ -26,6 +38,7 @@ let { module.exports = async function (deployer) { await deployBondedSortitionPoolFactory(artifacts, deployer) + await deployFullyBackedSortitionPoolFactory(artifacts, deployer) if (process.env.TEST) { TokenStakingStub = artifacts.require("TokenStakingStub") @@ -73,6 +86,19 @@ module.exports = async function (deployer) { implInitializeCallData ) + // ETH-only Staking + await deployer.deploy(FullyBackedBonding, RegistryAddress) + + await deployer.deploy(FullyBackedBondedECDSAKeep) + + await deployer.deploy( + FullyBackedBondedECDSAKeepFactory, + FullyBackedBondedECDSAKeep.address, + FullyBackedSortitionPoolFactory.address, + FullyBackedBonding.address, + RandomBeaconAddress + ) + // ETH-only backed bonding await deployer.deploy(EthBonding, RegistryAddress) } diff --git a/solidity/migrations/3_initialize.js b/solidity/migrations/3_initialize.js index d87c4ac21..193c850da 100644 --- a/solidity/migrations/3_initialize.js +++ b/solidity/migrations/3_initialize.js @@ -3,12 +3,16 @@ const BondedECDSAKeepVendorImplV1 = artifacts.require( "BondedECDSAKeepVendorImplV1" ) const BondedECDSAKeepFactory = artifacts.require("BondedECDSAKeepFactory") +const FullyBackedBondedECDSAKeepFactory = artifacts.require( + "FullyBackedBondedECDSAKeepFactory" +) const KeepRegistry = artifacts.require("KeepRegistry") const {RegistryAddress} = require("./external-contracts") module.exports = async function (deployer) { await BondedECDSAKeepFactory.deployed() + await BondedECDSAKeepFactory.deployed() let registry if (process.env.TEST) { @@ -32,7 +36,14 @@ module.exports = async function (deployer) { // Configure registry await registry.approveOperatorContract(BondedECDSAKeepFactory.address) console.log( - `approved operator contract [${BondedECDSAKeepFactory.address}] in registry` + `approved BondedECDSAKeepFactory operator contract [${BondedECDSAKeepFactory.address}] in registry` + ) + + await registry.approveOperatorContract( + FullyBackedBondedECDSAKeepFactory.address + ) + console.log( + `approved FullyBackedBondedECDSAKeepFactory operator contract [${FullyBackedBondedECDSAKeepFactory.address}] in registry` ) // Set service contract owner as operator contract upgrader by default From 0079c13b9bfaec90b15c647923c0b767ed8bd447 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 25 Sep 2020 10:16:04 +0200 Subject: [PATCH 25/57] Claim delegated authority in Fully Backed keep contract When initializing a keep we want to claim delegated authority from keep factory so the keep can manage bonds. --- solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol index 5eb5dd514..e50b43f88 100644 --- a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol +++ b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol @@ -49,6 +49,8 @@ contract FullyBackedBondedECDSAKeep is AbstractBondedECDSAKeep { bonding = FullyBackedBonding(_bonding); keepFactory = FullyBackedBondedECDSAKeepFactory(_keepFactory); + + bonding.claimDelegatedAuthority(_keepFactory); } function slashForSignatureFraud() internal { From d5d67038b9a916086ab3049f0e7a41c6adf67efc Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 25 Sep 2020 15:55:43 +0200 Subject: [PATCH 26/57] Added missing import in Keep Factory contract --- .../fully-backed/FullyBackedBondedECDSAKeepFactory.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol index 8af387020..3a73491f4 100644 --- a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol +++ b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol @@ -22,6 +22,10 @@ import "../KeepCreator.sol"; import "../GroupSelectionSeed.sol"; import "../CandidatesPools.sol"; +import { + AuthorityDelegator +} from "@keep-network/keep-core/contracts/Authorizations.sol"; + import "@keep-network/sortition-pools/contracts/api/IFullyBackedBonding.sol"; import "@keep-network/sortition-pools/contracts/FullyBackedSortitionPoolFactory.sol"; import "@keep-network/sortition-pools/contracts/FullyBackedSortitionPool.sol"; From c2fc5efa5279d5e1b5110d27905c65b326224d48 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 25 Sep 2020 15:56:37 +0200 Subject: [PATCH 27/57] Minor improvements to docs --- .../fully-backed/FullyBackedBondedECDSAKeepFactory.sol | 9 +++++---- solidity/contracts/fully-backed/FullyBackedBonding.sol | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol index 3a73491f4..8c8c903dc 100644 --- a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol +++ b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol @@ -60,9 +60,9 @@ contract FullyBackedBondedECDSAKeepFactory is uint256 public constant minimumBond = 20e18; // 20 ETH // TODO: Decide on value // Signer candidates in bonded sortition pool are weighted by their eligible - // stake divided by a constant divisor. The divisor is set to 1 KEEP so that - // all KEEPs in eligible stake matter when calculating operator's eligible - // weight for signer selection. + // stake divided by a constant divisor. The divisor is set to 1 ETH so that + // all ETHs in available unbonded value matter when calculating operator's + // eligible weight for signer selection. uint256 public constant bondWeightDivisor = 1e18; // 1 ETH // TODO: Decide on value // Notification that a new keep has been created. @@ -118,7 +118,8 @@ contract FullyBackedBondedECDSAKeepFactory is /// @param _honestThreshold Minimum number of honest keep signers. /// @param _owner Address of the keep owner. /// @param _bond Value of ETH bond required from the keep in wei. - /// @param _stakeLockDuration Stake lock duration in seconds. + /// @param _stakeLockDuration Stake lock duration in seconds. Ignored by + /// this implementation. /// @return Created keep address. function openKeep( uint256 _groupSize, diff --git a/solidity/contracts/fully-backed/FullyBackedBonding.sol b/solidity/contracts/fully-backed/FullyBackedBonding.sol index cd258e5ef..566cfb024 100644 --- a/solidity/contracts/fully-backed/FullyBackedBonding.sol +++ b/solidity/contracts/fully-backed/FullyBackedBonding.sol @@ -44,7 +44,7 @@ contract FullyBackedBonding is // TODO: Decide on the final value and if we want a setter for it. uint256 public constant MINIMUM_DELEGATION_DEPOSIT = 12345; - uint256 public initializationPeriod; + uint256 public initializationPeriod; // varies between mainnet and testnet /// @notice Initializes Fully Backed Bonding contract. /// @param _keepRegistry Keep Registry contract address. From 360486ffbf13a8830b6a148d5484c952588dd613 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Sat, 26 Sep 2020 08:49:38 +0200 Subject: [PATCH 28/57] Lock bonding withdraw just after delegation As a protection from griefing we introduced a lock period that unbonded value is not possible to be withdrawn just after the initial delegation. --- .../fully-backed/FullyBackedBonding.sol | 33 +++++++++++++++++-- .../FullyBackedBondedECDSAKeepFactoryTest.js | 4 ++- .../test/FullyBackedBondedECDSAKeepTest.js | 2 ++ solidity/test/FullyBackedBondingTest.js | 29 +++++++++++++++- 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/solidity/contracts/fully-backed/FullyBackedBonding.sol b/solidity/contracts/fully-backed/FullyBackedBonding.sol index 566cfb024..29542a733 100644 --- a/solidity/contracts/fully-backed/FullyBackedBonding.sol +++ b/solidity/contracts/fully-backed/FullyBackedBonding.sol @@ -41,8 +41,13 @@ contract FullyBackedBonding is address indexed authorizer ); - // TODO: Decide on the final value and if we want a setter for it. - uint256 public constant MINIMUM_DELEGATION_DEPOSIT = 12345; + // The ether value (in wei) that should be passed along with the delegation + // and deposited for bonding. + uint256 public constant MINIMUM_DELEGATION_DEPOSIT = 12345; // TODO: Decide right value + + // Once a delegation to an operator is received the delegator has to wait for + // specific time period before being able to pull out the funds. + uint256 public constant DELEGATION_LOCK_PERIOD = 1 days; // TODO: Decide right value uint256 public initializationPeriod; // varies between mainnet and testnet @@ -121,7 +126,9 @@ contract FullyBackedBonding is /// This function can be called only by: /// - operator, /// - owner of the stake. - /// + /// Withdraw cannot be performed immediately after delegation to protect + /// from a griefing. It is required that delegator waits specific period + /// of time before they can pull out the funds deposited on delegation. /// @param amount Value to withdraw in wei. /// @param operator Address of the operator. function withdraw(uint256 amount, address operator) public { @@ -130,6 +137,11 @@ contract FullyBackedBonding is "Only operator or the owner is allowed to withdraw bond" ); + require( + hasDelegationLockPassed(operator), + "Delegation lock period has not passed yet" + ); + withdrawBond(amount, operator); } @@ -161,4 +173,19 @@ contract FullyBackedBonding is block.timestamp > operatorParams.getCreationTimestamp().add(initializationPeriod); } + + /// @notice Has lock period passed for a delegation. + /// @param operator Address of the operator. + /// @return True if delegation lock period passed, false otherwise. + function hasDelegationLockPassed(address operator) + internal + view + returns (bool) + { + return + block.timestamp > + operators[operator].packedParams.getCreationTimestamp().add( + DELEGATION_LOCK_PERIOD + ); + } } diff --git a/solidity/test/FullyBackedBondedECDSAKeepFactoryTest.js b/solidity/test/FullyBackedBondedECDSAKeepFactoryTest.js index c71be0590..08086a24c 100644 --- a/solidity/test/FullyBackedBondedECDSAKeepFactoryTest.js +++ b/solidity/test/FullyBackedBondedECDSAKeepFactoryTest.js @@ -56,6 +56,7 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { const stakeLockDuration = 0 // parameter is ignored by FullyBackedBondedECDSAKeepFactory implementation const delegationInitPeriod = time.duration.hours(12) + const delegationLockPeriod = time.duration.days(1) before(async () => { await FullyBackedSortitionPoolFactory.detectNetwork() @@ -1555,7 +1556,8 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { ) } - await time.increase(delegationInitPeriod.addn(1)) + // delegationLockPeriod > delegationInitPeriod so we wait the longer one. + await time.increase(delegationLockPeriod.addn(1)) } async function delegate(operator, beneficiary, authorizer, unbondedValue) { diff --git a/solidity/test/FullyBackedBondedECDSAKeepTest.js b/solidity/test/FullyBackedBondedECDSAKeepTest.js index 09b28d8db..52131a6c0 100644 --- a/solidity/test/FullyBackedBondedECDSAKeepTest.js +++ b/solidity/test/FullyBackedBondedECDSAKeepTest.js @@ -1642,6 +1642,8 @@ describe("FullyBackedBondedECDSAKeep", function () { await delegate(members[0], beneficiaries[0], authorizers[0]) await delegate(members[1], beneficiaries[1], authorizers[1]) await delegate(members[2], beneficiaries[2], authorizers[2]) + + await time.increase(await bonding.DELEGATION_LOCK_PERIOD.call()) } async function delegate(operator, beneficiary, authorizer, unbondedValue) { diff --git a/solidity/test/FullyBackedBondingTest.js b/solidity/test/FullyBackedBondingTest.js index 2f3491a33..1870709bd 100644 --- a/solidity/test/FullyBackedBondingTest.js +++ b/solidity/test/FullyBackedBondingTest.js @@ -227,11 +227,14 @@ describe("FullyBackedBonding", function () { }) describe("withdraw", async () => { - let initialDeposit const value = new BN(1000) + let initialDeposit + let delegationLockPeriod + beforeEach(async () => { initialDeposit = minimumDelegationValue + delegationLockPeriod = await bonding.DELEGATION_LOCK_PERIOD.call() await bonding.delegate(operator, beneficiary, authorizer, { from: owner, @@ -241,6 +244,8 @@ describe("FullyBackedBonding", function () { await bonding.authorizeOperatorContract(operator, bondCreator, { from: authorizer, }) + + await time.increase(delegationLockPeriod.addn(1)) }) it("can be called by operator", async () => { @@ -253,6 +258,26 @@ describe("FullyBackedBonding", function () { // ok, no reverts }) + it("cannot be called before delegation lock period passes", async () => { + const operator2 = await web3.eth.personal.newAccount("pass") + + await bonding.delegate(operator2, beneficiary, authorizer, { + from: owner, + value: initialDeposit, + }) + + await bonding.authorizeOperatorContract(operator2, bondCreator, { + from: authorizer, + }) + + await time.increase(delegationLockPeriod) + + await expectRevert( + bonding.withdraw(value, operator2, {from: owner}), + "Delegation lock period has not passed yet" + ) + }) + it("cannot be called by authorizer", async () => { await expectRevert( bonding.withdraw(value, operator, {from: authorizer}), @@ -334,6 +359,8 @@ describe("FullyBackedBonding", function () { value: initialDeposit, }) + await time.increase(delegationLockPeriod.addn(1)) + await expectRevert( bonding.withdraw(value, operator2, {from: operator2}), "Transfer failed" From 742d3cfe9baaf58ac4380fe40e268f8c82dca28d Mon Sep 17 00:00:00 2001 From: Piotr Dyraga Date: Tue, 27 Oct 2020 13:37:05 +0100 Subject: [PATCH 29/57] Refer to the most recent pre versions of keep dependencies Both keep-core and sortition-pools dependency have been updated to point to the most recent -pre versions. --- solidity/package-lock.json | 6823 ++++++++++++++++-------------------- solidity/package.json | 4 +- 2 files changed, 3099 insertions(+), 3728 deletions(-) diff --git a/solidity/package-lock.json b/solidity/package-lock.json index c9272d5a5..946ffc19b 100644 --- a/solidity/package-lock.json +++ b/solidity/package-lock.json @@ -872,6 +872,7 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.4.tgz", "integrity": "sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw==", + "dev": true, "requires": { "regenerator-runtime": "^0.13.4" }, @@ -879,7 +880,8 @@ "regenerator-runtime": { "version": "0.13.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", + "dev": true } } }, @@ -956,9 +958,9 @@ } }, "@keep-network/sortition-pools": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@keep-network/sortition-pools/-/sortition-pools-1.1.2.tgz", - "integrity": "sha512-bBaKyxkXDc8kJHq3qeESMrJ02m+Wbh6Uz9qUpWn8Zq3aTZaKXRZfGWT+J71OiBlAdyB4WoHZymrddWHkjImHdQ==", + "version": "1.2.0-pre.3", + "resolved": "https://registry.npmjs.org/@keep-network/sortition-pools/-/sortition-pools-1.2.0-pre.3.tgz", + "integrity": "sha512-MlhhegYQ/bG/vA9IT8Vxgn+ojvluC0YENF+Ic3xJNP6Ir/MEWH6gC7rDeaILzOJdqSVV5/8I53aTbYSRwzHoSg==", "requires": { "@openzeppelin/contracts": "^2.4.0" } @@ -2112,14 +2114,6 @@ } } }, - "@types/bignumber.js": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/bignumber.js/-/bignumber.js-5.0.0.tgz", - "integrity": "sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA==", - "requires": { - "bignumber.js": "*" - } - }, "@types/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", @@ -2163,44 +2157,6 @@ "@types/underscore": "*" } }, - "@web3-js/scrypt-shim": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz", - "integrity": "sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw==", - "requires": { - "scryptsy": "^2.1.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "@web3-js/websocket": { - "version": "1.0.30", - "resolved": "https://registry.npmjs.org/@web3-js/websocket/-/websocket-1.0.30.tgz", - "integrity": "sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA==", - "requires": { - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "nan": "^2.14.0", - "typedarray-to-buffer": "^3.1.5", - "yaeti": "^0.0.6" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - } - } - }, "abstract-leveldown": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", @@ -2270,15 +2226,6 @@ } } }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -2293,11 +2240,6 @@ "color-convert": "^1.9.0" } }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" - }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -2308,6 +2250,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, + "optional": true, "requires": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" @@ -2318,6 +2261,7 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, + "optional": true, "requires": { "remove-trailing-separator": "^1.0.1" } @@ -2330,21 +2274,6 @@ "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=", "dev": true }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -2360,107 +2289,23 @@ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -2517,18 +2362,6 @@ "lodash": "^4.17.14" } }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - } - }, "async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", @@ -2549,15 +2382,6 @@ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3400,23 +3224,6 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, "backoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", @@ -3787,12 +3594,6 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -3976,6 +3777,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", "dev": true, + "optional": true, "requires": { "anymatch": "^2.0.0", "async-each": "^1.0.1", @@ -4092,12 +3894,6 @@ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -4106,23 +3902,6 @@ "mimic-response": "^1.0.0" } }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", - "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - } - }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -4153,28 +3932,6 @@ } } }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - } - } - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -4198,12 +3955,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -4302,16 +4053,6 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, - "copy-props": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", - "dev": true, - "requires": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" - } - }, "core-js": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", @@ -4633,29 +4374,6 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true - }, "defer-to-connect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.0.2.tgz", @@ -4754,12 +4472,6 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", @@ -4829,28 +4541,6 @@ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -4925,15 +4615,6 @@ "prr": "~1.0.1" } }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, "es-abstract": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", @@ -4986,18 +4667,6 @@ "es5-ext": "^0.10.51" } }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -6191,15 +5860,6 @@ } } }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -6373,18 +6033,6 @@ "checkpoint-store": "^1.1.0" } }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -6540,37 +6188,6 @@ } } }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, "flat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", @@ -6605,16 +6222,6 @@ "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, "follow-redirects": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", @@ -6706,16 +6313,6 @@ "minipass": "^2.6.0" } }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, "fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", @@ -7362,12 +6959,15 @@ "json5": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==" + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "requires": { + "minimist": "^1.2.0" + } }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "semver": { "version": "5.7.1", @@ -7422,53 +7022,6 @@ "@babel/types": "^7.8.3" } }, - "@babel/helper-member-expression-to-functions": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", - "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==" - }, - "@babel/helper-module-imports": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", - "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==" - }, - "@babel/helper-module-transforms": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", - "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "lodash": "^4.17.19" - }, - "dependencies": { - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - } - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==" - }, - "@babel/helper-replace-supers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", - "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", - "requires": { - "@babel/helper-member-expression-to-functions": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4" - } - }, - "@babel/helper-simple-access": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", - "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==" - }, "@babel/helper-split-export-declaration": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", @@ -7477,11 +7030,6 @@ "@babel/types": "^7.8.3" } }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" - }, "@babel/helpers": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.3.tgz", @@ -7540,6 +7088,21 @@ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==" }, + "@babel/runtime": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.3.tgz", + "integrity": "sha512-fVHx1rzEmwB130VTkLnxR+HmxcTjGzH12LYQcFFoBwakMd3aOMD4OsRN7tGG/UOYE2ektgFrS8uACAoRk1CY0w==", + "requires": { + "regenerator-runtime": "^0.13.2" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", + "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" + } + } + }, "@babel/template": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", @@ -7578,11 +7141,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" } } }, @@ -7596,11 +7154,6 @@ "to-fast-properties": "^2.0.0" }, "dependencies": { - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -7608,156 +7161,22 @@ } } }, - "@ethersproject/abi": { - "version": "5.0.0-beta.153", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz", - "integrity": "sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg==", - "requires": { - "@ethersproject/address": ">=5.0.0-beta.128", - "@ethersproject/bignumber": ">=5.0.0-beta.130", - "@ethersproject/bytes": ">=5.0.0-beta.129", - "@ethersproject/constants": ">=5.0.0-beta.128", - "@ethersproject/hash": ">=5.0.0-beta.128", - "@ethersproject/keccak256": ">=5.0.0-beta.127", - "@ethersproject/logger": ">=5.0.0-beta.129", - "@ethersproject/properties": ">=5.0.0-beta.131", - "@ethersproject/strings": ">=5.0.0-beta.130" - } - }, - "@ethersproject/address": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.4.tgz", - "integrity": "sha512-CIjAeG6zNehbpJTi0sgwUvaH2ZICiAV9XkCBaFy5tjuEVFpQNeqd6f+B7RowcNO7Eut+QbhcQ5CVLkmP5zhL9A==", - "requires": { - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/rlp": "^5.0.3", - "bn.js": "^4.4.0" - } - }, - "@ethersproject/bignumber": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.7.tgz", - "integrity": "sha512-wwKgDJ+KA7IpgJwc8Fc0AjKIRuDskKA2cque29/+SgII9/1K/38JpqVNPKIovkLwTC2DDofIyzHcxeaKpMFouQ==", - "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "bn.js": "^4.4.0" - } - }, - "@ethersproject/bytes": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.4.tgz", - "integrity": "sha512-9R6A6l9JN8x1U4s1dJCR+9h3MZTT3xQofr/Xx8wbDvj6NnY4CbBB0o8ZgHXvR74yV90pY2EzCekpkMBJnRzkSw==", - "requires": { - "@ethersproject/logger": "^5.0.5" - } - }, - "@ethersproject/constants": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.4.tgz", - "integrity": "sha512-Df32lcXDHPgZRPgp1dgmByNbNe4Ki1QoXR+wU61on5nggQGTqWR1Bb7pp9VtI5Go9kyE/JflFc4Te6o9MvYt8A==", - "requires": { - "@ethersproject/bignumber": "^5.0.7" - } - }, - "@ethersproject/hash": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.4.tgz", - "integrity": "sha512-VCs/bFBU8AQFhHcT1cQH6x7a4zjulR6fJmAOcPxUgrN7bxOQ7QkpBKF+YCDJhFtkLdaljIsr/r831TuWU4Ysfg==", - "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/strings": "^5.0.4" - } - }, - "@ethersproject/keccak256": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.3.tgz", - "integrity": "sha512-VhW3mgZMBZlETV6AyOmjNeNG+Pg68igiKkPpat8/FZl0CKnfgQ+KZQZ/ee1vT+X0IUM8/djqnei6btmtbA27Ug==", - "requires": { - "@ethersproject/bytes": "^5.0.4", - "js-sha3": "0.5.7" - }, - "dependencies": { - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" - } - } - }, - "@ethersproject/logger": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.5.tgz", - "integrity": "sha512-gJj72WGzQhUtCk6kfvI8elTaPOQyMvrMghp/nbz0ivTo39fZ7IjypFh/ySDeUSdBNplAwhzWKKejQhdpyefg/w==" - }, - "@ethersproject/properties": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.3.tgz", - "integrity": "sha512-wLCSrbywkQgTO6tIF9ZdKsH9AIxPEqAJF/z5xcPkz1DK4mMAZgAXRNw1MrKYhyb+7CqNHbj3vxenNKFavGY/IA==", - "requires": { - "@ethersproject/logger": "^5.0.5" - } - }, - "@ethersproject/rlp": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.3.tgz", - "integrity": "sha512-Hz4yyA/ilGafASAqtTlLWkA/YqwhQmhbDAq2LSIp1AJNx+wtbKWFAKSckpeZ+WG/xZmT+fw5OFKK7a5IZ4DR5g==", - "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5" - } - }, - "@ethersproject/signing-key": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.4.tgz", - "integrity": "sha512-I6pJoga1IvhtjYK5yXzCjs4ZpxrVbt9ZRAlpEw0SW9UuV020YfJH5EIVEGR2evdRceS3nAQIggqbsXSkP8Y1Dg==", - "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3" - } - }, - "@ethersproject/strings": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.4.tgz", - "integrity": "sha512-azXFHaNkDXzefhr4LVVzzDMFwj3kH9EOKlATu51HjxabQafuUyVLPFgmxRFmCynnAi0Bmmp7nr+qK1pVDgRDLQ==", - "requires": { - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/logger": "^5.0.5" - } - }, - "@ethersproject/transactions": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.5.tgz", - "integrity": "sha512-1Ga/QmbcB74DItggP8/DK1tggu4ErEvwTkIwIlUXUcvIAuRNXXE7kgQhlp+w1xA/SAQFhv56SqCoyqPiiLCvVA==", - "requires": { - "@ethersproject/address": "^5.0.4", - "@ethersproject/bignumber": "^5.0.7", - "@ethersproject/bytes": "^5.0.4", - "@ethersproject/constants": "^5.0.4", - "@ethersproject/keccak256": "^5.0.3", - "@ethersproject/logger": "^5.0.5", - "@ethersproject/properties": "^5.0.3", - "@ethersproject/rlp": "^5.0.3", - "@ethersproject/signing-key": "^5.0.4" - } - }, "@istanbuljs/load-nyc-config": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", "requires": { + "camelcase": "^5.3.1", "find-up": "^4.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" }, "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -7834,6 +7253,14 @@ "defer-to-connect": "^1.0.1" } }, + "@types/bignumber.js": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/bignumber.js/-/bignumber.js-5.0.0.tgz", + "integrity": "sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA==", + "requires": { + "bignumber.js": "*" + } + }, "@types/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", @@ -7847,11 +7274,6 @@ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, - "@types/json-schema": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==" - }, "@types/node": { "version": "13.5.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.5.2.tgz", @@ -7862,28 +7284,65 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, - "@types/pbkdf2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", - "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "@types/web3": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/web3/-/web3-1.2.2.tgz", + "integrity": "sha512-eFiYJKggNrOl0nsD+9cMh2MLk4zVBfXfGnVeRFbpiZzBE20eet4KLA3fXcjSuHaBn0RnQzwLAGdgzgzdet4C0A==", "requires": { - "@types/node": "*" + "web3": "*" } }, - "@types/secp256k1": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", - "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", + "@web3-js/scrypt-shim": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz", + "integrity": "sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw==", "requires": { - "@types/node": "*" + "scryptsy": "^2.1.0", + "semver": "^6.3.0" + }, + "dependencies": { + "scryptsy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz", + "integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==" + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } } }, - "@types/web3": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/web3/-/web3-1.2.2.tgz", - "integrity": "sha512-eFiYJKggNrOl0nsD+9cMh2MLk4zVBfXfGnVeRFbpiZzBE20eet4KLA3fXcjSuHaBn0RnQzwLAGdgzgzdet4C0A==", + "@web3-js/websocket": { + "version": "1.0.30", + "resolved": "https://registry.npmjs.org/@web3-js/websocket/-/websocket-1.0.30.tgz", + "integrity": "sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA==", "requires": { - "web3": "*" + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "nan": "^2.14.0", + "typedarray-to-buffer": "^3.1.5", + "yaeti": "^0.0.6" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + } } }, "@webassemblyjs/ast": { @@ -8130,6 +7589,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, "requires": { "ansi-wrap": "^0.1.0" } @@ -8140,13 +7600,15 @@ "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", "requires": { "type-fest": "^0.8.1" - }, - "dependencies": { - "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==" - } + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" } }, "ansi-regex": { @@ -8159,11 +7621,22 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, "any-observable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==" }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, "anymatch": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", @@ -8173,6 +7646,15 @@ "normalize-path": "^2.1.1" } }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, "append-transform": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", @@ -8204,16 +7686,40 @@ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -8229,6 +7735,66 @@ "is-string": "^1.0.5" } }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -8304,6 +7870,18 @@ "lodash": "^4.17.11" } }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, "async-each": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", @@ -8323,6 +7901,15 @@ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "requires": { + "async-done": "^1.2.2" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -9053,6 +8640,23 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, "backoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", @@ -9121,6 +8725,8 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.7.tgz", "integrity": "sha512-zAKJGuQPihXW22fkrfOclUUZXM2g92z5GzlSMHxhO6r6Qj+Nm0ccaGNBzDZojzwOMkpjAv4J0fOv1U4go+a4iw==", + "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.0.1" } @@ -9160,6 +8766,14 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bip39": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/bip39/-/bip39-2.5.0.tgz", @@ -9173,10 +8787,22 @@ "unorm": "^1.3.3" } }, - "blakejs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", - "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" + "bip66": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", + "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } }, "bluebird": { "version": "3.7.2", @@ -9236,6 +8862,7 @@ "requires": { "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", @@ -9243,6 +8870,16 @@ "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "brorand": { @@ -9307,6 +8944,16 @@ "randombytes": "^2.0.1" } }, + "browserify-sha3": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/browserify-sha3/-/browserify-sha3-0.0.4.tgz", + "integrity": "sha1-CGxHuMgjFsnUcCLCYYWVRXbdjiY=", + "dev": true, + "requires": { + "js-sha3": "^0.6.1", + "safe-buffer": "^5.1.1" + } + }, "browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", @@ -9319,13 +8966,6 @@ "elliptic": "^6.0.0", "inherits": "^2.0.1", "parse-asn1": "^5.0.0" - }, - "dependencies": { - "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" - } } }, "browserify-zlib": { @@ -9350,6 +8990,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "dev": true, + "optional": true, "requires": { "base-x": "^3.0.2" } @@ -9358,6 +9000,8 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, + "optional": true, "requires": { "bs58": "^4.0.0", "create-hash": "^1.1.0", @@ -9373,6 +9017,36 @@ "ieee754": "^1.1.4" } }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -9388,21 +9062,6 @@ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, - "bufferutil": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", - "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", - "requires": { - "node-gyp-build": "~3.7.0" - }, - "dependencies": { - "node-gyp-build": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", - "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==" - } - } - }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -9443,6 +9102,7 @@ "glob": "^7.1.4", "graceful-fs": "^4.2.2", "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", "minipass": "^3.0.0", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", @@ -9464,6 +9124,21 @@ "minipass": "^3.0.0" } }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, "minipass": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.1.tgz", @@ -9558,15 +9233,6 @@ "requires": { "xtend": "~4.0.0" } - }, - "lru-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", - "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", - "dev": true, - "requires": { - "pseudomap": "^1.0.1" - } } } }, @@ -9576,8 +9242,24 @@ "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "requires": { "hasha": "^5.0.0", + "make-dir": "^3.0.0", "package-hash": "^4.0.0", "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } } }, "callsites": { @@ -9588,7 +9270,8 @@ "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true }, "caniuse-lite": { "version": "1.0.30001023", @@ -9640,9 +9323,17 @@ "inherits": "^2.0.3", "is-binary-path": "^1.0.0", "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", "path-is-absolute": "^1.0.0", "readdirp": "^2.2.1", "upath": "^1.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + } } }, "chownr": { @@ -9663,27 +9354,6 @@ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" }, - "cids": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", - "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", - "requires": { - "class-is": "^1.1.0", - "multibase": "~0.6.0", - "multicodec": "^1.0.0", - "multihashes": "~0.4.15" - }, - "dependencies": { - "multicodec": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", - "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", - "requires": { - "varint": "^5.0.0" - } - } - } - }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", @@ -9693,11 +9363,6 @@ "safe-buffer": "^5.0.1" } }, - "class-is": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", - "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==" - }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -9741,28 +9406,10 @@ "string-width": "^1.0.1" }, "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, "slice-ansi": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } } } }, @@ -9775,63 +9422,11 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - } } }, "clone": { @@ -9840,6 +9435,12 @@ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -9848,11 +9449,59 @@ "mimic-response": "^1.0.0" } }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, + "coinstring": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/coinstring/-/coinstring-2.3.0.tgz", + "integrity": "sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q=", + "dev": true, + "optional": true, + "requires": { + "bs58": "^2.0.1", + "create-hash": "^1.1.1" + }, + "dependencies": { + "bs58": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.1.tgz", + "integrity": "sha1-VZCNWPGYKrogCPob7Y+RmYopv40=", + "dev": true, + "optional": true + } + } + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -9875,6 +9524,12 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -9920,40 +9575,6 @@ "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "console-browserify": { @@ -9986,16 +9607,6 @@ } } }, - "content-hash": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", - "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", - "requires": { - "cids": "^0.7.1", - "multicodec": "^0.5.5", - "multihashes": "^0.4.15" - } - }, "content-type": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", @@ -10059,6 +9670,16 @@ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, "core-js": { "version": "2.6.11", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", @@ -10122,7 +9743,15 @@ "js-yaml": "^3.13.1", "lcov-parse": "^1.0.0", "log-driver": "^1.2.7", + "minimist": "^1.2.0", "request": "^2.88.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } } }, "create-ecdh": { @@ -10183,7 +9812,18 @@ "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", "requires": { "path-key": "^3.1.0", - "shebang-command": "^2.0.0" + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } } }, "crypto-browserify": { @@ -10213,7 +9853,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, "requires": { "es5-ext": "^0.10.50", "type": "^1.0.1" @@ -10250,6 +9889,28 @@ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, + "decompress": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.0.tgz", + "integrity": "sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=", + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, "decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", @@ -10258,21 +9919,92 @@ "mimic-response": "^1.0.0" } }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=" + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + } }, - "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha1-3qrM39FK6vhVePczroIQ+bSEj2k=", + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" + }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=" + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", "object-keys": "^1.1.1", "regexp.prototype.flags": "^1.2.0" }, @@ -10290,6 +10022,23 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "default-require-extensions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", @@ -10305,6 +10054,12 @@ } } }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true + }, "defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -10468,6 +10223,16 @@ "minimatch": "^3.0.4" } }, + "drbg.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", + "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", + "requires": { + "browserify-aes": "^1.0.6", + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4" + } + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -10482,40 +10247,16 @@ "inherits": "^2.0.1", "readable-stream": "^2.0.0", "stream-shift": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" } }, "ecc-jsbn": { @@ -10579,17 +10320,6 @@ "dev": true, "requires": { "iconv-lite": "~0.4.13" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } } }, "encoding-down": { @@ -10634,11 +10364,6 @@ "tapable": "^1.0.0" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, "memory-fs": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", @@ -10647,33 +10372,6 @@ "errno": "^0.1.3", "readable-stream": "^2.0.1" } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } } } }, @@ -10732,7 +10430,6 @@ "version": "0.10.53", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.3", @@ -10748,7 +10445,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, "requires": { "d": "1", "es5-ext": "^0.10.35", @@ -10759,12 +10455,23 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, "requires": { "d": "^1.0.1", "ext": "^1.1.2" } }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -10794,6 +10501,7 @@ "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", "globals": "^12.1.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", @@ -10868,6 +10576,14 @@ "ms": "^2.1.1" } }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "requires": { + "is-glob": "^4.0.1" + } + }, "globals": { "version": "12.3.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", @@ -10922,14 +10638,6 @@ "requires": { "has-flag": "^3.0.0" } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } } } }, @@ -11025,6 +10733,7 @@ "has": "^1.0.3", "minimatch": "^3.0.4", "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", "resolve": "^1.12.0" }, "dependencies": { @@ -11045,15 +10754,71 @@ "isarray": "^1.0.0" } }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" } } }, @@ -11143,13 +10908,6 @@ "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "requires": { "estraverse": "^4.0.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" - } } }, "esrecurse": { @@ -11158,13 +10916,6 @@ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "requires": { "estraverse": "^4.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" - } } }, "estraverse": { @@ -11441,6 +11192,12 @@ } } } + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true } } }, @@ -11703,6 +11460,12 @@ } } } + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true } } }, @@ -11718,21 +11481,12 @@ "miller-rabin": "^4.0.0" }, "dependencies": { - "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, - "buffer-xor": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-2.0.2.tgz", - "integrity": "sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.1" - } - }, "ethereumjs-util": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", @@ -11769,25 +11523,6 @@ "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", "dev": true }, - "ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "requires": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "setimmediate": "^1.0.5" - } - }, "ethereumjs-abi": { "version": "0.6.7", "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.7.tgz", @@ -11857,6 +11592,21 @@ "semaphore": "^1.1.0" }, "dependencies": { + "ethereumjs-util": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz", + "integrity": "sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q==", + "dev": true, + "requires": { + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^1.0.2", + "rlp": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -11906,6 +11656,11 @@ "nan": "^2.14.0", "safe-buffer": "^5.2.0" } + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" } } }, @@ -11930,6 +11685,41 @@ "rustbn.js": "~0.2.0", "safe-buffer": "^5.1.1", "util.promisify": "^1.0.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz", + "integrity": "sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ==", + "dev": true, + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "ethjs-util": "0.1.6", + "keccak": "^2.0.0", + "rlp": "^2.2.3", + "secp256k1": "^3.0.1" + } + }, + "keccak": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", + "integrity": "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==", + "dev": true, + "requires": { + "bindings": "^1.5.0", + "inherits": "^2.0.4", + "nan": "^2.14.0", + "safe-buffer": "^5.2.0" + } + }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true + } } }, "ethereumjs-wallet": { @@ -11971,20 +11761,6 @@ "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" }, - "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", - "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, "hash.js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", @@ -12211,7 +11987,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, "requires": { "type": "^2.0.0" }, @@ -12219,8 +11994,7 @@ "type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", - "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", - "dev": true + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==" } } }, @@ -12341,6 +12115,18 @@ "checkpoint-store": "^1.1.0" } }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, "fast-deep-equal": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", @@ -12356,6 +12142,14 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, "fetch-ponyfill": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz", @@ -12398,6 +12192,16 @@ "flat-cache": "^2.0.1" } }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha1-LdvqfHP/42No365J3DOMBYwritY=" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, "filesize": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", @@ -12408,9 +12212,20 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "requires": { + "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "finalhandler": { @@ -12448,6 +12263,7 @@ "integrity": "sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg==", "requires": { "commondir": "^1.0.1", + "make-dir": "^3.0.0", "pkg-dir": "^4.1.0" }, "dependencies": { @@ -12468,6 +12284,14 @@ "p-locate": "^4.1.0" } }, + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "requires": { + "semver": "^6.0.0" + } + }, "p-limit": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", @@ -12501,6 +12325,11 @@ "requires": { "find-up": "^4.0.0" } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -12508,6 +12337,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, "requires": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" @@ -12522,114 +12352,41 @@ "is-glob": "^4.0.0", "micromatch": "^3.0.4", "resolve-dir": "^1.0.1" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "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" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "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" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } } }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, "flat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==" + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "requires": { + "is-buffer": "~2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" + } + } }, "flat-cache": { "version": "2.0.1", @@ -12669,40 +12426,6 @@ "requires": { "inherits": "^2.0.3", "readable-stream": "^2.3.6" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "for-each": { @@ -12719,6 +12442,15 @@ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, "foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", @@ -12768,40 +12500,6 @@ "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "fromentries": { @@ -12809,6 +12507,11 @@ "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==" }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "fs-extra": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", @@ -12827,6 +12530,16 @@ "minipass": "^2.6.0" } }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -12836,40 +12549,6 @@ "iferr": "^0.1.5", "imurmurhash": "^0.1.4", "readable-stream": "1 || 2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "fs.realpath": { @@ -12884,50 +12563,526 @@ "optional": true, "requires": { "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" - }, - "generic-pool": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.4.tgz", - "integrity": "sha1-+XGN7agvoSXtXEPjQcmiFadm2aM=" - }, - "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" - }, - "get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==" - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" + "nan": "^2.12.1", + "node-pre-gyp": "*" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "optional": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.3", + "bundled": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "bundled": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "optional": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "optional": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "optional": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.7", + "bundled": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "bundled": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "optional": true + }, + "semver": { + "version": "5.7.1", + "bundled": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "optional": true + }, + "tar": { + "version": "4.4.13", + "bundled": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "yallist": { + "version": "3.1.1", + "bundled": true, + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + }, + "generic-pool": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.0.4.tgz", + "integrity": "sha1-+XGN7agvoSXtXEPjQcmiFadm2aM=" + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==" + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" } }, "get-value": { @@ -12963,6 +13118,48 @@ "requires": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + } + }, + "glob-watcher": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", + "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "object.defaults": "^1.1.0" } }, "global": { @@ -12982,26 +13179,6 @@ "global-prefix": "^1.0.1", "is-windows": "^1.0.1", "resolve-dir": "^1.0.0" - }, - "dependencies": { - "global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "requires": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - } } }, "global-prefix": { @@ -13014,16 +13191,6 @@ "ini": "^1.3.4", "is-windows": "^1.0.1", "which": "^1.2.14" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - } } }, "globals": { @@ -13032,6 +13199,15 @@ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -13055,11 +13231,65 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" }, + "gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "dependencies": { + "gulp-cli": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.2.0.tgz", + "integrity": "sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.1.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.0.1", + "yargs": "^7.1.0" + } + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -13132,29 +13362,6 @@ "kind-of": "^4.0.0" }, "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -13199,6 +13406,18 @@ } } }, + "hdkey": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-1.1.1.tgz", + "integrity": "sha512-DvHZ5OuavsfWs5yfVJZestsnc3wzPvLWNk6c2nRUfo6X+OtxypGt20vDDf7Ba+MJzjL3KS1og2nw2eBbLCOUTA==", + "dev": true, + "optional": true, + "requires": { + "coinstring": "^2.0.0", + "safe-buffer": "^5.1.1", + "secp256k1": "^3.0.1" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -13460,8 +13679,7 @@ "immediate": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", - "dev": true + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" }, "import-fresh": { "version": "3.2.1", @@ -13494,7 +13712,8 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "requires": { - "p-locate": "^3.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, "p-limit": { @@ -13518,6 +13737,11 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", @@ -13577,6 +13801,7 @@ "mute-stream": "0.0.8", "run-async": "^2.2.0", "rxjs": "^6.5.3", + "string-width": "^4.1.0", "strip-ansi": "^5.1.0", "through": "^2.3.6" }, @@ -13604,35 +13829,49 @@ "supports-color": "^5.3.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "requires": { "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + } } }, "supports-color": { @@ -13662,13 +13901,24 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true }, "ipaddr.js": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -13677,11 +13927,6 @@ "kind-of": "^3.0.2" }, "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -13729,11 +13974,6 @@ "kind-of": "^3.0.2" }, "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -13817,15 +14057,34 @@ "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" }, - "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=" + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=" + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } }, "is-obj": { "version": "1.0.1", @@ -13876,6 +14135,15 @@ "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, "is-retry-allowed": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", @@ -13904,6 +14172,27 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -13977,11 +14266,20 @@ "archy": "^1.0.0", "cross-spawn": "^7.0.0", "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", "p-map": "^3.0.0", "rimraf": "^3.0.0", "uuid": "^3.3.3" }, "dependencies": { + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "requires": { + "semver": "^6.0.0" + } + }, "p-map": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", @@ -13997,6 +14295,11 @@ "requires": { "glob": "^7.1.3" } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -14006,6 +14309,7 @@ "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "requires": { "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", "supports-color": "^7.1.0" }, "dependencies": { @@ -14014,6 +14318,19 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, "supports-color": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", @@ -14092,7 +14409,8 @@ "js-sha3": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.6.1.tgz", - "integrity": "sha1-W4n3enR3Z5h39YxKB1JAk0sflcA=" + "integrity": "sha1-W4n3enR3Z5h39YxKB1JAk0sflcA=", + "dev": true }, "js-tokens": { "version": "3.0.2", @@ -14130,11 +14448,6 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, "json-rpc-engine": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz", @@ -14224,6 +14537,12 @@ "verror": "1.10.0" } }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, "keccak": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", @@ -14236,6 +14555,16 @@ "safe-buffer": "^5.1.0" } }, + "keccakjs": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.3.tgz", + "integrity": "sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg==", + "dev": true, + "requires": { + "browserify-sha3": "^0.0.4", + "sha3": "^1.2.2" + } + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -14257,10 +14586,30 @@ "graceful-fs": "^4.1.9" } }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, "requires": { "invert-kv": "^1.0.0" } @@ -14270,6 +14619,15 @@ "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=" }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } + }, "level-codec": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-9.0.1.tgz", @@ -14322,12 +14680,6 @@ "isarray": "0.0.1", "string_decoder": "~0.10.x" } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true } } }, @@ -14350,12 +14702,6 @@ "xtend": "~4.0.0" } }, - "immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", - "dev": true - }, "memdown": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/memdown/-/memdown-3.0.0.tgz", @@ -14415,12 +14761,6 @@ "xtend": "~4.0.0" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "level-iterator-stream": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz", @@ -14437,36 +14777,6 @@ "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.1.3.tgz", "integrity": "sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ=", "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } } } }, @@ -14500,12 +14810,6 @@ "string_decoder": "~0.10.x" } }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, "xtend": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", @@ -14548,12 +14852,6 @@ "inherits": "^2.0.3" } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "level-iterator-stream": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz", @@ -14564,36 +14862,6 @@ "readable-stream": "^2.3.6", "xtend": "^4.0.0" } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } } } }, @@ -14606,6 +14874,22 @@ "type-check": "~0.3.2" } }, + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -14617,12 +14901,15 @@ "integrity": "sha512-/MrZOLMnljjMHakxlRd1Z5Kr8wWWlrWFasye7HaTv5tx56icwzT/STRty8flMKsyzBGTfTa9QszNVPsDS/yOug==", "requires": { "chalk": "^3.0.0", + "commander": "^4.0.1", "cosmiconfig": "^6.0.0", "debug": "^4.1.1", "dedent": "^0.7.0", "execa": "^3.4.0", "listr": "^0.14.3", "log-symbols": "^3.0.0", + "micromatch": "^4.0.2", + "normalize-path": "^3.0.0", "please-upgrade-node": "^3.2.0", "stringify-object": "^3.3.0" }, @@ -14636,6 +14923,14 @@ "color-convert": "^2.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, "chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -14658,6 +14953,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "commander": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.0.tgz", + "integrity": "sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==" + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -14666,11 +14966,38 @@ "ms": "^2.1.1" } }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, "supports-color": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", @@ -14678,6 +15005,14 @@ "requires": { "has-flag": "^4.0.0" } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } } } }, @@ -14817,6 +15152,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -14828,7 +15164,8 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true } } }, @@ -14850,7 +15187,15 @@ "json5": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==" + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } }, @@ -14859,7 +15204,15 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "requires": { - "p-locate": "^2.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + } } }, "lodash": { @@ -14924,7 +15277,8 @@ "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", "requires": { "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0" + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" }, "dependencies": { "ansi-escapes": { @@ -14932,6 +15286,11 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -14940,6 +15299,11 @@ "restore-cursor": "^2.0.0" } }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", @@ -14961,6 +15325,32 @@ "onetime": "^2.0.0", "signal-exit": "^3.0.2" } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } } } }, @@ -14988,6 +15378,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", + "dev": true, "requires": { "pseudomap": "^1.0.1" } @@ -15001,14 +15392,26 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + }, "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" } } }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, "mamacro": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", @@ -15035,6 +15438,41 @@ "object-visit": "^1.0.0" } }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "dependencies": { + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -15082,11 +15520,6 @@ "level-supports": "~1.0.0", "xtend": "~4.0.0" } - }, - "immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" } } }, @@ -15097,40 +15530,6 @@ "requires": { "errno": "^0.1.3", "readable-stream": "^2.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "memorystream": { @@ -15194,12 +15593,6 @@ "secp256k1": "^3.0.1" } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "level-codec": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", @@ -15239,32 +15632,9 @@ "abstract-leveldown": "~2.7.1", "functional-red-black-tree": "^1.0.1", "immediate": "^3.2.3", - "inherits": "~2.0.1", - "ltgt": "~2.2.0", - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "~2.0.1", + "ltgt": "~2.2.0", + "safe-buffer": "~5.1.1" }, "dependencies": { "safe-buffer": { @@ -15280,23 +15650,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } } } }, @@ -15533,7 +15886,9 @@ "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.0.0.tgz", "integrity": "sha512-CirsOPbO3jU86YKjjMzFLcXIb5YiGLUrjrXFHoJ3e2z9vWiaZVCZQ2+gtRGMPWF+nFhN6AWwLM/juzAQ6KRkbA==", "requires": { + "ansi-colors": "3.2.3", "browser-stdout": "1.3.1", + "chokidar": "3.3.0", "debug": "3.2.6", "diff": "3.5.0", "escape-string-regexp": "1.0.5", @@ -15552,9 +15907,21 @@ "supports-color": "6.0.0", "which": "1.3.1", "wide-align": "1.1.3", + "yargs": "13.3.0", + "yargs-parser": "13.1.1", "yargs-unparser": "1.6.0" }, "dependencies": { + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==" + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -15563,6 +15930,33 @@ "color-convert": "^1.9.0" } }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==" + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -15583,6 +15977,44 @@ } } }, + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -15591,6 +16023,17 @@ "locate-path": "^3.0.0" } }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", @@ -15604,21 +16047,39 @@ "path-is-absolute": "^1.0.0" } }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "binary-extensions": "^2.0.0" } }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "requires": { - "p-locate": "^3.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, "log-symbols": { @@ -15629,11 +16090,6 @@ "chalk": "^2.0.1" } }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -15647,21 +16103,10 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "p-limit": { "version": "2.2.2", @@ -15684,6 +16129,42 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "requires": { + "picomatch": "^2.0.4" + } + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -15697,12 +16178,58 @@ "has-flag": "^3.0.0" } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "requires": { - "isexe": "^2.0.0" + "is-number": "^7.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -15745,40 +16272,22 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "multibase": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", - "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==" - }, - "multicodec": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", - "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", - "requires": { - "varint": "^5.0.0" - } - }, - "multihashes": { - "version": "0.4.21", - "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", - "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", - "requires": { - "multibase": "^0.7.0", - "varint": "^5.0.0" - }, - "dependencies": { - "multibase": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", - "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==" - } - } + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==" + }, "nano-json-stream-parser": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", @@ -15820,19 +16329,13 @@ "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, - "node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" - }, "node-environment-flags": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", @@ -15855,11 +16358,6 @@ "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", "dev": true }, - "node-gyp-build": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", - "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" - }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -15882,6 +16380,7 @@ "readable-stream": "^2.3.3", "stream-browserify": "^2.0.1", "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", "url": "^0.11.0", @@ -15899,6 +16398,11 @@ "isarray": "^1.0.0" } }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -15914,48 +16418,20 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "safe-buffer": "~5.2.0" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, "util": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "requires": { "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } } } } @@ -15999,6 +16475,15 @@ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -16050,6 +16535,7 @@ "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.0", "js-yaml": "^3.13.1", + "make-dir": "^3.0.0", "node-preload": "^0.2.0", "p-map": "^3.0.0", "process-on-spawn": "^1.0.0", @@ -16076,11 +16562,17 @@ "color-convert": "^2.0.1" } }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "requires": { + "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } @@ -16107,6 +16599,16 @@ "path-exists": "^4.0.0" } }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -16115,6 +16617,14 @@ "p-locate": "^4.1.0" } }, + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "requires": { + "semver": "^6.0.0" + } + }, "p-limit": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", @@ -16149,6 +16659,11 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -16162,6 +16677,21 @@ "glob": "^7.1.3" } }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -16170,15 +16700,26 @@ "ansi-regex": "^5.0.0" } }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "requires": { "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, "yargs": { "version": "15.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.1.0.tgz", @@ -16187,8 +16728,13 @@ "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", "yargs-parser": "^16.1.0" } }, @@ -16197,6 +16743,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", "requires": { + "camelcase": "^5.0.0", "decamelize": "^1.2.0" } } @@ -16230,11 +16777,6 @@ "is-descriptor": "^0.1.0" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -16281,22 +16823,6 @@ "object-keys": "^1.0.11" }, "dependencies": { - "es-abstract": { - "version": "1.18.0-next.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", - "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-negative-zero": "^2.0.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -16304,6 +16830,18 @@ } } }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, "object.getownpropertydescriptors": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", @@ -16313,6 +16851,16 @@ "es-abstract": "^1.17.0-next.1" } }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -16321,6 +16869,16 @@ "isobject": "^3.0.1" } }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, "object.values": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", @@ -16382,6 +16940,15 @@ "word-wrap": "~1.2.3" } }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -16397,75 +16964,9 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, "requires": { "lcid": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.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" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "^2.0.0" - } - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - } } }, "os-tmpdir": { @@ -16551,40 +17052,6 @@ "cyclist": "^1.0.1", "inherits": "^2.0.3", "readable-stream": "^2.1.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "parent-module": { @@ -16608,6 +17075,17 @@ "safe-buffer": "^5.1.1" } }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, "parse-headers": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", @@ -16621,6 +17099,12 @@ "error-ex": "^1.2.0" } }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -16650,6 +17134,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, "requires": { "pinkie-promise": "^2.0.0" } @@ -16669,6 +17154,21 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -16678,6 +17178,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "pify": "^2.0.0", @@ -16687,7 +17188,8 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true } } }, @@ -16703,6 +17205,11 @@ "sha.js": "^2.4.8" } }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -16711,18 +17218,43 @@ "picomatch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", - "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", - "optional": true + "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==" }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=" + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "requires": { + "find-up": "^2.1.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + } + } }, "please-upgrade-node": { "version": "3.2.0", @@ -16778,6 +17310,12 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==" }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -16839,7 +17377,8 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true }, "psl": { "version": "1.7.0", @@ -17014,6 +17553,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, "requires": { "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", @@ -17024,6 +17564,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, "requires": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" @@ -17036,8 +17577,31 @@ "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", + "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "readdirp": { @@ -17050,6 +17614,15 @@ "readable-stream": "^2.0.2" } }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -17130,6 +17703,27 @@ "es6-error": "^4.0.1" } }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -17154,6 +17748,23 @@ "is-finite": "^1.0.0" } }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -17201,7 +17812,8 @@ "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true }, "resolve": { "version": "1.14.2", @@ -17233,18 +17845,6 @@ "requires": { "expand-tilde": "^2.0.0", "global-modules": "^1.0.0" - }, - "dependencies": { - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - } } }, "resolve-from": { @@ -17252,6 +17852,15 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -17379,15 +17988,38 @@ "ajv-keywords": "^3.4.1" } }, + "scrypt": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", + "integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.0.8" + } + }, "scrypt-js": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=" }, + "scrypt.js": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.3.0.tgz", + "integrity": "sha512-42LTc1nyFsyv/o0gcHtDztrn+aqpkaCNt5Qh7ATBZfhEZU7IC/0oT/qbBH+uRNoAPvs2fwiOId68FDEoSRA8/A==", + "dev": true, + "optional": true, + "requires": { + "scrypt": "^6.0.2", + "scryptsy": "^1.2.1" + } + }, "scryptsy": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", + "dev": true, + "optional": true, "requires": { "pbkdf2": "^3.0.3" } @@ -17405,6 +18037,13 @@ "elliptic": "^6.5.2", "nan": "^2.14.0", "safe-buffer": "^5.1.2" + }, + "dependencies": { + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==" + } } }, "seedrandom": { @@ -17413,6 +18052,14 @@ "integrity": "sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg==", "dev": true }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "requires": { + "commander": "~2.8.1" + } + }, "semaphore": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", @@ -17429,6 +18076,15 @@ "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=" }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -17550,6 +18206,15 @@ "safe-buffer": "^5.0.1" } }, + "sha3": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.6.tgz", + "integrity": "sha512-KgLGmJGrmNB4JWVsAV11Yk6KbvsAiygWJc7t5IebWva/0NukNrjJqhtKhzy3Eiv2AKuGvhZZt7dt1mDo7HkoiQ==", + "dev": true, + "requires": { + "nan": "2.13.2" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -17719,11 +18384,6 @@ "kind-of": "^3.2.0" }, "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -17742,6 +18402,7 @@ "command-exists": "^1.2.8", "commander": "3.0.2", "fs-extra": "^0.30.0", + "js-sha3": "0.8.0", "memorystream": "^0.3.1", "require-from-string": "^2.0.0", "semver": "^5.5.0", @@ -17765,6 +18426,11 @@ "rimraf": "^2.2.8" } }, + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "jsonfile": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", @@ -17824,6 +18490,12 @@ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, "spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", @@ -17831,16 +18503,39 @@ "requires": { "foreground-child": "^2.0.0", "is-windows": "^1.0.2", + "make-dir": "^3.0.0", "rimraf": "^3.0.0", - "signal-exit": "^3.0.2" + "signal-exit": "^3.0.2", + "which": "^2.0.1" }, "dependencies": { + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "requires": { + "semver": "^6.0.0" + } + }, "rimraf": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.1.tgz", "integrity": "sha512-IQ4ikL8SjBiEDZfk+DFVwqRK8md24RWMEJkdSlgNLkyyAImcjf8SWvU1qFMDOb4igBClbTQ/ugPqXcRwdFTxZw==", "requires": { - "glob": "^7.1.3" + "glob": "^7.1.3" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" } } } @@ -17933,6 +18628,12 @@ } } }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -17964,40 +18665,6 @@ "requires": { "inherits": "~2.0.1", "readable-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "stream-each": { @@ -18009,6 +18676,12 @@ "stream-shift": "^1.0.0" } }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, "stream-http": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", @@ -18019,40 +18692,6 @@ "readable-stream": "^2.3.6", "to-arraybuffer": "^1.0.0", "xtend": "^4.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, "stream-shift": { @@ -18091,21 +18730,6 @@ "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - } } }, "string.prototype.trim": { @@ -18117,229 +18741,31 @@ "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", - "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } } }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - } + "function-bind": "^1.1.1" } }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "requires": { - "has-symbols": "^1.0.1" - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - } + "function-bind": "^1.1.1" } }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true }, "stringify-object": { "version": "3.3.0", @@ -18363,10 +18789,19 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, "requires": { "is-utf8": "^0.2.0" } }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "requires": { + "is-natural-number": "^4.0.1" + } + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -18395,6 +18830,16 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, "swarm-js": { "version": "0.1.39", "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.39.tgz", @@ -18539,26 +18984,11 @@ "through": "~2.3.8" }, "dependencies": { - "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true - }, - "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true } } }, @@ -18586,6 +19016,20 @@ } } }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, "temp": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.1.tgz", @@ -18663,42 +19107,24 @@ "requires": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", @@ -18721,11 +19147,26 @@ "rimraf": "^2.6.3" } }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=" }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", @@ -18740,11 +19181,6 @@ "kind-of": "^3.0.2" }, "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -18780,6 +19216,15 @@ "repeat-string": "^1.6.1" } }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + } + }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -18792,6 +19237,13 @@ "requires": { "psl": "^1.1.24", "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } } }, "trim-right": { @@ -18833,8 +19285,7 @@ "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" }, "type-check": { "version": "0.3.2", @@ -18897,11 +19348,49 @@ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" }, + "unbzip2-stream": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz", + "integrity": "sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==", + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, "underscore": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" }, + "undertaker": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", + "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true + }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -18929,6 +19418,16 @@ "imurmurhash": "^0.1.4" } }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -19043,21 +19542,6 @@ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" }, - "utf-8-validate": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz", - "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==", - "requires": { - "node-gyp-build": "~3.7.0" - }, - "dependencies": { - "node-gyp-build": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", - "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==" - } - } - }, "utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", @@ -19110,6 +19594,15 @@ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==" }, + "v8flags": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", + "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -19119,10 +19612,11 @@ "spdx-expression-parse": "^3.0.0" } }, - "varint": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.0.tgz", - "integrity": "sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8=" + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true }, "vary": { "version": "1.1.2", @@ -19139,6 +19633,60 @@ "extsprintf": "^1.2.0" } }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "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" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + } + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -19152,274 +19700,6 @@ "chokidar": "^2.0.2", "graceful-fs": "^4.1.2", "neo-async": "^2.5.0" - }, - "dependencies": { - "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", - "requires": { - "is-glob": "~4.0.1", - "readdirp": "~3.4.0" - } - }, - "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", - "optional": true, - "requires": { - "picomatch": "^2.2.1" - } - } - } - }, - "watchpack-chokidar2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", - "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", - "requires": { - "chokidar": "^2.1.8" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "optional": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "optional": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "optional": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "optional": true, - "requires": { - "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" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "optional": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "optional": true - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "optional": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "optional": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "optional": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "optional": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "optional": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "optional": true, - "requires": { - "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" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "optional": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "optional": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } } }, "web3": { @@ -19802,20 +20082,6 @@ "keccak": "^2.0.0", "rlp": "^2.2.3", "secp256k1": "^3.0.1" - }, - "dependencies": { - "keccak": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", - "integrity": "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==", - "dev": true, - "requires": { - "bindings": "^1.5.0", - "inherits": "^2.0.4", - "nan": "^2.14.0", - "safe-buffer": "^5.2.0" - } - } } } } @@ -19875,6 +20141,20 @@ "rlp": "^2.0.0", "safe-buffer": "^5.1.1", "secp256k1": "^3.0.1" + }, + "dependencies": { + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "dev": true, + "requires": { + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + } + } } }, "ethereumjs-vm": { @@ -19923,6 +20203,18 @@ "safe-buffer": "^5.1.1", "secp256k1": "^3.0.1" } + }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "dev": true, + "requires": { + "bindings": "^1.2.1", + "inherits": "^2.0.3", + "nan": "^2.2.1", + "safe-buffer": "^5.1.0" + } } } }, @@ -19949,70 +20241,28 @@ "keccak": "^2.0.0", "rlp": "^2.2.3", "secp256k1": "^3.0.1" - }, - "dependencies": { - "keccak": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", - "integrity": "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==", - "dev": true, - "requires": { - "bindings": "^1.5.0", - "inherits": "^2.0.4", - "nan": "^2.14.0", - "safe-buffer": "^5.2.0" - } - } } } } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "keccak": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-2.1.0.tgz", + "integrity": "sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } + "bindings": "^1.5.0", + "inherits": "^2.0.4", + "nan": "^2.14.0", + "safe-buffer": "^5.2.0" } }, + "nan": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "dev": true + }, "ws": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", @@ -20126,33 +20376,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "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" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "cacache": { "version": "12.0.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", @@ -20164,13 +20387,15 @@ "glob": "^7.1.4", "graceful-fs": "^4.1.15", "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.3", "ssri": "^6.0.1", - "unique-filename": "^1.1.1" + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" } }, "eslint-scope": { @@ -20182,27 +20407,6 @@ "estraverse": "^4.1.1" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "find-cache-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", @@ -20221,35 +20425,21 @@ "locate-path": "^3.0.0" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "requires": { - "p-locate": "^3.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" } }, "make-dir": { @@ -20261,26 +20451,6 @@ "semver": "^5.6.0" } }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "requires": { - "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" - } - }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -20310,6 +20480,11 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", @@ -20333,14 +20508,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "requires": { - "randombytes": "^2.1.0" - } - }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", @@ -20365,14 +20532,10 @@ "worker-farm": "^1.7.0" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" } } }, @@ -20402,6 +20565,7 @@ "cross-spawn": "6.0.5", "enhanced-resolve": "4.1.0", "findup-sync": "3.0.0", + "global-modules": "2.0.0", "import-local": "2.0.0", "interpret": "1.2.0", "loader-utils": "1.2.3", @@ -20423,6 +20587,11 @@ "color-convert": "^1.9.0" } }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -20443,6 +20612,16 @@ } } }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -20460,11 +20639,6 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" - }, "enhanced-resolve": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", @@ -20475,6 +20649,20 @@ "tapable": "^1.0.0" } }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.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" + } + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -20483,24 +20671,45 @@ "locate-path": "^3.0.0" } }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==" + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==" - }, - "loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "requires": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" + "invert-kv": "^2.0.0" } }, "locate-path": { @@ -20508,7 +20717,26 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "requires": { - "p-locate": "^3.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" } }, "p-limit": { @@ -20532,11 +20760,21 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -20586,23 +20824,51 @@ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz", "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==" }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "requires": { - "isexe": "^2.0.0" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" } }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, "yargs": { "version": "13.2.4", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", "requires": { + "cliui": "^5.0.0", "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^3.0.0" + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.0" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -20663,7 +20929,8 @@ "which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true }, "which-pm-runs": { "version": "1.0.0", @@ -20676,35 +20943,6 @@ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "requires": { "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } } }, "word-wrap": { @@ -20724,38 +20962,10 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } } }, "wrappy": { @@ -20863,13 +21073,13 @@ "y18n": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true }, "yaeti": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", - "dev": true + "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" }, "yallist": { "version": "3.1.1", @@ -20888,6 +21098,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, "requires": { "camelcase": "^3.0.0", "cliui": "^3.2.0", @@ -20902,6 +21113,25 @@ "which-module": "^1.0.0", "y18n": "^3.2.1", "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "^3.0.0" + } + }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" }, "dependencies": { "ansi-regex": { @@ -20909,6 +21139,29 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -20922,6 +21175,11 @@ "locate-path": "^3.0.0" } }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -20932,13 +21190,19 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "requires": { - "p-locate": "^3.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", "requires": { "p-try": "^2.0.0" } @@ -20956,6 +21220,16 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -20973,31 +21247,62 @@ "requires": { "ansi-regex": "^4.1.0" } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, - "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "requires": { - "camelcase": "^3.0.0" - } - }, - "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - } + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" } } } @@ -21064,326 +21369,112 @@ "dependencies": { "glob-parent": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - } - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, - "global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "requires": { - "min-document": "^2.19.0", - "process": "~0.5.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "dependencies": { - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } - } - } - }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - }, - "dependencies": { - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "homedir-polyfill": "^1.0.1" + "is-glob": "^2.0.0" } }, - "which-module": { + "is-extglob": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", "dev": true }, - "yargs": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", - "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "5.0.0-security.0" + "is-extglob": "^1.0.0" } - }, - "yargs-parser": { - "version": "5.0.0-security.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", - "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, + "optional": true, "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" + "is-extglob": "^2.1.0" } } } }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "requires": { + "min-document": "^2.19.0", + "process": "~0.5.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", "requires": { - "glogg": "^1.0.0" + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + } } }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -21642,12 +21733,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, "inquirer": { "version": "7.3.3", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", @@ -21742,12 +21827,6 @@ } } }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -21768,16 +21847,6 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -21804,12 +21873,6 @@ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", "dev": true }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -21943,12 +22006,6 @@ "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -22008,15 +22065,6 @@ "has": "^1.0.1" } }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, "is-retry-allowed": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", @@ -22040,26 +22088,6 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -22266,12 +22294,6 @@ "verror": "1.10.0" } }, - "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, "keccak": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", @@ -22316,25 +22338,6 @@ "graceful-fs": "^4.1.9" } }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", @@ -22344,15 +22347,6 @@ "invert-kv": "^1.0.0" } }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } - }, "level-codec": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", @@ -22490,43 +22484,6 @@ "type-check": "~0.3.2" } }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -22708,15 +22665,6 @@ "semver": "^5.6.0" } }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -22732,41 +22680,6 @@ "object-visit": "^1.0.0" } }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, "math-random": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", @@ -23380,12 +23293,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true - }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -23483,18 +23390,6 @@ "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-1.0.3.tgz", "integrity": "sha512-FlUlqwRK6reQCaFLAhMcF+6VkVG2caYjKQY3YsRDTl4/SEch595Qb3oLjJRDr8dkHAAOVj2pOx3VknfnSgkE5g==" }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -23506,15 +23401,6 @@ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "requires": { - "once": "^1.3.2" - } - }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -23625,29 +23511,6 @@ "object-keys": "^1.0.11" } }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - } - } - }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -23655,28 +23518,7 @@ "dev": true, "requires": { "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - } + "es-abstract": "^1.5.1" } }, "object.omit": { @@ -23698,27 +23540,6 @@ "isobject": "^3.0.1" } }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - } - } - }, "oboe": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.4.tgz", @@ -23770,15 +23591,6 @@ "word-wrap": "~1.2.3" } }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, "original-require": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/original-require/-/original-require-1.0.1.tgz", @@ -23922,17 +23734,6 @@ "integrity": "sha512-OZQaqKaQnR21iqhlnPfVisFjBWjhnMl5J9MgbP8xC+EwoVqbXrq78lp+9Zb3ahmLzrIX5Us/qbvBnaS3hkH6OA==", "dev": true }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", @@ -23971,21 +23772,6 @@ "string.prototype.trim": "^1.1.2" } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -24007,7 +23793,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true + "dev": true, + "optional": true }, "path-exists": { "version": "3.0.0", @@ -24031,45 +23818,11 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", @@ -24278,12 +24031,6 @@ } } }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -24364,29 +24111,6 @@ "once": "^1.3.1" } }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -24465,48 +24189,6 @@ "unpipe": "1.0.0" } }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", @@ -24532,15 +24214,6 @@ "readable-stream": "^2.0.2" } }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -24702,27 +24375,6 @@ } } }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -24750,23 +24402,6 @@ "is-finite": "^1.0.0" } }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -24833,31 +24468,12 @@ "path-parse": "^1.0.6" } }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } - }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -25087,15 +24703,6 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } - }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -25585,44 +25192,6 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", - "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", - "dev": true - }, "spinnies": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/spinnies/-/spinnies-0.4.3.tgz", @@ -25679,12 +25248,6 @@ "tweetnacl": "~0.14.0" } }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -25711,18 +25274,6 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -25770,6 +25321,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, "requires": { "define-properties": "^1.1.3", "function-bind": "^1.1.1" @@ -25779,6 +25331,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, "requires": { "define-properties": "^1.1.3", "function-bind": "^1.1.1" @@ -25801,15 +25354,6 @@ "ansi-regex": "^2.0.0" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, "strip-dirs": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", @@ -25847,16 +25391,6 @@ "has-flag": "^3.0.0" } }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, "swarm-js": { "version": "0.1.39", "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.39.tgz", @@ -26170,22 +25704,6 @@ "xtend": "~4.0.1" } }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", @@ -26200,16 +25718,6 @@ "os-tmpdir": "~1.0.2" } }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, "to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", @@ -26268,15 +25776,6 @@ "repeat-string": "^1.6.1" } }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "^2.0.3" - } - }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -26532,49 +26031,11 @@ "through": "^2.3.8" } }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, "underscore": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" }, - "undertaker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", - "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "fast-levenshtein": "^1.0.0", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - }, - "dependencies": { - "fast-levenshtein": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", - "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=", - "dev": true - } - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -26615,16 +26076,6 @@ "set-value": "^2.0.1" } }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -26685,7 +26136,8 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", - "dev": true + "dev": true, + "optional": true }, "uri-js": { "version": "4.2.2", @@ -26760,22 +26212,6 @@ "homedir-polyfill": "^1.0.1" } }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -26791,71 +26227,6 @@ "extsprintf": "^1.2.0" } }, - "vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", - "dev": true, - "requires": { - "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" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, "web3": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.1.tgz", @@ -27229,7 +26600,7 @@ } }, "websocket": { - "version": "github:web3-js/WebSocket-Node#ef5ea2f41daf4a2113b80c9223df884b4d56c400", + "version": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e", "from": "github:web3-js/WebSocket-Node#polyfill/globalThis", "requires": { "debug": "^2.2.0", diff --git a/solidity/package.json b/solidity/package.json index 612d30e4f..ab80622d4 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -34,8 +34,8 @@ }, "homepage": "https://github.com/keep-network/keep-ecdsa", "dependencies": { - "@keep-network/keep-core": "1.3.1-pre.2", - "@keep-network/sortition-pools": "1.1.2", + "@keep-network/keep-core": ">1.3.1-pre <1.3.1-rc", + "@keep-network/sortition-pools": ">1.2.0-pre <1.2.0-rc", "@openzeppelin/upgrades": "^2.7.2", "openzeppelin-solidity": "2.3.0" }, From a9cb6f30163bd560406cb7a1f76ded782b911e70 Mon Sep 17 00:00:00 2001 From: Piotr Dyraga Date: Tue, 27 Oct 2020 13:39:18 +0100 Subject: [PATCH 30/57] Project version for contracts set to 1.3.0-pre.0 --- solidity/package-lock.json | 2 +- solidity/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/solidity/package-lock.json b/solidity/package-lock.json index 946ffc19b..15e8bbc35 100644 --- a/solidity/package-lock.json +++ b/solidity/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keep-network/keep-ecdsa", - "version": "1.2.2-rc", + "version": "1.3.0-pre.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/solidity/package.json b/solidity/package.json index ab80622d4..fc3444999 100644 --- a/solidity/package.json +++ b/solidity/package.json @@ -1,6 +1,6 @@ { "name": "@keep-network/keep-ecdsa", - "version": "1.2.2-rc", + "version": "1.3.0-pre.0", "description": "Smart contracts for ECDSA Keep", "repository": { "type": "git", From 80c6e4950c0881b8d8ccc1756e0460695f219bf9 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 29 Oct 2020 11:37:25 +0100 Subject: [PATCH 31/57] Revert "Expect contract typed addresses in constructors" This reverts commit 24797782173abcbbec9d71ba163efc1d992eb9f1. --- solidity/contracts/AbstractBonding.sol | 6 +++--- solidity/contracts/KeepBonding.sol | 18 +++++++++--------- .../fully-backed/FullyBackedBonding.sol | 2 +- .../contracts/test/AbstractBondingStub.sol | 8 +++----- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/solidity/contracts/AbstractBonding.sol b/solidity/contracts/AbstractBonding.sol index d296079ea..44efdc9cd 100644 --- a/solidity/contracts/AbstractBonding.sol +++ b/solidity/contracts/AbstractBonding.sol @@ -71,9 +71,9 @@ contract AbstractBonding is IBondingManagement { ); /// @notice Initializes Keep Bonding contract. - /// @param _keepRegistry Keep Registry contract address. - constructor(KeepRegistry _keepRegistry) public { - registry = _keepRegistry; + /// @param registryAddress Keep registry contract address. + constructor(address registryAddress) public { + registry = KeepRegistry(registryAddress); } /// @notice Add the provided value to operator's pool available for bonding. diff --git a/solidity/contracts/KeepBonding.sol b/solidity/contracts/KeepBonding.sol index c313d3ffa..2042ef070 100644 --- a/solidity/contracts/KeepBonding.sol +++ b/solidity/contracts/KeepBonding.sol @@ -31,16 +31,16 @@ contract KeepBonding is AbstractBonding { TokenGrant internal tokenGrant; /// @notice Initializes Keep Bonding contract. - /// @param _keepRegistry Keep Registry contract address. - /// @param _tokenStaking KEEP token staking contract address. - /// @param _tokenGrant KEEP token grant contract address. + /// @param registryAddress Keep registry contract address. + /// @param tokenStakingAddress KEEP token staking contract address. + /// @param tokenGrantAddress KEEP token grant contract address. constructor( - KeepRegistry _keepRegistry, - TokenStaking _tokenStaking, - TokenGrant _tokenGrant - ) public AbstractBonding(_keepRegistry) { - tokenStaking = _tokenStaking; - tokenGrant = _tokenGrant; + address registryAddress, + address tokenStakingAddress, + address tokenGrantAddress + ) public AbstractBonding(registryAddress) { + tokenStaking = TokenStaking(tokenStakingAddress); + tokenGrant = TokenGrant(tokenGrantAddress); } /// @notice Withdraws amount from operator's value available for bonding. diff --git a/solidity/contracts/fully-backed/FullyBackedBonding.sol b/solidity/contracts/fully-backed/FullyBackedBonding.sol index 29542a733..b0aac5b00 100644 --- a/solidity/contracts/fully-backed/FullyBackedBonding.sol +++ b/solidity/contracts/fully-backed/FullyBackedBonding.sol @@ -58,7 +58,7 @@ contract FullyBackedBonding is /// before being eligible for group selection. constructor(KeepRegistry _keepRegistry, uint256 _initializationPeriod) public - AbstractBonding(_keepRegistry) + AbstractBonding(address(_keepRegistry)) Authorizations(_keepRegistry) { initializationPeriod = _initializationPeriod; diff --git a/solidity/contracts/test/AbstractBondingStub.sol b/solidity/contracts/test/AbstractBondingStub.sol index aa2f71cbb..7fd083881 100644 --- a/solidity/contracts/test/AbstractBondingStub.sol +++ b/solidity/contracts/test/AbstractBondingStub.sol @@ -4,16 +4,14 @@ import "../../contracts/AbstractBonding.sol"; import "./StakingInfoStub.sol"; -import "@keep-network/keep-core/contracts/KeepRegistry.sol"; - contract AbstractBondingStub is AbstractBonding { StakingInfoStub stakingInfoStub; - constructor(KeepRegistry _keepRegistry, StakingInfoStub _stakingInfoStub) + constructor(address registryAddress, address stakingInfoAddress) public - AbstractBonding(_keepRegistry) + AbstractBonding(registryAddress) { - stakingInfoStub = _stakingInfoStub; + stakingInfoStub = StakingInfoStub(stakingInfoAddress); } function withdraw(uint256 amount, address operator) public { From 26eea9de25c27b4bc2203612f210da7e49a93c5e Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 29 Oct 2020 11:39:59 +0100 Subject: [PATCH 32/57] Removed comment about clone removal It's not possible to remove the contract once dpeloyed so the comment was not needed. --- solidity/contracts/BondedECDSAKeep.sol | 3 +-- solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/solidity/contracts/BondedECDSAKeep.sol b/solidity/contracts/BondedECDSAKeep.sol index 3cf0dedb5..3ce325a67 100644 --- a/solidity/contracts/BondedECDSAKeep.sol +++ b/solidity/contracts/BondedECDSAKeep.sol @@ -22,8 +22,7 @@ import "@keep-network/keep-core/contracts/TokenStaking.sol"; /// @title Bonded ECDSA Keep /// @notice ECDSA keep with additional signer bond requirement. /// @dev This contract is used as a master contract for clone factory in -/// BondedECDSAKeepFactory as per EIP-1167. It should never be removed after -/// initial deployment as this will break functionality for all created clones. +/// BondedECDSAKeepFactory as per EIP-1167. contract BondedECDSAKeep is AbstractBondedECDSAKeep { // Stake that was required from each keep member on keep creation. // The value is used for keep members slashing. diff --git a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol index e50b43f88..9c3ada040 100644 --- a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol +++ b/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol @@ -22,8 +22,7 @@ import "./FullyBackedBondedECDSAKeepFactory.sol"; /// @notice ECDSA keep with additional signer bond requirement that is fully backed /// by ETH only. /// @dev This contract is used as a master contract for clone factory in -/// BondedECDSAKeepFactory as per EIP-1167. It should never be removed after -/// initial deployment as this will break functionality for all created clones. +/// BondedECDSAKeepFactory as per EIP-1167. contract FullyBackedBondedECDSAKeep is AbstractBondedECDSAKeep { FullyBackedBonding bonding; FullyBackedBondedECDSAKeepFactory keepFactory; From cc58f14e66f4a9d5dd0300feae5776d67b2e8ed9 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 29 Oct 2020 12:26:08 +0100 Subject: [PATCH 33/57] Renamed FullyBackedBondedECDSAKeep to FullyBackedECDSAKeep Simplified the name as we have just two keep types and we don't need such long name. The current naming is also consistent with sortition pools. --- ...ECDSAKeep.sol => FullyBackedECDSAKeep.sol} | 8 ++-- ...ry.sol => FullyBackedECDSAKeepFactory.sol} | 10 ++--- ... FullyBackedECDSAKeepCloneFactoryStub.sol} | 12 +++--- ...ol => FullyBackedECDSAKeepFactoryStub.sol} | 8 ++-- ...pStub.sol => FullyBackedECDSAKeepStub.sol} | 4 +- solidity/migrations/2_deploy_contracts.js | 14 +++---- solidity/migrations/3_initialize.js | 10 ++--- ....js => FullyBackedECDSAKeepFactoryTest.js} | 40 +++++++++---------- ...eepTest.js => FullyBackedECDSAKeepTest.js} | 30 +++++++------- 9 files changed, 62 insertions(+), 74 deletions(-) rename solidity/contracts/fully-backed/{FullyBackedBondedECDSAKeep.sol => FullyBackedECDSAKeep.sol} (94%) rename solidity/contracts/fully-backed/{FullyBackedBondedECDSAKeepFactory.sol => FullyBackedECDSAKeepFactory.sol} (97%) rename solidity/contracts/test/{FullyBackedBondedECDSAKeepCloneFactoryStub.sol => FullyBackedECDSAKeepCloneFactoryStub.sol} (76%) rename solidity/contracts/test/{FullyBackedBondedECDSAKeepFactoryStub.sol => FullyBackedECDSAKeepFactoryStub.sol} (81%) rename solidity/contracts/test/{FullyBackedBondedECDSAKeepStub.sol => FullyBackedECDSAKeepStub.sol} (76%) rename solidity/test/{FullyBackedBondedECDSAKeepFactoryTest.js => FullyBackedECDSAKeepFactoryTest.js} (97%) rename solidity/test/{FullyBackedBondedECDSAKeepTest.js => FullyBackedECDSAKeepTest.js} (98%) diff --git a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol b/solidity/contracts/fully-backed/FullyBackedECDSAKeep.sol similarity index 94% rename from solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol rename to solidity/contracts/fully-backed/FullyBackedECDSAKeep.sol index 9c3ada040..d06ca4332 100644 --- a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeep.sol +++ b/solidity/contracts/fully-backed/FullyBackedECDSAKeep.sol @@ -16,16 +16,16 @@ pragma solidity 0.5.17; import "../AbstractBondedECDSAKeep.sol"; import "./FullyBackedBonding.sol"; -import "./FullyBackedBondedECDSAKeepFactory.sol"; +import "./FullyBackedECDSAKeepFactory.sol"; /// @title Fully Backed Bonded ECDSA Keep /// @notice ECDSA keep with additional signer bond requirement that is fully backed /// by ETH only. /// @dev This contract is used as a master contract for clone factory in /// BondedECDSAKeepFactory as per EIP-1167. -contract FullyBackedBondedECDSAKeep is AbstractBondedECDSAKeep { +contract FullyBackedECDSAKeep is AbstractBondedECDSAKeep { FullyBackedBonding bonding; - FullyBackedBondedECDSAKeepFactory keepFactory; + FullyBackedECDSAKeepFactory keepFactory; /// @notice Initialization function. /// @dev We use clone factory to create new keep. That is why this contract @@ -47,7 +47,7 @@ contract FullyBackedBondedECDSAKeep is AbstractBondedECDSAKeep { super.initialize(_owner, _members, _honestThreshold, _bonding); bonding = FullyBackedBonding(_bonding); - keepFactory = FullyBackedBondedECDSAKeepFactory(_keepFactory); + keepFactory = FullyBackedECDSAKeepFactory(_keepFactory); bonding.claimDelegatedAuthority(_keepFactory); } diff --git a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol b/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol similarity index 97% rename from solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol rename to solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol index 8c8c903dc..935e800b7 100644 --- a/solidity/contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol +++ b/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol @@ -14,7 +14,7 @@ pragma solidity 0.5.17; -import "./FullyBackedBondedECDSAKeep.sol"; +import "./FullyBackedECDSAKeep.sol"; import "./FullyBackedBonding.sol"; import "../api/IBondedECDSAKeepFactory.sol"; @@ -38,7 +38,7 @@ import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /// Proxy delegates calls to sortition pool and therefore does not affect contract's /// state. This means that we only need to deploy the bonded ECDSA keep contract /// once. The factory provides clean state for every new bonded ECDSA keep clone. -contract FullyBackedBondedECDSAKeepFactory is +contract FullyBackedECDSAKeepFactory is IBondedECDSAKeepFactory, KeepCreator, AuthorityDelegator, @@ -66,7 +66,7 @@ contract FullyBackedBondedECDSAKeepFactory is uint256 public constant bondWeightDivisor = 1e18; // 1 ETH // TODO: Decide on value // Notification that a new keep has been created. - event FullyBackedBondedECDSAKeepCreated( + event FullyBackedECDSAKeepCreated( address indexed keepAddress, address[] members, address indexed owner, @@ -165,7 +165,7 @@ contract FullyBackedBondedECDSAKeepFactory is // in `__isRecognized` function. keepAddress = createKeep(); - FullyBackedBondedECDSAKeep(keepAddress).initialize( + FullyBackedECDSAKeep(keepAddress).initialize( _owner, members, _honestThreshold, @@ -183,7 +183,7 @@ contract FullyBackedBondedECDSAKeepFactory is ); } - emit FullyBackedBondedECDSAKeepCreated( + emit FullyBackedECDSAKeepCreated( keepAddress, members, _owner, diff --git a/solidity/contracts/test/FullyBackedBondedECDSAKeepCloneFactoryStub.sol b/solidity/contracts/test/FullyBackedECDSAKeepCloneFactoryStub.sol similarity index 76% rename from solidity/contracts/test/FullyBackedBondedECDSAKeepCloneFactoryStub.sol rename to solidity/contracts/test/FullyBackedECDSAKeepCloneFactoryStub.sol index 1668f5a3f..c27e2d267 100644 --- a/solidity/contracts/test/FullyBackedBondedECDSAKeepCloneFactoryStub.sol +++ b/solidity/contracts/test/FullyBackedECDSAKeepCloneFactoryStub.sol @@ -1,6 +1,6 @@ pragma solidity 0.5.17; -import "../../contracts/fully-backed/FullyBackedBondedECDSAKeep.sol"; +import "../../contracts/fully-backed/FullyBackedECDSAKeep.sol"; import "../../contracts/CloneFactory.sol"; import { @@ -9,7 +9,7 @@ import { /// @title Fully Backed Bonded ECDSA Keep Factory Stub using clone factory. /// @dev This contract is for testing purposes only. -contract FullyBackedBondedECDSAKeepCloneFactoryStub is +contract FullyBackedECDSAKeepCloneFactoryStub is CloneFactory, AuthorityDelegator { @@ -19,7 +19,7 @@ contract FullyBackedBondedECDSAKeepCloneFactoryStub is masterKeepAddress = _masterKeepAddress; } - event FullyBackedBondedECDSAKeepCreated(address keepAddress); + event FullyBackedECDSAKeepCreated(address keepAddress); function newKeep( address _owner, @@ -31,9 +31,7 @@ contract FullyBackedBondedECDSAKeepCloneFactoryStub is keepAddress = createClone(masterKeepAddress); assert(isClone(masterKeepAddress, keepAddress)); - FullyBackedBondedECDSAKeep keep = FullyBackedBondedECDSAKeep( - keepAddress - ); + FullyBackedECDSAKeep keep = FullyBackedECDSAKeep(keepAddress); keep.initialize( _owner, _members, @@ -42,7 +40,7 @@ contract FullyBackedBondedECDSAKeepCloneFactoryStub is _keepFactory ); - emit FullyBackedBondedECDSAKeepCreated(keepAddress); + emit FullyBackedECDSAKeepCreated(keepAddress); } function __isRecognized(address _delegatedAuthorityRecipient) diff --git a/solidity/contracts/test/FullyBackedBondedECDSAKeepFactoryStub.sol b/solidity/contracts/test/FullyBackedECDSAKeepFactoryStub.sol similarity index 81% rename from solidity/contracts/test/FullyBackedBondedECDSAKeepFactoryStub.sol rename to solidity/contracts/test/FullyBackedECDSAKeepFactoryStub.sol index e80464bd4..da4eca92e 100644 --- a/solidity/contracts/test/FullyBackedBondedECDSAKeepFactoryStub.sol +++ b/solidity/contracts/test/FullyBackedECDSAKeepFactoryStub.sol @@ -1,12 +1,10 @@ pragma solidity 0.5.17; -import "../../contracts/fully-backed/FullyBackedBondedECDSAKeepFactory.sol"; +import "../../contracts/fully-backed/FullyBackedECDSAKeepFactory.sol"; /// @title Fully Backed Bonded ECDSA Keep Factory Stub /// @dev This contract is for testing purposes only. -contract FullyBackedBondedECDSAKeepFactoryStub is - FullyBackedBondedECDSAKeepFactory -{ +contract FullyBackedECDSAKeepFactoryStub is FullyBackedECDSAKeepFactory { constructor( address _masterKeepAddress, address _sortitionPoolFactoryAddress, @@ -14,7 +12,7 @@ contract FullyBackedBondedECDSAKeepFactoryStub is address _randomBeaconAddress ) public - FullyBackedBondedECDSAKeepFactory( + FullyBackedECDSAKeepFactory( _masterKeepAddress, _sortitionPoolFactoryAddress, _bondingAddress, diff --git a/solidity/contracts/test/FullyBackedBondedECDSAKeepStub.sol b/solidity/contracts/test/FullyBackedECDSAKeepStub.sol similarity index 76% rename from solidity/contracts/test/FullyBackedBondedECDSAKeepStub.sol rename to solidity/contracts/test/FullyBackedECDSAKeepStub.sol index 3f5a2119b..5116d293e 100644 --- a/solidity/contracts/test/FullyBackedBondedECDSAKeepStub.sol +++ b/solidity/contracts/test/FullyBackedECDSAKeepStub.sol @@ -1,10 +1,10 @@ pragma solidity 0.5.17; -import "../../contracts/fully-backed/FullyBackedBondedECDSAKeep.sol"; +import "../../contracts/fully-backed/FullyBackedECDSAKeep.sol"; /// @title Fully Backed Bonded ECDSA Keep Stub /// @dev This contract is for testing purposes only. -contract FullyBackedBondedECDSAKeepStub is FullyBackedBondedECDSAKeep { +contract FullyBackedECDSAKeepStub is FullyBackedECDSAKeep { function publicMarkAsClosed() public { markAsClosed(); } diff --git a/solidity/migrations/2_deploy_contracts.js b/solidity/migrations/2_deploy_contracts.js index ae504a835..dd6405a28 100644 --- a/solidity/migrations/2_deploy_contracts.js +++ b/solidity/migrations/2_deploy_contracts.js @@ -9,11 +9,9 @@ const BondedECDSAKeepVendorImplV1 = artifacts.require( ) const FullyBackedBonding = artifacts.require("FullyBackedBonding") -const FullyBackedBondedECDSAKeep = artifacts.require( - "FullyBackedBondedECDSAKeep" -) -const FullyBackedBondedECDSAKeepFactory = artifacts.require( - "FullyBackedBondedECDSAKeepFactory" +const FullyBackedECDSAKeep = artifacts.require("FullyBackedECDSAKeep") +const FullyBackedECDSAKeepFactory = artifacts.require( + "FullyBackedECDSAKeepFactory" ) const EthBonding = artifacts.require("EthBonding") @@ -89,11 +87,11 @@ module.exports = async function (deployer) { // ETH-only Staking await deployer.deploy(FullyBackedBonding, RegistryAddress) - await deployer.deploy(FullyBackedBondedECDSAKeep) + await deployer.deploy(FullyBackedECDSAKeep) await deployer.deploy( - FullyBackedBondedECDSAKeepFactory, - FullyBackedBondedECDSAKeep.address, + FullyBackedECDSAKeepFactory, + FullyBackedECDSAKeep.address, FullyBackedSortitionPoolFactory.address, FullyBackedBonding.address, RandomBeaconAddress diff --git a/solidity/migrations/3_initialize.js b/solidity/migrations/3_initialize.js index 193c850da..c5340fdd4 100644 --- a/solidity/migrations/3_initialize.js +++ b/solidity/migrations/3_initialize.js @@ -3,8 +3,8 @@ const BondedECDSAKeepVendorImplV1 = artifacts.require( "BondedECDSAKeepVendorImplV1" ) const BondedECDSAKeepFactory = artifacts.require("BondedECDSAKeepFactory") -const FullyBackedBondedECDSAKeepFactory = artifacts.require( - "FullyBackedBondedECDSAKeepFactory" +const FullyBackedECDSAKeepFactory = artifacts.require( + "FullyBackedECDSAKeepFactory" ) const KeepRegistry = artifacts.require("KeepRegistry") @@ -39,11 +39,9 @@ module.exports = async function (deployer) { `approved BondedECDSAKeepFactory operator contract [${BondedECDSAKeepFactory.address}] in registry` ) - await registry.approveOperatorContract( - FullyBackedBondedECDSAKeepFactory.address - ) + await registry.approveOperatorContract(FullyBackedECDSAKeepFactory.address) console.log( - `approved FullyBackedBondedECDSAKeepFactory operator contract [${FullyBackedBondedECDSAKeepFactory.address}] in registry` + `approved FullyBackedECDSAKeepFactory operator contract [${FullyBackedECDSAKeepFactory.address}] in registry` ) // Set service contract owner as operator contract upgrader by default diff --git a/solidity/test/FullyBackedBondedECDSAKeepFactoryTest.js b/solidity/test/FullyBackedECDSAKeepFactoryTest.js similarity index 97% rename from solidity/test/FullyBackedBondedECDSAKeepFactoryTest.js rename to solidity/test/FullyBackedECDSAKeepFactoryTest.js index 08086a24c..42d2bebc5 100644 --- a/solidity/test/FullyBackedBondedECDSAKeepFactoryTest.js +++ b/solidity/test/FullyBackedECDSAKeepFactoryTest.js @@ -9,8 +9,8 @@ const truffleAssert = require("truffle-assertions") const StackLib = contract.fromArtifact("StackLib") const KeepRegistry = contract.fromArtifact("KeepRegistry") -const FullyBackedBondedECDSAKeepFactoryStub = contract.fromArtifact( - "FullyBackedBondedECDSAKeepFactoryStub" +const FullyBackedECDSAKeepFactoryStub = contract.fromArtifact( + "FullyBackedECDSAKeepFactoryStub" ) const FullyBackedBonding = contract.fromArtifact("FullyBackedBonding") const FullyBackedSortitionPool = contract.fromArtifact( @@ -20,9 +20,7 @@ const FullyBackedSortitionPoolFactory = contract.fromArtifact( "FullyBackedSortitionPoolFactory" ) const RandomBeaconStub = contract.fromArtifact("RandomBeaconStub") -const FullyBackedBondedECDSAKeep = contract.fromArtifact( - "FullyBackedBondedECDSAKeep" -) +const FullyBackedECDSAKeep = contract.fromArtifact("FullyBackedECDSAKeep") const BN = web3.utils.BN @@ -31,7 +29,7 @@ chai.use(require("bn-chai")(BN)) const expect = chai.expect const assert = chai.assert -describe("FullyBackedBondedECDSAKeepFactory", function () { +describe("FullyBackedECDSAKeepFactory", function () { let registry let keepFactory let sortitionPoolFactory @@ -54,7 +52,7 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { const singleBond = web3.utils.toWei(new BN(20)) const bond = singleBond.mul(groupSize) - const stakeLockDuration = 0 // parameter is ignored by FullyBackedBondedECDSAKeepFactory implementation + const stakeLockDuration = 0 // parameter is ignored by FullyBackedECDSAKeepFactory implementation const delegationInitPeriod = time.duration.hours(12) const delegationLockPeriod = time.duration.days(1) @@ -603,7 +601,7 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { ) const eventList = await keepFactory.getPastEvents( - "FullyBackedBondedECDSAKeepCreated", + "FullyBackedECDSAKeepCreated", { fromBlock: blockNumber, toBlock: "latest", @@ -643,7 +641,7 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { ) const eventList = await keepFactory.getPastEvents( - "FullyBackedBondedECDSAKeepCreated", + "FullyBackedECDSAKeepCreated", { fromBlock: blockNumber, toBlock: "latest", @@ -683,7 +681,7 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { ) const eventList = await keepFactory.getPastEvents( - "FullyBackedBondedECDSAKeepCreated", + "FullyBackedECDSAKeepCreated", { fromBlock: blockNumber, toBlock: "latest", @@ -725,7 +723,7 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { ) const eventList = await keepFactory.getPastEvents( - "FullyBackedBondedECDSAKeepCreated", + "FullyBackedECDSAKeepCreated", { fromBlock: blockNumber, toBlock: "latest", @@ -803,7 +801,7 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { const keep = await openKeep() const eventList = await keepFactory.getPastEvents( - "FullyBackedBondedECDSAKeepCreated", + "FullyBackedECDSAKeepCreated", { fromBlock: blockNumber, toBlock: "latest", @@ -991,7 +989,7 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { ) const eventList = await keepFactory.getPastEvents( - "FullyBackedBondedECDSAKeepCreated", + "FullyBackedECDSAKeepCreated", { fromBlock: blockNumber, toBlock: "latest", @@ -1025,7 +1023,7 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { } ) const recordedKeepAddress = await keepFactory.getKeepAtIndex(preKeepCount) - const keep = await FullyBackedBondedECDSAKeep.at(keepAddress) + const keep = await FullyBackedECDSAKeep.at(keepAddress) const keepOpenedTime = await keep.getOpenedTimestamp() const factoryKeepOpenedTime = await keepFactory.getKeepOpenedTimestamp( keepAddress @@ -1065,7 +1063,7 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { } ) - const keep = await FullyBackedBondedECDSAKeep.at(keepAddress) + const keep = await FullyBackedECDSAKeep.at(keepAddress) assert.isTrue(await keep.isActive(), "keep should be active") }) @@ -1092,7 +1090,7 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { ) const eventList = await keepFactory.getPastEvents( - "FullyBackedBondedECDSAKeepCreated", + "FullyBackedECDSAKeepCreated", { fromBlock: blockNumber, toBlock: "latest", @@ -1191,8 +1189,8 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { delegationInitPeriod ) randomBeacon = accounts[1] - const keepMasterContract = await FullyBackedBondedECDSAKeep.new() - keepFactory = await FullyBackedBondedECDSAKeepFactoryStub.new( + const keepMasterContract = await FullyBackedECDSAKeep.new() + keepFactory = await FullyBackedECDSAKeepFactoryStub.new( keepMasterContract.address, sortitionPoolFactory.address, bonding.address, @@ -1528,8 +1526,8 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { delegationInitPeriod ) randomBeacon = await RandomBeaconStub.new() - const keepMasterContract = await FullyBackedBondedECDSAKeep.new() - keepFactory = await FullyBackedBondedECDSAKeepFactoryStub.new( + const keepMasterContract = await FullyBackedECDSAKeep.new() + keepFactory = await FullyBackedECDSAKeepFactoryStub.new( keepMasterContract.address, sortitionPoolFactory.address, bonding.address, @@ -1629,6 +1627,6 @@ describe("FullyBackedBondedECDSAKeepFactory", function () { } ) - return await FullyBackedBondedECDSAKeep.at(keepAddress) + return await FullyBackedECDSAKeep.at(keepAddress) } }) diff --git a/solidity/test/FullyBackedBondedECDSAKeepTest.js b/solidity/test/FullyBackedECDSAKeepTest.js similarity index 98% rename from solidity/test/FullyBackedBondedECDSAKeepTest.js rename to solidity/test/FullyBackedECDSAKeepTest.js index 52131a6c0..fa96c6adf 100644 --- a/solidity/test/FullyBackedBondedECDSAKeepTest.js +++ b/solidity/test/FullyBackedECDSAKeepTest.js @@ -11,17 +11,15 @@ const {createSnapshot, restoreSnapshot} = require("./helpers/snapshot") const {expectRevert, time} = require("@openzeppelin/test-helpers") const KeepRegistry = contract.fromArtifact("KeepRegistry") -const FullyBackedBondedECDSAKeep = contract.fromArtifact( - "FullyBackedBondedECDSAKeep" -) -const FullyBackedBondedECDSAKeepStub = contract.fromArtifact( - "FullyBackedBondedECDSAKeepStub" +const FullyBackedECDSAKeep = contract.fromArtifact("FullyBackedECDSAKeep") +const FullyBackedECDSAKeepStub = contract.fromArtifact( + "FullyBackedECDSAKeepStub" ) const TestToken = contract.fromArtifact("TestToken") const FullyBackedBondingStub = contract.fromArtifact("FullyBackedBondingStub") const TestEtherReceiver = contract.fromArtifact("TestEtherReceiver") -const FullyBackedBondedECDSAKeepCloneFactoryStub = contract.fromArtifact( - "FullyBackedBondedECDSAKeepCloneFactoryStub" +const FullyBackedECDSAKeepCloneFactoryStub = contract.fromArtifact( + "FullyBackedECDSAKeepCloneFactoryStub" ) const truffleAssert = require("truffle-assertions") @@ -33,7 +31,7 @@ chai.use(require("bn-chai")(BN)) const expect = chai.expect const assert = chai.assert -describe("FullyBackedBondedECDSAKeep", function () { +describe("FullyBackedECDSAKeep", function () { const bondCreator = accounts[0] const owner = accounts[1] const nonOwner = accounts[2] @@ -69,7 +67,7 @@ describe("FullyBackedBondedECDSAKeep", function () { ) const events = await factoryStub.getPastEvents( - "FullyBackedBondedECDSAKeepCreated", + "FullyBackedECDSAKeepCreated", { fromBlock: startBlock, toBlock: "latest", @@ -78,11 +76,11 @@ describe("FullyBackedBondedECDSAKeep", function () { assert.lengthOf( events, 1, - "unexpected length of FullyBackedBondedECDSAKeepCreated events" + "unexpected length of FullyBackedECDSAKeepCreated events" ) const keepAddress = events[0].returnValues.keepAddress - return await FullyBackedBondedECDSAKeepStub.at(keepAddress) + return await FullyBackedECDSAKeepStub.at(keepAddress) } before(async () => { @@ -91,8 +89,8 @@ describe("FullyBackedBondedECDSAKeep", function () { registry.address, delegationInitPeriod ) - keepStubMaster = await FullyBackedBondedECDSAKeepStub.new() - factoryStub = await FullyBackedBondedECDSAKeepCloneFactoryStub.new( + keepStubMaster = await FullyBackedECDSAKeepStub.new() + factoryStub = await FullyBackedECDSAKeepCloneFactoryStub.new( keepStubMaster.address ) @@ -120,7 +118,7 @@ describe("FullyBackedBondedECDSAKeep", function () { describe("initialize", async () => { it("succeeds", async () => { - keep = await FullyBackedBondedECDSAKeepStub.new() + keep = await FullyBackedECDSAKeepStub.new() await keep.initialize( owner, members, @@ -131,7 +129,7 @@ describe("FullyBackedBondedECDSAKeep", function () { }) it("claims bonding delegated authority", async () => { - keep = await FullyBackedBondedECDSAKeepStub.new() + keep = await FullyBackedECDSAKeepStub.new() await keep.initialize( owner, members, @@ -307,7 +305,7 @@ describe("FullyBackedBondedECDSAKeep", function () { factoryStub.address ) - keepWith16Signers = await FullyBackedBondedECDSAKeep.at(keepAddress) + keepWith16Signers = await FullyBackedECDSAKeep.at(keepAddress) }) it("should be less than 350k if all submitted keys match", async () => { From 1e088d85569b7f588f92ead3b5b107e04f385695 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 29 Oct 2020 13:54:35 +0100 Subject: [PATCH 34/57] Confirmed bondWeightDivisor to 1 ETH Confirmed value 1e18 (1ETH) to be correct as per: https://github.com/keep-network/keep-ecdsa/pull/483#discussion_r512865630 --- solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol b/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol index 935e800b7..15f51b401 100644 --- a/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol +++ b/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol @@ -63,7 +63,7 @@ contract FullyBackedECDSAKeepFactory is // stake divided by a constant divisor. The divisor is set to 1 ETH so that // all ETHs in available unbonded value matter when calculating operator's // eligible weight for signer selection. - uint256 public constant bondWeightDivisor = 1e18; // 1 ETH // TODO: Decide on value + uint256 public constant bondWeightDivisor = 1e18; // 1 ETH // Notification that a new keep has been created. event FullyBackedECDSAKeepCreated( From c04038ba18e95bbd1553ef2b5db0955eabd6793c Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 29 Oct 2020 13:55:41 +0100 Subject: [PATCH 35/57] Increased DELEGATION_LOCK_PERIOD to 2 weeks --- solidity/contracts/fully-backed/FullyBackedBonding.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solidity/contracts/fully-backed/FullyBackedBonding.sol b/solidity/contracts/fully-backed/FullyBackedBonding.sol index b0aac5b00..94bd88a2b 100644 --- a/solidity/contracts/fully-backed/FullyBackedBonding.sol +++ b/solidity/contracts/fully-backed/FullyBackedBonding.sol @@ -47,7 +47,7 @@ contract FullyBackedBonding is // Once a delegation to an operator is received the delegator has to wait for // specific time period before being able to pull out the funds. - uint256 public constant DELEGATION_LOCK_PERIOD = 1 days; // TODO: Decide right value + uint256 public constant DELEGATION_LOCK_PERIOD = 14 days; // TODO: Decide right value uint256 public initializationPeriod; // varies between mainnet and testnet From c8dc76e0616bd4586794c67cfd8c8bbc99c95d50 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Thu, 29 Oct 2020 14:15:42 +0100 Subject: [PATCH 36/57] Updated delegation lock period hardcoded in test --- solidity/test/FullyBackedECDSAKeepFactoryTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solidity/test/FullyBackedECDSAKeepFactoryTest.js b/solidity/test/FullyBackedECDSAKeepFactoryTest.js index 42d2bebc5..4e8dd0916 100644 --- a/solidity/test/FullyBackedECDSAKeepFactoryTest.js +++ b/solidity/test/FullyBackedECDSAKeepFactoryTest.js @@ -54,7 +54,7 @@ describe("FullyBackedECDSAKeepFactory", function () { const stakeLockDuration = 0 // parameter is ignored by FullyBackedECDSAKeepFactory implementation const delegationInitPeriod = time.duration.hours(12) - const delegationLockPeriod = time.duration.days(1) + const delegationLockPeriod = time.duration.days(14) before(async () => { await FullyBackedSortitionPoolFactory.detectNetwork() From 85c3663ae5270418116c1f4cb3d2df93d8c8f1a9 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 30 Oct 2020 14:14:31 +0100 Subject: [PATCH 37/57] Include delegation value in OperatorDelegated event We added a value of a deletaion to the emitted event. This is similiar we do for KEEP based delegations in OperatorStaked event. --- solidity/contracts/fully-backed/FullyBackedBonding.sol | 5 +++-- solidity/test/FullyBackedBondingTest.js | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/solidity/contracts/fully-backed/FullyBackedBonding.sol b/solidity/contracts/fully-backed/FullyBackedBonding.sol index 94bd88a2b..edc20463a 100644 --- a/solidity/contracts/fully-backed/FullyBackedBonding.sol +++ b/solidity/contracts/fully-backed/FullyBackedBonding.sol @@ -38,7 +38,8 @@ contract FullyBackedBonding is event OperatorDelegated( address indexed operator, address indexed beneficiary, - address indexed authorizer + address indexed authorizer, + uint256 value ); // The ether value (in wei) that should be passed along with the delegation @@ -101,7 +102,7 @@ contract FullyBackedBonding is deposit(operator); emit Delegated(owner, operator); - emit OperatorDelegated(operator, beneficiary, authorizer); + emit OperatorDelegated(operator, beneficiary, authorizer, msg.value); } /// @notice Checks if the operator for the given bond creator contract diff --git a/solidity/test/FullyBackedBondingTest.js b/solidity/test/FullyBackedBondingTest.js index 1870709bd..7b9223587 100644 --- a/solidity/test/FullyBackedBondingTest.js +++ b/solidity/test/FullyBackedBondingTest.js @@ -111,6 +111,7 @@ describe("FullyBackedBonding", function () { operator: operator, beneficiary: beneficiary, authorizer: authorizer, + value: minimumDelegationValue, }) }) From 566cc48a133401facda4f7b7a2123fbaac7a2abe Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 30 Oct 2020 15:53:13 +0100 Subject: [PATCH 38/57] Set minimum delegation deposit to 40 ETH Set the value as agreed in https://github.com/keep-network/keep-ecdsa/pull/483#discussion_r515006697 --- .../fully-backed/FullyBackedBonding.sol | 2 +- .../test/FullyBackedECDSAKeepFactoryTest.js | 31 ++++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/solidity/contracts/fully-backed/FullyBackedBonding.sol b/solidity/contracts/fully-backed/FullyBackedBonding.sol index edc20463a..064c6a573 100644 --- a/solidity/contracts/fully-backed/FullyBackedBonding.sol +++ b/solidity/contracts/fully-backed/FullyBackedBonding.sol @@ -44,7 +44,7 @@ contract FullyBackedBonding is // The ether value (in wei) that should be passed along with the delegation // and deposited for bonding. - uint256 public constant MINIMUM_DELEGATION_DEPOSIT = 12345; // TODO: Decide right value + uint256 public constant MINIMUM_DELEGATION_DEPOSIT = 40 ether; // Once a delegation to an operator is received the delegator has to wait for // specific time period before being able to pull out the funds. diff --git a/solidity/test/FullyBackedECDSAKeepFactoryTest.js b/solidity/test/FullyBackedECDSAKeepFactoryTest.js index 4e8dd0916..f3e61aebc 100644 --- a/solidity/test/FullyBackedECDSAKeepFactoryTest.js +++ b/solidity/test/FullyBackedECDSAKeepFactoryTest.js @@ -225,12 +225,7 @@ describe("FullyBackedECDSAKeepFactory", function () { await keepFactory.createSortitionPool(application) const pool = await FullyBackedSortitionPool.at(signerPool) - await delegate( - members[0], - members[0], - authorizers[0], - minimumBondableValue - ) + await delegate(members[0], members[0], authorizers[0]) await time.increase(delegationInitPeriod.subn(1)) @@ -452,10 +447,15 @@ describe("FullyBackedECDSAKeepFactory", function () { }) describe("updateOperatorStatus", async () => { + let minimumBondableValue + before(async () => { await initializeNewFactory() await initializeMemberCandidates() await registerMemberCandidates() + + const pool = await FullyBackedSortitionPool.at(signerPool) + minimumBondableValue = await pool.getMinimumBondableValue() }) it("revers if operator is up to date", async () => { @@ -466,7 +466,11 @@ describe("FullyBackedECDSAKeepFactory", function () { }) it("removes operator if bonding value has changed below minimum", async () => { - bonding.withdraw(new BN(1), members[0], {from: members[0]}) + currentValue = await bonding.unbondedValue(members[0]) + + const valueToWithdraw = currentValue.sub(minimumBondableValue).addn(1) + + bonding.withdraw(valueToWithdraw, members[0], {from: members[0]}) assert.isFalse( await keepFactory.isOperatorUpToDate(members[0], application), "unexpected status of the operator after bonding value change" @@ -666,7 +670,7 @@ describe("FullyBackedECDSAKeepFactory", function () { it("rounds up members bonds", async () => { const requestedBond = bond.add(new BN(1)) const unbondedAmount = singleBond.add(new BN(1)) - const expectedMemberBond = singleBond.add(new BN(1)) + const expectedMemberBond = unbondedAmount await depositMemberCandidates(unbondedAmount) @@ -1073,7 +1077,7 @@ describe("FullyBackedECDSAKeepFactory", function () { // create and authorize enough operators to perform the test; // we need more than the default 10 accounts - await createDepositAndRegisterMembers(groupSize, singleBond) + await createDepositAndRegisterMembers(groupSize) const blockNumber = await web3.eth.getBlockNumber() @@ -1461,12 +1465,9 @@ describe("FullyBackedECDSAKeepFactory", function () { await initializeMemberCandidates() await registerMemberCandidates() - const poolAddress = await keepFactory.getSortitionPool(application) - const pool = await FullyBackedSortitionPool.at(poolAddress) - const poolWeight = await keepFactory.getSortitionPoolWeight(application) - const expectedPoolWeight = (await pool.getMinimumBondableValue()) + const expectedPoolWeight = minimumDelegationDeposit .div(await keepFactory.bondWeightDivisor.call()) .muln(3) expect(poolWeight).to.eq.BN( @@ -1540,7 +1541,7 @@ describe("FullyBackedECDSAKeepFactory", function () { } async function initializeMemberCandidates(unbondedValue) { - const minimumBond = await keepFactory.minimumBond.call() + const minimumDelegationValue = await bonding.MINIMUM_DELEGATION_DEPOSIT.call() signerPool = await keepFactory.createSortitionPool.call(application) await keepFactory.createSortitionPool(application) @@ -1550,7 +1551,7 @@ describe("FullyBackedECDSAKeepFactory", function () { members[i], members[i], authorizers[i], - unbondedValue || minimumBond + unbondedValue || minimumDelegationValue ) } From a1ea59b3db570d1cb21e5a99e240e276162405ad Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 30 Oct 2020 15:55:20 +0100 Subject: [PATCH 39/57] Decided on 20 ETH as minimum bond value As agreed in https://github.com/keep-network/keep-ecdsa/pull/483#discussion_r515085932 Also replaced e18 with ether which improves readability. --- .../contracts/fully-backed/FullyBackedECDSAKeepFactory.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol b/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol index 15f51b401..59cad0060 100644 --- a/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol +++ b/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol @@ -57,13 +57,13 @@ contract FullyBackedECDSAKeepFactory is // Anyone can create a sortition pool for an application with the default // minimum bond value but the application can change this value later, at // any point. - uint256 public constant minimumBond = 20e18; // 20 ETH // TODO: Decide on value + uint256 public constant minimumBond = 20 ether; // Signer candidates in bonded sortition pool are weighted by their eligible // stake divided by a constant divisor. The divisor is set to 1 ETH so that // all ETHs in available unbonded value matter when calculating operator's // eligible weight for signer selection. - uint256 public constant bondWeightDivisor = 1e18; // 1 ETH + uint256 public constant bondWeightDivisor = 1 ether; // Notification that a new keep has been created. event FullyBackedECDSAKeepCreated( From e4c9d82c8c28aa565520b9f2ee6f555f0f4e0831 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 30 Oct 2020 16:09:59 +0100 Subject: [PATCH 40/57] Improved time increase value in test By subtracting 1 we will get more stable test results --- solidity/test/FullyBackedBondingTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solidity/test/FullyBackedBondingTest.js b/solidity/test/FullyBackedBondingTest.js index 7b9223587..d7d1018f1 100644 --- a/solidity/test/FullyBackedBondingTest.js +++ b/solidity/test/FullyBackedBondingTest.js @@ -395,7 +395,7 @@ describe("FullyBackedBonding", function () { from: authorizer, }) - await time.increase(initializationPeriod) + await time.increase(initializationPeriod.subn(1)) assert.isFalse(await bonding.isInitialized(operator, bondCreator)) }) From ff5008c95eef688fcc89624963c35229c05f3443 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 30 Oct 2020 16:10:52 +0100 Subject: [PATCH 41/57] Updated delegation lock period to 12 hours As agreed in https://github.com/keep-network/keep-ecdsa/pull/483#discussion_r514996888 --- solidity/contracts/fully-backed/FullyBackedBonding.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solidity/contracts/fully-backed/FullyBackedBonding.sol b/solidity/contracts/fully-backed/FullyBackedBonding.sol index 064c6a573..cb31751ec 100644 --- a/solidity/contracts/fully-backed/FullyBackedBonding.sol +++ b/solidity/contracts/fully-backed/FullyBackedBonding.sol @@ -48,7 +48,7 @@ contract FullyBackedBonding is // Once a delegation to an operator is received the delegator has to wait for // specific time period before being able to pull out the funds. - uint256 public constant DELEGATION_LOCK_PERIOD = 14 days; // TODO: Decide right value + uint256 public constant DELEGATION_LOCK_PERIOD = 12 hours; uint256 public initializationPeriod; // varies between mainnet and testnet From 0c0475ac4a53e99065bc045e7018874a3a1f391f Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 30 Oct 2020 16:35:39 +0100 Subject: [PATCH 42/57] Improved docs around fully backed bonding --- .../contracts/fully-backed/FullyBackedBonding.sol | 5 ++--- .../fully-backed/FullyBackedECDSAKeepFactory.sol | 11 +++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/solidity/contracts/fully-backed/FullyBackedBonding.sol b/solidity/contracts/fully-backed/FullyBackedBonding.sol index cb31751ec..2b3f16f1b 100644 --- a/solidity/contracts/fully-backed/FullyBackedBonding.sol +++ b/solidity/contracts/fully-backed/FullyBackedBonding.sol @@ -24,9 +24,8 @@ import "@keep-network/sortition-pools/contracts/api/IFullyBackedBonding.sol"; /// @title Fully Backed Bonding /// @notice Contract holding deposits and delegations for ETH-only keeps' -/// operators. An owner of the ETH can delegate ETH to an operator. The value -/// of ETH the owner is willing to delegate should be deposited for the given -/// operator. +/// operators. An owner of the ETH can delegate ETH to an operator by depositing +/// it in this contract. contract FullyBackedBonding is IFullyBackedBonding, AbstractBonding, diff --git a/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol b/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol index 59cad0060..9793310d1 100644 --- a/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol +++ b/solidity/contracts/fully-backed/FullyBackedECDSAKeepFactory.sol @@ -57,6 +57,17 @@ contract FullyBackedECDSAKeepFactory is // Anyone can create a sortition pool for an application with the default // minimum bond value but the application can change this value later, at // any point. + // + // The minimum bond value is a boundary value for an operator to remain + // in the sortition pool. Once operator's unbonded value drops below the + // minimum bond value the operator is removed from the sortition pool. + // Operator can top-up the unbonded value deposited in bonding contract + // and re-register to the sortition pool. + // + // This property is configured along with `MINIMUM_DELEGATION_DEPOSIT` defined + // in `FullyBackedBonding` contract. Minimum delegation deposit determines + // a minimum value of ether that should be transferred to the bonding contract + // by an owner when delegating to an operator. uint256 public constant minimumBond = 20 ether; // Signer candidates in bonded sortition pool are weighted by their eligible From ae34de46ec3636ace9259f619cd65e65bbb7d55d Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 30 Oct 2020 16:38:39 +0100 Subject: [PATCH 43/57] Cleaned up truffle deploy script --- solidity/migrations/2_deploy_contracts.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/solidity/migrations/2_deploy_contracts.js b/solidity/migrations/2_deploy_contracts.js index dd6405a28..b605f0d3c 100644 --- a/solidity/migrations/2_deploy_contracts.js +++ b/solidity/migrations/2_deploy_contracts.js @@ -14,8 +14,6 @@ const FullyBackedECDSAKeepFactory = artifacts.require( "FullyBackedECDSAKeepFactory" ) -const EthBonding = artifacts.require("EthBonding") - const { deployBondedSortitionPoolFactory, deployFullyBackedSortitionPoolFactory, @@ -51,7 +49,7 @@ module.exports = async function (deployer) { RegistryAddress = (await deployer.deploy(KeepRegistry)).address } - // KEEP and ETH backed bonding + // KEEP staking and ETH bonding await deployer.deploy( KeepBonding, RegistryAddress, @@ -84,7 +82,7 @@ module.exports = async function (deployer) { implInitializeCallData ) - // ETH-only Staking + // ETH bonding only await deployer.deploy(FullyBackedBonding, RegistryAddress) await deployer.deploy(FullyBackedECDSAKeep) @@ -96,7 +94,4 @@ module.exports = async function (deployer) { FullyBackedBonding.address, RandomBeaconAddress ) - - // ETH-only backed bonding - await deployer.deploy(EthBonding, RegistryAddress) } From 25c6a4d306efd54ba88a34b017bc64aec8dc05a9 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 30 Oct 2020 16:51:41 +0100 Subject: [PATCH 44/57] Assert createdAt and undelegatedAt in delegation test --- solidity/test/FullyBackedBondingTest.js | 28 +++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/solidity/test/FullyBackedBondingTest.js b/solidity/test/FullyBackedBondingTest.js index d7d1018f1..1dee0fff1 100644 --- a/solidity/test/FullyBackedBondingTest.js +++ b/solidity/test/FullyBackedBondingTest.js @@ -62,10 +62,15 @@ describe("FullyBackedBonding", function () { describe("delegate", async () => { it("registers delegation", async () => { - await bonding.delegate(operator, beneficiary, authorizer, { - from: owner, - value: minimumDelegationValue, - }) + const {receipt} = await bonding.delegate( + operator, + beneficiary, + authorizer, + { + from: owner, + value: minimumDelegationValue, + } + ) assert.equal( await bonding.ownerOf(operator), @@ -89,6 +94,21 @@ describe("FullyBackedBonding", function () { 0, "incorrect delegation balance" ) + + const {timestamp: expectedCreatedAt} = await web3.eth.getBlock( + receipt.blockNumber + ) + + const {createdAt, undelegatedAt} = await bonding.getDelegationInfo( + operator + ) + + expect(createdAt).to.eq.BN( + expectedCreatedAt, + "incorrect created at value" + ) + + expect(undelegatedAt).to.eq.BN(0, "incorrect undelegated at value") }) it("emits events", async () => { From faca5bdce46d00a359e415142cc245a424cbbfe0 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 30 Oct 2020 17:05:55 +0100 Subject: [PATCH 45/57] Cleaned truffle init script --- solidity/migrations/3_initialize.js | 1 - 1 file changed, 1 deletion(-) diff --git a/solidity/migrations/3_initialize.js b/solidity/migrations/3_initialize.js index c5340fdd4..ef829aa81 100644 --- a/solidity/migrations/3_initialize.js +++ b/solidity/migrations/3_initialize.js @@ -12,7 +12,6 @@ const {RegistryAddress} = require("./external-contracts") module.exports = async function (deployer) { await BondedECDSAKeepFactory.deployed() - await BondedECDSAKeepFactory.deployed() let registry if (process.env.TEST) { From 03daf5f478e921c6c89951e1a4c75846c4b85598 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 30 Oct 2020 17:06:36 +0100 Subject: [PATCH 46/57] Removed not used addKeep function from test stubs --- solidity/contracts/test/BondedECDSAKeepFactoryStub.sol | 10 +++------- .../contracts/test/FullyBackedECDSAKeepFactoryStub.sol | 6 ------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/solidity/contracts/test/BondedECDSAKeepFactoryStub.sol b/solidity/contracts/test/BondedECDSAKeepFactoryStub.sol index 518b93496..594579bff 100644 --- a/solidity/contracts/test/BondedECDSAKeepFactoryStub.sol +++ b/solidity/contracts/test/BondedECDSAKeepFactoryStub.sol @@ -30,12 +30,6 @@ contract BondedECDSAKeepFactoryStub is BondedECDSAKeepFactory { return groupSelectionSeed; } - function addKeep(address keep) public { - keeps.push(keep); - /* solium-disable-next-line security/no-block-members*/ - keepOpenedTimestamp[keep] = block.timestamp; - } - /// @notice Opens a new ECDSA keep. /// @param _owner Address of the keep owner. /// @param _members Keep members. @@ -75,7 +69,9 @@ contract BondedECDSAKeepFactoryStub is BondedECDSAKeepFactory { for (uint256 i = 0; i < _numberOfKeeps; i++) { address keepAddress = address(block.timestamp.add(i)); keeps.push(keepAddress); - keepOpenedTimestamp[keepAddress] = _firstKeepCreationTimestamp.add(i); + keepOpenedTimestamp[keepAddress] = _firstKeepCreationTimestamp.add( + i + ); } } } diff --git a/solidity/contracts/test/FullyBackedECDSAKeepFactoryStub.sol b/solidity/contracts/test/FullyBackedECDSAKeepFactoryStub.sol index da4eca92e..7bca679fb 100644 --- a/solidity/contracts/test/FullyBackedECDSAKeepFactoryStub.sol +++ b/solidity/contracts/test/FullyBackedECDSAKeepFactoryStub.sol @@ -27,10 +27,4 @@ contract FullyBackedECDSAKeepFactoryStub is FullyBackedECDSAKeepFactory { function getGroupSelectionSeed() public view returns (uint256) { return groupSelectionSeed; } - - function addKeep(address keep) public { - keeps.push(keep); - /* solium-disable-next-line security/no-block-members*/ - keepOpenedTimestamp[keep] = block.timestamp; - } } From 196880a6dd06d577b7df3f7009a0c4209ff94cd9 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Fri, 30 Oct 2020 17:07:53 +0100 Subject: [PATCH 47/57] Improved time increase margin in tests --- solidity/test/FullyBackedBondingTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solidity/test/FullyBackedBondingTest.js b/solidity/test/FullyBackedBondingTest.js index 1dee0fff1..9858b21d3 100644 --- a/solidity/test/FullyBackedBondingTest.js +++ b/solidity/test/FullyBackedBondingTest.js @@ -291,7 +291,7 @@ describe("FullyBackedBonding", function () { from: authorizer, }) - await time.increase(delegationLockPeriod) + await time.increase(delegationLockPeriod.subn(1)) await expectRevert( bonding.withdraw(value, operator2, {from: owner}), From ee9a30b226d00f5da8ef3b3be2877a218854ab08 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Mon, 2 Nov 2020 11:36:16 +0100 Subject: [PATCH 48/57] Removed not needed TODO comment in test --- solidity/test/FullyBackedECDSAKeepFactoryTest.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/solidity/test/FullyBackedECDSAKeepFactoryTest.js b/solidity/test/FullyBackedECDSAKeepFactoryTest.js index f3e61aebc..65f0c8cf6 100644 --- a/solidity/test/FullyBackedECDSAKeepFactoryTest.js +++ b/solidity/test/FullyBackedECDSAKeepFactoryTest.js @@ -351,9 +351,6 @@ describe("FullyBackedECDSAKeepFactory", function () { minimumBondableValue = await pool.getMinimumBondableValue() }) - // TODO: Add a case to check if operator is initialized - // github.com/keep-network/sortition-pools/blob/413abd66536032ee757f190a29fda2705c7b70cf/contracts/FullyBackedSortitionPool.sol#L155 - it("returns true if the operator is up to date for the application", async () => { await keepFactory.registerMemberCandidate(application, { from: members[0], From 65186c97167045281f833f01f3a5a1efba5e9200 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Mon, 2 Nov 2020 12:02:24 +0100 Subject: [PATCH 49/57] Very minor improvements to tests --- solidity/test/FullyBackedECDSAKeepFactoryTest.js | 2 +- solidity/test/FullyBackedECDSAKeepTest.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/solidity/test/FullyBackedECDSAKeepFactoryTest.js b/solidity/test/FullyBackedECDSAKeepFactoryTest.js index 65f0c8cf6..919214c72 100644 --- a/solidity/test/FullyBackedECDSAKeepFactoryTest.js +++ b/solidity/test/FullyBackedECDSAKeepFactoryTest.js @@ -420,7 +420,7 @@ describe("FullyBackedECDSAKeepFactory", function () { ) }) - it("returns false if the operator stake dropped below minimum", async () => { + it("returns false if the operator bonding value dropped below minimum", async () => { await keepFactory.registerMemberCandidate(application, { from: members[0], }) diff --git a/solidity/test/FullyBackedECDSAKeepTest.js b/solidity/test/FullyBackedECDSAKeepTest.js index fa96c6adf..cab27c623 100644 --- a/solidity/test/FullyBackedECDSAKeepTest.js +++ b/solidity/test/FullyBackedECDSAKeepTest.js @@ -460,7 +460,7 @@ describe("FullyBackedECDSAKeep", function () { // as they are registered in the keep. We want to stress this scenario // and confirm that logic works correctly in such sophisticated scenario. - // First member submits a public key, there are not conflicts. + // First member submits a public key, there are no conflicts. let startBlock = await web3.eth.getBlockNumber() await keep.submitPublicKey(publicKey1, {from: members[2]}) assert.lengthOf( From b92218cf33a4777e2e59e61324693dbdf1ea571e Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Mon, 2 Nov 2020 12:09:24 +0100 Subject: [PATCH 50/57] Get delegation lock period from contract in tests --- solidity/test/FullyBackedECDSAKeepFactoryTest.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/solidity/test/FullyBackedECDSAKeepFactoryTest.js b/solidity/test/FullyBackedECDSAKeepFactoryTest.js index 919214c72..7e5ed26f1 100644 --- a/solidity/test/FullyBackedECDSAKeepFactoryTest.js +++ b/solidity/test/FullyBackedECDSAKeepFactoryTest.js @@ -37,6 +37,7 @@ describe("FullyBackedECDSAKeepFactory", function () { let randomBeacon let signerPool let minimumDelegationDeposit + let delegationLockPeriod const application = accounts[1] const members = [accounts[2], accounts[3], accounts[4]] @@ -54,7 +55,6 @@ describe("FullyBackedECDSAKeepFactory", function () { const stakeLockDuration = 0 // parameter is ignored by FullyBackedECDSAKeepFactory implementation const delegationInitPeriod = time.duration.hours(12) - const delegationLockPeriod = time.duration.days(14) before(async () => { await FullyBackedSortitionPoolFactory.detectNetwork() @@ -1533,6 +1533,7 @@ describe("FullyBackedECDSAKeepFactory", function () { ) minimumDelegationDeposit = await bonding.MINIMUM_DELEGATION_DEPOSIT.call() + delegationLockPeriod = await bonding.DELEGATION_LOCK_PERIOD.call() await registry.approveOperatorContract(keepFactory.address) } From 766a8415c29d4f64e3d0b75d9419cccc655bad76 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Mon, 2 Nov 2020 12:24:17 +0100 Subject: [PATCH 51/57] Removed not needed call in initialization script --- solidity/migrations/3_initialize.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/solidity/migrations/3_initialize.js b/solidity/migrations/3_initialize.js index ef829aa81..887a8931a 100644 --- a/solidity/migrations/3_initialize.js +++ b/solidity/migrations/3_initialize.js @@ -11,8 +11,6 @@ const KeepRegistry = artifacts.require("KeepRegistry") const {RegistryAddress} = require("./external-contracts") module.exports = async function (deployer) { - await BondedECDSAKeepFactory.deployed() - let registry if (process.env.TEST) { registry = await KeepRegistry.deployed() From 8a4ff8225432b97b59fed263548b0d13739777b6 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Mon, 2 Nov 2020 12:24:56 +0100 Subject: [PATCH 52/57] Defined ini period in truffle deployment script --- solidity/migrations/2_deploy_contracts.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/solidity/migrations/2_deploy_contracts.js b/solidity/migrations/2_deploy_contracts.js index b605f0d3c..88df8c8dc 100644 --- a/solidity/migrations/2_deploy_contracts.js +++ b/solidity/migrations/2_deploy_contracts.js @@ -25,6 +25,8 @@ const FullyBackedSortitionPoolFactory = artifacts.require( "FullyBackedSortitionPoolFactory" ) +let initializationPeriod = 43200 // 12 hours in seconds + let { RandomBeaconAddress, TokenStakingAddress, @@ -32,7 +34,12 @@ let { RegistryAddress, } = require("./external-contracts") -module.exports = async function (deployer) { +module.exports = async function (deployer, network) { + // Set the stake initialization period to 1 second for local development and testnet. + if (network === "local" || network === "ropsten" || network === "keep_dev") { + initializationPeriod = 1 + } + await deployBondedSortitionPoolFactory(artifacts, deployer) await deployFullyBackedSortitionPoolFactory(artifacts, deployer) @@ -83,7 +90,11 @@ module.exports = async function (deployer) { ) // ETH bonding only - await deployer.deploy(FullyBackedBonding, RegistryAddress) + await deployer.deploy( + FullyBackedBonding, + RegistryAddress, + initializationPeriod + ) await deployer.deploy(FullyBackedECDSAKeep) From 3778ae14b8298ad9de3eb02fbcc355bc2cb8bad0 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Mon, 2 Nov 2020 13:18:59 +0100 Subject: [PATCH 53/57] Added tests for operator updates --- .../test/FullyBackedECDSAKeepFactoryTest.js | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/solidity/test/FullyBackedECDSAKeepFactoryTest.js b/solidity/test/FullyBackedECDSAKeepFactoryTest.js index 7e5ed26f1..c12b8f293 100644 --- a/solidity/test/FullyBackedECDSAKeepFactoryTest.js +++ b/solidity/test/FullyBackedECDSAKeepFactoryTest.js @@ -453,6 +453,8 @@ describe("FullyBackedECDSAKeepFactory", function () { const pool = await FullyBackedSortitionPool.at(signerPool) minimumBondableValue = await pool.getMinimumBondableValue() + + await setUnbondedValue(members[0], minimumBondableValue.muln(3)) }) it("revers if operator is up to date", async () => { @@ -462,7 +464,7 @@ describe("FullyBackedECDSAKeepFactory", function () { ) }) - it("removes operator if bonding value has changed below minimum", async () => { + it("removes operator if bonding value has decreased below minimum", async () => { currentValue = await bonding.unbondedValue(members[0]) const valueToWithdraw = currentValue.sub(minimumBondableValue).addn(1) @@ -481,7 +483,7 @@ describe("FullyBackedECDSAKeepFactory", function () { ) }) - it("updates operator if bonding value has changed above minimum", async () => { + it("does not update operator if bonding value increased insignificantly above minimum", async () => { bonding.deposit(members[0], {value: new BN(1)}) assert.isTrue( await keepFactory.isOperatorUpToDate(members[0], application), @@ -494,6 +496,58 @@ describe("FullyBackedECDSAKeepFactory", function () { ) }) + it("updates operator if bonding value increased significantly above minimum", async () => { + bonding.deposit(members[0], {value: minimumBondableValue.muln(2)}) + + assert.isFalse( + await keepFactory.isOperatorUpToDate(members[0], application), + "unexpected status of the operator after stake change" + ) + + await keepFactory.updateOperatorStatus(members[0], application) + + assert.isTrue( + await keepFactory.isOperatorUpToDate(members[0], application), + "unexpected status of the operator after status update" + ) + }) + + it("updates operator if bonding value decreased insignificantly above minimum", async () => { + bonding.withdraw(new BN(1), members[0], {from: members[0]}) + + assert.isFalse( + await keepFactory.isOperatorUpToDate(members[0], application), + "unexpected status of the operator after stake change" + ) + + await keepFactory.updateOperatorStatus(members[0], application) + + assert.isTrue( + await keepFactory.isOperatorUpToDate(members[0], application), + "unexpected status of the operator after status update" + ) + }) + + it("updates operator if bonding value decreased significantly above minimum", async () => { + currentValue = await bonding.unbondedValue(members[0]) + + const valueToWithdraw = currentValue.sub(minimumBondableValue).subn(1) + + bonding.withdraw(valueToWithdraw, members[0], {from: members[0]}) + + assert.isFalse( + await keepFactory.isOperatorUpToDate(members[0], application), + "unexpected status of the operator after stake change" + ) + + await keepFactory.updateOperatorStatus(members[0], application) + + assert.isTrue( + await keepFactory.isOperatorUpToDate(members[0], application), + "unexpected status of the operator after status update" + ) + }) + it("reverts if the operator is not registered for the application", async () => { await initializeNewFactory() await initializeMemberCandidates() From cf0127cd2011f53e8889107d1ccaf3db48548ecf Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Mon, 2 Nov 2020 13:42:55 +0100 Subject: [PATCH 54/57] Added top up function to Fully Backed Bonding contract We defined a `topUp` function in `FullyBackedBonding` contract. This function should be used when adding new value for bonding. We emitt an additional event to clearly find value that has been deposited. The `deposit` function defined in the abstract contract can be used also by applications that return part of seized value to the contract. This made calculation of totally deposited value much more difficult. --- .../fully-backed/FullyBackedBonding.sol | 14 ++++++ solidity/test/FullyBackedBondingTest.js | 48 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/solidity/contracts/fully-backed/FullyBackedBonding.sol b/solidity/contracts/fully-backed/FullyBackedBonding.sol index 2b3f16f1b..4c9ee81f7 100644 --- a/solidity/contracts/fully-backed/FullyBackedBonding.sol +++ b/solidity/contracts/fully-backed/FullyBackedBonding.sol @@ -41,6 +41,8 @@ contract FullyBackedBonding is uint256 value ); + event OperatorToppedUp(address indexed operator, uint256 value); + // The ether value (in wei) that should be passed along with the delegation // and deposited for bonding. uint256 public constant MINIMUM_DELEGATION_DEPOSIT = 40 ether; @@ -104,6 +106,18 @@ contract FullyBackedBonding is emit OperatorDelegated(operator, beneficiary, authorizer, msg.value); } + /// @notice Top-ups operator's unbonded value. + /// @dev This function should be used to add new unbonded value to the system + /// for an operator. The `deposit` function defined in parent abstract contract + /// should be called only by applications returning value that has been already + /// initially deposited and seized later. + /// @param operator Address of the operator. + function topUp(address operator) public payable { + deposit(operator); + + emit OperatorToppedUp(operator, msg.value); + } + /// @notice Checks if the operator for the given bond creator contract /// has passed the initialization period. /// @param operator The operator address. diff --git a/solidity/test/FullyBackedBondingTest.js b/solidity/test/FullyBackedBondingTest.js index 9858b21d3..2ca360f73 100644 --- a/solidity/test/FullyBackedBondingTest.js +++ b/solidity/test/FullyBackedBondingTest.js @@ -204,6 +204,54 @@ describe("FullyBackedBonding", function () { }) }) + describe("topUp", async () => { + const value = new BN(123) + + let initialDeposit + + before(async () => { + initialDeposit = minimumDelegationValue + + await bonding.delegate(operator, beneficiary, authorizer, { + from: owner, + value: initialDeposit, + }) + }) + + it("adds value to deposited on delegation", async () => { + const expectedFinalBalance = initialDeposit.add(value) + + await bonding.topUp(operator, { + value: value, + }) + + expect(await bonding.unbondedValue(operator)).to.eq.BN( + expectedFinalBalance, + "invalid final unbonded value" + ) + }) + + it("emits event", async () => { + const receipt = await bonding.topUp(operator, { + value: value, + }) + + expectEvent(receipt, "OperatorToppedUp", { + operator: operator, + value: value, + }) + }) + + it("reverts when no delegation happened", async () => { + await expectRevert( + bonding.topUp(thirdParty, { + value: new BN(123), + }), + "Beneficiary not defined for the operator" + ) + }) + }) + describe("deposit", async () => { it("adds value to deposited on delegation", async () => { const initialDeposit = minimumDelegationValue From 102ce154274a2fe7b30fa888378ed891414b975a Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Mon, 2 Nov 2020 13:56:11 +0100 Subject: [PATCH 55/57] Fixed failing test --- solidity/test/FullyBackedECDSAKeepFactoryTest.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/solidity/test/FullyBackedECDSAKeepFactoryTest.js b/solidity/test/FullyBackedECDSAKeepFactoryTest.js index c12b8f293..aac804220 100644 --- a/solidity/test/FullyBackedECDSAKeepFactoryTest.js +++ b/solidity/test/FullyBackedECDSAKeepFactoryTest.js @@ -455,9 +455,10 @@ describe("FullyBackedECDSAKeepFactory", function () { minimumBondableValue = await pool.getMinimumBondableValue() await setUnbondedValue(members[0], minimumBondableValue.muln(3)) + await keepFactory.updateOperatorStatus(members[0], application) }) - it("revers if operator is up to date", async () => { + it("reverts if operator is up to date", async () => { await expectRevert( keepFactory.updateOperatorStatus(members[0], application), "Operator already up to date" From dc040216070724ee84ded605442a5922e165219c Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Mon, 2 Nov 2020 14:08:07 +0100 Subject: [PATCH 56/57] Replaced before with beforeEach for topUp test --- solidity/test/FullyBackedBondingTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solidity/test/FullyBackedBondingTest.js b/solidity/test/FullyBackedBondingTest.js index 2ca360f73..5923fda97 100644 --- a/solidity/test/FullyBackedBondingTest.js +++ b/solidity/test/FullyBackedBondingTest.js @@ -209,7 +209,7 @@ describe("FullyBackedBonding", function () { let initialDeposit - before(async () => { + beforeEach(async () => { initialDeposit = minimumDelegationValue await bonding.delegate(operator, beneficiary, authorizer, { From f9f719aa0c0e5d8da6658aee1a40f05c5ba993b9 Mon Sep 17 00:00:00 2001 From: Jakub Nowakowski Date: Mon, 2 Nov 2020 14:16:39 +0100 Subject: [PATCH 57/57] Added details to topup documentation --- solidity/contracts/fully-backed/FullyBackedBonding.sol | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/solidity/contracts/fully-backed/FullyBackedBonding.sol b/solidity/contracts/fully-backed/FullyBackedBonding.sol index 4c9ee81f7..5f49805ba 100644 --- a/solidity/contracts/fully-backed/FullyBackedBonding.sol +++ b/solidity/contracts/fully-backed/FullyBackedBonding.sol @@ -110,7 +110,12 @@ contract FullyBackedBonding is /// @dev This function should be used to add new unbonded value to the system /// for an operator. The `deposit` function defined in parent abstract contract /// should be called only by applications returning value that has been already - /// initially deposited and seized later. + /// initially deposited and seized later. As an application may seize bonds + /// and return them to the bonding contract with `deposit` function it makes + /// tracking the totally deposited value much more complicated. Functions + /// `delegate` and `topUps` should be used to add fresh value to the contract + /// and events emitted by these functions should be enough to determine total + /// value deposited ever for an operator. /// @param operator Address of the operator. function topUp(address operator) public payable { deposit(operator);