diff --git a/.solhint.json b/.solhint.json index 437403c4d..0f1c52e8e 100644 --- a/.solhint.json +++ b/.solhint.json @@ -8,6 +8,7 @@ "no-inline-assembly": "off", "multiple-sends": "off", "bracket-align": "off", + "no-complex-fallback": "off", "compiler-version": ["error", "0.4.24"] } } diff --git a/contracts/ERC677BridgeTokenRewardable.sol b/contracts/ERC677BridgeTokenRewardable.sol index 61f8cdb2b..c9ba329f8 100644 --- a/contracts/ERC677BridgeTokenRewardable.sol +++ b/contracts/ERC677BridgeTokenRewardable.sol @@ -33,21 +33,14 @@ contract ERC677BridgeTokenRewardable is ERC677BridgeToken { _; } - function mintReward(address[] _receivers, uint256[] _rewards) external onlyBlockRewardContract { - uint256 receiversLength = _receivers.length; - for (uint256 i = 0; i < receiversLength; i++) { - uint256 amount = _rewards[i]; - - if (amount == 0) continue; - - address to = _receivers[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 mintReward(uint256 _amount) external onlyBlockRewardContract { + if (_amount == 0) return; + // Mint `_amount` for the BlockReward contract + address to = blockRewardContract; + 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 onlyStakingContract { @@ -58,11 +51,13 @@ contract ERC677BridgeTokenRewardable is ERC677BridgeToken { } function transfer(address _to, uint256 _value) public returns (bool) { + require(_to != blockRewardContract); require(_to != stakingContract); return super.transfer(_to, _value); } function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { + require(_to != blockRewardContract); require(_to != stakingContract); return super.transferFrom(_from, _to, _value); } diff --git a/contracts/mocks/BlockReward.sol b/contracts/mocks/BlockReward.sol index 7d53fc947..af7716d91 100644 --- a/contracts/mocks/BlockReward.sol +++ b/contracts/mocks/BlockReward.sol @@ -7,11 +7,12 @@ contract BlockReward { using SafeMath for uint256; address[] public validatorList; + uint256[] public validatorRewardList; uint256 public mintedCoins = 0; uint256 public feeAmount = 0; mapping(bytes32 => uint256) internal uintStorage; bytes32 internal constant MINTED_TOTALLY_BY_BRIDGE = "mintedTotallyByBridge"; - bytes4 internal constant MINT_REWARD = 0xe2f764a3; // mintReward(address[],uint256[]) + bytes4 internal constant MINT_REWARD = 0x91c0aabf; // mintReward(uint256) address public token; function() external payable { @@ -67,8 +68,7 @@ contract BlockReward { } function addBridgeTokenFeeReceivers(uint256 _amount) external { - address[] memory receivers = new address[](validatorList.length); - uint256[] memory rewards = new uint256[](validatorList.length); + validatorRewardList = new uint256[](validatorList.length); feeAmount = _amount; uint256 feePerValidator = _amount.div(validatorList.length); @@ -83,11 +83,10 @@ contract BlockReward { if (diff > 0 && randomValidatorIndex == i) { feeToDistribute = feeToDistribute.add(diff); } - receivers[i] = validatorList[i]; - rewards[i] = feeToDistribute; + validatorRewardList[i] = feeToDistribute; } - require(token.call(abi.encodeWithSelector(MINT_REWARD, receivers, rewards))); + require(token.call(abi.encodeWithSelector(MINT_REWARD, _amount))); } function random(uint256 _count) public view returns (uint256) { diff --git a/contracts/mocks/FeeManagerMock.sol b/contracts/mocks/FeeManagerMock.sol index 01af6b823..aa2ee1b2e 100644 --- a/contracts/mocks/FeeManagerMock.sol +++ b/contracts/mocks/FeeManagerMock.sol @@ -12,7 +12,7 @@ contract FeeManagerMock is BaseFeeManager { } function getFeeManagerMode() external pure returns (bytes4) { - return bytes4(keccak256(abi.encodePacked("manages-one-direction"))); + return 0xf2aed8f7; // bytes4(keccak256(abi.encodePacked("manages-one-direction"))) } function randomTest(uint256 _count) external view returns (uint256) { diff --git a/contracts/upgradeable_contracts/BaseBridgeValidators.sol b/contracts/upgradeable_contracts/BaseBridgeValidators.sol index b231c0bdd..a55710d62 100644 --- a/contracts/upgradeable_contracts/BaseBridgeValidators.sol +++ b/contracts/upgradeable_contracts/BaseBridgeValidators.sol @@ -9,8 +9,8 @@ contract BaseBridgeValidators is InitializableBridge, Ownable { address public constant F_ADDR = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; uint256 internal constant MAX_VALIDATORS = 100; - bytes32 internal constant REQUIRED_SIGNATURES = keccak256(abi.encodePacked("requiredSignatures")); - bytes32 internal constant VALIDATOR_COUNT = keccak256(abi.encodePacked("validatorCount")); + bytes32 internal constant REQUIRED_SIGNATURES = 0xd18ea17c351d6834a0e568067fb71804d2a588d5e26d60f792b1c724b1bd53b1; // keccak256(abi.encodePacked("requiredSignatures")) + bytes32 internal constant VALIDATOR_COUNT = 0x8656d603d9f985c3483946a92789d52202f49736384ba131cb92f62c4c1aa082; // keccak256(abi.encodePacked("validatorCount")) event ValidatorAdded(address indexed validator); event ValidatorRemoved(address indexed validator); diff --git a/contracts/upgradeable_contracts/BaseFeeManager.sol b/contracts/upgradeable_contracts/BaseFeeManager.sol index 2a520bddc..7af5b2497 100644 --- a/contracts/upgradeable_contracts/BaseFeeManager.sol +++ b/contracts/upgradeable_contracts/BaseFeeManager.sol @@ -13,8 +13,8 @@ contract BaseFeeManager is EternalStorage, FeeTypes { // This is not a real fee value but a relative value used to calculate the fee percentage uint256 internal constant MAX_FEE = 1 ether; - bytes32 internal constant HOME_FEE_STORAGE_KEY = keccak256(abi.encodePacked("homeFee")); - bytes32 internal constant FOREIGN_FEE_STORAGE_KEY = keccak256(abi.encodePacked("foreignFee")); + bytes32 internal constant HOME_FEE_STORAGE_KEY = 0xc3781f3cec62d28f56efe98358f59c2105504b194242dbcb2cc0806850c306e7; // keccak256(abi.encodePacked("homeFee")) + bytes32 internal constant FOREIGN_FEE_STORAGE_KEY = 0x68c305f6c823f4d2fa4140f9cf28d32a1faccf9b8081ff1c2de11cf32c733efc; // keccak256(abi.encodePacked("foreignFee")) function calculateFee(uint256 _value, bool _recover, bytes32 _feeType) public view returns (uint256) { uint256 fee = _feeType == HOME_FEE ? getHomeFee() : getForeignFee(); diff --git a/contracts/upgradeable_contracts/BaseOverdrawManagement.sol b/contracts/upgradeable_contracts/BaseOverdrawManagement.sol index 4482e8ec0..b7339369b 100644 --- a/contracts/upgradeable_contracts/BaseOverdrawManagement.sol +++ b/contracts/upgradeable_contracts/BaseOverdrawManagement.sol @@ -6,7 +6,7 @@ contract BaseOverdrawManagement is EternalStorage { event AmountLimitExceeded(address recipient, uint256 value, bytes32 transactionHash); event AssetAboveLimitsFixed(bytes32 indexed transactionHash, uint256 value, uint256 remaining); - bytes32 internal constant OUT_OF_LIMIT_AMOUNT = keccak256(abi.encodePacked("outOfLimitAmount")); + bytes32 internal constant OUT_OF_LIMIT_AMOUNT = 0x145286dc85799b6fb9fe322391ba2d95683077b2adf34dd576dedc437e537ba7; // keccak256(abi.encodePacked("outOfLimitAmount")) function outOfLimitAmount() public view returns (uint256) { return uintStorage[OUT_OF_LIMIT_AMOUNT]; diff --git a/contracts/upgradeable_contracts/BasicBridge.sol b/contracts/upgradeable_contracts/BasicBridge.sol index e3548b031..59bd3bf01 100644 --- a/contracts/upgradeable_contracts/BasicBridge.sol +++ b/contracts/upgradeable_contracts/BasicBridge.sol @@ -12,8 +12,8 @@ contract BasicBridge is InitializableBridge, Validatable, Ownable, Upgradeable, event GasPriceChanged(uint256 gasPrice); event RequiredBlockConfirmationChanged(uint256 requiredBlockConfirmations); - bytes32 internal constant GAS_PRICE = keccak256(abi.encodePacked("gasPrice")); - bytes32 internal constant REQUIRED_BLOCK_CONFIRMATIONS = keccak256(abi.encodePacked("requiredBlockConfirmations")); + bytes32 internal constant GAS_PRICE = 0x55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b; // keccak256(abi.encodePacked("gasPrice")) + bytes32 internal constant REQUIRED_BLOCK_CONFIRMATIONS = 0x916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d79407230071; // keccak256(abi.encodePacked("requiredBlockConfirmations")) function setGasPrice(uint256 _gasPrice) external onlyOwner { require(_gasPrice > 0); diff --git a/contracts/upgradeable_contracts/BasicTokenBridge.sol b/contracts/upgradeable_contracts/BasicTokenBridge.sol index 0b12e2866..15723b45b 100644 --- a/contracts/upgradeable_contracts/BasicTokenBridge.sol +++ b/contracts/upgradeable_contracts/BasicTokenBridge.sol @@ -10,12 +10,12 @@ contract BasicTokenBridge is EternalStorage, Ownable { event DailyLimitChanged(uint256 newLimit); event ExecutionDailyLimitChanged(uint256 newLimit); - bytes32 internal constant MIN_PER_TX = keccak256(abi.encodePacked("minPerTx")); - bytes32 internal constant MAX_PER_TX = keccak256(abi.encodePacked("maxPerTx")); - bytes32 internal constant DAILY_LIMIT = keccak256(abi.encodePacked("dailyLimit")); - bytes32 internal constant EXECUTION_MAX_PER_TX = keccak256(abi.encodePacked("executionMaxPerTx")); - bytes32 internal constant EXECUTION_DAILY_LIMIT = keccak256(abi.encodePacked("executionDailyLimit")); - bytes32 internal constant DECIMAL_SHIFT = keccak256(abi.encodePacked("decimalShift")); + bytes32 internal constant MIN_PER_TX = 0xbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d1; // keccak256(abi.encodePacked("minPerTx")) + bytes32 internal constant MAX_PER_TX = 0x0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c; // keccak256(abi.encodePacked("maxPerTx")) + bytes32 internal constant DAILY_LIMIT = 0x4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a5; // keccak256(abi.encodePacked("dailyLimit")) + bytes32 internal constant EXECUTION_MAX_PER_TX = 0xc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d5; // keccak256(abi.encodePacked("executionMaxPerTx")) + bytes32 internal constant EXECUTION_DAILY_LIMIT = 0x21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d237; // keccak256(abi.encodePacked("executionDailyLimit")) + bytes32 internal constant DECIMAL_SHIFT = 0x1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee5; // keccak256(abi.encodePacked("decimalShift")) function totalSpentPerDay(uint256 _day) public view returns (uint256) { return uintStorage[keccak256(abi.encodePacked("totalSpentPerDay", _day))]; diff --git a/contracts/upgradeable_contracts/BlockRewardBridge.sol b/contracts/upgradeable_contracts/BlockRewardBridge.sol index 1441f9a0c..440aa19ad 100644 --- a/contracts/upgradeable_contracts/BlockRewardBridge.sol +++ b/contracts/upgradeable_contracts/BlockRewardBridge.sol @@ -5,7 +5,7 @@ import "../upgradeability/EternalStorage.sol"; import "openzeppelin-solidity/contracts/AddressUtils.sol"; contract BlockRewardBridge is EternalStorage { - bytes32 internal constant BLOCK_REWARD_CONTRACT = keccak256(abi.encodePacked("blockRewardContract")); + bytes32 internal constant BLOCK_REWARD_CONTRACT = 0x20ae0b8a761b32f3124efb075f427dd6ca669e88ae7747fec9fd1ad688699f32; // keccak256(abi.encodePacked("blockRewardContract")) bytes4 internal constant BLOCK_REWARD_CONTRACT_ID = 0x2ee57f8d; // blockRewardContractId() bytes4 internal constant BRIDGES_ALLOWED_LENGTH = 0x10f2ee7c; // bridgesAllowedLength() diff --git a/contracts/upgradeable_contracts/ERC20Bridge.sol b/contracts/upgradeable_contracts/ERC20Bridge.sol index b14a09516..a7600c7d9 100644 --- a/contracts/upgradeable_contracts/ERC20Bridge.sol +++ b/contracts/upgradeable_contracts/ERC20Bridge.sol @@ -1,14 +1,14 @@ pragma solidity 0.4.24; import "../upgradeability/EternalStorage.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; import "openzeppelin-solidity/contracts/AddressUtils.sol"; contract ERC20Bridge is EternalStorage { - bytes32 internal constant ERC20_TOKEN = keccak256(abi.encodePacked("erc20token")); + bytes32 internal constant ERC20_TOKEN = 0x15d63b18dbc21bf4438b7972d80076747e1d93c4f87552fe498c90cbde51665e; // keccak256(abi.encodePacked("erc20token")) - function erc20token() public view returns (ERC20Basic) { - return ERC20Basic(addressStorage[ERC20_TOKEN]); + function erc20token() public view returns (ERC20) { + return ERC20(addressStorage[ERC20_TOKEN]); } function setErc20token(address _token) internal { diff --git a/contracts/upgradeable_contracts/ERC677Storage.sol b/contracts/upgradeable_contracts/ERC677Storage.sol index ff9de3170..8ec53a028 100644 --- a/contracts/upgradeable_contracts/ERC677Storage.sol +++ b/contracts/upgradeable_contracts/ERC677Storage.sol @@ -1,5 +1,5 @@ pragma solidity 0.4.24; contract ERC677Storage { - bytes32 internal constant ERC677_TOKEN = keccak256(abi.encodePacked("erc677token")); + bytes32 internal constant ERC677_TOKEN = 0xa8b0ade3e2b734f043ce298aca4cc8d19d74270223f34531d0988b7d00cba21d; // keccak256(abi.encodePacked("erc677token")) } diff --git a/contracts/upgradeable_contracts/FeeTypes.sol b/contracts/upgradeable_contracts/FeeTypes.sol index 334980462..7018c9ccb 100644 --- a/contracts/upgradeable_contracts/FeeTypes.sol +++ b/contracts/upgradeable_contracts/FeeTypes.sol @@ -1,6 +1,6 @@ pragma solidity 0.4.24; contract FeeTypes { - bytes32 internal constant HOME_FEE = keccak256(abi.encodePacked("home-fee")); - bytes32 internal constant FOREIGN_FEE = keccak256(abi.encodePacked("foreign-fee")); + bytes32 internal constant HOME_FEE = 0x89d93e5e92f7e37e490c25f0e50f7f4aad7cc94b308a566553280967be38bcf1; // keccak256(abi.encodePacked("home-fee")) + bytes32 internal constant FOREIGN_FEE = 0xdeb7f3adca07d6d1f708c1774389db532a2b2f18fd05a62b957e4089f4696ed5; // keccak256(abi.encodePacked("foreign-fee")) } diff --git a/contracts/upgradeable_contracts/Initializable.sol b/contracts/upgradeable_contracts/Initializable.sol index 63a1c5860..691771392 100644 --- a/contracts/upgradeable_contracts/Initializable.sol +++ b/contracts/upgradeable_contracts/Initializable.sol @@ -3,7 +3,7 @@ pragma solidity 0.4.24; import "../upgradeability/EternalStorage.sol"; contract Initializable is EternalStorage { - bytes32 internal constant INITIALIZED = keccak256(abi.encodePacked("isInitialized")); + bytes32 internal constant INITIALIZED = 0x0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba; // keccak256(abi.encodePacked("isInitialized")) function setInitialize() internal { boolStorage[INITIALIZED] = true; diff --git a/contracts/upgradeable_contracts/InitializableBridge.sol b/contracts/upgradeable_contracts/InitializableBridge.sol index d07778964..757711a9e 100644 --- a/contracts/upgradeable_contracts/InitializableBridge.sol +++ b/contracts/upgradeable_contracts/InitializableBridge.sol @@ -3,7 +3,7 @@ pragma solidity 0.4.24; import "./Initializable.sol"; contract InitializableBridge is Initializable { - bytes32 internal constant DEPLOYED_AT_BLOCK = keccak256(abi.encodePacked("deployedAtBlock")); + bytes32 internal constant DEPLOYED_AT_BLOCK = 0xb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b0; // keccak256(abi.encodePacked("deployedAtBlock")); function deployedAtBlock() external view returns (uint256) { return uintStorage[DEPLOYED_AT_BLOCK]; diff --git a/contracts/upgradeable_contracts/Ownable.sol b/contracts/upgradeable_contracts/Ownable.sol index bf2d7a744..e1220e8c6 100644 --- a/contracts/upgradeable_contracts/Ownable.sol +++ b/contracts/upgradeable_contracts/Ownable.sol @@ -23,12 +23,14 @@ contract Ownable is EternalStorage { _; } + bytes32 internal constant OWNER = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0; // keccak256(abi.encodePacked("owner")) + /** * @dev Tells the address of the owner * @return the address of the owner */ function owner() public view returns (address) { - return addressStorage[keccak256(abi.encodePacked("owner"))]; + return addressStorage[OWNER]; } /** @@ -45,6 +47,6 @@ contract Ownable is EternalStorage { */ function setOwner(address newOwner) internal { emit OwnershipTransferred(owner(), newOwner); - addressStorage[keccak256(abi.encodePacked("owner"))] = newOwner; + addressStorage[OWNER] = newOwner; } } diff --git a/contracts/upgradeable_contracts/ReentrancyGuard.sol b/contracts/upgradeable_contracts/ReentrancyGuard.sol index 8df9be0b1..14c6874ac 100644 --- a/contracts/upgradeable_contracts/ReentrancyGuard.sol +++ b/contracts/upgradeable_contracts/ReentrancyGuard.sol @@ -3,7 +3,7 @@ pragma solidity 0.4.24; import "../upgradeability/EternalStorage.sol"; contract ReentrancyGuard is EternalStorage { - bytes32 internal constant LOCK = keccak256(abi.encodePacked("lock")); + bytes32 internal constant LOCK = 0x6168652c307c1e813ca11cfb3a601f1cf3b22452021a5052d8b05f1f1f8a3e92; // keccak256(abi.encodePacked("lock")) function lock() internal returns (bool) { return boolStorage[LOCK]; diff --git a/contracts/upgradeable_contracts/RewardableBridge.sol b/contracts/upgradeable_contracts/RewardableBridge.sol index e72ac30ae..48a349128 100644 --- a/contracts/upgradeable_contracts/RewardableBridge.sol +++ b/contracts/upgradeable_contracts/RewardableBridge.sol @@ -8,7 +8,7 @@ contract RewardableBridge is Ownable, FeeTypes { event FeeDistributedFromAffirmation(uint256 feeAmount, bytes32 indexed transactionHash); event FeeDistributedFromSignatures(uint256 feeAmount, bytes32 indexed transactionHash); - bytes32 internal constant FEE_MANAGER_CONTRACT = keccak256(abi.encodePacked("feeManagerContract")); + bytes32 internal constant FEE_MANAGER_CONTRACT = 0x779a349c5bee7817f04c960f525ee3e2f2516078c38c68a3149787976ee837e5; // keccak256(abi.encodePacked("feeManagerContract")) bytes4 internal constant GET_HOME_FEE = 0x94da17cd; // getHomeFee() bytes4 internal constant GET_FOREIGN_FEE = 0xffd66196; // getForeignFee() bytes4 internal constant GET_FEE_MANAGER_MODE = 0xf2ba9561; // getFeeManagerMode() diff --git a/contracts/upgradeable_contracts/ValidatorStorage.sol b/contracts/upgradeable_contracts/ValidatorStorage.sol index c14d4a5af..7230f047a 100644 --- a/contracts/upgradeable_contracts/ValidatorStorage.sol +++ b/contracts/upgradeable_contracts/ValidatorStorage.sol @@ -1,5 +1,5 @@ pragma solidity 0.4.24; contract ValidatorStorage { - bytes32 internal constant VALIDATOR_CONTRACT = keccak256(abi.encodePacked("validatorContract")); + bytes32 internal constant VALIDATOR_CONTRACT = 0x5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe; // keccak256(abi.encodePacked("validatorContract")) } diff --git a/contracts/upgradeable_contracts/ValidatorsFeeManager.sol b/contracts/upgradeable_contracts/ValidatorsFeeManager.sol index aa7e098a2..c30dac87f 100644 --- a/contracts/upgradeable_contracts/ValidatorsFeeManager.sol +++ b/contracts/upgradeable_contracts/ValidatorsFeeManager.sol @@ -5,13 +5,8 @@ import "../interfaces/IRewardableValidators.sol"; import "./ValidatorStorage.sol"; contract ValidatorsFeeManager is BaseFeeManager, ValidatorStorage { - bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_HOME = keccak256( - abi.encodePacked("reward-transferring-from-home") - ); - - bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_FOREIGN = keccak256( - abi.encodePacked("reward-transferring-from-foreign") - ); + bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_HOME = 0x2a11db67c480122765825a7e4bc5428e8b7b9eca0d4e62b91aac194f99edd0d7; // keccak256(abi.encodePacked("reward-transferring-from-home")) + bytes32 public constant REWARD_FOR_TRANSFERRING_FROM_FOREIGN = 0xb14796d751eb4f2570065a479f9e526eabeb2077c564c8a1c5ea559883ea2fab; // keccak256(abi.encodePacked("reward-transferring-from-foreign")) function distributeFeeFromAffirmation(uint256 _fee) external { distributeFeeProportionally(_fee, REWARD_FOR_TRANSFERRING_FROM_FOREIGN); diff --git a/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicAMBErc677ToErc677.sol b/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicAMBErc677ToErc677.sol index c338f9d1e..28493eaa7 100644 --- a/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicAMBErc677ToErc677.sol +++ b/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicAMBErc677ToErc677.sol @@ -24,10 +24,10 @@ contract BasicAMBErc677ToErc677 is { event FailedMessageFixed(bytes32 indexed dataHash, address recipient, uint256 value); - bytes32 internal constant BRIDGE_CONTRACT = keccak256(abi.encodePacked("bridgeContract")); - bytes32 internal constant MEDIATOR_CONTRACT = keccak256(abi.encodePacked("mediatorContract")); - bytes32 internal constant REQUEST_GAS_LIMIT = keccak256(abi.encodePacked("requestGasLimit")); - bytes32 internal constant NONCE = keccak256(abi.encodePacked("nonce")); + bytes32 internal constant BRIDGE_CONTRACT = 0x811bbb11e8899da471f0e69a3ed55090fc90215227fc5fb1cb0d6e962ea7b74f; // keccak256(abi.encodePacked("bridgeContract")) + bytes32 internal constant MEDIATOR_CONTRACT = 0x98aa806e31e94a687a31c65769cb99670064dd7f5a87526da075c5fb4eab9880; // keccak256(abi.encodePacked("mediatorContract")) + bytes32 internal constant REQUEST_GAS_LIMIT = 0x2dfd6c9f781bb6bbb5369c114e949b69ebb440ef3d4dd6b2836225eb1dc3a2be; // keccak256(abi.encodePacked("requestGasLimit")) + bytes32 internal constant NONCE = 0x7ab1577440dd7bedf920cb6de2f9fc6bf7ba98c78c85a3fa1f8311aac95e1759; // keccak256(abi.encodePacked("nonce")) function initialize( address _bridgeContract, @@ -119,7 +119,7 @@ contract BasicAMBErc677ToErc677 is } function getBridgeMode() external pure returns (bytes4 _data) { - return bytes4(keccak256(abi.encodePacked("erc-to-erc-amb"))); + return 0x76595b56; // bytes4(keccak256(abi.encodePacked("erc-to-erc-amb"))) } function setBridgeContract(address _bridgeContract) external onlyOwner { diff --git a/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol b/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol index 84eb575c8..fa48373d9 100644 --- a/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol +++ b/contracts/upgradeable_contracts/arbitrary_message/BasicAMB.sol @@ -3,7 +3,7 @@ pragma solidity 0.4.24; import "../BasicBridge.sol"; contract BasicAMB is BasicBridge { - bytes32 internal constant MAX_GAS_PER_TX = keccak256(abi.encodePacked("maxGasPerTx")); + bytes32 internal constant MAX_GAS_PER_TX = 0x2670ecc91ec356e32067fd27b36614132d727b84a1e03e08f412a4f2cf075974; // keccak256(abi.encodePacked("maxGasPerTx")) function initialize( address _validatorContract, @@ -32,7 +32,7 @@ contract BasicAMB is BasicBridge { } function getBridgeMode() external pure returns (bytes4 _data) { - return bytes4(keccak256(abi.encodePacked("arbitrary-message-bridge-core"))); + return 0x2544fbb9; // bytes4(keccak256(abi.encodePacked("arbitrary-message-bridge-core"))) } function maxGasPerTx() public view returns (uint256) { diff --git a/contracts/upgradeable_contracts/arbitrary_message/MessageProcessor.sol b/contracts/upgradeable_contracts/arbitrary_message/MessageProcessor.sol index 16792b3c1..220e3a862 100644 --- a/contracts/upgradeable_contracts/arbitrary_message/MessageProcessor.sol +++ b/contracts/upgradeable_contracts/arbitrary_message/MessageProcessor.sol @@ -4,8 +4,8 @@ import "../../upgradeability/EternalStorage.sol"; import "../../libraries/Bytes.sol"; contract MessageProcessor is EternalStorage { - bytes32 internal constant MESSAGE_SENDER = keccak256(abi.encodePacked("messageSender")); - bytes32 internal constant TRANSACTION_HASH = keccak256(abi.encodePacked("transactionHash")); + bytes32 internal constant MESSAGE_SENDER = 0x7b58b2a669d8e0992eae9eaef641092c0f686fd31070e7236865557fa1571b5b; // keccak256(abi.encodePacked("messageSender")) + bytes32 internal constant TRANSACTION_HASH = 0x7bce44346b9831b0c81437a092605c6fc51612016e2c51e62f21d829e434bcf6; // keccak256(abi.encodePacked("transactionHash")) function messageCallStatus(bytes32 _txHash) external view returns (bool) { return boolStorage[keccak256(abi.encodePacked("messageCallStatus", _txHash))]; diff --git a/contracts/upgradeable_contracts/erc20_to_erc20/BasicForeignBridgeErcToErc.sol b/contracts/upgradeable_contracts/erc20_to_erc20/BasicForeignBridgeErcToErc.sol index b6cbc1406..3872d5593 100644 --- a/contracts/upgradeable_contracts/erc20_to_erc20/BasicForeignBridgeErcToErc.sol +++ b/contracts/upgradeable_contracts/erc20_to_erc20/BasicForeignBridgeErcToErc.sol @@ -1,7 +1,7 @@ pragma solidity 0.4.24; import "../BasicForeignBridge.sol"; -import "openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol"; +import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; contract BasicForeignBridgeErcToErc is BasicForeignBridge { function _initialize( @@ -38,7 +38,7 @@ contract BasicForeignBridgeErcToErc is BasicForeignBridge { } function getBridgeMode() external pure returns (bytes4 _data) { - return bytes4(keccak256(abi.encodePacked("erc-to-erc-core"))); + return 0xba4690f5; // bytes4(keccak256(abi.encodePacked("erc-to-erc-core"))) } function claimTokens(address _token, address _to) public { @@ -61,7 +61,7 @@ contract BasicForeignBridgeErcToErc is BasicForeignBridge { } /* solcov ignore next */ - function erc20token() public view returns (ERC20Basic); + function erc20token() public view returns (ERC20); /* solcov ignore next */ function setErc20token(address _token) internal; diff --git a/contracts/upgradeable_contracts/erc20_to_erc20/FeeManagerErcToErcPOSDAO.sol b/contracts/upgradeable_contracts/erc20_to_erc20/FeeManagerErcToErcPOSDAO.sol index 5d1e83976..5573c64c1 100644 --- a/contracts/upgradeable_contracts/erc20_to_erc20/FeeManagerErcToErcPOSDAO.sol +++ b/contracts/upgradeable_contracts/erc20_to_erc20/FeeManagerErcToErcPOSDAO.sol @@ -4,7 +4,7 @@ import "../BlockRewardFeeManager.sol"; contract FeeManagerErcToErcPOSDAO is BlockRewardFeeManager { function getFeeManagerMode() external pure returns (bytes4) { - return bytes4(keccak256(abi.encodePacked("manages-both-directions"))); + return 0xd7de965f; // bytes4(keccak256(abi.encodePacked("manages-both-directions"))) } function blockRewardContract() external view returns (address) { diff --git a/contracts/upgradeable_contracts/erc20_to_erc20/ForeignBridgeErc677ToErc677.sol b/contracts/upgradeable_contracts/erc20_to_erc20/ForeignBridgeErc677ToErc677.sol index 27fa5a326..ecaf98d5f 100644 --- a/contracts/upgradeable_contracts/erc20_to_erc20/ForeignBridgeErc677ToErc677.sol +++ b/contracts/upgradeable_contracts/erc20_to_erc20/ForeignBridgeErc677ToErc677.sol @@ -43,7 +43,7 @@ contract ForeignBridgeErc677ToErc677 is ERC677Bridge, BasicForeignBridgeErcToErc return isInitialized(); } - function erc20token() public view returns (ERC20Basic) { + function erc20token() public view returns (ERC20) { return erc677token(); } diff --git a/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol b/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol index 74b2cc492..65ed05952 100644 --- a/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol +++ b/contracts/upgradeable_contracts/erc20_to_erc20/HomeBridgeErcToErc.sol @@ -141,7 +141,7 @@ contract HomeBridgeErcToErc is } function getBridgeMode() external pure returns (bytes4 _data) { - return bytes4(keccak256(abi.encodePacked("erc-to-erc-core"))); + return 0xba4690f5; // bytes4(keccak256(abi.encodePacked("erc-to-erc-core"))) } function onExecuteAffirmation(address _recipient, uint256 _value, bytes32 txHash) internal returns (bool) { diff --git a/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNative.sol b/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNative.sol index 30a6cec51..7a3698587 100644 --- a/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNative.sol +++ b/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNative.sol @@ -7,7 +7,7 @@ import "../BlockRewardBridge.sol"; contract FeeManagerErcToNative is ValidatorsFeeManager, BlockRewardBridge { function getFeeManagerMode() external pure returns (bytes4) { - return bytes4(keccak256(abi.encodePacked("manages-both-directions"))); + return 0xd7de965f; // bytes4(keccak256(abi.encodePacked("manages-both-directions"))) } function onAffirmationFeeDistribution(address _rewardAddress, uint256 _fee) internal { diff --git a/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNativePOSDAO.sol b/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNativePOSDAO.sol index ef4e24f63..a4a43b3a8 100644 --- a/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNativePOSDAO.sol +++ b/contracts/upgradeable_contracts/erc20_to_native/FeeManagerErcToNativePOSDAO.sol @@ -5,7 +5,7 @@ import "../BlockRewardFeeManager.sol"; contract FeeManagerErcToNativePOSDAO is BlockRewardFeeManager { function getFeeManagerMode() external pure returns (bytes4) { - return bytes4(keccak256(abi.encodePacked("manages-both-directions"))); + return 0xd7de965f; // bytes4(keccak256(abi.encodePacked("manages-both-directions"))) } function distributeFeeFromBlockReward(uint256 _fee) internal { diff --git a/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol b/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol index 712174b89..262cedab4 100644 --- a/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol +++ b/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol @@ -5,44 +5,59 @@ import "../ERC20Bridge.sol"; contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge { event RelayedMessage(address recipient, uint256 value, bytes32 transactionHash); + event UserRequestForAffirmation(address recipient, uint256 value); + + bytes32 internal constant BRIDGE_CONTRACT = 0x71483949fe7a14d16644d63320f24d10cf1d60abecc30cc677a340e82b699dd2; // keccak256(abi.encodePacked("bridgeOnOtherSide")) function initialize( address _validatorContract, address _erc20token, uint256 _requiredBlockConfirmations, uint256 _gasPrice, - uint256[] _maxPerTxHomeDailyLimitHomeMaxPerTxArray, //[ 0 = _maxPerTx, 1 = _homeDailyLimit, 2 = _homeMaxPerTx ] + uint256[] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ] + uint256[] _homeDailyLimitHomeMaxPerTxArray, //[ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ] address _owner, - uint256 _decimalShift + uint256 _decimalShift, + address _bridgeOnOtherSide ) external returns (bool) { require(!isInitialized()); require(AddressUtils.isContract(_validatorContract)); require(_requiredBlockConfirmations != 0); require(_gasPrice > 0); - require(_maxPerTxHomeDailyLimitHomeMaxPerTxArray[2] < _maxPerTxHomeDailyLimitHomeMaxPerTxArray[1]); // _homeMaxPerTx < _homeDailyLimit + require( + _dailyLimitMaxPerTxMinPerTxArray[2] > 0 && // _minPerTx > 0 + _dailyLimitMaxPerTxMinPerTxArray[1] > _dailyLimitMaxPerTxMinPerTxArray[2] && // _maxPerTx > _minPerTx + _dailyLimitMaxPerTxMinPerTxArray[0] > _dailyLimitMaxPerTxMinPerTxArray[1] // _dailyLimit > _maxPerTx + ); + require(_homeDailyLimitHomeMaxPerTxArray[1] < _homeDailyLimitHomeMaxPerTxArray[0]); // _homeMaxPerTx < _homeDailyLimit require(_owner != address(0)); + require(_bridgeOnOtherSide != address(0)); addressStorage[VALIDATOR_CONTRACT] = _validatorContract; setErc20token(_erc20token); uintStorage[DEPLOYED_AT_BLOCK] = block.number; uintStorage[REQUIRED_BLOCK_CONFIRMATIONS] = _requiredBlockConfirmations; uintStorage[GAS_PRICE] = _gasPrice; - uintStorage[MAX_PER_TX] = _maxPerTxHomeDailyLimitHomeMaxPerTxArray[0]; - uintStorage[EXECUTION_DAILY_LIMIT] = _maxPerTxHomeDailyLimitHomeMaxPerTxArray[1]; - uintStorage[EXECUTION_MAX_PER_TX] = _maxPerTxHomeDailyLimitHomeMaxPerTxArray[2]; + uintStorage[DAILY_LIMIT] = _dailyLimitMaxPerTxMinPerTxArray[0]; + uintStorage[MAX_PER_TX] = _dailyLimitMaxPerTxMinPerTxArray[1]; + uintStorage[MIN_PER_TX] = _dailyLimitMaxPerTxMinPerTxArray[2]; + uintStorage[EXECUTION_DAILY_LIMIT] = _homeDailyLimitHomeMaxPerTxArray[0]; + uintStorage[EXECUTION_MAX_PER_TX] = _homeDailyLimitHomeMaxPerTxArray[1]; uintStorage[DECIMAL_SHIFT] = _decimalShift; setOwner(_owner); + _setBridgeContractOnOtherSide(_bridgeOnOtherSide); setInitialize(); emit RequiredBlockConfirmationChanged(_requiredBlockConfirmations); emit GasPriceChanged(_gasPrice); - emit ExecutionDailyLimitChanged(_maxPerTxHomeDailyLimitHomeMaxPerTxArray[1]); + emit DailyLimitChanged(_dailyLimitMaxPerTxMinPerTxArray[0]); + emit ExecutionDailyLimitChanged(_homeDailyLimitHomeMaxPerTxArray[0]); return isInitialized(); } function getBridgeMode() external pure returns (bytes4 _data) { - return bytes4(keccak256(abi.encodePacked("erc-to-native-core"))); + return 0x18762d46; // bytes4(keccak256(abi.encodePacked("erc-to-native-core"))) } function claimTokens(address _token, address _to) public { @@ -63,4 +78,33 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge { function onFailedMessage(address, uint256, bytes32) internal { revert(); } + + function _setBridgeContractOnOtherSide(address _bridgeContract) internal { + addressStorage[BRIDGE_CONTRACT] = _bridgeContract; + } + + function bridgeContractOnOtherSide() public view returns (address) { + return addressStorage[BRIDGE_CONTRACT]; + } + + function _relayTokens(address _sender, address _receiver, uint256 _amount) internal { + require(_receiver != address(0)); + require(_receiver != address(this)); + require(_receiver != bridgeContractOnOtherSide()); + require(_amount > 0); + require(withinLimit(_amount)); + setTotalSpentPerDay(getCurrentDay(), totalSpentPerDay(getCurrentDay()).add(_amount)); + + erc20token().transferFrom(_sender, address(this), _amount); + emit UserRequestForAffirmation(_receiver, _amount); + } + + function relayTokens(address _from, address _receiver, uint256 _amount) external { + require(_from == msg.sender || _from == _receiver); + _relayTokens(_from, _receiver, _amount); + } + + function relayTokens(address _receiver, uint256 _amount) external { + _relayTokens(msg.sender, _receiver, _amount); + } } diff --git a/contracts/upgradeable_contracts/erc20_to_native/HomeBridgeErcToNative.sol b/contracts/upgradeable_contracts/erc20_to_native/HomeBridgeErcToNative.sol index c8ec25739..52ede28af 100644 --- a/contracts/upgradeable_contracts/erc20_to_native/HomeBridgeErcToNative.sol +++ b/contracts/upgradeable_contracts/erc20_to_native/HomeBridgeErcToNative.sol @@ -16,15 +16,15 @@ contract HomeBridgeErcToNative is RewardableHomeBridgeErcToNative, BlockRewardBridge { - bytes32 internal constant TOTAL_BURNT_COINS = keccak256(abi.encodePacked("totalBurntCoins")); + bytes32 internal constant TOTAL_BURNT_COINS = 0x17f187b2e5d1f8770602b32c1159b85c9600859277fae1eaa9982e9bcf63384c; // keccak256(abi.encodePacked("totalBurntCoins")) function() public payable { - nativeTransfer(); + require(msg.data.length == 0); + nativeTransfer(msg.sender); } - function nativeTransfer() internal { + function nativeTransfer(address _receiver) internal { require(msg.value > 0); - require(msg.data.length == 0); require(withinLimit(msg.value)); IBlockReward blockReward = blockRewardContract(); uint256 totalMinted = blockReward.mintedTotallyByBridge(address(this)); @@ -41,7 +41,11 @@ contract HomeBridgeErcToNative is } setTotalBurntCoins(totalBurnt.add(valueToBurn)); address(0).transfer(valueToBurn); - emit UserRequestForSignature(msg.sender, valueToTransfer); + emit UserRequestForSignature(_receiver, valueToTransfer); + } + + function relayTokens(address _receiver) external payable { + nativeTransfer(_receiver); } function initialize( @@ -101,7 +105,7 @@ contract HomeBridgeErcToNative is } function getBridgeMode() external pure returns (bytes4 _data) { - return bytes4(keccak256(abi.encodePacked("erc-to-native-core"))); + return 0x18762d46; // bytes4(keccak256(abi.encodePacked("erc-to-native-core"))) } function blockRewardContract() public view returns (IBlockReward) { diff --git a/contracts/upgradeable_contracts/native_to_erc20/ClassicHomeBridgeNativeToErc.sol b/contracts/upgradeable_contracts/native_to_erc20/ClassicHomeBridgeNativeToErc.sol index 680b10d50..74ec8e291 100644 --- a/contracts/upgradeable_contracts/native_to_erc20/ClassicHomeBridgeNativeToErc.sol +++ b/contracts/upgradeable_contracts/native_to_erc20/ClassicHomeBridgeNativeToErc.sol @@ -21,7 +21,7 @@ contract ClassicHomeBridgeNativeToErc is HomeBridgeNativeToErc { _owner, _decimalShift ); - uintStorage[keccak256(abi.encodePacked("dataSizes", bytes4(keccak256("signature(bytes32,uint256)"))))] = 132; - uintStorage[keccak256(abi.encodePacked("dataSizes", bytes4(keccak256("message(bytes32)"))))] = 210; + uintStorage[0x5e16d82565fc7ee8775cc18db290ff4010745d3fd46274a7bc7ddbebb727fa54] = 132; // keccak256(abi.encodePacked("dataSizes", bytes4(keccak256("signature(bytes32,uint256)")))) + uintStorage[0x3b0a1ac531be1657049cf649eca2510ce9e3ef7df1be26d5c248fe8b298f4374] = 210; // keccak256(abi.encodePacked("dataSizes", bytes4(keccak256("message(bytes32)")))) } } diff --git a/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErc.sol b/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErc.sol index 032c82ca5..9919526a5 100644 --- a/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErc.sol +++ b/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErc.sol @@ -7,7 +7,7 @@ import "../ERC677Storage.sol"; contract FeeManagerNativeToErc is ValidatorsFeeManager, ERC677Storage { function getFeeManagerMode() external pure returns (bytes4) { - return bytes4(keccak256(abi.encodePacked("manages-one-direction"))); + return 0xf2aed8f7; // bytes4(keccak256(abi.encodePacked("manages-one-direction"))) } function erc677token() public view returns (IBurnableMintableERC677Token) { diff --git a/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErcBothDirections.sol b/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErcBothDirections.sol index b61f44599..9a61cfafc 100644 --- a/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErcBothDirections.sol +++ b/contracts/upgradeable_contracts/native_to_erc20/FeeManagerNativeToErcBothDirections.sol @@ -5,7 +5,7 @@ import "../ValidatorsFeeManager.sol"; contract FeeManagerNativeToErcBothDirections is ValidatorsFeeManager { function getFeeManagerMode() external pure returns (bytes4) { - return bytes4(keccak256(abi.encodePacked("manages-both-directions"))); + return 0xd7de965f; // bytes4(keccak256(abi.encodePacked("manages-both-directions"))) } function onAffirmationFeeDistribution(address _rewardAddress, uint256 _fee) internal { diff --git a/contracts/upgradeable_contracts/native_to_erc20/ForeignBridgeNativeToErc.sol b/contracts/upgradeable_contracts/native_to_erc20/ForeignBridgeNativeToErc.sol index b77c9716d..74b581649 100644 --- a/contracts/upgradeable_contracts/native_to_erc20/ForeignBridgeNativeToErc.sol +++ b/contracts/upgradeable_contracts/native_to_erc20/ForeignBridgeNativeToErc.sol @@ -68,7 +68,7 @@ contract ForeignBridgeNativeToErc is } function getBridgeMode() external pure returns (bytes4 _data) { - return bytes4(keccak256(abi.encodePacked("native-to-erc-core"))); + return 0x92a8d7fe; // bytes4(keccak256(abi.encodePacked("native-to-erc-core"))) } function claimTokensFromErc677(address _token, address _to) external onlyIfUpgradeabilityOwner { diff --git a/contracts/upgradeable_contracts/native_to_erc20/HomeBridgeNativeToErc.sol b/contracts/upgradeable_contracts/native_to_erc20/HomeBridgeNativeToErc.sol index 07ea687e1..4617f2407 100644 --- a/contracts/upgradeable_contracts/native_to_erc20/HomeBridgeNativeToErc.sol +++ b/contracts/upgradeable_contracts/native_to_erc20/HomeBridgeNativeToErc.sol @@ -76,7 +76,7 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicHomeBridge, RewardableHom } function getBridgeMode() external pure returns (bytes4 _data) { - return bytes4(keccak256(abi.encodePacked("native-to-erc-core"))); + return 0x92a8d7fe; // bytes4(keccak256(abi.encodePacked("native-to-erc-core"))) } function _initialize( diff --git a/deploy/deploy.js b/deploy/deploy.js index 287c7ab72..17a8b0216 100644 --- a/deploy/deploy.js +++ b/deploy/deploy.js @@ -73,7 +73,7 @@ async function deployErcToNative() { const deployForeign = require('./src/erc_to_native/foreign') await preDeploy() const { homeBridge } = await deployHome() - const { foreignBridge } = await deployForeign() + const { foreignBridge } = await deployForeign(homeBridge.address) console.log('\nDeployment has been completed.\n\n') console.log(`[ Home ] HomeBridge: ${homeBridge.address} at block ${homeBridge.deployedBlockNumber}`) console.log(`[ Foreign ] ForeignBridge: ${foreignBridge.address} at block ${foreignBridge.deployedBlockNumber}`) diff --git a/deploy/src/erc_to_native/foreign.js b/deploy/src/erc_to_native/foreign.js index 76013547a..088f6b378 100644 --- a/deploy/src/erc_to_native/foreign.js +++ b/deploy/src/erc_to_native/foreign.js @@ -27,7 +27,9 @@ const { FOREIGN_UPGRADEABLE_ADMIN, FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS, ERC20_TOKEN_ADDRESS, + FOREIGN_DAILY_LIMIT, FOREIGN_MAX_AMOUNT_PER_TX, + FOREIGN_MIN_AMOUNT_PER_TX, HOME_DAILY_LIMIT, HOME_MAX_AMOUNT_PER_TX, FOREIGN_TO_HOME_DECIMAL_SHIFT @@ -37,17 +39,22 @@ const DEPLOYMENT_ACCOUNT_ADDRESS = privateKeyToAddress(DEPLOYMENT_ACCOUNT_PRIVAT const foreignToHomeDecimalShift = FOREIGN_TO_HOME_DECIMAL_SHIFT || 0 -async function initializeBridge({ validatorsBridge, bridge, nonce }) { +async function initializeBridge({ validatorsBridge, bridge, nonce, homeBridgeAddress }) { console.log(`Foreign Validators: ${validatorsBridge.options.address}, ERC20_TOKEN_ADDRESS: ${ERC20_TOKEN_ADDRESS}, + FOREIGN_DAILY_LIMIT: ${FOREIGN_DAILY_LIMIT} which is ${Web3Utils.fromWei(FOREIGN_DAILY_LIMIT)} in eth, FOREIGN_MAX_AMOUNT_PER_TX: ${FOREIGN_MAX_AMOUNT_PER_TX} which is ${Web3Utils.fromWei( FOREIGN_MAX_AMOUNT_PER_TX )} in eth, + FOREIGN_MIN_AMOUNT_PER_TX: ${FOREIGN_MIN_AMOUNT_PER_TX} which is ${Web3Utils.fromWei( + FOREIGN_MIN_AMOUNT_PER_TX + )} in eth, FOREIGN_GAS_PRICE: ${FOREIGN_GAS_PRICE}, FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS : ${FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS}, - HOME_DAILY_LIMIT: ${HOME_DAILY_LIMIT} which is ${Web3Utils.fromWei(HOME_DAILY_LIMIT)} in eth, + HOME_DAILY_LIMIT: ${HOME_DAILY_LIMIT} which is ${Web3Utils.fromWei(HOME_DAILY_LIMIT)} in eth, HOME_MAX_AMOUNT_PER_TX: ${HOME_MAX_AMOUNT_PER_TX} which is ${Web3Utils.fromWei(HOME_MAX_AMOUNT_PER_TX)} in eth, FOREIGN_BRIDGE_OWNER: ${FOREIGN_BRIDGE_OWNER}, - FOREIGN_TO_HOME_DECIMAL_SHIFT: ${foreignToHomeDecimalShift} + FOREIGN_TO_HOME_DECIMAL_SHIFT: ${foreignToHomeDecimalShift}, + Home bridge Address: ${homeBridgeAddress} `) const initializeFBridgeData = await bridge.methods .initialize( @@ -55,9 +62,11 @@ async function initializeBridge({ validatorsBridge, bridge, nonce }) { ERC20_TOKEN_ADDRESS, FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS, FOREIGN_GAS_PRICE, - [FOREIGN_MAX_AMOUNT_PER_TX, HOME_DAILY_LIMIT, HOME_MAX_AMOUNT_PER_TX], + [FOREIGN_DAILY_LIMIT, FOREIGN_MAX_AMOUNT_PER_TX, FOREIGN_MIN_AMOUNT_PER_TX], + [HOME_DAILY_LIMIT, HOME_MAX_AMOUNT_PER_TX], FOREIGN_BRIDGE_OWNER, - foreignToHomeDecimalShift + foreignToHomeDecimalShift, + homeBridgeAddress ) .encodeABI() const txInitializeBridge = await sendRawTxForeign({ @@ -74,7 +83,7 @@ async function initializeBridge({ validatorsBridge, bridge, nonce }) { } } -async function deployForeign() { +async function deployForeign(homeBridgeAddress) { if (!Web3Utils.isAddress(ERC20_TOKEN_ADDRESS)) { throw new Error('ERC20_TOKEN_ADDRESS env var is not defined') } @@ -167,7 +176,8 @@ async function deployForeign() { await initializeBridge({ validatorsBridge: storageValidatorsForeign, bridge: foreignBridgeImplementation, - nonce + nonce, + homeBridgeAddress }) nonce++ diff --git a/deploy/src/loadEnv.js b/deploy/src/loadEnv.js index 1e92535ad..fe093c47e 100644 --- a/deploy/src/loadEnv.js +++ b/deploy/src/loadEnv.js @@ -248,7 +248,8 @@ if (BRIDGE_MODE === 'ERC_TO_NATIVE') { ERC20_TOKEN_ADDRESS: addressValidator(), BLOCK_REWARD_ADDRESS: addressValidator({ default: ZERO_ADDRESS - }) + }), + FOREIGN_MIN_AMOUNT_PER_TX: bigNumValidator() } } @@ -282,9 +283,7 @@ if (env.BRIDGE_MODE === 'NATIVE_TO_ERC') { if (env.HOME_REWARDABLE === 'BOTH_DIRECTIONS' && env.FOREIGN_REWARDABLE === 'ONE_DIRECTION') { throw new Error( - `Combination of HOME_REWARDABLE: ${env.HOME_REWARDABLE} and FOREIGN_REWARDABLE: ${ - env.FOREIGN_REWARDABLE - } should be avoided on ${env.BRIDGE_MODE} bridge mode.` + `Combination of HOME_REWARDABLE: ${env.HOME_REWARDABLE} and FOREIGN_REWARDABLE: ${env.FOREIGN_REWARDABLE} should be avoided on ${env.BRIDGE_MODE} bridge mode.` ) } } @@ -308,9 +307,7 @@ if (env.BRIDGE_MODE === 'ERC_TO_ERC') { } if (env.BRIDGE_MODE === 'ERC_TO_NATIVE') { - if (env.FOREIGN_MAX_AMOUNT_PER_TX.gte(env.FOREIGN_DAILY_LIMIT)) { - throw new Error(`FOREIGN_DAILY_LIMIT should be greater than FOREIGN_MAX_AMOUNT_PER_TX`) - } + checkLimits(env.FOREIGN_MIN_AMOUNT_PER_TX, env.FOREIGN_MAX_AMOUNT_PER_TX, env.FOREIGN_DAILY_LIMIT, foreignPrefix) if (HOME_REWARDABLE === 'ONE_DIRECTION') { throw new Error( diff --git a/test/erc_to_erc/home_bridge.test.js b/test/erc_to_erc/home_bridge.test.js index 2941c776d..fa51afc79 100644 --- a/test/erc_to_erc/home_bridge.test.js +++ b/test/erc_to_erc/home_bridge.test.js @@ -1541,8 +1541,8 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => { const message = createMessage(recipient, value, transactionHash, homeBridge.address) const signature = await sign(validators[0], message) - const rewardAddressBalanceBefore = await token.balanceOf(rewards[0]) - rewardAddressBalanceBefore.should.be.bignumber.equal('0') + const blockRewardBalanceBefore = await token.balanceOf(blockRewardContract.address) + blockRewardBalanceBefore.should.be.bignumber.equal('0') // When const { logs } = await homeBridge.submitSignature(signature, message, { from: validators[0] }).should.be.fulfilled @@ -1561,8 +1561,11 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => { const feeDistributed = await blockRewardContract.feeAmount() feeDistributed.should.be.bignumber.equal(feeAmount) - const rewardAddressBalanceAfter = await token.balanceOf(rewards[0]) + const rewardAddressBalanceAfter = await blockRewardContract.validatorRewardList(0) rewardAddressBalanceAfter.should.be.bignumber.equal(feeAmount) + + const blockRewardBalanceAfter = await token.balanceOf(blockRewardContract.address) + blockRewardBalanceAfter.should.be.bignumber.equal(feeAmount) }) it('should distribute fee to 3 validators', async () => { // Given @@ -1608,9 +1611,9 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => { const feeDistributed = await blockRewardContract.feeAmount() feeDistributed.should.be.bignumber.equal(feeAmount) - const balanceRewardAddress1 = await token.balanceOf(rewards[0]) - const balanceRewardAddress2 = await token.balanceOf(rewards[1]) - const balanceRewardAddress3 = await token.balanceOf(rewards[2]) + const balanceRewardAddress1 = await blockRewardContract.validatorRewardList(0) + const balanceRewardAddress2 = await blockRewardContract.validatorRewardList(1) + const balanceRewardAddress3 = await blockRewardContract.validatorRewardList(2) expect(balanceRewardAddress1.eq(feePerValidator) || balanceRewardAddress1.eq(feePerValidatorPlusDiff)).to.equal( true @@ -1667,11 +1670,11 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => { const feeDistributed = await blockRewardContract.feeAmount() feeDistributed.should.be.bignumber.equal(feeAmount) - const balanceRewardAddress1 = await token.balanceOf(rewards[0]) - const balanceRewardAddress2 = await token.balanceOf(rewards[1]) - const balanceRewardAddress3 = await token.balanceOf(rewards[2]) - const balanceRewardAddress4 = await token.balanceOf(rewards[3]) - const balanceRewardAddress5 = await token.balanceOf(rewards[4]) + const balanceRewardAddress1 = await blockRewardContract.validatorRewardList(0) + const balanceRewardAddress2 = await blockRewardContract.validatorRewardList(1) + const balanceRewardAddress3 = await blockRewardContract.validatorRewardList(2) + const balanceRewardAddress4 = await blockRewardContract.validatorRewardList(3) + const balanceRewardAddress5 = await blockRewardContract.validatorRewardList(4) balanceRewardAddress1.should.be.bignumber.equal(feePerValidator) balanceRewardAddress2.should.be.bignumber.equal(feePerValidator) @@ -1754,7 +1757,7 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => { const feeDistributed = await blockRewardContract.feeAmount() feeDistributed.should.be.bignumber.equal(feeAmount) - const rewardAddressBalanceAfter = await token.balanceOf(rewards[0]) + const rewardAddressBalanceAfter = await blockRewardContract.validatorRewardList(0) rewardAddressBalanceAfter.should.be.bignumber.equal(feeAmount) const recipientBalance = await token.balanceOf(recipient) @@ -1811,9 +1814,9 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => { const recipientBalance = await token.balanceOf(recipient) recipientBalance.should.be.bignumber.equal(value) - const balanceRewardAddress1 = await token.balanceOf(rewards[0]) - const balanceRewardAddress2 = await token.balanceOf(rewards[1]) - const balanceRewardAddress3 = await token.balanceOf(rewards[2]) + const balanceRewardAddress1 = await blockRewardContract.validatorRewardList(0) + const balanceRewardAddress2 = await blockRewardContract.validatorRewardList(1) + const balanceRewardAddress3 = await blockRewardContract.validatorRewardList(2) expect(balanceRewardAddress1.eq(feePerValidator) || balanceRewardAddress1.eq(feePerValidatorPlusDiff)).to.equal( true @@ -1878,11 +1881,11 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => { const recipientBalance = await token.balanceOf(recipient) recipientBalance.should.be.bignumber.equal(value) - const balanceRewardAddress1 = await token.balanceOf(rewards[0]) - const balanceRewardAddress2 = await token.balanceOf(rewards[1]) - const balanceRewardAddress3 = await token.balanceOf(rewards[2]) - const balanceRewardAddress4 = await token.balanceOf(rewards[3]) - const balanceRewardAddress5 = await token.balanceOf(rewards[4]) + const balanceRewardAddress1 = await blockRewardContract.validatorRewardList(0) + const balanceRewardAddress2 = await blockRewardContract.validatorRewardList(1) + const balanceRewardAddress3 = await blockRewardContract.validatorRewardList(2) + const balanceRewardAddress4 = await blockRewardContract.validatorRewardList(3) + const balanceRewardAddress5 = await blockRewardContract.validatorRewardList(4) balanceRewardAddress1.should.be.bignumber.equal(feePerValidator) balanceRewardAddress2.should.be.bignumber.equal(feePerValidator) diff --git a/test/erc_to_native/foreign_bridge.test.js b/test/erc_to_native/foreign_bridge.test.js index e83436337..c474e37b3 100644 --- a/test/erc_to_native/foreign_bridge.test.js +++ b/test/erc_to_native/foreign_bridge.test.js @@ -14,7 +14,9 @@ const gasPrice = web3.utils.toWei('1', 'gwei') const oneEther = ether('1') const homeDailyLimit = oneEther const homeMaxPerTx = halfEther +const dailyLimit = oneEther const maxPerTx = halfEther +const minPerTx = ether('0.01') const ZERO = toBN(0) const decimalShiftZero = 0 @@ -23,13 +25,14 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { let authorities let owner let token + let otherSideBridge before(async () => { validatorContract = await BridgeValidators.new() authorities = [accounts[1], accounts[2]] owner = accounts[0] await validatorContract.initialize(1, authorities, owner) + otherSideBridge = await ForeignBridge.new() }) - describe('#initialize', async () => { it('should initialize', async () => { token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18) @@ -42,92 +45,106 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { expect(await foreignBridge.requiredBlockConfirmations()).to.be.bignumber.equal(ZERO) expect(await foreignBridge.decimalShift()).to.be.bignumber.equal(ZERO) - await foreignBridge - .initialize( - ZERO_ADDRESS, - token.address, - requireBlockConfirmations, - gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], - owner, - decimalShiftZero - ) - .should.be.rejectedWith(ERROR_MSG) - await foreignBridge - .initialize( - validatorContract.address, - ZERO_ADDRESS, - requireBlockConfirmations, - gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], - owner, - decimalShiftZero - ) - .should.be.rejectedWith(ERROR_MSG) - await foreignBridge - .initialize( - validatorContract.address, - token.address, - 0, - gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], - owner, - decimalShiftZero - ) - .should.be.rejectedWith(ERROR_MSG) - await foreignBridge - .initialize( - validatorContract.address, - token.address, - requireBlockConfirmations, - 0, - [maxPerTx, homeDailyLimit, homeMaxPerTx], - owner, - decimalShiftZero - ) - .should.be.rejectedWith(ERROR_MSG) - await foreignBridge - .initialize( - validatorContract.address, - owner, - requireBlockConfirmations, - gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], - owner, - decimalShiftZero - ) - .should.be.rejectedWith(ERROR_MSG) - await foreignBridge - .initialize( - owner, - token.address, - requireBlockConfirmations, - gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], - owner, - decimalShiftZero - ) - .should.be.rejectedWith(ERROR_MSG) - await foreignBridge - .initialize( - validatorContract.address, - token.address, - requireBlockConfirmations, - gasPrice, - [maxPerTx, halfEther, homeMaxPerTx], - owner, - decimalShiftZero - ) - .should.be.rejectedWith(ERROR_MSG) + await foreignBridge.initialize( + ZERO_ADDRESS, + token.address, + requireBlockConfirmations, + gasPrice, + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], + owner, + decimalShiftZero, + otherSideBridge.address + ).should.be.rejected + await foreignBridge.initialize( + validatorContract.address, + ZERO_ADDRESS, + requireBlockConfirmations, + gasPrice, + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], + owner, + decimalShiftZero, + otherSideBridge.address + ).should.be.rejected + await foreignBridge.initialize( + validatorContract.address, + token.address, + 0, + gasPrice, + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], + owner, + decimalShiftZero, + otherSideBridge.address + ).should.be.rejected + await foreignBridge.initialize( + validatorContract.address, + token.address, + requireBlockConfirmations, + 0, + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], + owner, + decimalShiftZero, + otherSideBridge.address + ).should.be.rejected + await foreignBridge.initialize( + validatorContract.address, + owner, + requireBlockConfirmations, + gasPrice, + [maxPerTx, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], + owner, + decimalShiftZero, + otherSideBridge.address + ).should.be.rejected + await foreignBridge.initialize( + owner, + token.address, + requireBlockConfirmations, + gasPrice, + [dailyLimit, minPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], + owner, + decimalShiftZero, + otherSideBridge.address + ).should.be.rejected + await foreignBridge.initialize( + validatorContract.address, + token.address, + requireBlockConfirmations, + gasPrice, + [dailyLimit, maxPerTx, minPerTx], + [homeMaxPerTx, homeMaxPerTx], + owner, + decimalShiftZero, + otherSideBridge.address + ).should.be.rejected + + await foreignBridge.initialize( + validatorContract.address, + token.address, + requireBlockConfirmations, + gasPrice, + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], + owner, + '9', + ZERO_ADDRESS + ).should.be.rejected const { logs } = await foreignBridge.initialize( validatorContract.address, token.address, requireBlockConfirmations, gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], owner, - '9' + '9', + otherSideBridge.address ) expect(await foreignBridge.erc20token()).to.be.equal(token.address) @@ -137,6 +154,11 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { expect(await foreignBridge.requiredBlockConfirmations()).to.be.bignumber.equal( requireBlockConfirmations.toString() ) + expect(await foreignBridge.dailyLimit()).to.be.bignumber.equal(dailyLimit) + expect(await foreignBridge.maxPerTx()).to.be.bignumber.equal(maxPerTx) + expect(await foreignBridge.minPerTx()).to.be.bignumber.equal(minPerTx) + expect(await foreignBridge.executionDailyLimit()).to.be.bignumber.equal(homeDailyLimit) + expect(await foreignBridge.executionMaxPerTx()).to.be.bignumber.equal(homeMaxPerTx) expect(await foreignBridge.decimalShift()).to.be.bignumber.equal('9') expect(await foreignBridge.gasPrice()).to.be.bignumber.equal(gasPrice) const bridgeMode = '0x18762d46' // 4 bytes of keccak256('erc-to-native-core') @@ -150,10 +172,10 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { requiredBlockConfirmations: toBN(requireBlockConfirmations) }) expectEventInLogs(logs, 'GasPriceChanged', { gasPrice }) + expectEventInLogs(logs, 'DailyLimitChanged', { newLimit: dailyLimit }) expectEventInLogs(logs, 'ExecutionDailyLimitChanged', { newLimit: homeDailyLimit }) }) }) - describe('#executeSignatures', async () => { const value = ether('0.25') let foreignBridge @@ -165,9 +187,11 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { token.address, requireBlockConfirmations, gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], owner, - decimalShiftZero + decimalShiftZero, + otherSideBridge.address ) await token.mint(foreignBridge.address, value) }) @@ -288,7 +312,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { await foreignBridge.executeSignatures([vrs3.v], [vrs3.r], [vrs3.s], message3).should.be.rejectedWith(ERROR_MSG) }) }) - describe('#withdraw with 2 minimum signatures', async () => { let multisigValidatorContract let twoAuthorities @@ -309,9 +332,11 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { token.address, requireBlockConfirmations, gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], owner, decimalShiftZero, + otherSideBridge.address, { from: ownerOfValidatorContract } ) await token.mint(foreignBridgeWithMultiSignatures.address, value) @@ -375,9 +400,11 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { erc20Token.address, requireBlockConfirmations, gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], owner, - decimalShiftZero + decimalShiftZero, + otherSideBridge.address ) await erc20Token.mint(foreignBridgeWithThreeSigs.address, value) @@ -408,7 +435,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { true.should.be.equal(await foreignBridgeWithThreeSigs.relayedMessages(txHash)) }) }) - describe('#upgradeable', async () => { it('can be upgraded', async () => { const REQUIRED_NUMBER_OF_VALIDATORS = 1 @@ -436,9 +462,11 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { token.address, requireBlockConfirmations, gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], owner, - decimalShiftZero + decimalShiftZero, + otherSideBridge.address ) // Deploy V2 @@ -460,9 +488,11 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { tokenAddress, requireBlockConfirmations, gasPrice, - ['2', '3', '2'], + ['3', '2', '1'], + ['3', '2'], owner, - decimalShiftZero + decimalShiftZero, + otherSideBridge.address ) .encodeABI() @@ -473,7 +503,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { validatorsAddress.should.be.equal(await finalContract.validatorContract()) }) }) - describe('#claimTokens', async () => { it('can send erc20', async () => { const owner = accounts[0] @@ -488,9 +517,11 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { token.address, requireBlockConfirmations, gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], owner, - decimalShiftZero + decimalShiftZero, + otherSideBridge.address ) const tokenSecond = await ERC677BridgeToken.new('Roman Token', 'RST', 18) @@ -509,7 +540,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { expect(await tokenSecond.balanceOf(accounts[3])).to.be.bignumber.equal(halfEther) }) }) - describe('#decimalShift', async () => { const decimalShiftTwo = 2 it('Home to Foreign: withdraw with 1 signature with a decimalShift of 2', async () => { @@ -530,9 +560,11 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { token.address, requireBlockConfirmations, gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], owner, - decimalShiftTwo + decimalShiftTwo, + otherSideBridge.address ) await token.mint(foreignBridge.address, valueOnForeign) @@ -575,9 +607,11 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { token.address, requireBlockConfirmations, gasPrice, - [maxPerTx, homeDailyLimit, homeMaxPerTx], + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], owner, decimalShiftTwo, + otherSideBridge.address, { from: ownerOfValidatorContract } ) await token.mint(foreignBridgeWithMultiSignatures.address, valueOnForeign) @@ -611,4 +645,193 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { true.should.be.equal(await foreignBridgeWithMultiSignatures.relayedMessages(txHash)) }) }) + describe('#relayTokens', () => { + const value = ether('0.25') + const user = accounts[7] + const recipient = accounts[8] + 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, + [dailyLimit, maxPerTx, minPerTx], + [homeDailyLimit, homeMaxPerTx], + owner, + decimalShiftZero, + otherSideBridge.address + ) + await token.mint(user, ether('2')) + }) + it('should allow to bridge tokens using approve and relayTokens', async () => { + // Given + const currentDay = await foreignBridge.getCurrentDay() + expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) + + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + + await token.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled + + // When + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, ZERO_ADDRESS, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, foreignBridge.address, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, user, 0, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + const { logs } = await foreignBridge.methods['relayTokens(address,address,uint256)'](user, user, value, { + from: user + }).should.be.fulfilled + + // Then + expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) + expectEventInLogs(logs, 'UserRequestForAffirmation', { + recipient: user, + value + }) + }) + it('should allow to bridge tokens using approve and relayTokens with different recipient', async () => { + // Given + const currentDay = await foreignBridge.getCurrentDay() + expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) + + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + + await token.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled + + // When + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, ZERO_ADDRESS, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, foreignBridge.address, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, 0, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + const { logs } = await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { + from: user + }).should.be.fulfilled + + // Then + expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) + expectEventInLogs(logs, 'UserRequestForAffirmation', { + recipient, + value + }) + }) + it('should allow only sender to specify a different receiver', async () => { + // Given + const currentDay = await foreignBridge.getCurrentDay() + expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) + + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + + await token.approve(foreignBridge.address, oneEther, { from: user }).should.be.fulfilled + + // When + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, ZERO_ADDRESS, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, foreignBridge.address, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, 0, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { + from: recipient + }).should.be.rejectedWith(ERROR_MSG) + const { logs } = await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { + from: user + }).should.be.fulfilled + const { logs: logsSecondTx } = await foreignBridge.methods['relayTokens(address,address,uint256)']( + user, + user, + value, + { from: recipient } + ).should.be.fulfilled + + // Then + expectEventInLogs(logs, 'UserRequestForAffirmation', { + recipient, + value + }) + expectEventInLogs(logsSecondTx, 'UserRequestForAffirmation', { + recipient: user, + value + }) + }) + it('should not be able to transfer more than limit', async () => { + // Given + const userSupply = ether('2') + const bigValue = oneEther + const smallValue = ether('0.001') + const currentDay = await foreignBridge.getCurrentDay() + expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) + + await token.approve(foreignBridge.address, userSupply, { from: user }).should.be.fulfilled + + // When + // value < minPerTx + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, smallValue, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + // value > maxPerTx + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, bigValue, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, halfEther, { from: user }) + .should.be.fulfilled + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, halfEther, { from: user }) + .should.be.fulfilled + // totalSpentPerDay > dailyLimit + await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, halfEther, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + + // Then + expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(oneEther) + }) + it('should allow to call relayTokens without specifying the sender', async () => { + // Given + await foreignBridge.methods['relayTokens(address,uint256)'](recipient, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + + await token.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled + + // When + await foreignBridge.methods['relayTokens(address,uint256)'](ZERO_ADDRESS, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.methods['relayTokens(address,uint256)'](foreignBridge.address, value, { + from: user + }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.methods['relayTokens(address,uint256)'](recipient, 0, { from: user }).should.be.rejectedWith( + ERROR_MSG + ) + const { logs } = await foreignBridge.methods['relayTokens(address,uint256)'](recipient, value, { from: user }) + .should.be.fulfilled + + // Then + expectEventInLogs(logs, 'UserRequestForAffirmation', { + recipient, + value + }) + }) + }) }) diff --git a/test/erc_to_native/home_bridge.test.js b/test/erc_to_native/home_bridge.test.js index 3cb22c3f2..2e2e3de2e 100644 --- a/test/erc_to_native/home_bridge.test.js +++ b/test/erc_to_native/home_bridge.test.js @@ -36,7 +36,6 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { owner = accounts[0] await validatorContract.initialize(1, authorities, owner) }) - describe('#initialize', async () => { beforeEach(async () => { homeContract = await HomeBridge.new() @@ -291,7 +290,6 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { true.should.be.equal(await homeContract.isInitialized()) }) }) - describe('#rewardableInitialize', async () => { let feeManager let homeFee @@ -535,7 +533,6 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { expect(await homeContract.getForeignFee()).to.be.bignumber.equals(newForeignFee) }) }) - describe('#fallback', async () => { beforeEach(async () => { homeContract = await HomeBridge.new() @@ -678,7 +675,143 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { burnt.should.be.bignumber.equal('2') }) }) + describe('#relayTokens', () => { + const recipient = accounts[7] + beforeEach(async () => { + homeContract = await HomeBridge.new() + await homeContract.initialize( + validatorContract.address, + ['3', '2', '1'], + gasPrice, + requireBlockConfirmations, + blockRewardContract.address, + [foreignDailyLimit, foreignMaxPerTx], + owner, + decimalShiftZero + ) + }) + it('should accept native coins and alternative receiver', async () => { + const currentDay = await homeContract.getCurrentDay() + expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) + + await blockRewardContract.addMintedTotallyByBridge(10, homeContract.address) + const minted = await blockRewardContract.mintedTotallyByBridge(homeContract.address) + minted.should.be.bignumber.equal('10') + + const { logs } = await homeContract.relayTokens(recipient, { from: accounts[1], value: 1 }).should.be.fulfilled + + expectEventInLogs(logs, 'UserRequestForSignature', { recipient, value: toBN(1) }) + expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('1') + expect(await homeContract.totalBurntCoins()).to.be.bignumber.equal('1') + + const homeContractBalance = toBN(await web3.eth.getBalance(homeContract.address)) + homeContractBalance.should.be.bignumber.equal(ZERO) + }) + it('should accumulate burnt coins', async () => { + await blockRewardContract.addMintedTotallyByBridge(10, homeContract.address) + + const currentDay = await homeContract.getCurrentDay() + expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) + + await homeContract.relayTokens(recipient, { from: accounts[1], value: 1 }).should.be.fulfilled + expect(await homeContract.totalBurntCoins()).to.be.bignumber.equal('1') + + await homeContract.relayTokens(recipient, { from: accounts[1], value: 1 }).should.be.fulfilled + expect(await homeContract.totalBurntCoins()).to.be.bignumber.equal('2') + + await homeContract.relayTokens(recipient, { from: accounts[1], value: 1 }).should.be.fulfilled + expect(await homeContract.totalBurntCoins()).to.be.bignumber.equal('3') + + const homeContractBalance = toBN(await web3.eth.getBalance(homeContract.address)) + homeContractBalance.should.be.bignumber.equal(ZERO) + }) + it('doesnt let you send more than daily limit', async () => { + await blockRewardContract.addMintedTotallyByBridge(10, homeContract.address) + + const currentDay = await homeContract.getCurrentDay() + expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) + + await homeContract.relayTokens(recipient, { from: accounts[1], value: 1 }).should.be.fulfilled + + expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('1') + expect(await homeContract.totalBurntCoins()).to.be.bignumber.equal('1') + + await homeContract.relayTokens(recipient, { from: accounts[1], value: 1 }).should.be.fulfilled + expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('2') + + await homeContract.relayTokens(recipient, { from: accounts[1], value: 2 }).should.be.rejectedWith(ERROR_MSG) + await homeContract.setDailyLimit(4).should.be.fulfilled + await homeContract.relayTokens(recipient, { from: accounts[1], value: 2 }).should.be.fulfilled + expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('4') + expect(await homeContract.totalBurntCoins()).to.be.bignumber.equal('4') + }) + it('doesnt let you send more than max amount per tx', async () => { + await blockRewardContract.addMintedTotallyByBridge(200, homeContract.address) + + await homeContract.relayTokens(recipient, { + from: accounts[1], + value: 1 + }).should.be.fulfilled + await homeContract + .relayTokens(recipient, { + from: accounts[1], + value: 3 + }) + .should.be.rejectedWith(ERROR_MSG) + await homeContract.setMaxPerTx(100).should.be.rejectedWith(ERROR_MSG) + await homeContract.setDailyLimit(100).should.be.fulfilled + await homeContract.setMaxPerTx(99).should.be.fulfilled + // meets max per tx and daily limit + await homeContract.relayTokens(recipient, { + from: accounts[1], + value: 99 + }).should.be.fulfilled + // above daily limit + await homeContract + .relayTokens(recipient, { + from: accounts[1], + value: 1 + }) + .should.be.rejectedWith(ERROR_MSG) + }) + it('should not let to deposit less than minPerTx', async () => { + const newDailyLimit = 100 + const newMaxPerTx = 50 + const newMinPerTx = 20 + + await blockRewardContract.addMintedTotallyByBridge(200, homeContract.address) + + await homeContract.setDailyLimit(newDailyLimit).should.be.fulfilled + await homeContract.setMaxPerTx(newMaxPerTx).should.be.fulfilled + await homeContract.setMinPerTx(newMinPerTx).should.be.fulfilled + + await homeContract.relayTokens(recipient, { from: accounts[1], value: newMinPerTx }).should.be.fulfilled + await homeContract + .relayTokens(recipient, { from: accounts[1], value: newMinPerTx - 1 }) + .should.be.rejectedWith(ERROR_MSG) + }) + it('should fail if not enough bridged tokens', async () => { + const initiallyMinted = await blockRewardContract.mintedTotallyByBridge(homeContract.address) + initiallyMinted.should.be.bignumber.equal(ZERO) + + await homeContract.relayTokens(recipient, { from: accounts[1], value: 1 }).should.be.rejectedWith(ERROR_MSG) + + await blockRewardContract.addMintedTotallyByBridge(2, homeContract.address) + + await homeContract.relayTokens(recipient, { from: accounts[1], value: 1 }).should.be.fulfilled + + await homeContract.relayTokens(recipient, { from: accounts[1], value: 1 }).should.be.fulfilled + + await homeContract.relayTokens(recipient, { from: accounts[1], value: 1 }).should.be.rejectedWith(ERROR_MSG) + + const minted = await blockRewardContract.mintedTotallyByBridge(homeContract.address) + const burnt = await homeContract.totalBurntCoins() + + minted.should.be.bignumber.equal('2') + burnt.should.be.bignumber.equal('2') + }) + }) describe('#setting limits', async () => { let homeContract beforeEach(async () => { @@ -747,7 +880,6 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { expect(await homeContract.executionDailyLimit()).to.be.bignumber.equal(newValue) }) }) - describe('#executeAffirmation', async () => { let homeBridge beforeEach(async () => { @@ -1056,7 +1188,6 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { newOutOfLimitAmount.should.be.bignumber.equal(oneEther) }) }) - describe('#submitSignature', async () => { let validatorContractWith2Signatures let authoritiesThreeAccs @@ -1225,7 +1356,6 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { logs[1].args.authorityResponsibleForRelay.should.be.equal(authoritiesThreeAccs[1]) }) }) - describe('#requiredMessageLength', async () => { beforeEach(async () => { homeContract = await HomeBridge.new() @@ -1535,7 +1665,6 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { }) }) }) - describe('#feeManager', async () => { let homeBridge let rewardableValidators @@ -1956,6 +2085,62 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { expect(toBN(homeBridgeBalance)).to.be.bignumber.equal(value.sub(finalValue)) }) }) + describe('#feeManager_relayTokens', async () => { + let homeBridge + let rewardableValidators + const owner = accounts[9] + const validators = [accounts[1]] + const rewards = [accounts[2]] + const requiredSignatures = 1 + beforeEach(async () => { + rewardableValidators = await RewardableValidators.new() + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner).should.be.fulfilled + 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( + rewardableValidators.address, + [oneEther, halfEther, minPerTx], + gasPrice, + requireBlockConfirmations, + blockRewardContract.address, + [foreignDailyLimit, foreignMaxPerTx], + owner, + decimalShiftZero + ).should.be.fulfilled + await blockRewardContract.addMintedTotallyByBridge(oneEther, homeBridge.address) + }) + + it('should subtract fee from value', async () => { + // Given + // 0.1% fee + const value = halfEther + const recipient = accounts[8] + const sender = accounts[7] + const fee = 0.001 + const feeInWei = ether(fee.toString()) + const valueCalc = 0.5 * (1 - fee) + const finalValue = ether(valueCalc.toString()) + const feeManager = await FeeManagerErcToNative.new() + await homeBridge.setFeeManagerContract(feeManager.address, { from: owner }).should.be.fulfilled + await homeBridge.setHomeFee(feeInWei, { from: owner }).should.be.fulfilled + + // When + const { logs } = await homeBridge.relayTokens(recipient, { from: sender, value }).should.be.fulfilled + + // Then + expectEventInLogs(logs, 'UserRequestForSignature', { + recipient, + value: finalValue + }) + const currentDay = await homeBridge.getCurrentDay() + value.should.be.bignumber.equal(await homeBridge.totalSpentPerDay(currentDay)) + finalValue.should.be.bignumber.equal(await homeBridge.totalBurntCoins()) + const homeBridgeBalance = await web3.eth.getBalance(homeBridge.address) + expect(toBN(homeBridgeBalance)).to.be.bignumber.equal(value.sub(finalValue)) + }) + }) describe('#feeManager_submitSignature', async () => { it('should distribute fee to validator', async () => { // Initialize @@ -2589,6 +2774,62 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { expect(toBN(homeBridgeBalance)).to.be.bignumber.equal(ZERO) }) }) + describe('#feeManager_relayTokens_POSDAO', async () => { + let homeBridge + let rewardableValidators + const owner = accounts[9] + const validators = [accounts[1]] + const rewards = [accounts[2]] + const requiredSignatures = 1 + beforeEach(async () => { + rewardableValidators = await RewardableValidators.new() + await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner).should.be.fulfilled + 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( + rewardableValidators.address, + [oneEther, halfEther, minPerTx], + gasPrice, + requireBlockConfirmations, + blockRewardContract.address, + [foreignDailyLimit, foreignMaxPerTx], + owner, + decimalShiftZero + ).should.be.fulfilled + await blockRewardContract.addMintedTotallyByBridge(oneEther, homeBridge.address) + }) + + it('should subtract fee from value', async () => { + // Given + // 0.1% fee + const value = halfEther + const recipient = accounts[8] + const sender = accounts[7] + const fee = 0.001 + const feeInWei = ether(fee.toString()) + const feeManager = await FeeManagerErcToNativePOSDAO.new() + await homeBridge.setFeeManagerContract(feeManager.address, { from: owner }).should.be.fulfilled + await homeBridge.setHomeFee(feeInWei, { from: owner }).should.be.fulfilled + + // When + const { logs } = await homeBridge.relayTokens(recipient, { from: sender, value }).should.be.fulfilled + + // Then + const valueCalc = 0.5 * (1 - fee) + const finalValue = ether(valueCalc.toString()) + expectEventInLogs(logs, 'UserRequestForSignature', { + recipient, + value: finalValue + }) + const currentDay = await homeBridge.getCurrentDay() + value.should.be.bignumber.equal(await homeBridge.totalSpentPerDay(currentDay)) + value.should.be.bignumber.equal(await homeBridge.totalBurntCoins()) + const homeBridgeBalance = await web3.eth.getBalance(homeBridge.address) + expect(toBN(homeBridgeBalance)).to.be.bignumber.equal(ZERO) + }) + }) describe('#feeManager_submitSignature_POSDAO', async () => { it('should distribute fee to validator', async () => { // Initialize @@ -2876,7 +3117,6 @@ contract('HomeBridge_ERC20_to_Native', async accounts => { feeAmountBlockReward.should.be.bignumber.equal(feeAmount) }) }) - describe('#decimals Shift', async () => { const decimalShiftTwo = 2 it('Foreign to Home: test with 2 signatures required and decimal shift 2', async () => { diff --git a/test/poa20_test.js b/test/poa20_test.js index 920e41440..79cbfbae0 100644 --- a/test/poa20_test.js +++ b/test/poa20_test.js @@ -156,47 +156,39 @@ async function testERC677BridgeToken(accounts, rewardable) { 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 + await token.mintReward(1, { from: user }).should.be.rejectedWith(ERROR_MSG) + await token.mintReward(1, { 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] - + it('should increase totalSupply and balance', async () => { expect(await token.totalSupply()).to.be.bignumber.equal(ZERO) - expect(await token.balanceOf(user1)).to.be.bignumber.equal(ZERO) - expect(await token.balanceOf(user2)).to.be.bignumber.equal(ZERO) - expect(await token.balanceOf(user3)).to.be.bignumber.equal(ZERO) + expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO) - await token.setBlockRewardContractMock(accounts[4]).should.be.fulfilled - await token.mintReward([user1, user2, user3], [100, 200, 300], { from: accounts[4] }).should.be.fulfilled + await token.setBlockRewardContractMock(user).should.be.fulfilled + await token.mintReward(100, { from: user }).should.be.fulfilled - expect(await token.totalSupply()).to.be.bignumber.equal('600') - expect(await token.balanceOf(user1)).to.be.bignumber.equal('100') - expect(await token.balanceOf(user2)).to.be.bignumber.equal('200') - expect(await token.balanceOf(user3)).to.be.bignumber.equal('300') + expect(await token.totalSupply()).to.be.bignumber.equal('100') + expect(await token.balanceOf(user)).to.be.bignumber.equal('100') }) }) describe('#stake', async () => { it('can only be called by Staking contract', async () => { - await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled - await token.mintReward([user], ['100'], { from: accounts[2] }).should.be.fulfilled - await token.setStakingContractMock(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 + await token.setBlockRewardContractMock(user).should.be.fulfilled + await token.mintReward('100', { from: user }).should.be.fulfilled + await token.setStakingContractMock(accounts[4]).should.be.fulfilled + await token.stake(user, '100', { from: accounts[3] }).should.be.rejectedWith(ERROR_MSG) + await token.stake(user, '100', { from: accounts[4] }).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.setBlockRewardContractMock(user).should.be.fulfilled + await token.mintReward('99', { from: user }).should.be.fulfilled expect(await token.balanceOf(user)).to.be.bignumber.equal('99') await token.setStakingContractMock(accounts[3]).should.be.fulfilled await token.stake(user, '100', { from: accounts[3] }).should.be.rejectedWith(ERROR_MSG_OPCODE) }) it("should decrease user's balance and increase Staking's balance", async () => { - await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled - await token.mintReward([user], ['100'], { from: accounts[2] }).should.be.fulfilled + await token.setBlockRewardContractMock(user).should.be.fulfilled + await token.mintReward('100', { from: user }).should.be.fulfilled expect(await token.balanceOf(user)).to.be.bignumber.equal('100') expect(await token.balanceOf(accounts[3])).to.be.bignumber.equal(ZERO) await token.setStakingContractMock(accounts[3]).should.be.fulfilled @@ -324,6 +316,15 @@ async function testERC677BridgeToken(accounts, rewardable) { }) if (rewardable) { + it('fail to send tokens to BlockReward contract directly', async () => { + const amount = ether('1') + const blockRewardContractAddress = accounts[2] + const arbitraryAccountAddress = accounts[3] + await token.setBlockRewardContractMock(blockRewardContractAddress, { from: owner }).should.be.fulfilled + await token.mint(user, amount, { from: owner }).should.be.fulfilled + await token.transfer(blockRewardContractAddress, amount, { from: user }).should.be.rejectedWith(ERROR_MSG) + await token.transfer(arbitraryAccountAddress, amount, { from: user }).should.be.fulfilled + }) it('fail to send tokens to Staking contract directly', async () => { const amount = ether('1') const stakingContractAddress = accounts[2] @@ -356,6 +357,19 @@ async function testERC677BridgeToken(accounts, rewardable) { expect(await receiver.data()).to.be.equal(null) }) if (rewardable) { + it('fail to send tokens to BlockReward contract directly', async () => { + const amount = ether('1') + const user2 = accounts[2] + const blockRewardContractAddress = accounts[3] + const arbitraryAccountAddress = accounts[4] + await token.setBlockRewardContractMock(blockRewardContractAddress, { from: owner }).should.be.fulfilled + await token.mint(user, amount, { from: owner }).should.be.fulfilled + await token.approve(user2, amount, { from: user }).should.be.fulfilled + await token + .transferFrom(user, blockRewardContractAddress, amount, { from: user2 }) + .should.be.rejectedWith(ERROR_MSG) + await token.transferFrom(user, arbitraryAccountAddress, amount, { from: user2 }).should.be.fulfilled + }) it('fail to send tokens to Staking contract directly', async () => { const amount = ether('1') const user2 = accounts[2]