Merge branch '119-Epic-rewards-for-bridge-validators' into 122-create-feemanager-basic-contract-and-its-interface

# Conflicts:
#	contracts/upgradeable_contracts/BasicHomeBridge.sol
#	test/erc_to_native/home_bridge.test.js
This commit is contained in:
Gerardo Nardelli 2019-01-10 09:06:35 -03:00
commit 6deecdafac
37 changed files with 1614 additions and 339 deletions

View File

@ -75,7 +75,7 @@ contract ERC677BridgeToken is
}
function isContract(address _addr)
private
internal
view
returns (bool)
{

View File

@ -0,0 +1,66 @@
pragma solidity 0.4.24;
import "./ERC677BridgeToken.sol";
contract ERC677BridgeTokenRewardable is ERC677BridgeToken {
address public blockRewardContract;
address public validatorSetContract;
constructor(
string _name,
string _symbol,
uint8 _decimals
) public ERC677BridgeToken(_name, _symbol, _decimals) {}
function setBlockRewardContract(address _blockRewardContract) onlyOwner public {
require(_blockRewardContract != address(0) && isContract(_blockRewardContract));
blockRewardContract = _blockRewardContract;
}
function setValidatorSetContract(address _validatorSetContract) onlyOwner public {
require(_validatorSetContract != address(0) && isContract(_validatorSetContract));
validatorSetContract = _validatorSetContract;
}
modifier onlyBlockRewardContract() {
require(msg.sender == blockRewardContract);
_;
}
modifier onlyValidatorSetContract() {
require(msg.sender == validatorSetContract);
_;
}
function mintReward(address[] _receivers, uint256[] _rewards) external onlyBlockRewardContract {
for (uint256 i = 0; i < _receivers.length; i++) {
address to = _receivers[i];
uint256 amount = _rewards[i];
// Mint `amount` for `to`
totalSupply_ = totalSupply_.add(amount);
balances[to] = balances[to].add(amount);
emit Mint(to, amount);
emit Transfer(address(0), to, amount);
}
}
function stake(address _staker, uint256 _amount) external onlyValidatorSetContract {
// Transfer `_amount` from `_staker` to `validatorSetContract`
require(_amount <= balances[_staker]);
balances[_staker] = balances[_staker].sub(_amount);
balances[validatorSetContract] = balances[validatorSetContract].add(_amount);
emit Transfer(_staker, validatorSetContract, _amount);
}
function withdraw(address _staker, uint256 _amount) external onlyValidatorSetContract {
// Transfer `_amount` from `validatorSetContract` to `_staker`
require(_amount <= balances[validatorSetContract]);
balances[validatorSetContract] = balances[validatorSetContract].sub(_amount);
balances[_staker] = balances[_staker].add(_amount);
emit Transfer(validatorSetContract, _staker, _amount);
}
}

View File

@ -0,0 +1,6 @@
pragma solidity 0.4.24;
interface IOwnedUpgradeabilityProxy {
function proxyOwner() public view returns (address);
}

View File

@ -0,0 +1,6 @@
pragma solidity 0.4.24;
contract ValidatorSet {
constructor() {}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -17,27 +17,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);
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;
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);
setNumAffirmationsSigned(hashMsg, signed);
emit SignedForAffirmation(msg.sender, transactionHash);
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 (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);
}
}
@ -161,6 +165,13 @@ contract BasicHomeBridge is EternalStorage, Validatable {
return Message.requiredMessageLength();
}
function affirmationWithinLimits(uint256) internal view returns(bool) {
return true;
}
function onFailedAffirmation(address, uint256, bytes32) internal {
}
function feeManagerContract() public view returns(address) {
return addressStorage[keccak256(abi.encodePacked("feeManagerContract"))];
}

View File

@ -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;
}
}

View File

@ -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());
_;
}
}

View File

