diff --git a/contracts/IOwnedUpgradeabilityProxy.sol b/contracts/IOwnedUpgradeabilityProxy.sol new file mode 100644 index 000000000..7da3d5c65 --- /dev/null +++ b/contracts/IOwnedUpgradeabilityProxy.sol @@ -0,0 +1,6 @@ +pragma solidity 0.4.24; + + +interface IOwnedUpgradeabilityProxy { + function proxyOwner() public view returns (address); +} diff --git a/contracts/upgradeable_contracts/BasicBridge.sol b/contracts/upgradeable_contracts/BasicBridge.sol index 6965de1a8..f805c6573 100644 --- a/contracts/upgradeable_contracts/BasicBridge.sol +++ b/contracts/upgradeable_contracts/BasicBridge.sol @@ -1,20 +1,23 @@ pragma solidity 0.4.24; import "../IBridgeValidators.sol"; +import "./OwnedUpgradeability.sol"; import "../upgradeability/EternalStorage.sol"; import "../libraries/SafeMath.sol"; import "./Validatable.sol"; +import "./Ownable.sol"; import "openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol"; -contract BasicBridge is EternalStorage, Validatable { +contract BasicBridge is EternalStorage, Validatable, Ownable, OwnedUpgradeability { using SafeMath for uint256; event GasPriceChanged(uint256 gasPrice); event RequiredBlockConfirmationChanged(uint256 requiredBlockConfirmations); event DailyLimitChanged(uint256 newLimit); + event ExecutionDailyLimitChanged(uint256 newLimit); function getBridgeInterfacesVersion() public pure returns(uint64 major, uint64 minor, uint64 patch) { - return (2, 1, 0); + return (2, 2, 0); } function setGasPrice(uint256 _gasPrice) public onlyOwner { @@ -49,6 +52,14 @@ contract BasicBridge is EternalStorage, Validatable { return uintStorage[keccak256(abi.encodePacked("totalSpentPerDay", _day))]; } + function setTotalExecutedPerDay(uint256 _day, uint256 _value) internal { + uintStorage[keccak256(abi.encodePacked("totalExecutedPerDay", _day))] = _value; + } + + function totalExecutedPerDay(uint256 _day) public view returns(uint256) { + return uintStorage[keccak256(abi.encodePacked("totalExecutedPerDay", _day))]; + } + function minPerTx() public view returns(uint256) { return uintStorage[keccak256(abi.encodePacked("minPerTx"))]; } @@ -57,6 +68,10 @@ contract BasicBridge is EternalStorage, Validatable { return uintStorage[keccak256(abi.encodePacked("maxPerTx"))]; } + function executionMaxPerTx() public view returns(uint256) { + return uintStorage[keccak256(abi.encodePacked("executionMaxPerTx"))]; + } + function setInitialize(bool _status) internal { boolStorage[keccak256(abi.encodePacked("isInitialized"))] = _status; } @@ -78,6 +93,20 @@ contract BasicBridge is EternalStorage, Validatable { return uintStorage[keccak256(abi.encodePacked("dailyLimit"))]; } + function setExecutionDailyLimit(uint256 _dailyLimit) public onlyOwner { + uintStorage[keccak256(abi.encodePacked("executionDailyLimit"))] = _dailyLimit; + emit ExecutionDailyLimitChanged(_dailyLimit); + } + + function executionDailyLimit() public view returns(uint256) { + return uintStorage[keccak256(abi.encodePacked("executionDailyLimit"))]; + } + + function setExecutionMaxPerTx(uint256 _maxPerTx) external onlyOwner { + require(_maxPerTx < executionDailyLimit()); + uintStorage[keccak256(abi.encodePacked("executionMaxPerTx"))] = _maxPerTx; + } + function setMaxPerTx(uint256 _maxPerTx) external onlyOwner { require(_maxPerTx < dailyLimit()); uintStorage[keccak256(abi.encodePacked("maxPerTx"))] = _maxPerTx; @@ -93,7 +122,12 @@ contract BasicBridge is EternalStorage, Validatable { return dailyLimit() >= nextLimit && _amount <= maxPerTx() && _amount >= minPerTx(); } - function claimTokens(address _token, address _to) public onlyOwner { + function withinExecutionLimit(uint256 _amount) public view returns(bool) { + uint256 nextLimit = totalExecutedPerDay(getCurrentDay()).add(_amount); + return executionDailyLimit() >= nextLimit && _amount <= executionMaxPerTx(); + } + + function claimTokens(address _token, address _to) public onlyIfOwnerOfProxy { require(_to != address(0)); if (_token == address(0)) { _to.transfer(address(this).balance); diff --git a/contracts/upgradeable_contracts/BasicForeignBridge.sol b/contracts/upgradeable_contracts/BasicForeignBridge.sol index 5b1614161..5198a1a5f 100644 --- a/contracts/upgradeable_contracts/BasicForeignBridge.sol +++ b/contracts/upgradeable_contracts/BasicForeignBridge.sol @@ -17,16 +17,18 @@ contract BasicForeignBridge is EternalStorage, Validatable { bytes32 txHash; address contractAddress; (recipient, amount, txHash, contractAddress) = Message.parseMessage(message); - require(contractAddress == address(this)); - require(!relayedMessages(txHash)); - setRelayedMessages(txHash, true); - require(onExecuteMessage(recipient, amount)); - emit RelayedMessage(recipient, amount, txHash); + if (messageWithinLimits(amount)) { + require(contractAddress == address(this)); + require(!relayedMessages(txHash)); + setRelayedMessages(txHash, true); + require(onExecuteMessage(recipient, amount)); + emit RelayedMessage(recipient, amount, txHash); + } else { + onFailedMessage(recipient, amount, txHash); + } } - function onExecuteMessage(address, uint256) internal returns(bool){ - // has to be defined - } + function onExecuteMessage(address, uint256) internal returns(bool); function setRelayedMessages(bytes32 _txHash, bool _status) internal { boolStorage[keccak256(abi.encodePacked("relayedMessages", _txHash))] = _status; @@ -35,4 +37,8 @@ contract BasicForeignBridge is EternalStorage, Validatable { function relayedMessages(bytes32 _txHash) public view returns(bool) { return boolStorage[keccak256(abi.encodePacked("relayedMessages", _txHash))]; } + + function messageWithinLimits(uint256) internal view returns(bool); + + function onFailedMessage(address, uint256, bytes32) internal; } diff --git a/contracts/upgradeable_contracts/BasicHomeBridge.sol b/contracts/upgradeable_contracts/BasicHomeBridge.sol index 6b5229c9c..f1c27d03b 100644 --- a/contracts/upgradeable_contracts/BasicHomeBridge.sol +++ b/contracts/upgradeable_contracts/BasicHomeBridge.sol @@ -16,27 +16,31 @@ contract BasicHomeBridge is EternalStorage, Validatable { event CollectedSignatures(address authorityResponsibleForRelay, bytes32 messageHash, uint256 NumberOfCollectedSignatures); function executeAffirmation(address recipient, uint256 value, bytes32 transactionHash) external onlyValidator { - bytes32 hashMsg = keccak256(abi.encodePacked(recipient, value, transactionHash)); - bytes32 hashSender = keccak256(abi.encodePacked(msg.sender, hashMsg)); - // Duplicated affirmations - require(!affirmationsSigned(hashSender)); - setAffirmationsSigned(hashSender, true); - - uint256 signed = numAffirmationsSigned(hashMsg); - require(!isAlreadyProcessed(signed)); - // the check above assumes that the case when the value could be overflew will not happen in the addition operation below - signed = signed + 1; - - setNumAffirmationsSigned(hashMsg, signed); - - emit SignedForAffirmation(msg.sender, transactionHash); - - if (signed >= requiredSignatures()) { - // If the bridge contract does not own enough tokens to transfer - // it will couse funds lock on the home side of the bridge - setNumAffirmationsSigned(hashMsg, markAsProcessed(signed)); - require(onExecuteAffirmation(recipient, value)); - emit AffirmationCompleted(recipient, value, transactionHash); + if (affirmationWithinLimits(value)) { + bytes32 hashMsg = keccak256(abi.encodePacked(recipient, value, transactionHash)); + bytes32 hashSender = keccak256(abi.encodePacked(msg.sender, hashMsg)); + // Duplicated affirmations + require(!affirmationsSigned(hashSender)); + setAffirmationsSigned(hashSender, true); + + uint256 signed = numAffirmationsSigned(hashMsg); + require(!isAlreadyProcessed(signed)); + // the check above assumes that the case when the value could be overflew will not happen in the addition operation below + signed = signed + 1; + + setNumAffirmationsSigned(hashMsg, signed); + + emit SignedForAffirmation(msg.sender, transactionHash); + + if (signed >= requiredSignatures()) { + // If the bridge contract does not own enough tokens to transfer + // it will couse funds lock on the home side of the bridge + setNumAffirmationsSigned(hashMsg, markAsProcessed(signed)); + require(onExecuteAffirmation(recipient, value)); + emit AffirmationCompleted(recipient, value, transactionHash); + } + } else { + onFailedAffirmation(recipient, value, transactionHash); } } @@ -144,4 +148,11 @@ contract BasicHomeBridge is EternalStorage, Validatable { function requiredMessageLength() public pure returns(uint256) { return Message.requiredMessageLength(); } + + function affirmationWithinLimits(uint256) internal view returns(bool) { + return true; + } + + function onFailedAffirmation(address, uint256, bytes32) internal { + } } diff --git a/contracts/upgradeable_contracts/OverdrawManagement.sol b/contracts/upgradeable_contracts/OverdrawManagement.sol new file mode 100644 index 000000000..b376ccb12 --- /dev/null +++ b/contracts/upgradeable_contracts/OverdrawManagement.sol @@ -0,0 +1,51 @@ +pragma solidity 0.4.24; + +import "../upgradeability/EternalStorage.sol"; +import "../libraries/SafeMath.sol"; +import "./OwnedUpgradeability.sol"; + + +contract OverdrawManagement is EternalStorage, OwnedUpgradeability { + using SafeMath for uint256; + + event UserRequestForSignature(address recipient, uint256 value); + + function fixAssetsAboveLimits(bytes32 txHash, bool unlockOnForeign) external onlyIfOwnerOfProxy { + require(!fixedAssets(txHash)); + address recipient; + uint256 value; + (recipient, value) = txAboveLimits(txHash); + require(recipient != address(0) && value > 0); + setOutOfLimitAmount(outOfLimitAmount().sub(value)); + if (unlockOnForeign) { + emit UserRequestForSignature(recipient, value); + } + setFixedAssets(txHash, true); + } + + function outOfLimitAmount() public view returns(uint256) { + return uintStorage[keccak256(abi.encodePacked("outOfLimitAmount"))]; + } + + function fixedAssets(bytes32 _txHash) public view returns(bool) { + return boolStorage[keccak256(abi.encodePacked("fixedAssets", _txHash))]; + } + + function setOutOfLimitAmount(uint256 _value) internal { + uintStorage[keccak256(abi.encodePacked("outOfLimitAmount"))] = _value; + } + + function txAboveLimits(bytes32 _txHash) internal view returns(address recipient, uint256 value) { + recipient = addressStorage[keccak256(abi.encodePacked("txOutOfLimitRecipient", _txHash))]; + value = uintStorage[keccak256(abi.encodePacked("txOutOfLimitValue", _txHash))]; + } + + function setTxAboveLimits(address _recipient, uint256 _value, bytes32 _txHash) internal { + addressStorage[keccak256(abi.encodePacked("txOutOfLimitRecipient", _txHash))] = _recipient; + uintStorage[keccak256(abi.encodePacked("txOutOfLimitValue", _txHash))] = _value; + } + + function setFixedAssets(bytes32 _txHash, bool _status) internal { + boolStorage[keccak256(abi.encodePacked("fixedAssets", _txHash))] = _status; + } +} diff --git a/contracts/upgradeable_contracts/OwnedUpgradeability.sol b/contracts/upgradeable_contracts/OwnedUpgradeability.sol new file mode 100644 index 000000000..c31b15ed2 --- /dev/null +++ b/contracts/upgradeable_contracts/OwnedUpgradeability.sol @@ -0,0 +1,17 @@ +pragma solidity 0.4.24; + +import "../IOwnedUpgradeabilityProxy.sol"; + + +contract OwnedUpgradeability { + + function upgradeabilityAdmin() public view returns (address) { + return IOwnedUpgradeabilityProxy(this).proxyOwner(); + } + + // Avoid using onlyProxyOwner name to prevent issues with implementation from proxy contract + modifier onlyIfOwnerOfProxy() { + require(msg.sender == upgradeabilityAdmin()); + _; + } +} diff --git a/contracts/upgradeable_contracts/Validatable.sol b/contracts/upgradeable_contracts/Validatable.sol index 655ef1da8..098ca1232 100644 --- a/contracts/upgradeable_contracts/Validatable.sol +++ b/contracts/upgradeable_contracts/Validatable.sol @@ -13,11 +13,6 @@ contract Validatable is EternalStorage { _; } - modifier onlyOwner() { - require(validatorContract().owner() == msg.sender); - _; - } - function requiredSignatures() public view returns(uint256) { return validatorContract().requiredSignatures(); } diff --git a/contracts/upgradeable_contracts/erc20_to_erc20/ForeignBridgeErcToErc.sol b/contracts/upgradeable_contracts/erc20_to_erc20/ForeignBridgeErcToErc.sol index 92f3547c5..73a2a34ab 100644 --- a/contracts/upgradeable_contracts/erc20_to_erc20/ForeignBridgeErcToErc.sol +++ b/contracts/upgradeable_contracts/erc20_to_erc20/ForeignBridgeErcToErc.sol @@ -16,17 +16,27 @@ contract ForeignBridgeErcToErc is BasicBridge, BasicForeignBridge { address _validatorContract, address _erc20token, uint256 _requiredBlockConfirmations, - uint256 _gasPrice + uint256 _gasPrice, + uint256 _maxPerTx, + uint256 _homeDailyLimit, + uint256 _homeMaxPerTx, + address _owner ) public returns(bool) { require(!isInitialized()); require(_validatorContract != address(0) && isContract(_validatorContract)); require(_requiredBlockConfirmations != 0); require(_gasPrice > 0); + require(_homeMaxPerTx < _homeDailyLimit); + require(_owner != address(0)); addressStorage[keccak256(abi.encodePacked("validatorContract"))] = _validatorContract; setErc20token(_erc20token); uintStorage[keccak256(abi.encodePacked("deployedAtBlock"))] = block.number; uintStorage[keccak256(abi.encodePacked("requiredBlockConfirmations"))] = _requiredBlockConfirmations; uintStorage[keccak256(abi.encodePacked("gasPrice"))] = _gasPrice; + uintStorage[keccak256(abi.encodePacked("maxPerTx"))] = _maxPerTx; + uintStorage[keccak256(abi.encodePacked("executionDailyLimit"))] = _homeDailyLimit; + uintStorage[keccak256(abi.encodePacked("executionMaxPerTx"))] = _homeMaxPerTx; + setOwner(_owner); setInitialize(true); return isInitialized(); } @@ -35,7 +45,7 @@ contract ForeignBridgeErcToErc is BasicBridge, BasicForeignBridge { return bytes4(keccak256(abi.encodePacked("erc-to-erc-core"))); } - function claimTokens(address _token, address _to) public onlyOwner { + function claimTokens(address _token, address _to) public onlyIfOwnerOfProxy { require(_token != address(erc20token())); super.claimTokens(_token, _to); } @@ -45,6 +55,7 @@ contract ForeignBridgeErcToErc is BasicBridge, BasicForeignBridge { } function onExecuteMessage(address _recipient, uint256 _amount) internal returns(bool){ + setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_amount)); return erc20token().transfer(_recipient, _amount); } @@ -52,4 +63,12 @@ contract ForeignBridgeErcToErc is BasicBridge, BasicForeignBridge { require(_token != address(0) && isContract(_token)); addressStorage[keccak256(abi.encodePacked("erc20token"))] = _token; } + + function messageWithinLimits(uint256 _amount) internal view returns(bool) { + return withinExecutionLimit(_amount); + } + + function onFailedMessage(address, uint256, bytes32) internal { + revert(); + } } diff --git a/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol b/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol index 76ea54536..51313be11 100644 --- a/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol +++ b/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol @@ -7,9 +7,12 @@ import "../../IBurnableMintableERC677Token.sol"; import "../../ERC677Receiver.sol"; import "../BasicHomeBridge.sol"; import "../ERC677Bridge.sol"; +import "../OverdrawManagement.sol"; -contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, BasicHomeBridge, ERC677Bridge { +contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, BasicHomeBridge, ERC677Bridge, OverdrawManagement { + + event AmountLimitExceeded(address recipient, uint256 value, bytes32 transactionHash); function initialize ( address _validatorContract, @@ -18,8 +21,10 @@ contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, Basi uint256 _minPerTx, uint256 _homeGasPrice, uint256 _requiredBlockConfirmations, - address _erc677token - + address _erc677token, + uint256 _foreignDailyLimit, + uint256 _foreignMaxPerTx, + address _owner ) public returns(bool) { @@ -28,6 +33,8 @@ contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, Basi require(_homeGasPrice > 0); require(_requiredBlockConfirmations > 0); require(_minPerTx > 0 && _maxPerTx > _minPerTx && _dailyLimit > _maxPerTx); + require(_foreignMaxPerTx < _foreignDailyLimit); + require(_owner != address(0)); addressStorage[keccak256(abi.encodePacked("validatorContract"))] = _validatorContract; uintStorage[keccak256(abi.encodePacked("deployedAtBlock"))] = block.number; uintStorage[keccak256(abi.encodePacked("dailyLimit"))] = _dailyLimit; @@ -35,6 +42,9 @@ contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, Basi uintStorage[keccak256(abi.encodePacked("minPerTx"))] = _minPerTx; uintStorage[keccak256(abi.encodePacked("gasPrice"))] = _homeGasPrice; uintStorage[keccak256(abi.encodePacked("requiredBlockConfirmations"))] = _requiredBlockConfirmations; + uintStorage[keccak256(abi.encodePacked("executionDailyLimit"))] = _foreignDailyLimit; + uintStorage[keccak256(abi.encodePacked("executionMaxPerTx"))] = _foreignMaxPerTx; + setOwner(_owner); setInitialize(true); setErc677token(_erc677token); @@ -45,11 +55,12 @@ contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, Basi return bytes4(keccak256(abi.encodePacked("erc-to-erc-core"))); } - function () public { + function () payable public { revert(); } function onExecuteAffirmation(address _recipient, uint256 _value) internal returns(bool) { + setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_value)); return erc677token().mint(_recipient, _value); } @@ -57,4 +68,17 @@ contract HomeBridgeErcToErc is ERC677Receiver, EternalStorage, BasicBridge, Basi emit UserRequestForSignature(_from, _value); } + function affirmationWithinLimits(uint256 _amount) internal view returns(bool) { + return withinExecutionLimit(_amount); + } + + function onFailedAffirmation(address _recipient, uint256 _value, bytes32 _txHash) internal { + address recipient; + uint256 value; + (recipient, value) = txAboveLimits(_txHash); + require(recipient == address(0) && value == 0); + setOutOfLimitAmount(outOfLimitAmount().add(_value)); + setTxAboveLimits(_recipient, _value, _txHash); + emit AmountLimitExceeded(_recipient, _value, _txHash); + } } diff --git a/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol b/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol index 1653c37f4..c64317685 100644 --- a/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol +++ b/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol @@ -15,17 +15,27 @@ contract ForeignBridgeErcToNative is BasicBridge, BasicForeignBridge { address _validatorContract, address _erc20token, uint256 _requiredBlockConfirmations, - uint256 _gasPrice + uint256 _gasPrice, + uint256 _maxPerTx, + uint256 _homeDailyLimit, + uint256 _homeMaxPerTx, + address _owner ) public returns(bool) { require(!isInitialized()); require(_validatorContract != address(0) && isContract(_validatorContract)); require(_requiredBlockConfirmations != 0); require(_gasPrice > 0); + require(_homeMaxPerTx < _homeDailyLimit); + require(_owner != address(0)); addressStorage[keccak256(abi.encodePacked("validatorContract"))] = _validatorContract; setErc20token(_erc20token); uintStorage[keccak256(abi.encodePacked("deployedAtBlock"))] = block.number; uintStorage[keccak256(abi.encodePacked("requiredBlockConfirmations"))] = _requiredBlockConfirmations; uintStorage[keccak256(abi.encodePacked("gasPrice"))] = _gasPrice; + uintStorage[keccak256(abi.encodePacked("maxPerTx"))] = _maxPerTx; + uintStorage[keccak256(abi.encodePacked("executionDailyLimit"))] = _homeDailyLimit; + uintStorage[keccak256(abi.encodePacked("executionMaxPerTx"))] = _homeMaxPerTx; + setOwner(_owner); setInitialize(true); return isInitialized(); } @@ -34,7 +44,7 @@ contract ForeignBridgeErcToNative is BasicBridge, BasicForeignBridge { return bytes4(keccak256(abi.encodePacked("erc-to-native-core"))); } - function claimTokens(address _token, address _to) public onlyOwner { + function claimTokens(address _token, address _to) public onlyIfOwnerOfProxy { require(_token != address(erc20token())); super.claimTokens(_token, _to); } @@ -44,6 +54,7 @@ contract ForeignBridgeErcToNative is BasicBridge, BasicForeignBridge { } function onExecuteMessage(address _recipient, uint256 _amount) internal returns(bool) { + setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_amount)); return erc20token().transfer(_recipient, _amount); } @@ -51,4 +62,12 @@ contract ForeignBridgeErcToNative is BasicBridge, BasicForeignBridge { require(_token != address(0) && isContract(_token)); addressStorage[keccak256(abi.encodePacked("erc20token"))] = _token; } + + function messageWithinLimits(uint256 _amount) internal view returns(bool) { + return withinExecutionLimit(_amount); + } + + function onFailedMessage(address, uint256, bytes32) internal { + revert(); + } } diff --git a/contracts/upgradeable_contracts/erc20_to_native/HomeBridgeErcToNative.sol b/contracts/upgradeable_contracts/erc20_to_native/HomeBridgeErcToNative.sol index db98fae61..8a42f4586 100644 --- a/contracts/upgradeable_contracts/erc20_to_native/HomeBridgeErcToNative.sol +++ b/contracts/upgradeable_contracts/erc20_to_native/HomeBridgeErcToNative.sol @@ -7,9 +7,12 @@ import "../../IBlockReward.sol"; import "../../ERC677Receiver.sol"; import "../BasicHomeBridge.sol"; import "../ERC677Bridge.sol"; +import "../OverdrawManagement.sol"; -contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge { +contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge, OverdrawManagement { + + event AmountLimitExceeded(address recipient, uint256 value, bytes32 transactionHash); function () public payable { require(msg.value > 0); @@ -31,8 +34,10 @@ contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge { uint256 _minPerTx, uint256 _homeGasPrice, uint256 _requiredBlockConfirmations, - address _blockReward - + address _blockReward, + uint256 _foreignDailyLimit, + uint256 _foreignMaxPerTx, + address _owner ) public returns(bool) { require(!isInitialized()); @@ -40,6 +45,8 @@ contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge { require(_requiredBlockConfirmations > 0); require(_minPerTx > 0 && _maxPerTx > _minPerTx && _dailyLimit > _maxPerTx); require(_blockReward == address(0) || isContract(_blockReward)); + require(_foreignMaxPerTx < _foreignDailyLimit); + require(_owner != address(0)); addressStorage[keccak256(abi.encodePacked("validatorContract"))] = _validatorContract; uintStorage[keccak256(abi.encodePacked("deployedAtBlock"))] = block.number; uintStorage[keccak256(abi.encodePacked("dailyLimit"))] = _dailyLimit; @@ -48,6 +55,9 @@ contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge { uintStorage[keccak256(abi.encodePacked("gasPrice"))] = _homeGasPrice; uintStorage[keccak256(abi.encodePacked("requiredBlockConfirmations"))] = _requiredBlockConfirmations; addressStorage[keccak256(abi.encodePacked("blockRewardContract"))] = _blockReward; + uintStorage[keccak256(abi.encodePacked("executionDailyLimit"))] = _foreignDailyLimit; + uintStorage[keccak256(abi.encodePacked("executionMaxPerTx"))] = _foreignMaxPerTx; + setOwner(_owner); setInitialize(true); return isInitialized(); @@ -71,6 +81,7 @@ contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge { } function onExecuteAffirmation(address _recipient, uint256 _value) internal returns(bool) { + setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_value)); IBlockReward blockReward = blockRewardContract(); require(blockReward != address(0)); blockReward.addExtraReceiver(_value, _recipient); @@ -84,4 +95,18 @@ contract HomeBridgeErcToNative is EternalStorage, BasicBridge, BasicHomeBridge { function setTotalBurntCoins(uint256 _amount) internal { uintStorage[keccak256(abi.encodePacked("totalBurntCoins"))] = _amount; } + + function affirmationWithinLimits(uint256 _amount) internal view returns(bool) { + return withinExecutionLimit(_amount); + } + + function onFailedAffirmation(address _recipient, uint256 _value, bytes32 _txHash) internal { + address recipient; + uint256 value; + (recipient, value) = txAboveLimits(_txHash); + require(recipient == address(0) && value == 0); + setOutOfLimitAmount(outOfLimitAmount().add(_value)); + setTxAboveLimits(_recipient, _value, _txHash); + emit AmountLimitExceeded(_recipient, _value, _txHash); + } } diff --git a/contracts/upgradeable_contracts/native_to_erc20/ForeignBridgeNativeToErc.sol b/contracts/upgradeable_contracts/native_to_erc20/ForeignBridgeNativeToErc.sol index 2075908dd..3b52049a2 100644 --- a/contracts/upgradeable_contracts/native_to_erc20/ForeignBridgeNativeToErc.sol +++ b/contracts/upgradeable_contracts/native_to_erc20/ForeignBridgeNativeToErc.sol @@ -20,12 +20,17 @@ contract ForeignBridgeNativeToErc is ERC677Receiver, BasicBridge, BasicForeignBr uint256 _maxPerTx, uint256 _minPerTx, uint256 _foreignGasPrice, - uint256 _requiredBlockConfirmations + uint256 _requiredBlockConfirmations, + uint256 _homeDailyLimit, + uint256 _homeMaxPerTx, + address _owner ) public returns(bool) { require(!isInitialized()); require(_validatorContract != address(0) && isContract(_validatorContract)); require(_minPerTx > 0 && _maxPerTx > _minPerTx && _dailyLimit > _maxPerTx); require(_foreignGasPrice > 0); + require(_homeMaxPerTx < _homeDailyLimit); + require(_owner != address(0)); addressStorage[keccak256(abi.encodePacked("validatorContract"))] = _validatorContract; setErc677token(_erc677token); uintStorage[keccak256(abi.encodePacked("dailyLimit"))] = _dailyLimit; @@ -34,6 +39,9 @@ contract ForeignBridgeNativeToErc is ERC677Receiver, BasicBridge, BasicForeignBr uintStorage[keccak256(abi.encodePacked("minPerTx"))] = _minPerTx; uintStorage[keccak256(abi.encodePacked("gasPrice"))] = _foreignGasPrice; uintStorage[keccak256(abi.encodePacked("requiredBlockConfirmations"))] = _requiredBlockConfirmations; + uintStorage[keccak256(abi.encodePacked("executionDailyLimit"))] = _homeDailyLimit; + uintStorage[keccak256(abi.encodePacked("executionMaxPerTx"))] = _homeMaxPerTx; + setOwner(_owner); setInitialize(true); return isInitialized(); } @@ -42,11 +50,12 @@ contract ForeignBridgeNativeToErc is ERC677Receiver, BasicBridge, BasicForeignBr return bytes4(keccak256(abi.encodePacked("native-to-erc-core"))); } - function claimTokensFromErc677(address _token, address _to) external onlyOwner { + function claimTokensFromErc677(address _token, address _to) external onlyIfOwnerOfProxy { erc677token().claimTokens(_token, _to); } function onExecuteMessage(address _recipient, uint256 _amount) internal returns(bool){ + setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_amount)); return erc677token().mint(_recipient, _amount); } @@ -54,4 +63,11 @@ contract ForeignBridgeNativeToErc is ERC677Receiver, BasicBridge, BasicForeignBr emit UserRequestForAffirmation(_from, _value); } + function messageWithinLimits(uint256 _amount) internal view returns(bool) { + return withinExecutionLimit(_amount); + } + + function onFailedMessage(address, uint256, bytes32) internal { + revert(); + } } diff --git a/contracts/upgradeable_contracts/native_to_erc20/HomeBridgeNativeToErc.sol b/contracts/upgradeable_contracts/native_to_erc20/HomeBridgeNativeToErc.sol index 43fd268d6..e561c4c4f 100644 --- a/contracts/upgradeable_contracts/native_to_erc20/HomeBridgeNativeToErc.sol +++ b/contracts/upgradeable_contracts/native_to_erc20/HomeBridgeNativeToErc.sol @@ -19,7 +19,10 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicBridge, BasicHomeBridge { uint256 _maxPerTx, uint256 _minPerTx, uint256 _homeGasPrice, - uint256 _requiredBlockConfirmations + uint256 _requiredBlockConfirmations, + uint256 _foreignDailyLimit, + uint256 _foreignMaxPerTx, + address _owner ) public returns(bool) { @@ -28,6 +31,8 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicBridge, BasicHomeBridge { require(_homeGasPrice > 0); require(_requiredBlockConfirmations > 0); require(_minPerTx > 0 && _maxPerTx > _minPerTx && _dailyLimit > _maxPerTx); + require(_foreignMaxPerTx < _foreignDailyLimit); + require(_owner != address(0)); addressStorage[keccak256(abi.encodePacked("validatorContract"))] = _validatorContract; uintStorage[keccak256(abi.encodePacked("deployedAtBlock"))] = block.number; uintStorage[keccak256(abi.encodePacked("dailyLimit"))] = _dailyLimit; @@ -35,6 +40,9 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicBridge, BasicHomeBridge { uintStorage[keccak256(abi.encodePacked("minPerTx"))] = _minPerTx; uintStorage[keccak256(abi.encodePacked("gasPrice"))] = _homeGasPrice; uintStorage[keccak256(abi.encodePacked("requiredBlockConfirmations"))] = _requiredBlockConfirmations; + uintStorage[keccak256(abi.encodePacked("executionDailyLimit"))] = _foreignDailyLimit; + uintStorage[keccak256(abi.encodePacked("executionMaxPerTx"))] = _foreignMaxPerTx; + setOwner(_owner); setInitialize(true); return isInitialized(); } @@ -52,9 +60,18 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicBridge, BasicHomeBridge { } function onExecuteAffirmation(address _recipient, uint256 _value) internal returns(bool) { + setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_value)); if (!_recipient.send(_value)) { (new Sacrifice).value(_value)(_recipient); } return true; } + + function affirmationWithinLimits(uint256 _amount) internal view returns(bool) { + return withinExecutionLimit(_amount); + } + + function onFailedAffirmation(address _recipient, uint256 _value, bytes32 _txHash) internal { + revert(); + } } diff --git a/deploy/.env.example b/deploy/.env.example index 954064a0f..06bd47ebe 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -1,19 +1,19 @@ #BRIDGE_MODE=ERC_TO_ERC BRIDGE_MODE=NATIVE_TO_ERC DEPLOYMENT_ACCOUNT_PRIVATE_KEY=67..14 -DEPLOYMENT_GAS_LIMIT=4000000 +DEPLOYMENT_GAS_LIMIT=5000000 HOME_DEPLOYMENT_GAS_PRICE=10000000000 FOREIGN_DEPLOYMENT_GAS_PRICE=10000000000 GET_RECEIPT_INTERVAL_IN_MILLISECONDS=3000 -BRIDGEABLE_TOKEN_NAME="Your New Bridged Token" -BRIDGEABLE_TOKEN_SYMBOL="TEST" -BRIDGEABLE_TOKEN_DECIMALS="18" +BRIDGEABLE_TOKEN_NAME=Your New Bridged Token +BRIDGEABLE_TOKEN_SYMBOL=TEST +BRIDGEABLE_TOKEN_DECIMALS=18 HOME_RPC_URL=https://sokol.poa.network -HOME_OWNER_MULTISIG=0x -HOME_UPGRADEABLE_ADMIN_VALIDATORS=0x -HOME_UPGRADEABLE_ADMIN_BRIDGE=0x +HOME_BRIDGE_OWNER=0x +HOME_VALIDATORS_OWNER=0x +HOME_UPGRADEABLE_ADMIN=0x HOME_DAILY_LIMIT=30000000000000000000000000 HOME_MAX_AMOUNT_PER_TX=1500000000000000000000000 HOME_MIN_AMOUNT_PER_TX=500000000000000000 @@ -24,9 +24,9 @@ HOME_GAS_PRICE=1000000000 BLOCK_REWARD_ADDRESS= FOREIGN_RPC_URL=https://sokol.poa.network -FOREIGN_OWNER_MULTISIG=0x -FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS=0x -FOREIGN_UPGRADEABLE_ADMIN_BRIDGE=0x +FOREIGN_BRIDGE_OWNER=0x +FOREIGN_VALIDATORS_OWNER=0x +FOREIGN_UPGRADEABLE_ADMIN=0x FOREIGN_DAILY_LIMIT=15000000000000000000000000 FOREIGN_MAX_AMOUNT_PER_TX=750000000000000000000000 FOREIGN_MIN_AMOUNT_PER_TX=500000000000000000 @@ -36,6 +36,6 @@ FOREIGN_GAS_PRICE=10000000000 ERC20_TOKEN_ADDRESS= REQUIRED_NUMBER_OF_VALIDATORS=1 -VALIDATORS="0x 0x 0x" - - +#If several validators are used, list them separated by space without quotes +#E.g. VALIDATORS=0x 0x 0x +VALIDATORS=0x diff --git a/deploy/README.md b/deploy/README.md index 77c9051d0..50b38b473 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -49,24 +49,23 @@ FOREIGN_DEPLOYMENT_GAS_PRICE=10000000000 GET_RECEIPT_INTERVAL_IN_MILLISECONDS=3000 # The name of the ERC677 token to be deployed on the Foreign network. -BRIDGEABLE_TOKEN_NAME="Your New Bridged Token" +BRIDGEABLE_TOKEN_NAME=Your New Bridged Token # The symbol name of the ERC677 token to be deployed on the Foreign network. -BRIDGEABLE_TOKEN_SYMBOL="TEST" +BRIDGEABLE_TOKEN_SYMBOL=TEST # The number of supportable decimal digits after the "point" in the ERC677 token # to be deployed on the Foreign network. -BRIDGEABLE_TOKEN_DECIMALS="18" +BRIDGEABLE_TOKEN_DECIMALS=18 # The RPC channel to a Home node able to handle deployment/configuration # transactions. HOME_RPC_URL=https://poa.infura.io -# The address of an administrator on the Home network who can change bridge -# parameters and a validator's contract. For extra security we recommended using -# a multi-sig wallet contract address here. -HOME_OWNER_MULTISIG=0x -# The address from which a validator's contract can be upgraded on Home. -HOME_UPGRADEABLE_ADMIN_VALIDATORS=0x -# The address from which the bridge's contract can be upgraded on Home. -HOME_UPGRADEABLE_ADMIN_BRIDGE=0x +# Address on Home network with permissions to change parameters of the bridge contract. +# For extra security we recommended using a multi-sig wallet contract address here. +HOME_BRIDGE_OWNER=0x +# Address on Home network with permissions to change parameters of bridge validator contract. +HOME_VALIDATORS_OWNER=0x +# Address on Home network with permissions to upgrade the bridge contract and the bridge validator contract. +HOME_UPGRADEABLE_ADMIN=0x # The daily transaction limit in Wei. As soon as this limit is exceeded, any # transaction which requests to relay assets will fail. HOME_DAILY_LIMIT=30000000000000000000000000 @@ -89,14 +88,13 @@ HOME_GAS_PRICE=1000000000 # The RPC channel to a Foreign node able to handle deployment/configuration # transactions. FOREIGN_RPC_URL=https://mainnet.infura.io -# The address of an administrator on the Foreign network who can change bridge -# parameters and the validator's contract. For extra security we recommended -# using a multi-sig wallet contract address here. -FOREIGN_OWNER_MULTISIG=0x -# The address from which a validator's contract can be upgraded on Foreign. -FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS=0x -# The address from which the bridge's contract can be upgraded on Foreign. -FOREIGN_UPGRADEABLE_ADMIN_BRIDGE=0x +# Address on Foreign network with permissions to change parameters of the bridge contract. +# For extra security we recommended using a multi-sig wallet contract address here. +FOREIGN_BRIDGE_OWNER=0x +# Address on Foreign network with permissions to change parameters of bridge validator contract. +FOREIGN_VALIDATORS_OWNER=0x +# Address on Foreign network with permissions to upgrade the bridge contract and the bridge validator contract. +FOREIGN_UPGRADEABLE_ADMIN=0x # The daily limit in Wei. As soon as this limit is exceeded, any transaction # requesting to relay assets will fail. FOREIGN_DAILY_LIMIT=15000000000000000000000000 @@ -124,7 +122,7 @@ REQUIRED_NUMBER_OF_VALIDATORS=1 # addresses are collected on the Home side. The same addresses will be used on # the Foreign network to confirm that the finalized agreement was transferred # correctly to the Foreign network. -VALIDATORS="0x 0x 0x" +VALIDATORS=0x 0x 0x ``` @@ -153,24 +151,23 @@ FOREIGN_DEPLOYMENT_GAS_PRICE=10000000000 GET_RECEIPT_INTERVAL_IN_MILLISECONDS=3000 # The name of the ERC677 token to be deployed on the Home network. -BRIDGEABLE_TOKEN_NAME="Your New Bridged Token" +BRIDGEABLE_TOKEN_NAME=Your New Bridged Token # The symbol name of the ERC677 token to be deployed on the Home network. -BRIDGEABLE_TOKEN_SYMBOL="TEST" +BRIDGEABLE_TOKEN_SYMBOL=TEST # The number of supportable decimal digits after the "point" in the ERC677 token # to be deployed on the Home network. -BRIDGEABLE_TOKEN_DECIMALS="18" +BRIDGEABLE_TOKEN_DECIMALS=18 # The RPC channel to a Home node able to handle deployment/configuration # transactions. HOME_RPC_URL=https://poa.infura.io -# The address of an administrator on the Home network who can change bridge -# parameters and a validator's contract. For extra security we recommended using -# a multi-sig wallet contract address here. -HOME_OWNER_MULTISIG=0x -# The address from which a validator's contract can be upgraded on Home. -HOME_UPGRADEABLE_ADMIN_VALIDATORS=0x -# The address from which the bridge's contract can be upgraded on Home. -HOME_UPGRADEABLE_ADMIN_BRIDGE=0x +# Address on Home network with permissions to change parameters of the bridge contract. +# For extra security we recommended using a multi-sig wallet contract address here. +HOME_BRIDGE_OWNER=0x +# Address on Home network with permissions to change parameters of bridge validator contract. +HOME_VALIDATORS_OWNER=0x +# Address on Home network with permissions to upgrade the bridge contract and the bridge validator contract. +HOME_UPGRADEABLE_ADMIN=0x # The daily transaction limit in Wei. As soon as this limit is exceeded, any # transaction which requests to relay assets will fail. HOME_DAILY_LIMIT=30000000000000000000000000 @@ -193,14 +190,13 @@ HOME_GAS_PRICE=1000000000 # The RPC channel to a Foreign node able to handle deployment/configuration # transactions. FOREIGN_RPC_URL=https://mainnet.infura.io -# The address of an administrator on the Foreign network who can change bridge -# parameters and the validator's contract. For extra security we recommended -# using a multi-sig wallet contract address here. -FOREIGN_OWNER_MULTISIG=0x -# The address from which a validator's contract can be upgraded on Foreign. -FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS=0x -# The address from which the bridge's contract can be upgraded on Foreign. -FOREIGN_UPGRADEABLE_ADMIN_BRIDGE=0x +# Address on Foreign network with permissions to change parameters of the bridge contract. +# For extra security we recommended using a multi-sig wallet contract address here. +FOREIGN_BRIDGE_OWNER=0x +# Address on Foreign network with permissions to change parameters of bridge validator contract. +FOREIGN_VALIDATORS_OWNER=0x +# Address on Foreign network with permissions to upgrade the bridge contract and the bridge validator contract. +FOREIGN_UPGRADEABLE_ADMIN=0x # These three parameters are not used in this mode, but the deployment script # requires it to be set to some value. FOREIGN_DAILY_LIMIT=0 @@ -226,7 +222,7 @@ REQUIRED_NUMBER_OF_VALIDATORS=1 # addresses are collected on the Home side. The same addresses will be used on # the Foreign network to confirm that the finalized agreement was transferred # correctly to the Foreign network. -VALIDATORS="0x 0x 0x" +VALIDATORS=0x 0x 0x ``` ## `ERC-TO-NATIVE` Bridge Mode Configuration Example. @@ -256,14 +252,13 @@ GET_RECEIPT_INTERVAL_IN_MILLISECONDS=3000 # The RPC channel to a Home node able to handle deployment/configuration # transactions. HOME_RPC_URL=https://poa.infura.io -# The address of an administrator on the Home network who can change bridge -# parameters and a validator's contract. For extra security we recommended using -# a multi-sig wallet contract address here. -HOME_OWNER_MULTISIG=0x -# The address from which a validator's contract can be upgraded on Home. -HOME_UPGRADEABLE_ADMIN_VALIDATORS=0x -# The address from which the bridge's contract can be upgraded on Home. -HOME_UPGRADEABLE_ADMIN_BRIDGE=0x +# Address on Home network with permissions to change parameters of the bridge contract. +# For extra security we recommended using a multi-sig wallet contract address here. +HOME_BRIDGE_OWNER=0x +# Address on Home network with permissions to change parameters of bridge validator contract. +HOME_VALIDATORS_OWNER=0x +# Address on Home network with permissions to upgrade the bridge contract and the bridge validator contract. +HOME_UPGRADEABLE_ADMIN=0x # The daily transaction limit in Wei. As soon as this limit is exceeded, any # transaction which requests to relay assets will fail. HOME_DAILY_LIMIT=30000000000000000000000000 @@ -289,14 +284,13 @@ BLOCK_REWARD_ADDRESS=0x # The RPC channel to a Foreign node able to handle deployment/configuration # transactions. FOREIGN_RPC_URL=https://mainnet.infura.io -# The address of an administrator on the Foreign network who can change bridge -# parameters and the validator's contract. For extra security we recommended -# using a multi-sig wallet contract address here. -FOREIGN_OWNER_MULTISIG=0x -# The address from which a validator's contract can be upgraded on Foreign. -FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS=0x -# The address from which the bridge's contract can be upgraded on Foreign. -FOREIGN_UPGRADEABLE_ADMIN_BRIDGE=0x +# Address on Foreign network with permissions to change parameters of the bridge contract. +# For extra security we recommended using a multi-sig wallet contract address here. +FOREIGN_BRIDGE_OWNER=0x +# Address on Foreign network with permissions to change parameters of bridge validator contract. +FOREIGN_VALIDATORS_OWNER=0x +# Address on Foreign network with permissions to upgrade the bridge contract and the bridge validator contract. +FOREIGN_UPGRADEABLE_ADMIN=0x # These three parameters are not used in this mode, but the deployment script # requires it to be set to some value. FOREIGN_DAILY_LIMIT=0 @@ -323,5 +317,5 @@ REQUIRED_NUMBER_OF_VALIDATORS=1 # addresses are collected on the Home side. The same addresses will be used on # the Foreign network to confirm that the finalized agreement was transferred # correctly to the Foreign network. -VALIDATORS="0x 0x 0x" +VALIDATORS=0x 0x 0x ``` diff --git a/deploy/deploy.js b/deploy/deploy.js index d953aef58..a727c5d49 100644 --- a/deploy/deploy.js +++ b/deploy/deploy.js @@ -1,9 +1,8 @@ const fs = require('fs') const path = require('path') const env = require('./src/loadEnv') -const { ZERO_ADDRESS } = require('./src/constants') -const { BRIDGE_MODE, BLOCK_REWARD_ADDRESS, ERC20_TOKEN_ADDRESS } = env +const { BRIDGE_MODE, ERC20_TOKEN_ADDRESS } = env const deployResultsPath = path.join(__dirname, './bridgeDeploymentResults.json') @@ -33,7 +32,7 @@ async function deployNativeToErc() { foreignBridge: { ...foreignBridge, erc677 - }, + } }, null, 4 @@ -49,7 +48,9 @@ async function deployErcToErc() { const { homeBridge, erc677 } = await deployHome() const { foreignBridge } = await deployForeign() console.log('\nDeployment has been completed.\n\n') - console.log(`[ Home ] HomeBridge: ${homeBridge.address} at block ${homeBridge.deployedBlockNumber}`) + console.log( + `[ Home ] HomeBridge: ${homeBridge.address} at block ${homeBridge.deployedBlockNumber}` + ) console.log(`[ Home ] ERC677 Bridgeable Token: ${erc677.address}`) console.log( `[ Foreign ] ForeignBridge: ${foreignBridge.address} at block ${ @@ -84,9 +85,7 @@ async function deployErcToNative() { const { foreignBridge } = await deployForeign() console.log('\nDeployment has been completed.\n\n') console.log( - `[ Home ] HomeBridge: ${homeBridge.address} at block ${ - homeBridge.deployedBlockNumber - }` + `[ Home ] HomeBridge: ${homeBridge.address} at block ${homeBridge.deployedBlockNumber}` ) console.log( `[ Foreign ] ForeignBridge: ${foreignBridge.address} at block ${ diff --git a/deploy/src/deploymentUtils.js b/deploy/src/deploymentUtils.js index 1d111bd50..3d06a86fd 100644 --- a/deploy/src/deploymentUtils.js +++ b/deploy/src/deploymentUtils.js @@ -44,9 +44,9 @@ async function deployContract(contractJson, args, { from, network, nonce }) { to: null, privateKey: deploymentPrivateKey, url, - gasPrice: gasPrice + gasPrice }) - if (tx.status !== '0x1') { + if (Web3Utils.hexToNumber(tx.status) !== 1) { throw new Error('Tx failed') } instance.options.address = tx.contractAddress @@ -110,7 +110,7 @@ async function sendNodeRequest(url, method, signedData) { }) const json = await request.json() if (method === 'eth_sendRawTransaction') { - assert.equal(json.result.length, 66, `Tx wasn't sent ${json}`) + assert.strictEqual(json.result.length, 66, `Tx wasn't sent ${json}`) } return json.result } diff --git a/deploy/src/erc_to_erc/foreign.js b/deploy/src/erc_to_erc/foreign.js index 9aa2a8fec..6dc7d81f9 100644 --- a/deploy/src/erc_to_erc/foreign.js +++ b/deploy/src/erc_to_erc/foreign.js @@ -14,12 +14,15 @@ const VALIDATORS = env.VALIDATORS.split(' ') const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY, REQUIRED_NUMBER_OF_VALIDATORS, - FOREIGN_OWNER_MULTISIG, - FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS, - FOREIGN_UPGRADEABLE_ADMIN_BRIDGE, + FOREIGN_BRIDGE_OWNER, + FOREIGN_VALIDATORS_OWNER, + FOREIGN_UPGRADEABLE_ADMIN, FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS, ERC20_TOKEN_ADDRESS, - FOREIGN_GAS_PRICE + FOREIGN_GAS_PRICE, + FOREIGN_MAX_AMOUNT_PER_TX, + HOME_DAILY_LIMIT, + HOME_MAX_AMOUNT_PER_TX } = env const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) @@ -65,7 +68,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToBridgeVForeign.status), 1, 'Transaction Failed') + assert.strictEqual( + Web3Utils.hexToNumber(txUpgradeToBridgeVForeign.status), + 1, + 'Transaction Failed' + ) foreignNonce++ console.log('\ninitializing Foreign Bridge Validators with following parameters:\n') @@ -74,7 +81,7 @@ async function deployForeign() { ) bridgeValidatorsForeign.options.address = storageValidatorsForeign.options.address const initializeForeignData = await bridgeValidatorsForeign.methods - .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, FOREIGN_OWNER_MULTISIG) + .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, FOREIGN_VALIDATORS_OWNER) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitializeForeign = await sendRawTxForeign({ data: initializeForeignData, @@ -83,12 +90,12 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitializeForeign.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitializeForeign.status), 1, 'Transaction Failed') foreignNonce++ console.log('\nTransferring ownership of ValidatorsProxy\n') const validatorsForeignOwnershipData = await storageValidatorsForeign.methods - .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS) + .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txValidatorsForeignOwnershipData = await sendRawTxForeign({ data: validatorsForeignOwnershipData, @@ -97,7 +104,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txValidatorsForeignOwnershipData.status), 1, 'Transaction Failed') + assert.strictEqual( + Web3Utils.hexToNumber(txValidatorsForeignOwnershipData.status), + 1, + 'Transaction Failed' + ) foreignNonce++ console.log('\ndeploying foreignBridge storage\n') @@ -132,7 +143,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToForeignBridge.status), 1, 'Transaction Failed') + assert.strictEqual( + Web3Utils.hexToNumber(txUpgradeToForeignBridge.status), + 1, + 'Transaction Failed' + ) foreignNonce++ console.log('\ninitializing Foreign Bridge with following parameters:\n') @@ -144,7 +159,11 @@ async function deployForeign() { storageValidatorsForeign.options.address, ERC20_TOKEN_ADDRESS, FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS, - FOREIGN_GAS_PRICE + FOREIGN_GAS_PRICE, + FOREIGN_MAX_AMOUNT_PER_TX, + HOME_DAILY_LIMIT, + HOME_MAX_AMOUNT_PER_TX, + FOREIGN_BRIDGE_OWNER ) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitializeBridge = await sendRawTxForeign({ @@ -154,11 +173,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitializeBridge.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitializeBridge.status), 1, 'Transaction Failed') foreignNonce++ const bridgeOwnershipData = await foreignBridgeStorage.methods - .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN_BRIDGE) + .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txBridgeOwnershipData = await sendRawTxForeign({ data: bridgeOwnershipData, @@ -167,7 +186,7 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txBridgeOwnershipData.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txBridgeOwnershipData.status), 1, 'Transaction Failed') foreignNonce++ console.log('\nForeign Deployment Bridge completed\n') diff --git a/deploy/src/erc_to_erc/home.js b/deploy/src/erc_to_erc/home.js index 96fe54852..d8f238d21 100644 --- a/deploy/src/erc_to_erc/home.js +++ b/deploy/src/erc_to_erc/home.js @@ -15,9 +15,9 @@ const VALIDATORS = env.VALIDATORS.split(' ') const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY, REQUIRED_NUMBER_OF_VALIDATORS, - HOME_OWNER_MULTISIG, - HOME_UPGRADEABLE_ADMIN_VALIDATORS, - HOME_UPGRADEABLE_ADMIN_BRIDGE, + HOME_BRIDGE_OWNER, + HOME_VALIDATORS_OWNER, + HOME_UPGRADEABLE_ADMIN, HOME_DAILY_LIMIT, HOME_MAX_AMOUNT_PER_TX, HOME_MIN_AMOUNT_PER_TX, @@ -25,7 +25,9 @@ const { HOME_GAS_PRICE, BRIDGEABLE_TOKEN_NAME, BRIDGEABLE_TOKEN_SYMBOL, - BRIDGEABLE_TOKEN_DECIMALS + BRIDGEABLE_TOKEN_DECIMALS, + FOREIGN_DAILY_LIMIT, + FOREIGN_MAX_AMOUNT_PER_TX } = env const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) @@ -59,7 +61,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToBridgeVHome.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txUpgradeToBridgeVHome.status), 1, 'Transaction Failed') homeNonce++ console.log('\ninitializing Home Bridge Validators with following parameters:\n') @@ -68,7 +70,7 @@ async function deployHome() { ) bridgeValidatorsHome.options.address = storageValidatorsHome.options.address const initializeData = await bridgeValidatorsHome.methods - .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, HOME_OWNER_MULTISIG) + .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, HOME_VALIDATORS_OWNER) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitialize = await sendRawTxHome({ data: initializeData, @@ -77,12 +79,12 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitialize.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitialize.status), 1, 'Transaction Failed') homeNonce++ console.log('transferring proxy ownership to multisig for Validators Proxy contract') const proxyDataTransfer = await storageValidatorsHome.methods - .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN_VALIDATORS) + .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN) .encodeABI() const txProxyDataTransfer = await sendRawTxHome({ data: proxyDataTransfer, @@ -91,7 +93,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txProxyDataTransfer.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txProxyDataTransfer.status), 1, 'Transaction Failed') homeNonce++ console.log('\ndeploying homeBridge storage\n') @@ -121,7 +123,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToHomeBridge.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txUpgradeToHomeBridge.status), 1, 'Transaction Failed') homeNonce++ console.log('\n[Home] deploying Bridgeble token') @@ -144,7 +146,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(setBridgeContract.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(setBridgeContract.status), 1, 'Transaction Failed') homeNonce++ console.log('transferring ownership of Bridgeble token to homeBridge contract') @@ -158,7 +160,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txOwnership.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txOwnership.status), 1, 'Transaction Failed') homeNonce++ console.log('\ninitializing Home Bridge with following parameters:\n') @@ -181,7 +183,10 @@ async function deployHome() { HOME_MIN_AMOUNT_PER_TX, HOME_GAS_PRICE, HOME_REQUIRED_BLOCK_CONFIRMATIONS, - erc677token.options.address + erc677token.options.address, + FOREIGN_DAILY_LIMIT, + FOREIGN_MAX_AMOUNT_PER_TX, + HOME_BRIDGE_OWNER ) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitializeHomeBridge = await sendRawTxHome({ @@ -191,12 +196,12 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitializeHomeBridge.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitializeHomeBridge.status), 1, 'Transaction Failed') homeNonce++ console.log('transferring proxy ownership to multisig for Home bridge Proxy contract') const homeBridgeProxyData = await homeBridgeStorage.methods - .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN_BRIDGE) + .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN) .encodeABI() const txhomeBridgeProxyData = await sendRawTxHome({ data: homeBridgeProxyData, @@ -205,7 +210,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txhomeBridgeProxyData.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txhomeBridgeProxyData.status), 1, 'Transaction Failed') homeNonce++ console.log('\nHome Deployment Bridge completed\n') @@ -213,7 +218,7 @@ async function deployHome() { homeBridge: { address: homeBridgeStorage.options.address, deployedBlockNumber: Web3Utils.hexToNumber(homeBridgeStorage.deployedBlockNumber) - }, + }, erc677: { address: erc677token.options.address } } } diff --git a/deploy/src/erc_to_native/foreign.js b/deploy/src/erc_to_native/foreign.js index 9112b404a..7584fa7c5 100644 --- a/deploy/src/erc_to_native/foreign.js +++ b/deploy/src/erc_to_native/foreign.js @@ -15,11 +15,14 @@ const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY, REQUIRED_NUMBER_OF_VALIDATORS, FOREIGN_GAS_PRICE, - FOREIGN_OWNER_MULTISIG, - FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS, - FOREIGN_UPGRADEABLE_ADMIN_BRIDGE, + FOREIGN_BRIDGE_OWNER, + FOREIGN_VALIDATORS_OWNER, + FOREIGN_UPGRADEABLE_ADMIN, FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS, - ERC20_TOKEN_ADDRESS + ERC20_TOKEN_ADDRESS, + FOREIGN_MAX_AMOUNT_PER_TX, + HOME_DAILY_LIMIT, + HOME_MAX_AMOUNT_PER_TX } = env const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) @@ -65,7 +68,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToBridgeVForeign.status), 1, 'Transaction Failed') + assert.strictEqual( + Web3Utils.hexToNumber(txUpgradeToBridgeVForeign.status), + 1, + 'Transaction Failed' + ) foreignNonce++ console.log('\ninitializing Foreign Bridge Validators with following parameters:\n') @@ -74,7 +81,7 @@ async function deployForeign() { ) bridgeValidatorsForeign.options.address = storageValidatorsForeign.options.address const initializeForeignData = await bridgeValidatorsForeign.methods - .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, FOREIGN_OWNER_MULTISIG) + .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, FOREIGN_VALIDATORS_OWNER) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitializeForeign = await sendRawTxForeign({ data: initializeForeignData, @@ -83,12 +90,12 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitializeForeign.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitializeForeign.status), 1, 'Transaction Failed') foreignNonce++ console.log('\nTransferring ownership of ValidatorsProxy\n') const validatorsForeignOwnershipData = await storageValidatorsForeign.methods - .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS) + .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txValidatorsForeignOwnershipData = await sendRawTxForeign({ data: validatorsForeignOwnershipData, @@ -97,7 +104,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txValidatorsForeignOwnershipData.status), 1, 'Transaction Failed') + assert.strictEqual( + Web3Utils.hexToNumber(txValidatorsForeignOwnershipData.status), + 1, + 'Transaction Failed' + ) foreignNonce++ console.log('\ndeploying foreignBridge storage\n') @@ -132,7 +143,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToForeignBridge.status), 1, 'Transaction Failed') + assert.strictEqual( + Web3Utils.hexToNumber(txUpgradeToForeignBridge.status), + 1, + 'Transaction Failed' + ) foreignNonce++ console.log('\ninitializing Foreign Bridge with following parameters:\n') @@ -144,7 +159,11 @@ async function deployForeign() { storageValidatorsForeign.options.address, ERC20_TOKEN_ADDRESS, FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS, - FOREIGN_GAS_PRICE + FOREIGN_GAS_PRICE, + FOREIGN_MAX_AMOUNT_PER_TX, + HOME_DAILY_LIMIT, + HOME_MAX_AMOUNT_PER_TX, + FOREIGN_BRIDGE_OWNER ) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitializeBridge = await sendRawTxForeign({ @@ -154,11 +173,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitializeBridge.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitializeBridge.status), 1, 'Transaction Failed') foreignNonce++ const bridgeOwnershipData = await foreignBridgeStorage.methods - .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN_BRIDGE) + .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txBridgeOwnershipData = await sendRawTxForeign({ data: bridgeOwnershipData, @@ -167,7 +186,7 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txBridgeOwnershipData.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txBridgeOwnershipData.status), 1, 'Transaction Failed') foreignNonce++ console.log('\nForeign Deployment Bridge completed\n') diff --git a/deploy/src/erc_to_native/home.js b/deploy/src/erc_to_native/home.js index 554d5fa37..2040b953a 100644 --- a/deploy/src/erc_to_native/home.js +++ b/deploy/src/erc_to_native/home.js @@ -16,13 +16,15 @@ const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY, REQUIRED_NUMBER_OF_VALIDATORS, HOME_GAS_PRICE, - HOME_OWNER_MULTISIG, - HOME_UPGRADEABLE_ADMIN_VALIDATORS, - HOME_UPGRADEABLE_ADMIN_BRIDGE, + HOME_BRIDGE_OWNER, + HOME_VALIDATORS_OWNER, + HOME_UPGRADEABLE_ADMIN, HOME_DAILY_LIMIT, HOME_MAX_AMOUNT_PER_TX, HOME_MIN_AMOUNT_PER_TX, - HOME_REQUIRED_BLOCK_CONFIRMATIONS + HOME_REQUIRED_BLOCK_CONFIRMATIONS, + FOREIGN_DAILY_LIMIT, + FOREIGN_MAX_AMOUNT_PER_TX } = env const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) @@ -56,7 +58,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToBridgeVHome.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txUpgradeToBridgeVHome.status), 1, 'Transaction Failed') homeNonce++ console.log('\ninitializing Home Bridge Validators with following parameters:\n') @@ -65,7 +67,7 @@ async function deployHome() { ) bridgeValidatorsHome.options.address = storageValidatorsHome.options.address const initializeData = await bridgeValidatorsHome.methods - .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, HOME_OWNER_MULTISIG) + .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, HOME_VALIDATORS_OWNER) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitialize = await sendRawTxHome({ data: initializeData, @@ -74,12 +76,12 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitialize.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitialize.status), 1, 'Transaction Failed') homeNonce++ console.log('transferring proxy ownership to multisig for Validators Proxy contract') const proxyDataTransfer = await storageValidatorsHome.methods - .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN_VALIDATORS) + .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN) .encodeABI() const txProxyDataTransfer = await sendRawTxHome({ data: proxyDataTransfer, @@ -88,7 +90,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txProxyDataTransfer.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txProxyDataTransfer.status), 1, 'Transaction Failed') homeNonce++ console.log('\ndeploying homeBridge storage\n') @@ -118,7 +120,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToHomeBridge.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txUpgradeToHomeBridge.status), 1, 'Transaction Failed') homeNonce++ console.log('\ninitializing Home Bridge with following parameters:\n') @@ -140,7 +142,10 @@ async function deployHome() { HOME_MIN_AMOUNT_PER_TX, HOME_GAS_PRICE, HOME_REQUIRED_BLOCK_CONFIRMATIONS, - BLOCK_REWARD_ADDRESS + BLOCK_REWARD_ADDRESS, + FOREIGN_DAILY_LIMIT, + FOREIGN_MAX_AMOUNT_PER_TX, + HOME_BRIDGE_OWNER ) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitializeHomeBridge = await sendRawTxHome({ @@ -150,12 +155,12 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitializeHomeBridge.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitializeHomeBridge.status), 1, 'Transaction Failed') homeNonce++ console.log('transferring proxy ownership to multisig for Home bridge Proxy contract') const homeBridgeProxyData = await homeBridgeStorage.methods - .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN_BRIDGE) + .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN) .encodeABI() const txhomeBridgeProxyData = await sendRawTxHome({ data: homeBridgeProxyData, @@ -164,7 +169,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txhomeBridgeProxyData.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txhomeBridgeProxyData.status), 1, 'Transaction Failed') homeNonce++ console.log('\nHome Deployment Bridge completed\n') diff --git a/deploy/src/loadEnv.js b/deploy/src/loadEnv.js index 2645a0568..21d5f9fe8 100644 --- a/deploy/src/loadEnv.js +++ b/deploy/src/loadEnv.js @@ -35,18 +35,18 @@ let validations = { FOREIGN_DEPLOYMENT_GAS_PRICE: bigNumValidator(), GET_RECEIPT_INTERVAL_IN_MILLISECONDS: bigNumValidator(), HOME_RPC_URL: envalid.str(), - HOME_OWNER_MULTISIG: addressValidator(), - HOME_UPGRADEABLE_ADMIN_VALIDATORS: addressesValidator(), - HOME_UPGRADEABLE_ADMIN_BRIDGE: addressValidator(), + HOME_BRIDGE_OWNER: addressValidator(), + HOME_VALIDATORS_OWNER: addressesValidator(), + HOME_UPGRADEABLE_ADMIN: addressValidator(), HOME_DAILY_LIMIT: bigNumValidator(), HOME_MAX_AMOUNT_PER_TX: bigNumValidator(), HOME_MIN_AMOUNT_PER_TX: bigNumValidator(), HOME_REQUIRED_BLOCK_CONFIRMATIONS: envalid.num(), HOME_GAS_PRICE: bigNumValidator(), FOREIGN_RPC_URL: envalid.str(), - FOREIGN_OWNER_MULTISIG: addressValidator(), - FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS: addressValidator(), - FOREIGN_UPGRADEABLE_ADMIN_BRIDGE: addressValidator(), + FOREIGN_BRIDGE_OWNER: addressValidator(), + FOREIGN_VALIDATORS_OWNER: addressValidator(), + FOREIGN_UPGRADEABLE_ADMIN: addressValidator(), FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS: envalid.num(), FOREIGN_GAS_PRICE: bigNumValidator(), REQUIRED_NUMBER_OF_VALIDATORS: envalid.num(), diff --git a/deploy/src/native_to_erc/foreign.js b/deploy/src/native_to_erc/foreign.js index dfd1877d0..39202dc81 100644 --- a/deploy/src/native_to_erc/foreign.js +++ b/deploy/src/native_to_erc/foreign.js @@ -16,16 +16,18 @@ const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY, REQUIRED_NUMBER_OF_VALIDATORS, FOREIGN_GAS_PRICE, - FOREIGN_OWNER_MULTISIG, - FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS, - FOREIGN_UPGRADEABLE_ADMIN_BRIDGE, + FOREIGN_BRIDGE_OWNER, + FOREIGN_VALIDATORS_OWNER, + FOREIGN_UPGRADEABLE_ADMIN, FOREIGN_DAILY_LIMIT, FOREIGN_MAX_AMOUNT_PER_TX, FOREIGN_MIN_AMOUNT_PER_TX, FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS, BRIDGEABLE_TOKEN_NAME, BRIDGEABLE_TOKEN_SYMBOL, - BRIDGEABLE_TOKEN_DECIMALS + BRIDGEABLE_TOKEN_DECIMALS, + HOME_DAILY_LIMIT, + HOME_MAX_AMOUNT_PER_TX } = env const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) @@ -77,7 +79,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToBridgeVForeign.status), 1, 'Transaction Failed') + assert.strictEqual( + Web3Utils.hexToNumber(txUpgradeToBridgeVForeign.status), + 1, + 'Transaction Failed' + ) foreignNonce++ console.log('\ninitializing Foreign Bridge Validators with following parameters:\n') @@ -86,7 +92,7 @@ async function deployForeign() { ) bridgeValidatorsForeign.options.address = storageValidatorsForeign.options.address const initializeForeignData = await bridgeValidatorsForeign.methods - .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, FOREIGN_OWNER_MULTISIG) + .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, FOREIGN_VALIDATORS_OWNER) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitializeForeign = await sendRawTxForeign({ data: initializeForeignData, @@ -95,12 +101,12 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitializeForeign.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitializeForeign.status), 1, 'Transaction Failed') foreignNonce++ console.log('\nTransferring ownership of ValidatorsProxy\n') const validatorsForeignOwnershipData = await storageValidatorsForeign.methods - .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS) + .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txValidatorsForeignOwnershipData = await sendRawTxForeign({ data: validatorsForeignOwnershipData, @@ -109,7 +115,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txValidatorsForeignOwnershipData.status), 1, 'Transaction Failed') + assert.strictEqual( + Web3Utils.hexToNumber(txValidatorsForeignOwnershipData.status), + 1, + 'Transaction Failed' + ) foreignNonce++ console.log('\ndeploying foreignBridge storage\n') @@ -144,7 +154,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToForeignBridge.status), 1, 'Transaction Failed') + assert.strictEqual( + Web3Utils.hexToNumber(txUpgradeToForeignBridge.status), + 1, + 'Transaction Failed' + ) foreignNonce++ console.log('\ninitializing Foreign Bridge with following parameters:\n') @@ -168,7 +182,10 @@ async function deployForeign() { FOREIGN_MAX_AMOUNT_PER_TX, FOREIGN_MIN_AMOUNT_PER_TX, FOREIGN_GAS_PRICE, - FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS + FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS, + HOME_DAILY_LIMIT, + HOME_MAX_AMOUNT_PER_TX, + FOREIGN_BRIDGE_OWNER ) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitializeBridge = await sendRawTxForeign({ @@ -178,7 +195,7 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitializeBridge.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitializeBridge.status), 1, 'Transaction Failed') foreignNonce++ console.log('\nset bridge contract on ERC677BridgeToken') @@ -192,7 +209,7 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(setBridgeContract.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(setBridgeContract.status), 1, 'Transaction Failed') foreignNonce++ console.log('transferring ownership of ERC677BridgeToken token to foreignBridge contract') @@ -206,11 +223,11 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txOwnership.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txOwnership.status), 1, 'Transaction Failed') foreignNonce++ const bridgeOwnershipData = await foreignBridgeStorage.methods - .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN_BRIDGE) + .transferProxyOwnership(FOREIGN_UPGRADEABLE_ADMIN) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txBridgeOwnershipData = await sendRawTxForeign({ data: bridgeOwnershipData, @@ -219,7 +236,7 @@ async function deployForeign() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txBridgeOwnershipData.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txBridgeOwnershipData.status), 1, 'Transaction Failed') foreignNonce++ console.log('\nForeign Deployment Bridge completed\n') diff --git a/deploy/src/native_to_erc/home.js b/deploy/src/native_to_erc/home.js index 3d6bf828f..a8002587d 100644 --- a/deploy/src/native_to_erc/home.js +++ b/deploy/src/native_to_erc/home.js @@ -15,13 +15,15 @@ const { DEPLOYMENT_ACCOUNT_PRIVATE_KEY, REQUIRED_NUMBER_OF_VALIDATORS, HOME_GAS_PRICE, - HOME_OWNER_MULTISIG, - HOME_UPGRADEABLE_ADMIN_VALIDATORS, - HOME_UPGRADEABLE_ADMIN_BRIDGE, + HOME_BRIDGE_OWNER, + HOME_VALIDATORS_OWNER, + HOME_UPGRADEABLE_ADMIN, HOME_DAILY_LIMIT, HOME_MAX_AMOUNT_PER_TX, HOME_MIN_AMOUNT_PER_TX, - HOME_REQUIRED_BLOCK_CONFIRMATIONS + HOME_REQUIRED_BLOCK_CONFIRMATIONS, + FOREIGN_DAILY_LIMIT, + FOREIGN_MAX_AMOUNT_PER_TX } = env const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY) @@ -55,7 +57,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToBridgeVHome.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txUpgradeToBridgeVHome.status), 1, 'Transaction Failed') homeNonce++ console.log('\ninitializing Home Bridge Validators with following parameters:\n') @@ -64,7 +66,7 @@ async function deployHome() { ) bridgeValidatorsHome.options.address = storageValidatorsHome.options.address const initializeData = await bridgeValidatorsHome.methods - .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, HOME_OWNER_MULTISIG) + .initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, HOME_VALIDATORS_OWNER) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitialize = await sendRawTxHome({ data: initializeData, @@ -73,12 +75,12 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitialize.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitialize.status), 1, 'Transaction Failed') homeNonce++ console.log('transferring proxy ownership to multisig for Validators Proxy contract') const proxyDataTransfer = await storageValidatorsHome.methods - .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN_VALIDATORS) + .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN) .encodeABI() const txProxyDataTransfer = await sendRawTxHome({ data: proxyDataTransfer, @@ -87,7 +89,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txProxyDataTransfer.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txProxyDataTransfer.status), 1, 'Transaction Failed') homeNonce++ console.log('\ndeploying homeBridge storage\n') @@ -117,7 +119,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txUpgradeToHomeBridge.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txUpgradeToHomeBridge.status), 1, 'Transaction Failed') homeNonce++ console.log('\ninitializing Home Bridge with following parameters:\n') @@ -139,7 +141,10 @@ async function deployHome() { HOME_MAX_AMOUNT_PER_TX, HOME_MIN_AMOUNT_PER_TX, HOME_GAS_PRICE, - HOME_REQUIRED_BLOCK_CONFIRMATIONS + HOME_REQUIRED_BLOCK_CONFIRMATIONS, + FOREIGN_DAILY_LIMIT, + FOREIGN_MAX_AMOUNT_PER_TX, + HOME_BRIDGE_OWNER ) .encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS }) const txInitializeHomeBridge = await sendRawTxHome({ @@ -149,12 +154,12 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txInitializeHomeBridge.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txInitializeHomeBridge.status), 1, 'Transaction Failed') homeNonce++ console.log('transferring proxy ownership to multisig for Home bridge Proxy contract') const homeBridgeProxyData = await homeBridgeStorage.methods - .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN_BRIDGE) + .transferProxyOwnership(HOME_UPGRADEABLE_ADMIN) .encodeABI() const txhomeBridgeProxyData = await sendRawTxHome({ data: homeBridgeProxyData, @@ -163,7 +168,7 @@ async function deployHome() { privateKey: deploymentPrivateKey, url: HOME_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txhomeBridgeProxyData.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txhomeBridgeProxyData.status), 1, 'Transaction Failed') homeNonce++ console.log('\nHome Deployment Bridge completed\n') diff --git a/deploy/src/utils/deployERC20Token.js b/deploy/src/utils/deployERC20Token.js index 4e2f73095..f18922397 100644 --- a/deploy/src/utils/deployERC20Token.js +++ b/deploy/src/utils/deployERC20Token.js @@ -38,11 +38,11 @@ async function deployToken() { privateKey: deploymentPrivateKey, url: FOREIGN_RPC_URL }) - assert.equal(Web3Utils.hexToNumber(txMint.status), 1, 'Transaction Failed') + assert.strictEqual(Web3Utils.hexToNumber(txMint.status), 1, 'Transaction Failed') console.log('\nToken deployment is completed\n') return { - erc677tokenAddress: erc677token.options.address, + erc677tokenAddress: erc677token.options.address } } module.exports = deployToken diff --git a/deploy/testenv-deploy.js b/deploy/testenv-deploy.js index 6571f2797..9c4316bcb 100644 --- a/deploy/testenv-deploy.js +++ b/deploy/testenv-deploy.js @@ -1,11 +1,9 @@ -const env = require('./src/loadEnv') - const deployToken = require('./src/utils/deployERC20Token') const mode = process.argv[2] async function main() { - switch(mode) { + switch (mode) { case 'token': await deployToken() break diff --git a/test/erc_to_erc/foreign_bridge.test.js b/test/erc_to_erc/foreign_bridge.test.js index c121f5ead..a6564e59d 100644 --- a/test/erc_to_erc/foreign_bridge.test.js +++ b/test/erc_to_erc/foreign_bridge.test.js @@ -9,6 +9,10 @@ const {createMessage, sign, signatureToVRS} = require('../helpers/helpers'); const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether")); const requireBlockConfirmations = 8; const gasPrice = web3.toWei('1', 'gwei') +const oneEther = web3.toBigNumber(web3.toWei(1, "ether")); +const homeDailyLimit = oneEther +const homeMaxPerTx = halfEther +const maxPerTx = halfEther contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => { let validatorContract, authorities, owner, token; @@ -30,16 +34,16 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => { false.should.be.equal(await foreignBridge.isInitialized()) '0'.should.be.bignumber.equal(await foreignBridge.requiredBlockConfirmations()) - await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations).should.be.rejectedWith(INVALID_ARGUMENTS); + await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, owner).should.be.rejectedWith(INVALID_ARGUMENTS); - await foreignBridge.initialize(ZERO_ADDRESS, token.address, requireBlockConfirmations, gasPrice).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, ZERO_ADDRESS, requireBlockConfirmations, gasPrice).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, owner, requireBlockConfirmations, gasPrice).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, token.address, 0, gasPrice).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, 0).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(owner, token.address, requireBlockConfirmations, gasPrice).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(ZERO_ADDRESS, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, ZERO_ADDRESS, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, owner, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, token.address, 0, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, 0, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(owner, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice); + await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner); token.address.should.be.equal(await foreignBridge.erc20token()); true.should.be.equal(await foreignBridge.isInitialized()) @@ -60,10 +64,11 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => { }) describe('#executeSignatures', async () => { var value = web3.toBigNumber(web3.toWei(0.25, "ether")); + let foreignBridge beforeEach(async () => { foreignBridge = await ForeignBridge.new() token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18); - await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice); + await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner); await token.mint(foreignBridge.address,value); }) it('should allow to executeSignatures', async () => { @@ -133,6 +138,45 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => { true.should.be.equal(await foreignBridge.relayedMessages(transactionHash)) await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message2).should.be.rejectedWith(ERROR_MSG) }) + + it('should not allow withdraw over home max tx limit', async () => { + const recipientAccount = accounts[3]; + const invalidValue = web3.toBigNumber(web3.toWei(0.75, "ether")); + await token.mint(foreignBridge.address, web3.toBigNumber(web3.toWei(5, "ether"))); + + const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + const message = createMessage(recipientAccount, invalidValue, transactionHash, foreignBridge.address); + const signature = await sign(authorities[0], message) + const vrs = signatureToVRS(signature); + + await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.rejectedWith(ERROR_MSG) + }) + + it('should not allow withdraw over daily home limit', async () => { + const recipientAccount = accounts[3]; + await token.mint(foreignBridge.address, web3.toBigNumber(web3.toWei(5, "ether"))); + + const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + const message = createMessage(recipientAccount, halfEther, transactionHash, foreignBridge.address); + const signature = await sign(authorities[0], message) + const vrs = signatureToVRS(signature); + + await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled + + const transactionHash2 = "0x69debd8fd1923c9cb3cd8ef6461e2740b2d037943b941729d5a47671a2bb8712"; + const message2 = createMessage(recipientAccount, halfEther, transactionHash2, foreignBridge.address); + const signature2 = await sign(authorities[0], message2) + const vrs2 = signatureToVRS(signature2); + + await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.fulfilled + + const transactionHash3 = "0x022695428093bb292db8e48bd1417c5e1b84c0bf673bd0fff23ed0fb6495b872"; + const message3 = createMessage(recipientAccount, halfEther, transactionHash3, foreignBridge.address); + const signature3 = await sign(authorities[0], message3) + const vrs3 = signatureToVRS(signature3); + + await foreignBridge.executeSignatures([vrs3.v], [vrs3.r], [vrs3.s], message3).should.be.rejectedWith(ERROR_MSG) + }) }) describe('#withdraw with 2 minimum signatures', async () => { @@ -147,7 +191,7 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => { await multisigValidatorContract.initialize(2, twoAuthorities, ownerOfValidatorContract, {from: ownerOfValidatorContract}) foreignBridgeWithMultiSignatures = await ForeignBridge.new() const oneEther = web3.toBigNumber(web3.toWei(1, "ether")); - await foreignBridgeWithMultiSignatures.initialize(multisigValidatorContract.address, token.address, requireBlockConfirmations, gasPrice, {from: ownerOfValidatorContract}); + await foreignBridgeWithMultiSignatures.initialize(multisigValidatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner, {from: ownerOfValidatorContract}); await token.mint(foreignBridgeWithMultiSignatures.address,value); }) it('withdraw should fail if not enough signatures are provided', async () => { @@ -191,7 +235,7 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => { const value = web3.toBigNumber(web3.toWei(0.5, "ether")); const foreignBridgeWithThreeSigs = await ForeignBridge.new() - await foreignBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, erc20Token.address, requireBlockConfirmations, gasPrice); + await foreignBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, erc20Token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner); await erc20Token.mint(foreignBridgeWithThreeSigs.address, value); const txHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; @@ -240,7 +284,7 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => { await foreignBridgeProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled; foreignBridgeProxy = await ForeignBridge.at(foreignBridgeProxy.address); - await foreignBridgeProxy.initialize(validatorsProxy.address, token.address, requireBlockConfirmations, gasPrice) + await foreignBridgeProxy.initialize(validatorsProxy.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner) // Deploy V2 let foreignImplV2 = await ForeignBridgeV2.new(); @@ -260,7 +304,7 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => { let storageProxy = await EternalStorageProxy.new().should.be.fulfilled; let foreignBridge = await ForeignBridge.new(); let data = foreignBridge.initialize.request( - validatorsAddress, tokenAddress, requireBlockConfirmations, gasPrice).params[0].data + validatorsAddress, tokenAddress, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).params[0].data await storageProxy.upgradeToAndCall('1', foreignBridge.address, data).should.be.fulfilled; let finalContract = await ForeignBridge.at(storageProxy.address); true.should.be.equal(await finalContract.isInitialized()); @@ -272,8 +316,11 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => { it('can send erc20', async () => { const owner = accounts[0]; token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18); - foreignBridge = await ForeignBridge.new(); - await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice); + const foreignBridgeImpl = await ForeignBridge.new(); + const storageProxy = await EternalStorageProxy.new().should.be.fulfilled; + await storageProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled + const foreignBridge = await ForeignBridge.at(storageProxy.address); + await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner); let tokenSecond = await ERC677BridgeToken.new("Roman Token", "RST", 18); diff --git a/test/erc_to_erc/home_bridge.test.js b/test/erc_to_erc/home_bridge.test.js index 512fab1ca..25805ce42 100644 --- a/test/erc_to_erc/home_bridge.test.js +++ b/test/erc_to_erc/home_bridge.test.js @@ -10,6 +10,8 @@ const requireBlockConfirmations = 8; const gasPrice = Web3Utils.toWei('1', 'gwei'); const oneEther = web3.toBigNumber(web3.toWei(1, "ether")); const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether")); +const foreignDailyLimit = oneEther +const foreignMaxPerTx = halfEther contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { @@ -31,7 +33,7 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { '0'.should.be.bignumber.equal(await homeContract.dailyLimit()) '0'.should.be.bignumber.equal(await homeContract.maxPerTx()) false.should.be.equal(await homeContract.isInitialized()) - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address).should.be.fulfilled; + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.fulfilled; true.should.be.equal(await homeContract.isInitialized()) validatorContract.address.should.be.equal(await homeContract.validatorContract()); (await homeContract.deployedAtBlock()).should.be.bignumber.above(0); @@ -48,14 +50,14 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { }) it('cant set maxPerTx > dailyLimit', async () => { false.should.be.equal(await homeContract.isInitialized()) - await homeContract.initialize(validatorContract.address, '1', '2', '1', gasPrice, requireBlockConfirmations, token.address).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(validatorContract.address, '3', '2', '2', gasPrice, requireBlockConfirmations, token.address).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '1', '2', '1', gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '3', '2', '2', gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); false.should.be.equal(await homeContract.isInitialized()) }) it('can be deployed via upgradeToAndCall', async () => { let storageProxy = await EternalStorageProxy.new().should.be.fulfilled; - let data = homeContract.initialize.request(validatorContract.address, "3", "2", "1", gasPrice, requireBlockConfirmations, token.address).params[0].data + let data = homeContract.initialize.request(validatorContract.address, "3", "2", "1", gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner).params[0].data await storageProxy.upgradeToAndCall('1', homeContract.address, data).should.be.fulfilled; let finalContract = await HomeBridge.at(storageProxy.address); true.should.be.equal(await finalContract.isInitialized()); @@ -67,13 +69,14 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { it('cant initialize with invalid arguments', async () => { false.should.be.equal(await homeContract.isInitialized()) - await homeContract.initialize(validatorContract.address, '3', '2', '1', 0, requireBlockConfirmations, token.address).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, 0, token.address).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(owner, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(ZERO_ADDRESS, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, owner).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address).should.be.fulfilled; + await homeContract.initialize(validatorContract.address, '3', '2', '1', 0, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, 0, token.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(owner, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(ZERO_ADDRESS, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, ZERO_ADDRESS, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, owner, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address, halfEther, oneEther, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.fulfilled; true.should.be.equal(await homeContract.isInitialized()) }) }) @@ -82,7 +85,7 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { beforeEach(async () => { homeContract = await HomeBridge.new() token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18); - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address) + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner) }) it('reverts', async () => { const {logs} = await homeContract.sendTransaction({ @@ -97,7 +100,7 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { beforeEach(async () => { homeContract = await HomeBridge.new() token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18); - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address) + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner) }) it('#setMaxPerTx allows to set only to owner and cannot be more than daily limit', async () => { await homeContract.setMaxPerTx(2, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG); @@ -119,7 +122,7 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { beforeEach(async () => { homeBridge = await HomeBridge.new(); token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18); - await homeBridge.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address); + await homeBridge.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner); await token.transferOwnership(homeBridge.address); }) it('should allow validator to withdraw', async () => { @@ -159,7 +162,7 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { let ownerOfValidators = accounts[0] await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators) let homeBridgeWithTwoSigs = await HomeBridge.new(); - await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token2sig.address); + await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token2sig.address, foreignDailyLimit, foreignMaxPerTx, owner); await token2sig.transferOwnership(homeBridgeWithTwoSigs.address); const recipient = accounts[5]; const value = halfEther; @@ -222,7 +225,7 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { let ownerOfValidators = accounts[0] await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators) let homeBridgeWithTwoSigs = await HomeBridge.new(); - await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token2sig.address); + await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token2sig.address, foreignDailyLimit, foreignMaxPerTx, owner); await token2sig.transferOwnership(homeBridgeWithTwoSigs.address); const recipient = accounts[5]; const value = halfEther.div(2); @@ -249,7 +252,7 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { const token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18); const homeBridgeWithThreeSigs = await HomeBridge.new(); - await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address); + await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner); await token.transferOwnership(homeBridgeWithThreeSigs.address); const value = web3.toBigNumber(web3.toWei(0.5, "ether")); @@ -272,6 +275,95 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { transactionHash }) }) + it('should not allow execute affirmation over foreign max tx limit', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const {logs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled; + + logs[0].event.should.be.equal("AmountLimitExceeded"); + logs[0].args.should.be.deep.equal({ + recipient, + value, + transactionHash + }); + }) + it('should fail if txHash already set as above of limits', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const {logs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled; + + logs[0].event.should.be.equal("AmountLimitExceeded"); + logs[0].args.should.be.deep.equal({ + recipient, + value, + transactionHash + }); + + await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG) + await homeBridge.executeAffirmation(accounts[6], value, transactionHash, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG) + }) + it('should not allow execute affirmation over daily foreign limit', async () => { + const recipient = accounts[5]; + const value = halfEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const { logs } = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled; + + logs[0].event.should.be.equal("SignedForAffirmation"); + logs[0].args.should.be.deep.equal({ + signer: authorities[0], + transactionHash + }); + logs[1].event.should.be.equal("AffirmationCompleted"); + logs[1].args.should.be.deep.equal({ + recipient, + value, + transactionHash + }) + + const transactionHash2 = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + const { logs: logs2 } = await homeBridge.executeAffirmation(recipient, value, transactionHash2, {from: authorities[0]}).should.be.fulfilled; + + logs2[0].event.should.be.equal("SignedForAffirmation"); + logs2[0].args.should.be.deep.equal({ + signer: authorities[0], + transactionHash: transactionHash2 + }); + logs2[1].event.should.be.equal("AffirmationCompleted"); + logs2[1].args.should.be.deep.equal({ + recipient, + value, + transactionHash: transactionHash2 + }) + + const transactionHash3 = "0x69debd8fd1923c9cb3cd8ef6461e2740b2d037943b941729d5a47671a2bb8712"; + const { logs: logs3 } = await homeBridge.executeAffirmation(recipient, value, transactionHash3, {from: authorities[0]}).should.be.fulfilled; + + logs3[0].event.should.be.equal("AmountLimitExceeded"); + logs3[0].args.should.be.deep.equal({ + recipient, + value, + transactionHash: transactionHash3 + }); + + const outOfLimitAmount = await homeBridge.outOfLimitAmount() + + outOfLimitAmount.should.be.bignumber.equal(halfEther) + + const transactionHash4 = "0xc9ffe298d85ec5c515153608924b7bdcf1835539813dcc82cdbcc071170c3196"; + const { logs: logs4 } = await homeBridge.executeAffirmation(recipient, value, transactionHash4, {from: authorities[0]}).should.be.fulfilled; + + logs4[0].event.should.be.equal("AmountLimitExceeded"); + logs4[0].args.should.be.deep.equal({ + recipient, + value, + transactionHash: transactionHash4 + }); + + const newOutOfLimitAmount = await homeBridge.outOfLimitAmount() + newOutOfLimitAmount.should.be.bignumber.equal(oneEther) + }) }) describe('#isAlreadyProcessed', async () => { it('returns ', async () => { @@ -293,7 +385,7 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { ownerOfValidators = accounts[0] await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators) homeBridgeWithTwoSigs = await HomeBridge.new(); - await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token2sig.address); + await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token2sig.address, foreignDailyLimit, foreignMaxPerTx, owner); await token2sig.transferOwnership(homeBridgeWithTwoSigs.address); }) it('allows a validator to submit a signature', async () => { @@ -343,7 +435,7 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { const token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18); const homeBridgeWithThreeSigs = await HomeBridge.new(); - await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address); + await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner); const value = web3.toBigNumber(web3.toWei(0.5, "ether")); const transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; @@ -411,4 +503,120 @@ contract('HomeBridge_ERC20_to_ERC20', async (accounts) => { '104'.should.be.bignumber.equal(requiredMessageLength) }) }) + + describe('#fixAssetsAboveLimits', async () => { + let homeBridge; + const zeroValue = web3.toBigNumber(web3.toWei(0, "ether")) + beforeEach(async () => { + const homeBridgeImpl = await HomeBridge.new(); + const storageProxy = await EternalStorageProxy.new().should.be.fulfilled; + await storageProxy.upgradeTo('1', homeBridgeImpl.address).should.be.fulfilled + homeBridge = await HomeBridge.at(storageProxy.address); + await homeBridge.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.fulfilled + }) + it('Should reduce outOfLimitAmount and not emit any event', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const {logs: affirmationLogs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled + + affirmationLogs[0].event.should.be.equal("AmountLimitExceeded"); + + const outOfLimitAmount = await homeBridge.outOfLimitAmount() + outOfLimitAmount.should.be.bignumber.equal(value) + + const { logs } = await homeBridge.fixAssetsAboveLimits(transactionHash, false).should.be.fulfilled + + logs.length.should.be.equal(0) + + const newOutOfLimitAmount = await homeBridge.outOfLimitAmount() + newOutOfLimitAmount.should.be.bignumber.equal(zeroValue) + }) + it('Should reduce outOfLimitAmount and emit UserRequestForSignature', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const {logs: affirmationLogs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled + + affirmationLogs[0].event.should.be.equal("AmountLimitExceeded"); + + const outOfLimitAmount = await homeBridge.outOfLimitAmount() + outOfLimitAmount.should.be.bignumber.equal(value) + + const { logs } = await homeBridge.fixAssetsAboveLimits(transactionHash, true).should.be.fulfilled + + logs.length.should.be.equal(1) + logs[0].event.should.be.equal('UserRequestForSignature') + logs[0].args.should.be.deep.equal({ + recipient, + value + }) + + const newOutOfLimitAmount = await homeBridge.outOfLimitAmount() + newOutOfLimitAmount.should.be.bignumber.equal(zeroValue) + }) + it('Should not be allow to be called by an already fixed txHash', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const transactionHash2 = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + + await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled + await homeBridge.executeAffirmation(recipient, value, transactionHash2, {from: authorities[0]}).should.be.fulfilled + + const outOfLimitAmount = await homeBridge.outOfLimitAmount() + outOfLimitAmount.should.be.bignumber.equal(value.add(value)) + + await homeBridge.fixAssetsAboveLimits(transactionHash, false).should.be.fulfilled + + const newOutOfLimitAmount = await homeBridge.outOfLimitAmount() + newOutOfLimitAmount.should.be.bignumber.equal(value) + + await homeBridge.fixAssetsAboveLimits(transactionHash, false).should.be.rejectedWith(ERROR_MSG) + await homeBridge.fixAssetsAboveLimits(transactionHash2, false).should.be.fulfilled + + const updatedOutOfLimitAmount = await homeBridge.outOfLimitAmount() + updatedOutOfLimitAmount.should.be.bignumber.equal(zeroValue) + + await homeBridge.fixAssetsAboveLimits(transactionHash2, false).should.be.rejectedWith(ERROR_MSG) + }) + it('Should fail if txHash didnt increase out of limit amount', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const invalidTxHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + + const {logs: affirmationLogs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled + + affirmationLogs[0].event.should.be.equal("AmountLimitExceeded"); + + await homeBridge.fixAssetsAboveLimits(invalidTxHash, true).should.be.rejectedWith(ERROR_MSG) + }) + it('Should fail if not called by proxyOwner', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + + const {logs: affirmationLogs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled + + affirmationLogs[0].event.should.be.equal("AmountLimitExceeded"); + + await homeBridge.fixAssetsAboveLimits(transactionHash, true, { from: recipient}).should.be.rejectedWith(ERROR_MSG) + await homeBridge.fixAssetsAboveLimits(transactionHash, true, { from: owner}).should.be.fulfilled + }) + }) + describe('#OwnedUpgradeability', async () => { + + it('upgradeabilityAdmin should return the proxy owner', async () => { + const homeBridgeImpl = await HomeBridge.new(); + const storageProxy = await EternalStorageProxy.new().should.be.fulfilled; + await storageProxy.upgradeTo('1', homeBridgeImpl.address).should.be.fulfilled + const homeBridge = await HomeBridge.at(storageProxy.address); + + const proxyOwner = await storageProxy.proxyOwner() + const upgradeabilityAdmin = await homeBridge.upgradeabilityAdmin() + + upgradeabilityAdmin.should.be.equal(proxyOwner) + }) + }) }) diff --git a/test/erc_to_native/foreign_bridge.test.js b/test/erc_to_native/foreign_bridge.test.js index fa49de156..b11a783e1 100644 --- a/test/erc_to_native/foreign_bridge.test.js +++ b/test/erc_to_native/foreign_bridge.test.js @@ -9,6 +9,10 @@ const { createMessage, sign, signatureToVRS } = require('../helpers/helpers'); const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether")); const requireBlockConfirmations = 8; const gasPrice = web3.toWei('1', 'gwei'); +const oneEther = web3.toBigNumber(web3.toWei(1, "ether")); +const homeDailyLimit = oneEther +const homeMaxPerTx = halfEther +const maxPerTx = halfEther contract('ForeignBridge_ERC20_to_Native', async (accounts) => { let validatorContract, authorities, owner, token; @@ -30,14 +34,15 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => { false.should.be.equal(await foreignBridge.isInitialized()) '0'.should.be.bignumber.equal(await foreignBridge.requiredBlockConfirmations()) - await foreignBridge.initialize(ZERO_ADDRESS, token.address, requireBlockConfirmations, gasPrice).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, ZERO_ADDRESS, requireBlockConfirmations, gasPrice).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, token.address, 0, gasPrice).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, 0).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, owner, requireBlockConfirmations, gasPrice).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(owner, token.address, requireBlockConfirmations, gasPrice).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(ZERO_ADDRESS, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, ZERO_ADDRESS, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, token.address, 0, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, 0, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, owner, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(owner, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, halfEther, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice); + await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner); token.address.should.be.equal(await foreignBridge.erc20token()); true.should.be.equal(await foreignBridge.isInitialized()) @@ -63,7 +68,7 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => { beforeEach(async () => { foreignBridge = await ForeignBridge.new() token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18); - await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice); + await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner); await token.mint(foreignBridge.address,value); }) @@ -143,6 +148,45 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => { await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.rejectedWith(ERROR_MSG) }) + + it('should not allow withdraw over home max tx limit', async () => { + const recipientAccount = accounts[3]; + const invalidValue = web3.toBigNumber(web3.toWei(0.75, "ether")); + await token.mint(foreignBridge.address, web3.toBigNumber(web3.toWei(5, "ether"))); + + const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + const message = createMessage(recipientAccount, invalidValue, transactionHash, foreignBridge.address); + const signature = await sign(authorities[0], message) + const vrs = signatureToVRS(signature); + + await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.rejectedWith(ERROR_MSG) + }) + + it('should not allow withdraw over daily home limit', async () => { + const recipientAccount = accounts[3]; + await token.mint(foreignBridge.address, web3.toBigNumber(web3.toWei(5, "ether"))); + + const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + const message = createMessage(recipientAccount, halfEther, transactionHash, foreignBridge.address); + const signature = await sign(authorities[0], message) + const vrs = signatureToVRS(signature); + + await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled + + const transactionHash2 = "0x69debd8fd1923c9cb3cd8ef6461e2740b2d037943b941729d5a47671a2bb8712"; + const message2 = createMessage(recipientAccount, halfEther, transactionHash2, foreignBridge.address); + const signature2 = await sign(authorities[0], message2) + const vrs2 = signatureToVRS(signature2); + + await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.fulfilled + + const transactionHash3 = "0x022695428093bb292db8e48bd1417c5e1b84c0bf673bd0fff23ed0fb6495b872"; + const message3 = createMessage(recipientAccount, halfEther, transactionHash3, foreignBridge.address); + const signature3 = await sign(authorities[0], message3) + const vrs3 = signatureToVRS(signature3); + + await foreignBridge.executeSignatures([vrs3.v], [vrs3.r], [vrs3.s], message3).should.be.rejectedWith(ERROR_MSG) + }) }) describe('#withdraw with 2 minimum signatures', async () => { @@ -155,7 +199,7 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => { ownerOfValidatorContract = accounts[3] await multisigValidatorContract.initialize(2, twoAuthorities, ownerOfValidatorContract, {from: ownerOfValidatorContract}) foreignBridgeWithMultiSignatures = await ForeignBridge.new() - await foreignBridgeWithMultiSignatures.initialize(multisigValidatorContract.address, token.address, requireBlockConfirmations, gasPrice, {from: ownerOfValidatorContract}); + await foreignBridgeWithMultiSignatures.initialize(multisigValidatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner, {from: ownerOfValidatorContract}); await token.mint(foreignBridgeWithMultiSignatures.address,value); }) @@ -203,7 +247,7 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => { const value = web3.toBigNumber(web3.toWei(0.5, "ether")); const foreignBridgeWithThreeSigs = await ForeignBridge.new() - await foreignBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, erc20Token.address, requireBlockConfirmations, gasPrice); + await foreignBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, erc20Token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner); await erc20Token.mint(foreignBridgeWithThreeSigs.address, value); const txHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; @@ -252,18 +296,13 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => { await foreignBridgeProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled; foreignBridgeProxy = await ForeignBridge.at(foreignBridgeProxy.address); - await foreignBridgeProxy.initialize(validatorsProxy.address, token.address, requireBlockConfirmations, gasPrice) + await foreignBridgeProxy.initialize(validatorsProxy.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner) // Deploy V2 let foreignImplV2 = await ForeignBridgeV2.new(); let foreignBridgeProxyUpgrade = await EternalStorageProxy.at(foreignBridgeProxy.address); await foreignBridgeProxyUpgrade.upgradeTo('2', foreignImplV2.address).should.be.fulfilled; foreignImplV2.address.should.be.equal(await foreignBridgeProxyUpgrade.implementation()) - - let foreignBridgeV2Proxy = await ForeignBridgeV2.at(foreignBridgeProxy.address) - await foreignBridgeV2Proxy.doSomething(accounts[2], {from: accounts[4]}).should.be.rejectedWith(ERROR_MSG) - await foreignBridgeV2Proxy.doSomething(accounts[2], {from: PROXY_OWNER}).should.be.fulfilled; - (await foreignBridgeV2Proxy.something()).should.be.equal(accounts[2]) }) it('can be deployed via upgradeToAndCall', async () => { @@ -272,7 +311,7 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => { const storageProxy = await EternalStorageProxy.new().should.be.fulfilled; const foreignBridge = await ForeignBridge.new(); - const data = foreignBridge.initialize.request(validatorsAddress, tokenAddress, requireBlockConfirmations, gasPrice).params[0].data + const data = foreignBridge.initialize.request(validatorsAddress, tokenAddress, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).params[0].data await storageProxy.upgradeToAndCall('1', foreignBridge.address, data).should.be.fulfilled; @@ -286,9 +325,12 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => { it('can send erc20', async () => { const owner = accounts[0]; token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18); - const foreignBridge = await ForeignBridge.new(); + const foreignBridgeImpl = await ForeignBridge.new(); + const storageProxy = await EternalStorageProxy.new().should.be.fulfilled; + await storageProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled + const foreignBridge = await ForeignBridge.at(storageProxy.address); - await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice); + await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner); const tokenSecond = await ERC677BridgeToken.new("Roman Token", "RST", 18); await tokenSecond.mint(accounts[0], halfEther).should.be.fulfilled; diff --git a/test/erc_to_native/home_bridge.test.js b/test/erc_to_native/home_bridge.test.js index a78e33062..9660f7b2d 100644 --- a/test/erc_to_native/home_bridge.test.js +++ b/test/erc_to_native/home_bridge.test.js @@ -10,6 +10,9 @@ const requireBlockConfirmations = 8; const gasPrice = Web3Utils.toWei('1', 'gwei'); const oneEther = web3.toBigNumber(web3.toWei(1, "ether")); const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether")); +const foreignDailyLimit = oneEther +const foreignMaxPerTx = halfEther + contract('HomeBridge_ERC20_to_Native', async (accounts) => { let homeContract, validatorContract, blockRewardContract, authorities, owner; @@ -33,7 +36,7 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { false.should.be.equal(await homeContract.isInitialized()) ZERO_ADDRESS.should.be.equal(await homeContract.blockRewardContract()) - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address).should.be.fulfilled + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.fulfilled true.should.be.equal(await homeContract.isInitialized()) validatorContract.address.should.be.equal(await homeContract.validatorContract()) @@ -56,7 +59,7 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { it('can update block reward contract', async () => { ZERO_ADDRESS.should.be.equal(await homeContract.blockRewardContract()) - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address).should.be.fulfilled + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.fulfilled blockRewardContract.address.should.be.equal(await homeContract.blockRewardContract()) @@ -79,15 +82,15 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { it('cant set maxPerTx > dailyLimit', async () => { false.should.be.equal(await homeContract.isInitialized()) - await homeContract.initialize(validatorContract.address, '1', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address).should.be.rejectedWith(ERROR_MSG) - await homeContract.initialize(validatorContract.address, '3', '2', '2', gasPrice, requireBlockConfirmations, blockRewardContract.address).should.be.rejectedWith(ERROR_MSG) + await homeContract.initialize(validatorContract.address, '1', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG) + await homeContract.initialize(validatorContract.address, '3', '2', '2', gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG) false.should.be.equal(await homeContract.isInitialized()) }) it('can be deployed via upgradeToAndCall', async () => { let storageProxy = await EternalStorageProxy.new().should.be.fulfilled; - let data = homeContract.initialize.request(validatorContract.address, "3", "2", "1", gasPrice, requireBlockConfirmations, blockRewardContract.address).params[0].data + let data = homeContract.initialize.request(validatorContract.address, "3", "2", "1", gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner).params[0].data await storageProxy.upgradeToAndCall('1', homeContract.address, data).should.be.fulfilled let finalContract = await HomeBridge.at(storageProxy.address); @@ -99,13 +102,44 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { "2".should.be.bignumber.equal(await finalContract.maxPerTx()) "1".should.be.bignumber.equal(await finalContract.minPerTx()) }) + it('can be upgraded keeping the state', async () => { + const homeOwner = accounts[8] + const storageProxy = await EternalStorageProxy.new().should.be.fulfilled; + const proxyOwner = await storageProxy.proxyOwner() + const data = homeContract.initialize.request(validatorContract.address, "3", "2", "1", gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, homeOwner).params[0].data + + await storageProxy.upgradeToAndCall('1', homeContract.address, data).should.be.fulfilled + const finalContract = await HomeBridge.at(storageProxy.address); + + true.should.be.equal(await finalContract.isInitialized()) + validatorContract.address.should.be.equal(await finalContract.validatorContract()) + blockRewardContract.address.should.be.equal(await finalContract.blockRewardContract()) + "3".should.be.bignumber.equal(await finalContract.dailyLimit()) + "2".should.be.bignumber.equal(await finalContract.maxPerTx()) + "1".should.be.bignumber.equal(await finalContract.minPerTx()) + const upgradeabilityAdmin = await finalContract.upgradeabilityAdmin() + upgradeabilityAdmin.should.be.equal(proxyOwner) + + const homeContractV2 = await HomeBridge.new() + await storageProxy.upgradeTo('2', homeContractV2.address).should.be.fulfilled + const finalContractV2 = await HomeBridge.at(storageProxy.address); + + validatorContract.address.should.be.equal(await finalContractV2.validatorContract()) + blockRewardContract.address.should.be.equal(await finalContractV2.blockRewardContract()) + "3".should.be.bignumber.equal(await finalContractV2.dailyLimit()) + "2".should.be.bignumber.equal(await finalContractV2.maxPerTx()) + "1".should.be.bignumber.equal(await finalContractV2.minPerTx()) + const upgradeabilityAdminV2 = await finalContractV2.upgradeabilityAdmin() + upgradeabilityAdminV2.should.be.equal(proxyOwner) + }) it('cant initialize with invalid arguments', async () => { false.should.be.equal(await homeContract.isInitialized()) - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, 0, blockRewardContract.address).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(owner, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(ZERO_ADDRESS, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, owner).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address).should.be.fulfilled; + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, 0, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(owner, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(ZERO_ADDRESS, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, owner, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address, halfEther, oneEther, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner).should.be.fulfilled; true.should.be.equal(await homeContract.isInitialized()) }) }) @@ -113,7 +147,7 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { describe('#fallback', async () => { beforeEach(async () => { homeContract = await HomeBridge.new() - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address) + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner) }) it('should accept native coins', async () => { @@ -244,13 +278,15 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { let homeContract; beforeEach(async () => { homeContract = await HomeBridge.new() - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address) + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner) }) it('setMaxPerTx allows to set only to owner and cannot be more than daily limit', async () => { await homeContract.setMaxPerTx(2, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG); await homeContract.setMaxPerTx(2, {from: owner}).should.be.fulfilled; await homeContract.setMaxPerTx(3, {from: owner}).should.be.rejectedWith(ERROR_MSG); + const maxPerTx = await homeContract.maxPerTx() + maxPerTx.should.be.bignumber.equal(web3.toBigNumber(2)) }) it('setMinPerTx allows to set only to owner and cannot be more than daily limit and should be less than maxPerTx', async () => { @@ -258,6 +294,37 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { await homeContract.setMinPerTx(1, {from: owner}).should.be.fulfilled; await homeContract.setMinPerTx(2, {from: owner}).should.be.rejectedWith(ERROR_MSG); + const minPerTx = await homeContract.minPerTx() + minPerTx.should.be.bignumber.equal(web3.toBigNumber(1)) + }) + + it('setExecutionMaxPerTx allows to set only to owner and cannot be more than execution daily limit', async () => { + const newValue = web3.toBigNumber(web3.toWei(0.3, "ether")); + + const initialExecutionMaxPerTx = await homeContract.executionMaxPerTx() + + initialExecutionMaxPerTx.should.be.bignumber.not.equal(newValue) + + await homeContract.setExecutionMaxPerTx(newValue, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG); + await homeContract.setExecutionMaxPerTx(newValue, {from: owner}).should.be.fulfilled; + + await homeContract.setExecutionMaxPerTx(oneEther, {from: owner}).should.be.rejectedWith(ERROR_MSG); + const executionMaxPerTx = await homeContract.executionMaxPerTx() + executionMaxPerTx.should.be.bignumber.equal(newValue) + }) + + it('executionDailyLimit allows to set only to owner', async () => { + const newValue = web3.toBigNumber(web3.toWei(1.5, "ether")); + + const initialExecutionDailyLimit= await homeContract.executionDailyLimit() + + initialExecutionDailyLimit.should.be.bignumber.not.equal(newValue) + + await homeContract.setExecutionDailyLimit(newValue, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG); + await homeContract.setExecutionDailyLimit(newValue, {from: owner}).should.be.fulfilled; + + const executionDailyLimit = await homeContract.executionDailyLimit() + executionDailyLimit.should.be.bignumber.equal(newValue) }) }) @@ -265,7 +332,7 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { let homeBridge; beforeEach(async () => { homeBridge = await HomeBridge.new(); - await homeBridge.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, blockRewardContract.address); + await homeBridge.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner); await blockRewardContract.sendTransaction({ from: accounts[2], value: oneEther @@ -304,7 +371,7 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { const ownerOfValidators = accounts[0] await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators) const homeBridgeWithTwoSigs = await HomeBridge.new(); - await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, blockRewardContract.address); + await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner); const recipient = accounts[5]; const value = halfEther; const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; @@ -346,7 +413,7 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { it('should fail if the block reward contract is not set', async () => { homeBridge = await HomeBridge.new(); - await homeBridge.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, ZERO_ADDRESS); + await homeBridge.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, ZERO_ADDRESS, foreignDailyLimit, foreignMaxPerTx, owner); const recipient = accounts[5]; const value = halfEther; @@ -361,7 +428,7 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators) const homeBridgeWithThreeSigs = await HomeBridge.new(); - await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, blockRewardContract.address); + await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner); const value = web3.toBigNumber(web3.toWei(0.5, "ether")); const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; @@ -383,6 +450,100 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { transactionHash }) }) + it('should not allow execute affirmation over foreign max tx limit', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const {logs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled; + + logs[0].event.should.be.equal("AmountLimitExceeded"); + logs[0].args.should.be.deep.equal({ + recipient, + value, + transactionHash + }); + }) + it('should fail if txHash already set as above of limits', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const {logs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled; + + logs[0].event.should.be.equal("AmountLimitExceeded"); + logs[0].args.should.be.deep.equal({ + recipient, + value, + transactionHash + }); + + await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG) + await homeBridge.executeAffirmation(accounts[6], value, transactionHash, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG) + }) + it('should not allow execute affirmation over daily foreign limit', async () => { + await blockRewardContract.sendTransaction({ + from: accounts[2], + value: oneEther + }).should.be.fulfilled + + const recipient = accounts[5]; + const value = halfEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const { logs } = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled; + + logs[0].event.should.be.equal("SignedForAffirmation"); + logs[0].args.should.be.deep.equal({ + signer: authorities[0], + transactionHash + }); + logs[1].event.should.be.equal("AffirmationCompleted"); + logs[1].args.should.be.deep.equal({ + recipient, + value, + transactionHash + }) + + const transactionHash2 = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + const { logs: logs2 } = await homeBridge.executeAffirmation(recipient, value, transactionHash2, {from: authorities[0]}).should.be.fulfilled; + + logs2[0].event.should.be.equal("SignedForAffirmation"); + logs2[0].args.should.be.deep.equal({ + signer: authorities[0], + transactionHash: transactionHash2 + }); + logs2[1].event.should.be.equal("AffirmationCompleted"); + logs2[1].args.should.be.deep.equal({ + recipient, + value, + transactionHash: transactionHash2 + }) + + const transactionHash3 = "0x69debd8fd1923c9cb3cd8ef6461e2740b2d037943b941729d5a47671a2bb8712"; + const { logs: logs3 } = await homeBridge.executeAffirmation(recipient, value, transactionHash3, {from: authorities[0]}).should.be.fulfilled; + + logs3[0].event.should.be.equal("AmountLimitExceeded"); + logs3[0].args.should.be.deep.equal({ + recipient, + value, + transactionHash: transactionHash3 + }); + + const outOfLimitAmount = await homeBridge.outOfLimitAmount() + + outOfLimitAmount.should.be.bignumber.equal(halfEther) + + const transactionHash4 = "0xc9ffe298d85ec5c515153608924b7bdcf1835539813dcc82cdbcc071170c3196"; + const { logs: logs4 } = await homeBridge.executeAffirmation(recipient, value, transactionHash4, {from: authorities[0]}).should.be.fulfilled; + + logs4[0].event.should.be.equal("AmountLimitExceeded"); + logs4[0].args.should.be.deep.equal({ + recipient, + value, + transactionHash: transactionHash4 + }); + + const newOutOfLimitAmount = await homeBridge.outOfLimitAmount() + newOutOfLimitAmount.should.be.bignumber.equal(oneEther) + }) }) describe('#submitSignature', async () => { @@ -393,7 +554,7 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { ownerOfValidators = accounts[0] await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators) homeBridgeWithTwoSigs = await HomeBridge.new(); - await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, blockRewardContract.address); + await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner); }) it('allows a validator to submit a signature', async () => { @@ -442,7 +603,7 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators) const homeBridgeWithThreeSigs = await HomeBridge.new(); - await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, blockRewardContract.address); + await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner); const value = web3.toBigNumber(web3.toWei(0.5, "ether")); const transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; @@ -513,4 +674,119 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => { '104'.should.be.bignumber.equal(requiredMessageLength) }) }) + describe('#fixAssetsAboveLimits', async () => { + let homeBridge; + const zeroValue = web3.toBigNumber(web3.toWei(0, "ether")) + beforeEach(async () => { + const homeBridgeImpl = await HomeBridge.new(); + const storageProxy = await EternalStorageProxy.new().should.be.fulfilled; + await storageProxy.upgradeTo('1', homeBridgeImpl.address).should.be.fulfilled + homeBridge = await HomeBridge.at(storageProxy.address); + await homeBridge.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, blockRewardContract.address, foreignDailyLimit, foreignMaxPerTx, owner); + }) + it('Should reduce outOfLimitAmount and not emit any event', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const {logs: affirmationLogs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled + + affirmationLogs[0].event.should.be.equal("AmountLimitExceeded"); + + const outOfLimitAmount = await homeBridge.outOfLimitAmount() + outOfLimitAmount.should.be.bignumber.equal(value) + + const { logs } = await homeBridge.fixAssetsAboveLimits(transactionHash, false).should.be.fulfilled + + logs.length.should.be.equal(0) + + const newOutOfLimitAmount = await homeBridge.outOfLimitAmount() + newOutOfLimitAmount.should.be.bignumber.equal(zeroValue) + }) + it('Should reduce outOfLimitAmount and emit UserRequestForSignature', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const {logs: affirmationLogs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled + + affirmationLogs[0].event.should.be.equal("AmountLimitExceeded"); + + const outOfLimitAmount = await homeBridge.outOfLimitAmount() + outOfLimitAmount.should.be.bignumber.equal(value) + + const { logs } = await homeBridge.fixAssetsAboveLimits(transactionHash, true).should.be.fulfilled + + logs.length.should.be.equal(1) + logs[0].event.should.be.equal('UserRequestForSignature') + logs[0].args.should.be.deep.equal({ + recipient, + value + }) + + const newOutOfLimitAmount = await homeBridge.outOfLimitAmount() + newOutOfLimitAmount.should.be.bignumber.equal(zeroValue) + }) + it('Should not be allow to be called by an already fixed txHash', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const transactionHash2 = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + + await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled + await homeBridge.executeAffirmation(recipient, value, transactionHash2, {from: authorities[0]}).should.be.fulfilled + + const outOfLimitAmount = await homeBridge.outOfLimitAmount() + outOfLimitAmount.should.be.bignumber.equal(value.add(value)) + + await homeBridge.fixAssetsAboveLimits(transactionHash, false).should.be.fulfilled + + const newOutOfLimitAmount = await homeBridge.outOfLimitAmount() + newOutOfLimitAmount.should.be.bignumber.equal(value) + + await homeBridge.fixAssetsAboveLimits(transactionHash, false).should.be.rejectedWith(ERROR_MSG) + await homeBridge.fixAssetsAboveLimits(transactionHash2, false).should.be.fulfilled + + const updatedOutOfLimitAmount = await homeBridge.outOfLimitAmount() + updatedOutOfLimitAmount.should.be.bignumber.equal(zeroValue) + + await homeBridge.fixAssetsAboveLimits(transactionHash2, false).should.be.rejectedWith(ERROR_MSG) + }) + it('Should fail if txHash didnt increase out of limit amount', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const invalidTxHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + + const {logs: affirmationLogs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled + + affirmationLogs[0].event.should.be.equal("AmountLimitExceeded"); + + await homeBridge.fixAssetsAboveLimits(invalidTxHash, true).should.be.rejectedWith(ERROR_MSG) + }) + it('Should fail if not called by proxyOwner', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + + const {logs: affirmationLogs} = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled + + affirmationLogs[0].event.should.be.equal("AmountLimitExceeded"); + + await homeBridge.fixAssetsAboveLimits(transactionHash, true, { from: recipient}).should.be.rejectedWith(ERROR_MSG) + await homeBridge.fixAssetsAboveLimits(transactionHash, true, { from: owner}).should.be.fulfilled + }) + }) + describe('#OwnedUpgradeability', async () => { + + it('upgradeabilityAdmin should return the proxy owner', async () => { + const homeBridgeImpl = await HomeBridge.new(); + const storageProxy = await EternalStorageProxy.new().should.be.fulfilled; + await storageProxy.upgradeTo('1', homeBridgeImpl.address).should.be.fulfilled + const homeBridge = await HomeBridge.at(storageProxy.address); + + const proxyOwner = await storageProxy.proxyOwner() + const upgradeabilityAdmin = await homeBridge.upgradeabilityAdmin() + + upgradeabilityAdmin.should.be.equal(proxyOwner) + }) + }) }) diff --git a/test/native_to_erc/foreign_bridge_test.js b/test/native_to_erc/foreign_bridge_test.js index 42b115cb1..7bff1378a 100644 --- a/test/native_to_erc/foreign_bridge_test.js +++ b/test/native_to_erc/foreign_bridge_test.js @@ -12,6 +12,8 @@ const minPerTx = web3.toBigNumber(web3.toWei(0.01, "ether")); const Web3Utils = require('web3-utils'); const requireBlockConfirmations = 8; const gasPrice = Web3Utils.toWei('1', 'gwei'); +const homeDailyLimit = oneEther +const homeMaxPerTx = halfEther const getEvents = function(contract, filter) { return new Promise((resolve, reject) => { @@ -47,12 +49,12 @@ contract('ForeignBridge', async (accounts) => { '0'.should.be.bignumber.equal(await foreignBridge.maxPerTx()) false.should.be.equal(await foreignBridge.isInitialized()) - await foreignBridge.initialize(ZERO_ADDRESS, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, ZERO_ADDRESS, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, 0, requireBlockConfirmations).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(owner, token.address, oneEther, halfEther, minPerTx, requireBlockConfirmations, gasPrice).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, owner, oneEther, halfEther, minPerTx, requireBlockConfirmations, gasPrice).should.be.rejectedWith(ERROR_MSG); - await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await foreignBridge.initialize(ZERO_ADDRESS, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, ZERO_ADDRESS, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, 0, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(owner, token.address, oneEther, halfEther, minPerTx, requireBlockConfirmations, gasPrice, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, owner, oneEther, halfEther, minPerTx, requireBlockConfirmations, gasPrice, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner); true.should.be.equal(await foreignBridge.isInitialized()) validatorContract.address.should.be.equal(await foreignBridge.validatorContract()); @@ -75,7 +77,7 @@ contract('ForeignBridge', async (accounts) => { token = await POA20.new("POA ERC20 Foundation", "POA20", 18); const oneEther = web3.toBigNumber(web3.toWei(1, "ether")); const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether")); - await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner); oneEther.should.be.bignumber.equal(await foreignBridge.dailyLimit()); await token.transferOwnership(foreignBridge.address); }) @@ -165,6 +167,43 @@ contract('ForeignBridge', async (accounts) => { true.should.be.equal(await foreignBridge.relayedMessages(transactionHash)) await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message2).should.be.rejectedWith(ERROR_MSG) }) + + it('should not allow withdraw over home max tx limit', async () => { + const recipientAccount = accounts[3]; + const invalidValue = web3.toBigNumber(web3.toWei(0.75, "ether")); + + const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + const message = createMessage(recipientAccount, invalidValue, transactionHash, foreignBridge.address); + const signature = await sign(authorities[0], message) + const vrs = signatureToVRS(signature); + + await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.rejectedWith(ERROR_MSG) + }) + + it('should not allow withdraw over daily home limit', async () => { + const recipientAccount = accounts[3]; + + const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + const message = createMessage(recipientAccount, halfEther, transactionHash, foreignBridge.address); + const signature = await sign(authorities[0], message) + const vrs = signatureToVRS(signature); + + await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled + + const transactionHash2 = "0x69debd8fd1923c9cb3cd8ef6461e2740b2d037943b941729d5a47671a2bb8712"; + const message2 = createMessage(recipientAccount, halfEther, transactionHash2, foreignBridge.address); + const signature2 = await sign(authorities[0], message2) + const vrs2 = signatureToVRS(signature2); + + await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.fulfilled + + const transactionHash3 = "0x022695428093bb292db8e48bd1417c5e1b84c0bf673bd0fff23ed0fb6495b872"; + const message3 = createMessage(recipientAccount, halfEther, transactionHash3, foreignBridge.address); + const signature3 = await sign(authorities[0], message3) + const vrs3 = signatureToVRS(signature3); + + await foreignBridge.executeSignatures([vrs3.v], [vrs3.r], [vrs3.s], message3).should.be.rejectedWith(ERROR_MSG) + }) }) describe('#executeSignatures with 2 minimum signatures', async () => { @@ -178,7 +217,7 @@ contract('ForeignBridge', async (accounts) => { await multisigValidatorContract.initialize(2, twoAuthorities, ownerOfValidatorContract, {from: ownerOfValidatorContract}) foreignBridgeWithMultiSignatures = await ForeignBridge.new() const oneEther = web3.toBigNumber(web3.toWei(1, "ether")); - await foreignBridgeWithMultiSignatures.initialize(multisigValidatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, {from: ownerOfValidatorContract}); + await foreignBridgeWithMultiSignatures.initialize(multisigValidatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner, {from: ownerOfValidatorContract}); await token.transferOwnership(foreignBridgeWithMultiSignatures.address); }) it('deposit should fail if not enough signatures are provided', async () => { @@ -232,7 +271,7 @@ contract('ForeignBridge', async (accounts) => { const value = web3.toBigNumber(web3.toWei(0.5, "ether")); const foreignBridgeWithThreeSigs = await ForeignBridge.new() - await foreignBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, erc20Token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await foreignBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, erc20Token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner); await erc20Token.transferOwnership(foreignBridgeWithThreeSigs.address); const txHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; @@ -266,7 +305,7 @@ contract('ForeignBridge', async (accounts) => { const user = accounts[4] token = await POA20.new("POA ERC20 Foundation", "POA20", 18, {from: owner}); foreignBridge = await ForeignBridge.new(); - await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner); await token.mint(user, halfEther, {from: owner }).should.be.fulfilled; await token.transferOwnership(foreignBridge.address, {from: owner}); await foreignBridge.onTokenTransfer(user, halfEther, '0x00', {from: owner}).should.be.rejectedWith(ERROR_MSG); @@ -280,7 +319,7 @@ contract('ForeignBridge', async (accounts) => { const valueMoreThanLimit = halfEther.add(1); token = await POA20.new("POA ERC20 Foundation", "POA20", 18, {from: owner}); foreignBridge = await ForeignBridge.new(); - await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner); await token.mint(user, valueMoreThanLimit, {from: owner }).should.be.fulfilled; await token.transferOwnership(foreignBridge.address, {from: owner}); await token.transferAndCall(foreignBridge.address, valueMoreThanLimit, '0x00', {from: user}).should.be.rejectedWith(ERROR_MSG); @@ -301,7 +340,7 @@ contract('ForeignBridge', async (accounts) => { const valueMoreThanLimit = halfEther.add(1); token = await POA20.new("POA ERC20 Foundation", "POA20", 18, {from: owner}); foreignBridge = await ForeignBridge.new(); - await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner); await token.mint(user, oneEther.add(1), {from: owner }).should.be.fulfilled; await token.transferOwnership(foreignBridge.address, {from: owner}); await token.transferAndCall(foreignBridge.address, valueMoreThanLimit, '0x00', {from: user}).should.be.rejectedWith(ERROR_MSG); @@ -322,7 +361,7 @@ contract('ForeignBridge', async (accounts) => { const valueLessThanMinPerTx = minPerTx.sub(1); token = await POA20.new("POA ERC20 Foundation", "POA20", 18, {from: owner}); foreignBridge = await ForeignBridge.new(); - await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner); await token.mint(user, oneEther, {from: owner }).should.be.fulfilled; await token.transferOwnership(foreignBridge.address, {from: owner}); await token.transferAndCall(foreignBridge.address, valueLessThanMinPerTx, '0x00', {from: user}).should.be.rejectedWith(ERROR_MSG); @@ -339,7 +378,7 @@ contract('ForeignBridge', async (accounts) => { beforeEach(async () => { token = await POA20.new("POA ERC20 Foundation", "POA20", 18); foreignBridge = await ForeignBridge.new(); - await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner); await token.transferOwnership(foreignBridge.address) }) it('#setMaxPerTx allows to set only to owner and cannot be more than daily limit', async () => { @@ -383,7 +422,7 @@ contract('ForeignBridge', async (accounts) => { await foreignBridgeProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled; foreignBridgeProxy = await ForeignBridge.at(foreignBridgeProxy.address); - await foreignBridgeProxy.initialize(validatorsProxy.address, token.address, FOREIGN_DAILY_LIMIT, FOREIGN_MAX_AMOUNT_PER_TX, FOREIGN_MIN_AMOUNT_PER_TX, gasPrice, requireBlockConfirmations) + await foreignBridgeProxy.initialize(validatorsProxy.address, token.address, FOREIGN_DAILY_LIMIT, FOREIGN_MAX_AMOUNT_PER_TX, FOREIGN_MIN_AMOUNT_PER_TX, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner) await token.transferOwnership(foreignBridgeProxy.address).should.be.fulfilled; foreignBridgeProxy.address.should.be.equal(await token.owner()); @@ -393,11 +432,6 @@ contract('ForeignBridge', async (accounts) => { let foreignBridgeProxyUpgrade = await EternalStorageProxy.at(foreignBridgeProxy.address); await foreignBridgeProxyUpgrade.upgradeTo('2', foreignImplV2.address).should.be.fulfilled; foreignImplV2.address.should.be.equal(await foreignBridgeProxyUpgrade.implementation()) - - let foreignBridgeV2Proxy = await ForeignBridgeV2.at(foreignBridgeProxy.address) - await foreignBridgeV2Proxy.changeTokenOwnership(accounts[2], {from: accounts[4]}).should.be.rejectedWith(ERROR_MSG) - await foreignBridgeV2Proxy.changeTokenOwnership(accounts[2], {from: PROXY_OWNER}).should.be.fulfilled; - await token.transferOwnership(foreignBridgeProxy.address, {from: accounts[2]}).should.be.fulfilled; }) it('can be deployed via upgradeToAndCall', async () => { const tokenAddress = token.address @@ -409,7 +443,7 @@ contract('ForeignBridge', async (accounts) => { let storageProxy = await EternalStorageProxy.new().should.be.fulfilled; let foreignBridge = await ForeignBridge.new(); let data = foreignBridge.initialize.request( - validatorsAddress, tokenAddress, FOREIGN_DAILY_LIMIT, FOREIGN_MAX_AMOUNT_PER_TX, FOREIGN_MIN_AMOUNT_PER_TX, gasPrice, requireBlockConfirmations).params[0].data + validatorsAddress, tokenAddress, FOREIGN_DAILY_LIMIT, FOREIGN_MAX_AMOUNT_PER_TX, FOREIGN_MIN_AMOUNT_PER_TX, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner).params[0].data await storageProxy.upgradeToAndCall('1', foreignBridge.address, data).should.be.fulfilled; let finalContract = await ForeignBridge.at(storageProxy.address); true.should.be.equal(await finalContract.isInitialized()); @@ -423,7 +457,7 @@ contract('ForeignBridge', async (accounts) => { const foreignBridge = await ForeignBridge.new(); const storageProxy = await EternalStorageProxy.new().should.be.fulfilled; const data = foreignBridge.initialize.request( - validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations).params[0].data + validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner).params[0].data await storageProxy.upgradeToAndCall('1', foreignBridge.address, data).should.be.fulfilled; await storageProxy.transferProxyOwnership(owner).should.be.fulfilled }) @@ -433,8 +467,11 @@ contract('ForeignBridge', async (accounts) => { it('can send erc20', async () => { const owner = accounts[0]; token = await POA20.new("POA ERC20 Foundation", "POA20", 18); - foreignBridge = await ForeignBridge.new(); - await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + const foreignBridgeImpl = await ForeignBridge.new(); + const storageProxy = await EternalStorageProxy.new().should.be.fulfilled; + await storageProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled + const foreignBridge = await ForeignBridge.at(storageProxy.address); + await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner); await token.transferOwnership(foreignBridge.address) let tokenSecond = await POA20.new("Roman Token", "RST", 18); @@ -453,8 +490,11 @@ contract('ForeignBridge', async (accounts) => { it('also calls claimTokens on tokenAddress', async () => { const owner = accounts[0]; token = await POA20.new("POA ERC20 Foundation", "POA20", 18); - foreignBridge = await ForeignBridge.new(); - await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + const foreignBridgeImpl = await ForeignBridge.new(); + const storageProxy = await EternalStorageProxy.new().should.be.fulfilled; + await storageProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled + const foreignBridge = await ForeignBridge.at(storageProxy.address); + await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, homeDailyLimit, homeMaxPerTx, owner); await token.transferOwnership(foreignBridge.address) let tokenSecond = await POA20.new("Roman Token", "RST", 18); diff --git a/test/native_to_erc/home_bridge_test.js b/test/native_to_erc/home_bridge_test.js index 94cddca3e..39aefcace 100644 --- a/test/native_to_erc/home_bridge_test.js +++ b/test/native_to_erc/home_bridge_test.js @@ -9,7 +9,10 @@ const minPerTx = web3.toBigNumber(web3.toWei(0.01, "ether")); const requireBlockConfirmations = 8; const gasPrice = Web3Utils.toWei('1', 'gwei'); const oneEther = web3.toBigNumber(web3.toWei(1, "ether")); +const twoEther = web3.toBigNumber(web3.toWei(2, "ether")); const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether")); +const foreignDailyLimit = oneEther +const foreignMaxPerTx = halfEther contract('HomeBridge', async (accounts) => { let homeContract, validatorContract, authorities, owner; @@ -29,7 +32,7 @@ contract('HomeBridge', async (accounts) => { '0'.should.be.bignumber.equal(await homeContract.dailyLimit()) '0'.should.be.bignumber.equal(await homeContract.maxPerTx()) false.should.be.equal(await homeContract.isInitialized()) - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations).should.be.fulfilled; + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner).should.be.fulfilled; true.should.be.equal(await homeContract.isInitialized()) validatorContract.address.should.be.equal(await homeContract.validatorContract()); (await homeContract.deployedAtBlock()).should.be.bignumber.above(0); @@ -46,14 +49,14 @@ contract('HomeBridge', async (accounts) => { }) it('cant set maxPerTx > dailyLimit', async () => { false.should.be.equal(await homeContract.isInitialized()) - await homeContract.initialize(validatorContract.address, '1', '2', '1', gasPrice, requireBlockConfirmations).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(validatorContract.address, '3', '2', '2', gasPrice, requireBlockConfirmations).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '1', '2', '1', gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '3', '2', '2', gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); false.should.be.equal(await homeContract.isInitialized()) }) it('can be deployed via upgradeToAndCall', async () => { let storageProxy = await EternalStorageProxy.new().should.be.fulfilled; - let data = homeContract.initialize.request(validatorContract.address, "3", "2", "1", gasPrice, requireBlockConfirmations).params[0].data + let data = homeContract.initialize.request(validatorContract.address, "3", "2", "1", gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner).params[0].data await storageProxy.upgradeToAndCall('1', homeContract.address, data).should.be.fulfilled; let finalContract = await HomeBridge.at(storageProxy.address); true.should.be.equal(await finalContract.isInitialized()); @@ -64,15 +67,15 @@ contract('HomeBridge', async (accounts) => { }) it('cant initialize with invalid arguments', async () => { false.should.be.equal(await homeContract.isInitialized()) - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, 0).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(owner, '3', '2', '1', gasPrice, requireBlockConfirmations).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(ZERO_ADDRESS, '3', '2', '1', gasPrice, requireBlockConfirmations).should.be.rejectedWith(ERROR_MSG); - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations).should.be.fulfilled; + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, 0, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(owner, '3', '2', '1', gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(ZERO_ADDRESS, '3', '2', '1', gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG); + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner).should.be.fulfilled; true.should.be.equal(await homeContract.isInitialized()) }) it('can transfer ownership', async () => { let storageProxy = await EternalStorageProxy.new().should.be.fulfilled; - let data = homeContract.initialize.request(validatorContract.address, "3", "2", "1", gasPrice, requireBlockConfirmations).params[0].data + let data = homeContract.initialize.request(validatorContract.address, "3", "2", "1", gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner).params[0].data await storageProxy.upgradeToAndCall('1', homeContract.address, data).should.be.fulfilled; await storageProxy.transferProxyOwnership(owner).should.be.fulfilled }) @@ -81,7 +84,7 @@ contract('HomeBridge', async (accounts) => { describe('#fallback', async () => { beforeEach(async () => { homeContract = await HomeBridge.new() - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations) + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner) }) it('should accept POA', async () => { const currentDay = await homeContract.getCurrentDay() @@ -156,7 +159,7 @@ contract('HomeBridge', async (accounts) => { let homeContract; beforeEach(async () => { homeContract = await HomeBridge.new() - await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations) + await homeContract.initialize(validatorContract.address, '3', '2', '1', gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner) }) it('#setMaxPerTx allows to set only to owner and cannot be more than daily limit', async () => { await homeContract.setMaxPerTx(2, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG); @@ -177,7 +180,7 @@ contract('HomeBridge', async (accounts) => { let homeBridge; beforeEach(async () => { homeBridge = await HomeBridge.new(); - await homeBridge.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await homeBridge.initialize(validatorContract.address, twoEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner); const {logs} = await homeBridge.sendTransaction({ from: accounts[2], value: halfEther @@ -216,7 +219,7 @@ contract('HomeBridge', async (accounts) => { let ownerOfValidators = accounts[0] await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators) let homeBridgeWithTwoSigs = await HomeBridge.new(); - await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, twoEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner); await homeBridgeWithTwoSigs.sendTransaction({ from: accounts[2], @@ -286,7 +289,7 @@ contract('HomeBridge', async (accounts) => { let ownerOfValidators = accounts[0] await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators) let homeBridgeWithTwoSigs = await HomeBridge.new(); - await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner); await homeBridgeWithTwoSigs.sendTransaction({ from: accounts[2], @@ -344,7 +347,7 @@ contract('HomeBridge', async (accounts) => { await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators) const homeBridgeWithThreeSigs = await HomeBridge.new(); - await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner); const value = web3.toBigNumber(web3.toWei(0.5, "ether")); const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; @@ -371,6 +374,53 @@ contract('HomeBridge', async (accounts) => { transactionHash }) }) + it('should not allow execute affirmation over foreign max tx limit', async () => { + const recipient = accounts[5]; + const value = oneEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + + await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG); + }) + it('should not allow execute affirmation over daily foreign limit', async () => { + + await homeBridge.sendTransaction({ from: accounts[2], value: halfEther }).should.be.fulfilled; + await homeBridge.sendTransaction({ from: accounts[2], value: halfEther }).should.be.fulfilled; + + const recipient = accounts[5]; + const value = halfEther; + const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415"; + const { logs } = await homeBridge.executeAffirmation(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled; + + logs[0].event.should.be.equal("SignedForAffirmation"); + logs[0].args.should.be.deep.equal({ + signer: authorities[0], + transactionHash + }); + logs[1].event.should.be.equal("AffirmationCompleted"); + logs[1].args.should.be.deep.equal({ + recipient, + value, + transactionHash + }) + + const transactionHash2 = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121"; + const { logs: logs2 } = await homeBridge.executeAffirmation(recipient, value, transactionHash2, {from: authorities[0]}).should.be.fulfilled; + + logs2[0].event.should.be.equal("SignedForAffirmation"); + logs2[0].args.should.be.deep.equal({ + signer: authorities[0], + transactionHash: transactionHash2 + }); + logs2[1].event.should.be.equal("AffirmationCompleted"); + logs2[1].args.should.be.deep.equal({ + recipient, + value, + transactionHash: transactionHash2 + }) + + const transactionHash3 = "0x69debd8fd1923c9cb3cd8ef6461e2740b2d037943b941729d5a47671a2bb8712"; + await homeBridge.executeAffirmation(recipient, value, transactionHash3, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG); + }) }) describe('#isAlreadyProcessed', async () => { it('returns ', async () => { @@ -391,7 +441,7 @@ contract('HomeBridge', async (accounts) => { ownerOfValidators = accounts[0] await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators) homeBridgeWithTwoSigs = await HomeBridge.new(); - await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await homeBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner); }) it('allows a validator to submit a signature', async () => { var recipientAccount = accounts[8] @@ -434,7 +484,7 @@ contract('HomeBridge', async (accounts) => { await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators) const homeBridgeWithThreeSigs = await HomeBridge.new(); - await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await homeBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, foreignDailyLimit, foreignMaxPerTx, owner); const value = web3.toBigNumber(web3.toWei(0.5, "ether")); const transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80"; diff --git a/test/poa20_test.js b/test/poa20_test.js index f4d1d4c82..4e9ed8b77 100644 --- a/test/poa20_test.js +++ b/test/poa20_test.js @@ -10,6 +10,8 @@ const requireBlockConfirmations = 8; const gasPrice = Web3Utils.toWei('1', 'gwei'); const oneEther = web3.toBigNumber(web3.toWei(1, "ether")); const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether")); +const executionDailyLimit = oneEther +const executionMaxPerTx = halfEther contract('ERC677BridgeToken', async (accounts) => { let token @@ -101,9 +103,9 @@ contract('ERC677BridgeToken', async (accounts) => { const authorities = [accounts[2]]; await validatorContract.initialize(1, authorities, owner) homeErcToErcContract = await HomeErcToErcBridge.new() - await homeErcToErcContract.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address) + await homeErcToErcContract.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, executionDailyLimit, executionMaxPerTx, owner) foreignNativeToErcBridge = await ForeignNativeToErcBridge.new() - await foreignNativeToErcBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await foreignNativeToErcBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, executionDailyLimit, executionMaxPerTx, owner); }) it('sends tokens to recipient', async () => { await token.mint(user, 1, {from: owner }).should.be.fulfilled; @@ -189,9 +191,9 @@ contract('ERC677BridgeToken', async (accounts) => { const authorities = [accounts[2]]; await validatorContract.initialize(1, authorities, owner) homeErcToErcContract = await HomeErcToErcBridge.new() - await homeErcToErcContract.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address) + await homeErcToErcContract.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, executionDailyLimit, executionMaxPerTx, owner) foreignNativeToErcBridge = await ForeignNativeToErcBridge.new() - await foreignNativeToErcBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations); + await foreignNativeToErcBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, executionDailyLimit, executionMaxPerTx, owner); }) it('calls contractFallback', async () => { const receiver = await ERC677ReceiverTest.new();