diff --git a/.vscode/launch.json b/.vscode/launch.json index 9657397..d918134 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,7 +18,10 @@ "${workspaceFolder}/node_modules/**/*.js", "${workspaceFolder}/lib/**/*.js", "/**/*.js" - ] + ], + "env": { + "CONTRACTS_NO_UPGRADE_PROXY": "true" + } }, { "name": "run stakingTest", diff --git a/contracts/CertifierHbbft.sol b/contracts/CertifierHbbft.sol index 6794c8b..3e85e6e 100644 --- a/contracts/CertifierHbbft.sol +++ b/contracts/CertifierHbbft.sol @@ -50,7 +50,8 @@ contract CertifierHbbft is UpgradeableOwned, ICertifier { address[] calldata _certifiedAddresses, address _validatorSet ) external { - require(msg.sender == _admin() || tx.origin == _admin() || block.number == 0, "Sender must be admin"); + require(msg.sender == _admin() || tx.origin == _admin() || address(0) == _admin() || block.number == 0, + "Sender must be admin"); require(!isInitialized(), "Contract is already initialized"); require(_validatorSet != address(0), "Validatorset must not be 0"); for (uint256 i = 0; i < _certifiedAddresses.length; i++) { diff --git a/contracts/InitializerHbbft.sol b/contracts/InitializerHbbft.sol index f00ff18..12ddf95 100644 --- a/contracts/InitializerHbbft.sol +++ b/contracts/InitializerHbbft.sol @@ -42,7 +42,6 @@ contract InitializerHbbft { /// @param _internetAddresses bytes16[] memory /// @param _parts bytes[] memory /// @param _acks bytes[][] memory - /// @param _blockReward uint256 constructor( address[] memory _contracts, address _owner, @@ -52,8 +51,7 @@ contract InitializerHbbft { bytes32[] memory _publicKeys, bytes16[] memory _internetAddresses, bytes[] memory _parts, - bytes[][] memory _acks, - uint256 _blockReward + bytes[][] memory _acks ) public { IValidatorSetHbbft(_contracts[0]).initialize( _contracts[1], // _blockRewardContract @@ -80,7 +78,7 @@ contract InitializerHbbft { _parts, _acks ); - IBlockRewardHbbft(_contracts[1]).initialize(_contracts[0], _blockReward); + IBlockRewardHbbft(_contracts[1]).initialize(_contracts[0]); address[] memory permittedAddresses = new address[](1); permittedAddresses[0] = _owner; diff --git a/contracts/KeyGenHistory.sol b/contracts/KeyGenHistory.sol index 03e78db..fc5d268 100644 --- a/contracts/KeyGenHistory.sol +++ b/contracts/KeyGenHistory.sol @@ -59,7 +59,7 @@ contract KeyGenHistory is UpgradeabilityAdmin, IKeyGenHistory { bytes[][] memory _acks ) public { // Unit Tests may deploy at block numbers other than 0. - require(msg.sender == _admin() || tx.origin == _admin() || block.number == 0, "Sender must be admin"); + require(msg.sender == _admin() || tx.origin == _admin() || address(0) == _admin() || block.number == 0, "Sender must be admin"); require(!isInitialized(), "initialization can only be done once"); // initialization can only be done once require(_validators.length != 0, "Validators must be more than 0."); require(_validators.length == _parts.length, "Wrong number of Parts!"); diff --git a/contracts/TxPermissionHbbft.sol b/contracts/TxPermissionHbbft.sol index 304f14f..1ef00fc 100644 --- a/contracts/TxPermissionHbbft.sol +++ b/contracts/TxPermissionHbbft.sol @@ -67,7 +67,7 @@ contract TxPermissionHbbft is UpgradeableOwned, ITxPermission { address _validatorSet, address _keyGenHistoryContract ) external { - require(msg.sender == _admin() || tx.origin == _admin() || block.number == 0); + require(msg.sender == _admin() || tx.origin == _admin() || address(0) == _admin() || block.number == 0); require(!isInitialized(), "initialization can only be done once"); require(_certifier != address(0)); require(_validatorSet != address(0), "ValidatorSet must not be 0"); diff --git a/contracts/ValidatorSetHbbft.sol b/contracts/ValidatorSetHbbft.sol index 51c3f95..f54a326 100644 --- a/contracts/ValidatorSetHbbft.sol +++ b/contracts/ValidatorSetHbbft.sol @@ -84,7 +84,7 @@ contract ValidatorSetHbbft is UpgradeabilityAdmin, IValidatorSetHbbft { // ============================================== Constants ======================================================= /// @dev The max number of validators. - uint256 public constant MAX_VALIDATORS = 19; + uint256 public constant MAX_VALIDATORS = 25; // ================================================ Events ======================================================== @@ -160,8 +160,8 @@ contract ValidatorSetHbbft is UpgradeabilityAdmin, IValidatorSetHbbft { address[] calldata _initialMiningAddresses, address[] calldata _initialStakingAddresses ) external { - require(msg.sender == _admin() || tx.origin == _admin() || block.number == 0, - "Initialization only on genesis block or by admin"); + require(msg.sender == _admin() || tx.origin == _admin() || address(0) == _admin() || block.number == 0, + "ValidatorSet: Initialization only on genesis block or by admin"); require(!isInitialized(), "ValidatorSet contract is already initialized"); require(_blockRewardContract != address(0), "BlockReward contract address can't be 0x0"); require(_randomContract != address(0), "Random contract address can't be 0x0"); diff --git a/contracts/base/BlockRewardHbbftBase.sol b/contracts/base/BlockRewardHbbftBase.sol index 0599ecd..5c9d636 100644 --- a/contracts/base/BlockRewardHbbftBase.sol +++ b/contracts/base/BlockRewardHbbftBase.sol @@ -26,9 +26,6 @@ contract BlockRewardHbbftBase is UpgradeableOwned, IBlockRewardHbbft { mapping(address => uint256[]) internal _epochsPoolGotRewardFor; - /// @dev The maximum per-block reward distributed among the validators. - uint256 public maxEpochReward; - /// @dev The reward amount to be distributed in native coins among participants (the validator and their /// delegators) of the specified pool (mining address) for the specified staking epoch. mapping(uint256 => mapping(address => uint256)) public epochPoolNativeReward; @@ -51,9 +48,37 @@ contract BlockRewardHbbftBase is UpgradeableOwned, IBlockRewardHbbft { /// constant by upgrading the contract. mapping(uint256 => uint256) public validatorMinRewardPercent; + /// @dev the Delta Pool holds all coins that never got emitted, since the maximum supply is 4,380,000 + uint256 public deltaPot; + + /// @dev each epoch reward, one Fraction of the delta pool gets payed out. + /// the number is the divisor of the fraction. 60 means 1/60 of the delta pool gets payed out. + uint256 public deltaPotPayoutFraction = 60; + + + /// @dev the reinsertPot holds all coins that are designed for getting reinserted into the coin circulation. + /// sources are: + /// + uint256 public reinsertPot; + + /// @dev each epoch reward, one Fraction of the reinsert pool gets payed out. + /// the number is the divisor of the fraction. 60 means 1/60 of the reinsert pool gets payed out. + uint256 public reinsertPotPayoutFraction; + /// @dev The address of the `ValidatorSet` contract. IValidatorSetHbbft public validatorSetContract; + /// @dev parts of the epoch reward get forwarded to a governance fund + /// just a dummy function for now. + address payable public governancePotAddress; + + uint256 public governancePotShareNominator; + uint256 public governancePotShareDenominator; + + uint256 public constant VALIDATOR_MIN_REWARD_PERCENT = 30; // 30% + uint256 public constant REWARD_PERCENT_MULTIPLIER = 1000000; + + // ================================================ Events ======================================================== /// @dev Emitted by the `reward` function. @@ -96,14 +121,45 @@ contract BlockRewardHbbftBase is UpgradeableOwned, IBlockRewardHbbft { /// @dev Initializes the contract at network startup. /// Can only be called by the constructor of the `InitializerHbbft` contract or owner. /// @param _validatorSet The address of the `ValidatorSetHbbft` contract. - function initialize(address _validatorSet, uint256 _maxEpochReward) external { - require(msg.sender == _admin() || tx.origin == _admin() || block.number == 0, + function initialize(address _validatorSet) external { + require(msg.sender == _admin() || tx.origin == _admin() || address(0) == _admin() || block.number == 0, "Initialization only on genesis block or by admin"); require(!isInitialized(), "initialization can only be done once"); require(_validatorSet != address(0), "ValidatorSet must not be 0"); validatorSetContract = IValidatorSetHbbft(_validatorSet); - maxEpochReward = _maxEpochReward; validatorMinRewardPercent[0] = VALIDATOR_MIN_REWARD_PERCENT; + + deltaPotPayoutFraction = 6000; + reinsertPotPayoutFraction = 6000; + governancePotAddress = 0xDA0da0da0Da0Da0Da0DA00DA0da0da0DA0DA0dA0; + governancePotShareNominator = 1; + governancePotShareDenominator = 10; + } + + function addToDeltaPot() + external + payable { + deltaPot += msg.value; + } + + function addToReinsertPot() + external + payable { + reinsertPot += msg.value; + } + + function setdeltaPotPayoutFraction(uint256 _value) + external + onlyOwner { + require(_value != 0, "Payout fraction must not be 0"); + deltaPotPayoutFraction = _value; + } + + function setReinsertPotPayoutFraction(uint256 _value) + external + onlyOwner { + require(_value != 0, "Payout fraction must not be 0"); + reinsertPotPayoutFraction = _value; } /// @dev Called by the engine when producing and closing a block, @@ -366,9 +422,6 @@ contract BlockRewardHbbftBase is UpgradeableOwned, IBlockRewardHbbft { // ============================================== Internal ======================================================== - uint256 internal constant VALIDATOR_MIN_REWARD_PERCENT = 30; // 30% - uint256 internal constant REWARD_PERCENT_MULTIPLIER = 1000000; - /// @dev Distributes rewards among pools at the latest block of a staking epoch. /// This function is called by the `reward` function. @@ -384,11 +437,28 @@ contract BlockRewardHbbftBase is UpgradeableOwned, IBlockRewardHbbft { uint256 numValidators = validators.length; require(numValidators != 0, "Empty Validator list"); - uint256 totalReward = maxEpochReward + nativeRewardUndistributed; + uint256 deltaPotShare = deltaPot / deltaPotPayoutFraction; + deltaPot -= deltaPotShare; + + // we could reuse the deltaPotShare variable here, to combat the "stack to deep" problem. + uint256 reinsertPotShare = reinsertPot / reinsertPotPayoutFraction; + reinsertPot -= reinsertPotShare; + + uint256 totalReward = deltaPotShare + reinsertPotShare + nativeRewardUndistributed; if (totalReward == 0) { return 0; } + + // we calculate the governance share here, and store it in the distributeAmount variable. + // the distributedAmount variable is later resused to track all distributed shares + // in order to handle division results in a correct way. + // we can not write clean code here, because of EVMs restriction to use only 16 local variables. + uint256 distributedAmount = totalReward * governancePotShareNominator / governancePotShareDenominator; + + governancePotAddress.transfer(distributedAmount); + + uint256 rewardToDistribute = totalReward - distributedAmount; // Indicates whether the validator is entitled to share the rewartds or not. bool[] memory isRewardedValidator = new bool[](numValidators); @@ -402,7 +472,7 @@ contract BlockRewardHbbftBase is UpgradeableOwned, IBlockRewardHbbft { ) { isRewardedValidator[i] = true; numRewardedValidators++; - } + } } // No rewards distributed in this epoch @@ -411,8 +481,7 @@ contract BlockRewardHbbftBase is UpgradeableOwned, IBlockRewardHbbft { } // Share the reward equally among the validators. - uint256 poolReward = totalReward / numRewardedValidators; - uint256 distributedAmount; + uint256 poolReward = rewardToDistribute / numRewardedValidators; if (poolReward != 0) { for (uint256 i = 0; i < numValidators; i++) { diff --git a/contracts/base/StakingHbbftBase.sol b/contracts/base/StakingHbbftBase.sol index 71d3507..41605f4 100644 --- a/contracts/base/StakingHbbftBase.sol +++ b/contracts/base/StakingHbbftBase.sol @@ -959,7 +959,7 @@ contract StakingHbbftBase is UpgradeableOwned, IStakingHbbft { bytes16[] memory _internetAddresses ) internal { - require(msg.sender == _admin() || tx.origin == _admin() || block.number == 0, + require(msg.sender == _admin() || tx.origin == _admin() || address(0) == _admin() || block.number == 0, "Initialization only on genesis block or by admin"); require(!isInitialized(), "Already initialized"); // initialization can only be done once require(_validatorSetContract != address(0),"ValidatorSet can't be 0"); diff --git a/contracts/interfaces/IBlockRewardHbbft.sol b/contracts/interfaces/IBlockRewardHbbft.sol index 40e60cb..050cf87 100644 --- a/contracts/interfaces/IBlockRewardHbbft.sol +++ b/contracts/interfaces/IBlockRewardHbbft.sol @@ -2,6 +2,6 @@ pragma solidity ^0.5.16; interface IBlockRewardHbbft { - function initialize(address, uint256) external; + function initialize(address) external; function epochsPoolGotRewardFor(address) external view returns(uint256[] memory); } diff --git a/contracts/upgradeability/UpgradeabilityAdmin.sol b/contracts/upgradeability/UpgradeabilityAdmin.sol index 76da603..8e35399 100644 --- a/contracts/upgradeability/UpgradeabilityAdmin.sol +++ b/contracts/upgradeability/UpgradeabilityAdmin.sol @@ -21,7 +21,7 @@ contract UpgradeabilityAdmin { } } - // function adminAddress() + // function getAdminAddress() // public // view // returns (address adm) { diff --git a/package-lock.json b/package-lock.json index f609d5e..6813140 100644 --- a/package-lock.json +++ b/package-lock.json @@ -537,9 +537,9 @@ }, "dependencies": { "@types/node": { - "version": "12.12.64", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.64.tgz", - "integrity": "sha512-UV1/ZJMC+HcP902wWdpC43cAcGu0IQk/I5bXjP2aSuCjsk3cE74mDvFrLKga7oDC170ugOAYBwfT4DSQW3akDA==", + "version": "12.12.69", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.69.tgz", + "integrity": "sha512-2F2VQRSFmzqgUEXw75L51MgnnZqc6bKWVSUPfrDPzp6mzGGibeVwyQcpvZvBr5RnsoMRHmC8EcBQiobSeqeJxg==", "dev": true }, "web3": { @@ -572,9 +572,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.37", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.37.tgz", - "integrity": "sha512-4c38N7p9k9yqdcANh/WExTahkBgOTmggCyrTvVcbE8ByqO3g8evt/407v/I4X/gdfUkIyZBSQh/Rc3tvuwlVGw==", + "version": "10.17.40", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.40.tgz", + "integrity": "sha512-3hZT2z2/531A5pc8hYhn1gU5Qb1SIRSgMLQ6zuHA5xtt16lWAxUGprtr8lJuc9zNJMXEIIBWfSnzqBP/4mglpA==", "dev": true }, "bn.js": { @@ -993,54 +993,6 @@ "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==", "dev": true }, - "@web3-js/scrypt-shim": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz", - "integrity": "sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw==", - "dev": true, - "requires": { - "scryptsy": "^2.1.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@web3-js/websocket": { - "version": "1.0.30", - "resolved": "https://registry.npmjs.org/@web3-js/websocket/-/websocket-1.0.30.tgz", - "integrity": "sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA==", - "dev": true, - "requires": { - "debug": "^2.2.0", - "es5-ext": "^0.10.50", - "nan": "^2.14.0", - "typedarray-to-buffer": "^3.1.5", - "yaeti": "^0.0.6" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -4994,9 +4946,9 @@ } }, "jsonschema": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.10.tgz", - "integrity": "sha512-CoRSun5gmvgSYMHx5msttse19SnQpaHoPzIqULwE7B9KtR4Od1g70sBqeUriq5r8b9R3ptDc0o7WKpUDjUgLgg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.3.0.tgz", + "integrity": "sha512-qg48ckmeeQNPyPAUVIb4Qgmg/U2Kgg5SuEyMs8Z72cnxsw5Ra088U/Foi6sMp/cs7sZ+LNrmvX0Ww+ohE2By0g==", "dev": true }, "jsprim": { @@ -6924,9 +6876,9 @@ } }, "solidity-coverage": { - "version": "0.7.10", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.10.tgz", - "integrity": "sha512-F98rYoD3bscB9qIJJrqkk+o93GbOWTT54VgfO97PrcWAenOFIC1EI5DzGJSrMvmFFfr8fsMPR89on6JR0Xf/Ig==", + "version": "0.7.11", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.11.tgz", + "integrity": "sha512-HtBhXNTK2pO6hj82lf3txZ8afoyIGSmduJHJSoeZ71RjiuNzjGFj4duEZY/kfqxYSq1yARERC6jOTZGfIAeRyA==", "dev": true, "requires": { "@solidity-parser/parser": "^0.7.0", @@ -6935,7 +6887,7 @@ "death": "^1.1.0", "detect-port": "^1.3.0", "fs-extra": "^8.1.0", - "ganache-cli": "6.9.0", + "ganache-cli": "^6.11.0", "ghost-testrpc": "^0.0.2", "global-modules": "^2.0.0", "globby": "^10.0.1", @@ -6946,7 +6898,7 @@ "recursive-readdir": "^2.2.2", "sc-istanbul": "^0.4.5", "shelljs": "^0.8.3", - "web3": "1.2.6" + "web3": "^1.3.0" }, "dependencies": { "@solidity-parser/parser": { @@ -6955,78 +6907,46 @@ "integrity": "sha512-5ma2uuwPAEX1TPl2rAPAAuGlBkKnn2oUKQvnhTFlDIB8U/KDWX77FpHtL6Rcz+OwqSCWx9IClxACgyIEJ/GhIw==", "dev": true }, - "@types/node": { - "version": "12.12.64", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.64.tgz", - "integrity": "sha512-UV1/ZJMC+HcP902wWdpC43cAcGu0IQk/I5bXjP2aSuCjsk3cE74mDvFrLKga7oDC170ugOAYBwfT4DSQW3akDA==", - "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==", - "dev": true - }, - "eth-lib": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", - "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "ethers": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", - "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", + "ganache-cli": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.12.0.tgz", + "integrity": "sha512-WV354mOSCbVH+qR609ftpz/1zsZPRsHMaQ4jo9ioBQAkguYNVU5arfgIE0+0daU0Vl9WJ/OMhRyl0XRswd/j9A==", "dev": true, "requires": { - "@types/node": "^10.3.2", - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "elliptic": "6.3.3", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.3", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" + "ethereumjs-util": "6.2.1", + "source-map-support": "0.5.12", + "yargs": "13.2.4" }, "dependencies": { + "@types/bn.js": { + "version": "4.11.6", + "bundled": true, + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { - "version": "10.17.37", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.37.tgz", - "integrity": "sha512-4c38N7p9k9yqdcANh/WExTahkBgOTmggCyrTvVcbE8ByqO3g8evt/407v/I4X/gdfUkIyZBSQh/Rc3tvuwlVGw==", + "version": "14.11.2", + "bundled": true, "dev": true }, - "elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "@types/pbkdf2": { + "version": "3.1.0", + "bundled": true, "dev": true, "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" + "@types/node": "*" } - } - } - }, - "ganache-cli": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.9.0.tgz", - "integrity": "sha512-ZdL6kPrApXF/O+f6uU431OJcwxMk69H3KPDSHHrMP82ZvZRNpDHbR+rVv7XX/YUeoQ5q6nZ2AFiGiFAVn9pfzA==", - "dev": true, - "requires": { - "ethereumjs-util": "6.1.0", - "source-map-support": "0.5.12", - "yargs": "13.2.4" - }, - "dependencies": { + }, + "@types/secp256k1": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "requires": { + "@types/node": "*" + } + }, "ansi-regex": { "version": "4.1.0", "bundled": true, @@ -7040,24 +6960,21 @@ "color-convert": "^1.9.0" } }, - "bindings": { - "version": "1.5.0", + "base-x": { + "version": "3.0.8", "bundled": true, "dev": true, "requires": { - "file-uri-to-path": "1.0.0" + "safe-buffer": "^5.0.1" } }, - "bip66": { - "version": "1.1.5", + "blakejs": { + "version": "1.1.0", "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } + "dev": true }, "bn.js": { - "version": "4.11.8", + "version": "4.11.9", "bundled": true, "dev": true }, @@ -7079,6 +6996,24 @@ "safe-buffer": "^5.0.1" } }, + "bs58": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "requires": { + "base-x": "^3.0.2" + } + }, + "bs58check": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "requires": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, "buffer-from": { "version": "1.1.1", "bundled": true, @@ -7168,18 +7103,8 @@ "bundled": true, "dev": true }, - "drbg.js": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "browserify-aes": "^1.0.6", - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4" - } - }, "elliptic": { - "version": "6.5.0", + "version": "6.5.3", "bundled": true, "dev": true, "requires": { @@ -7198,25 +7123,47 @@ "dev": true }, "end-of-stream": { - "version": "1.4.1", + "version": "1.4.4", "bundled": true, "dev": true, "requires": { "once": "^1.4.0" } }, + "ethereum-cryptography": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "requires": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, "ethereumjs-util": { - "version": "6.1.0", + "version": "6.2.1", "bundled": true, "dev": true, "requires": { + "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", "ethjs-util": "0.1.6", - "keccak": "^1.0.2", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1", - "secp256k1": "^3.0.1" + "rlp": "^2.2.3" } }, "ethjs-util": { @@ -7251,11 +7198,6 @@ "strip-eof": "^1.0.0" } }, - "file-uri-to-path": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, "find-up": { "version": "3.0.0", "bundled": true, @@ -7278,12 +7220,13 @@ } }, "hash-base": { - "version": "3.0.4", + "version": "3.1.0", "bundled": true, "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" } }, "hash.js": { @@ -7336,14 +7279,12 @@ "dev": true }, "keccak": { - "version": "1.4.0", + "version": "3.0.1", "bundled": true, "dev": true, "requires": { - "bindings": "^1.2.1", - "inherits": "^2.0.3", - "nan": "^2.2.1", - "safe-buffer": "^5.1.0" + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" } }, "lcid": { @@ -7406,13 +7347,18 @@ "bundled": true, "dev": true }, - "nan": { - "version": "2.14.0", + "nice-try": { + "version": "1.0.5", "bundled": true, "dev": true }, - "nice-try": { - "version": "1.0.5", + "node-addon-api": { + "version": "2.0.2", + "bundled": true, + "dev": true + }, + "node-gyp-build": { + "version": "4.2.3", "bundled": true, "dev": true }, @@ -7458,7 +7404,7 @@ "dev": true }, "p-limit": { - "version": "2.2.0", + "version": "2.3.0", "bundled": true, "dev": true, "requires": { @@ -7488,6 +7434,18 @@ "bundled": true, "dev": true }, + "pbkdf2": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "pump": { "version": "3.0.0", "bundled": true, @@ -7497,6 +7455,24 @@ "once": "^1.3.1" } }, + "randombytes": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "bundled": true, + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "require-directory": { "version": "2.1.1", "bundled": true, @@ -7517,36 +7493,35 @@ } }, "rlp": { - "version": "2.2.3", + "version": "2.2.6", "bundled": true, "dev": true, "requires": { - "bn.js": "^4.11.1", - "safe-buffer": "^5.1.1" + "bn.js": "^4.11.1" } }, "safe-buffer": { - "version": "5.2.0", + "version": "5.2.1", + "bundled": true, + "dev": true + }, + "scrypt-js": { + "version": "3.0.1", "bundled": true, "dev": true }, "secp256k1": { - "version": "3.7.1", + "version": "4.0.2", "bundled": true, "dev": true, "requires": { - "bindings": "^1.5.0", - "bip66": "^1.1.5", - "bn.js": "^4.11.8", - "create-hash": "^1.2.0", - "drbg.js": "^1.0.1", - "elliptic": "^6.4.1", - "nan": "^2.14.0", - "safe-buffer": "^5.1.2" + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" } }, "semver": { - "version": "5.7.0", + "version": "5.7.1", "bundled": true, "dev": true }, @@ -7555,6 +7530,11 @@ "bundled": true, "dev": true }, + "setimmediate": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, "sha.js": { "version": "2.4.11", "bundled": true, @@ -7578,7 +7558,7 @@ "dev": true }, "signal-exit": { - "version": "3.0.2", + "version": "3.0.3", "bundled": true, "dev": true }, @@ -7606,6 +7586,14 @@ "strip-ansi": "^5.1.0" } }, + "string_decoder": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, "strip-ansi": { "version": "5.2.0", "bundled": true, @@ -7627,6 +7615,11 @@ "is-hex-prefixed": "1.0.0" } }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, "which": { "version": "1.3.1", "bundled": true, @@ -7679,7 +7672,7 @@ } }, "yargs-parser": { - "version": "13.1.1", + "version": "13.1.2", "bundled": true, "dev": true, "requires": { @@ -7704,335 +7697,6 @@ "merge2": "^1.2.3", "slash": "^3.0.0" } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=", - "dev": true - }, - "scrypt-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", - "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=", - "dev": true - }, - "web3": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.6.tgz", - "integrity": "sha512-tpu9fLIComgxGrFsD8LUtA4s4aCZk7px8UfcdEy6kS2uDi/ZfR07KJqpXZMij7Jvlq+cQrTAhsPSiBVvoMaivA==", - "dev": true, - "requires": { - "@types/node": "^12.6.1", - "web3-bzz": "1.2.6", - "web3-core": "1.2.6", - "web3-eth": "1.2.6", - "web3-eth-personal": "1.2.6", - "web3-net": "1.2.6", - "web3-shh": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-bzz": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.6.tgz", - "integrity": "sha512-9NiHLlxdI1XeFtbPJAmi2jnnIHVF+GNy517wvOS72P7ZfuJTPwZaSNXfT01vWgPPE9R96/uAHDWHOg+T4WaDQQ==", - "dev": true, - "requires": { - "@types/node": "^10.12.18", - "got": "9.6.0", - "swarm-js": "0.1.39", - "underscore": "1.9.1" - }, - "dependencies": { - "@types/node": { - "version": "10.17.37", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.37.tgz", - "integrity": "sha512-4c38N7p9k9yqdcANh/WExTahkBgOTmggCyrTvVcbE8ByqO3g8evt/407v/I4X/gdfUkIyZBSQh/Rc3tvuwlVGw==", - "dev": true - } - } - }, - "web3-core": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.6.tgz", - "integrity": "sha512-y/QNBFtr5cIR8vxebnotbjWJpOnO8LDYEAzZjeRRUJh2ijmhjoYk7dSNx9ExgC0UCfNFRoNCa9dGRu/GAxwRlw==", - "dev": true, - "requires": { - "@types/bn.js": "^4.11.4", - "@types/node": "^12.6.1", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-requestmanager": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-core-helpers": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.6.tgz", - "integrity": "sha512-gYKWmC2HmO7RcDzpo4L1K8EIoy5L8iubNDuTC6q69UxczwqKF/Io0kbK/1Z10Av++NlzOSiuyGp2gc4t4UOsDw==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-eth-iban": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-core-method": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.6.tgz", - "integrity": "sha512-r2dzyPEonqkBg7Mugq5dknhV5PGaZTHBZlS/C+aMxNyQs3T3eaAsCTqlQDitwNUh/sUcYPEGF0Vo7ahYK4k91g==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6", - "web3-core-promievent": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-core-promievent": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.6.tgz", - "integrity": "sha512-km72kJef/qtQNiSjDJJVHIZvoVOm6ytW3FCYnOcCs7RIkviAb5JYlPiye0o4pJOLzCXYID7DK7Q9bhY8qWb1lw==", - "dev": true, - "requires": { - "any-promise": "1.3.0", - "eventemitter3": "3.1.2" - } - }, - "web3-core-requestmanager": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.6.tgz", - "integrity": "sha512-QU2cbsj9Dm0r6om40oSwk8Oqbp3wTa08tXuMpSmeOTkGZ3EMHJ1/4LiJ8shwg1AvPMrKVU0Nri6+uBNCdReZ+g==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6", - "web3-providers-http": "1.2.6", - "web3-providers-ipc": "1.2.6", - "web3-providers-ws": "1.2.6" - } - }, - "web3-core-subscriptions": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.6.tgz", - "integrity": "sha512-M0PzRrP2Ct13x3wPulFtc5kENH4UtnPxO9YxkfQlX2WRKENWjt4Rfq+BCVGYEk3rTutDfWrjfzjmqMRvXqEY5Q==", - "dev": true, - "requires": { - "eventemitter3": "3.1.2", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6" - } - }, - "web3-eth": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.6.tgz", - "integrity": "sha512-ROWlDPzh4QX6tlGGGlAK6X4kA2n0/cNj/4kb0nNVWkRouGmYO0R8k6s47YxYHvGiXt0s0++FUUv5vAbWovtUQw==", - "dev": true, - "requires": { - "underscore": "1.9.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-eth-abi": "1.2.6", - "web3-eth-accounts": "1.2.6", - "web3-eth-contract": "1.2.6", - "web3-eth-ens": "1.2.6", - "web3-eth-iban": "1.2.6", - "web3-eth-personal": "1.2.6", - "web3-net": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-eth-abi": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.6.tgz", - "integrity": "sha512-w9GAyyikn8nSifSDZxAvU9fxtQSX+W2xQWMmrtTXmBGCaE4/ywKOSPAO78gq8AoU4Wq5yqVGKZLLbfpt7/sHlA==", - "dev": true, - "requires": { - "ethers": "4.0.0-beta.3", - "underscore": "1.9.1", - "web3-utils": "1.2.6" - } - }, - "web3-eth-accounts": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.6.tgz", - "integrity": "sha512-cDVtonHRgzqi/ZHOOf8kfCQWFEipcfQNAMzXIaKZwc0UUD9mgSI5oJrN45a89Ze+E6Lz9m77cDG5Ax9zscSkcw==", - "dev": true, - "requires": { - "@web3-js/scrypt-shim": "^0.1.0", - "any-promise": "1.3.0", - "crypto-browserify": "3.12.0", - "eth-lib": "^0.2.8", - "ethereumjs-common": "^1.3.2", - "ethereumjs-tx": "^2.1.1", - "underscore": "1.9.1", - "uuid": "3.3.2", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-utils": "1.2.6" - }, - "dependencies": { - "eth-lib": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", - "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, - "requires": { - "bn.js": "^4.11.6", - "elliptic": "^6.4.0", - "xhr-request-promise": "^0.1.2" - } - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - } - } - }, - "web3-eth-contract": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.6.tgz", - "integrity": "sha512-ak4xbHIhWgsbdPCkSN+HnQc1SH4c856y7Ly+S57J/DQVzhFZemK5HvWdpwadJrQTcHET3ZeId1vq3kmW7UYodw==", - "dev": true, - "requires": { - "@types/bn.js": "^4.11.4", - "underscore": "1.9.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-promievent": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-eth-abi": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-eth-ens": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.6.tgz", - "integrity": "sha512-8UEqt6fqR/dji/jBGPFAyBs16OJjwi0t2dPWXPyGXmty/fH+osnXwWXE4HRUyj4xuafiM5P1YkXMsPhKEadjiw==", - "dev": true, - "requires": { - "eth-ens-namehash": "2.0.8", - "underscore": "1.9.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-promievent": "1.2.6", - "web3-eth-abi": "1.2.6", - "web3-eth-contract": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-eth-iban": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.6.tgz", - "integrity": "sha512-TPMc3BW9Iso7H+9w+ytbqHK9wgOmtocyCD3PaAe5Eie50KQ/j7ThA60dGJnxItVo6yyRv5pZAYxPVob9x/fJlg==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "web3-utils": "1.2.6" - } - }, - "web3-eth-personal": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.6.tgz", - "integrity": "sha512-T2NUkh1plY8d7wePXSoHnaiKOd8dLNFaQfgBl9JHU6S7IJrG9jnYD9bVxLEgRUfHs9gKf9tQpDf7AcPFdq/A8g==", - "dev": true, - "requires": { - "@types/node": "^12.6.1", - "web3-core": "1.2.6", - "web3-core-helpers": "1.2.6", - "web3-core-method": "1.2.6", - "web3-net": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-net": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.6.tgz", - "integrity": "sha512-hsNHAPddrhgjWLmbESW0KxJi2GnthPcow0Sqpnf4oB6+/+ZnQHU9OsIyHb83bnC1OmunrK2vf9Ye2mLPdFIu3A==", - "dev": true, - "requires": { - "web3-core": "1.2.6", - "web3-core-method": "1.2.6", - "web3-utils": "1.2.6" - } - }, - "web3-providers-http": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.6.tgz", - "integrity": "sha512-2+SaFCspb5f82QKuHB3nEPQOF9iSWxRf7c18fHtmnLNVkfG9SwLN1zh67bYn3tZGUdOI3gj8aX4Uhfpwx9Ezpw==", - "dev": true, - "requires": { - "web3-core-helpers": "1.2.6", - "xhr2-cookies": "1.1.0" - } - }, - "web3-providers-ipc": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.6.tgz", - "integrity": "sha512-b0Es+/GTZyk5FG3SgUDW+2/mBwJAXWt5LuppODptiOas8bB2khLjG6+Gm1K4uwOb+1NJGPt5mZZ8Wi7vibtQ+A==", - "dev": true, - "requires": { - "oboe": "2.1.4", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6" - } - }, - "web3-providers-ws": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.6.tgz", - "integrity": "sha512-20waSYX+gb5M5yKhug5FIwxBBvkKzlJH7sK6XEgdOx6BZ9YYamLmvg9wcRVtnSZO8hV/3cWenO/tRtTrHVvIgQ==", - "dev": true, - "requires": { - "@web3-js/websocket": "^1.0.29", - "underscore": "1.9.1", - "web3-core-helpers": "1.2.6" - } - }, - "web3-shh": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.6.tgz", - "integrity": "sha512-rouWyOOM6YMbLQd65grpj8BBezQfgNeRRX+cGyW4xsn6Xgu+B73Zvr6OtA/ftJwwa9bqHGpnLrrLMeWyy4YLUw==", - "dev": true, - "requires": { - "web3-core": "1.2.6", - "web3-core-method": "1.2.6", - "web3-core-subscriptions": "1.2.6", - "web3-net": "1.2.6" - } - }, - "web3-utils": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.6.tgz", - "integrity": "sha512-8/HnqG/l7dGmKMgEL9JeKPTtjScxOePTzopv5aaKFExPfaBrYRkgoMqhoowCiAl/s16QaTn4DoIF1QC4YsT7Mg==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "eth-lib": "0.2.7", - "ethereum-bloom-filters": "^1.0.6", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "underscore": "1.9.1", - "utf8": "3.0.0" - } } } }, @@ -9597,9 +9261,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.37", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.37.tgz", - "integrity": "sha512-4c38N7p9k9yqdcANh/WExTahkBgOTmggCyrTvVcbE8ByqO3g8evt/407v/I4X/gdfUkIyZBSQh/Rc3tvuwlVGw==", + "version": "10.17.40", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.40.tgz", + "integrity": "sha512-3hZT2z2/531A5pc8hYhn1gU5Qb1SIRSgMLQ6zuHA5xtt16lWAxUGprtr8lJuc9zNJMXEIIBWfSnzqBP/4mglpA==", "dev": true } } @@ -9619,9 +9283,9 @@ }, "dependencies": { "@types/node": { - "version": "12.12.64", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.64.tgz", - "integrity": "sha512-UV1/ZJMC+HcP902wWdpC43cAcGu0IQk/I5bXjP2aSuCjsk3cE74mDvFrLKga7oDC170ugOAYBwfT4DSQW3akDA==", + "version": "12.12.69", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.69.tgz", + "integrity": "sha512-2F2VQRSFmzqgUEXw75L51MgnnZqc6bKWVSUPfrDPzp6mzGGibeVwyQcpvZvBr5RnsoMRHmC8EcBQiobSeqeJxg==", "dev": true } } @@ -9717,9 +9381,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.37", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.37.tgz", - "integrity": "sha512-4c38N7p9k9yqdcANh/WExTahkBgOTmggCyrTvVcbE8ByqO3g8evt/407v/I4X/gdfUkIyZBSQh/Rc3tvuwlVGw==", + "version": "10.17.40", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.40.tgz", + "integrity": "sha512-3hZT2z2/531A5pc8hYhn1gU5Qb1SIRSgMLQ6zuHA5xtt16lWAxUGprtr8lJuc9zNJMXEIIBWfSnzqBP/4mglpA==", "dev": true }, "elliptic": { @@ -9881,9 +9545,9 @@ }, "dependencies": { "@types/node": { - "version": "12.12.64", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.64.tgz", - "integrity": "sha512-UV1/ZJMC+HcP902wWdpC43cAcGu0IQk/I5bXjP2aSuCjsk3cE74mDvFrLKga7oDC170ugOAYBwfT4DSQW3akDA==", + "version": "12.12.69", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.69.tgz", + "integrity": "sha512-2F2VQRSFmzqgUEXw75L51MgnnZqc6bKWVSUPfrDPzp6mzGGibeVwyQcpvZvBr5RnsoMRHmC8EcBQiobSeqeJxg==", "dev": true } } diff --git a/package.json b/package.json index 451e54b..c1e8c9d 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "generate-uml": "sol2uml ./contracts -o docs/classDiagram.svg", "runGanache": "node_modules/.bin/ganache-cli --allowUnlimitedContractSize --gasLimit 0xfffffffffff --port \"8545\" --accounts 200 --defaultBalanceEther 1000000 --mnemonic \"vanish project fall sister ceiling extend repeat stool promote magnet century engine trouble blanket fruit\"", "test": "node scripts/check_for_clashing.js && bash scripts/test.sh", - "testDev": "bash scripts/test.sh test/Initializer.js" + "testNoUpgradeProxy": "export CONTRACTS_NO_UPGRADE_PROXY=true && node scripts/check_for_clashing.js && bash scripts/test.sh", + "testDev": "bash scripts/test.sh test/BlockRewardHbbft.js test/mockContracts/BlockRewardHbbftCoinsMock.sol test/mockContracts/RandomHbbftMock.sol test/mockContracts/ValidatorSetHbbftMock.sol test/mockContracts/StakingHbbftCoinsMock.sol" }, "repository": { "type": "git", @@ -41,7 +42,7 @@ "node-fetch": "^2.6.0", "solc": "^0.5.16", "solhint": "^2.0.0", - "solidity-coverage": "^0.7.10", + "solidity-coverage": "^0.7.11", "truffle": "^5.1.42", "web3": "^1.2.11" } diff --git a/scripts/make_spec_hbbft.js b/scripts/make_spec_hbbft.js index 1e0585c..b9f715d 100755 --- a/scripts/make_spec_hbbft.js +++ b/scripts/make_spec_hbbft.js @@ -286,8 +286,7 @@ async function main() { publicKeysSplit, internetAddresses, init_data.parts, - init_data.acks, - ethToWei + init_data.acks ]}); spec.accounts['0xFF00000000000000000000000000000000000000'] = { diff --git a/test/BlockRewardHbbft.js b/test/BlockRewardHbbft.js index fab69cb..a413afe 100644 --- a/test/BlockRewardHbbft.js +++ b/test/BlockRewardHbbft.js @@ -13,6 +13,15 @@ require('chai') .use(require('chai-bn')(BN)) .should(); +// delegatecall are a problem for truffle debugger +// therefore it makes sense to use a proxy for automated testing to have the proxy testet. +// and to not use it if specific transactions needs to get debugged, +// like truffle `debug 0xabc`. +const useUpgradeProxy = !(process.env.CONTRACTS_NO_UPGRADE_PROXY == 'true'); + +const governanceFundAddress = '0xDA0da0da0Da0Da0Da0DA00DA0da0da0DA0DA0dA0'; +console.log('useUpgradeProxy:', useUpgradeProxy); + contract('BlockRewardHbbft', async accounts => { let owner; let blockRewardHbbft; @@ -36,7 +45,7 @@ contract('BlockRewardHbbft', async accounts => { const KEY_GEN_DURATION = new BN(2); // we assume that there is a fixed duration in blocks, in reality it varies. const STAKE_WITHDRAW_DISALLOW_PERIOD = 2; // one less than EPOCH DURATION, therefore it meets the conditions. const MIN_STAKE = new BN(web3.utils.toWei('1', 'ether')); - const MAX_BLOCK_REWARD = new BN(100); // the maximum per-block reward distributed to the validators + describe('reward()', async () => { @@ -49,28 +58,45 @@ contract('BlockRewardHbbft', async accounts => { initialStakingAddresses[0].should.not.be.equal('0x0000000000000000000000000000000000000000'); initialStakingAddresses[1].should.not.be.equal('0x0000000000000000000000000000000000000000'); initialStakingAddresses[2].should.not.be.equal('0x0000000000000000000000000000000000000000'); + + + // Deploy BlockRewardHbbft contract blockRewardHbbft = await BlockRewardHbbft.new(); - blockRewardHbbft = await AdminUpgradeabilityProxy.new(blockRewardHbbft.address, owner, []); - blockRewardHbbft = await BlockRewardHbbft.at(blockRewardHbbft.address); + if (useUpgradeProxy) { + blockRewardHbbft = await AdminUpgradeabilityProxy.new(blockRewardHbbft.address, owner, []); + blockRewardHbbft = await BlockRewardHbbft.at(blockRewardHbbft.address); + } + // Deploy RandomHbbft contract randomHbbft = await RandomHbbft.new(); - randomHbbft = await AdminUpgradeabilityProxy.new(randomHbbft.address, owner, []); - randomHbbft = await RandomHbbft.at(randomHbbft.address); + if (useUpgradeProxy) { + randomHbbft = await AdminUpgradeabilityProxy.new(randomHbbft.address, owner, []); + randomHbbft = await RandomHbbft.at(randomHbbft.address); + } // Deploy StakingHbbft contract stakingHbbft = await StakingHbbft.new(); - stakingHbbft = await AdminUpgradeabilityProxy.new(stakingHbbft.address, owner, []); - stakingHbbft = await StakingHbbft.at(stakingHbbft.address); + if (useUpgradeProxy) { + stakingHbbft = await AdminUpgradeabilityProxy.new(stakingHbbft.address, owner, []); + stakingHbbft = await StakingHbbft.at(stakingHbbft.address); + } // Deploy ValidatorSetHbbft contract validatorSetHbbft = await ValidatorSetHbbft.new(); - validatorSetHbbft = await AdminUpgradeabilityProxy.new(validatorSetHbbft.address, owner, []); - validatorSetHbbft = await ValidatorSetHbbft.at(validatorSetHbbft.address); + if (useUpgradeProxy) { + validatorSetHbbft = await AdminUpgradeabilityProxy.new(validatorSetHbbft.address, owner, []); + validatorSetHbbft = await ValidatorSetHbbft.at(validatorSetHbbft.address); + } //await increaseTime(1); keyGenHistory = await KeyGenHistory.new(); - keyGenHistory = await AdminUpgradeabilityProxy.new(keyGenHistory.address, owner, []); - keyGenHistory = await KeyGenHistory.at(keyGenHistory.address); + if (useUpgradeProxy) { + keyGenHistory = await AdminUpgradeabilityProxy.new(keyGenHistory.address, owner, []); + keyGenHistory = await KeyGenHistory.at(keyGenHistory.address); + } + + // console.log('keyGenHistory._admin(): ', await keyGenHistory._admin.call()); + // console.log('owner: ', owner); await keyGenHistory.initialize(validatorSetHbbft.address, initialValidators, [[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,181,129,31,84,186,242,5,151,59,35,196,140,106,29,40,112,142,156,132,158,47,223,253,185,227,249,190,96,5,99,239,213,127,29,136,115,71,164,202,44,6,171,131,251,147,159,54,49,1,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,177,133,61,18,58,222,74,65,5,126,253,181,113,165,43,141,56,226,132,208,218,197,119,179,128,30,162,251,23,33,73,38,120,246,223,233,11,104,60,154,241,182,147,219,81,45,134,239,69,169,198,188,152,95,254,170,108,60,166,107,254,204,195,170,234,154,134,26,91,9,139,174,178,248,60,65,196,218,46,163,218,72,1,98,12,109,186,152,148,159,121,254,34,112,51,70,121,51,167,35,240,5,134,197,125,252,3,213,84,70,176,160,36,73,140,104,92,117,184,80,26,240,106,230,241,26,79,46,241,195,20,106,12,186,49,254,168,233,25,179,96,62,104,118,153,95,53,127,160,237,246,41],[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,181,129,31,84,186,242,5,151,59,35,196,140,106,29,40,112,142,156,132,158,47,223,253,185,227,249,190,96,5,99,239,213,127,29,136,115,71,164,202,44,6,171,131,251,147,159,54,49,1,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,177,133,61,18,58,222,74,65,5,126,253,181,113,165,43,141,56,226,132,208,218,197,119,179,128,30,162,251,23,33,73,38,120,246,223,233,11,104,60,154,241,182,147,219,81,45,134,239,69,169,198,188,152,95,254,170,108,60,166,107,254,204,195,170,234,154,134,26,91,9,139,174,178,248,60,65,196,218,46,163,218,72,1,98,12,109,186,152,148,159,121,254,34,112,51,70,121,51,167,35,240,5,134,197,125,252,3,213,84,70,176,160,36,73,140,104,92,117,184,80,26,240,106,230,241,26,79,46,241,195,20,106,12,186,49,254,168,233,25,179,96,62,104,118,153,95,53,127,160,237,246,41],[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,181,129,31,84,186,242,5,151,59,35,196,140,106,29,40,112,142,156,132,158,47,223,253,185,227,249,190,96,5,99,239,213,127,29,136,115,71,164,202,44,6,171,131,251,147,159,54,49,1,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,177,133,61,18,58,222,74,65,5,126,253,181,113,165,43,141,56,226,132,208,218,197,119,179,128,30,162,251,23,33,73,38,120,246,223,233,11,104,60,154,241,182,147,219,81,45,134,239,69,169,198,188,152,95,254,170,108,60,166,107,254,204,195,170,234,154,134,26,91,9,139,174,178,248,60,65,196,218,46,163,218,72,1,98,12,109,186,152,148,159,121,254,34,112,51,70,121,51,167,35,240,5,134,197,125,252,3,213,84,70,176,160,36,73,140,104,92,117,184,80,26,240,106,230,241,26,79,46,241,195,20,106,12,186,49,254,168,233,25,179,96,62,104,118,153,95,53,127,160,237,246,41]], [[[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,239,1,112,13,13,251,103,186,212,78,44,47,250,221,84,118,88,7,64,206,186,11,2,8,204,140,106,179,52,251,237,19,53,74,187,217,134,94,66,68,89,42,85,207,155,220,101,223,51,199,37,38,203,132,13,77,78,114,53,219,114,93,21,25,164,12,43,252,160,16,23,111,79,230,121,95,223,174,211,172,231,0,52,25,49,152,79,128,39,117,216,85,201,237,242,151,219,149,214,77,233,145,47,10,184,175,162,174,237,177,131,45,126,231,32,147,227,170,125,133,36,123,164,232,129,135,196,136,186,45,73,226,179,169,147,42,41,140,202,191,12,73,146,2]],[[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,239,1,112,13,13,251,103,186,212,78,44,47,250,221,84,118,88,7,64,206,186,11,2,8,204,140,106,179,52,251,237,19,53,74,187,217,134,94,66,68,89,42,85,207,155,220,101,223,51,199,37,38,203,132,13,77,78,114,53,219,114,93,21,25,164,12,43,252,160,16,23,111,79,230,121,95,223,174,211,172,231,0,52,25,49,152,79,128,39,117,216,85,201,237,242,151,219,149,214,77,233,145,47,10,184,175,162,174,237,177,131,45,126,231,32,147,227,170,125,133,36,123,164,232,129,135,196,136,186,45,73,226,179,169,147,42,41,140,202,191,12,73,146,2]],[[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,239,1,112,13,13,251,103,186,212,78,44,47,250,221,84,118,88,7,64,206,186,11,2,8,204,140,106,179,52,251,237,19,53,74,187,217,134,94,66,68,89,42,85,207,155,220,101,223,51,199,37,38,203,132,13,77,78,114,53,219,114,93,21,25,164,12,43,252,160,16,23,111,79,230,121,95,223,174,211,172,231,0,52,25,49,152,79,128,39,117,216,85,201,237,242,151,219,149,214,77,233,145,47,10,184,175,162,174,237,177,131,45,126,231,32,147,227,170,125,133,36,123,164,232,129,135,196,136,186,45,73,226,179,169,147,42,41,140,202,191,12,73,146,2]]] @@ -113,12 +139,13 @@ contract('BlockRewardHbbft', async accounts => { // Initialize BlockRewardHbbft await blockRewardHbbft.initialize( - validatorSetHbbft.address, - MAX_BLOCK_REWARD + validatorSetHbbft.address ).should.be.fulfilled; + }); + it('staking epoch #0 finished', async () => { let stakingEpoch = await stakingHbbft.stakingEpoch.call(); @@ -239,6 +266,102 @@ contract('BlockRewardHbbft', async accounts => { ); } }); + + const addToDeltaPotValue = new BN(web3.utils.toWei('60')); + + it('DMD Pots: filling delta pot', async () => { + + const stakingEpoch = await stakingHbbft.stakingEpoch.call(); + stakingEpoch.should.be.bignumber.equal(new BN(2)); + + //checking preconditions. + // get the current address pof the governance pot. + + const blockRewardBalance = await web3.eth.getBalance(blockRewardHbbft.address); + blockRewardBalance.should.be.equal('0'); + + (await blockRewardHbbft.deltaPot.call()).should.be.bignumber.equal(new BN('0')); + (await blockRewardHbbft.reinsertPot.call()).should.be.bignumber.equal(new BN('0')); + + await blockRewardHbbft.addToDeltaPot({value: addToDeltaPotValue}).should.be.fulfilled; + (await blockRewardHbbft.deltaPot.call()).should.be.bignumber.equal(addToDeltaPotValue); + + }); + + + it('DMD Pots: governance and validators got correct share.', async () => { + + const currentValidators = await validatorSetHbbft.getValidators.call(); + currentValidators.length.should.be.equal(3); + const initialGovernancePotBalance = await getCurrentGovernancePotValue(); + stakingEpoch = await stakingHbbft.stakingEpoch.call(); + + await timeTravelToTransition(); + await timeTravelToEndEpoch(); + + const currentGovernancePotBalance = await getCurrentGovernancePotValue(); + const governancePotIncrease = currentGovernancePotBalance.sub(initialGovernancePotBalance); + + const totalReward = addToDeltaPotValue.div(new BN('6000')); + const expectedDAOShare = totalReward.div(new BN('10')); + + governancePotIncrease.should.to.be.bignumber.equal(expectedDAOShare); + + //since there are a lot of delegators, we need to calc it on a basis that pays out the validator min reward. + const minValidatorSharePercent = await blockRewardHbbft.VALIDATOR_MIN_REWARD_PERCENT.call(); + + const expectedValidatorReward = totalReward.sub(expectedDAOShare).div(new BN(currentValidators.length)).mul(minValidatorSharePercent).div(new BN('100')); + const actualValidatorReward = await blockRewardHbbft.getValidatorReward.call(stakingEpoch, currentValidators[1]); + + actualValidatorReward.should.be.bignumber.equal(expectedValidatorReward); + + }); + + + + it('DMD Pots: reinsert pot works as expected.', async () => { + + //refilling the delta pot. + const deltaPotCurrentValue = await blockRewardHbbft.deltaPot.call() + const fillUpMissing = addToDeltaPotValue.sub(deltaPotCurrentValue); + + await blockRewardHbbft.addToDeltaPot({value: fillUpMissing}).should.be.fulfilled; + (await blockRewardHbbft.deltaPot.call()).should.be.bignumber.equal(addToDeltaPotValue); + + const addedToReinsertPot = new BN(web3.utils.toWei('60')); + + await blockRewardHbbft.addToReinsertPot({value: addedToReinsertPot}).should.be.fulfilled; + const reinsertPotAfterAdd = await blockRewardHbbft.reinsertPot.call(); + reinsertPotAfterAdd.should.be.bignumber.equal(addedToReinsertPot); + + stakingEpoch = await stakingHbbft.stakingEpoch.call(); + + const initialGovernancePotBalance = await getCurrentGovernancePotValue(); + + await timeTravelToTransition(); + await timeTravelToEndEpoch(); + + const currentGovernancePotBalance = await getCurrentGovernancePotValue(); + const governancePotIncrease = currentGovernancePotBalance.sub(initialGovernancePotBalance); + + const totalReward = addToDeltaPotValue.div(new BN('6000')).add(addedToReinsertPot.div(new BN('6000'))); + + const expectedDAOShare = totalReward.div(new BN('10')); + + // we expect 1 wei difference, since the reward combination from 2 pots results in that. + //expectedDAOShare.sub(governancePotIncrease).should.to.be.bignumber.lte(new BN('1')); + governancePotIncrease.should.to.be.bignumber.equal(expectedDAOShare); + + //since there are a lot of delegators, we need to calc it on a basis that pays out the validator min reward. + const minValidatorSharePercent = await blockRewardHbbft.VALIDATOR_MIN_REWARD_PERCENT.call(); + const currentValidators = await validatorSetHbbft.getValidators.call(); + const expectedValidatorReward = totalReward.sub(expectedDAOShare).div(new BN(currentValidators.length)).mul(minValidatorSharePercent).div(new BN('100')); + const actualValidatorReward = await blockRewardHbbft.getValidatorReward.call(stakingEpoch, currentValidators[1]); + + actualValidatorReward.should.be.bignumber.equal(expectedValidatorReward); + }); + + }); Array.prototype.sortedEqual = function(arr) { @@ -251,14 +374,23 @@ contract('BlockRewardHbbft', async accounts => { // await validatorSetHbbft.setSystemAddress('0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE').should.be.fulfilled; // } + async function getCurrentGovernancePotValue() { + const governnancePotAddress = await blockRewardHbbft.governancePotAddress.call(); + (new BN(governnancePotAddress)).should.be.bignumber.gt(new BN(0)); + const result = new BN(await web3.eth.getBalance(governnancePotAddress)); + return result; + } + + async function callReward(isEpochEndBlock) { // console.log('getting validators...'); // note: this call used to crash because of a internal problem with a previous call of evm_mine and evm_increase_time https://github.com/DMDcoin/hbbft-posdao-contracts/issues/13 const validators = await validatorSetHbbft.getValidators.call(); - //console.log('got validators:', validators); + // console.log('got validators:', validators); await blockRewardHbbft.setSystemAddress(owner).should.be.fulfilled; await blockRewardHbbft.reward(isEpochEndBlock, {from: owner}).should.be.fulfilled; await blockRewardHbbft.setSystemAddress('0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE').should.be.fulfilled; + } @@ -284,6 +416,7 @@ contract('BlockRewardHbbft', async accounts => { } async function timeTravelToEndEpoch() { + const endTimeOfCurrentEpoch = await stakingHbbft.stakingFixedEpochEndTime.call(); await validatorSetHbbft.setCurrentTimestamp(endTimeOfCurrentEpoch); await callReward(true); diff --git a/test/Initializer.js b/test/Initializer.js index 9700a23..7eade68 100644 --- a/test/Initializer.js +++ b/test/Initializer.js @@ -56,7 +56,6 @@ contract('InitializerHbbft', async accounts => { '0x20200000000000000000000000000000', '0x30300000000000000000000000000000']; - let epochReward = new BN(web3.utils.toWei('5', 'ether')); const partsRaw = [[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,162,238,181,164,119,226,238,142,43,227,179,139,95,25,108,237,11,190,84,64,234,22,245,210,187,24,142,145,31,26,197,119,92,171,182,30,182,191,151,218,208,96,103,110,14,170,189,220,3,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,21,73,242,168,17,236,103,137,92,198,188,151,185,9,174,175,170,174,57,210,222,4,81,210,164,8,69,148,77,228,38,240,153,232,223,247,87,154,182,186,84,25,66,211,40,191,201,51,82,23,210,22,213,222,200,8,206,218,143,128,49,28,60,223,37,52,95,47,33,245,72,158,241,216,97,244,234,136,89,239,199,11,252,232,95,18,174,135,13,237,240,213,206,206,85,52,124,247,123,199,87,112,132,42,136,94,223,15,75,137,122,27,20,92,167,40,222,99,160,147,245,251,242,221,134,74,193,248,249,246,54,58,185,109,78,212,36,101,241,65,82,183,246,62,156,217,247,255,92,205,160,220,153,0,0,0,0,0,0,0,4,249,64,230,166,97,82,165,124,79,27,92,167,19,229,52,40,203,120,236,87,142,125,122,227,174,162,64,228,170,35,46,169,74,119,13,26,126,67,141,151,3,86,253,135,156,100,60,42,68,245,201,4,66,216,34,29,88,229,82,88,171,213,215,25,96,245,193,33,229,228,139,233,239,14,164,187,39,151,82,164,72,181,215,161,64,167,181,169,96,89,32,93,180,176,201,116,8,190,99,179,132,43,11,107,59,223,207,173,43,197,181,169,127,184,189,122,220,159,133,133,17,192,5,149,159,97,197,143,104,103,252,93,120,213,56,242,193,4,27,187,151,60,172,129,55,69,23,243,110,119,16,151,153,0,0,0,0,0,0,0,4,144,226,236,244,137,245,236,219,56,172,227,38,22,176,15,182,184,184,45,175,169,208,170,150,182,129,76,191,47,255,123,213,136,70,214,129,234,24,96,55,181,159,73,123,96,55,238,104,140,106,39,86,194,82,217,229,245,194,114,78,33,192,217,137,147,141,230,183,211,227,236,196,102,226,30,247,198,211,117,159,70,135,219,249,232,158,39,102,214,42,163,97,67,172,10,15,53,212,46,69,144,227,87,81,113,248,238,229,74,78,4,158,139,125,42,181,220,208,108,188,71,4,193,66,135,63,246,180,166,251,117,160,133,3,14,154,17,254,34,215,98,212,107,3,219,145,162,81,154,129,98,30],[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,178,73,138,14,3,78,162,102,191,223,232,10,81,96,118,193,17,245,152,100,177,160,138,30,241,144,254,80,221,191,133,251,43,252,251,55,111,234,36,30,11,227,3,209,11,29,97,12,3,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,190,190,139,180,190,148,3,35,23,114,210,184,188,37,29,84,197,247,58,199,180,139,151,50,108,72,160,72,104,120,177,113,88,114,102,35,83,214,49,107,226,189,62,146,134,227,121,204,221,170,229,103,242,35,66,174,12,222,96,244,80,109,177,162,22,173,241,253,188,107,213,119,32,142,210,120,23,6,255,53,195,183,16,224,211,157,34,76,41,196,121,60,10,124,231,193,177,178,201,176,242,10,34,30,74,16,76,255,101,225,104,179,5,15,231,147,247,214,103,172,127,161,226,217,18,140,93,42,235,252,105,19,214,191,80,37,230,77,82,122,248,38,124,30,68,164,81,129,51,162,87,154,153,0,0,0,0,0,0,0,4,45,167,32,19,176,115,181,244,240,144,71,62,123,234,47,139,101,220,132,48,31,222,255,194,15,65,214,103,75,68,161,78,40,143,28,242,143,191,87,76,169,19,24,217,145,231,90,139,69,34,90,12,175,146,173,49,116,34,148,58,62,142,168,154,1,79,76,99,59,135,153,22,213,9,80,206,179,110,110,123,8,42,101,53,36,241,202,64,203,169,148,175,0,2,217,163,109,89,248,214,243,66,44,69,11,100,90,132,74,218,16,240,20,157,154,134,8,63,131,18,59,157,105,93,133,47,166,97,196,160,48,54,218,118,46,146,224,36,123,226,204,171,215,17,73,92,147,55,1,41,54,32,153,0,0,0,0,0,0,0,4,116,101,44,65,60,102,230,141,166,221,113,19,43,220,253,67,27,109,103,171,33,42,189,108,84,229,139,200,63,218,76,180,101,159,208,102,117,168,34,185,211,61,12,143,250,49,210,194,39,135,64,150,174,159,196,254,136,138,229,53,214,85,228,119,125,222,201,207,137,10,57,88,233,155,50,94,50,238,174,188,71,119,14,67,50,222,24,92,82,87,126,120,5,30,112,40,106,216,120,181,16,197,44,52,86,129,181,241,249,91,31,253,24,42,106,14,5,175,226,29,226,200,218,97,99,81,125,219,133,214,228,198,138,241,41,193,138,218,51,168,61,46,35,86,144,153,99,180,150,11,4,112],[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,170,254,25,182,81,8,235,232,45,133,72,208,54,10,151,224,33,250,175,154,155,189,139,187,155,22,199,114,11,221,65,195,66,45,57,81,129,41,252,72,173,189,241,122,193,176,97,209,3,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,106,140,219,6,75,230,222,99,131,82,163,144,68,231,71,69,7,214,27,149,103,189,152,156,32,231,59,113,140,92,46,178,144,219,172,255,183,225,111,161,65,244,242,135,6,223,69,149,189,167,16,27,107,145,136,2,12,12,243,105,75,232,172,184,119,164,14,223,101,219,182,114,55,189,158,72,194,84,185,46,74,77,128,16,2,195,132,20,78,189,141,196,64,145,81,196,15,182,249,21,181,205,247,242,35,208,150,216,84,254,243,5,232,211,110,196,137,93,18,176,42,201,176,20,114,94,139,48,60,113,173,246,59,152,54,204,22,124,81,29,86,57,176,80,68,85,253,54,169,193,165,91,153,0,0,0,0,0,0,0,4,104,82,218,8,57,188,206,90,232,210,234,64,176,216,102,167,61,82,75,197,47,186,148,82,186,148,182,186,30,33,232,250,130,0,204,228,25,63,7,21,157,244,225,15,53,251,119,149,11,45,150,165,213,162,59,248,44,174,177,88,128,38,11,228,110,198,243,237,199,79,167,252,11,250,131,140,109,122,89,181,115,128,198,25,153,196,196,248,72,212,208,54,32,102,7,208,238,103,32,125,62,111,222,83,6,5,148,59,10,74,29,64,4,251,189,34,108,226,206,8,77,109,181,121,208,54,82,193,89,132,22,238,147,160,28,88,39,32,50,147,222,138,153,191,243,96,34,218,212,51,159,23,153,0,0,0,0,0,0,0,4,20,112,232,10,136,250,15,177,137,89,249,144,240,199,202,172,135,49,130,254,98,208,175,191,151,185,180,168,51,4,128,163,66,75,212,151,21,75,144,199,45,191,89,166,90,109,221,74,10,97,171,7,180,219,192,127,71,90,221,87,223,233,110,232,90,245,107,197,138,136,222,206,16,139,147,205,107,117,53,190,36,204,74,112,199,210,123,131,71,199,95,6,181,165,60,186,116,116,46,203,91,155,5,187,22,95,215,92,2,77,79,204,34,75,118,213,76,78,37,180,26,63,220,229,190,164,60,155,245,136,80,165,197,44,64,108,99,152,129,80,83,235,94,234,233,252,49,252,182,182,178,2]] @@ -104,7 +103,7 @@ contract('InitializerHbbft', async accounts => { // Deploy TxPermission contract txPermission = await TxPermission.new(); txPermission = await AdminUpgradeabilityProxy.new(txPermission.address, owner, []); - txPermission = await StakingHbbft.at(txPermission.address); + txPermission = await TxPermission.at(txPermission.address); // Deploy Certifier contract certifier = await Certifier.new(); certifier = await AdminUpgradeabilityProxy.new(certifier.address, owner, []); @@ -144,7 +143,7 @@ contract('InitializerHbbft', async accounts => { stakingEpochDuration, //_stakingEpochDuration stakingTransitionwindowLength, //_stakingTransitionTimeframeLength stakingWithdrawDisallowPeriod, //_stakingWithdrawDisallowPeriod - ] + ]; await Initializer.new( contractAddresses , @@ -155,8 +154,7 @@ contract('InitializerHbbft', async accounts => { publicKeys, initialValidatorsIpAddresses, parts, - acks, - epochReward); + acks); const validators = await validatorSetHbbft.getValidators.call(); diff --git a/test/StakingHbbft.js b/test/StakingHbbft.js index e05fbd2..802596f 100644 --- a/test/StakingHbbft.js +++ b/test/StakingHbbft.js @@ -16,6 +16,14 @@ require('chai') let currentAccounts; +// delegatecall are a problem for truffle debugger +// therefore it makes sense to use a proxy for automated testing to have the proxy testet. +// and to not use it if specific transactions needs to get debugged, +// like truffle `debug 0xabc`. +const useUpgradeProxy = !(process.env.CONTRACTS_NO_UPGRADE_PROXY == 'true'); +console.log('useUpgradeProxy:', useUpgradeProxy); + + contract('StakingHbbft', async accounts => { @@ -33,7 +41,6 @@ contract('StakingHbbft', async accounts => { currentAccounts = accounts; const minStake = new BN(web3.utils.toWei('1', 'ether')); - const maxEpochReward = new BN(100); // the maximum per-block reward distributed to the validators // one epoch in 1 day. const stakingFixedEpochDuration = new BN(86400); @@ -42,8 +49,14 @@ contract('StakingHbbft', async accounts => { const stakingTransitionTimeframeLength = new BN(3600); const stakingWithdrawDisallowPeriod = new BN(1); - //const stakingEpochStartBlock = new BN(0); - //const keyGenerationDuration = new BN(2); // we assume that there is a fixed duration in blocks, in reality it varies. + + // the reward for the first epoch. + const epochReward = new BN(web3.utils.toWei('1', 'ether')); + + // the amount the deltaPot gets filled up. + // this is 60-times more, since the deltaPot get's + // drained each step by 60 by default. + const deltaPotFillupValue = epochReward.mul(new BN('60')); beforeEach(async () => { owner = accounts[0]; @@ -53,30 +66,43 @@ contract('StakingHbbft', async accounts => { initialStakingAddresses[0].should.not.be.equal('0x0000000000000000000000000000000000000000'); initialStakingAddresses[1].should.not.be.equal('0x0000000000000000000000000000000000000000'); initialStakingAddresses[2].should.not.be.equal('0x0000000000000000000000000000000000000000'); + + + // Deploy BlockReward contract blockRewardHbbft = await BlockRewardHbbft.new(); - blockRewardHbbft = await AdminUpgradeabilityProxy.new(blockRewardHbbft.address, owner, []); - blockRewardHbbft = await BlockRewardHbbft.at(blockRewardHbbft.address); + if (useUpgradeProxy) { + blockRewardHbbft = await AdminUpgradeabilityProxy.new(blockRewardHbbft.address, owner, []); + blockRewardHbbft = await BlockRewardHbbft.at(blockRewardHbbft.address); + } // Deploy Random contract randomHbbft = await RandomHbbft.new(); - randomHbbft = await AdminUpgradeabilityProxy.new(randomHbbft.address, owner, []); - randomHbbft = await RandomHbbft.at(randomHbbft.address); + if (useUpgradeProxy) { + randomHbbft = await AdminUpgradeabilityProxy.new(randomHbbft.address, owner, []); + randomHbbft = await RandomHbbft.at(randomHbbft.address); + } // Deploy Staking contract stakingHbbft = await StakingHbbftCoins.new(); - stakingHbbft = await AdminUpgradeabilityProxy.new(stakingHbbft.address, owner, []); - stakingHbbft = await StakingHbbftCoins.at(stakingHbbft.address); + if (useUpgradeProxy) { + stakingHbbft = await AdminUpgradeabilityProxy.new(stakingHbbft.address, owner, []); + stakingHbbft = await StakingHbbftCoins.at(stakingHbbft.address); + } // Deploy ValidatorSet contract validatorSetHbbft = await ValidatorSetHbbft.new(); - validatorSetHbbft = await AdminUpgradeabilityProxy.new(validatorSetHbbft.address, owner, []); - validatorSetHbbft = await ValidatorSetHbbft.at(validatorSetHbbft.address); + if (useUpgradeProxy) { + validatorSetHbbft = await AdminUpgradeabilityProxy.new(validatorSetHbbft.address, owner, []); + validatorSetHbbft = await ValidatorSetHbbft.at(validatorSetHbbft.address); + } //without that, the Time is 0, //meaning a lot of checks that expect time to have some value deliver incorrect results. await increaseTime(1); keyGenHistory = await KeyGenHistory.new(); - keyGenHistory = await AdminUpgradeabilityProxy.new(keyGenHistory.address, owner, []); - keyGenHistory = await KeyGenHistory.at(keyGenHistory.address); + if (useUpgradeProxy) { + keyGenHistory = await AdminUpgradeabilityProxy.new(keyGenHistory.address, owner, []); + keyGenHistory = await KeyGenHistory.at(keyGenHistory.address); + } await keyGenHistory.initialize(validatorSetHbbft.address, initialValidators, [[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,181,129,31,84,186,242,5,151,59,35,196,140,106,29,40,112,142,156,132,158,47,223,253,185,227,249,190,96,5,99,239,213,127,29,136,115,71,164,202,44,6,171,131,251,147,159,54,49,1,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,177,133,61,18,58,222,74,65,5,126,253,181,113,165,43,141,56,226,132,208,218,197,119,179,128,30,162,251,23,33,73,38,120,246,223,233,11,104,60,154,241,182,147,219,81,45,134,239,69,169,198,188,152,95,254,170,108,60,166,107,254,204,195,170,234,154,134,26,91,9,139,174,178,248,60,65,196,218,46,163,218,72,1,98,12,109,186,152,148,159,121,254,34,112,51,70,121,51,167,35,240,5,134,197,125,252,3,213,84,70,176,160,36,73,140,104,92,117,184,80,26,240,106,230,241,26,79,46,241,195,20,106,12,186,49,254,168,233,25,179,96,62,104,118,153,95,53,127,160,237,246,41],[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,181,129,31,84,186,242,5,151,59,35,196,140,106,29,40,112,142,156,132,158,47,223,253,185,227,249,190,96,5,99,239,213,127,29,136,115,71,164,202,44,6,171,131,251,147,159,54,49,1,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,177,133,61,18,58,222,74,65,5,126,253,181,113,165,43,141,56,226,132,208,218,197,119,179,128,30,162,251,23,33,73,38,120,246,223,233,11,104,60,154,241,182,147,219,81,45,134,239,69,169,198,188,152,95,254,170,108,60,166,107,254,204,195,170,234,154,134,26,91,9,139,174,178,248,60,65,196,218,46,163,218,72,1,98,12,109,186,152,148,159,121,254,34,112,51,70,121,51,167,35,240,5,134,197,125,252,3,213,84,70,176,160,36,73,140,104,92,117,184,80,26,240,106,230,241,26,79,46,241,195,20,106,12,186,49,254,168,233,25,179,96,62,104,118,153,95,53,127,160,237,246,41],[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,181,129,31,84,186,242,5,151,59,35,196,140,106,29,40,112,142,156,132,158,47,223,253,185,227,249,190,96,5,99,239,213,127,29,136,115,71,164,202,44,6,171,131,251,147,159,54,49,1,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,177,133,61,18,58,222,74,65,5,126,253,181,113,165,43,141,56,226,132,208,218,197,119,179,128,30,162,251,23,33,73,38,120,246,223,233,11,104,60,154,241,182,147,219,81,45,134,239,69,169,198,188,152,95,254,170,108,60,166,107,254,204,195,170,234,154,134,26,91,9,139,174,178,248,60,65,196,218,46,163,218,72,1,98,12,109,186,152,148,159,121,254,34,112,51,70,121,51,167,35,240,5,134,197,125,252,3,213,84,70,176,160,36,73,140,104,92,117,184,80,26,240,106,230,241,26,79,46,241,195,20,106,12,186,49,254,168,233,25,179,96,62,104,118,153,95,53,127,160,237,246,41]], [[[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,239,1,112,13,13,251,103,186,212,78,44,47,250,221,84,118,88,7,64,206,186,11,2,8,204,140,106,179,52,251,237,19,53,74,187,217,134,94,66,68,89,42,85,207,155,220,101,223,51,199,37,38,203,132,13,77,78,114,53,219,114,93,21,25,164,12,43,252,160,16,23,111,79,230,121,95,223,174,211,172,231,0,52,25,49,152,79,128,39,117,216,85,201,237,242,151,219,149,214,77,233,145,47,10,184,175,162,174,237,177,131,45,126,231,32,147,227,170,125,133,36,123,164,232,129,135,196,136,186,45,73,226,179,169,147,42,41,140,202,191,12,73,146,2]],[[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,239,1,112,13,13,251,103,186,212,78,44,47,250,221,84,118,88,7,64,206,186,11,2,8,204,140,106,179,52,251,237,19,53,74,187,217,134,94,66,68,89,42,85,207,155,220,101,223,51,199,37,38,203,132,13,77,78,114,53,219,114,93,21,25,164,12,43,252,160,16,23,111,79,230,121,95,223,174,211,172,231,0,52,25,49,152,79,128,39,117,216,85,201,237,242,151,219,149,214,77,233,145,47,10,184,175,162,174,237,177,131,45,126,231,32,147,227,170,125,133,36,123,164,232,129,135,196,136,186,45,73,226,179,169,147,42,41,140,202,191,12,73,146,2]],[[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,239,1,112,13,13,251,103,186,212,78,44,47,250,221,84,118,88,7,64,206,186,11,2,8,204,140,106,179,52,251,237,19,53,74,187,217,134,94,66,68,89,42,85,207,155,220,101,223,51,199,37,38,203,132,13,77,78,114,53,219,114,93,21,25,164,12,43,252,160,16,23,111,79,230,121,95,223,174,211,172,231,0,52,25,49,152,79,128,39,117,216,85,201,237,242,151,219,149,214,77,233,145,47,10,184,175,162,174,237,177,131,45,126,231,32,147,227,170,125,133,36,123,164,232,129,135,196,136,186,45,73,226,179,169,147,42,41,140,202,191,12,73,146,2]]] @@ -103,6 +129,9 @@ contract('StakingHbbft', async accounts => { // The IP addresses are irrelevant for these unit test, just initialize them to 0. initialValidatorsIpAddresses = ['0x00000000000000000000000000000000', '0x00000000000000000000000000000000', '0x00000000000000000000000000000000']; + + //await blockRewardHbbft.addToDeltaPot({value: deltaPotFillupValue}).should.be.fulfilled; + }); describe('addPool()', async () => { @@ -325,8 +354,7 @@ contract('StakingHbbft', async accounts => { // Initialize BlockRewardHbbft await blockRewardHbbft.initialize( - validatorSetHbbft.address, - maxEpochReward + validatorSetHbbft.address ).should.be.fulfilled; // Initialize StakingHbbft @@ -348,6 +376,7 @@ contract('StakingHbbft', async accounts => { //(await validatorSetHbbft.getCurrentBlockNumber.call()).should.be.bignumber.equal(new BN(1)); //(await stakingHbbft.getCurrentBlockNumber.call()).should.be.bignumber.equal(new BN(1)); + // Validators place stakes during the epoch #0 const candidateMinStake = await stakingHbbft.candidateMinStake.call(); for (let i = 0; i < initialStakingAddresses.length; i++) { @@ -471,7 +500,12 @@ contract('StakingHbbft', async accounts => { const miningAddress = initialValidators[0]; const stakingAddress = initialStakingAddresses[0]; + const epochPoolReward = new BN(web3.utils.toWei('1', 'ether')); + const deltaPotFillupValue = epochPoolReward.mul(new BN('60')); + //blockRewardHbbft.add + await blockRewardHbbft.addToDeltaPot({value: deltaPotFillupValue}).should.be.fulfilled; + // the beforeeach alsready runs 1 epoch, so we expect to be in epoch 1 here. (await stakingHbbft.stakingEpoch.call()).should.be.bignumber.equal(new BN(1)); @@ -496,9 +530,15 @@ contract('StakingHbbft', async accounts => { // the pending validator set should be updated (await validatorSetHbbft.getPendingValidators.call()).length.should.be.equal(3); + //!!! here it failes for some reason //Staking epoch #1: Epoch end block await timeTravelToEndEpoch(); + // we restock this one epoch reward that got payed out. + // todo: think about: Maybe this restocking should happen in the timeTravelToEndEpoch function to have + // constant epoch payouts. + await blockRewardHbbft.addToDeltaPot({value: epochPoolReward}).should.be.fulfilled; + // now epoch #2 has started. (await stakingHbbft.stakingEpoch.call()).should.be.bignumber.equal(new BN(2)); @@ -616,7 +656,13 @@ contract('StakingHbbft', async accounts => { const stakingAddress = initialStakingAddresses[0]; const epochPoolReward = new BN(web3.utils.toWei('1', 'ether')); - (await web3.eth.getBalance(blockRewardHbbft.address)).should.be.equal('0'); + + const deltaPotFillupValue = epochPoolReward.mul(new BN('60')); + //blockRewardHbbft.add + await blockRewardHbbft.addToDeltaPot({value: deltaPotFillupValue}).should.be.fulfilled; + + const currentblockRewardHbbftBalance = new BN(await web3.eth.getBalance(blockRewardHbbft.address)); + currentblockRewardHbbftBalance.should.be.bignumber.equal(deltaPotFillupValue); for (let i = 0; i < epochsPoolRewarded.length; i++) { const stakingEpoch = epochsPoolRewarded[i]; @@ -630,7 +676,8 @@ contract('StakingHbbft', async accounts => { // initial validator got reward for epochsPoolRewarded (await blockRewardHbbft.epochsPoolGotRewardFor.call(miningAddress)).length.should.be.equal(epochsPoolRewarded.length); - (new BN(await web3.eth.getBalance(blockRewardHbbft.address))).should.be.bignumber.equal(epochPoolReward.mul(new BN(epochsPoolRewarded.length))); + + (new BN(await web3.eth.getBalance(blockRewardHbbft.address))).should.be.bignumber.equal(deltaPotFillupValue.add(epochPoolReward.mul(new BN(epochsPoolRewarded.length)))); for (let i = 0; i < epochsStakeMovement.length; i++) { const stakingEpoch = epochsStakeMovement[i]; @@ -703,16 +750,21 @@ contract('StakingHbbft', async accounts => { result.logs.length.should.be.equal(0); } } - (new BN(await web3.eth.getBalance(blockRewardHbbft.address))).should.be.bignumber.equal(new BN(0)); + (new BN(await web3.eth.getBalance(blockRewardHbbft.address))).should.be.bignumber.equal(deltaPotFillupValue); } it('reward tries to be withdrawn before first stake', async () => { const { miningAddress, stakingAddress, - epochPoolReward } = await _delegatorNeverStakedBefore(); + //const deltaPotFillupValue = new BN(web3.eth.toWei(60)); + //await blockRewardHbbft.addToDeltaPot({value: deltaPotFillupValue}); + + // a fake epoch reward. + const epochPoolReward = '1000'; + // Emulate snapshotting and rewards for the pool on the epoch #9 let stakingEpoch = 9; await blockRewardHbbft.snapshotPoolStakeAmounts(stakingHbbft.address, stakingEpoch, miningAddress).should.be.fulfilled; @@ -758,6 +810,8 @@ contract('StakingHbbft', async accounts => { result = await stakingHbbft.claimReward([], stakingAddress, {from: stakingAddress}).should.be.fulfilled; + //console.log('rewards for ', stakingAddress); + //console.log(result); result.logs.length.should.be.equal(5); result.logs[0].args.stakingEpoch.should.be.bignumber.equal(new BN(1)); result.logs[1].args.stakingEpoch.should.be.bignumber.equal(new BN(2)); @@ -778,10 +832,11 @@ contract('StakingHbbft', async accounts => { it('delegator stakes and withdraws at the same epoch', async () => { const { miningAddress, - stakingAddress, - epochPoolReward + stakingAddress } = await _delegatorNeverStakedBefore(); + const epochPoolReward = '1000'; + // Emulate snapshotting and rewards for the pool on the epoch #9 let stakingEpoch = 9; await blockRewardHbbft.snapshotPoolStakeAmounts(stakingHbbft.address, stakingEpoch, miningAddress).should.be.fulfilled; @@ -1099,6 +1154,8 @@ contract('StakingHbbft', async accounts => { const stakingEpoch = 2600; + await blockRewardHbbft.addToDeltaPot({value: deltaPotFillupValue}); + for (let i = 0; i < initialValidators.length; i++) { await blockRewardHbbft.snapshotPoolStakeAmounts(stakingHbbft.address, stakingEpoch, initialValidators[i]); } @@ -1136,6 +1193,11 @@ contract('StakingHbbft', async accounts => { epochPoolNativeReward.should.be.bignumber.above(new BN(0)); distributedCoinsAmount = distributedCoinsAmount.add(epochPoolNativeReward); } + + // const blockRewardHbbft.maintenanceFundAddress.call(); + // console.log('DAO Coin amount'); + // distributedCoinsAmount + let blockRewardCoinsBalanceAfter = new BN(await web3.eth.getBalance(blockRewardHbbft.address)); blockRewardCoinsBalanceAfter.should.be.bignumber.equal(blockRewardCoinsBalanceBefore.add(distributedCoinsAmount)); @@ -1175,6 +1237,8 @@ contract('StakingHbbft', async accounts => { const maxStakingEpoch = 20; maxStakingEpoch.should.be.above(2); + await blockRewardHbbft.addToDeltaPot({value: deltaPotFillupValue}); + // Loop of staking epochs for (let stakingEpoch = 1; stakingEpoch <= maxStakingEpoch; stakingEpoch++) { // Finalize change i.e. finalize pending validators, increase epoch and set stakingEpochStartBlock @@ -1312,6 +1376,8 @@ contract('StakingHbbft', async accounts => { it('gas consumption for 52 staking epochs is OK 1', async () => { const maxStakingEpoch = 52; + await blockRewardHbbft.addToDeltaPot({value: deltaPotFillupValue}); + // Loop of staking epochs for (let stakingEpoch = 1; stakingEpoch <= maxStakingEpoch; stakingEpoch++) { if ( stakingEpoch == 1) { @@ -1424,14 +1490,13 @@ contract('StakingHbbft', async accounts => { const maxStakingEpochs = 52; const gapSize = 10; + await blockRewardHbbft.addToDeltaPot({value: deltaPotFillupValue}); + // Loop of staking epochs for (let s = 0; s < maxStakingEpochs; s++) { if ( s == 0) { await stakingHbbft.setStakingEpoch(1).should.be.fulfilled; - const startBlock = new BN(120954 + 2 + 1); - await stakingHbbft.setValidatorSetAddress(owner).should.be.fulfilled; - //await stakingHbbft.setStakingEpochStartBlock(startBlock).should.be.fulfilled; await stakingHbbft.setValidatorSetAddress(validatorSetHbbft.address).should.be.fulfilled; } @@ -2159,7 +2224,7 @@ contract('StakingHbbft', async accounts => { await stakingHbbft.stake(initialStakingAddresses[1], {from: initialStakingAddresses[1], value: stakeAmount}).should.be.fulfilled; await stakingHbbft.stake(initialStakingAddresses[1], {from: delegatorAddress, value: stakeAmount}).should.be.fulfilled; - await validatorSetHbbft.setBannedUntil(initialValidators[1], 100).should.be.fulfilled; + await validatorSetHbbft.setBannedUntil(initialValidators[1], '0xffffffffffffffff').should.be.fulfilled; await stakingHbbft.withdraw(initialStakingAddresses[1], stakeAmount, {from: initialStakingAddresses[1]}).should.be.rejectedWith(ERROR_MSG); await stakingHbbft.withdraw(initialStakingAddresses[1], stakeAmount, {from: delegatorAddress}).should.be.rejectedWith(ERROR_MSG); await validatorSetHbbft.setBannedUntil(initialValidators[1], 0).should.be.fulfilled; @@ -2205,7 +2270,7 @@ contract('StakingHbbft', async accounts => { await stakingHbbft.stake(initialStakingAddresses[1], {from: delegatorAddress, value: stakeAmount}).should.be.fulfilled; // Finalize a new validator set and change staking epoch - await blockRewardHbbft.initialize(validatorSetHbbft.address, maxEpochReward).should.be.fulfilled; + await blockRewardHbbft.initialize(validatorSetHbbft.address).should.be.fulfilled; await validatorSetHbbft.setStakingContract(stakingHbbft.address).should.be.fulfilled; // Set BlockRewardContract await validatorSetHbbft.setBlockRewardContract(accounts[7]).should.be.fulfilled; diff --git a/test/ValidatorSetHbbft.js b/test/ValidatorSetHbbft.js index 0891b87..ee64b7b 100644 --- a/test/ValidatorSetHbbft.js +++ b/test/ValidatorSetHbbft.js @@ -22,6 +22,13 @@ require('chai') .use(require('chai-bn')(BN)) .should(); +// delegatecall are a problem for truffle debugger +// therefore it makes sense to use a proxy for automated testing to have the proxy testet. +// and to not use it if specific transactions needs to get debugged, +// like truffle `debug 0xabc`. +const useUpgradeProxy = !(process.env.CONTRACTS_NO_UPGRADE_PROXY == 'true'); +console.log('useUpgradeProxy:', useUpgradeProxy); + contract('ValidatorSetHbbft', async accounts => { let owner; let blockRewardHbbft; @@ -32,18 +39,29 @@ contract('ValidatorSetHbbft', async accounts => { beforeEach(async () => { owner = accounts[0]; + + + // Deploy BlockReward contract blockRewardHbbft = await BlockRewardHbbft.new(); - blockRewardHbbft = await AdminUpgradeabilityProxy.new(blockRewardHbbft.address, owner, []); - blockRewardHbbft = await BlockRewardHbbft.at(blockRewardHbbft.address); + if (useUpgradeProxy) { + blockRewardHbbft = await AdminUpgradeabilityProxy.new(blockRewardHbbft.address, owner, []); + blockRewardHbbft = await BlockRewardHbbft.at(blockRewardHbbft.address); + } + // Deploy Staking contract stakingHbbft = await StakingHbbft.new(); - stakingHbbft = await AdminUpgradeabilityProxy.new(stakingHbbft.address, owner, []); - stakingHbbft = await StakingHbbft.at(stakingHbbft.address); + if (useUpgradeProxy) { + stakingHbbft = await AdminUpgradeabilityProxy.new(stakingHbbft.address, owner, []); + stakingHbbft = await StakingHbbft.at(stakingHbbft.address); + } + // Deploy ValidatorSet contract validatorSetHbbft = await ValidatorSetHbbft.new(); - validatorSetHbbft = await AdminUpgradeabilityProxy.new(validatorSetHbbft.address, owner, []); - validatorSetHbbft = await ValidatorSetHbbft.at(validatorSetHbbft.address); + if (useUpgradeProxy) { + validatorSetHbbft = await AdminUpgradeabilityProxy.new(validatorSetHbbft.address, owner, []); + validatorSetHbbft = await ValidatorSetHbbft.at(validatorSetHbbft.address); + } await increaseTime(1); @@ -104,17 +122,21 @@ contract('ValidatorSetHbbft', async accounts => { await validatorSetHbbft.isValidator.call('0x0000000000000000000000000000000000000000') ); }); - it('should fail if initialization is not done on the genesis block and sender is not admin', async () => { - await validatorSetHbbft.initialize( - blockRewardHbbft.address, // _blockRewardContract - '0x3000000000000000000000000000000000000001', // _randomContract - stakingHbbft.address, // _stakingContract - '0x8000000000000000000000000000000000000001', //_keyGenHistoryContract - initialValidators, // _initialMiningAddresses - initialStakingAddresses, // _initialStakingAddresses - {from: accounts[1]} - ).should.be.rejectedWith("Initialization only on genesis block or by admin"); - }); + + it('should fail if initialization is not done on the genesis block and sender is not admin', async () => { + if (useUpgradeProxy) { //this test only works if using the upgrade proxy. + await validatorSetHbbft.initialize( + blockRewardHbbft.address, // _blockRewardContract + '0x3000000000000000000000000000000000000001', // _randomContract + stakingHbbft.address, // _stakingContract + '0x8000000000000000000000000000000000000001', //_keyGenHistoryContract + initialValidators, // _initialMiningAddresses + initialStakingAddresses, // _initialStakingAddresses + {from: accounts[1]} + ).should.be.rejectedWith("Initialization only on genesis block or by admin"); + } + }); + it('should initialize successfully if not done on genesis block but sender is admin', async () => { await validatorSetHbbft.initialize( blockRewardHbbft.address, // _blockRewardContract @@ -359,7 +381,7 @@ contract('ValidatorSetHbbft', async accounts => { (await validatorSetHbbft.getPendingValidators.call()).should.be.deep.equal([initialValidators[0]]); }); it('should choose validators randomly', async () => { - const stakingAddresses = accounts.slice(7, 29 + 1); // accounts[7...29] + const stakingAddresses = accounts.slice(7, 29 + 3); // accounts[7...31] let miningAddresses = []; for (let i = 0; i < stakingAddresses.length; i++) {