@ -13,11 +13,6 @@ contract Validatable is EternalStorage {
_;
}
modifier onlyOwner() {
require(validatorContract().owner() == msg.sender);
_;
}
function requiredSignatures() public view returns(uint256) {
return validatorContract().requiredSignatures();
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
@ -37,8 +40,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());
@ -46,6 +51,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;
@ -54,6 +61,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();
@ -77,6 +87,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));
uint256 valueToMint = _value;
@ -98,4 +109,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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -1,7 +1,7 @@
#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
@ -11,22 +11,22 @@ 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
HOME_REQUIRED_BLOCK_CONFIRMATIONS=1
HOME_GAS_PRICE=1000000000
#for bridge erc to native mode
#for bridge erc_to_native and native_to_erc mode
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
@ -39,3 +39,7 @@ REQUIRED_NUMBER_OF_VALIDATORS=1
#If several validators are used, list them separated by space without quotes
#E.g. VALIDATORS=0x 0x 0x
VALIDATORS=0x
#for bridge native_to_erc mode
DEPLOY_REWARDABLE_TOKEN=false
DPOS_VALIDATOR_SET_ADDRESS=

View File

@ -59,14 +59,13 @@ 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
@ -125,6 +123,16 @@ REQUIRED_NUMBER_OF_VALIDATORS=1
# the Foreign network to confirm that the finalized agreement was transferred
# correctly to the Foreign network.
VALIDATORS=0x 0x 0x
# The flag defining whether to use ERC677BridgeTokenRewardable contract instead of
# ERC677BridgeToken.
DEPLOY_REWARDABLE_TOKEN=false
# The address of ValidatorSet contract used by ERC677BridgeTokenRewardable contract.
# Makes sense only when DEPLOY_REWARDABLE_TOKEN=true
DPOS_VALIDATOR_SET_ADDRESS=0x
# The address of BlockReward contract used by ERC677BridgeTokenRewardable contract.
# Makes sense only when DEPLOY_REWARDABLE_TOKEN=true
BLOCK_REWARD_ADDRESS=0x
```
@ -163,14 +171,13 @@ 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 +200,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
@ -256,14 +262,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 +294,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

View File

@ -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 ${

View File

@ -44,7 +44,7 @@ async function deployContract(contractJson, args, { from, network, nonce }) {
to: null,
privateKey: deploymentPrivateKey,
url,
gasPrice: gasPrice
gasPrice
})
if (Web3Utils.hexToNumber(tx.status) !== 1) {
throw new Error('Tx failed')
@ -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
}

View File

@ -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')

View File

@ -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 }
}
}

View File

@ -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')

View File

@ -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')

View File

@ -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(),
@ -61,7 +61,10 @@ if (BRIDGE_MODE === 'NATIVE_TO_ERC') {
BRIDGEABLE_TOKEN_DECIMALS: envalid.num(),
FOREIGN_DAILY_LIMIT: bigNumValidator(),
FOREIGN_MAX_AMOUNT_PER_TX: bigNumValidator(),
FOREIGN_MIN_AMOUNT_PER_TX: bigNumValidator()
FOREIGN_MIN_AMOUNT_PER_TX: bigNumValidator(),
DEPLOY_REWARDABLE_TOKEN: envalid.bool(),
DPOS_VALIDATOR_SET_ADDRESS: addressValidator(),
BLOCK_REWARD_ADDRESS: addressValidator()
}
}
if (BRIDGE_MODE === 'ERC_TO_ERC') {

View File

@ -6,6 +6,7 @@ const { deployContract, privateKeyToAddress, sendRawTxForeign } = require('../de
const { web3Foreign, deploymentPrivateKey, FOREIGN_RPC_URL } = require('../web3')
const ERC677BridgeToken = require('../../../build/contracts/ERC677BridgeToken.json')
const ERC677BridgeTokenRewardable = require('../../../build/contracts/ERC677BridgeTokenRewardable.json')
const EternalStorageProxy = require('../../../build/contracts/EternalStorageProxy.json')
const BridgeValidators = require('../../../build/contracts/BridgeValidators.json')
const ForeignBridge = require('../../../build/contracts/ForeignBridgeNativeToErc.json')
@ -16,16 +17,21 @@ 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,
DEPLOY_REWARDABLE_TOKEN,
BLOCK_REWARD_ADDRESS,
DPOS_VALIDATOR_SET_ADDRESS
} = env
const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVATE_KEY)
@ -38,7 +44,7 @@ async function deployForeign() {
console.log('\n[Foreign] deploying BRIDGEABLE_TOKEN_SYMBOL token')
const erc677bridgeToken = await deployContract(
ERC677BridgeToken,
DEPLOY_REWARDABLE_TOKEN ? ERC677BridgeTokenRewardable : ERC677BridgeToken,
[BRIDGEABLE_TOKEN_NAME, BRIDGEABLE_TOKEN_SYMBOL, BRIDGEABLE_TOKEN_DECIMALS],
{ from: DEPLOYMENT_ACCOUNT_ADDRESS, network: 'foreign', nonce: foreignNonce }
)
@ -77,7 +83,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 +96,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 +105,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 +119,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 +158,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 +186,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 +199,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,9 +213,39 @@ 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++
if (DEPLOY_REWARDABLE_TOKEN) {
console.log('\nset BlockReward contract on ERC677BridgeTokenRewardable')
const setBlockRewardContractData = await erc677bridgeToken.methods
.setBlockRewardContract(BLOCK_REWARD_ADDRESS)
.encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS })
const setBlockRewardContract = await sendRawTxForeign({
data: setBlockRewardContractData,
nonce: foreignNonce,
to: erc677bridgeToken.options.address,
privateKey: deploymentPrivateKey,
url: FOREIGN_RPC_URL
})
assert.equal(Web3Utils.hexToNumber(setBlockRewardContract.status), 1, 'Transaction Failed')
foreignNonce++
console.log('\nset ValidatorSet contract on ERC677BridgeTokenRewardable')
const setValidatorSetContractData = await erc677bridgeToken.methods
.setValidatorSetContract(DPOS_VALIDATOR_SET_ADDRESS)
.encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS })
const setValidatorSetContract = await sendRawTxForeign({
data: setValidatorSetContractData,
nonce: foreignNonce,
to: erc677bridgeToken.options.address,
privateKey: deploymentPrivateKey,
url: FOREIGN_RPC_URL
})
assert.equal(Web3Utils.hexToNumber(setValidatorSetContract.status), 1, 'Transaction Failed')
foreignNonce++
}
console.log('transferring ownership of ERC677BridgeToken token to foreignBridge contract')
const txOwnershipData = await erc677bridgeToken.methods
.transferOwnership(foreignBridgeStorage.options.address)
@ -206,11 +257,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 +270,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')

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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())
@ -61,10 +65,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 () => {
@ -134,6 +139,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 () => {
@ -148,7 +192,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 () => {
@ -192,7 +236,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";
@ -241,7 +285,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();
@ -261,7 +305,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());
@ -273,8 +317,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);

View File

@ -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, authoritiesThreeAccs, 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, authoritiesThreeAccs, 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, authoritiesThreeAccs, 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)
})
})
})

View File

@ -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;

View File

@ -12,6 +12,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;
@ -35,7 +38,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())
@ -58,7 +61,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())
@ -81,15 +84,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);
@ -101,13 +104,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())
})
})
@ -115,7 +149,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 () => {
@ -246,13 +280,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 () => {
@ -260,6 +296,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)
})
})
@ -267,7 +334,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
@ -306,7 +373,7 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => {
const ownerOfValidators = accounts[0]
await validatorContractWith2Signatures.initialize(2, authoritiesThreeAccs, 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";
@ -348,7 +415,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;
@ -363,7 +430,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";
@ -385,6 +452,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 () => {
@ -395,7 +556,7 @@ contract('HomeBridge_ERC20_to_Native', async (accounts) => {
ownerOfValidators = accounts[0]
await validatorContractWith2Signatures.initialize(2, authoritiesThreeAccs, 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 () => {
@ -444,7 +605,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";
@ -515,6 +676,121 @@ 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)
})
})
describe('#feeManager', async () => {
let homeBridge, rewardableValidators

View File

@ -0,0 +1,22 @@
pragma solidity 0.4.24;
import '../../contracts/ERC677BridgeTokenRewardable.sol';
contract ERC677BridgeTokenRewardableMock is ERC677BridgeTokenRewardable {
constructor(
string _name,
string _symbol,
uint8 _decimals
) public ERC677BridgeTokenRewardable(_name, _symbol, _decimals) {}
function setBlockRewardContractMock(address _blockRewardContract) public {
blockRewardContract = _blockRewardContract;
}
function setValidatorSetContractMock(address _validatorSetContract) public {
validatorSetContract = _validatorSetContract;
}
}

View File

@ -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());
@ -76,7 +78,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);
})
@ -166,6 +168,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 () => {
@ -179,7 +218,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 () => {
@ -233,7 +272,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);

View File

@ -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;
@ -30,7 +33,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);
@ -47,14 +50,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());
@ -65,15 +68,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
})
@ -82,7 +85,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()
@ -157,7 +160,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);
@ -178,7 +181,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
@ -217,7 +220,7 @@ contract('HomeBridge', async (accounts) => {
let ownerOfValidators = accounts[0]
await validatorContractWith2Signatures.initialize(2, authoritiesThreeAccs, 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],
@ -287,7 +290,7 @@ contract('HomeBridge', async (accounts) => {
let ownerOfValidators = accounts[0]
await validatorContractWith2Signatures.initialize(2, authoritiesThreeAccs, 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],
@ -345,7 +348,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";
@ -372,6 +375,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 () => {
@ -393,7 +443,7 @@ contract('HomeBridge', async (accounts) => {
ownerOfValidators = accounts[0]
await validatorContractWith2Signatures.initialize(2, authoritiesThreeAccs, 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]
@ -436,7 +486,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";

View File

@ -1,5 +1,8 @@
const POA20 = artifacts.require("ERC677BridgeToken.sol");
const POA20RewardableMock = artifacts.require("./mockContracts/ERC677BridgeTokenRewardableMock");
const ERC677ReceiverTest = artifacts.require("ERC677ReceiverTest.sol")
const BlockRewardTest = artifacts.require("BlockReward.sol")
const ValidatorSetTest = artifacts.require("ValidatorSet.sol")
const { ERROR_MSG, ZERO_ADDRESS} = require('./setup');
const Web3Utils = require('web3-utils');
const HomeErcToErcBridge = artifacts.require("HomeBridgeErcToErc.sol");
@ -10,13 +13,16 @@ 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) => {
async function testERC677BridgeToken(accounts, rewardable) {
let token
let owner = accounts[0]
const user = accounts[1];
const tokenContract = rewardable ? POA20RewardableMock : POA20;
beforeEach(async () => {
token = await POA20.new("POA ERC20 Foundation", "POA20", 18);
token = await tokenContract.new("POA ERC20 Foundation", "POA20", 18);
})
it('default values', async () => {
@ -74,6 +80,160 @@ contract('ERC677BridgeToken', async (accounts) => {
})
})
if (rewardable) {
describe('#blockRewardContract', async() => {
it('can set BlockReward contract', async () => {
const blockRewardContract = await BlockRewardTest.new();
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
await token.setBlockRewardContract(blockRewardContract.address).should.be.fulfilled;
(await token.blockRewardContract()).should.be.equal(blockRewardContract.address);
})
it('only owner can set BlockReward contract', async () => {
const blockRewardContract = await BlockRewardTest.new();
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
await token.setBlockRewardContract(blockRewardContract.address, {from: user }).should.be.rejectedWith(ERROR_MSG);
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
await token.setBlockRewardContract(blockRewardContract.address, {from: owner }).should.be.fulfilled;
(await token.blockRewardContract()).should.be.equal(blockRewardContract.address);
})
it('fail to set invalid BlockReward contract address', async () => {
const invalidContractAddress = '0xaaB52d66283F7A1D5978bcFcB55721ACB467384b';
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
await token.setBlockRewardContract(invalidContractAddress).should.be.rejectedWith(ERROR_MSG);
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
await token.setBlockRewardContract(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG);
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
})
})
describe('#validatorSetContract', async() => {
it('can set ValidatorSet contract', async () => {
const validatorSetContract = await ValidatorSetTest.new();
(await token.validatorSetContract()).should.be.equal(ZERO_ADDRESS);
await token.setValidatorSetContract(validatorSetContract.address).should.be.fulfilled;
(await token.validatorSetContract()).should.be.equal(validatorSetContract.address);
})
it('only owner can set ValidatorSet contract', async () => {
const validatorSetContract = await ValidatorSetTest.new();
(await token.validatorSetContract()).should.be.equal(ZERO_ADDRESS);
await token.setValidatorSetContract(validatorSetContract.address, {from: user }).should.be.rejectedWith(ERROR_MSG);
(await token.validatorSetContract()).should.be.equal(ZERO_ADDRESS);
await token.setValidatorSetContract(validatorSetContract.address, {from: owner }).should.be.fulfilled;
(await token.validatorSetContract()).should.be.equal(validatorSetContract.address);
})
it('fail to set invalid ValidatorSet contract address', async () => {
const invalidContractAddress = '0xaaB52d66283F7A1D5978bcFcB55721ACB467384b';
(await token.validatorSetContract()).should.be.equal(ZERO_ADDRESS);
await token.setValidatorSetContract(invalidContractAddress).should.be.rejectedWith(ERROR_MSG);
(await token.validatorSetContract()).should.be.equal(ZERO_ADDRESS);
await token.setValidatorSetContract(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG);
(await token.validatorSetContract()).should.be.equal(ZERO_ADDRESS);
})
})
describe('#mintReward', async() => {
it('can only be called by BlockReward contract', async () => {
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
await token.mintReward([], [], {from: user }).should.be.rejectedWith(ERROR_MSG);
await token.mintReward([], [], {from: accounts[2] }).should.be.fulfilled;
})
it('should increase totalSupply and balances', async () => {
const user1 = accounts[1];
const user2 = accounts[2];
const user3 = accounts[3];
assert.equal(await token.totalSupply(), 0);
(await token.balanceOf(user1)).should.be.bignumber.equal(0);
(await token.balanceOf(user2)).should.be.bignumber.equal(0);
(await token.balanceOf(user3)).should.be.bignumber.equal(0);
await token.setBlockRewardContractMock(accounts[4]).should.be.fulfilled;
await token.mintReward([user1, user2, user3], [100, 200, 300], {from: accounts[4] }).should.be.fulfilled;
assert.equal(await token.totalSupply(), 600);
(await token.balanceOf(user1)).should.be.bignumber.equal(100);
(await token.balanceOf(user2)).should.be.bignumber.equal(200);
(await token.balanceOf(user3)).should.be.bignumber.equal(300);
})
})
describe('#stake', async() => {
it('can only be called by ValidatorSet contract', async () => {
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
await token.mintReward([user], [100], {from: accounts[2] }).should.be.fulfilled;
await token.setValidatorSetContractMock(accounts[3]).should.be.fulfilled;
await token.stake(user, 100, {from: accounts[4] }).should.be.rejectedWith(ERROR_MSG);
await token.stake(user, 100, {from: accounts[3] }).should.be.fulfilled;
})
it('should revert if user doesn\'t have enough balance', async () => {
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
await token.mintReward([user], [99], {from: accounts[2] }).should.be.fulfilled;
(await token.balanceOf(user)).should.be.bignumber.equal(99);
await token.setValidatorSetContractMock(accounts[3]).should.be.fulfilled;
await token.stake(user, 100, {from: accounts[3] }).should.be.rejectedWith(ERROR_MSG);
})
it('should decrease user\'s balance and increase ValidatorSet\'s balance', async () => {
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
await token.mintReward([user], [100], {from: accounts[2] }).should.be.fulfilled;
(await token.balanceOf(user)).should.be.bignumber.equal(100);
(await token.balanceOf(accounts[3])).should.be.bignumber.equal(0);
await token.setValidatorSetContractMock(accounts[3]).should.be.fulfilled;
await token.stake(user, 100, {from: accounts[3] }).should.be.fulfilled;
(await token.balanceOf(user)).should.be.bignumber.equal(0);
(await token.balanceOf(accounts[3])).should.be.bignumber.equal(100);
})
})
describe('#withdraw', async() => {
it('can only be called by ValidatorSet contract', async () => {
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
await token.mintReward([user], [100], {from: accounts[2] }).should.be.fulfilled;
await token.setValidatorSetContractMock(accounts[3]).should.be.fulfilled;
await token.stake(user, 100, {from: accounts[3] }).should.be.fulfilled;
await token.withdraw(user, 100, {from: accounts[4] }).should.be.rejectedWith(ERROR_MSG);
await token.withdraw(user, 100, {from: accounts[3] }).should.be.fulfilled;
})
it('should revert if ValidatorSet doesn\'t have enough balance', async () => {
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
await token.mintReward([user], [100], {from: accounts[2] }).should.be.fulfilled;
(await token.balanceOf(user)).should.be.bignumber.equal(100);
await token.setValidatorSetContractMock(accounts[3]).should.be.fulfilled;
await token.stake(user, 100, {from: accounts[3] }).should.be.fulfilled;
await token.withdraw(user, 101, {from: accounts[3] }).should.be.rejectedWith(ERROR_MSG);
await token.withdraw(user, 100, {from: accounts[3] }).should.be.fulfilled;
})
it('should decrease ValidatorSet\'s balance and increase user\'s balance', async () => {
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
await token.mintReward([user], [100], {from: accounts[2] }).should.be.fulfilled;
(await token.balanceOf(user)).should.be.bignumber.equal(100);
(await token.balanceOf(accounts[3])).should.be.bignumber.equal(0);
await token.setValidatorSetContractMock(accounts[3]).should.be.fulfilled;
await token.stake(user, 100, {from: accounts[3] }).should.be.fulfilled;
(await token.balanceOf(user)).should.be.bignumber.equal(0);
(await token.balanceOf(accounts[3])).should.be.bignumber.equal(100);
await token.withdraw(user, 60, {from: accounts[3] }).should.be.fulfilled;
(await token.balanceOf(user)).should.be.bignumber.equal(60);
(await token.balanceOf(accounts[3])).should.be.bignumber.equal(40);
})
})
}
describe('#mint', async() => {
it('can mint by owner', async () => {
(await token.totalSupply()).should.be.bignumber.equal(0);
@ -101,9 +261,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 +349,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();
@ -260,7 +420,7 @@ contract('ERC677BridgeToken', async (accounts) => {
it('can take send ERC20 tokens', async ()=> {
const owner = accounts[0];
const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether"));
let tokenSecond = await POA20.new("Roman Token", "RST", 18);
let tokenSecond = await tokenContract.new("Roman Token", "RST", 18);
await tokenSecond.mint(accounts[0], halfEther).should.be.fulfilled;
halfEther.should.be.bignumber.equal(await tokenSecond.balanceOf(accounts[0]))
@ -271,7 +431,6 @@ contract('ERC677BridgeToken', async (accounts) => {
await token.claimTokens(tokenSecond.address, accounts[3], {from: owner});
'0'.should.be.bignumber.equal(await tokenSecond.balanceOf(token.address))
halfEther.should.be.bignumber.equal(await tokenSecond.balanceOf(accounts[3]))
})
})
describe('#transfer', async () => {
@ -293,7 +452,7 @@ contract('ERC677BridgeToken', async (accounts) => {
logs[0].event.should.be.equal("Transfer")
})
it('if transfer called on contract, still works even if onTokenTransfer doesnot exist', async () => {
const someContract = await POA20.new("Some", "Token", 18);
const someContract = await tokenContract.new("Some", "Token", 18);
await token.mint(user, 2, {from: owner }).should.be.fulfilled;
const tokenTransfer = await token.transfer(someContract.address, 1, {from: user}).should.be.fulfilled;
const tokenTransfer2 = await token.transfer(accounts[0], 1, {from: user}).should.be.fulfilled;
@ -301,7 +460,14 @@ contract('ERC677BridgeToken', async (accounts) => {
(await token.balanceOf(user)).should.be.bignumber.equal(0);
tokenTransfer.logs[0].event.should.be.equal("Transfer")
tokenTransfer2.logs[0].event.should.be.equal("Transfer")
})
})
}
contract('ERC677BridgeToken', async (accounts) => {
await testERC677BridgeToken(accounts, false);
})
contract('ERC677BridgeTokenRewardable', async (accounts) => {
await testERC677BridgeToken(accounts, true);
})