diff --git a/REWARD_MANAGEMENT.md b/REWARD_MANAGEMENT.md index 270655cf1..0ed6b0d16 100644 --- a/REWARD_MANAGEMENT.md +++ b/REWARD_MANAGEMENT.md @@ -19,3 +19,13 @@ Fees are calculated and distributed on Home network. Validators will receive nat ### Home to Foreign transfer Fees are calculated and distributed on Home network. Validators will receive native coins. ![erc-native-hometoforeign](https://user-images.githubusercontent.com/4614574/51607508-96f47480-1ef3-11e9-93a1-0f1111793f2a.png) + +## ERC-TO-ERC + +### Foreign to Home transfer +Fees are calculated and distributed on Home network. Validators will receive ERC20 tokens. +![ERC-ERC-ForeignToHome (1)](https://user-images.githubusercontent.com/4614574/56502412-98c8d680-64e8-11e9-8eea-5bcd545d74d9.png) + +### Home to Foreign transfer +Fees are calculated and distributed on Home network. Validators will receive ERC20 tokens. +![ERC-ERC-HomeToForeign (1)](https://user-images.githubusercontent.com/4614574/56502454-b8f89580-64e8-11e9-84ae-d9a1c229e0c4.png) diff --git a/contracts/IBlockReward.sol b/contracts/IBlockReward.sol index 2d9e1b89a..b4a2da589 100644 --- a/contracts/IBlockReward.sol +++ b/contracts/IBlockReward.sol @@ -6,4 +6,5 @@ interface IBlockReward { function mintedTotally() public view returns (uint256); function mintedTotallyByBridge(address _bridge) public view returns(uint256); function bridgesAllowedLength() external view returns(uint256); + function addBridgeTokenFeeReceivers(uint256 _amount) external; } diff --git a/contracts/test/BlockReward.sol b/contracts/test/BlockReward.sol index ea5c4cfa9..7a9b868b2 100644 --- a/contracts/test/BlockReward.sol +++ b/contracts/test/BlockReward.sol @@ -7,9 +7,12 @@ import "../libraries/SafeMath.sol"; contract BlockReward is IBlockReward { using SafeMath for uint256; + address[] public validatorList; uint256 public mintedCoins = 0; + uint256 public feeAmount = 0; mapping(bytes32 => uint256) internal uintStorage; bytes32 internal constant MINTED_TOTALLY_BY_BRIDGE = "mintedTotallyByBridge"; + address public token; function () external payable { } @@ -40,4 +43,40 @@ contract BlockReward is IBlockReward { bytes32 hash = keccak256(abi.encode(MINTED_TOTALLY_BY_BRIDGE, _bridge)); uintStorage[hash] = uintStorage[hash].add(_amount); } + + function setValidatorsRewards(address[] _initialValidators) external { + validatorList = _initialValidators; + } + + function setToken(address _token) external { + token = _token; + } + + function addBridgeTokenFeeReceivers(uint256 _amount) external { + address[] memory receivers = new address[](validatorList.length); + uint256[] memory rewards = new uint256[](validatorList.length); + feeAmount = _amount; + uint256 feePerValidator = _amount.div(validatorList.length); + + uint256 randomValidatorIndex; + uint256 diff = _amount.sub(feePerValidator.mul(validatorList.length)); + if (diff > 0) { + randomValidatorIndex = random(validatorList.length); + } + + for (uint256 i = 0; i < validatorList.length; i++) { + uint256 feeToDistribute = feePerValidator; + if (diff > 0 && randomValidatorIndex == i) { + feeToDistribute = feeToDistribute.add(diff); + } + receivers[i] = validatorList[i]; + rewards[i] = feeToDistribute; + } + + require(token.call(abi.encodeWithSignature("mintReward(address[],uint256[])", receivers, rewards))); + } + + function random(uint256 _count) public view returns(uint256) { + return uint256(blockhash(block.number.sub(1))) % _count; + } } diff --git a/contracts/upgradeable_contracts/BaseFeeManager.sol b/contracts/upgradeable_contracts/BaseFeeManager.sol index 52eb98865..3b2f668d0 100644 --- a/contracts/upgradeable_contracts/BaseFeeManager.sol +++ b/contracts/upgradeable_contracts/BaseFeeManager.sol @@ -9,10 +9,6 @@ import "./FeeTypes.sol"; contract BaseFeeManager is EternalStorage, FeeTypes { using SafeMath for uint256; - bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_HOME = keccak256(abi.encodePacked("reward-transferring-from-home")); - - bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_FOREIGN = keccak256(abi.encodePacked("reward-transferring-from-foreign")); - event HomeFeeUpdated(uint256 fee); event ForeignFeeUpdated(uint256 fee); @@ -43,54 +39,13 @@ contract BaseFeeManager is EternalStorage, FeeTypes { return uintStorage[keccak256(abi.encodePacked("foreignFee"))]; } - function distributeFeeFromAffirmation(uint256 _fee) external { - distributeFeeProportionally(_fee, REWARD_FOR_TRANSFERRING_FROM_FOREIGN); - } + function distributeFeeFromAffirmation(uint256 _fee) external; - function distributeFeeFromSignatures(uint256 _fee) external { - distributeFeeProportionally(_fee, REWARD_FOR_TRANSFERRING_FROM_HOME); - } + function distributeFeeFromSignatures(uint256 _fee) external; function getFeeManagerMode() public pure returns(bytes4); function random(uint256 _count) public view returns(uint256) { return uint256(blockhash(block.number.sub(1))) % _count; } - - function distributeFeeProportionally(uint256 _fee, bytes32 _direction) internal { - IRewardableValidators validators = rewardableValidatorContract(); - address[] memory validatorList = validators.validatorList(); - uint256 feePerValidator = _fee.div(validatorList.length); - - uint256 randomValidatorIndex; - uint256 diff = _fee.sub(feePerValidator.mul(validatorList.length)); - if (diff > 0) { - randomValidatorIndex = random(validatorList.length); - } - - for (uint256 i = 0; i < validatorList.length; i++) { - uint256 feeToDistribute = feePerValidator; - if (diff > 0 && randomValidatorIndex == i) { - feeToDistribute = feeToDistribute.add(diff); - } - address rewardAddress = validators.getValidatorRewardAddress(validatorList[i]); - onFeeDistribution(rewardAddress, feeToDistribute, _direction); - } - } - - function onFeeDistribution(address _rewardAddress, uint256 _fee, bytes32 _direction) internal { - if (_direction == REWARD_FOR_TRANSFERRING_FROM_FOREIGN) { - onAffirmationFeeDistribution(_rewardAddress, _fee); - } else { - onSignatureFeeDistribution(_rewardAddress, _fee); - } - } - - function onAffirmationFeeDistribution(address _rewardAddress, uint256 _fee) internal; - - function onSignatureFeeDistribution(address _rewardAddress, uint256 _fee) internal; - - function rewardableValidatorContract() public view returns(IRewardableValidators) { - return IRewardableValidators(addressStorage[keccak256(abi.encodePacked("validatorContract"))]); - } } diff --git a/contracts/upgradeable_contracts/BlockRewardFeeManager.sol b/contracts/upgradeable_contracts/BlockRewardFeeManager.sol new file mode 100644 index 000000000..cfdeedc6f --- /dev/null +++ b/contracts/upgradeable_contracts/BlockRewardFeeManager.sol @@ -0,0 +1,24 @@ +pragma solidity 0.4.24; + +import "./BaseFeeManager.sol"; +import "../IBlockReward.sol"; + +contract BlockRewardFeeManager is BaseFeeManager { + + function distributeFeeFromAffirmation(uint256 _fee) external { + distributeFeeFromBlockReward(_fee); + } + + function distributeFeeFromSignatures(uint256 _fee) external { + distributeFeeFromBlockReward(_fee); + } + + function distributeFeeFromBlockReward(uint256 _fee) internal { + IBlockReward blockReward = _blockRewardContract(); + blockReward.addBridgeTokenFeeReceivers(_fee); + } + + function _blockRewardContract() internal view returns(IBlockReward) { + return IBlockReward(addressStorage[keccak256(abi.encodePacked("blockRewardContract"))]); + } +} diff --git a/contracts/upgradeable_contracts/ValidatorsFeeManager.sol b/contracts/upgradeable_contracts/ValidatorsFeeManager.sol new file mode 100644 index 000000000..0f7f32b0d --- /dev/null +++ b/contracts/upgradeable_contracts/ValidatorsFeeManager.sol @@ -0,0 +1,56 @@ +pragma solidity 0.4.24; + +import "./BaseFeeManager.sol"; +import "../IRewardableValidators.sol"; + +contract ValidatorsFeeManager is BaseFeeManager { + + bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_HOME = keccak256(abi.encodePacked("reward-transferring-from-home")); + + bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_FOREIGN = keccak256(abi.encodePacked("reward-transferring-from-foreign")); + + function distributeFeeFromAffirmation(uint256 _fee) external { + distributeFeeProportionally(_fee, REWARD_FOR_TRANSFERRING_FROM_FOREIGN); + } + + function distributeFeeFromSignatures(uint256 _fee) external { + distributeFeeProportionally(_fee, REWARD_FOR_TRANSFERRING_FROM_HOME); + } + + function rewardableValidatorContract() internal view returns(IRewardableValidators) { + return IRewardableValidators(addressStorage[keccak256(abi.encodePacked("validatorContract"))]); + } + + function distributeFeeProportionally(uint256 _fee, bytes32 _direction) internal { + IRewardableValidators validators = rewardableValidatorContract(); + address[] memory validatorList = validators.validatorList(); + uint256 feePerValidator = _fee.div(validatorList.length); + + uint256 randomValidatorIndex; + uint256 diff = _fee.sub(feePerValidator.mul(validatorList.length)); + if (diff > 0) { + randomValidatorIndex = random(validatorList.length); + } + + for (uint256 i = 0; i < validatorList.length; i++) { + uint256 feeToDistribute = feePerValidator; + if (diff > 0 && randomValidatorIndex == i) { + feeToDistribute = feeToDistribute.add(diff); + } + address rewardAddress = validators.getValidatorRewardAddress(validatorList[i]); + onFeeDistribution(rewardAddress, feeToDistribute, _direction); + } + } + + function onFeeDistribution(address _rewardAddress, uint256 _fee, bytes32 _direction) internal { + if (_direction == REWARD_FOR_TRANSFERRING_FROM_FOREIGN) { + onAffirmationFeeDistribution(_rewardAddress, _fee); + } else { + onSignatureFeeDistribution(_rewardAddress, _fee); + } + } + + function onAffirmationFeeDistribution(address _rewardAddress, uint256 _fee) internal; + + function onSignatureFeeDistribution(address _rewardAddress, uint256 _fee) internal; +} diff --git a/contracts/upgradeable_contracts/erc20_to_erc20/FeeManagerErcToErcPOSDAO.sol b/contracts/upgradeable_contracts/erc20_to_erc20/FeeManagerErcToErcPOSDAO.sol new file mode 100644 index 000000000..da27b4379 --- /dev/null +++ b/contracts/upgradeable_contracts/erc20_to_erc20/FeeManagerErcToErcPOSDAO.sol @@ -0,0 +1,26 @@ +pragma solidity 0.4.24; + +import "../BlockRewardFeeManager.sol"; + +contract FeeManagerErcToErcPOSDAO is BlockRewardFeeManager { + + function getFeeManagerMode() public pure returns(bytes4) { + return bytes4(keccak256(abi.encodePacked("manages-both-directions"))); + } + + function blockRewardContract() public view returns(address) { + return _blockRewardContract(); + } + + function setBlockRewardContract(address _blockReward) external { + require(_blockReward != address(0) && isContract(_blockReward) && (IBlockReward(_blockReward).bridgesAllowedLength() != 0)); + addressStorage[keccak256(abi.encodePacked("blockRewardContract"))] = _blockReward; + } + + function isContract(address _addr) internal view returns (bool) + { + uint length; + assembly { length := extcodesize(_addr) } + return length > 0; + } +} diff --git a/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol b/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol index c65dd11e4..dca16d50a 100644 --- a/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol +++ b/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol @@ -8,9 +8,11 @@ import "../../ERC677Receiver.sol"; import "../BasicHomeBridge.sol"; import "../ERC677Bridge.sol"; import "../OverdrawManagement.sol"; +import "./RewardableHomeBridgeErcToErc.sol"; +import "../../IBlockReward.sol"; -contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, BasicHomeBridge, ERC677Bridge, OverdrawManagement { +contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, BasicHomeBridge, ERC677Bridge, OverdrawManagement, RewardableHomeBridgeErcToErc { event AmountLimitExceeded(address recipient, uint256 value, bytes32 transactionHash); @@ -27,6 +29,109 @@ contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, Basi address _owner ) public returns(bool) + { + _initialize ( + _validatorContract, + _dailyLimit, + _maxPerTx, + _minPerTx, + _homeGasPrice, + _requiredBlockConfirmations, + _erc677token, + _foreignDailyLimit, + _foreignMaxPerTx, + _owner + ); + setInitialize(true); + + return isInitialized(); + } + + function rewardableInitialize ( + address _validatorContract, + uint256 _dailyLimit, + uint256 _maxPerTx, + uint256 _minPerTx, + uint256 _homeGasPrice, + uint256 _requiredBlockConfirmations, + address _erc677token, + uint256 _foreignDailyLimit, + uint256 _foreignMaxPerTx, + address _owner, + address _feeManager, + uint256 _homeFee, + uint256 _foreignFee + ) public + returns(bool) + { + _rewardableInitialize ( + _validatorContract, + _dailyLimit, + _maxPerTx, + _minPerTx, + _homeGasPrice, + _requiredBlockConfirmations, + _erc677token, + _foreignDailyLimit, + _foreignMaxPerTx, + _owner, + _feeManager, + _homeFee, + _foreignFee + ); + setInitialize(true); + + return isInitialized(); + } + + function _rewardableInitialize ( + address _validatorContract, + uint256 _dailyLimit, + uint256 _maxPerTx, + uint256 _minPerTx, + uint256 _homeGasPrice, + uint256 _requiredBlockConfirmations, + address _erc677token, + uint256 _foreignDailyLimit, + uint256 _foreignMaxPerTx, + address _owner, + address _feeManager, + uint256 _homeFee, + uint256 _foreignFee + ) internal + returns(bool) + { + _initialize ( + _validatorContract, + _dailyLimit, + _maxPerTx, + _minPerTx, + _homeGasPrice, + _requiredBlockConfirmations, + _erc677token, + _foreignDailyLimit, + _foreignMaxPerTx, + _owner + ); + require(isContract(_feeManager)); + addressStorage[keccak256(abi.encodePacked("feeManagerContract"))] = _feeManager; + _setFee(_feeManager, _homeFee, HOME_FEE); + _setFee(_feeManager, _foreignFee, FOREIGN_FEE); + } + + function _initialize ( + address _validatorContract, + uint256 _dailyLimit, + uint256 _maxPerTx, + uint256 _minPerTx, + uint256 _homeGasPrice, + uint256 _requiredBlockConfirmations, + address _erc677token, + uint256 _foreignDailyLimit, + uint256 _foreignMaxPerTx, + address _owner + ) internal + returns(bool) { require(!isInitialized()); require(_validatorContract != address(0) && isContract(_validatorContract)); @@ -45,10 +150,7 @@ contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, Basi uintStorage[keccak256(abi.encodePacked("executionDailyLimit"))] = _foreignDailyLimit; uintStorage[keccak256(abi.encodePacked("executionMaxPerTx"))] = _foreignMaxPerTx; setOwner(_owner); - setInitialize(true); setErc677token(_erc677token); - - return isInitialized(); } function getBridgeMode() public pure returns(bytes4 _data) { @@ -61,11 +163,37 @@ contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, Basi function onExecuteAffirmation(address _recipient, uint256 _value, bytes32 txHash) internal returns(bool) { setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_value)); - return erc677token().mint(_recipient, _value); + uint256 valueToMint = _value; + address feeManager = feeManagerContract(); + if (feeManager != address(0)) { + uint256 fee = calculateFee(valueToMint, false, feeManager, FOREIGN_FEE); + distributeFeeFromAffirmation(fee, feeManager, txHash); + valueToMint = valueToMint.sub(fee); + } + return erc677token().mint(_recipient, valueToMint); } function fireEventOnTokenTransfer(address _from, uint256 _value) internal { - emit UserRequestForSignature(_from, _value); + uint256 valueToTransfer = _value; + address feeManager = feeManagerContract(); + if (feeManager != address(0)) { + uint256 fee = calculateFee(valueToTransfer, false, feeManager, HOME_FEE); + valueToTransfer = valueToTransfer.sub(fee); + } + emit UserRequestForSignature(_from, valueToTransfer); + } + + function onSignaturesCollected(bytes _message) internal { + address feeManager = feeManagerContract(); + if (feeManager != address(0)) { + address recipient; + uint256 amount; + bytes32 txHash; + address contractAddress; + (recipient, amount, txHash, contractAddress) = Message.parseMessage(_message); + uint256 fee = calculateFee(amount, true, feeManager, HOME_FEE); + distributeFeeFromSignatures(fee, feeManager, txHash); + } } function affirmationWithinLimits(uint256 _amount) internal view returns(bool) { diff --git a/contracts/upgradeable_contracts/erc20_to_erc20/POSDAOHomeBridgeErcToErc.sol b/contracts/upgradeable_contracts/erc20_to_erc20/POSDAOHomeBridgeErcToErc.sol new file mode 100644 index 000000000..76b4bd409 --- /dev/null +++ b/contracts/upgradeable_contracts/erc20_to_erc20/POSDAOHomeBridgeErcToErc.sol @@ -0,0 +1,70 @@ +pragma solidity 0.4.24; + +import "./HomeBridgeErcToErc.sol"; + +contract POSDAOHomeBridgeErcToErc is HomeBridgeErcToErc { + + function rewardableInitialize ( + address _validatorContract, + uint256 _dailyLimit, + uint256 _maxPerTx, + uint256 _minPerTx, + uint256 _homeGasPrice, + uint256 _requiredBlockConfirmations, + address _erc677token, + uint256 _foreignDailyLimit, + uint256 _foreignMaxPerTx, + address _owner, + address _feeManager, + uint256 _homeFee, + uint256 _foreignFee, + address _blockReward + ) public + returns(bool) + { + _rewardableInitialize ( + _validatorContract, + _dailyLimit, + _maxPerTx, + _minPerTx, + _homeGasPrice, + _requiredBlockConfirmations, + _erc677token, + _foreignDailyLimit, + _foreignMaxPerTx, + _owner, + _feeManager, + _homeFee, + _foreignFee + ); + _setBlockRewardContract(_feeManager, _blockReward); + setInitialize(true); + + return isInitialized(); + } + + function blockRewardContract() public view returns(address) { + address blockReward; + address feeManager = feeManagerContract(); + bytes memory callData = abi.encodeWithSignature("blockRewardContract()"); + + assembly { + let result := callcode(gas, feeManager, 0x0, add(callData, 0x20), mload(callData), 0, 32) + blockReward := mload(0) + + switch result + case 0 { revert(0, 0) } + } + + return blockReward; + } + + function setBlockRewardContract(address _blockReward) public onlyOwner { + address feeManager = feeManagerContract(); + _setBlockRewardContract(feeManager, _blockReward); + } + + function _setBlockRewardContract(address _feeManager, address _blockReward) internal { + require(_feeManager.delegatecall(abi.encodeWithSignature("setBlockRewardContract(address)", _blockReward))); + } +} diff --git a/contracts/upgradeable_contracts/erc20_to_erc20/RewardableHomeBridgeErcToErc.sol b/contracts/upgradeable_contracts/erc20_to_erc20/RewardableHomeBridgeErcToErc.sol new file mode 100644 index 000000000..0b9282755 --- /dev/null +++ b/contracts/upgradeable_contracts/erc20_to_erc20/RewardableHomeBridgeErcToErc.sol @@ -0,0 +1,23 @@ +pragma solidity 0.4.24; + +import "../RewardableBridge.sol"; + + +contract RewardableHomeBridgeErcToErc is RewardableBridge { + + function setHomeFee(uint256 _fee) external onlyOwner { + _setFee(feeManagerContract(), _fee, HOME_FEE); + } + + function setForeignFee(uint256 _fee) external onlyOwner { + _setFee(feeManagerContract(), _fee, FOREIGN_FEE); + } + + function getHomeFee() public view returns(uint256) { + return _getFee(HOME_FEE); + } + + function getForeignFee() public view returns(uint256) { + return _getFee(FOREIGN_FEE); + } +} diff --git a/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNative.sol b/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNative.sol index be80bdd03..0829fbfe5 100644 --- a/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNative.sol +++ b/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNative.sol @@ -1,11 +1,11 @@ pragma solidity 0.4.24; -import "../BaseFeeManager.sol"; import "../../IBlockReward.sol"; import "../Sacrifice.sol"; +import "../ValidatorsFeeManager.sol"; -contract FeeManagerErcToNative is BaseFeeManager { +contract FeeManagerErcToNative is ValidatorsFeeManager { function getFeeManagerMode() public pure returns(bytes4) { return bytes4(keccak256(abi.encodePacked("manages-both-directions"))); diff --git a/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErc.sol b/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErc.sol index a1f5b4c4e..521ff559a 100644 --- a/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErc.sol +++ b/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErc.sol @@ -1,11 +1,11 @@ pragma solidity 0.4.24; -import "../BaseFeeManager.sol"; import "../../IBurnableMintableERC677Token.sol"; import "../Sacrifice.sol"; +import "../ValidatorsFeeManager.sol"; -contract FeeManagerNativeToErc is BaseFeeManager { +contract FeeManagerNativeToErc is ValidatorsFeeManager { function getFeeManagerMode() public pure returns(bytes4) { return bytes4(keccak256(abi.encodePacked("manages-one-direction"))); diff --git a/deploy/src/erc_to_erc/home.js b/deploy/src/erc_to_erc/home.js index fd8655f71..ca276a0bd 100644 --- a/deploy/src/erc_to_erc/home.js +++ b/deploy/src/erc_to_erc/home.js @@ -1,17 +1,27 @@ const assert = require('assert') const Web3Utils = require('web3-utils') const env = require('../loadEnv') +const { ZERO_ADDRESS } = require('../constants') -const { deployContract, privateKeyToAddress, sendRawTxHome } = require('../deploymentUtils') +const { + deployContract, + privateKeyToAddress, + sendRawTxHome, + logValidatorsAndRewardAccounts +} = require('../deploymentUtils') const { web3Home, deploymentPrivateKey, HOME_RPC_URL } = require('../web3') const EternalStorageProxy = require('../../../build/contracts/EternalStorageProxy.json') const BridgeValidators = require('../../../build/contracts/BridgeValidators.json') +const RewardableValidators = require('../../../build/contracts/RewardableValidators.json') +const FeeManagerErcToErcPOSDAO = require('../../../build/contracts/FeeManagerErcToErcPOSDAO.json') const HomeBridge = require('../../../build/contracts/HomeBridgeErcToErc.json') +const POSDAOHomeBridge = require('../../../build/contracts/POSDAOHomeBridgeErcToErc.json') const ERC677BridgeToken = require('../../../build/contracts/ERC677BridgeToken.json') const ERC677BridgeTokenRewardable = require('../../../build/contracts/ERC677BridgeTokenRewardable.json') const VALIDATORS = env.VALIDATORS.split(' ') +const VALIDATORS_REWARD_ACCOUNTS = env.VALIDATORS_REWARD_ACCOUNTS.split(' ') const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY, @@ -31,11 +41,16 @@ const { FOREIGN_MAX_AMOUNT_PER_TX, DEPLOY_REWARDABLE_TOKEN, BLOCK_REWARD_ADDRESS, - DPOS_STAKING_ADDRESS + DPOS_STAKING_ADDRESS, + HOME_REWARDABLE, + HOME_TRANSACTIONS_FEE, + FOREIGN_TRANSACTIONS_FEE } = env const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) +const isRewardableBridge = HOME_REWARDABLE === 'true' + async function deployHome() { let homeNonce = await web3Home.eth.getTransactionCount(DEPLOYMENT_ACCOUNT_ADDRESS) console.log('deploying storage for home validators') @@ -47,7 +62,11 @@ async function deployHome() { homeNonce++ console.log('\ndeploying implementation for home validators') - const bridgeValidatorsHome = await deployContract(BridgeValidators, [], { + const bridgeValidatorsContract = + isRewardableBridge && BLOCK_REWARD_ADDRESS === ZERO_ADDRESS + ? RewardableValidators + : BridgeValidators + const bridgeValidatorsHome = await deployContract(bridgeValidatorsContract, [], { from: DEPLOYMENT_ACCOUNT_ADDRESS, nonce: homeNonce }) @@ -69,13 +88,31 @@ async function deployHome() { homeNonce++ console.log('\ninitializing Home Bridge Validators with following parameters:\n') - console.log( - `REQUIRED_NUMBER_OF_VALIDATORS: ${REQUIRED_NUMBER_OF_VALIDATORS}, VALIDATORS: ${VALIDATORS}` - ) bridgeValidatorsHome.options.address = storageValidatorsHome.options.address - const initializeData = await bridgeValidatorsHome.methods - .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, HOME_VALIDATORS_OWNER) - .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) + + let initializeData + + if (isRewardableBridge && BLOCK_REWARD_ADDRESS === ZERO_ADDRESS) { + console.log( + `REQUIRED_NUMBER_OF_VALIDATORS: ${REQUIRED_NUMBER_OF_VALIDATORS}, HOME_VALIDATORS_OWNER: ${HOME_VALIDATORS_OWNER}` + ) + logValidatorsAndRewardAccounts(VALIDATORS, VALIDATORS_REWARD_ACCOUNTS) + initializeData = await bridgeValidatorsHome.methods + .initialize( + REQUIRED_NUMBER_OF_VALIDATORS, + VALIDATORS, + VALIDATORS_REWARD_ACCOUNTS, + HOME_VALIDATORS_OWNER + ) + .encodeABI() + } else { + console.log( + `REQUIRED_NUMBER_OF_VALIDATORS: ${REQUIRED_NUMBER_OF_VALIDATORS}, VALIDATORS: ${VALIDATORS}` + ) + initializeData = await bridgeValidatorsHome.methods + .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, HOME_VALIDATORS_OWNER) + .encodeABI() + } const txInitialize = await sendRawTxHome({ data: initializeData, nonce: homeNonce, @@ -109,7 +146,9 @@ async function deployHome() { console.log('[Home] HomeBridge Storage: ', homeBridgeStorage.options.address) console.log('\ndeploying homeBridge implementation\n') - const homeBridgeImplementation = await deployContract(HomeBridge, [], { + const bridgeContract = + isRewardableBridge && BLOCK_REWARD_ADDRESS !== ZERO_ADDRESS ? POSDAOHomeBridge : HomeBridge + const homeBridgeImplementation = await deployContract(bridgeContract, [], { from: DEPLOYMENT_ACCOUNT_ADDRESS, nonce: homeNonce }) @@ -131,8 +170,12 @@ async function deployHome() { homeNonce++ console.log('\n[Home] deploying Bridgeble token') + const erc677Contract = + (isRewardableBridge && BLOCK_REWARD_ADDRESS !== ZERO_ADDRESS) || DEPLOY_REWARDABLE_TOKEN + ? ERC677BridgeTokenRewardable + : ERC677BridgeToken const erc677token = await deployContract( - DEPLOY_REWARDABLE_TOKEN ? ERC677BridgeTokenRewardable : ERC677BridgeToken, + erc677Contract, [BRIDGEABLE_TOKEN_NAME, BRIDGEABLE_TOKEN_SYMBOL, BRIDGEABLE_TOKEN_DECIMALS], { from: DEPLOYMENT_ACCOUNT_ADDRESS, network: 'home', nonce: homeNonce } ) @@ -153,7 +196,7 @@ async function deployHome() { assert.strictEqual(Web3Utils.hexToNumber(setBridgeContract.status), 1, 'Transaction Failed') homeNonce++ - if (DEPLOY_REWARDABLE_TOKEN) { + if ((isRewardableBridge && BLOCK_REWARD_ADDRESS !== ZERO_ADDRESS) || DEPLOY_REWARDABLE_TOKEN) { console.log('\nset BlockReward contract on ERC677BridgeTokenRewardable') const setBlockRewardContractData = await erc677token.methods .setBlockRewardContract(BLOCK_REWARD_ADDRESS) @@ -165,9 +208,15 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.strictEqual(Web3Utils.hexToNumber(setBlockRewardContract.status), 1, 'Transaction Failed') + assert.strictEqual( + Web3Utils.hexToNumber(setBlockRewardContract.status), + 1, + 'Transaction Failed' + ) homeNonce++ + } + if (DEPLOY_REWARDABLE_TOKEN) { console.log('\nset Staking contract on ERC677BridgeTokenRewardable') const setStakingContractData = await erc677token.methods .setStakingContract(DPOS_STAKING_ADDRESS) @@ -197,32 +246,81 @@ async function deployHome() { assert.strictEqual(Web3Utils.hexToNumber(txOwnership.status), 1, 'Transaction Failed') homeNonce++ - console.log('\ninitializing Home Bridge with following parameters:\n') - console.log(`Home Validators: ${storageValidatorsHome.options.address}, - HOME_DAILY_LIMIT : ${HOME_DAILY_LIMIT} which is ${Web3Utils.fromWei(HOME_DAILY_LIMIT)} in eth, - HOME_MAX_AMOUNT_PER_TX: ${HOME_MAX_AMOUNT_PER_TX} which is ${Web3Utils.fromWei( - HOME_MAX_AMOUNT_PER_TX - )} in eth, - HOME_MIN_AMOUNT_PER_TX: ${HOME_MIN_AMOUNT_PER_TX} which is ${Web3Utils.fromWei( - HOME_MIN_AMOUNT_PER_TX - )} in eth, - HOME_GAS_PRICE: ${HOME_GAS_PRICE}, HOME_REQUIRED_BLOCK_CONFIRMATIONS : ${HOME_REQUIRED_BLOCK_CONFIRMATIONS} - `) + let initializeHomeBridgeData homeBridgeImplementation.options.address = homeBridgeStorage.options.address - const initializeHomeBridgeData = await homeBridgeImplementation.methods - .initialize( - storageValidatorsHome.options.address, - HOME_DAILY_LIMIT, - HOME_MAX_AMOUNT_PER_TX, - HOME_MIN_AMOUNT_PER_TX, - HOME_GAS_PRICE, - HOME_REQUIRED_BLOCK_CONFIRMATIONS, - erc677token.options.address, - FOREIGN_DAILY_LIMIT, - FOREIGN_MAX_AMOUNT_PER_TX, - HOME_BRIDGE_OWNER - ) - .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) + + if (isRewardableBridge && BLOCK_REWARD_ADDRESS !== ZERO_ADDRESS) { + console.log('\ndeploying implementation for fee manager') + const feeManager = await deployContract(FeeManagerErcToErcPOSDAO, [], { + from: DEPLOYMENT_ACCOUNT_ADDRESS, + nonce: homeNonce + }) + console.log('[Home] feeManager Implementation: ', feeManager.options.address) + homeNonce++ + + const homeFeeInWei = Web3Utils.toWei(HOME_TRANSACTIONS_FEE.toString(), 'ether') + const foreignFeeInWei = Web3Utils.toWei(FOREIGN_TRANSACTIONS_FEE.toString(), 'ether') + console.log('\ninitializing Home Bridge with fee contract:\n') + console.log(`Home Validators: ${storageValidatorsHome.options.address}, + HOME_DAILY_LIMIT : ${HOME_DAILY_LIMIT} which is ${Web3Utils.fromWei(HOME_DAILY_LIMIT)} in eth, + HOME_MAX_AMOUNT_PER_TX: ${HOME_MAX_AMOUNT_PER_TX} which is ${Web3Utils.fromWei( + HOME_MAX_AMOUNT_PER_TX + )} in eth, + HOME_MIN_AMOUNT_PER_TX: ${HOME_MIN_AMOUNT_PER_TX} which is ${Web3Utils.fromWei( + HOME_MIN_AMOUNT_PER_TX + )} in eth, + HOME_GAS_PRICE: ${HOME_GAS_PRICE}, HOME_REQUIRED_BLOCK_CONFIRMATIONS : ${HOME_REQUIRED_BLOCK_CONFIRMATIONS}, + Block Reward: ${BLOCK_REWARD_ADDRESS}, + Fee Manager: ${feeManager.options.address}, + Home Fee: ${homeFeeInWei} which is ${HOME_TRANSACTIONS_FEE * 100}% + Foreign Fee: ${foreignFeeInWei} which is ${FOREIGN_TRANSACTIONS_FEE * 100}%`) + initializeHomeBridgeData = await homeBridgeImplementation.methods + .rewardableInitialize( + storageValidatorsHome.options.address, + HOME_DAILY_LIMIT, + HOME_MAX_AMOUNT_PER_TX, + HOME_MIN_AMOUNT_PER_TX, + HOME_GAS_PRICE, + HOME_REQUIRED_BLOCK_CONFIRMATIONS, + erc677token.options.address, + FOREIGN_DAILY_LIMIT, + FOREIGN_MAX_AMOUNT_PER_TX, + HOME_BRIDGE_OWNER, + feeManager.options.address, + homeFeeInWei, + foreignFeeInWei, + BLOCK_REWARD_ADDRESS + ) + .encodeABI() + } else { + console.log('\ninitializing Home Bridge with following parameters:\n') + console.log(`Home Validators: ${storageValidatorsHome.options.address}, + HOME_DAILY_LIMIT : ${HOME_DAILY_LIMIT} which is ${Web3Utils.fromWei(HOME_DAILY_LIMIT)} in eth, + HOME_MAX_AMOUNT_PER_TX: ${HOME_MAX_AMOUNT_PER_TX} which is ${Web3Utils.fromWei( + HOME_MAX_AMOUNT_PER_TX + )} in eth, + HOME_MIN_AMOUNT_PER_TX: ${HOME_MIN_AMOUNT_PER_TX} which is ${Web3Utils.fromWei( + HOME_MIN_AMOUNT_PER_TX + )} in eth, + HOME_GAS_PRICE: ${HOME_GAS_PRICE}, HOME_REQUIRED_BLOCK_CONFIRMATIONS : ${HOME_REQUIRED_BLOCK_CONFIRMATIONS} + `) + + initializeHomeBridgeData = await homeBridgeImplementation.methods + .initialize( + storageValidatorsHome.options.address, + HOME_DAILY_LIMIT, + HOME_MAX_AMOUNT_PER_TX, + HOME_MIN_AMOUNT_PER_TX, + HOME_GAS_PRICE, + HOME_REQUIRED_BLOCK_CONFIRMATIONS, + erc677token.options.address, + FOREIGN_DAILY_LIMIT, + FOREIGN_MAX_AMOUNT_PER_TX, + HOME_BRIDGE_OWNER + ) + .encodeABI() + } + const txInitializeHomeBridge = await sendRawTxHome({ data: initializeHomeBridgeData, nonce: homeNonce, diff --git a/deploy/src/loadEnv.js b/deploy/src/loadEnv.js index f5f59fa8a..0e515578e 100644 --- a/deploy/src/loadEnv.js +++ b/deploy/src/loadEnv.js @@ -100,6 +100,12 @@ if (BRIDGE_MODE === 'ERC_TO_ERC') { DPOS_STAKING_ADDRESS: addressValidator(), BLOCK_REWARD_ADDRESS: addressValidator() } + + if (FOREIGN_REWARDABLE === 'true') { + throw new Error( + `Collecting fees on Foreign Network on ${BRIDGE_MODE} bridge mode is not supported.` + ) + } } if (BRIDGE_MODE === 'ERC_TO_NATIVE') { validations = { @@ -129,4 +135,14 @@ if (HOME_REWARDABLE === 'true' || FOREIGN_REWARDABLE === 'true') { const env = envalid.cleanEnv(process.env, validations) +if ( + env.BRIDGE_MODE === 'ERC_TO_ERC' && + env.HOME_REWARDABLE === 'true' && + env.BLOCK_REWARD_ADDRESS === ZERO_ADDRESS +) { + throw new Error( + 'Collecting fees on Home Network on ERC_TO_ERC mode without Block Reward contract is not supported.' + ) +} + module.exports = env diff --git a/package-lock.json b/package-lock.json index 301109f25..8301e96f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,14 +4,6 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@babel/runtime": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.1.tgz", - "integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==", - "requires": { - "regenerator-runtime": "^0.12.0" - } - }, "@resolver-engine/core": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.2.1.tgz", @@ -54,14 +46,6 @@ "debug": "^3.1.0" } }, - "@types/bn.js": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.4.tgz", - "integrity": "sha512-AO8WW+aRcKWKQAYTfKLzwnpL6U+TfPqS+haRrhCy5ff04Da8WZud3ZgVjspQXaEXJDcTlsjUEVvL39wegDek5w==", - "requires": { - "@types/node": "*" - } - }, "@types/concat-stream": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.0.tgz", @@ -81,14 +65,15 @@ } }, "@types/node": { - "version": "10.12.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.26.tgz", - "integrity": "sha512-nMRqS+mL1TOnIJrL6LKJcNZPB8V3eTfRo9FQA2b5gDvrHurC8XbSA86KNe0dShlEL7ReWJv/OU9NL7Z0dnqWTg==" + "version": "10.14.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.4.tgz", + "integrity": "sha512-DT25xX/YgyPKiHFOpNuANIQIVvYEwCWXgK2jYYwqgaMrYE6+tq+DtmMwlD3drl6DJbUwtlIDnn0d7tIn/EbXBg==", + "dev": true }, "@types/qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-mNhVdZHdtKHMMxbqzNK3RzkBcN1cux3AvuCYGTvjEIQT2uheH3eCAyYsbMbh2Bq8nXkeOWs1kyDiF7geWRFQ4Q==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-47kAAs3yV/hROraCTQYDMh4p/6zI9+gtssjD0kq9OWsGdLcBge59rl49FnCuJ+iWxEKiqFz6KXzeGH5DRVjNJA==", "dev": true }, "abbrev": { @@ -106,11 +91,19 @@ "web3": "^0.18.4" } }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, "ajv": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", - "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", - "dev": true, + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -229,6 +222,11 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "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-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -245,7 +243,6 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, "requires": { "safer-buffer": "~2.1.0" } @@ -253,8 +250,7 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "assertion-error": { "version": "1.1.0", @@ -275,16 +271,20 @@ "dev": true }, "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.2.tgz", + "integrity": "sha512-6xrbvN0MOBKSJDdonmSSz2OwFSgxRaVtBDes26mj9KIGtDo+g9xosFRSC+i1gQh2oAN/tQ62AI/pGZGQjVOiRg==", "dev": true }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "atob": { "version": "2.1.2", @@ -295,14 +295,12 @@ "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "balanced-match": { "version": "1.0.0", @@ -368,7 +366,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, "requires": { "tweetnacl": "^0.14.3" } @@ -379,15 +376,42 @@ "dev": true }, "binary-extensions": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", - "integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "dev": true }, "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "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" + } + } + } }, "boxen": { "version": "1.3.0", @@ -495,7 +519,6 @@ "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" @@ -512,6 +535,11 @@ "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", "integrity": "sha1-YGSkD6dutDxyOrqe+PbhIW0QURo=" }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -543,8 +571,7 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chai": { "version": "4.2.0", @@ -616,9 +643,9 @@ "dev": true }, "chokidar": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.1.tgz", - "integrity": "sha512-gfw3p2oQV2wEt+8VuMlNsPjCxDxvvgnm/kz+uATu805mWVF8IJN7uz9DN7iBz+RMJISmiVbCOBFs9qBGMjtPfQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", + "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -632,7 +659,7 @@ "normalize-path": "^3.0.0", "path-is-absolute": "^1.0.0", "readdirp": "^2.2.1", - "upath": "^1.1.0" + "upath": "^1.1.1" } }, "ci-info": { @@ -764,7 +791,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -811,6 +837,26 @@ "xdg-basedir": "^3.0.0" } }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -820,8 +866,16 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } }, "create-error-class": { "version": "3.0.2", @@ -865,7 +919,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -923,6 +976,14 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -967,8 +1028,17 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "diff": { "version": "3.3.1", @@ -999,12 +1069,16 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", @@ -1019,6 +1093,11 @@ "minimalistic-crypto-utils": "^1.0.0" } }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -1027,6 +1106,34 @@ "is-arrayish": "^0.2.1" } }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1075,6 +1182,11 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, "eth-gas-reporter": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.1.12.tgz", @@ -1096,12 +1208,16 @@ } }, "eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", "requires": { "bn.js": "^4.11.6", "elliptic": "^6.4.0", + "keccakjs": "^0.2.1", + "nano-json-stream-parser": "^0.1.2", + "servify": "^0.1.12", + "ws": "^3.0.0", "xhr-request-promise": "^0.1.2" } }, @@ -1121,13 +1237,6 @@ "requires": { "bn.js": "4.11.6", "number-to-bn": "1.7.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" - } } }, "execa": { @@ -1189,11 +1298,62 @@ } } }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "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" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { "version": "3.0.2", @@ -1284,20 +1444,17 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fast-levenshtein": { "version": "2.0.6", @@ -1328,6 +1485,35 @@ } } }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + }, + "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" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -1354,20 +1540,23 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12" } }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -1377,6 +1566,11 @@ "map-cache": "^0.2.2" } }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, "fs-extra": { "version": "0.30.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", @@ -1923,10 +2117,15 @@ } } }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, "ganache-cli": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.3.0.tgz", - "integrity": "sha512-8SyzfX2ipRVBx1fBZLg3j8I3E334U3Vazk5mEpYcWqnIjC2ace6jtOXHG4aTuAvSz3+HzQ8p8pRjOJxdDZ2pnQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.4.1.tgz", + "integrity": "sha512-MUZ1DNnmlTrXnH6EuINuew75AI9d/wbIC0WpZCJo5Endsf6ZwEvfnfxGMpEnVizRri1mon2WWxLGAmALDxVcRQ==", "requires": { "bn.js": "4.11.8", "source-map-support": "0.5.9", @@ -1935,23 +2134,28 @@ "dependencies": { "ansi-regex": { "version": "3.0.0", - "bundled": true + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "bn.js": { "version": "4.11.8", - "bundled": true + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, "buffer-from": { "version": "1.1.1", - "bundled": true + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, "camelcase": { "version": "4.1.0", - "bundled": true + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" }, "cliui": { "version": "4.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "requires": { "string-width": "^2.1.1", "strip-ansi": "^4.0.0", @@ -1960,11 +2164,13 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "cross-spawn": { "version": "5.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "requires": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", @@ -1973,11 +2179,13 @@ }, "decamelize": { "version": "1.2.0", - "bundled": true + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "execa": { "version": "0.7.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "requires": { "cross-spawn": "^5.0.1", "get-stream": "^3.0.0", @@ -1990,45 +2198,54 @@ }, "find-up": { "version": "2.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "requires": { "locate-path": "^2.0.0" } }, "get-caller-file": { "version": "1.0.3", - "bundled": true + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" }, "get-stream": { "version": "3.0.0", - "bundled": true + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "invert-kv": { "version": "1.0.0", - "bundled": true + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "is-fullwidth-code-point": { "version": "2.0.0", - "bundled": true + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "is-stream": { "version": "1.1.0", - "bundled": true + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "isexe": { "version": "2.0.0", - "bundled": true + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "lcid": { "version": "1.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "requires": { "invert-kv": "^1.0.0" } }, "locate-path": { "version": "2.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -2036,7 +2253,8 @@ }, "lru-cache": { "version": "4.1.4", - "bundled": true, + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.4.tgz", + "integrity": "sha512-EPstzZ23znHUVLKj+lcXO1KvZkrlw+ZirdwvOmnAnA/1PB4ggyXJ77LRkCqkff+ShQ+cqoxCxLQOh4cKITO5iA==", "requires": { "pseudomap": "^1.0.2", "yallist": "^3.0.2" @@ -2044,29 +2262,34 @@ }, "mem": { "version": "1.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "requires": { "mimic-fn": "^1.0.0" } }, "mimic-fn": { "version": "1.2.0", - "bundled": true + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" }, "npm-run-path": { "version": "2.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "requires": { "path-key": "^2.0.0" } }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "os-locale": { "version": "2.1.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "requires": { "execa": "^0.7.0", "lcid": "^1.0.0", @@ -2075,72 +2298,87 @@ }, "p-finally": { "version": "1.0.0", - "bundled": true + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-limit": { "version": "1.3.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "requires": { "p-try": "^1.0.0" } }, "p-locate": { "version": "2.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "requires": { "p-limit": "^1.1.0" } }, "p-try": { "version": "1.0.0", - "bundled": true + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, "path-exists": { "version": "3.0.0", - "bundled": true + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-key": { "version": "2.0.1", - "bundled": true + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "pseudomap": { "version": "1.0.2", - "bundled": true + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "require-directory": { "version": "2.1.1", - "bundled": true + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "1.0.1", - "bundled": true + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, "set-blocking": { "version": "2.0.0", - "bundled": true + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "shebang-command": { "version": "1.2.0", - "bundled": true, + "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", - "bundled": true + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "signal-exit": { "version": "3.0.2", - "bundled": true + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "source-map": { "version": "0.6.1", - "bundled": true + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { "version": "0.5.9", - "bundled": true, + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -2148,7 +2386,8 @@ }, "string-width": { "version": "2.1.1", - "bundled": true, + "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" @@ -2156,29 +2395,34 @@ }, "strip-ansi": { "version": "4.0.0", - "bundled": true, + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "requires": { "ansi-regex": "^3.0.0" } }, "strip-eof": { "version": "1.0.0", - "bundled": true + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "which": { "version": "1.3.1", - "bundled": true, + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "requires": { "isexe": "^2.0.0" } }, "which-module": { "version": "2.0.0", - "bundled": true + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "wrap-ansi": { "version": "2.1.0", - "bundled": true, + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" @@ -2186,18 +2430,21 @@ "dependencies": { "ansi-regex": { "version": "2.1.1", - "bundled": true + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "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" } }, "string-width": { "version": "1.0.2", - "bundled": true, + "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", @@ -2206,7 +2453,8 @@ }, "strip-ansi": { "version": "3.0.1", - "bundled": true, + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" } @@ -2215,15 +2463,18 @@ }, "y18n": { "version": "3.2.1", - "bundled": true + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, "yallist": { "version": "3.0.2", - "bundled": true + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" }, "yargs": { "version": "11.1.0", - "bundled": true, + "resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", "requires": { "cliui": "^4.0.0", "decamelize": "^1.1.1", @@ -2241,7 +2492,8 @@ }, "yargs-parser": { "version": "9.0.2", - "bundled": true, + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "requires": { "camelcase": "^4.1.0" } @@ -2281,7 +2533,6 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -2368,26 +2619,17 @@ "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==" }, "handlebars": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz", - "integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", + "integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", "dev": true, "requires": { - "async": "^2.5.0", + "neo-async": "^2.6.0", "optimist": "^0.6.1", "source-map": "^0.6.1", "uglify-js": "^3.1.4" }, "dependencies": { - "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -2399,24 +2641,35 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "dev": true, "requires": { "ajv": "^6.5.5", "har-schema": "^2.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -2479,55 +2732,55 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" }, "http-basic": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-7.0.0.tgz", - "integrity": "sha1-gvClBr6UJzLsje6+6A50bvVzbbo=", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.1.tgz", + "integrity": "sha512-RRPtpg/R7HbDEoICA1MlLy0IH0D/1ShY9AcvY6U2zqT/8mjjJ893H/2URxx6JtFYEfL3IlKTkQQcKwTyLuubKA==", "dev": true, "requires": { - "@types/concat-stream": "^1.6.0", - "@types/node": "^9.4.1", - "caseless": "~0.12.0", - "concat-stream": "^1.4.6", + "caseless": "^0.12.0", + "concat-stream": "^1.6.2", "http-response-object": "^3.0.1", "parse-cache-control": "^1.0.1" - }, - "dependencies": { - "@types/node": { - "version": "9.6.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.42.tgz", - "integrity": "sha512-SpeVQJFekfnEaZZO1yl4je/36upII36L7gOT4DBx51B1GeAB45mmDb3a5OBQB+ZeFxVVOP37r8Owsl940G/fBg==", - "dev": true - } + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" } }, "http-response-object": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.1.tgz", - "integrity": "sha512-6L0Fkd6TozA8kFSfh9Widst0wfza3U1Ex2RjJ6zNDK0vR1U1auUR6jY4Nn2Xl7CCy0ikFmxW1XcspVpb9RvwTg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", + "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", "dev": true, "requires": { - "@types/node": "^9.3.0" - }, - "dependencies": { - "@types/node": { - "version": "9.6.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.42.tgz", - "integrity": "sha512-SpeVQJFekfnEaZZO1yl4je/36upII36L7gOT4DBx51B1GeAB45mmDb3a5OBQB+ZeFxVVOP37r8Owsl940G/fBg==", - "dev": true - } + "@types/node": "^10.0.3" } }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" } }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -2577,6 +2830,11 @@ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -2651,6 +2909,11 @@ } } }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -2696,9 +2959,9 @@ "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { "is-extglob": "^2.1.1" @@ -2775,6 +3038,14 @@ "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", "dev": true }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "^1.0.1" + } + }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", @@ -2787,11 +3058,18 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "requires": { + "has-symbols": "^1.0.0" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-utf8": { "version": "0.2.1", @@ -2825,8 +3103,7 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul": { "version": "0.4.5", @@ -2904,13 +3181,12 @@ "js-sha3": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.6.1.tgz", - "integrity": "sha1-W4n3enR3Z5h39YxKB1JAk0sflcA=", - "dev": true + "integrity": "sha1-W4n3enR3Z5h39YxKB1JAk0sflcA=" }, "js-yaml": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", - "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", + "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -2928,26 +3204,22 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "jsonfile": { "version": "2.4.0", @@ -2961,7 +3233,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -2973,7 +3244,6 @@ "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" @@ -3053,7 +3323,8 @@ "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true }, "lodash.assign": { "version": "4.2.0", @@ -3108,11 +3379,26 @@ "object-visit": "^1.0.0" } }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, "memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -3134,17 +3420,20 @@ "to-regex": "^3.0.2" } }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, "mime-db": { "version": "1.38.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", - "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", - "dev": true + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" }, "mime-types": { "version": "2.1.22", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", - "dev": true, "requires": { "mime-db": "~1.38.0" } @@ -3237,11 +3526,14 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "nan": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", - "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", - "dev": true, - "optional": true + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + }, + "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", + "integrity": "sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18=" }, "nanomatch": { "version": "1.2.13", @@ -3262,6 +3554,17 @@ "to-regex": "^3.0.1" } }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "neo-async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", + "dev": true + }, "nodemon": { "version": "1.18.10", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.18.10.tgz", @@ -3344,20 +3647,12 @@ "requires": { "bn.js": "4.11.6", "strip-hex-prefix": "1.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" - } } }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "object-assign": { "version": "4.1.1", @@ -3395,6 +3690,11 @@ } } }, + "object-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==" + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -3413,6 +3713,14 @@ "isobject": "^3.0.1" } }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3520,12 +3828,12 @@ "dev": true }, "parse-headers": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz", - "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.2.tgz", + "integrity": "sha512-/LypJhzFmyBIDYP9aDVgeyEb5sQfbfY5mnDq4hVhlQ69js87wXfmEI5V3xI6vvXasqebp0oCytYFLxsBVfCzSg==", "requires": { - "for-each": "^0.3.2", - "trim": "0.0.1" + "for-each": "^0.3.3", + "string.prototype.trim": "^1.1.2" } }, "parse-json": { @@ -3536,6 +3844,11 @@ "error-ex": "^1.2.0" } }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -3578,6 +3891,11 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, + "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", @@ -3603,8 +3921,7 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pify": { "version": "2.3.0", @@ -3654,14 +3971,23 @@ "dev": true }, "promise": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.0.2.tgz", - "integrity": "sha512-EIyzM39FpVOMbqgzEHhxdrEhtOSDOtjMZQ0M6iVfCE+kWNgCkAyOdnuCWqfmflylftfadU6FkiMgHZA2kUzwRw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.0.3.tgz", + "integrity": "sha512-HeRDUL1RJiLhyA0/grn+PTShlBAcLuh/1BJGtrvjwbvRDCTLLMEz9rOGCV+R3vHY4MixIuoMEd9Yq/XvsTPcjw==", "dev": true, "requires": { "asap": "~2.0.6" } }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -3671,8 +3997,7 @@ "psl": { "version": "1.1.31", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", - "dev": true + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" }, "pstree.remy": { "version": "1.1.6", @@ -3683,14 +4008,12 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "query-string": { "version": "5.1.1", @@ -3707,6 +4030,22 @@ "resolved": "https://registry.npmjs.org/randomhex/-/randomhex-0.1.5.tgz", "integrity": "sha1-us7vmCMpCRQA8qKRLGzQLxCU9YU=" }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -3781,11 +4120,6 @@ "resolve": "^1.1.6" } }, - "regenerator-runtime": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", - "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -3797,9 +4131,9 @@ } }, "registry-auth-token": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", - "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", "dev": true, "requires": { "rc": "^1.1.6", @@ -3855,7 +4189,6 @@ "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -3966,8 +4299,7 @@ "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 + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safe-regex": { "version": "1.1.0", @@ -3981,13 +4313,12 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" }, "semver-diff": { "version": "2.1.0", @@ -3998,6 +4329,64 @@ "semver": "^5.0.3" } }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "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" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "requires": { + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "request": "^2.79.0", + "xhr": "^2.3.3" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -4026,6 +4415,11 @@ } } }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, "sha1": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", @@ -4040,17 +4434,8 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/sha3/-/sha3-1.2.2.tgz", "integrity": "sha1-pmxQmN5MJbyIM27ItIF9AFvKe6k=", - "dev": true, "requires": { "nan": "2.10.0" - }, - "dependencies": { - "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true - } } }, "shebang-command": { @@ -4315,9 +4700,9 @@ } }, "source-map-support": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", - "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz", + "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -4385,7 +4770,6 @@ "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -4419,6 +4803,11 @@ } } }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", @@ -4440,6 +4829,16 @@ "strip-ansi": "^3.0.0" } }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -4494,9 +4893,9 @@ } }, "sync-request": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.0.0.tgz", - "integrity": "sha512-jGNIAlCi9iU4X3Dm4oQnNQshDD3h0/1A7r79LyqjbjUnj69sX6mShAXlhRXgImsfVKtTcnra1jfzabdZvp+Lmw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", + "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", "dev": true, "requires": { "http-response-object": "^3.0.1", @@ -4523,9 +4922,9 @@ } }, "then-request": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.0.tgz", - "integrity": "sha512-xA+7uEMc+jsQIoyySJ93Ad08Kuqnik7u6jLS5hR91Z3smAoCfL3M8/MqMlobAa9gzBfO9pA88A/AntfepkkMJQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", + "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", "dev": true, "requires": { "@types/concat-stream": "^1.6.0", @@ -4535,16 +4934,16 @@ "caseless": "~0.12.0", "concat-stream": "^1.6.0", "form-data": "^2.2.0", - "http-basic": "^7.0.0", + "http-basic": "^8.1.1", "http-response-object": "^3.0.1", "promise": "^8.0.0", "qs": "^6.4.0" }, "dependencies": { "@types/node": { - "version": "8.10.40", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.40.tgz", - "integrity": "sha512-RRSjdwz63kS4u7edIwJUn8NqKLLQ6LyqF/X4+4jp38MBT3Vwetewi2N4dgJEshLbDwNgOJXNYoOwzVZUSSLhkQ==", + "version": "8.10.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.45.tgz", + "integrity": "sha512-tGVTbA+i3qfXsLbq9rEq/hezaHY55QxQLeXQL2ejNgFAxxrgu8eMmYIOsRcl7hN1uTLVsKOOYacV/rcJM3sfgQ==", "dev": true } } @@ -4609,7 +5008,6 @@ "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, "requires": { "psl": "^1.1.24", "punycode": "^1.4.1" @@ -4618,8 +5016,7 @@ "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" } } }, @@ -4629,11 +5026,6 @@ "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", "dev": true }, - "trim": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" - }, "truffle": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/truffle/-/truffle-4.1.11.tgz", @@ -4667,9 +5059,9 @@ } }, "solidity-parser-antlr": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/solidity-parser-antlr/-/solidity-parser-antlr-0.4.0.tgz", - "integrity": "sha512-RrIsh5VoHmrMQia6yLY8u8rx3JPREhSiCFz4Xb0h1Oh0prUYU2ukyWO8gG892V0UMHIXCWqvdZ3wSctNwdWThg==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/solidity-parser-antlr/-/solidity-parser-antlr-0.4.2.tgz", + "integrity": "sha512-0OKT2YKZAqPe14HN7Nbo24hjmnyUYh92UjyZG0Zz2rpQhl/w8asX8qHb+ASSXfayQaiW8g9zGIupXEE355tOQQ==", "dev": true } } @@ -4684,7 +5076,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -4692,8 +5083,7 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "type-check": { "version": "0.3.2", @@ -4710,6 +5100,15 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -4717,20 +5116,20 @@ "dev": true }, "uglify-js": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.5.3.tgz", + "integrity": "sha512-rIQPT2UMDnk4jRX+w4WO84/pebU2jiLsjgIyrCktYgSvx28enOE3iYQMr+BD1rHiitWnDmpu0cY/LfIEpKcjcw==", "dev": true, "optional": true, "requires": { - "commander": "~2.17.1", + "commander": "~2.19.0", "source-map": "~0.6.1" }, "dependencies": { "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", "dev": true, "optional": true }, @@ -4743,6 +5142,11 @@ } } }, + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" + }, "undefsafe": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", @@ -4763,6 +5167,11 @@ } } }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", @@ -4807,6 +5216,11 @@ "crypto-random-string": "^1.0.0" } }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -4854,9 +5268,9 @@ "dev": true }, "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", "dev": true }, "update-notifier": { @@ -4881,7 +5295,6 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, "requires": { "punycode": "^2.1.0" } @@ -4923,11 +5336,15 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, "validate-npm-package-license": { "version": "3.0.4", @@ -4938,11 +5355,15 @@ "spdx-expression-parse": "^3.0.0" } }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -4963,19 +5384,16 @@ } }, "web3-utils": { - "version": "1.0.0-beta.46", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.46.tgz", - "integrity": "sha512-mSz+NrAil2fDZkxTXHPntCclZ8DofMjv8Q+BYR0VAyzTzylpYNXAV0WDdxBp/sXgniWRZXZMF7OkQNWqhZ1J9g==", + "version": "1.0.0-beta.34", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.0.0-beta.34.tgz", + "integrity": "sha1-lBH8OarvOcpOBhafdiKX2f8CCXA=", "requires": { - "@babel/runtime": "^7.3.1", - "@types/bn.js": "^4.11.4", - "@types/node": "^10.12.18", - "bn.js": "4.11.8", - "eth-lib": "0.2.8", - "ethjs-unit": "^0.1.6", - "lodash": "^4.17.11", + "bn.js": "4.11.6", + "eth-lib": "0.1.27", + "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", "randomhex": "0.1.5", + "underscore": "1.8.3", "utf8": "2.1.1" } }, @@ -5071,6 +5489,16 @@ "signal-exit": "^3.0.2" } }, + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, "xdg-basedir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", diff --git a/package.json b/package.json index 3dfb3abaf..86e6d2e89 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "ganache-cli": "^6.1.0", "openzeppelin-solidity": "^1.10.0", "truffle": "4.1.11", - "web3-utils": "^1.0.0-beta.34" + "web3-utils": "1.0.0-beta.34" }, "devDependencies": { "chai": "^4.1.2", diff --git a/test/erc_to_erc/home_bridge.test.js b/test/erc_to_erc/home_bridge.test.js index b145acb8f..99da6ff33 100644 --- a/test/erc_to_erc/home_bridge.test.js +++ b/test/erc_to_erc/home_bridge.test.js @@ -1,10 +1,15 @@ const Web3Utils = require('web3-utils'); const HomeBridge = artifacts.require("HomeBridgeErcToErc.sol"); +const POSDAOHomeBridge = artifacts.require("POSDAOHomeBridgeErcToErc.sol"); const EternalStorageProxy = artifacts.require("EternalStorageProxy.sol"); const BridgeValidators = artifacts.require("BridgeValidators.sol"); const ERC677BridgeToken = artifacts.require("ERC677BridgeToken.sol"); +const ERC677BridgeTokenRewardable = artifacts.require("ERC677BridgeTokenRewardable.sol"); +const FeeManagerErcToErcPOSDAO = artifacts.require("FeeManagerErcToErcPOSDAO.sol"); +const RewardableValidators = artifacts.require("RewardableValidators.sol"); +const BlockReward = artifacts.require('BlockReward') const {ERROR_MSG, ZERO_ADDRESS} = require('../setup'); -const {createMessage, sign, signatureToVRS} = require('../helpers/helpers'); +const {createMessage, sign, getEvents} = require('../helpers/helpers'); const minPerTx = web3.toBigNumber(web3.toWei(0.01, "ether")); const requireBlockConfirmations = 8; const gasPrice = Web3Utils.toWei('1', 'gwei'); @@ -619,4 +624,509 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { upgradeabilityAdmin.should.be.equal(proxyOwner) }) }) + + describe('#rewardableInitialize', async () => { + let homeFee, foreignFee, homeBridge, rewardableValidators, blockRewardContract + let validators = [accounts[1]] + let rewards = [accounts[2]] + let requiredSignatures = 1 + beforeEach(async () => { + token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18); + rewardableValidators = await RewardableValidators.new() + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner).should.be.fulfilled + homeBridge = await POSDAOHomeBridge.new() + homeFee = web3.toBigNumber(web3.toWei(0.002, "ether")) + foreignFee = web3.toBigNumber(web3.toWei(0.002, "ether")) + blockRewardContract = await BlockReward.new() + }) + it('sets variables', async () => { + const feeManager = await FeeManagerErcToErcPOSDAO.new() + ZERO_ADDRESS.should.be.equal(await homeBridge.validatorContract()) + '0'.should.be.bignumber.equal(await homeBridge.deployedAtBlock()) + '0'.should.be.bignumber.equal(await homeBridge.dailyLimit()) + '0'.should.be.bignumber.equal(await homeBridge.maxPerTx()) + false.should.be.equal(await homeBridge.isInitialized()) + + await homeBridge.rewardableInitialize(ZERO_ADDRESS, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner, feeManager.address, homeFee, foreignFee, blockRewardContract.address).should.be.rejectedWith(ERROR_MSG); + await homeBridge.rewardableInitialize(rewardableValidators.address, oneEther, halfEther, minPerTx, 0, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner, feeManager.address, homeFee, foreignFee, blockRewardContract.address).should.be.rejectedWith(ERROR_MSG); + await homeBridge.rewardableInitialize(rewardableValidators.address, oneEther, halfEther, minPerTx, gasPrice, 0, foreignDailyLimit, token.address, foreignMaxPerTx, owner, feeManager.address, homeFee, foreignFee, blockRewardContract.address).should.be.rejectedWith(ERROR_MSG); + await homeBridge.rewardableInitialize(rewardableValidators.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner, ZERO_ADDRESS, homeFee, foreignFee, blockRewardContract.address).should.be.rejectedWith(ERROR_MSG); + await homeBridge.rewardableInitialize(rewardableValidators.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner, feeManager.address, homeFee, foreignFee, blockRewardContract.address).should.be.fulfilled; + + true.should.be.equal(await homeBridge.isInitialized()) + rewardableValidators.address.should.be.equal(await homeBridge.validatorContract()); + (await homeBridge.deployedAtBlock()).should.be.bignumber.above(0); + oneEther.should.be.bignumber.equal(await homeBridge.dailyLimit()) + halfEther.should.be.bignumber.equal(await homeBridge.maxPerTx()) + minPerTx.should.be.bignumber.equal(await homeBridge.minPerTx()) + const bridgeMode = '0xba4690f5' // 4 bytes of keccak256('erc-to-erc-core') + const mode = await homeBridge.getBridgeMode(); + mode.should.be.equal(bridgeMode) + const [major, minor, patch] = await homeBridge.getBridgeInterfacesVersion() + major.should.be.bignumber.gte(0) + minor.should.be.bignumber.gte(0) + patch.should.be.bignumber.gte(0) + + const feeManagerContract = await homeBridge.feeManagerContract() + feeManagerContract.should.be.equals(feeManager.address) + const bridgeHomeFee = await homeBridge.getHomeFee() + bridgeHomeFee.should.be.bignumber.equal(homeFee) + const bridgeForeignFee = await homeBridge.getForeignFee() + bridgeForeignFee.should.be.bignumber.equal(foreignFee) + const blockReward = await homeBridge.blockRewardContract() + blockReward.should.be.equals(blockRewardContract.address) + }) + it('can update fee contract', async () => { + const feeManager = await FeeManagerErcToErcPOSDAO.new() + await homeBridge.rewardableInitialize(rewardableValidators.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner, feeManager.address, homeFee, foreignFee, blockRewardContract.address).should.be.fulfilled; + + // Given + const newFeeManager = await FeeManagerErcToErcPOSDAO.new() + + // When + await homeBridge.setFeeManagerContract(newFeeManager.address, {from: owner}).should.be.fulfilled + + // Then + const feeManagerContract = await homeBridge.feeManagerContract() + feeManagerContract.should.be.equals(newFeeManager.address) + }) + it('can update fee', async () => { + const feeManager = await FeeManagerErcToErcPOSDAO.new() + await homeBridge.rewardableInitialize(rewardableValidators.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner, feeManager.address, homeFee, foreignFee, blockRewardContract.address).should.be.fulfilled; + + // Given + const newHomeFee = web3.toBigNumber(web3.toWei(0.1, "ether")) + const newForeignFee = web3.toBigNumber(web3.toWei(0.4, "ether")) + + // When + await homeBridge.setHomeFee(newHomeFee, {from: owner}).should.be.fulfilled + await homeBridge.setForeignFee(newForeignFee, {from: owner}).should.be.fulfilled + + // Then + const bridgeHomeFee = await homeBridge.getHomeFee() + const bridgeForeignFee = await homeBridge.getForeignFee() + bridgeHomeFee.should.be.bignumber.equal(newHomeFee) + bridgeForeignFee.should.be.bignumber.equal(newForeignFee) + }) + it('should be able to get fee manager mode', async () => { + // Given + const feeManager = await FeeManagerErcToErcPOSDAO.new() + const bothDirectionsModeHash = '0xd7de965f' + + // When + await homeBridge.rewardableInitialize(rewardableValidators.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner, feeManager.address, homeFee, foreignFee, blockRewardContract.address).should.be.fulfilled; + + // Then + const feeManagerMode = await homeBridge.getFeeManagerMode() + feeManagerMode.should.be.equals(bothDirectionsModeHash) + }) + it('should be able to set blockReward contract', async () => { + // Given + const feeManager = await FeeManagerErcToErcPOSDAO.new() + + await homeBridge.rewardableInitialize(rewardableValidators.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner, feeManager.address, homeFee, foreignFee, blockRewardContract.address).should.be.fulfilled; + + const blockReward = await homeBridge.blockRewardContract() + blockReward.should.be.equals(blockRewardContract.address) + + // When + const newBlockRewardContract = await BlockReward.new() + await homeBridge.setBlockRewardContract(newBlockRewardContract.address).should.be.fulfilled + + // Then + const newBlockReward = await homeBridge.blockRewardContract() + newBlockReward.should.be.equals(newBlockRewardContract.address) + }) + }) + describe('#onTokenTransfer', async () => { + let homeBridge + beforeEach(async () => { + homeBridge = await HomeBridge.new() + token = await ERC677BridgeToken.new("Some ERC20", "TEST", 18); + }) + it('should trigger UserRequestForSignature with transfer value', async () => { + // Given + const owner = accounts[0] + const user = accounts[4] + await homeBridge.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.fulfilled; + const value = halfEther + await token.mint(user, value, {from: owner}).should.be.fulfilled; + + // When + await token.transferAndCall(homeBridge.address, value, '0x00', {from: user}).should.be.fulfilled; + + // Then + const events = await getEvents(homeBridge, {event: 'UserRequestForSignature'}); + events[0].args.should.be.deep.equal({ + recipient: user, + value + }) + }) + it('should trigger UserRequestForSignature with fee subtracted', async () => { + // Given + const homeBridge = await POSDAOHomeBridge.new() + const owner = accounts[0] + const user = accounts[4] + const validators = [accounts[1]] + const rewards = [accounts[2]] + const requiredSignatures = 1 + const blockRewardContract = await BlockReward.new() + const rewardableValidators = await RewardableValidators.new() + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner).should.be.fulfilled + const feeManager = await FeeManagerErcToErcPOSDAO.new() + const fee = 0.001 + const homeFee = web3.toBigNumber(web3.toWei(0.001, "ether")) + const foreignFee = web3.toBigNumber(web3.toWei(0.001, "ether")) + + await homeBridge.rewardableInitialize(rewardableValidators.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner, feeManager.address, homeFee, foreignFee, blockRewardContract.address).should.be.fulfilled; + const value = halfEther + const finalValue = value.mul(web3.toBigNumber(1 - fee)) + await token.mint(user, value, {from: owner}).should.be.fulfilled; + + // When + await token.transferAndCall(homeBridge.address, value, '0x00', {from: user}).should.be.fulfilled; + + // Then + const events = await getEvents(homeBridge, {event: 'UserRequestForSignature'}); + events[0].args.should.be.deep.equal({ + recipient: user, + value: finalValue + }) + }) + }) + describe('#rewardable_submitSignatures', () => { + let fee, homeFee, foreignFee, homeBridge, rewardableValidators, blockRewardContract, feeManager + beforeEach(async () => { + token = await ERC677BridgeTokenRewardable.new("Some ERC20", "RSZT", 18); + rewardableValidators = await RewardableValidators.new() + feeManager = await FeeManagerErcToErcPOSDAO.new() + homeBridge = await POSDAOHomeBridge.new() + fee = 0.001 + homeFee = web3.toBigNumber(web3.toWei(fee, "ether")) + foreignFee = web3.toBigNumber(web3.toWei(fee, "ether")) + blockRewardContract = await BlockReward.new() + await homeBridge.rewardableInitialize(rewardableValidators.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner, feeManager.address, homeFee, foreignFee, blockRewardContract.address).should.be.fulfilled; + }) + it('should distribute fee to one validator', async () => { + // Given + const recipient = accounts[9]; + const owner = accounts[0] + const validators = [accounts[1]] + const rewards = [accounts[2]] + const requiredSignatures = 1 + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner).should.be.fulfilled + await blockRewardContract.setValidatorsRewards(rewards) + await blockRewardContract.setToken(token.address) + await token.setBlockRewardContract(blockRewardContract.address, {from: owner}) + await token.transferOwnership(homeBridge.address, {from: owner}) + + const initialValue = halfEther + const value = initialValue.mul(web3.toBigNumber(1 - fee)) + const feeAmount = initialValue.mul(web3.toBigNumber(fee)) + const transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; + const message = createMessage(recipient, value, transactionHash, homeBridge.address); + const signature = await sign(validators[0], message) + + const rewardAddressBalanceBefore = await token.balanceOf(rewards[0]) + rewardAddressBalanceBefore.should.be.bignumber.equal('0') + + // When + const { logs } = await homeBridge.submitSignature(signature, message, {from: validators[0]}).should.be.fulfilled; + + // Then + logs.length.should.be.equal(3) + logs[1].event.should.be.equal('CollectedSignatures') + logs[2].event.should.be.equal("FeeDistributedFromSignatures"); + logs[2].args.should.be.deep.equal({ + feeAmount, + transactionHash + }) + + const finalBridgeBalance = await token.balanceOf(homeBridge.address) + finalBridgeBalance.should.be.bignumber.equal('0') + + const feeDistributed = await blockRewardContract.feeAmount() + feeDistributed.should.be.bignumber.equal(feeAmount) + + const rewardAddressBalanceAfter = await token.balanceOf(rewards[0]) + rewardAddressBalanceAfter.should.be.bignumber.equal(feeAmount) + }) + it('should distribute fee to 3 validators', async () => { + // Given + const recipient = accounts[8]; + const owner = accounts[9] + const validators = [accounts[1], accounts[2], accounts[3]] + const rewards = [accounts[4], accounts[5], accounts[6]] + const requiredSignatures = 2 + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner).should.be.fulfilled + await blockRewardContract.setValidatorsRewards(rewards) + await blockRewardContract.setToken(token.address) + await token.setBlockRewardContract(blockRewardContract.address) + await token.transferOwnership(homeBridge.address) + + const initialValue = halfEther + const value = initialValue.mul(web3.toBigNumber(1 - fee)) + const feeAmount = initialValue.mul(web3.toBigNumber(fee)) + const feePerValidator = web3.toBigNumber(166666666666666) + const feePerValidatorPlusDiff = web3.toBigNumber(166666666666668) + const transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; + const message = createMessage(recipient, value, transactionHash, homeBridge.address); + const signature = await sign(validators[0], message) + const signature2 = await sign(validators[1], message) + + // When + await homeBridge.submitSignature(signature, message, {from: validators[0]}).should.be.fulfilled; + const { logs } = await homeBridge.submitSignature(signature2, message, {from: validators[1]}).should.be.fulfilled; + + // Then + logs.length.should.be.equal(3) + logs[1].event.should.be.equal('CollectedSignatures') + logs[2].event.should.be.equal("FeeDistributedFromSignatures"); + logs[2].args.should.be.deep.equal({ + feeAmount, + transactionHash + }) + + const finalBridgeBalance = await token.balanceOf(homeBridge.address) + finalBridgeBalance.should.be.bignumber.equal('0') + + const feeDistributed = await blockRewardContract.feeAmount() + feeDistributed.should.be.bignumber.equal(feeAmount) + + const balanceRewardAddress1 = await token.balanceOf(rewards[0]) + const balanceRewardAddress2 = await token.balanceOf(rewards[1]) + const balanceRewardAddress3 = await token.balanceOf(rewards[2]) + + expect(balanceRewardAddress1.eq(feePerValidator) || balanceRewardAddress1.eq(feePerValidatorPlusDiff)).to.equal(true) + expect(balanceRewardAddress2.eq(feePerValidator) || balanceRewardAddress2.eq(feePerValidatorPlusDiff)).to.equal(true) + expect(balanceRewardAddress3.eq(feePerValidator) || balanceRewardAddress3.eq(feePerValidatorPlusDiff)).to.equal(true) + }) + it('should distribute fee to 5 validators', async () => { + // Given + const recipient = accounts[0]; + const owner = accounts[0] + const validators = [accounts[0], accounts[1], accounts[2], accounts[3], accounts[4]] + const rewards = [accounts[5], accounts[6], accounts[7], accounts[8], accounts[9]] + const requiredSignatures = 3 + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner).should.be.fulfilled + await blockRewardContract.setValidatorsRewards(rewards) + await blockRewardContract.setToken(token.address) + await token.setBlockRewardContract(blockRewardContract.address) + await token.transferOwnership(homeBridge.address) + + const initialValue = halfEther + const value = initialValue.mul(web3.toBigNumber(1 - fee)) + const feeAmount = initialValue.mul(web3.toBigNumber(fee)) + const feePerValidator = feeAmount.div(web3.toBigNumber(5)) + const transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; + const message = createMessage(recipient, value, transactionHash, homeBridge.address); + const signature = await sign(validators[0], message) + const signature2 = await sign(validators[1], message) + const signature3 = await sign(validators[2], message) + + // When + await homeBridge.submitSignature(signature, message, {from: validators[0]}).should.be.fulfilled; + await homeBridge.submitSignature(signature2, message, {from: validators[1]}).should.be.fulfilled; + const { logs } = await homeBridge.submitSignature(signature3, message, {from: validators[2]}).should.be.fulfilled; + + // Then + logs.length.should.be.equal(3) + logs[1].event.should.be.equal('CollectedSignatures') + logs[2].event.should.be.equal("FeeDistributedFromSignatures"); + logs[2].args.should.be.deep.equal({ + feeAmount, + transactionHash + }) + + const finalBridgeBalance = await token.balanceOf(homeBridge.address) + finalBridgeBalance.should.be.bignumber.equal('0') + + const feeDistributed = await blockRewardContract.feeAmount() + feeDistributed.should.be.bignumber.equal(feeAmount) + + const balanceRewardAddress1 = await token.balanceOf(rewards[0]) + const balanceRewardAddress2 = await token.balanceOf(rewards[1]) + const balanceRewardAddress3 = await token.balanceOf(rewards[2]) + const balanceRewardAddress4 = await token.balanceOf(rewards[3]) + const balanceRewardAddress5 = await token.balanceOf(rewards[4]) + + balanceRewardAddress1.should.be.bignumber.equal(feePerValidator) + balanceRewardAddress2.should.be.bignumber.equal(feePerValidator) + balanceRewardAddress3.should.be.bignumber.equal(feePerValidator) + balanceRewardAddress4.should.be.bignumber.equal(feePerValidator) + balanceRewardAddress5.should.be.bignumber.equal(feePerValidator) + }) + }) + describe('#rewardable_executeAffirmation', () => { + let fee, homeFee, foreignFee, homeBridge, rewardableValidators, blockRewardContract, feeManager + beforeEach(async () => { + token = await ERC677BridgeTokenRewardable.new("Some ERC20", "RSZT", 18); + rewardableValidators = await RewardableValidators.new() + feeManager = await FeeManagerErcToErcPOSDAO.new() + homeBridge = await POSDAOHomeBridge.new() + fee = 0.001 + homeFee = web3.toBigNumber(web3.toWei(fee, "ether")) + foreignFee = web3.toBigNumber(web3.toWei(fee, "ether")) + blockRewardContract = await BlockReward.new() + await homeBridge.rewardableInitialize(rewardableValidators.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner, feeManager.address, homeFee, foreignFee, blockRewardContract.address).should.be.fulfilled; + }) + it('should distribute fee to one validator', async () => { + // Given + const recipient = accounts[9]; + const owner = accounts[0] + const validators = [accounts[1]] + const rewards = [accounts[2]] + const requiredSignatures = 1 + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner).should.be.fulfilled + await blockRewardContract.setValidatorsRewards(rewards) + await blockRewardContract.setToken(token.address) + await token.setBlockRewardContract(blockRewardContract.address) + await token.transferOwnership(homeBridge.address) + + const initialValue = halfEther + const value = initialValue.mul(web3.toBigNumber(1 - fee)) + const feeAmount = initialValue.mul(web3.toBigNumber(fee)) + const transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; + + const rewardAddressBalanceBefore = await token.balanceOf(rewards[0]) + rewardAddressBalanceBefore.should.be.bignumber.equal('0') + + // When + const { logs } = await homeBridge.executeAffirmation(recipient, initialValue, transactionHash, {from: validators[0]}).should.be.fulfilled; + + // Then + logs[1].event.should.be.equal("FeeDistributedFromAffirmation"); + logs[1].args.should.be.deep.equal({ + feeAmount, + transactionHash + }) + logs[2].event.should.be.equal("AffirmationCompleted"); + logs[2].args.should.be.deep.equal({ + recipient, + value: initialValue, + transactionHash + }) + + const feeDistributed = await blockRewardContract.feeAmount() + feeDistributed.should.be.bignumber.equal(feeAmount) + + const rewardAddressBalanceAfter = await token.balanceOf(rewards[0]) + rewardAddressBalanceAfter.should.be.bignumber.equal(feeAmount) + + const recipientBalance = await token.balanceOf(recipient) + recipientBalance.should.be.bignumber.equal(value) + }) + it('should distribute fee to 3 validators', async () => { + // Given + const recipient = accounts[8] + const owner = accounts[9] + const validators = [accounts[1], accounts[2], accounts[3]] + const rewards = [accounts[4], accounts[5], accounts[6]] + const requiredSignatures = 2 + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner).should.be.fulfilled + await blockRewardContract.setValidatorsRewards(rewards) + await blockRewardContract.setToken(token.address) + await token.setBlockRewardContract(blockRewardContract.address) + await token.transferOwnership(homeBridge.address) + + const initialValue = halfEther + const value = initialValue.mul(web3.toBigNumber(1 - fee)) + const feeAmount = initialValue.mul(web3.toBigNumber(fee)) + const feePerValidator = web3.toBigNumber(166666666666666) + const feePerValidatorPlusDiff = web3.toBigNumber(166666666666668) + const transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80" + + const rewardAddressBalanceBefore = await token.balanceOf(rewards[0]) + rewardAddressBalanceBefore.should.be.bignumber.equal('0') + + // When + await homeBridge.executeAffirmation(recipient, initialValue, transactionHash, {from: validators[0]}).should.be.fulfilled + const { logs } = await homeBridge.executeAffirmation(recipient, initialValue, transactionHash, {from: validators[1]}).should.be.fulfilled + + // Then + logs[1].event.should.be.equal("FeeDistributedFromAffirmation"); + logs[1].args.should.be.deep.equal({ + feeAmount, + transactionHash + }) + logs[2].event.should.be.equal("AffirmationCompleted"); + logs[2].args.should.be.deep.equal({ + recipient, + value: initialValue, + transactionHash + }) + + const feeDistributed = await blockRewardContract.feeAmount() + feeDistributed.should.be.bignumber.equal(feeAmount) + + const recipientBalance = await token.balanceOf(recipient) + recipientBalance.should.be.bignumber.equal(value) + + const balanceRewardAddress1 = await token.balanceOf(rewards[0]) + const balanceRewardAddress2 = await token.balanceOf(rewards[1]) + const balanceRewardAddress3 = await token.balanceOf(rewards[2]) + + expect(balanceRewardAddress1.eq(feePerValidator) || balanceRewardAddress1.eq(feePerValidatorPlusDiff)).to.equal(true) + expect(balanceRewardAddress2.eq(feePerValidator) || balanceRewardAddress2.eq(feePerValidatorPlusDiff)).to.equal(true) + expect(balanceRewardAddress3.eq(feePerValidator) || balanceRewardAddress3.eq(feePerValidatorPlusDiff)).to.equal(true) + }) + it('should distribute fee to 5 validators', async () => { + // Given + const recipient = accounts[0] + const owner = accounts[0] + const validators = [accounts[0], accounts[1], accounts[2], accounts[3], accounts[4]] + const rewards = [accounts[5], accounts[6], accounts[7], accounts[8], accounts[9]] + const requiredSignatures = 3 + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner).should.be.fulfilled + await blockRewardContract.setValidatorsRewards(rewards) + await blockRewardContract.setToken(token.address) + await token.setBlockRewardContract(blockRewardContract.address) + await token.transferOwnership(homeBridge.address) + + const initialValue = halfEther + const value = initialValue.mul(web3.toBigNumber(1 - fee)) + const feeAmount = initialValue.mul(web3.toBigNumber(fee)) + const feePerValidator = feeAmount.div(web3.toBigNumber(5)) + const transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80" + + const rewardAddressBalanceBefore = await token.balanceOf(rewards[0]) + rewardAddressBalanceBefore.should.be.bignumber.equal('0') + + // When + await homeBridge.executeAffirmation(recipient, initialValue, transactionHash, {from: validators[0]}).should.be.fulfilled + await homeBridge.executeAffirmation(recipient, initialValue, transactionHash, {from: validators[1]}).should.be.fulfilled + const { logs } = await homeBridge.executeAffirmation(recipient, initialValue, transactionHash, {from: validators[2]}).should.be.fulfilled + + // Then + logs[1].event.should.be.equal("FeeDistributedFromAffirmation"); + logs[1].args.should.be.deep.equal({ + feeAmount, + transactionHash + }) + logs[2].event.should.be.equal("AffirmationCompleted"); + logs[2].args.should.be.deep.equal({ + recipient, + value: initialValue, + transactionHash + }) + + const feeDistributed = await blockRewardContract.feeAmount() + feeDistributed.should.be.bignumber.equal(feeAmount) + + const recipientBalance = await token.balanceOf(recipient) + recipientBalance.should.be.bignumber.equal(value) + + const balanceRewardAddress1 = await token.balanceOf(rewards[0]) + const balanceRewardAddress2 = await token.balanceOf(rewards[1]) + const balanceRewardAddress3 = await token.balanceOf(rewards[2]) + const balanceRewardAddress4 = await token.balanceOf(rewards[3]) + const balanceRewardAddress5 = await token.balanceOf(rewards[4]) + + balanceRewardAddress1.should.be.bignumber.equal(feePerValidator) + balanceRewardAddress2.should.be.bignumber.equal(feePerValidator) + balanceRewardAddress3.should.be.bignumber.equal(feePerValidator) + balanceRewardAddress4.should.be.bignumber.equal(feePerValidator) + balanceRewardAddress5.should.be.bignumber.equal(feePerValidator) + }) + }) }) diff --git a/test/helpers/helpers.js b/test/helpers/helpers.js index cb276a2a8..c5012a8a3 100644 --- a/test/helpers/helpers.js +++ b/test/helpers/helpers.js @@ -111,3 +111,20 @@ module.exports.range = range; function ignoreExpectedError() { } module.exports.ignoreExpectedError = ignoreExpectedError; + +const getEvents = function(contract, filter) { + return new Promise((resolve, reject) => { + var event = contract[filter.event](); + event.watch(); + event.get((error, logs) => { + if(logs.length > 0){ + resolve(logs); + } else { + throw Error("Failed to find filtered event for " + filter.event); + } + }); + event.stopWatching(); + }); +} + +module.exports.getEvents = getEvents; diff --git a/test/native_to_erc/foreign_bridge_test.js b/test/native_to_erc/foreign_bridge_test.js index 12640adf1..3ef289e70 100644 --- a/test/native_to_erc/foreign_bridge_test.js +++ b/test/native_to_erc/foreign_bridge_test.js @@ -7,7 +7,7 @@ const RewardableValidators = artifacts.require("RewardableValidators.sol"); const POA20 = artifacts.require("ERC677BridgeToken.sol"); const {ERROR_MSG, ZERO_ADDRESS, ERROR_MSG_OPCODE} = require('../setup'); -const {createMessage, sign, signatureToVRS, strip0x} = require('../helpers/helpers'); +const {createMessage, sign, signatureToVRS, strip0x, getEvents} = require('../helpers/helpers'); const oneEther = web3.toBigNumber(web3.toWei(1, "ether")); const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether")); const minPerTx = web3.toBigNumber(web3.toWei(0.01, "ether")); @@ -17,20 +17,6 @@ const gasPrice = Web3Utils.toWei('1', 'gwei'); const homeDailyLimit = oneEther const homeMaxPerTx = halfEther -const getEvents = function(contract, filter) { - return new Promise((resolve, reject) => { - var event = contract[filter.event](); - event.watch(); - event.get((error, logs) => { - if(logs.length > 0){ - resolve(logs); - } else { - throw Error("Failed to find filtered event for " + filter.event); - } - }); - event.stopWatching(); - }); -} contract('ForeignBridge', async (accounts) => { let validatorContract, authorities, rewards, owner, token; before(async () => {