Support negative decimal shift (#448)
This commit is contained in:
parent
1ed52725fc
commit
f8aea2366c
|
@ -23,6 +23,7 @@
|
|||
"no-use-before-define": ["error", { "functions": false }],
|
||||
"no-restricted-syntax": "off",
|
||||
"node/no-unpublished-require": "off",
|
||||
"func-names": "off"
|
||||
"func-names": "off",
|
||||
"no-loop-func": "off"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@ pragma solidity 0.4.24;
|
|||
|
||||
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
|
||||
import "../upgradeability/EternalStorage.sol";
|
||||
import "./DecimalShiftBridge.sol";
|
||||
import "./Ownable.sol";
|
||||
|
||||
contract BasicTokenBridge is EternalStorage, Ownable {
|
||||
contract BasicTokenBridge is EternalStorage, Ownable, DecimalShiftBridge {
|
||||
using SafeMath for uint256;
|
||||
|
||||
event DailyLimitChanged(uint256 newLimit);
|
||||
|
@ -15,7 +16,6 @@ contract BasicTokenBridge is EternalStorage, Ownable {
|
|||
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))];
|
||||
|
@ -45,10 +45,6 @@ contract BasicTokenBridge is EternalStorage, Ownable {
|
|||
return uintStorage[MIN_PER_TX];
|
||||
}
|
||||
|
||||
function decimalShift() public view returns (uint256) {
|
||||
return uintStorage[DECIMAL_SHIFT];
|
||||
}
|
||||
|
||||
function withinLimit(uint256 _amount) public view returns (bool) {
|
||||
uint256 nextLimit = totalSpentPerDay(getCurrentDay()).add(_amount);
|
||||
return dailyLimit() >= nextLimit && _amount <= maxPerTx() && _amount >= minPerTx();
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
pragma solidity 0.4.24;
|
||||
|
||||
import "../upgradeability/EternalStorage.sol";
|
||||
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
|
||||
|
||||
contract DecimalShiftBridge is EternalStorage {
|
||||
using SafeMath for uint256;
|
||||
|
||||
bytes32 internal constant DECIMAL_SHIFT = 0x1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee5; // keccak256(abi.encodePacked("decimalShift"))
|
||||
|
||||
/**
|
||||
* @dev Internal function for setting the decimal shift for bridge operations.
|
||||
* Decimal shift can be positive, negative, or equal to zero.
|
||||
* It has the following meaning: N tokens in the foreign chain are equivalent to N * pow(10, shift) tokens on the home side.
|
||||
* @param _shift new value of decimal shift.
|
||||
*/
|
||||
function _setDecimalShift(int256 _shift) internal {
|
||||
// since 1 wei * 10**77 > 2**255, it does not make any sense to use higher values
|
||||
require(_shift > -77 && _shift < 77);
|
||||
uintStorage[DECIMAL_SHIFT] = uint256(_shift);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the value of foreign-to-home decimal shift.
|
||||
* @return decimal shift.
|
||||
*/
|
||||
function decimalShift() public view returns (int256) {
|
||||
return int256(uintStorage[DECIMAL_SHIFT]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Converts the amount of home tokens into the equivalent amount of foreign tokens.
|
||||
* @param _value amount of home tokens.
|
||||
* @return equivalent amount of foreign tokens.
|
||||
*/
|
||||
function _unshiftValue(uint256 _value) internal view returns (uint256) {
|
||||
return _shiftUint(_value, -decimalShift());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Converts the amount of foreign tokens into the equivalent amount of home tokens.
|
||||
* @param _value amount of foreign tokens.
|
||||
* @return equivalent amount of home tokens.
|
||||
*/
|
||||
function _shiftValue(uint256 _value) internal view returns (uint256) {
|
||||
return _shiftUint(_value, decimalShift());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Calculates _value * pow(10, _shift).
|
||||
* @param _value amount of tokens.
|
||||
* @param _shift decimal shift to apply.
|
||||
* @return shifted value.
|
||||
*/
|
||||
function _shiftUint(uint256 _value, int256 _shift) private pure returns (uint256) {
|
||||
if (_shift == 0) {
|
||||
return _value;
|
||||
}
|
||||
if (_shift > 0) {
|
||||
return _value.mul(10**uint256(_shift));
|
||||
}
|
||||
return _value.div(10**uint256(-_shift));
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ contract BasicAMBErc20ToNative is Initializable, Upgradeable, Claimable, Version
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = dailyLimit, 1 = maxPerTx, 2 = minPerTx ]
|
||||
uint256[2] _executionDailyLimitExecutionMaxPerTxArray, // [ 0 = executionDailyLimit, 1 = executionMaxPerTx ]
|
||||
uint256 _requestGasLimit,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _owner
|
||||
) internal {
|
||||
require(!isInitialized());
|
||||
|
@ -49,7 +49,7 @@ contract BasicAMBErc20ToNative is Initializable, Upgradeable, Claimable, Version
|
|||
uintStorage[MIN_PER_TX] = _dailyLimitMaxPerTxMinPerTxArray[2];
|
||||
uintStorage[EXECUTION_DAILY_LIMIT] = _executionDailyLimitExecutionMaxPerTxArray[0];
|
||||
uintStorage[EXECUTION_MAX_PER_TX] = _executionDailyLimitExecutionMaxPerTxArray[1];
|
||||
uintStorage[DECIMAL_SHIFT] = _decimalShift;
|
||||
_setDecimalShift(_decimalShift);
|
||||
setOwner(_owner);
|
||||
|
||||
emit DailyLimitChanged(_dailyLimitMaxPerTxMinPerTxArray[0]);
|
||||
|
|
|
@ -31,7 +31,7 @@ contract ForeignAMBErc20ToNative is BasicAMBErc20ToNative, ReentrancyGuard, Base
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = dailyLimit, 1 = maxPerTx, 2 = minPerTx ]
|
||||
uint256[2] _executionDailyLimitExecutionMaxPerTxArray, // [ 0 = executionDailyLimit, 1 = executionMaxPerTx ]
|
||||
uint256 _requestGasLimit,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _owner,
|
||||
address _erc677token
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
|
@ -139,7 +139,7 @@ contract ForeignAMBErc20ToNative is BasicAMBErc20ToNative, ReentrancyGuard, Base
|
|||
* @param _value amount of tokens to be received
|
||||
*/
|
||||
function executeActionOnBridgedTokens(address _receiver, uint256 _value) internal {
|
||||
uint256 valueToTransfer = _value.div(10**decimalShift());
|
||||
uint256 valueToTransfer = _unshiftValue(_value);
|
||||
bytes32 _messageId = messageId();
|
||||
|
||||
_setMediatorBalance(mediatorBalance().sub(valueToTransfer));
|
||||
|
|
|
@ -31,7 +31,7 @@ contract HomeAMBErc20ToNative is BasicAMBErc20ToNative, BlockRewardBridge, HomeF
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = dailyLimit, 1 = maxPerTx, 2 = minPerTx ]
|
||||
uint256[2] _executionDailyLimitExecutionMaxPerTxArray, // [ 0 = executionDailyLimit, 1 = executionMaxPerTx ]
|
||||
uint256 _requestGasLimit,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _owner,
|
||||
address _blockReward
|
||||
) public onlyRelevantSender returns (bool) {
|
||||
|
@ -71,7 +71,7 @@ contract HomeAMBErc20ToNative is BasicAMBErc20ToNative, BlockRewardBridge, HomeF
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = dailyLimit, 1 = maxPerTx, 2 = minPerTx ]
|
||||
uint256[2] _executionDailyLimitExecutionMaxPerTxArray, // [ 0 = executionDailyLimit, 1 = executionMaxPerTx ]
|
||||
uint256 _requestGasLimit,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _owner,
|
||||
address _blockReward,
|
||||
address[] _rewardAddreses,
|
||||
|
@ -177,7 +177,7 @@ contract HomeAMBErc20ToNative is BasicAMBErc20ToNative, BlockRewardBridge, HomeF
|
|||
* @param _value amount of native tokens to be received
|
||||
*/
|
||||
function executeActionOnBridgedTokens(address _receiver, uint256 _value) internal {
|
||||
uint256 valueToMint = _value.mul(10**decimalShift());
|
||||
uint256 valueToMint = _shiftValue(_value);
|
||||
bytes32 _messageId = messageId();
|
||||
|
||||
uint256 fee = _distributeFee(FOREIGN_TO_HOME_FEE, valueToMint);
|
||||
|
|
|
@ -32,7 +32,7 @@ contract BasicAMBErc677ToErc677 is
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ]
|
||||
uint256[2] _executionDailyLimitExecutionMaxPerTxArray, // [ 0 = _executionDailyLimit, 1 = _executionMaxPerTx ]
|
||||
uint256 _requestGasLimit,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _owner
|
||||
) public onlyRelevantSender returns (bool) {
|
||||
require(!isInitialized());
|
||||
|
@ -52,7 +52,7 @@ contract BasicAMBErc677ToErc677 is
|
|||
uintStorage[EXECUTION_DAILY_LIMIT] = _executionDailyLimitExecutionMaxPerTxArray[0];
|
||||
uintStorage[EXECUTION_MAX_PER_TX] = _executionDailyLimitExecutionMaxPerTxArray[1];
|
||||
_setRequestGasLimit(_requestGasLimit);
|
||||
uintStorage[DECIMAL_SHIFT] = _decimalShift;
|
||||
_setDecimalShift(_decimalShift);
|
||||
setOwner(_owner);
|
||||
setInitialize();
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ contract ForeignAMBErc677ToErc677 is BasicAMBErc677ToErc677 {
|
|||
* @param _value amount of bridged tokens
|
||||
*/
|
||||
function executeActionOnBridgedTokens(address _recipient, uint256 _value) internal {
|
||||
uint256 value = _value.div(10**decimalShift());
|
||||
uint256 value = _unshiftValue(_value);
|
||||
bytes32 _messageId = messageId();
|
||||
erc677token().transfer(_recipient, value);
|
||||
emit TokensBridged(_recipient, value, _messageId);
|
||||
|
|
|
@ -15,7 +15,7 @@ contract ForeignStakeTokenMediator is BasicStakeTokenMediator {
|
|||
* @param _value amount of bridged tokens
|
||||
*/
|
||||
function executeActionOnBridgedTokens(address _recipient, uint256 _value) internal {
|
||||
uint256 value = _value.div(10**decimalShift());
|
||||
uint256 value = _unshiftValue(_value);
|
||||
bytes32 _messageId = messageId();
|
||||
_transferWithOptionalMint(_recipient, value);
|
||||
emit TokensBridged(_recipient, value, _messageId);
|
||||
|
|
|
@ -15,7 +15,7 @@ contract HomeAMBErc677ToErc677 is BasicAMBErc677ToErc677 {
|
|||
* @param _value amount of bridged tokens
|
||||
*/
|
||||
function executeActionOnBridgedTokens(address _recipient, uint256 _value) internal {
|
||||
uint256 value = _value.mul(10**decimalShift());
|
||||
uint256 value = _shiftValue(_value);
|
||||
bytes32 _messageId = messageId();
|
||||
IBurnableMintableERC677Token(erc677token()).mint(_recipient, value);
|
||||
emit TokensBridged(_recipient, value, _messageId);
|
||||
|
|
|
@ -21,7 +21,7 @@ contract HomeStakeTokenMediator is BasicStakeTokenMediator, HomeStakeTokenFeeMan
|
|||
* @param _dailyLimitMaxPerTxMinPerTxArray Home limits for outgoing transfers
|
||||
* @param _executionDailyLimitExecutionMaxPerTxArray Home execution limits for incoming transfers
|
||||
* @param _requestGasLimit gas limit used for AMB operations
|
||||
* @param _decimalShift decimal shift for bridged TAKE token
|
||||
* @param _decimalShift decimal shift for bridged STAKE token
|
||||
* @param _owner address of new bridge owner
|
||||
*/
|
||||
function initialize(
|
||||
|
@ -31,7 +31,7 @@ contract HomeStakeTokenMediator is BasicStakeTokenMediator, HomeStakeTokenFeeMan
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ]
|
||||
uint256[2] _executionDailyLimitExecutionMaxPerTxArray, // [ 0 = _executionDailyLimit, 1 = _executionMaxPerTx ]
|
||||
uint256 _requestGasLimit,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _owner
|
||||
) public returns (bool) {
|
||||
addressStorage[MINT_HANDLER] = _erc677token;
|
||||
|
@ -56,7 +56,7 @@ contract HomeStakeTokenMediator is BasicStakeTokenMediator, HomeStakeTokenFeeMan
|
|||
* @param _dailyLimitMaxPerTxMinPerTxArray Home limits for outgoing transfers
|
||||
* @param _executionDailyLimitExecutionMaxPerTxArray Home execution limits for incoming transfers
|
||||
* @param _requestGasLimit gas limit used for AMB operations
|
||||
* @param _decimalShift decimal shift for bridged TAKE token
|
||||
* @param _decimalShift decimal shift for bridged STAKE token
|
||||
* @param _owner address of new bridge owner
|
||||
* @param _blockReward address of block reward contract used for fee distribution
|
||||
* @param _fee initial home fee
|
||||
|
@ -68,7 +68,7 @@ contract HomeStakeTokenMediator is BasicStakeTokenMediator, HomeStakeTokenFeeMan
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ]
|
||||
uint256[2] _executionDailyLimitExecutionMaxPerTxArray, // [ 0 = _executionDailyLimit, 1 = _executionMaxPerTx ]
|
||||
uint256 _requestGasLimit,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _owner,
|
||||
address _blockReward,
|
||||
uint256 _fee
|
||||
|
@ -122,7 +122,7 @@ contract HomeStakeTokenMediator is BasicStakeTokenMediator, HomeStakeTokenFeeMan
|
|||
* @param _value amount of bridged tokens
|
||||
*/
|
||||
function executeActionOnBridgedTokens(address _recipient, uint256 _value) internal {
|
||||
uint256 value = _value.mul(10**decimalShift());
|
||||
uint256 value = _shiftValue(_value);
|
||||
bytes32 _messageId = messageId();
|
||||
getMintHandler().mint(_recipient, value);
|
||||
emit TokensBridged(_recipient, value, _messageId);
|
||||
|
|
|
@ -38,7 +38,7 @@ contract BasicAMBNativeToErc20 is
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray,
|
||||
uint256[2] _executionDailyLimitExecutionMaxPerTxArray,
|
||||
uint256 _requestGasLimit,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _owner,
|
||||
address _feeManager
|
||||
) internal {
|
||||
|
@ -59,7 +59,7 @@ contract BasicAMBNativeToErc20 is
|
|||
uintStorage[MIN_PER_TX] = _dailyLimitMaxPerTxMinPerTxArray[2];
|
||||
uintStorage[EXECUTION_DAILY_LIMIT] = _executionDailyLimitExecutionMaxPerTxArray[0];
|
||||
uintStorage[EXECUTION_MAX_PER_TX] = _executionDailyLimitExecutionMaxPerTxArray[1];
|
||||
uintStorage[DECIMAL_SHIFT] = _decimalShift;
|
||||
_setDecimalShift(_decimalShift);
|
||||
_setFeeManagerContract(_feeManager);
|
||||
setOwner(_owner);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ contract ForeignAMBNativeToErc20 is BasicAMBNativeToErc20, ReentrancyGuard, Base
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = dailyLimit, 1 = maxPerTx, 2 = minPerTx ]
|
||||
uint256[2] _executionDailyLimitExecutionMaxPerTxArray, // [ 0 = executionDailyLimit, 1 = executionMaxPerTx ]
|
||||
uint256 _requestGasLimit,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _owner,
|
||||
address _erc677token,
|
||||
address _feeManager
|
||||
|
@ -67,7 +67,7 @@ contract ForeignAMBNativeToErc20 is BasicAMBNativeToErc20, ReentrancyGuard, Base
|
|||
* @param _value amount of tokens to be received
|
||||
*/
|
||||
function executeActionOnBridgedTokens(address _receiver, uint256 _value) internal {
|
||||
uint256 valueToMint = _value.div(10**decimalShift());
|
||||
uint256 valueToMint = _unshiftValue(_value);
|
||||
|
||||
bytes32 _messageId = messageId();
|
||||
IMediatorFeeManager feeManager = feeManagerContract();
|
||||
|
|
|
@ -29,7 +29,7 @@ contract HomeAMBNativeToErc20 is BasicAMBNativeToErc20 {
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = dailyLimit, 1 = maxPerTx, 2 = minPerTx ]
|
||||
uint256[2] _executionDailyLimitExecutionMaxPerTxArray, // [ 0 = executionDailyLimit, 1 = executionMaxPerTx ]
|
||||
uint256 _requestGasLimit,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _owner,
|
||||
address _feeManager
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
|
@ -84,7 +84,7 @@ contract HomeAMBNativeToErc20 is BasicAMBNativeToErc20 {
|
|||
* @param _value amount of native tokens to be received
|
||||
*/
|
||||
function executeActionOnBridgedTokens(address _receiver, uint256 _value) internal {
|
||||
uint256 valueToTransfer = _value.mul(10**decimalShift());
|
||||
uint256 valueToTransfer = _shiftValue(_value);
|
||||
setMediatorBalance(mediatorBalance().sub(valueToTransfer));
|
||||
|
||||
bytes32 _messageId = messageId();
|
||||
|
|
|
@ -12,7 +12,7 @@ contract BasicForeignBridgeErcToErc is BasicForeignBridge {
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ]
|
||||
uint256[2] _homeDailyLimitHomeMaxPerTxArray, // [ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) internal {
|
||||
require(!isInitialized());
|
||||
require(AddressUtils.isContract(_validatorContract));
|
||||
|
@ -35,7 +35,7 @@ contract BasicForeignBridgeErcToErc is BasicForeignBridge {
|
|||
uintStorage[MIN_PER_TX] = _dailyLimitMaxPerTxMinPerTxArray[2];
|
||||
uintStorage[EXECUTION_DAILY_LIMIT] = _homeDailyLimitHomeMaxPerTxArray[0];
|
||||
uintStorage[EXECUTION_MAX_PER_TX] = _homeDailyLimitHomeMaxPerTxArray[1];
|
||||
uintStorage[DECIMAL_SHIFT] = _decimalShift;
|
||||
_setDecimalShift(_decimalShift);
|
||||
setOwner(_owner);
|
||||
setInitialize();
|
||||
|
||||
|
@ -59,7 +59,7 @@ contract BasicForeignBridgeErcToErc is BasicForeignBridge {
|
|||
bytes32 /*_txHash*/
|
||||
) internal returns (bool) {
|
||||
setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_amount));
|
||||
uint256 amount = _amount.div(10**decimalShift());
|
||||
uint256 amount = _unshiftValue(_amount);
|
||||
return erc20token().transfer(_recipient, amount);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ contract ForeignBridgeErc677ToErc677 is ERC677Bridge, BasicForeignBridgeErcToErc
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ]
|
||||
uint256[2] _homeDailyLimitHomeMaxPerTxArray, // [ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
_initialize(
|
||||
_validatorContract,
|
||||
|
|
|
@ -12,7 +12,7 @@ contract ForeignBridgeErcToErc is BasicForeignBridgeErcToErc, ERC20Bridge {
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ]
|
||||
uint256[2] _homeDailyLimitHomeMaxPerTxArray, // [ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
_initialize(
|
||||
_validatorContract,
|
||||
|
|
|
@ -23,7 +23,7 @@ contract HomeBridgeErcToErc is
|
|||
address _erc677token,
|
||||
uint256[2] _foreignDailyLimitForeignMaxPerTxArray, // [ 0 = _foreignDailyLimit, 1 = _foreignMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
_initialize(
|
||||
_validatorContract,
|
||||
|
@ -50,7 +50,7 @@ contract HomeBridgeErcToErc is
|
|||
address _owner,
|
||||
address _feeManager,
|
||||
uint256[2] _homeFeeForeignFeeArray, // [ 0 = _homeFee, 1 = _foreignFee ]
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
_rewardableInitialize(
|
||||
_validatorContract,
|
||||
|
@ -79,7 +79,7 @@ contract HomeBridgeErcToErc is
|
|||
address _owner,
|
||||
address _feeManager,
|
||||
uint256[2] _homeFeeForeignFeeArray, // [ 0 = _homeFee, 1 = _foreignFee ]
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) internal {
|
||||
_initialize(
|
||||
_validatorContract,
|
||||
|
@ -105,7 +105,7 @@ contract HomeBridgeErcToErc is
|
|||
address _erc677token,
|
||||
uint256[2] _foreignDailyLimitForeignMaxPerTxArray, // [ 0 = _foreignDailyLimit, 1 = _foreignMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) internal {
|
||||
require(!isInitialized());
|
||||
require(AddressUtils.isContract(_validatorContract));
|
||||
|
@ -126,7 +126,7 @@ contract HomeBridgeErcToErc is
|
|||
uintStorage[REQUIRED_BLOCK_CONFIRMATIONS] = _requiredBlockConfirmations;
|
||||
uintStorage[EXECUTION_DAILY_LIMIT] = _foreignDailyLimitForeignMaxPerTxArray[0];
|
||||
uintStorage[EXECUTION_MAX_PER_TX] = _foreignDailyLimitForeignMaxPerTxArray[1];
|
||||
uintStorage[DECIMAL_SHIFT] = _decimalShift;
|
||||
_setDecimalShift(_decimalShift);
|
||||
setOwner(_owner);
|
||||
setErc677token(_erc677token);
|
||||
|
||||
|
@ -145,7 +145,7 @@ contract HomeBridgeErcToErc is
|
|||
|
||||
function onExecuteAffirmation(address _recipient, uint256 _value, bytes32 txHash) internal returns (bool) {
|
||||
setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_value));
|
||||
uint256 valueToMint = _value.mul(10**decimalShift());
|
||||
uint256 valueToMint = _shiftValue(_value);
|
||||
address feeManager = feeManagerContract();
|
||||
if (feeManager != address(0)) {
|
||||
uint256 fee = calculateFee(valueToMint, false, feeManager, FOREIGN_FEE);
|
||||
|
|
|
@ -17,7 +17,7 @@ contract HomeBridgeErcToErcPOSDAO is HomeBridgeErcToErc {
|
|||
address _feeManager,
|
||||
uint256[2] _homeFeeForeignFeeArray, // [ 0 = _homeFee, 1 = _foreignFee ]
|
||||
address _blockReward,
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
_rewardableInitialize(
|
||||
_validatorContract,
|
||||
|
|
|
@ -19,7 +19,7 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB
|
|||
uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ]
|
||||
uint256[2] _homeDailyLimitHomeMaxPerTxArray, //[ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _bridgeOnOtherSide
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
require(!isInitialized());
|
||||
|
@ -44,7 +44,7 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB
|
|||
uintStorage[MIN_PER_TX] = _dailyLimitMaxPerTxMinPerTxArray[2];
|
||||
uintStorage[EXECUTION_DAILY_LIMIT] = _homeDailyLimitHomeMaxPerTxArray[0];
|
||||
uintStorage[EXECUTION_MAX_PER_TX] = _homeDailyLimitHomeMaxPerTxArray[1];
|
||||
uintStorage[DECIMAL_SHIFT] = _decimalShift;
|
||||
_setDecimalShift(_decimalShift);
|
||||
setOwner(_owner);
|
||||
_setBridgeContractOnOtherSide(_bridgeOnOtherSide);
|
||||
setInitialize();
|
||||
|
@ -86,7 +86,7 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB
|
|||
bytes32 /*_txHash*/
|
||||
) internal returns (bool) {
|
||||
setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_amount));
|
||||
uint256 amount = _amount.div(10**decimalShift());
|
||||
uint256 amount = _unshiftValue(_amount);
|
||||
|
||||
uint256 currentBalance = tokenBalance(erc20token());
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ contract HomeBridgeErcToNative is
|
|||
address _blockReward,
|
||||
uint256[2] _foreignDailyLimitForeignMaxPerTxArray, // [ 0 = _foreignDailyLimit, 1 = _foreignMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
_initialize(
|
||||
_validatorContract,
|
||||
|
@ -82,7 +82,7 @@ contract HomeBridgeErcToNative is
|
|||
address _owner,
|
||||
address _feeManager,
|
||||
uint256[2] _homeFeeForeignFeeArray, // [ 0 = _homeFee, 1 = _foreignFee ]
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
_initialize(
|
||||
_validatorContract,
|
||||
|
@ -127,7 +127,7 @@ contract HomeBridgeErcToNative is
|
|||
address _blockReward,
|
||||
uint256[2] _foreignDailyLimitForeignMaxPerTxArray, // [ 0 = _foreignDailyLimit, 1 = _foreignMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) internal {
|
||||
require(!isInitialized());
|
||||
require(AddressUtils.isContract(_validatorContract));
|
||||
|
@ -151,7 +151,7 @@ contract HomeBridgeErcToNative is
|
|||
addressStorage[BLOCK_REWARD_CONTRACT] = _blockReward;
|
||||
uintStorage[EXECUTION_DAILY_LIMIT] = _foreignDailyLimitForeignMaxPerTxArray[0];
|
||||
uintStorage[EXECUTION_MAX_PER_TX] = _foreignDailyLimitForeignMaxPerTxArray[1];
|
||||
uintStorage[DECIMAL_SHIFT] = _decimalShift;
|
||||
_setDecimalShift(_decimalShift);
|
||||
setOwner(_owner);
|
||||
|
||||
emit RequiredBlockConfirmationChanged(_requiredBlockConfirmations);
|
||||
|
@ -163,7 +163,7 @@ contract HomeBridgeErcToNative is
|
|||
setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_value));
|
||||
IBlockReward blockReward = blockRewardContract();
|
||||
require(blockReward != address(0));
|
||||
uint256 valueToMint = _value.mul(10**decimalShift());
|
||||
uint256 valueToMint = _shiftValue(_value);
|
||||
address feeManager = feeManagerContract();
|
||||
if (feeManager != address(0)) {
|
||||
uint256 fee = calculateFee(valueToMint, false, feeManager, FOREIGN_FEE);
|
||||
|
|
|
@ -10,7 +10,7 @@ contract ClassicHomeBridgeNativeToErc is HomeBridgeNativeToErc {
|
|||
uint256 _requiredBlockConfirmations,
|
||||
uint256[2] _foreignDailyLimitForeignMaxPerTxArray, // [ 0 = _foreignDailyLimit, 1 = _foreignMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) internal {
|
||||
super._initialize(
|
||||
_validatorContract,
|
||||
|
|
|
@ -19,7 +19,7 @@ contract ForeignBridgeNativeToErc is
|
|||
uint256 _requiredBlockConfirmations,
|
||||
uint256[2] _homeDailyLimitHomeMaxPerTxArray, // [ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _bridgeOnOtherSide
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
_initialize(
|
||||
|
@ -47,7 +47,7 @@ contract ForeignBridgeNativeToErc is
|
|||
address _owner,
|
||||
address _feeManager,
|
||||
uint256 _homeFee,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _bridgeOnOtherSide
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
_initialize(
|
||||
|
@ -84,7 +84,7 @@ contract ForeignBridgeNativeToErc is
|
|||
uint256 _requiredBlockConfirmations,
|
||||
uint256[2] _homeDailyLimitHomeMaxPerTxArray, // [ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift,
|
||||
int256 _decimalShift,
|
||||
address _bridgeOnOtherSide
|
||||
) internal {
|
||||
require(!isInitialized());
|
||||
|
@ -108,7 +108,7 @@ contract ForeignBridgeNativeToErc is
|
|||
uintStorage[REQUIRED_BLOCK_CONFIRMATIONS] = _requiredBlockConfirmations;
|
||||
uintStorage[EXECUTION_DAILY_LIMIT] = _homeDailyLimitHomeMaxPerTxArray[0];
|
||||
uintStorage[EXECUTION_MAX_PER_TX] = _homeDailyLimitHomeMaxPerTxArray[1];
|
||||
uintStorage[DECIMAL_SHIFT] = _decimalShift;
|
||||
_setDecimalShift(_decimalShift);
|
||||
setOwner(_owner);
|
||||
_setBridgeContractOnOtherSide(_bridgeOnOtherSide);
|
||||
|
||||
|
@ -119,7 +119,7 @@ contract ForeignBridgeNativeToErc is
|
|||
|
||||
function onExecuteMessage(address _recipient, uint256 _amount, bytes32 _txHash) internal returns (bool) {
|
||||
setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_amount));
|
||||
uint256 valueToMint = _amount.div(10**decimalShift());
|
||||
uint256 valueToMint = _unshiftValue(_amount);
|
||||
address feeManager = feeManagerContract();
|
||||
if (feeManager != address(0)) {
|
||||
uint256 fee = calculateFee(valueToMint, false, feeManager, HOME_FEE);
|
||||
|
|
|
@ -36,7 +36,7 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicHomeBridge, RewardableHom
|
|||
uint256 _requiredBlockConfirmations,
|
||||
uint256[2] _foreignDailyLimitForeignMaxPerTxArray, // [ 0 = _foreignDailyLimit, 1 = _foreignMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
_initialize(
|
||||
_validatorContract,
|
||||
|
@ -60,7 +60,7 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicHomeBridge, RewardableHom
|
|||
address _owner,
|
||||
address _feeManager,
|
||||
uint256[2] _homeFeeForeignFeeArray, // [ 0 = _homeFee, 1 = _foreignFee ]
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) external onlyRelevantSender returns (bool) {
|
||||
_initialize(
|
||||
_validatorContract,
|
||||
|
@ -90,7 +90,7 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicHomeBridge, RewardableHom
|
|||
uint256 _requiredBlockConfirmations,
|
||||
uint256[2] _foreignDailyLimitForeignMaxPerTxArray, // [ 0 = _foreignDailyLimit, 1 = _foreignMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
int256 _decimalShift
|
||||
) internal {
|
||||
require(!isInitialized());
|
||||
require(AddressUtils.isContract(_validatorContract));
|
||||
|
@ -112,7 +112,7 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicHomeBridge, RewardableHom
|
|||
uintStorage[REQUIRED_BLOCK_CONFIRMATIONS] = _requiredBlockConfirmations;
|
||||
uintStorage[EXECUTION_DAILY_LIMIT] = _foreignDailyLimitForeignMaxPerTxArray[0];
|
||||
uintStorage[EXECUTION_MAX_PER_TX] = _foreignDailyLimitForeignMaxPerTxArray[1];
|
||||
uintStorage[DECIMAL_SHIFT] = _decimalShift;
|
||||
_setDecimalShift(_decimalShift);
|
||||
setOwner(_owner);
|
||||
|
||||
emit RequiredBlockConfirmationChanged(_requiredBlockConfirmations);
|
||||
|
@ -137,7 +137,7 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicHomeBridge, RewardableHom
|
|||
|
||||
function onExecuteAffirmation(address _recipient, uint256 _value, bytes32 txHash) internal returns (bool) {
|
||||
setTotalExecutedPerDay(getCurrentDay(), totalExecutedPerDay(getCurrentDay()).add(_value));
|
||||
uint256 valueToTransfer = _value.mul(10**decimalShift());
|
||||
uint256 valueToTransfer = _shiftValue(_value);
|
||||
|
||||
address feeManager = feeManagerContract();
|
||||
if (feeManager != address(0)) {
|
||||
|
|
|
@ -142,6 +142,18 @@ contract('ForeignAMBErc20ToNative', async accounts => {
|
|||
token.address
|
||||
).should.be.rejected
|
||||
|
||||
// not valid decimal shift
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediator.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
100,
|
||||
owner,
|
||||
token.address
|
||||
).should.be.rejected
|
||||
|
||||
const { logs } = await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediator.address,
|
||||
|
@ -453,79 +465,80 @@ contract('ForeignAMBErc20ToNative', async accounts => {
|
|||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
|
||||
it('should unlock tokens on message from amb with decimal shift of two', async () => {
|
||||
// Given
|
||||
const decimalShiftTwo = 2
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`should unlock tokens on message from amb with decimal shift of ${decimalShift}`, async () => {
|
||||
// Given
|
||||
|
||||
contract = await ForeignAMBErc20ToNative.new()
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediator.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShiftTwo,
|
||||
owner,
|
||||
token.address
|
||||
).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(twoEthers)
|
||||
expect(await contract.mediatorBalance()).to.be.bignumber.equal(twoEthers)
|
||||
contract = await ForeignAMBErc20ToNative.new()
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediator.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShift,
|
||||
owner,
|
||||
token.address
|
||||
).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(twoEthers)
|
||||
expect(await contract.mediatorBalance()).to.be.bignumber.equal(twoEthers)
|
||||
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
|
||||
const data = await contract.contract.methods.handleBridgedTokens(user, valueOnHome.toString()).encodeABI()
|
||||
const data = await contract.contract.methods.handleBridgedTokens(user, valueOnHome.toString()).encodeABI()
|
||||
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
contract.address,
|
||||
otherSideMediator.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
contract.address,
|
||||
otherSideMediator.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
|
||||
// Then
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnHome)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(valueOnForeign)
|
||||
expect(await contract.mediatorBalance()).to.be.bignumber.equal(twoEthers.sub(valueOnForeign))
|
||||
// Then
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnHome)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(valueOnForeign)
|
||||
expect(await contract.mediatorBalance()).to.be.bignumber.equal(twoEthers.sub(valueOnForeign))
|
||||
|
||||
const event = await getEvents(contract, { event: 'TokensBridged' })
|
||||
expect(event.length).to.be.equal(1)
|
||||
expect(event[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(event[0].returnValues.value).to.be.equal(valueOnForeign.toString())
|
||||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
const event = await getEvents(contract, { event: 'TokensBridged' })
|
||||
expect(event.length).to.be.equal(1)
|
||||
expect(event[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(event[0].returnValues.value).to.be.equal(valueOnForeign.toString())
|
||||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
|
||||
it('should revert when out of execution limits on message from amb', async () => {
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(twoEthers)
|
||||
expect(await contract.mediatorBalance()).to.be.bignumber.equal(twoEthers)
|
||||
it('should revert when out of execution limits on message from amb', async () => {
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
await token.transfer(contract.address, value, { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(twoEthers)
|
||||
expect(await contract.mediatorBalance()).to.be.bignumber.equal(twoEthers)
|
||||
|
||||
// Given
|
||||
const outOfLimitValueData = await contract.contract.methods
|
||||
.handleBridgedTokens(user, twoEthers.toString())
|
||||
.encodeABI()
|
||||
// Given
|
||||
const outOfLimitValueData = await contract.contract.methods
|
||||
.handleBridgedTokens(user, twoEthers.toString())
|
||||
.encodeABI()
|
||||
|
||||
// when
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
contract.address,
|
||||
otherSideMediator.address,
|
||||
outOfLimitValueData,
|
||||
failedMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
// when
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
contract.address,
|
||||
otherSideMediator.address,
|
||||
outOfLimitValueData,
|
||||
failedMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
|
||||
expect(await ambBridgeContract.messageCallStatus(failedMessageId)).to.be.equal(false)
|
||||
expect(await ambBridgeContract.messageCallStatus(failedMessageId)).to.be.equal(false)
|
||||
|
||||
// Then
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
})
|
||||
// Then
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
describe('requestFailedMessageFix', () => {
|
||||
|
|
|
@ -153,6 +153,18 @@ contract('HomeAMBErc20ToNative', async accounts => {
|
|||
blockReward.address
|
||||
).should.be.rejected
|
||||
|
||||
// not valid decimal shift
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediator.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
100,
|
||||
owner,
|
||||
blockReward.address
|
||||
).should.be.rejected
|
||||
|
||||
const { logs } = await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediator.address,
|
||||
|
@ -748,47 +760,47 @@ contract('HomeAMBErc20ToNative', async accounts => {
|
|||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
|
||||
it('should unlock tokens on message from amb with decimal shift of two', async () => {
|
||||
// Given
|
||||
const decimalShiftTwo = 2
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`should unlock tokens on message from amb with decimal shift of ${decimalShift}`, async () => {
|
||||
// Given
|
||||
contract = await HomeAMBErc20ToNative.new()
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediator.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShift,
|
||||
owner,
|
||||
blockReward.address
|
||||
).should.be.fulfilled
|
||||
await blockReward.setBridgeContractAddress(contract.address)
|
||||
|
||||
contract = await HomeAMBErc20ToNative.new()
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediator.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShiftTwo,
|
||||
owner,
|
||||
blockReward.address
|
||||
).should.be.fulfilled
|
||||
await blockReward.setBridgeContractAddress(contract.address)
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const data = await contract.contract.methods.handleBridgedTokens(user, valueOnForeign.toString()).encodeABI()
|
||||
|
||||
const data = await contract.contract.methods.handleBridgedTokens(user, valueOnForeign.toString()).encodeABI()
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
contract.address,
|
||||
otherSideMediator.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
contract.address,
|
||||
otherSideMediator.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
// Then
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnForeign)
|
||||
|
||||
// Then
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnForeign)
|
||||
|
||||
const event = await getEvents(contract, { event: 'TokensBridged' })
|
||||
expect(event.length).to.be.equal(1)
|
||||
expect(event[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(event[0].returnValues.value).to.be.equal(valueOnHome.toString())
|
||||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
const event = await getEvents(contract, { event: 'TokensBridged' })
|
||||
expect(event.length).to.be.equal(1)
|
||||
expect(event[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(event[0].returnValues.value).to.be.equal(valueOnHome.toString())
|
||||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
}
|
||||
|
||||
it('should revert when out of execution limits on message from amb', async () => {
|
||||
// Given
|
||||
|
|
|
@ -132,6 +132,18 @@ function shouldBehaveLikeBasicAMBErc677ToErc677(otherSideMediatorContract, accou
|
|||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
// not valid decimal shift
|
||||
await contract.initialize(
|
||||
bridgeContract.address,
|
||||
mediatorContract.address,
|
||||
erc677Token.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
100,
|
||||
owner
|
||||
).should.be.rejected
|
||||
|
||||
const { logs } = await contract.initialize(
|
||||
bridgeContract.address,
|
||||
mediatorContract.address,
|
||||
|
|
|
@ -192,64 +192,65 @@ contract('ForeignAMBErc677ToErc677', async accounts => {
|
|||
expect(TokensBridgedEvent[0].returnValues.value).to.be.equal(oneEther.toString())
|
||||
expect(TokensBridgedEvent[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
it('should transfer locked tokens on message from amb with decimal shift of two', async () => {
|
||||
// Given
|
||||
const decimalShiftTwo = 2
|
||||
erc677Token = await ERC677BridgeToken.new('test', 'TST', 16)
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`should transfer locked tokens on message from amb with decimal shift of ${decimalShift}`, async () => {
|
||||
// Given
|
||||
erc677Token = await ERC677BridgeToken.new('test', 'TST', 16)
|
||||
|
||||
foreignBridge = await ForeignAMBErc677ToErc677.new()
|
||||
await foreignBridge.initialize(
|
||||
ambBridgeContract.address,
|
||||
mediatorContract.address,
|
||||
erc677Token.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShiftTwo,
|
||||
owner
|
||||
).should.be.fulfilled
|
||||
await erc677Token.mint(foreignBridge.address, twoEthers, { from: owner }).should.be.fulfilled
|
||||
await erc677Token.transferOwnership(foreignBridge.address)
|
||||
foreignBridge = await ForeignAMBErc677ToErc677.new()
|
||||
await foreignBridge.initialize(
|
||||
ambBridgeContract.address,
|
||||
mediatorContract.address,
|
||||
erc677Token.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShift,
|
||||
owner
|
||||
).should.be.fulfilled
|
||||
await erc677Token.mint(foreignBridge.address, twoEthers, { from: owner }).should.be.fulfilled
|
||||
await erc677Token.transferOwnership(foreignBridge.address)
|
||||
|
||||
const currentDay = await foreignBridge.getCurrentDay()
|
||||
expect(await foreignBridge.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
const initialEvents = await getEvents(erc677Token, { event: 'Transfer' })
|
||||
expect(initialEvents.length).to.be.equal(0)
|
||||
expect(await erc677Token.balanceOf(foreignBridge.address)).to.be.bignumber.equal(twoEthers)
|
||||
expect(await erc677Token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
const currentDay = await foreignBridge.getCurrentDay()
|
||||
expect(await foreignBridge.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
const initialEvents = await getEvents(erc677Token, { event: 'Transfer' })
|
||||
expect(initialEvents.length).to.be.equal(0)
|
||||
expect(await erc677Token.balanceOf(foreignBridge.address)).to.be.bignumber.equal(twoEthers)
|
||||
expect(await erc677Token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
|
||||
const data = await foreignBridge.contract.methods.handleBridgedTokens(user, valueOnHome.toString()).encodeABI()
|
||||
const data = await foreignBridge.contract.methods.handleBridgedTokens(user, valueOnHome.toString()).encodeABI()
|
||||
|
||||
// message must be generated by mediator contract on the other network
|
||||
await ambBridgeContract.executeMessageCall(foreignBridge.address, owner, data, otherMessageId, 1000000).should.be
|
||||
.fulfilled
|
||||
// message must be generated by mediator contract on the other network
|
||||
await ambBridgeContract.executeMessageCall(foreignBridge.address, owner, data, otherMessageId, 1000000).should
|
||||
.be.fulfilled
|
||||
|
||||
expect(await ambBridgeContract.messageCallStatus(otherMessageId)).to.be.equal(false)
|
||||
expect(await ambBridgeContract.messageCallStatus(otherMessageId)).to.be.equal(false)
|
||||
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
foreignBridge.address,
|
||||
mediatorContract.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
foreignBridge.address,
|
||||
mediatorContract.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
|
||||
// Then
|
||||
expect(await foreignBridge.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnHome)
|
||||
expect(await erc677Token.balanceOf(foreignBridge.address)).to.be.bignumber.equal(twoEthers.sub(valueOnForeign))
|
||||
expect(await erc677Token.balanceOf(user)).to.be.bignumber.equal(valueOnForeign)
|
||||
// Then
|
||||
expect(await foreignBridge.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnHome)
|
||||
expect(await erc677Token.balanceOf(foreignBridge.address)).to.be.bignumber.equal(twoEthers.sub(valueOnForeign))
|
||||
expect(await erc677Token.balanceOf(user)).to.be.bignumber.equal(valueOnForeign)
|
||||
|
||||
const TokensBridgedEvent = await getEvents(foreignBridge, { event: 'TokensBridged' })
|
||||
expect(TokensBridgedEvent.length).to.be.equal(1)
|
||||
expect(TokensBridgedEvent[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(TokensBridgedEvent[0].returnValues.value).to.be.equal(valueOnForeign.toString())
|
||||
expect(TokensBridgedEvent[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
const TokensBridgedEvent = await getEvents(foreignBridge, { event: 'TokensBridged' })
|
||||
expect(TokensBridgedEvent.length).to.be.equal(1)
|
||||
expect(TokensBridgedEvent[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(TokensBridgedEvent[0].returnValues.value).to.be.equal(valueOnForeign.toString())
|
||||
expect(TokensBridgedEvent[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
}
|
||||
it('should emit AmountLimitExceeded and not transfer tokens when out of execution limits', async () => {
|
||||
// Given
|
||||
const currentDay = await foreignBridge.getCurrentDay()
|
||||
|
|
|
@ -200,66 +200,67 @@ contract('HomeAMBErc677ToErc677', async accounts => {
|
|||
expect(TokensBridgedEvent[0].returnValues.value).to.be.equal(oneEther.toString())
|
||||
expect(TokensBridgedEvent[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
it('should mint tokens on message from amb with decimal shift of two', async () => {
|
||||
// Given
|
||||
const decimalShiftTwo = 2
|
||||
erc677Token = await ERC677BridgeToken.new('test', 'TST', 18)
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`should mint tokens on message from amb with decimal shift of ${decimalShift}`, async () => {
|
||||
// Given
|
||||
erc677Token = await ERC677BridgeToken.new('test', 'TST', 18)
|
||||
|
||||
homeBridge = await HomeAMBErc677ToErc677.new()
|
||||
await homeBridge.initialize(
|
||||
ambBridgeContract.address,
|
||||
mediatorContract.address,
|
||||
erc677Token.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShiftTwo,
|
||||
owner
|
||||
).should.be.fulfilled
|
||||
await erc677Token.transferOwnership(homeBridge.address)
|
||||
homeBridge = await HomeAMBErc677ToErc677.new()
|
||||
await homeBridge.initialize(
|
||||
ambBridgeContract.address,
|
||||
mediatorContract.address,
|
||||
erc677Token.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShift,
|
||||
owner
|
||||
).should.be.fulfilled
|
||||
await erc677Token.transferOwnership(homeBridge.address)
|
||||
|
||||
const currentDay = await homeBridge.getCurrentDay()
|
||||
expect(await homeBridge.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
const initialEvents = await getEvents(erc677Token, { event: 'Mint' })
|
||||
expect(initialEvents.length).to.be.equal(0)
|
||||
expect(await erc677Token.totalSupply()).to.be.bignumber.equal(ZERO)
|
||||
const currentDay = await homeBridge.getCurrentDay()
|
||||
expect(await homeBridge.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
const initialEvents = await getEvents(erc677Token, { event: 'Mint' })
|
||||
expect(initialEvents.length).to.be.equal(0)
|
||||
expect(await erc677Token.totalSupply()).to.be.bignumber.equal(ZERO)
|
||||
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
|
||||
const data = await homeBridge.contract.methods.handleBridgedTokens(user, valueOnForeign.toString()).encodeABI()
|
||||
const data = await homeBridge.contract.methods.handleBridgedTokens(user, valueOnForeign.toString()).encodeABI()
|
||||
|
||||
// message must be generated by mediator contract on the other network
|
||||
await ambBridgeContract.executeMessageCall(homeBridge.address, owner, data, otherMessageId, 1000000).should.be
|
||||
.fulfilled
|
||||
// message must be generated by mediator contract on the other network
|
||||
await ambBridgeContract.executeMessageCall(homeBridge.address, owner, data, otherMessageId, 1000000).should.be
|
||||
.fulfilled
|
||||
|
||||
expect(await ambBridgeContract.messageCallStatus(otherMessageId)).to.be.equal(false)
|
||||
expect(await ambBridgeContract.messageCallStatus(otherMessageId)).to.be.equal(false)
|
||||
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
homeBridge.address,
|
||||
mediatorContract.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
homeBridge.address,
|
||||
mediatorContract.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
|
||||
// Then
|
||||
expect(await homeBridge.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnForeign)
|
||||
const events = await getEvents(erc677Token, { event: 'Mint' })
|
||||
expect(events.length).to.be.equal(1)
|
||||
expect(events[0].returnValues.to).to.be.equal(user)
|
||||
expect(events[0].returnValues.amount).to.be.equal(valueOnHome.toString())
|
||||
expect(await erc677Token.totalSupply()).to.be.bignumber.equal(valueOnHome)
|
||||
expect(await erc677Token.balanceOf(user)).to.be.bignumber.equal(valueOnHome)
|
||||
// Then
|
||||
expect(await homeBridge.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnForeign)
|
||||
const events = await getEvents(erc677Token, { event: 'Mint' })
|
||||
expect(events.length).to.be.equal(1)
|
||||
expect(events[0].returnValues.to).to.be.equal(user)
|
||||
expect(events[0].returnValues.amount).to.be.equal(valueOnHome.toString())
|
||||
expect(await erc677Token.totalSupply()).to.be.bignumber.equal(valueOnHome)
|
||||
expect(await erc677Token.balanceOf(user)).to.be.bignumber.equal(valueOnHome)
|
||||
|
||||
const TokensBridgedEvent = await getEvents(homeBridge, { event: 'TokensBridged' })
|
||||
expect(TokensBridgedEvent.length).to.be.equal(1)
|
||||
expect(TokensBridgedEvent[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(TokensBridgedEvent[0].returnValues.value).to.be.equal(valueOnHome.toString())
|
||||
expect(TokensBridgedEvent[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
const TokensBridgedEvent = await getEvents(homeBridge, { event: 'TokensBridged' })
|
||||
expect(TokensBridgedEvent.length).to.be.equal(1)
|
||||
expect(TokensBridgedEvent[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(TokensBridgedEvent[0].returnValues.value).to.be.equal(valueOnHome.toString())
|
||||
expect(TokensBridgedEvent[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
}
|
||||
it('should emit AmountLimitExceeded and not mint tokens when out of execution limits', async () => {
|
||||
// Given
|
||||
const currentDay = await homeBridge.getCurrentDay()
|
||||
|
|
|
@ -198,6 +198,19 @@ contract('ForeignAMBNativeToErc20', async accounts => {
|
|||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
// not valid decimal shift
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediatorContract.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
100,
|
||||
owner,
|
||||
token.address,
|
||||
feeManager.address
|
||||
).should.be.rejected
|
||||
|
||||
const { logs } = await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediatorContract.address,
|
||||
|
@ -1005,68 +1018,69 @@ contract('ForeignAMBNativeToErc20', async accounts => {
|
|||
expect(event[0].returnValues.value).to.be.equal(oneEther.toString())
|
||||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
it('should mint tokens on message from amb with decimal shift of two', async () => {
|
||||
// Given
|
||||
const decimalShiftTwo = 2
|
||||
token = await ERC677BridgeToken.new('test', 'TST', 16)
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`should mint tokens on message from amb with decimal shift of ${decimalShift}`, async () => {
|
||||
// Given
|
||||
token = await ERC677BridgeToken.new('test', 'TST', 16)
|
||||
|
||||
contract = await ForeignAMBNativeToErc20.new()
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediatorContract.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShiftTwo,
|
||||
owner,
|
||||
token.address,
|
||||
ZERO_ADDRESS
|
||||
).should.be.fulfilled
|
||||
contract = await ForeignAMBNativeToErc20.new()
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediatorContract.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShift,
|
||||
owner,
|
||||
token.address,
|
||||
ZERO_ADDRESS
|
||||
).should.be.fulfilled
|
||||
|
||||
await token.transferOwnership(contract.address)
|
||||
await token.transferOwnership(contract.address)
|
||||
|
||||
const currentDay = await contract.getCurrentDay()
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
const initialEvents = await getEvents(token, { event: 'Mint' })
|
||||
expect(initialEvents.length).to.be.equal(0)
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO)
|
||||
const currentDay = await contract.getCurrentDay()
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
const initialEvents = await getEvents(token, { event: 'Mint' })
|
||||
expect(initialEvents.length).to.be.equal(0)
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO)
|
||||
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
|
||||
const data = await contract.contract.methods.handleBridgedTokens(user, valueOnHome.toString()).encodeABI()
|
||||
const data = await contract.contract.methods.handleBridgedTokens(user, valueOnHome.toString()).encodeABI()
|
||||
|
||||
// message must be generated by mediator contract on the other network
|
||||
await ambBridgeContract.executeMessageCall(contract.address, owner, data, failedMessageId, 1000000).should.be
|
||||
.fulfilled
|
||||
// message must be generated by mediator contract on the other network
|
||||
await ambBridgeContract.executeMessageCall(contract.address, owner, data, failedMessageId, 1000000).should.be
|
||||
.fulfilled
|
||||
|
||||
expect(await ambBridgeContract.messageCallStatus(failedMessageId)).to.be.equal(false)
|
||||
expect(await ambBridgeContract.messageCallStatus(failedMessageId)).to.be.equal(false)
|
||||
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
contract.address,
|
||||
otherSideMediatorContract.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
contract.address,
|
||||
otherSideMediatorContract.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
1000000
|
||||
).should.be.fulfilled
|
||||
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
|
||||
// Then
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnHome)
|
||||
const events = await getEvents(token, { event: 'Mint' })
|
||||
expect(events.length).to.be.equal(1)
|
||||
expect(events[0].returnValues.to).to.be.equal(user)
|
||||
expect(events[0].returnValues.amount).to.be.equal(valueOnForeign.toString())
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(valueOnForeign)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(valueOnForeign)
|
||||
// Then
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnHome)
|
||||
const events = await getEvents(token, { event: 'Mint' })
|
||||
expect(events.length).to.be.equal(1)
|
||||
expect(events[0].returnValues.to).to.be.equal(user)
|
||||
expect(events[0].returnValues.amount).to.be.equal(valueOnForeign.toString())
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(valueOnForeign)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(valueOnForeign)
|
||||
|
||||
const event = await getEvents(contract, { event: 'TokensBridged' })
|
||||
expect(event.length).to.be.equal(1)
|
||||
expect(event[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(event[0].returnValues.value).to.be.equal(valueOnForeign.toString())
|
||||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
const event = await getEvents(contract, { event: 'TokensBridged' })
|
||||
expect(event.length).to.be.equal(1)
|
||||
expect(event[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(event[0].returnValues.value).to.be.equal(valueOnForeign.toString())
|
||||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
}
|
||||
it('should revert when out of execution limits on message from amb', async () => {
|
||||
// Given
|
||||
const currentDay = await contract.getCurrentDay()
|
||||
|
|
|
@ -165,6 +165,18 @@ contract('HomeAMBNativeToErc20', async accounts => {
|
|||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
// not valid decimal shift
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediatorContract.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
100,
|
||||
owner,
|
||||
feeManager.address
|
||||
).should.be.rejected
|
||||
|
||||
const { logs } = await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediatorContract.address,
|
||||
|
@ -582,73 +594,74 @@ contract('HomeAMBNativeToErc20', async accounts => {
|
|||
expect(event[0].returnValues.value).to.be.equal(oneEther.toString())
|
||||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
it('should unlock native tokens on message from amb with decimal shift of two', async () => {
|
||||
// Given
|
||||
contract = await HomeAMBNativeToErc20.new()
|
||||
const decimalShiftTwo = 2
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`should unlock native tokens on message from amb with decimal shift of ${decimalShift}`, async () => {
|
||||
// Given
|
||||
contract = await HomeAMBNativeToErc20.new()
|
||||
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediatorContract.address,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShiftTwo,
|
||||
owner,
|
||||
ZERO_ADDRESS
|
||||
).should.be.fulfilled
|
||||
await contract.initialize(
|
||||
ambBridgeContract.address,
|
||||
otherSideMediatorContract.address,
|
||||
[dailyLimit, maxPerTx, ether('0.001')],
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
maxGasPerTx,
|
||||
decimalShift,
|
||||
owner,
|
||||
ZERO_ADDRESS
|
||||
).should.be.fulfilled
|
||||
|
||||
const valueOnForeign = ether('0.01')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const valueOnForeign = ether('0.01')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
|
||||
// send native tokens to the contract
|
||||
await contract.sendTransaction({
|
||||
from: user2,
|
||||
value: valueOnHome
|
||||
}).should.be.fulfilled
|
||||
// send native tokens to the contract
|
||||
await contract.sendTransaction({
|
||||
from: user2,
|
||||
value: valueOnHome
|
||||
}).should.be.fulfilled
|
||||
|
||||
expect(toBN(await web3.eth.getBalance(contract.address))).to.be.bignumber.equal(valueOnHome)
|
||||
expect(toBN(await web3.eth.getBalance(contract.address))).to.be.bignumber.equal(valueOnHome)
|
||||
|
||||
const currentDay = await contract.getCurrentDay()
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
const currentDay = await contract.getCurrentDay()
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
|
||||
// When
|
||||
// can't be called by user
|
||||
await contract.handleBridgedTokens(user, valueOnForeign, { from: user }).should.be.rejectedWith(ERROR_MSG)
|
||||
// can't be called by owner
|
||||
await contract.handleBridgedTokens(user, valueOnForeign, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
// When
|
||||
// can't be called by user
|
||||
await contract.handleBridgedTokens(user, valueOnForeign, { from: user }).should.be.rejectedWith(ERROR_MSG)
|
||||
// can't be called by owner
|
||||
await contract.handleBridgedTokens(user, valueOnForeign, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
const data = await contract.contract.methods.handleBridgedTokens(user, valueOnForeign.toString()).encodeABI()
|
||||
const data = await contract.contract.methods.handleBridgedTokens(user, valueOnForeign.toString()).encodeABI()
|
||||
|
||||
// message must be generated by mediator contract on the other network, here owner is the sender
|
||||
await ambBridgeContract.executeMessageCall(contract.address, owner, data, failedMessageId, '1000000').should.be
|
||||
.fulfilled
|
||||
// message must be generated by mediator contract on the other network, here owner is the sender
|
||||
await ambBridgeContract.executeMessageCall(contract.address, owner, data, failedMessageId, '1000000').should.be
|
||||
.fulfilled
|
||||
|
||||
expect(await ambBridgeContract.messageCallStatus(failedMessageId)).to.be.equal(false)
|
||||
expect(await ambBridgeContract.messageCallStatus(failedMessageId)).to.be.equal(false)
|
||||
|
||||
const balanceUserBefore = toBN(await web3.eth.getBalance(user))
|
||||
const balanceUserBefore = toBN(await web3.eth.getBalance(user))
|
||||
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
contract.address,
|
||||
otherSideMediatorContract.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
'1000000'
|
||||
).should.be.fulfilled
|
||||
await ambBridgeContract.executeMessageCall(
|
||||
contract.address,
|
||||
otherSideMediatorContract.address,
|
||||
data,
|
||||
exampleMessageId,
|
||||
'1000000'
|
||||
).should.be.fulfilled
|
||||
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true)
|
||||
|
||||
// Then
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnForeign)
|
||||
expect(toBN(await web3.eth.getBalance(contract.address))).to.be.bignumber.equal(ZERO)
|
||||
expect(toBN(await web3.eth.getBalance(user))).to.be.bignumber.equal(balanceUserBefore.add(valueOnHome))
|
||||
// Then
|
||||
expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(valueOnForeign)
|
||||
expect(toBN(await web3.eth.getBalance(contract.address))).to.be.bignumber.equal(ZERO)
|
||||
expect(toBN(await web3.eth.getBalance(user))).to.be.bignumber.equal(balanceUserBefore.add(valueOnHome))
|
||||
|
||||
const event = await getEvents(contract, { event: 'TokensBridged' })
|
||||
expect(event.length).to.be.equal(1)
|
||||
expect(event[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(event[0].returnValues.value).to.be.equal(valueOnHome.toString())
|
||||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
const event = await getEvents(contract, { event: 'TokensBridged' })
|
||||
expect(event.length).to.be.equal(1)
|
||||
expect(event[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(event[0].returnValues.value).to.be.equal(valueOnHome.toString())
|
||||
expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId)
|
||||
})
|
||||
}
|
||||
it('should revert when out of execution limits on message from amb', async () => {
|
||||
// Given
|
||||
// send native tokens to the contract
|
||||
|
|
|
@ -154,6 +154,18 @@ contract('ForeignBridge_ERC20_to_ERC20', async accounts => {
|
|||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
// not valid decimal shift
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
100
|
||||
).should.be.rejected
|
||||
|
||||
const { logs } = await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
|
@ -771,130 +783,132 @@ contract('ForeignBridge_ERC20_to_ERC20', async accounts => {
|
|||
})
|
||||
})
|
||||
describe('#decimalShift', async () => {
|
||||
const decimalShiftTwo = 2
|
||||
it('Home to Foreign: withdraw with 1 signature with a decimalShift of 2', async () => {
|
||||
const valueOnForeign = toBN('1000')
|
||||
// Value is decimals shifted from foreign to home: Native on home = 16+2 shift = 18 decimals
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const foreignBridge = await ForeignBridge.new()
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 16)
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo
|
||||
)
|
||||
await token.mint(foreignBridge.address, valueOnForeign)
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`Home to Foreign: withdraw with 1 signature with a decimalShift of ${decimalShift}`, async () => {
|
||||
const valueOnForeign = toBN('1000')
|
||||
// Value is decimals shifted from foreign to home: Native on home = 16+2 shift = 18 decimals
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
const foreignBridge = await ForeignBridge.new()
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 16)
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShift
|
||||
)
|
||||
await token.mint(foreignBridge.address, valueOnForeign)
|
||||
|
||||
const recipientAccount = accounts[3]
|
||||
const balanceBefore = await token.balanceOf(recipientAccount)
|
||||
const recipientAccount = accounts[3]
|
||||
const balanceBefore = await token.balanceOf(recipientAccount)
|
||||
|
||||
const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80'
|
||||
const message = createMessage(recipientAccount, valueOnHome, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature)
|
||||
const oneSignature = packSignatures([vrs])
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
const { logs } = await foreignBridge.executeSignatures(message, oneSignature).should.be.fulfilled
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipientAccount)
|
||||
logs[0].args.value.should.be.bignumber.equal(valueOnHome)
|
||||
const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80'
|
||||
const message = createMessage(recipientAccount, valueOnHome, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature)
|
||||
const oneSignature = packSignatures([vrs])
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
const { logs } = await foreignBridge.executeSignatures(message, oneSignature).should.be.fulfilled
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipientAccount)
|
||||
logs[0].args.value.should.be.bignumber.equal(valueOnHome)
|
||||
|
||||
const balanceAfter = await token.balanceOf(recipientAccount)
|
||||
const balanceAfterBridge = await token.balanceOf(foreignBridge.address)
|
||||
balanceAfter.should.be.bignumber.equal(balanceBefore.add(valueOnForeign))
|
||||
balanceAfterBridge.should.be.bignumber.equal(ZERO)
|
||||
true.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
})
|
||||
it('Home to Foreign : withdraw works with 5 validators and 3 required signatures with a decimalShift of 2', async () => {
|
||||
const valueOnForeign = toBN('1000')
|
||||
// Value is decimals shifted from foreign to home: Native on home = 16+2 shift = 18 decimals
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const recipient = accounts[8]
|
||||
const authoritiesFiveAccs = [accounts[1], accounts[2], accounts[3], accounts[4], accounts[5]]
|
||||
const ownerOfValidators = accounts[0]
|
||||
const validatorContractWith3Signatures = await BridgeValidators.new()
|
||||
await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators)
|
||||
const erc20Token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 16)
|
||||
const balanceAfter = await token.balanceOf(recipientAccount)
|
||||
const balanceAfterBridge = await token.balanceOf(foreignBridge.address)
|
||||
balanceAfter.should.be.bignumber.equal(balanceBefore.add(valueOnForeign))
|
||||
balanceAfterBridge.should.be.bignumber.equal(ZERO)
|
||||
true.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
})
|
||||
it('Home to Foreign : withdraw works with 5 validators and 3 required signatures with a decimalShift of 2', async () => {
|
||||
const valueOnForeign = toBN('1000')
|
||||
// Value is decimals shifted from foreign to home: Native on home = 16+2 shift = 18 decimals
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
const recipient = accounts[8]
|
||||
const authoritiesFiveAccs = [accounts[1], accounts[2], accounts[3], accounts[4], accounts[5]]
|
||||
const ownerOfValidators = accounts[0]
|
||||
const validatorContractWith3Signatures = await BridgeValidators.new()
|
||||
await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators)
|
||||
const erc20Token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 16)
|
||||
|
||||
const foreignBridgeWithThreeSigs = await ForeignBridge.new()
|
||||
const foreignBridgeWithThreeSigs = await ForeignBridge.new()
|
||||
|
||||
await foreignBridgeWithThreeSigs.initialize(
|
||||
validatorContractWith3Signatures.address,
|
||||
erc20Token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo
|
||||
)
|
||||
await erc20Token.mint(foreignBridgeWithThreeSigs.address, valueOnForeign)
|
||||
await foreignBridgeWithThreeSigs.initialize(
|
||||
validatorContractWith3Signatures.address,
|
||||
erc20Token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShift
|
||||
)
|
||||
await erc20Token.mint(foreignBridgeWithThreeSigs.address, valueOnForeign)
|
||||
|
||||
const balanceBeforeRecipient = await erc20Token.balanceOf(recipient)
|
||||
const balanceBeforeBridge = await erc20Token.balanceOf(foreignBridgeWithThreeSigs.address)
|
||||
const balanceBeforeRecipient = await erc20Token.balanceOf(recipient)
|
||||
const balanceBeforeBridge = await erc20Token.balanceOf(foreignBridgeWithThreeSigs.address)
|
||||
|
||||
const txHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipient, valueOnHome, txHash, foreignBridgeWithThreeSigs.address)
|
||||
const txHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipient, valueOnHome, txHash, foreignBridgeWithThreeSigs.address)
|
||||
|
||||
// signature 1
|
||||
const signature = await sign(authoritiesFiveAccs[0], message)
|
||||
const vrs = signatureToVRS(signature)
|
||||
// signature 1
|
||||
const signature = await sign(authoritiesFiveAccs[0], message)
|
||||
const vrs = signatureToVRS(signature)
|
||||
|
||||
// signature 2
|
||||
const signature2 = await sign(authoritiesFiveAccs[1], message)
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
// signature 2
|
||||
const signature2 = await sign(authoritiesFiveAccs[1], message)
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
|
||||
// signature 3
|
||||
const signature3 = await sign(authoritiesFiveAccs[2], message)
|
||||
const vrs3 = signatureToVRS(signature3)
|
||||
// signature 3
|
||||
const signature3 = await sign(authoritiesFiveAccs[2], message)
|
||||
const vrs3 = signatureToVRS(signature3)
|
||||
|
||||
const threeSignatures = packSignatures([vrs, vrs2, vrs3])
|
||||
const threeSignatures = packSignatures([vrs, vrs2, vrs3])
|
||||
|
||||
const { logs } = await foreignBridgeWithThreeSigs.executeSignatures(message, threeSignatures).should.be.fulfilled
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipient)
|
||||
logs[0].args.value.should.be.bignumber.equal(valueOnHome)
|
||||
true.should.be.equal(await foreignBridgeWithThreeSigs.relayedMessages(txHash))
|
||||
const balanceAfterRecipient = await erc20Token.balanceOf(recipient)
|
||||
balanceAfterRecipient.should.be.bignumber.equal(balanceBeforeRecipient.add(valueOnForeign))
|
||||
const balanceAfterBridge = await erc20Token.balanceOf(foreignBridgeWithThreeSigs.address)
|
||||
balanceBeforeBridge.should.be.bignumber.equal(balanceAfterBridge.add(valueOnForeign))
|
||||
})
|
||||
it('Foreign to Home: no impact in UserRequestForAffirmation event signal for bridges oracles with a decimalShift of 2.', async () => {
|
||||
const value = halfEther
|
||||
const owner = accounts[3]
|
||||
const user = accounts[4]
|
||||
token = await ERC677BridgeToken.new('TEST', 'TST', 16, { from: owner })
|
||||
const foreignBridge = await ForeignBridgeErc677ToErc677.new()
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo
|
||||
)
|
||||
const { logs } = await foreignBridgeWithThreeSigs.executeSignatures(message, threeSignatures).should.be
|
||||
.fulfilled
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipient)
|
||||
logs[0].args.value.should.be.bignumber.equal(valueOnHome)
|
||||
true.should.be.equal(await foreignBridgeWithThreeSigs.relayedMessages(txHash))
|
||||
const balanceAfterRecipient = await erc20Token.balanceOf(recipient)
|
||||
balanceAfterRecipient.should.be.bignumber.equal(balanceBeforeRecipient.add(valueOnForeign))
|
||||
const balanceAfterBridge = await erc20Token.balanceOf(foreignBridgeWithThreeSigs.address)
|
||||
balanceBeforeBridge.should.be.bignumber.equal(balanceAfterBridge.add(valueOnForeign))
|
||||
})
|
||||
it('Foreign to Home: no impact in UserRequestForAffirmation event signal for bridges oracles with a decimalShift of 2.', async () => {
|
||||
const value = halfEther
|
||||
const owner = accounts[3]
|
||||
const user = accounts[4]
|
||||
token = await ERC677BridgeToken.new('TEST', 'TST', 16, { from: owner })
|
||||
const foreignBridge = await ForeignBridgeErc677ToErc677.new()
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShift
|
||||
)
|
||||
|
||||
await token.mint(user, value, { from: owner }).should.be.fulfilled
|
||||
await token.transferOwnership(foreignBridge.address, { from: owner })
|
||||
await foreignBridge.onTokenTransfer(user, value, '0x', { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
await token.mint(user, value, { from: owner }).should.be.fulfilled
|
||||
await token.transferOwnership(foreignBridge.address, { from: owner })
|
||||
await foreignBridge.onTokenTransfer(user, value, '0x', { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
await token.transferAndCall(foreignBridge.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(value)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(foreignBridge.address)).to.be.bignumber.equal(value)
|
||||
await token.transferAndCall(foreignBridge.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(value)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(foreignBridge.address)).to.be.bignumber.equal(value)
|
||||
|
||||
const events = await getEvents(foreignBridge, { event: 'UserRequestForAffirmation' })
|
||||
expect(events[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(toBN(events[0].returnValues.value)).to.be.bignumber.equal(value)
|
||||
})
|
||||
const events = await getEvents(foreignBridge, { event: 'UserRequestForAffirmation' })
|
||||
expect(events[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(toBN(events[0].returnValues.value)).to.be.bignumber.equal(value)
|
||||
})
|
||||
}
|
||||
})
|
||||
describe('#relayTokens', () => {
|
||||
const value = ether('0.25')
|
||||
|
|
|
@ -216,6 +216,19 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => {
|
|||
decimalShiftZero
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
// not valid decimal shift
|
||||
await homeContract.initialize(
|
||||
validatorContract.address,
|
||||
['3', '2', '1'],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
token.address,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
100
|
||||
).should.be.rejected
|
||||
|
||||
await homeContract.initialize(
|
||||
validatorContract.address,
|
||||
['3', '2', '1'],
|
||||
|
@ -1981,86 +1994,87 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => {
|
|||
})
|
||||
})
|
||||
describe('#decimals Shift', async () => {
|
||||
const decimalShiftTwo = 2
|
||||
it('Foreign to Home: works with 5 validators and 3 required signatures with decimal shift 2', async () => {
|
||||
const recipient = accounts[8]
|
||||
const authoritiesFiveAccs = [accounts[1], accounts[2], accounts[3], accounts[4], accounts[5]]
|
||||
const ownerOfValidators = accounts[0]
|
||||
const validatorContractWith3Signatures = await BridgeValidators.new()
|
||||
await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators)
|
||||
const token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 16)
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`Foreign to Home: works with 5 validators and 3 required signatures with decimal shift ${decimalShift}`, async () => {
|
||||
const recipient = accounts[8]
|
||||
const authoritiesFiveAccs = [accounts[1], accounts[2], accounts[3], accounts[4], accounts[5]]
|
||||
const ownerOfValidators = accounts[0]
|
||||
const validatorContractWith3Signatures = await BridgeValidators.new()
|
||||
await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators)
|
||||
const token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 16)
|
||||
|
||||
const homeBridgeWithThreeSigs = await HomeBridge.new()
|
||||
await homeBridgeWithThreeSigs.initialize(
|
||||
validatorContractWith3Signatures.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
token.address,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo
|
||||
)
|
||||
await token.transferOwnership(homeBridgeWithThreeSigs.address)
|
||||
const homeBridgeWithThreeSigs = await HomeBridge.new()
|
||||
await homeBridgeWithThreeSigs.initialize(
|
||||
validatorContractWith3Signatures.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
token.address,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShift
|
||||
)
|
||||
await token.transferOwnership(homeBridgeWithThreeSigs.address)
|
||||
|
||||
const valueOnForeign = toBN('1000')
|
||||
// Value is decimals shifted from foreign to home: Native on home = 16+2 shift = 18 decimals
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const balanceBeforeRecipient = await token.balanceOf(recipient)
|
||||
const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415'
|
||||
const valueOnForeign = toBN('1000')
|
||||
// Value is decimals shifted from foreign to home: Native on home = 16+2 shift = 18 decimals
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
const balanceBeforeRecipient = await token.balanceOf(recipient)
|
||||
const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415'
|
||||
|
||||
const { logs } = await homeBridgeWithThreeSigs.executeAffirmation(recipient, valueOnForeign, transactionHash, {
|
||||
from: authoritiesFiveAccs[0]
|
||||
}).should.be.fulfilled
|
||||
expectEventInLogs(logs, 'SignedForAffirmation', {
|
||||
signer: authorities[0],
|
||||
transactionHash
|
||||
const { logs } = await homeBridgeWithThreeSigs.executeAffirmation(recipient, valueOnForeign, transactionHash, {
|
||||
from: authoritiesFiveAccs[0]
|
||||
}).should.be.fulfilled
|
||||
expectEventInLogs(logs, 'SignedForAffirmation', {
|
||||
signer: authorities[0],
|
||||
transactionHash
|
||||
})
|
||||
|
||||
await homeBridgeWithThreeSigs.executeAffirmation(recipient, valueOnForeign, transactionHash, {
|
||||
from: authoritiesFiveAccs[1]
|
||||
}).should.be.fulfilled
|
||||
const thirdSignature = await homeBridgeWithThreeSigs.executeAffirmation(
|
||||
recipient,
|
||||
valueOnForeign,
|
||||
transactionHash,
|
||||
{ from: authoritiesFiveAccs[2] }
|
||||
).should.be.fulfilled
|
||||
|
||||
expectEventInLogs(thirdSignature.logs, 'AffirmationCompleted', {
|
||||
recipient,
|
||||
value: valueOnForeign,
|
||||
transactionHash
|
||||
})
|
||||
const balanceAfterRecipient = await token.balanceOf(recipient)
|
||||
balanceAfterRecipient.should.be.bignumber.equal(balanceBeforeRecipient.add(valueOnHome))
|
||||
})
|
||||
it(`Foreign to Home: test decimal shift ${decimalShift}, no impact on UserRequestForSignature value`, async () => {
|
||||
// Given
|
||||
const homeBridge = await HomeBridge.new()
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'TEST', 16)
|
||||
const owner = accounts[0]
|
||||
const user = accounts[4]
|
||||
await homeBridge.initialize(
|
||||
validatorContract.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
token.address,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShift
|
||||
).should.be.fulfilled
|
||||
const value = halfEther
|
||||
await token.mint(user, value, { from: owner }).should.be.fulfilled
|
||||
|
||||
await homeBridgeWithThreeSigs.executeAffirmation(recipient, valueOnForeign, transactionHash, {
|
||||
from: authoritiesFiveAccs[1]
|
||||
}).should.be.fulfilled
|
||||
const thirdSignature = await homeBridgeWithThreeSigs.executeAffirmation(
|
||||
recipient,
|
||||
valueOnForeign,
|
||||
transactionHash,
|
||||
{ from: authoritiesFiveAccs[2] }
|
||||
).should.be.fulfilled
|
||||
// When
|
||||
await token.transferAndCall(homeBridge.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
expectEventInLogs(thirdSignature.logs, 'AffirmationCompleted', {
|
||||
recipient,
|
||||
value: valueOnForeign,
|
||||
transactionHash
|
||||
// Then
|
||||
const events = await getEvents(homeBridge, { event: 'UserRequestForSignature' })
|
||||
expect(events[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(toBN(events[0].returnValues.value)).to.be.bignumber.equal(value)
|
||||
})
|
||||
const balanceAfterRecipient = await token.balanceOf(recipient)
|
||||
balanceAfterRecipient.should.be.bignumber.equal(balanceBeforeRecipient.add(valueOnHome))
|
||||
})
|
||||
it('Foreign to Home: test decimal shift 2, no impact on UserRequestForSignature value', async () => {
|
||||
// Given
|
||||
const homeBridge = await HomeBridge.new()
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'TEST', 16)
|
||||
const owner = accounts[0]
|
||||
const user = accounts[4]
|
||||
await homeBridge.initialize(
|
||||
validatorContract.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
token.address,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo
|
||||
).should.be.fulfilled
|
||||
const value = halfEther
|
||||
await token.mint(user, value, { from: owner }).should.be.fulfilled
|
||||
|
||||
// When
|
||||
await token.transferAndCall(homeBridge.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
// Then
|
||||
const events = await getEvents(homeBridge, { event: 'UserRequestForSignature' })
|
||||
expect(events[0].returnValues.recipient).to.be.equal(user)
|
||||
expect(toBN(events[0].returnValues.value)).to.be.bignumber.equal(value)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -199,6 +199,19 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => {
|
|||
ZERO_ADDRESS
|
||||
).should.be.rejected
|
||||
|
||||
// not valid decimal shift
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
'100',
|
||||
otherSideBridge.address
|
||||
).should.be.rejected
|
||||
|
||||
const { logs } = await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
|
@ -776,108 +789,108 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => {
|
|||
})
|
||||
})
|
||||
describe('#decimalShift', async () => {
|
||||
const decimalShiftTwo = 2
|
||||
it('Home to Foreign: withdraw with 1 signature with a decimalShift of 2', async () => {
|
||||
// From a foreign a token erc token 16 decimals.
|
||||
const token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 16)
|
||||
const valueOnForeign = toBN('1000')
|
||||
// Value is decimals shifted from foreign to home: Native on home = 16+2 shift = 18 decimals
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`Home to Foreign: withdraw with 1 signature with a decimalShift of ${decimalShift}`, async () => {
|
||||
// From a foreign a token erc token 16 decimals.
|
||||
const token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 16)
|
||||
const valueOnForeign = toBN('1000')
|
||||
// Value is decimals shifted from foreign to home: Native on home = 16+2 shift = 18 decimals
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
|
||||
const owner = accounts[0]
|
||||
const foreignBridgeImpl = await ForeignBridgeErcToNativeMock.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)
|
||||
const owner = accounts[0]
|
||||
const foreignBridgeImpl = await ForeignBridgeErcToNativeMock.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,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo,
|
||||
otherSideBridge.address
|
||||
)
|
||||
await token.mint(foreignBridge.address, valueOnForeign)
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShift,
|
||||
otherSideBridge.address
|
||||
)
|
||||
await token.mint(foreignBridge.address, valueOnForeign)
|
||||
|
||||
const recipientAccount = accounts[3]
|
||||
const balanceBefore = await token.balanceOf(recipientAccount)
|
||||
const recipientAccount = accounts[3]
|
||||
const balanceBefore = await token.balanceOf(recipientAccount)
|
||||
|
||||
const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80'
|
||||
const message = createMessage(recipientAccount, valueOnHome, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature)
|
||||
const oneSignature = packSignatures([vrs])
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80'
|
||||
const message = createMessage(recipientAccount, valueOnHome, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature)
|
||||
const oneSignature = packSignatures([vrs])
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
|
||||
const { logs } = await foreignBridge.executeSignatures(message, oneSignature).should.be.fulfilled
|
||||
const { logs } = await foreignBridge.executeSignatures(message, oneSignature).should.be.fulfilled
|
||||
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipientAccount)
|
||||
logs[0].args.value.should.be.bignumber.equal(valueOnHome)
|
||||
const balanceAfter = await token.balanceOf(recipientAccount)
|
||||
balanceAfter.should.be.bignumber.equal(balanceBefore.add(valueOnForeign))
|
||||
const balanceAfterBridge = await token.balanceOf(foreignBridge.address)
|
||||
balanceAfterBridge.should.be.bignumber.equal(ZERO)
|
||||
true.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
})
|
||||
|
||||
it('Home to Foreign: withdraw with 2 minimum signatures with a decimalShift of 2', async () => {
|
||||
const multisigValidatorContract = await BridgeValidators.new()
|
||||
const valueOnForeign = toBN('1000')
|
||||
const decimalShiftTwo = 2
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 16)
|
||||
const twoAuthorities = [accounts[0], accounts[1]]
|
||||
const ownerOfValidatorContract = accounts[3]
|
||||
const recipient = accounts[8]
|
||||
await multisigValidatorContract.initialize(2, twoAuthorities, ownerOfValidatorContract, {
|
||||
from: ownerOfValidatorContract
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipientAccount)
|
||||
logs[0].args.value.should.be.bignumber.equal(valueOnHome)
|
||||
const balanceAfter = await token.balanceOf(recipientAccount)
|
||||
balanceAfter.should.be.bignumber.equal(balanceBefore.add(valueOnForeign))
|
||||
const balanceAfterBridge = await token.balanceOf(foreignBridge.address)
|
||||
balanceAfterBridge.should.be.bignumber.equal(ZERO)
|
||||
true.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
})
|
||||
const foreignBridgeWithMultiSignatures = await ForeignBridgeErcToNativeMock.new()
|
||||
await foreignBridgeWithMultiSignatures.initialize(
|
||||
multisigValidatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo,
|
||||
otherSideBridge.address,
|
||||
{ from: ownerOfValidatorContract }
|
||||
)
|
||||
await token.mint(foreignBridgeWithMultiSignatures.address, valueOnForeign)
|
||||
|
||||
const balanceBefore = await token.balanceOf(recipient)
|
||||
it(`Home to Foreign: withdraw with 2 minimum signatures with a decimalShift of ${decimalShift}`, async () => {
|
||||
const multisigValidatorContract = await BridgeValidators.new()
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
const token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 16)
|
||||
const twoAuthorities = [accounts[0], accounts[1]]
|
||||
const ownerOfValidatorContract = accounts[3]
|
||||
const recipient = accounts[8]
|
||||
await multisigValidatorContract.initialize(2, twoAuthorities, ownerOfValidatorContract, {
|
||||
from: ownerOfValidatorContract
|
||||
})
|
||||
const foreignBridgeWithMultiSignatures = await ForeignBridgeErcToNativeMock.new()
|
||||
await foreignBridgeWithMultiSignatures.initialize(
|
||||
multisigValidatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
[dailyLimit, maxPerTx, minPerTx],
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShift,
|
||||
otherSideBridge.address,
|
||||
{ from: ownerOfValidatorContract }
|
||||
)
|
||||
await token.mint(foreignBridgeWithMultiSignatures.address, valueOnForeign)
|
||||
|
||||
const txHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipient, valueOnHome, txHash, foreignBridgeWithMultiSignatures.address)
|
||||
const balanceBefore = await token.balanceOf(recipient)
|
||||
|
||||
// signature 1
|
||||
const signature = await sign(twoAuthorities[0], message)
|
||||
const vrs = signatureToVRS(signature)
|
||||
const txHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipient, valueOnHome, txHash, foreignBridgeWithMultiSignatures.address)
|
||||
|
||||
// signature 2
|
||||
const signature2 = await sign(twoAuthorities[1], message)
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
// signature 1
|
||||
const signature = await sign(twoAuthorities[0], message)
|
||||
const vrs = signatureToVRS(signature)
|
||||
|
||||
const twoSignatures = packSignatures([vrs, vrs2])
|
||||
// signature 2
|
||||
const signature2 = await sign(twoAuthorities[1], message)
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
|
||||
const { logs } = await foreignBridgeWithMultiSignatures.executeSignatures(message, twoSignatures).should.be
|
||||
.fulfilled
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipient)
|
||||
logs[0].args.value.should.be.bignumber.equal(valueOnHome)
|
||||
const balanceAfter = await token.balanceOf(recipient)
|
||||
balanceAfter.should.be.bignumber.equal(balanceBefore.add(valueOnForeign))
|
||||
const balanceAfterBridge = await token.balanceOf(foreignBridgeWithMultiSignatures.address)
|
||||
balanceAfterBridge.should.be.bignumber.equal(ZERO)
|
||||
true.should.be.equal(await foreignBridgeWithMultiSignatures.relayedMessages(txHash))
|
||||
})
|
||||
const twoSignatures = packSignatures([vrs, vrs2])
|
||||
|
||||
const { logs } = await foreignBridgeWithMultiSignatures.executeSignatures(message, twoSignatures).should.be
|
||||
.fulfilled
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipient)
|
||||
logs[0].args.value.should.be.bignumber.equal(valueOnHome)
|
||||
const balanceAfter = await token.balanceOf(recipient)
|
||||
balanceAfter.should.be.bignumber.equal(balanceBefore.add(valueOnForeign))
|
||||
const balanceAfterBridge = await token.balanceOf(foreignBridgeWithMultiSignatures.address)
|
||||
balanceAfterBridge.should.be.bignumber.equal(ZERO)
|
||||
true.should.be.equal(await foreignBridgeWithMultiSignatures.relayedMessages(txHash))
|
||||
})
|
||||
}
|
||||
})
|
||||
describe('#relayTokens', () => {
|
||||
const value = ether('0.25')
|
||||
|
|
|
@ -279,6 +279,19 @@ contract('HomeBridge_ERC20_to_Native', async accounts => {
|
|||
decimalShiftZero
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
// not valid decimal shift
|
||||
await homeContract.initialize(
|
||||
validatorContract.address,
|
||||
['3', '2', '1'],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
blockRewardContract.address,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
'100'
|
||||
).should.be.rejected
|
||||
|
||||
await homeContract.initialize(
|
||||
validatorContract.address,
|
||||
['3', '2', '1'],
|
||||
|
@ -3322,127 +3335,128 @@ contract('HomeBridge_ERC20_to_Native', async accounts => {
|
|||
})
|
||||
})
|
||||
describe('#decimals Shift', async () => {
|
||||
const decimalShiftTwo = 2
|
||||
it('Foreign to Home: test with 2 signatures required and decimal shift 2', async () => {
|
||||
await blockRewardContract.sendTransaction({
|
||||
from: accounts[2],
|
||||
value: oneEther
|
||||
}).should.be.fulfilled
|
||||
const recipient = accounts[5]
|
||||
const valueOnHome = halfEther
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`Foreign to Home: test with 2 signatures required and decimal shift ${decimalShift}`, async () => {
|
||||
await blockRewardContract.sendTransaction({
|
||||
from: accounts[2],
|
||||
value: oneEther
|
||||
}).should.be.fulfilled
|
||||
const recipient = accounts[5]
|
||||
const valueOnHome = halfEther
|
||||
|
||||
const valueOnForeign = toBN(valueOnHome / 10 ** decimalShiftTwo)
|
||||
const valueOnForeign = toBN(valueOnHome / 10 ** decimalShift)
|
||||
|
||||
const validatorContractWith2Signatures = await BridgeValidators.new()
|
||||
const authoritiesThreeAccs = [accounts[1], accounts[2], accounts[3]]
|
||||
const ownerOfValidators = accounts[0]
|
||||
await validatorContractWith2Signatures.initialize(2, authoritiesThreeAccs, ownerOfValidators)
|
||||
const homeBridgeWithTwoSigs = await HomeBridge.new()
|
||||
const currentDay = await homeBridgeWithTwoSigs.getCurrentDay()
|
||||
const validatorContractWith2Signatures = await BridgeValidators.new()
|
||||
const authoritiesThreeAccs = [accounts[1], accounts[2], accounts[3]]
|
||||
const ownerOfValidators = accounts[0]
|
||||
await validatorContractWith2Signatures.initialize(2, authoritiesThreeAccs, ownerOfValidators)
|
||||
const homeBridgeWithTwoSigs = await HomeBridge.new()
|
||||
const currentDay = await homeBridgeWithTwoSigs.getCurrentDay()
|
||||
|
||||
await homeBridgeWithTwoSigs.initialize(
|
||||
validatorContractWith2Signatures.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
blockRewardContract.address,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo
|
||||
)
|
||||
const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415'
|
||||
const balanceBefore = toBN(await web3.eth.getBalance(recipient))
|
||||
const totalExecutedPerDayBefore = await homeBridgeWithTwoSigs.totalExecutedPerDay(currentDay)
|
||||
const msgHash = web3.utils.soliditySha3(recipient, valueOnForeign, transactionHash)
|
||||
await homeBridgeWithTwoSigs.initialize(
|
||||
validatorContractWith2Signatures.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
blockRewardContract.address,
|
||||
[ether('100'), ether('10')],
|
||||
owner,
|
||||
decimalShift
|
||||
)
|
||||
const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415'
|
||||
const balanceBefore = toBN(await web3.eth.getBalance(recipient))
|
||||
const totalExecutedPerDayBefore = await homeBridgeWithTwoSigs.totalExecutedPerDay(currentDay)
|
||||
const msgHash = web3.utils.soliditySha3(recipient, valueOnForeign, transactionHash)
|
||||
|
||||
const { logs } = await homeBridgeWithTwoSigs.executeAffirmation(recipient, valueOnForeign, transactionHash, {
|
||||
from: authoritiesThreeAccs[0]
|
||||
}).should.be.fulfilled
|
||||
const { logs } = await homeBridgeWithTwoSigs.executeAffirmation(recipient, valueOnForeign, transactionHash, {
|
||||
from: authoritiesThreeAccs[0]
|
||||
}).should.be.fulfilled
|
||||
|
||||
expectEventInLogs(logs, 'SignedForAffirmation', { signer: authorities[0], transactionHash })
|
||||
expectEventInLogs(logs, 'SignedForAffirmation', { signer: authorities[0], transactionHash })
|
||||
|
||||
const notProcessed = await homeBridgeWithTwoSigs.numAffirmationsSigned(msgHash)
|
||||
notProcessed.should.be.bignumber.equal('1')
|
||||
const notProcessed = await homeBridgeWithTwoSigs.numAffirmationsSigned(msgHash)
|
||||
notProcessed.should.be.bignumber.equal('1')
|
||||
|
||||
await homeBridgeWithTwoSigs
|
||||
.executeAffirmation(recipient, valueOnForeign, transactionHash, { from: authoritiesThreeAccs[0] })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await homeBridgeWithTwoSigs
|
||||
.executeAffirmation(recipient, valueOnForeign, transactionHash, { from: authoritiesThreeAccs[0] })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
const secondSignature = await homeBridgeWithTwoSigs.executeAffirmation(
|
||||
recipient,
|
||||
valueOnForeign,
|
||||
transactionHash,
|
||||
{ from: authoritiesThreeAccs[1] }
|
||||
).should.be.fulfilled
|
||||
const balanceAfter = toBN(await web3.eth.getBalance(recipient))
|
||||
balanceAfter.should.be.bignumber.equal(balanceBefore.add(valueOnHome))
|
||||
const secondSignature = await homeBridgeWithTwoSigs.executeAffirmation(
|
||||
recipient,
|
||||
valueOnForeign,
|
||||
transactionHash,
|
||||
{ from: authoritiesThreeAccs[1] }
|
||||
).should.be.fulfilled
|
||||
const balanceAfter = toBN(await web3.eth.getBalance(recipient))
|
||||
balanceAfter.should.be.bignumber.equal(balanceBefore.add(valueOnHome))
|
||||
|
||||
const totalExecutedPerDayAfter = await homeBridgeWithTwoSigs.totalExecutedPerDay(currentDay)
|
||||
totalExecutedPerDayAfter.should.be.bignumber.equal(totalExecutedPerDayBefore.add(valueOnForeign))
|
||||
const totalExecutedPerDayAfter = await homeBridgeWithTwoSigs.totalExecutedPerDay(currentDay)
|
||||
totalExecutedPerDayAfter.should.be.bignumber.equal(totalExecutedPerDayBefore.add(valueOnForeign))
|
||||
|
||||
expectEventInLogs(secondSignature.logs, 'AffirmationCompleted', {
|
||||
recipient,
|
||||
value: valueOnForeign,
|
||||
transactionHash
|
||||
expectEventInLogs(secondSignature.logs, 'AffirmationCompleted', {
|
||||
recipient,
|
||||
value: valueOnForeign,
|
||||
transactionHash
|
||||
})
|
||||
|
||||
const senderHash = web3.utils.soliditySha3(authoritiesThreeAccs[0], msgHash)
|
||||
true.should.be.equal(await homeBridgeWithTwoSigs.affirmationsSigned(senderHash))
|
||||
|
||||
const senderHash2 = web3.utils.soliditySha3(authoritiesThreeAccs[1], msgHash)
|
||||
true.should.be.equal(await homeBridgeWithTwoSigs.affirmationsSigned(senderHash2))
|
||||
|
||||
const markedAsProcessed = await homeBridgeWithTwoSigs.numAffirmationsSigned(msgHash)
|
||||
const processed = toBN(2)
|
||||
.pow(toBN(255))
|
||||
.add(toBN(2))
|
||||
markedAsProcessed.should.be.bignumber.equal(processed)
|
||||
})
|
||||
|
||||
const senderHash = web3.utils.soliditySha3(authoritiesThreeAccs[0], msgHash)
|
||||
true.should.be.equal(await homeBridgeWithTwoSigs.affirmationsSigned(senderHash))
|
||||
it(`Home to Foreign: test decimal shift ${decimalShift}, no impact on UserRequestForSignature value`, async () => {
|
||||
homeContract = await HomeBridge.new()
|
||||
await homeContract.initialize(
|
||||
validatorContract.address,
|
||||
['3', '2', '1'],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
blockRewardContract.address,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShift
|
||||
)
|
||||
|
||||
const senderHash2 = web3.utils.soliditySha3(authoritiesThreeAccs[1], msgHash)
|
||||
true.should.be.equal(await homeBridgeWithTwoSigs.affirmationsSigned(senderHash2))
|
||||
const currentDay = await homeContract.getCurrentDay()
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
|
||||
const markedAsProcessed = await homeBridgeWithTwoSigs.numAffirmationsSigned(msgHash)
|
||||
const processed = toBN(2)
|
||||
.pow(toBN(255))
|
||||
.add(toBN(2))
|
||||
markedAsProcessed.should.be.bignumber.equal(processed)
|
||||
})
|
||||
await blockRewardContract.addMintedTotallyByBridge(10, homeContract.address)
|
||||
const minted = await blockRewardContract.mintedTotallyByBridge(homeContract.address)
|
||||
minted.should.be.bignumber.equal('10')
|
||||
|
||||
it('Home to Foreign: test decimal shift 2, no impact on UserRequestForSignature value', async () => {
|
||||
homeContract = await HomeBridge.new()
|
||||
await homeContract.initialize(
|
||||
validatorContract.address,
|
||||
['3', '2', '1'],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
blockRewardContract.address,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo
|
||||
)
|
||||
const recipientAccount = accounts[1]
|
||||
|
||||
const currentDay = await homeContract.getCurrentDay()
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
const { logs } = await homeContract.sendTransaction({ from: recipientAccount, value: 1 }).should.be.fulfilled
|
||||
|
||||
await blockRewardContract.addMintedTotallyByBridge(10, homeContract.address)
|
||||
const minted = await blockRewardContract.mintedTotallyByBridge(homeContract.address)
|
||||
minted.should.be.bignumber.equal('10')
|
||||
expectEventInLogs(logs, 'UserRequestForSignature', { recipient: recipientAccount, value: toBN(1) })
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('1')
|
||||
expect(await homeContract.totalBurntCoins()).to.be.bignumber.equal('1')
|
||||
|
||||
const recipientAccount = accounts[1]
|
||||
const homeContractBalance = toBN(await web3.eth.getBalance(homeContract.address))
|
||||
homeContractBalance.should.be.bignumber.equal(ZERO)
|
||||
|
||||
const { logs } = await homeContract.sendTransaction({ from: recipientAccount, value: 1 }).should.be.fulfilled
|
||||
const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80'
|
||||
const message = createMessage(recipientAccount, 1, transactionHash, homeContract.address)
|
||||
|
||||
expectEventInLogs(logs, 'UserRequestForSignature', { recipient: recipientAccount, value: toBN(1) })
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('1')
|
||||
expect(await homeContract.totalBurntCoins()).to.be.bignumber.equal('1')
|
||||
const signature = await sign(authorities[0], message)
|
||||
|
||||
const homeContractBalance = toBN(await web3.eth.getBalance(homeContract.address))
|
||||
homeContractBalance.should.be.bignumber.equal(ZERO)
|
||||
expect(await validatorContract.requiredSignatures()).to.be.bignumber.equal('1')
|
||||
|
||||
const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80'
|
||||
const message = createMessage(recipientAccount, 1, transactionHash, homeContract.address)
|
||||
const { logs: logsSubmitSignature } = await homeContract.submitSignature(signature, message, {
|
||||
from: authorities[0]
|
||||
}).should.be.fulfilled
|
||||
|
||||
const signature = await sign(authorities[0], message)
|
||||
|
||||
expect(await validatorContract.requiredSignatures()).to.be.bignumber.equal('1')
|
||||
|
||||
const { logs: logsSubmitSignature } = await homeContract.submitSignature(signature, message, {
|
||||
from: authorities[0]
|
||||
}).should.be.fulfilled
|
||||
|
||||
logsSubmitSignature.length.should.be.equal(2)
|
||||
logsSubmitSignature[1].event.should.be.equal('CollectedSignatures')
|
||||
})
|
||||
logsSubmitSignature.length.should.be.equal(2)
|
||||
logsSubmitSignature[1].event.should.be.equal('CollectedSignatures')
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -141,6 +141,20 @@ contract('ForeignBridge', async accounts => {
|
|||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
// not valid decimal shift
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
'100',
|
||||
otherSideBridgeAddress
|
||||
).should.be.rejected
|
||||
|
||||
const { logs } = await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
|
@ -1458,83 +1472,85 @@ contract('ForeignBridge', async accounts => {
|
|||
})
|
||||
})
|
||||
describe('#decimalShift', async () => {
|
||||
const decimalShiftTwo = 2
|
||||
it('Home to Foreign: withdraw works with decimalShift of 2', async () => {
|
||||
const recipient = accounts[8]
|
||||
const authoritiesFiveAccs = [accounts[1], accounts[2], accounts[3], accounts[4], accounts[5]]
|
||||
const ownerOfValidators = accounts[0]
|
||||
const validatorContractWith3Signatures = await BridgeValidators.new()
|
||||
await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators)
|
||||
const erc20Token = await POA20.new('Some ERC20', 'RSZT', 16)
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const foreignBridgeWithThreeSigs = await ForeignBridge.new()
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`Home to Foreign: withdraw works with decimalShift of ${decimalShift}`, async () => {
|
||||
const recipient = accounts[8]
|
||||
const authoritiesFiveAccs = [accounts[1], accounts[2], accounts[3], accounts[4], accounts[5]]
|
||||
const ownerOfValidators = accounts[0]
|
||||
const validatorContractWith3Signatures = await BridgeValidators.new()
|
||||
await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators)
|
||||
const erc20Token = await POA20.new('Some ERC20', 'RSZT', 16)
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
const foreignBridgeWithThreeSigs = await ForeignBridge.new()
|
||||
|
||||
await foreignBridgeWithThreeSigs.initialize(
|
||||
validatorContractWith3Signatures.address,
|
||||
erc20Token.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await erc20Token.transferOwnership(foreignBridgeWithThreeSigs.address)
|
||||
await foreignBridgeWithThreeSigs.initialize(
|
||||
validatorContractWith3Signatures.address,
|
||||
erc20Token.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShift,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await erc20Token.transferOwnership(foreignBridgeWithThreeSigs.address)
|
||||
|
||||
const balanceBeforeRecipient = await erc20Token.balanceOf(recipient)
|
||||
const txHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipient, valueOnHome, txHash, foreignBridgeWithThreeSigs.address)
|
||||
const balanceBeforeRecipient = await erc20Token.balanceOf(recipient)
|
||||
const txHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipient, valueOnHome, txHash, foreignBridgeWithThreeSigs.address)
|
||||
|
||||
// signature 1
|
||||
const signature = await sign(authoritiesFiveAccs[0], message)
|
||||
const vrs = signatureToVRS(signature)
|
||||
// signature 1
|
||||
const signature = await sign(authoritiesFiveAccs[0], message)
|
||||
const vrs = signatureToVRS(signature)
|
||||
|
||||
// signature 2
|
||||
const signature2 = await sign(authoritiesFiveAccs[1], message)
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
// signature 2
|
||||
const signature2 = await sign(authoritiesFiveAccs[1], message)
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
|
||||
// signature 3
|
||||
const signature3 = await sign(authoritiesFiveAccs[2], message)
|
||||
const vrs3 = signatureToVRS(signature3)
|
||||
// signature 3
|
||||
const signature3 = await sign(authoritiesFiveAccs[2], message)
|
||||
const vrs3 = signatureToVRS(signature3)
|
||||
|
||||
const threeSignatures = packSignatures([vrs, vrs2, vrs3])
|
||||
const threeSignatures = packSignatures([vrs, vrs2, vrs3])
|
||||
|
||||
const { logs } = await foreignBridgeWithThreeSigs.executeSignatures(message, threeSignatures).should.be.fulfilled
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipient)
|
||||
logs[0].args.value.should.be.bignumber.equal(valueOnHome)
|
||||
true.should.be.equal(await foreignBridgeWithThreeSigs.relayedMessages(txHash))
|
||||
const balanceAfterRecipient = await erc20Token.balanceOf(recipient)
|
||||
balanceAfterRecipient.should.be.bignumber.equal(balanceBeforeRecipient.add(valueOnForeign))
|
||||
const balanceAfterBridge = await erc20Token.balanceOf(foreignBridgeWithThreeSigs.address)
|
||||
balanceAfterBridge.should.be.bignumber.equal(ZERO)
|
||||
})
|
||||
it('Foreign to Home: no impact in transferAndCall event signal for bridges oracles with a decimalShift of 2.', async () => {
|
||||
const owner = accounts[3]
|
||||
const user = accounts[4]
|
||||
const value = halfEther
|
||||
token = await POA20.new('POA ERC20 Foundation', 'POA20', 16, { from: owner })
|
||||
const foreignBridge = await ForeignBridge.new()
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.mint(user, value, { from: owner }).should.be.fulfilled
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(value)
|
||||
await token.transferOwnership(foreignBridge.address, { from: owner })
|
||||
const { logs } = await token.transferAndCall(foreignBridge.address, value, '0x', { from: user })
|
||||
logs[0].event.should.be.equal('Transfer')
|
||||
logs[0].args.value.should.be.bignumber.equal(value)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
})
|
||||
const { logs } = await foreignBridgeWithThreeSigs.executeSignatures(message, threeSignatures).should.be
|
||||
.fulfilled
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipient)
|
||||
logs[0].args.value.should.be.bignumber.equal(valueOnHome)
|
||||
true.should.be.equal(await foreignBridgeWithThreeSigs.relayedMessages(txHash))
|
||||
const balanceAfterRecipient = await erc20Token.balanceOf(recipient)
|
||||
balanceAfterRecipient.should.be.bignumber.equal(balanceBeforeRecipient.add(valueOnForeign))
|
||||
const balanceAfterBridge = await erc20Token.balanceOf(foreignBridgeWithThreeSigs.address)
|
||||
balanceAfterBridge.should.be.bignumber.equal(ZERO)
|
||||
})
|
||||
it(`Foreign to Home: no impact in transferAndCall event signal for bridges oracles with a decimalShift of ${decimalShift}`, async () => {
|
||||
const owner = accounts[3]
|
||||
const user = accounts[4]
|
||||
const value = halfEther
|
||||
token = await POA20.new('POA ERC20 Foundation', 'POA20', 16, { from: owner })
|
||||
const foreignBridge = await ForeignBridge.new()
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShift,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.mint(user, value, { from: owner }).should.be.fulfilled
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(value)
|
||||
await token.transferOwnership(foreignBridge.address, { from: owner })
|
||||
const { logs } = await token.transferAndCall(foreignBridge.address, value, '0x', { from: user })
|
||||
logs[0].event.should.be.equal('Transfer')
|
||||
logs[0].args.value.should.be.bignumber.equal(value)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -220,6 +220,18 @@ contract('HomeBridge', async accounts => {
|
|||
decimalShiftZero
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
// not valid decimal shift
|
||||
await homeContract.initialize(
|
||||
validatorContract.address,
|
||||
['3', '2', '1'],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
'100'
|
||||
).should.be.rejected
|
||||
|
||||
await homeContract.initialize(
|
||||
validatorContract.address,
|
||||
['3', '2', '1'],
|
||||
|
@ -2495,99 +2507,100 @@ contract('HomeBridge', async accounts => {
|
|||
})
|
||||
})
|
||||
describe('#decimalShift', async () => {
|
||||
const decimalShiftTwo = 2
|
||||
it('Foreign to Home: works with 5 validators and 3 required signatures with decimal shift 2', async () => {
|
||||
const recipient = accounts[8]
|
||||
const authoritiesFiveAccs = [accounts[1], accounts[2], accounts[3], accounts[4], accounts[5]]
|
||||
const ownerOfValidators = accounts[0]
|
||||
const validatorContractWith3Signatures = await BridgeValidators.new()
|
||||
await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators)
|
||||
for (const decimalShift of [2, -1]) {
|
||||
it(`Foreign to Home: works with 5 validators and 3 required signatures with decimal shift ${decimalShift}`, async () => {
|
||||
const recipient = accounts[8]
|
||||
const authoritiesFiveAccs = [accounts[1], accounts[2], accounts[3], accounts[4], accounts[5]]
|
||||
const ownerOfValidators = accounts[0]
|
||||
const validatorContractWith3Signatures = await BridgeValidators.new()
|
||||
await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators)
|
||||
|
||||
const homeBridgeWithThreeSigs = await HomeBridge.new()
|
||||
await homeBridgeWithThreeSigs.initialize(
|
||||
validatorContractWith3Signatures.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo
|
||||
)
|
||||
const homeBridgeWithThreeSigs = await HomeBridge.new()
|
||||
await homeBridgeWithThreeSigs.initialize(
|
||||
validatorContractWith3Signatures.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShift
|
||||
)
|
||||
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShiftTwo)
|
||||
const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415'
|
||||
const valueOnForeign = toBN('1000')
|
||||
const valueOnHome = toBN(valueOnForeign * 10 ** decimalShift)
|
||||
const transactionHash = '0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415'
|
||||
|
||||
await homeBridgeWithThreeSigs.sendTransaction({
|
||||
from: recipient,
|
||||
value: halfEther
|
||||
}).should.be.fulfilled
|
||||
await homeBridgeWithThreeSigs.sendTransaction({
|
||||
from: recipient,
|
||||
value: halfEther
|
||||
}).should.be.fulfilled
|
||||
|
||||
const balanceBeforeRecipient = toBN(await web3.eth.getBalance(recipient))
|
||||
const balanceBeforeRecipient = toBN(await web3.eth.getBalance(recipient))
|
||||
|
||||
const { logs } = await homeBridgeWithThreeSigs.executeAffirmation(recipient, valueOnForeign, transactionHash, {
|
||||
from: authoritiesFiveAccs[0]
|
||||
}).should.be.fulfilled
|
||||
expectEventInLogs(logs, 'SignedForAffirmation', {
|
||||
signer: authorities[0],
|
||||
transactionHash
|
||||
})
|
||||
|
||||
await homeBridgeWithThreeSigs.executeAffirmation(recipient, valueOnForeign, transactionHash, {
|
||||
from: authoritiesFiveAccs[1]
|
||||
}).should.be.fulfilled
|
||||
const thirdSignature = await homeBridgeWithThreeSigs.executeAffirmation(
|
||||
recipient,
|
||||
valueOnForeign,
|
||||
transactionHash,
|
||||
{ from: authoritiesFiveAccs[2] }
|
||||
).should.be.fulfilled
|
||||
|
||||
expectEventInLogs(thirdSignature.logs, 'AffirmationCompleted', {
|
||||
recipient,
|
||||
value: valueOnForeign,
|
||||
transactionHash
|
||||
})
|
||||
|
||||
const balanceAfterRecipient = toBN(await web3.eth.getBalance(recipient))
|
||||
balanceAfterRecipient.should.be.bignumber.equal(balanceBeforeRecipient.add(valueOnHome))
|
||||
})
|
||||
it('Foreign to Home: test decimal shift 2, no impact on UserRequestForSignature value', async () => {
|
||||
homeContract = await HomeBridge.new()
|
||||
await homeContract.initialize(
|
||||
validatorContract.address,
|
||||
['3', '2', '1'],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo
|
||||
)
|
||||
const currentDay = await homeContract.getCurrentDay()
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
|
||||
const { logs } = await homeContract.sendTransaction({
|
||||
from: accounts[1],
|
||||
value: 1
|
||||
}).should.be.fulfilled
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('1')
|
||||
|
||||
expectEventInLogs(logs, 'UserRequestForSignature', { recipient: accounts[1], value: toBN(1) })
|
||||
|
||||
await homeContract
|
||||
.sendTransaction({
|
||||
from: accounts[1],
|
||||
value: 3
|
||||
const { logs } = await homeBridgeWithThreeSigs.executeAffirmation(recipient, valueOnForeign, transactionHash, {
|
||||
from: authoritiesFiveAccs[0]
|
||||
}).should.be.fulfilled
|
||||
expectEventInLogs(logs, 'SignedForAffirmation', {
|
||||
signer: authorities[0],
|
||||
transactionHash
|
||||
})
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
await homeContract.setDailyLimit(4).should.be.fulfilled
|
||||
await homeContract.sendTransaction({
|
||||
from: accounts[1],
|
||||
value: 1
|
||||
}).should.be.fulfilled
|
||||
await homeBridgeWithThreeSigs.executeAffirmation(recipient, valueOnForeign, transactionHash, {
|
||||
from: authoritiesFiveAccs[1]
|
||||
}).should.be.fulfilled
|
||||
const thirdSignature = await homeBridgeWithThreeSigs.executeAffirmation(
|
||||
recipient,
|
||||
valueOnForeign,
|
||||
transactionHash,
|
||||
{ from: authoritiesFiveAccs[2] }
|
||||
).should.be.fulfilled
|
||||
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('2')
|
||||
})
|
||||
expectEventInLogs(thirdSignature.logs, 'AffirmationCompleted', {
|
||||
recipient,
|
||||
value: valueOnForeign,
|
||||
transactionHash
|
||||
})
|
||||
|
||||
const balanceAfterRecipient = toBN(await web3.eth.getBalance(recipient))
|
||||
balanceAfterRecipient.should.be.bignumber.equal(balanceBeforeRecipient.add(valueOnHome))
|
||||
})
|
||||
it(`Foreign to Home: test decimal shift ${decimalShift}, no impact on UserRequestForSignature value`, async () => {
|
||||
homeContract = await HomeBridge.new()
|
||||
await homeContract.initialize(
|
||||
validatorContract.address,
|
||||
['3', '2', '1'],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShift
|
||||
)
|
||||
const currentDay = await homeContract.getCurrentDay()
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
|
||||
const { logs } = await homeContract.sendTransaction({
|
||||
from: accounts[1],
|
||||
value: 1
|
||||
}).should.be.fulfilled
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('1')
|
||||
|
||||
expectEventInLogs(logs, 'UserRequestForSignature', { recipient: accounts[1], value: toBN(1) })
|
||||
|
||||
await homeContract
|
||||
.sendTransaction({
|
||||
from: accounts[1],
|
||||
value: 3
|
||||
})
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
await homeContract.setDailyLimit(4).should.be.fulfilled
|
||||
await homeContract.sendTransaction({
|
||||
from: accounts[1],
|
||||
value: 1
|
||||
}).should.be.fulfilled
|
||||
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('2')
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue