diff --git a/contracts/upgradeable_contracts/BaseBridgeValidators.sol b/contracts/upgradeable_contracts/BaseBridgeValidators.sol index 508a75eca..70d75ad68 100644 --- a/contracts/upgradeable_contracts/BaseBridgeValidators.sol +++ b/contracts/upgradeable_contracts/BaseBridgeValidators.sol @@ -8,7 +8,7 @@ contract BaseBridgeValidators is InitializableBridge, Ownable { using SafeMath for uint256; address public constant F_ADDR = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; - uint256 internal constant MAX_VALIDATORS = 100; + uint256 internal constant MAX_VALIDATORS = 50; bytes32 internal constant REQUIRED_SIGNATURES = 0xd18ea17c351d6834a0e568067fb71804d2a588d5e26d60f792b1c724b1bd53b1; // keccak256(abi.encodePacked("requiredSignatures")) bytes32 internal constant VALIDATOR_COUNT = 0x8656d603d9f985c3483946a92789d52202f49736384ba131cb92f62c4c1aa082; // keccak256(abi.encodePacked("validatorCount")) @@ -96,6 +96,7 @@ contract BaseBridgeValidators is InitializableBridge, Ownable { } function setValidatorCount(uint256 _validatorCount) internal { + require(_validatorCount <= MAX_VALIDATORS); uintStorage[VALIDATOR_COUNT] = _validatorCount; } diff --git a/contracts/upgradeable_contracts/BridgeValidators.sol b/contracts/upgradeable_contracts/BridgeValidators.sol index 887baf835..8db5a1266 100644 --- a/contracts/upgradeable_contracts/BridgeValidators.sol +++ b/contracts/upgradeable_contracts/BridgeValidators.sol @@ -12,7 +12,6 @@ contract BridgeValidators is BaseBridgeValidators { setOwner(_owner); require(_requiredSignatures != 0); require(_initialValidators.length >= _requiredSignatures); - require(_initialValidators.length <= MAX_VALIDATORS); for (uint256 i = 0; i < _initialValidators.length; i++) { require(_initialValidators[i] != address(0) && _initialValidators[i] != F_ADDR); diff --git a/contracts/upgradeable_contracts/RewardableValidators.sol b/contracts/upgradeable_contracts/RewardableValidators.sol index f1a11545f..c71ebf4c5 100644 --- a/contracts/upgradeable_contracts/RewardableValidators.sol +++ b/contracts/upgradeable_contracts/RewardableValidators.sol @@ -14,7 +14,6 @@ contract RewardableValidators is BaseBridgeValidators { setOwner(_owner); require(_requiredSignatures != 0); require(_initialValidators.length >= _requiredSignatures); - require(_initialValidators.length <= MAX_VALIDATORS); require(_initialValidators.length == _initialRewards.length); for (uint256 i = 0; i < _initialValidators.length; i++) { diff --git a/test/erc_to_erc/home_bridge.test.js b/test/erc_to_erc/home_bridge.test.js index ea7bd01a2..2ae024f8d 100644 --- a/test/erc_to_erc/home_bridge.test.js +++ b/test/erc_to_erc/home_bridge.test.js @@ -11,7 +11,7 @@ const OldBlockReward = artifacts.require('OldBlockReward') const { expect } = require('chai') const { ERROR_MSG, ZERO_ADDRESS, toBN } = require('../setup') -const { createMessage, sign, getEvents, ether, expectEventInLogs } = require('../helpers/helpers') +const { createMessage, sign, getEvents, ether, expectEventInLogs, createAccounts } = require('../helpers/helpers') const minPerTx = ether('0.01') const requireBlockConfirmations = 8 @@ -22,6 +22,8 @@ const halfEther = ether('0.5') const foreignDailyLimit = oneEther const foreignMaxPerTx = halfEther const ZERO = toBN(0) +const MAX_GAS = 8000000 +const MAX_VALIDATORS = 50 const decimalShiftZero = 0 const markedAsProcessed = toBN(2) .pow(toBN(255)) @@ -1711,6 +1713,35 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => { balanceRewardAddress4.should.be.bignumber.equal(feePerValidator) balanceRewardAddress5.should.be.bignumber.equal(feePerValidator) }) + it('should distribute fee to max allowed number of validator', async () => { + // Given + const recipient = accounts[9] + const owner = accounts[0] + const validators = createAccounts(web3, MAX_VALIDATORS) + validators[0] = accounts[2] + const rewards = createAccounts(web3, MAX_VALIDATORS) + 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 valueCalc = 0.5 * (1 - fee) + const value = ether(valueCalc.toString()) + const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80' + const message = createMessage(recipient, value, transactionHash, homeBridge.address) + const signature = await sign(validators[0], message) + + const blockRewardBalanceBefore = await token.balanceOf(blockRewardContract.address) + blockRewardBalanceBefore.should.be.bignumber.equal('0') + + // When + const { receipt } = await homeBridge.submitSignature(signature, message, { + from: validators[0] + }).should.be.fulfilled + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + }) }) describe('#rewardable_executeAffirmation', () => { let fee @@ -1922,6 +1953,32 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => { balanceRewardAddress4.should.be.bignumber.equal(feePerValidator) balanceRewardAddress5.should.be.bignumber.equal(feePerValidator) }) + + it('should distribute fee to max allowed number of validators', async () => { + // Given + const recipient = accounts[0] + const owner = accounts[0] + const validators = createAccounts(web3, MAX_VALIDATORS) + validators[0] = accounts[2] + const rewards = createAccounts(web3, MAX_VALIDATORS) + const requiredSignatures = 1 + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner, { + from: 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 transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80' + + // When + const { receipt } = await homeBridge.executeAffirmation(recipient, initialValue, transactionHash, { + from: validators[0] + }).should.be.fulfilled + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + }) }) describe('#decimals Shift', async () => { const decimalShiftTwo = 2 diff --git a/test/erc_to_native/home_bridge.test.js b/test/erc_to_native/home_bridge.test.js index 2e2e3de2e..8b5f75d5a 100644 --- a/test/erc_to_native/home_bridge.test.js +++ b/test/erc_to_native/home_bridge.test.js @@ -10,7 +10,7 @@ const FeeManagerMock = artifacts.require('FeeManagerMock') const { expect } = require('chai') const { ERROR_MSG, ZERO_ADDRESS, toBN } = require('../setup') -const { createMessage, sign, ether, expectEventInLogs } = require('../helpers/helpers') +const { createMessage, sign, ether, expectEventInLogs, createAccounts } = require('../helpers/helpers') const minPerTx = ether('0.01') const requireBlockConfirmations = 8 @@ -21,6 +21,8 @@ const halfEther = ether('0.5') const foreignDailyLimit = oneEther const foreignMaxPerTx = halfEther const ZERO = toBN(0) +const MAX_GAS = 8000000 +const MAX_VALIDATORS = 50 const decimalShiftZero = 0 contract('HomeBridge_ERC20_to_Native', async accounts => { @@ -2029,6 +2031,53 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { updatedBalanceRewardAddress4.should.be.bignumber.equal(initialBalanceRewardAddress4.add(feePerValidator)) updatedBalanceRewardAddress5.should.be.bignumber.equal(initialBalanceRewardAddress5.add(feePerValidator)) }) + + it('should distribute fee to max allowed number of validators', async () => { + // Initialize + const owner = accounts[0] + const validators = createAccounts(web3, MAX_VALIDATORS) + validators[0] = accounts[2] + const rewards = createAccounts(web3, MAX_VALIDATORS) + const requiredSignatures = 1 + const rewardableValidators = await RewardableValidators.new() + const homeBridge = await HomeBridge.new() + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner, { + from: owner + }).should.be.fulfilled + await homeBridge.initialize( + rewardableValidators.address, + [oneEther, halfEther, minPerTx], + gasPrice, + requireBlockConfirmations, + blockRewardContract.address, + [foreignDailyLimit, foreignMaxPerTx], + owner, + decimalShiftZero + ).should.be.fulfilled + await blockRewardContract.sendTransaction({ + from: owner, + value: oneEther + }).should.be.fulfilled + + // Given + const value = halfEther + // 0.1% fee + const fee = 0.001 + const feeInWei = ether(fee.toString()) + const feeManager = await FeeManagerErcToNative.new() + await homeBridge.setFeeManagerContract(feeManager.address, { from: owner }).should.be.fulfilled + await homeBridge.setForeignFee(feeInWei, { from: owner }).should.be.fulfilled + + const recipient = '0xf4BEF13F9f4f2B203FAF0C3cBbaAbe1afE056955' + + const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415' + + // When + const { receipt } = await homeBridge.executeAffirmation(recipient, value, transactionHash, { + from: validators[0] + }) + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + }) }) describe('#feeManager_fallback', async () => { let homeBridge @@ -2396,6 +2445,56 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { updatedBalanceRewardAddress4.should.be.bignumber.equal(initialBalanceRewardAddress4.add(feePerValidator)) updatedBalanceRewardAddress5.should.be.bignumber.equal(initialBalanceRewardAddress5.add(feePerValidator)) }) + it('should distribute fee to max allowed number of validators', async () => { + // Initialize + const owner = accounts[0] + const validators = createAccounts(web3, MAX_VALIDATORS) + validators[0] = accounts[2] + const rewards = createAccounts(web3, MAX_VALIDATORS) + const requiredSignatures = 1 + const rewardableValidators = await RewardableValidators.new() + const homeBridge = await HomeBridge.new() + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner, { + from: owner + }).should.be.fulfilled + await homeBridge.initialize( + rewardableValidators.address, + [oneEther, halfEther, minPerTx], + gasPrice, + requireBlockConfirmations, + blockRewardContract.address, + [foreignDailyLimit, foreignMaxPerTx], + owner, + decimalShiftZero + ).should.be.fulfilled + await blockRewardContract.addMintedTotallyByBridge(oneEther, homeBridge.address) + + // Given + // 0.1% fee + const fee = 0.001 + const feeInWei = ether(fee.toString()) + const feeManager = await FeeManagerErcToNative.new() + await homeBridge.setFeeManagerContract(feeManager.address, { from: owner }).should.be.fulfilled + await homeBridge.setHomeFee(feeInWei, { from: owner }).should.be.fulfilled + + const recipient = accounts[0] + const initialValue = halfEther + const valueCalc = 0.5 * (1 - fee) + const value = ether(valueCalc.toString()) + const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415' + + // When + await homeBridge.sendTransaction({ from: recipient, value: initialValue }).should.be.fulfilled + + const message = createMessage(recipient, value, transactionHash, homeBridge.address) + + const signature = await sign(validators[0], message) + + const { receipt } = await homeBridge.submitSignature(signature, message, { + from: validators[0] + }).should.be.fulfilled + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + }) }) describe('#FeeManager_random', async () => { it('should return value between 0 and 3', async () => { @@ -2718,6 +2817,53 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { const feeAmountBlockReward = await blockRewardContract.feeAmount() expect(toBN(feeAmountBlockReward)).to.be.bignumber.equal(feeAmount) }) + it('should distribute fee to max allowed number of validators', async () => { + // Initialize + const owner = accounts[0] + const validators = createAccounts(web3, MAX_VALIDATORS) + validators[0] = accounts[2] + const rewards = createAccounts(web3, MAX_VALIDATORS) + const requiredSignatures = 1 + const rewardableValidators = await RewardableValidators.new() + const homeBridge = await HomeBridge.new() + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner, { + from: owner + }).should.be.fulfilled + await blockRewardContract.setValidatorsRewards(rewards) + await homeBridge.initialize( + rewardableValidators.address, + [oneEther, halfEther, minPerTx], + gasPrice, + requireBlockConfirmations, + blockRewardContract.address, + [foreignDailyLimit, foreignMaxPerTx], + owner, + decimalShiftZero + ).should.be.fulfilled + await blockRewardContract.sendTransaction({ + from: accounts[0], + value: oneEther + }).should.be.fulfilled + + // Given + const value = halfEther + // 0.1% fee + const fee = 0.001 + const feeInWei = ether(fee.toString()) + const feeManager = await FeeManagerErcToNativePOSDAO.new() + await homeBridge.setFeeManagerContract(feeManager.address, { from: owner }).should.be.fulfilled + await homeBridge.setForeignFee(feeInWei, { from: owner }).should.be.fulfilled + + const recipient = '0xf4BEF13F9f4f2B203FAF0C3cBbaAbe1afE056955' + + const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415' + + // When + const { receipt } = await homeBridge.executeAffirmation(recipient, value, transactionHash, { + from: validators[0] + }).should.be.fulfilled + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + }) }) describe('#feeManager_fallback_POSDAO', async () => { let homeBridge @@ -3116,6 +3262,57 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { const feeAmountBlockReward = await blockRewardContract.feeAmount() feeAmountBlockReward.should.be.bignumber.equal(feeAmount) }) + it('should distribute fee to max allowed number of validators', async () => { + // Initialize + const owner = accounts[0] + const validators = createAccounts(web3, MAX_VALIDATORS) + validators[0] = accounts[2] + const rewards = createAccounts(web3, MAX_VALIDATORS) + const requiredSignatures = 1 + const rewardableValidators = await RewardableValidators.new() + const homeBridge = await HomeBridge.new() + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner, { + from: owner + }).should.be.fulfilled + await blockRewardContract.setValidatorsRewards(rewards) + await homeBridge.initialize( + rewardableValidators.address, + [oneEther, halfEther, minPerTx], + gasPrice, + requireBlockConfirmations, + blockRewardContract.address, + [foreignDailyLimit, foreignMaxPerTx], + owner, + decimalShiftZero + ).should.be.fulfilled + await blockRewardContract.addMintedTotallyByBridge(oneEther, homeBridge.address) + + // Given + // 0.1% fee + const fee = 0.001 + const feeInWei = ether(fee.toString()) + const feeManager = await FeeManagerErcToNativePOSDAO.new() + await homeBridge.setFeeManagerContract(feeManager.address, { from: owner }).should.be.fulfilled + await homeBridge.setHomeFee(feeInWei, { from: owner }).should.be.fulfilled + + const recipient = accounts[0] + const initialValue = halfEther + const valueCalc = 0.5 * (1 - fee) + const value = ether(valueCalc.toString()) + const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415' + + // When + await homeBridge.sendTransaction({ from: recipient, value: initialValue }).should.be.fulfilled + + const message = createMessage(recipient, value, transactionHash, homeBridge.address) + + const signature = await sign(validators[0], message) + + const { receipt } = await homeBridge.submitSignature(signature, message, { + from: validators[0] + }).should.be.fulfilled + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + }) }) describe('#decimals Shift', async () => { const decimalShiftTwo = 2 diff --git a/test/native_to_erc/foreign_bridge_test.js b/test/native_to_erc/foreign_bridge_test.js index 5a9532074..beb7128d8 100644 --- a/test/native_to_erc/foreign_bridge_test.js +++ b/test/native_to_erc/foreign_bridge_test.js @@ -10,7 +10,15 @@ const NoReturnTransferTokenMock = artifacts.require('NoReturnTransferTokenMock.s const { expect } = require('chai') const { ERROR_MSG, ZERO_ADDRESS, toBN } = require('../setup') -const { createMessage, sign, signatureToVRS, getEvents, ether, expectEventInLogs } = require('../helpers/helpers') +const { + createMessage, + sign, + signatureToVRS, + getEvents, + ether, + expectEventInLogs, + createAccounts +} = require('../helpers/helpers') const oneEther = ether('1') const halfEther = ether('0.5') @@ -20,6 +28,8 @@ const gasPrice = web3.utils.toWei('1', 'gwei') const homeDailyLimit = oneEther const homeMaxPerTx = halfEther const ZERO = toBN(0) +const MAX_GAS = 8000000 +const MAX_VALIDATORS = 50 const decimalShiftZero = 0 contract('ForeignBridge', async accounts => { @@ -1371,6 +1381,43 @@ contract('ForeignBridge', async accounts => { updatedBalanceRewardAddress4.should.be.bignumber.equal(initialBalanceRewardAddress4.add(feePerValidator)) updatedBalanceRewardAddress5.should.be.bignumber.equal(initialBalanceRewardAddress5.add(feePerValidator)) }) + it('should distribute fee to max allowed number of validators', async () => { + // Given + const fee = 0.001 + const feeInWei = ether(fee.toString()) + const value = halfEther + + const validators = createAccounts(web3, MAX_VALIDATORS) + validators[0] = accounts[2] + const rewards = createAccounts(web3, MAX_VALIDATORS) + const requiredSignatures = 1 + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner).should.be.fulfilled + await foreignBridge.rewardableInitialize( + rewardableValidators.address, + token.address, + [oneEther, halfEther, minPerTx], + gasPrice, + requireBlockConfirmations, + [homeDailyLimit, homeMaxPerTx], + owner, + feeManager.address, + feeInWei, + decimalShiftZero, + otherSideBridgeAddress + ).should.be.fulfilled + await token.transferOwnership(foreignBridge.address) + + const recipientAccount = accounts[0] + + const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80' + const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address) + const signature = await sign(validators[0], message) + const vrs = signatureToVRS(signature) + + // When + const { receipt } = await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + }) }) describe('#decimalShift', async () => { const decimalShiftTwo = 2 diff --git a/test/native_to_erc/home_bridge_test.js b/test/native_to_erc/home_bridge_test.js index a337d40d5..38ae1f79d 100644 --- a/test/native_to_erc/home_bridge_test.js +++ b/test/native_to_erc/home_bridge_test.js @@ -10,7 +10,7 @@ const NoReturnTransferTokenMock = artifacts.require('NoReturnTransferTokenMock.s const { expect } = require('chai') const { ERROR_MSG, ZERO_ADDRESS, toBN } = require('../setup') -const { createMessage, sign, ether, expectEventInLogs } = require('../helpers/helpers') +const { createMessage, sign, ether, expectEventInLogs, createAccounts } = require('../helpers/helpers') const minPerTx = ether('0.01') const requireBlockConfirmations = 8 @@ -21,6 +21,8 @@ const halfEther = ether('0.5') const foreignDailyLimit = oneEther const foreignMaxPerTx = halfEther const ZERO = toBN(0) +const MAX_GAS = 8000000 +const MAX_VALIDATORS = 50 const decimalShiftZero = 0 contract('HomeBridge', async accounts => { @@ -1749,6 +1751,52 @@ contract('HomeBridge', async accounts => { updatedBalanceRewardAddress4.should.be.bignumber.equal(initialBalanceRewardAddress4.add(feePerValidator)) updatedBalanceRewardAddress5.should.be.bignumber.equal(initialBalanceRewardAddress5.add(feePerValidator)) }) + it('should distribute fee to max allowed number of validators', async () => { + // Given + const owner = accounts[0] + const validators = createAccounts(web3, MAX_VALIDATORS) + validators[0] = accounts[2] + const rewards = createAccounts(web3, MAX_VALIDATORS) + const requiredSignatures = 1 + + const value = halfEther + // 0.1% fee + const fee = 0.001 + const feeInWei = ether(fee.toString()) + const notUsedFee = ZERO + + const rewardableValidators = await RewardableValidators.new() + const homeBridge = await HomeBridge.new() + const feeManager = await FeeManagerNativeToErc.new() + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner, { + from: owner + }).should.be.fulfilled + await homeBridge.rewardableInitialize( + rewardableValidators.address, + [oneEther, halfEther, minPerTx], + gasPrice, + requireBlockConfirmations, + [foreignDailyLimit, foreignMaxPerTx], + owner, + feeManager.address, + [notUsedFee, feeInWei], + decimalShiftZero + ).should.be.fulfilled + await homeBridge.sendTransaction({ + from: accounts[0], + value: halfEther + }).should.be.fulfilled + + const recipient = '0xf4BEF13F9f4f2B203FAF0C3cBbaAbe1afE056955' + + const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415' + + // When + const { receipt } = await homeBridge.executeAffirmation(recipient, value, transactionHash, { + from: validators[0] + }).should.be.fulfilled + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + }) }) describe('#feeManager_BothDirections_fallback', () => { @@ -2084,6 +2132,56 @@ contract('HomeBridge', async accounts => { updatedBalanceRewardAddress4.should.be.bignumber.equal(initialBalanceRewardAddress4.add(feePerValidator)) updatedBalanceRewardAddress5.should.be.bignumber.equal(initialBalanceRewardAddress5.add(feePerValidator)) }) + it('should distribute fee to max allowed number of validators', async () => { + // Initialize + const user = accounts[0] + const owner = accounts[9] + const validators = createAccounts(web3, MAX_VALIDATORS) + validators[0] = accounts[2] + const rewards = createAccounts(web3, MAX_VALIDATORS) + const requiredSignatures = 1 + const rewardableValidators = await RewardableValidators.new() + const homeBridge = await HomeBridge.new() + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner, { + from: owner + }).should.be.fulfilled + const feeManager = await FeeManagerNativeToErcBothDirections.new() + + // Given + // 0.1% fee + const fee = 0.001 + const feeInWei = ether(fee.toString()) + const initialValue = halfEther + const valueCalc = 0.5 * (1 - fee) + const value = ether(valueCalc.toString()) + + await homeBridge.rewardableInitialize( + rewardableValidators.address, + [oneEther, halfEther, minPerTx], + gasPrice, + requireBlockConfirmations, + [foreignDailyLimit, foreignMaxPerTx], + owner, + feeManager.address, + [feeInWei, feeInWei], + decimalShiftZero + ).should.be.fulfilled + + await homeBridge.sendTransaction({ + from: user, + value: initialValue + }).should.be.fulfilled + + // When + const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80' + const message = createMessage(user, value, transactionHash, homeBridge.address) + const signature = await sign(validators[0], message) + + const { receipt } = await homeBridge.submitSignature(signature, message, { + from: validators[0] + }).should.be.fulfilled + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + }) }) describe('#feeManager_BothDirections_ExecuteAffirmation', async () => { @@ -2351,6 +2449,50 @@ contract('HomeBridge', async accounts => { updatedBalanceRewardAddress4.should.be.bignumber.equal(initialBalanceRewardAddress4.add(feePerValidator)) updatedBalanceRewardAddress5.should.be.bignumber.equal(initialBalanceRewardAddress5.add(feePerValidator)) }) + it('should distribute fee to max allowed number of validators', async () => { + // Given + const owner = accounts[0] + const validators = createAccounts(web3, MAX_VALIDATORS) + validators[0] = accounts[2] + const rewards = createAccounts(web3, MAX_VALIDATORS) + const requiredSignatures = 1 + + const value = halfEther + // 0.1% fee + const fee = 0.001 + const feeInWei = ether(fee.toString()) + + const rewardableValidators = await RewardableValidators.new() + const homeBridge = await HomeBridge.new() + const feeManager = await FeeManagerNativeToErcBothDirections.new() + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner, { + from: owner + }).should.be.fulfilled + await homeBridge.rewardableInitialize( + rewardableValidators.address, + [oneEther, halfEther, minPerTx], + gasPrice, + requireBlockConfirmations, + [foreignDailyLimit, foreignMaxPerTx], + owner, + feeManager.address, + [feeInWei, feeInWei], + decimalShiftZero + ).should.be.fulfilled + await homeBridge.sendTransaction({ + from: accounts[0], + value: halfEther + }).should.be.fulfilled + + const recipient = '0xf4BEF13F9f4f2B203FAF0C3cBbaAbe1afE056955' + + const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415' + + const { receipt } = await homeBridge.executeAffirmation(recipient, value, transactionHash, { + from: validators[0] + }).should.be.fulfilled + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + }) }) describe('#decimalShift', async () => { const decimalShiftTwo = 2 diff --git a/test/rewardable_validators_test.js b/test/rewardable_validators_test.js index 92d5e975a..62989e7e9 100644 --- a/test/rewardable_validators_test.js +++ b/test/rewardable_validators_test.js @@ -5,6 +5,8 @@ const { expect } = require('chai') const { ERROR_MSG, ZERO_ADDRESS, F_ADDRESS, BN } = require('./setup') const { expectEventInLogs, createAccounts } = require('./helpers/helpers') +const MAX_GAS = 8000000 +const MAX_VALIDATORS = 50 const ZERO = new BN(0) contract('RewardableValidators', async accounts => { @@ -62,18 +64,32 @@ contract('RewardableValidators', async accounts => { }) it('should fail if exceed amount of validators', async () => { // Given - const validators = createAccounts(web3, 101) + const validators = createAccounts(web3, MAX_VALIDATORS + 1) // When await bridgeValidators - .initialize(99, validators, validators, accounts[2], { from: accounts[2] }) + .initialize(MAX_VALIDATORS - 1, validators, validators, accounts[2], { from: accounts[2] }) .should.be.rejectedWith(ERROR_MSG) - await bridgeValidators.initialize(99, validators.slice(0, 100), validators.slice(0, 100), accounts[2], { + }) + + it('should be able to operate with max allowed number of validators', async () => { + // Given + const validators = createAccounts(web3, MAX_VALIDATORS) + + // When + const { receipt } = await bridgeValidators.initialize(MAX_VALIDATORS - 1, validators, validators, accounts[2], { from: accounts[2] }).should.be.fulfilled - // Then - expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('100') + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal(`${MAX_VALIDATORS}`) + + // removing last validator from list (the highest gas consumption) + await bridgeValidators.removeValidator(validators[MAX_VALIDATORS - 1], { + from: accounts[2] + }).should.be.fulfilled + + expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal(`${MAX_VALIDATORS - 1}`) }) }) diff --git a/test/validators_test.js b/test/validators_test.js index ca710bb7e..f2c2c7caa 100644 --- a/test/validators_test.js +++ b/test/validators_test.js @@ -5,6 +5,8 @@ const { expect } = require('chai') const { ERROR_MSG, ZERO_ADDRESS, F_ADDRESS, BN } = require('./setup') const { expectEventInLogs, createAccounts } = require('./helpers/helpers') +const MAX_GAS = 8000000 +const MAX_VALIDATORS = 50 const ZERO = new BN(0) contract('BridgeValidators', async accounts => { @@ -50,17 +52,30 @@ contract('BridgeValidators', async accounts => { }) it('should fail if exceed amount of validators', async () => { // Given - const validators = createAccounts(web3, 101) + const validators = createAccounts(web3, MAX_VALIDATORS + 1) // When await bridgeValidators - .initialize(99, validators, accounts[2], { from: accounts[2] }) + .initialize(MAX_VALIDATORS - 1, validators, accounts[2], { from: accounts[2] }) .should.be.rejectedWith(ERROR_MSG) - await bridgeValidators.initialize(99, validators.slice(0, 100), accounts[2], { from: accounts[2] }).should.be - .fulfilled + }) - // Then - expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('100') + it('should be able to operate with max allowed number of validators', async () => { + // Given + const validators = createAccounts(web3, MAX_VALIDATORS) + + // When + const { receipt } = await bridgeValidators.initialize(MAX_VALIDATORS - 1, validators, accounts[2], { + from: accounts[2] + }).should.be.fulfilled + + expect(receipt.gasUsed).to.be.lte(MAX_GAS) + expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal(`${MAX_VALIDATORS}`) + + // removing last validator from list (the highest gas consumption) + await bridgeValidators.removeValidator(validators[MAX_VALIDATORS - 1], { from: accounts[2] }).should.be.fulfilled + + expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal(`${MAX_VALIDATORS - 1}`) }) }) diff --git a/truffle-config.js b/truffle-config.js index a80a21688..0c83d6ef4 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -75,7 +75,8 @@ if (process.env.SOLIDITY_COVERAGE === 'true') { balance: '1000000000000000000000000' } ], - port: 8545 + port: 8545, + gasLimit: 10000000 }) provider.addProvider(ganacheSubprovider) provider.start(err => { @@ -91,13 +92,15 @@ module.exports = { networks: { development: { provider, - network_id: '*' + network_id: '*', + gas: 10000000 }, ganache: { host: '127.0.0.1', port: 8545, network_id: '*', // eslint-disable-line camelcase - gasPrice: 100000000000 + gasPrice: 100000000000, + gas: 10000000 } }, compilers: {