Add alternative receiver for transfer in native to erc20 mode (#302)
This commit is contained in:
parent
7d033bde33
commit
c0ee60806d
|
@ -5,6 +5,7 @@ import "./BasicTokenBridge.sol";
|
|||
import "../interfaces/ERC677.sol";
|
||||
import "../interfaces/ERC677Receiver.sol";
|
||||
import "./ERC677Storage.sol";
|
||||
import "../libraries/Bytes.sol";
|
||||
|
||||
contract BaseERC677Bridge is BasicTokenBridge, ERC677Receiver, ERC677Storage {
|
||||
function erc677token() public view returns (ERC677) {
|
||||
|
@ -25,6 +26,19 @@ contract BaseERC677Bridge is BasicTokenBridge, ERC677Receiver, ERC677Storage {
|
|||
return true;
|
||||
}
|
||||
|
||||
function chooseReceiver(address _from, bytes _data) internal view returns (address recipient) {
|
||||
recipient = _from;
|
||||
if (_data.length > 0) {
|
||||
require(_data.length == 20);
|
||||
recipient = Bytes.bytesToAddress(_data);
|
||||
require(recipient != address(0));
|
||||
require(recipient != bridgeContractOnOtherSide());
|
||||
}
|
||||
}
|
||||
|
||||
/* solcov ignore next */
|
||||
function bridgeSpecificActionsOnTokenTransfer(ERC677 _token, address _from, uint256 _value, bytes _data) internal;
|
||||
|
||||
/* solcov ignore next */
|
||||
function bridgeContractOnOtherSide() internal view returns (address);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
pragma solidity 0.4.24;
|
||||
|
||||
import "./BaseERC677Bridge.sol";
|
||||
import "./OtherSideBridgeStorage.sol";
|
||||
|
||||
contract ERC677Bridge is BaseERC677Bridge {
|
||||
contract ERC677Bridge is BaseERC677Bridge, OtherSideBridgeStorage {
|
||||
function bridgeSpecificActionsOnTokenTransfer(
|
||||
ERC677, /*_token*/
|
||||
address _from,
|
||||
|
|
|
@ -4,13 +4,8 @@ import "./ERC677Bridge.sol";
|
|||
import "../interfaces/IBurnableMintableERC677Token.sol";
|
||||
|
||||
contract ERC677BridgeForBurnableMintableToken is ERC677Bridge {
|
||||
function bridgeSpecificActionsOnTokenTransfer(
|
||||
ERC677 _token,
|
||||
address _from,
|
||||
uint256 _value,
|
||||
bytes /*_data*/
|
||||
) internal {
|
||||
function bridgeSpecificActionsOnTokenTransfer(ERC677 _token, address _from, uint256 _value, bytes _data) internal {
|
||||
IBurnableMintableERC677Token(_token).burn(_value);
|
||||
fireEventOnTokenTransfer(_from, _value);
|
||||
fireEventOnTokenTransfer(chooseReceiver(_from, _data), _value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ pragma solidity 0.4.24;
|
|||
import "./Initializable.sol";
|
||||
|
||||
contract InitializableBridge is Initializable {
|
||||
bytes32 internal constant DEPLOYED_AT_BLOCK = 0xb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b0; // keccak256(abi.encodePacked("deployedAtBlock"));
|
||||
bytes32 internal constant DEPLOYED_AT_BLOCK = 0xb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b0; // keccak256(abi.encodePacked("deployedAtBlock"))
|
||||
|
||||
function deployedAtBlock() external view returns (uint256) {
|
||||
return uintStorage[DEPLOYED_AT_BLOCK];
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
pragma solidity 0.4.24;
|
||||
|
||||
import "../upgradeability/EternalStorage.sol";
|
||||
|
||||
contract OtherSideBridgeStorage is EternalStorage {
|
||||
bytes32 internal constant BRIDGE_CONTRACT = 0x71483949fe7a14d16644d63320f24d10cf1d60abecc30cc677a340e82b699dd2; // keccak256(abi.encodePacked("bridgeOnOtherSide"))
|
||||
|
||||
function _setBridgeContractOnOtherSide(address _bridgeContract) internal {
|
||||
addressStorage[BRIDGE_CONTRACT] = _bridgeContract;
|
||||
}
|
||||
|
||||
function bridgeContractOnOtherSide() internal view returns (address) {
|
||||
return addressStorage[BRIDGE_CONTRACT];
|
||||
}
|
||||
}
|
|
@ -67,14 +67,8 @@ contract BasicAMBErc677ToErc677 is
|
|||
return isInitialized();
|
||||
}
|
||||
|
||||
function chooseReceiver(address _from, bytes _data) internal view returns (address recipient) {
|
||||
recipient = _from;
|
||||
if (_data.length > 0) {
|
||||
require(_data.length == 20);
|
||||
recipient = Bytes.bytesToAddress(_data);
|
||||
require(recipient != address(0));
|
||||
require(recipient != mediatorContractOnOtherSide());
|
||||
}
|
||||
function bridgeContractOnOtherSide() internal view returns (address) {
|
||||
return mediatorContractOnOtherSide();
|
||||
}
|
||||
|
||||
function passMessage(address _from, uint256 _value) internal {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
pragma solidity 0.4.24;
|
||||
|
||||
import "./BasicAMBErc677ToErc677.sol";
|
||||
import "../ERC677Bridge.sol";
|
||||
import "openzeppelin-solidity/contracts/AddressUtils.sol";
|
||||
|
||||
contract ForeignAMBErc677ToErc677 is BasicAMBErc677ToErc677 {
|
||||
function executeActionOnBridgedTokens(address _recipient, uint256 _value) internal {
|
||||
|
|
|
@ -2,7 +2,6 @@ pragma solidity 0.4.24;
|
|||
|
||||
import "./BasicAMBErc677ToErc677.sol";
|
||||
import "../../interfaces/IBurnableMintableERC677Token.sol";
|
||||
import "openzeppelin-solidity/contracts/AddressUtils.sol";
|
||||
|
||||
contract HomeAMBErc677ToErc677 is BasicAMBErc677ToErc677 {
|
||||
function executeActionOnBridgedTokens(address _recipient, uint256 _value) internal {
|
||||
|
|
|
@ -2,13 +2,12 @@ pragma solidity 0.4.24;
|
|||
|
||||
import "../BasicForeignBridge.sol";
|
||||
import "../ERC20Bridge.sol";
|
||||
import "../OtherSideBridgeStorage.sol";
|
||||
|
||||
contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge {
|
||||
contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideBridgeStorage {
|
||||
event RelayedMessage(address recipient, uint256 value, bytes32 transactionHash);
|
||||
event UserRequestForAffirmation(address recipient, uint256 value);
|
||||
|
||||
bytes32 internal constant BRIDGE_CONTRACT = 0x71483949fe7a14d16644d63320f24d10cf1d60abecc30cc677a340e82b699dd2; // keccak256(abi.encodePacked("bridgeOnOtherSide"))
|
||||
|
||||
function initialize(
|
||||
address _validatorContract,
|
||||
address _erc20token,
|
||||
|
@ -79,14 +78,6 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge {
|
|||
revert();
|
||||
}
|
||||
|
||||
function _setBridgeContractOnOtherSide(address _bridgeContract) internal {
|
||||
addressStorage[BRIDGE_CONTRACT] = _bridgeContract;
|
||||
}
|
||||
|
||||
function bridgeContractOnOtherSide() public view returns (address) {
|
||||
return addressStorage[BRIDGE_CONTRACT];
|
||||
}
|
||||
|
||||
function _relayTokens(address _sender, address _receiver, uint256 _amount) internal {
|
||||
require(_receiver != address(0));
|
||||
require(_receiver != address(this));
|
||||
|
|
|
@ -4,7 +4,6 @@ import "../../libraries/Message.sol";
|
|||
import "../../upgradeability/EternalStorage.sol";
|
||||
import "../../interfaces/IBlockReward.sol";
|
||||
import "../BasicHomeBridge.sol";
|
||||
import "../ERC677Bridge.sol";
|
||||
import "../OverdrawManagement.sol";
|
||||
import "./RewardableHomeBridgeErcToNative.sol";
|
||||
import "../BlockRewardBridge.sol";
|
||||
|
|
|
@ -22,7 +22,8 @@ contract ForeignBridgeNativeToErc is
|
|||
uint256 _requiredBlockConfirmations,
|
||||
uint256[] _homeDailyLimitHomeMaxPerTxArray, // [ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
uint256 _decimalShift,
|
||||
address _bridgeOnOtherSide
|
||||
) external returns (bool) {
|
||||
_initialize(
|
||||
_validatorContract,
|
||||
|
@ -32,7 +33,8 @@ contract ForeignBridgeNativeToErc is
|
|||
_requiredBlockConfirmations,
|
||||
_homeDailyLimitHomeMaxPerTxArray,
|
||||
_owner,
|
||||
_decimalShift
|
||||
_decimalShift,
|
||||
_bridgeOnOtherSide
|
||||
);
|
||||
setInitialize();
|
||||
return isInitialized();
|
||||
|
@ -48,7 +50,8 @@ contract ForeignBridgeNativeToErc is
|
|||
address _owner,
|
||||
address _feeManager,
|
||||
uint256 _homeFee,
|
||||
uint256 _decimalShift
|
||||
uint256 _decimalShift,
|
||||
address _bridgeOnOtherSide
|
||||
) external returns (bool) {
|
||||
_initialize(
|
||||
_validatorContract,
|
||||
|
@ -58,7 +61,8 @@ contract ForeignBridgeNativeToErc is
|
|||
_requiredBlockConfirmations,
|
||||
_homeDailyLimitHomeMaxPerTxArray,
|
||||
_owner,
|
||||
_decimalShift
|
||||
_decimalShift,
|
||||
_bridgeOnOtherSide
|
||||
);
|
||||
require(AddressUtils.isContract(_feeManager));
|
||||
addressStorage[FEE_MANAGER_CONTRACT] = _feeManager;
|
||||
|
@ -83,7 +87,8 @@ contract ForeignBridgeNativeToErc is
|
|||
uint256 _requiredBlockConfirmations,
|
||||
uint256[] _homeDailyLimitHomeMaxPerTxArray, // [ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ]
|
||||
address _owner,
|
||||
uint256 _decimalShift
|
||||
uint256 _decimalShift,
|
||||
address _bridgeOnOtherSide
|
||||
) internal {
|
||||
require(!isInitialized());
|
||||
require(AddressUtils.isContract(_validatorContract));
|
||||
|
@ -109,6 +114,7 @@ contract ForeignBridgeNativeToErc is
|
|||
uintStorage[EXECUTION_MAX_PER_TX] = _homeDailyLimitHomeMaxPerTxArray[1];
|
||||
uintStorage[DECIMAL_SHIFT] = _decimalShift;
|
||||
setOwner(_owner);
|
||||
_setBridgeContractOnOtherSide(_bridgeOnOtherSide);
|
||||
|
||||
emit RequiredBlockConfirmationChanged(_requiredBlockConfirmations);
|
||||
emit GasPriceChanged(_foreignGasPrice);
|
||||
|
|
|
@ -8,12 +8,12 @@ import "../Sacrifice.sol";
|
|||
|
||||
contract HomeBridgeNativeToErc is EternalStorage, BasicHomeBridge, RewardableHomeBridgeNativeToErc {
|
||||
function() public payable {
|
||||
nativeTransfer();
|
||||
require(msg.data.length == 0);
|
||||
nativeTransfer(msg.sender);
|
||||
}
|
||||
|
||||
function nativeTransfer() internal {
|
||||
function nativeTransfer(address _receiver) internal {
|
||||
require(msg.value > 0);
|
||||
require(msg.data.length == 0);
|
||||
require(withinLimit(msg.value));
|
||||
setTotalSpentPerDay(getCurrentDay(), totalSpentPerDay(getCurrentDay()).add(msg.value));
|
||||
uint256 valueToTransfer = msg.value;
|
||||
|
@ -22,7 +22,11 @@ contract HomeBridgeNativeToErc is EternalStorage, BasicHomeBridge, RewardableHom
|
|||
uint256 fee = calculateFee(valueToTransfer, false, feeManager, HOME_FEE);
|
||||
valueToTransfer = valueToTransfer.sub(fee);
|
||||
}
|
||||
emit UserRequestForSignature(msg.sender, valueToTransfer);
|
||||
emit UserRequestForSignature(_receiver, valueToTransfer);
|
||||
}
|
||||
|
||||
function relayTokens(address _receiver) external payable {
|
||||
nativeTransfer(_receiver);
|
||||
}
|
||||
|
||||
function initialize(
|
||||
|
|
|
@ -12,7 +12,7 @@ async function deployNativeToErc() {
|
|||
const deployForeign = require('./src/native_to_erc/foreign')
|
||||
await preDeploy()
|
||||
const { homeBridge } = await deployHome()
|
||||
const { foreignBridge, erc677 } = await deployForeign()
|
||||
const { foreignBridge, erc677 } = await deployForeign(homeBridge.address)
|
||||
console.log('\nDeployment has been completed.\n\n')
|
||||
console.log(`[ Home ] HomeBridge: ${homeBridge.address} at block ${homeBridge.deployedBlockNumber}`)
|
||||
console.log(`[ Foreign ] ForeignBridge: ${foreignBridge.address} at block ${foreignBridge.deployedBlockNumber}`)
|
||||
|
|
|
@ -64,7 +64,7 @@ if (isRewardableBridge) {
|
|||
VALIDATORS_REWARD_ACCOUNTS = env.VALIDATORS_REWARD_ACCOUNTS.split(' ')
|
||||
}
|
||||
|
||||
async function initializeBridge({ validatorsBridge, bridge, erc677bridgeToken, initialNonce }) {
|
||||
async function initializeBridge({ validatorsBridge, bridge, erc677bridgeToken, initialNonce, homeBridgeAddress }) {
|
||||
let nonce = initialNonce
|
||||
let initializeFBridgeData
|
||||
|
||||
|
@ -95,7 +95,8 @@ async function initializeBridge({ validatorsBridge, bridge, erc677bridgeToken, i
|
|||
FOREIGN_BRIDGE_OWNER: ${FOREIGN_BRIDGE_OWNER},
|
||||
Fee Manager: ${feeManager.options.address},
|
||||
Home Fee: ${homeFeeInWei} which is ${HOME_TRANSACTIONS_FEE * 100}%,
|
||||
FOREIGN_TO_HOME_DECIMAL_SHIFT: ${foreignToHomeDecimalShift}`)
|
||||
FOREIGN_TO_HOME_DECIMAL_SHIFT: ${foreignToHomeDecimalShift}
|
||||
Home bridge Address: ${homeBridgeAddress}`)
|
||||
|
||||
initializeFBridgeData = await bridge.methods
|
||||
.rewardableInitialize(
|
||||
|
@ -108,7 +109,8 @@ async function initializeBridge({ validatorsBridge, bridge, erc677bridgeToken, i
|
|||
FOREIGN_BRIDGE_OWNER,
|
||||
feeManager.options.address,
|
||||
homeFeeInWei,
|
||||
foreignToHomeDecimalShift
|
||||
foreignToHomeDecimalShift,
|
||||
homeBridgeAddress
|
||||
)
|
||||
.encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS })
|
||||
} else {
|
||||
|
@ -126,6 +128,7 @@ async function initializeBridge({ validatorsBridge, bridge, erc677bridgeToken, i
|
|||
HOME_MAX_AMOUNT_PER_TX: ${HOME_MAX_AMOUNT_PER_TX} which is ${Web3Utils.fromWei(HOME_MAX_AMOUNT_PER_TX)} in eth,
|
||||
FOREIGN_BRIDGE_OWNER: ${FOREIGN_BRIDGE_OWNER},
|
||||
FOREIGN_TO_HOME_DECIMAL_SHIFT: ${foreignToHomeDecimalShift}
|
||||
Home bridge Address: ${homeBridgeAddress}
|
||||
`)
|
||||
|
||||
initializeFBridgeData = await bridge.methods
|
||||
|
@ -137,7 +140,8 @@ async function initializeBridge({ validatorsBridge, bridge, erc677bridgeToken, i
|
|||
FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS,
|
||||
[HOME_DAILY_LIMIT, HOME_MAX_AMOUNT_PER_TX],
|
||||
FOREIGN_BRIDGE_OWNER,
|
||||
foreignToHomeDecimalShift
|
||||
foreignToHomeDecimalShift,
|
||||
homeBridgeAddress
|
||||
)
|
||||
.encodeABI({ from: DEPLOYMENT_ACCOUNT_ADDRESS })
|
||||
}
|
||||
|
@ -159,7 +163,7 @@ async function initializeBridge({ validatorsBridge, bridge, erc677bridgeToken, i
|
|||
return nonce
|
||||
}
|
||||
|
||||
async function deployForeign() {
|
||||
async function deployForeign(homeBridgeAddress) {
|
||||
let nonce = await web3Foreign.eth.getTransactionCount(DEPLOYMENT_ACCOUNT_ADDRESS)
|
||||
console.log('========================================')
|
||||
console.log('deploying ForeignBridge')
|
||||
|
@ -259,7 +263,8 @@ async function deployForeign() {
|
|||
validatorsBridge: storageValidatorsForeign,
|
||||
bridge: foreignBridgeImplementation,
|
||||
erc677bridgeToken,
|
||||
initialNonce: nonce
|
||||
initialNonce: nonce,
|
||||
homeBridgeAddress
|
||||
})
|
||||
|
||||
console.log('\nset bridge contract on ERC677BridgeToken')
|
||||
|
|
|
@ -1439,7 +1439,7 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => {
|
|||
await token.mint(user, value, { from: owner }).should.be.fulfilled
|
||||
|
||||
// When
|
||||
await token.transferAndCall(homeBridge.address, value, '0x00', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(homeBridge.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
// Then
|
||||
const events = await getEvents(homeBridge, { event: 'UserRequestForSignature' })
|
||||
|
@ -1481,7 +1481,7 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => {
|
|||
await token.mint(user, value, { from: owner }).should.be.fulfilled
|
||||
|
||||
// When
|
||||
await token.transferAndCall(homeBridge.address, value, '0x00', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(homeBridge.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
// Then
|
||||
const events = await getEvents(homeBridge, { event: 'UserRequestForSignature' })
|
||||
|
@ -1969,7 +1969,7 @@ contract('HomeBridge_ERC20_to_ERC20', async accounts => {
|
|||
await token.mint(user, value, { from: owner }).should.be.fulfilled
|
||||
|
||||
// When
|
||||
await token.transferAndCall(homeBridge.address, value, '0x00', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(homeBridge.address, value, '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
// Then
|
||||
const events = await getEvents(homeBridge, { event: 'UserRequestForSignature' })
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const ForeignBridge = artifacts.require('ForeignBridgeNativeToErc.sol')
|
||||
const ForeignBridgeV2 = artifacts.require('ForeignBridgeV2.sol')
|
||||
const HomeBridge = artifacts.require('HomeBridgeNativeToErc.sol')
|
||||
const BridgeValidators = artifacts.require('BridgeValidators.sol')
|
||||
const EternalStorageProxy = artifacts.require('EternalStorageProxy.sol')
|
||||
const FeeManagerNativeToErc = artifacts.require('FeeManagerNativeToErc.sol')
|
||||
|
@ -26,11 +27,14 @@ contract('ForeignBridge', async accounts => {
|
|||
let authorities
|
||||
let owner
|
||||
let token
|
||||
let otherSideBridgeAddress
|
||||
before(async () => {
|
||||
validatorContract = await BridgeValidators.new()
|
||||
authorities = [accounts[1], accounts[2]]
|
||||
owner = accounts[0]
|
||||
await validatorContract.initialize(1, authorities, owner)
|
||||
const otherSideBridge = await HomeBridge.new()
|
||||
otherSideBridgeAddress = otherSideBridge.address
|
||||
})
|
||||
|
||||
describe('#initialize', async () => {
|
||||
|
@ -55,7 +59,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
|
@ -67,7 +72,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
|
@ -79,7 +85,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
|
@ -91,7 +98,8 @@ contract('ForeignBridge', async accounts => {
|
|||
gasPrice,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
|
@ -103,7 +111,8 @@ contract('ForeignBridge', async accounts => {
|
|||
gasPrice,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
|
@ -115,7 +124,8 @@ contract('ForeignBridge', async accounts => {
|
|||
0,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
const { logs } = await foreignBridge.initialize(
|
||||
|
@ -126,7 +136,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
'9'
|
||||
'9',
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
|
||||
expect(await foreignBridge.isInitialized()).to.be.equal(true)
|
||||
|
@ -169,7 +180,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.transferOwnership(foreignBridge.address)
|
||||
})
|
||||
|
@ -315,6 +327,7 @@ contract('ForeignBridge', async accounts => {
|
|||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress,
|
||||
{ from: ownerOfValidatorContract }
|
||||
)
|
||||
await token.transferOwnership(foreignBridgeWithMultiSignatures.address)
|
||||
|
@ -378,7 +391,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await erc20Token.transferOwnership(foreignBridgeWithThreeSigs.address)
|
||||
|
||||
|
@ -426,7 +440,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await erc20Token.transferOwnership(foreignBridgeWithThreeSigs.address)
|
||||
|
||||
|
@ -474,12 +489,13 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.mint(user, halfEther, { from: owner }).should.be.fulfilled
|
||||
await token.transferOwnership(foreignBridge.address, { from: owner })
|
||||
await foreignBridge.onTokenTransfer(user, halfEther, '0x00', { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, '0x00', { from: user }).should.be.fulfilled
|
||||
await foreignBridge.onTokenTransfer(user, halfEther, '0x', { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, '0x', { from: user }).should.be.fulfilled
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
})
|
||||
|
@ -498,19 +514,20 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.mint(user, valueMoreThanLimit, { from: owner }).should.be.fulfilled
|
||||
await token.transferOwnership(foreignBridge.address, { from: owner })
|
||||
|
||||
await token
|
||||
.transferAndCall(foreignBridge.address, valueMoreThanLimit, '0x00', { from: user })
|
||||
.transferAndCall(foreignBridge.address, valueMoreThanLimit, '0x', { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
valueMoreThanLimit.should.be.bignumber.equal(await token.totalSupply())
|
||||
valueMoreThanLimit.should.be.bignumber.equal(await token.balanceOf(user))
|
||||
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, '0x00', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal('1')
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('1')
|
||||
|
@ -533,31 +550,31 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.mint(user, oneEther.add(toBN(1)), { from: owner }).should.be.fulfilled
|
||||
|
||||
await token.transferOwnership(foreignBridge.address, { from: owner })
|
||||
|
||||
await token
|
||||
.transferAndCall(foreignBridge.address, valueMoreThanLimit, '0x00', { from: user })
|
||||
.transferAndCall(foreignBridge.address, valueMoreThanLimit, '0x', { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
oneEther.add(toBN(1)).should.be.bignumber.equal(await token.totalSupply())
|
||||
oneEther.add(toBN(1)).should.be.bignumber.equal(await token.balanceOf(user))
|
||||
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, '0x00', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
valueMoreThanLimit.should.be.bignumber.equal(await token.totalSupply())
|
||||
valueMoreThanLimit.should.be.bignumber.equal(await token.balanceOf(user))
|
||||
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, '0x00', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal('1')
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('1')
|
||||
await token.transferAndCall(foreignBridge.address, '1', '0x00', { from: user }).should.be.rejectedWith(ERROR_MSG)
|
||||
await token.transferAndCall(foreignBridge.address, '1', '0x', { from: user }).should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
|
||||
it('should not let to withdraw less than minPerTx', async () => {
|
||||
const owner = accounts[3]
|
||||
const user = accounts[4]
|
||||
|
@ -572,23 +589,56 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.mint(user, oneEther, { from: owner }).should.be.fulfilled
|
||||
await token.transferOwnership(foreignBridge.address, { from: owner })
|
||||
|
||||
await token
|
||||
.transferAndCall(foreignBridge.address, valueLessThanMinPerTx, '0x00', { from: user })
|
||||
.transferAndCall(foreignBridge.address, valueLessThanMinPerTx, '0x', { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
oneEther.should.be.bignumber.equal(await token.totalSupply())
|
||||
oneEther.should.be.bignumber.equal(await token.balanceOf(user))
|
||||
|
||||
await token.transferAndCall(foreignBridge.address, minPerTx, '0x00', { from: user }).should.be.fulfilled
|
||||
await token.transferAndCall(foreignBridge.address, minPerTx, '0x', { from: user }).should.be.fulfilled
|
||||
|
||||
oneEther.sub(minPerTx).should.be.bignumber.equal(await token.totalSupply())
|
||||
oneEther.sub(minPerTx).should.be.bignumber.equal(await token.balanceOf(user))
|
||||
})
|
||||
it('should be able to specify a different receiver', async () => {
|
||||
const owner = accounts[3]
|
||||
const user = accounts[4]
|
||||
const user2 = accounts[5]
|
||||
token = await POA20.new('POA ERC20 Foundation', 'POA20', 18, { from: owner })
|
||||
const foreignBridge = await ForeignBridge.new()
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.mint(user, halfEther, { from: owner }).should.be.fulfilled
|
||||
await token.transferOwnership(foreignBridge.address, { from: owner })
|
||||
await token
|
||||
.transferAndCall(foreignBridge.address, halfEther, otherSideBridgeAddress, { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await token
|
||||
.transferAndCall(foreignBridge.address, halfEther, '0x00', { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, user2, { from: user }).should.be.fulfilled
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
const events = await getEvents(foreignBridge, { event: 'UserRequestForAffirmation' })
|
||||
expect(events[0].returnValues.recipient).to.be.equal(user2)
|
||||
expect(toBN(events[0].returnValues.value)).to.be.bignumber.equal(halfEther)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#setting limits', async () => {
|
||||
|
@ -604,7 +654,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.transferOwnership(foreignBridge.address)
|
||||
})
|
||||
|
@ -657,7 +708,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.transferOwnership(foreignBridgeProxy.address).should.be.fulfilled
|
||||
|
||||
|
@ -687,7 +739,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
['3', '2'],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.encodeABI()
|
||||
await storageProxy.upgradeToAndCall('1', foreignBridge.address, data).should.be.fulfilled
|
||||
|
@ -712,7 +765,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
['3', '2'],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.encodeABI()
|
||||
await storageProxy.upgradeToAndCall('1', foreignBridge.address, data).should.be.fulfilled
|
||||
|
@ -736,7 +790,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.transferOwnership(foreignBridge.address)
|
||||
|
||||
|
@ -768,7 +823,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await token.transferOwnership(foreignBridge.address)
|
||||
|
||||
|
@ -800,7 +856,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
|
||||
const tokenMock = await NoReturnTransferTokenMock.new()
|
||||
|
@ -854,7 +911,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
homeFee,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
|
@ -868,7 +926,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
homeFee,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
|
@ -882,7 +941,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
homeFee,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
|
@ -896,7 +956,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
homeFee,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
|
@ -910,7 +971,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
homeFee,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
|
@ -924,7 +986,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
ZERO_ADDRESS,
|
||||
homeFee,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge.rewardableInitialize(
|
||||
|
@ -937,7 +1000,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
homeFee,
|
||||
'9'
|
||||
'9',
|
||||
otherSideBridgeAddress
|
||||
).should.be.fulfilled
|
||||
|
||||
expect(await foreignBridge.isInitialized()).to.be.equal(true)
|
||||
|
@ -974,7 +1038,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
homeFee,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
).should.be.fulfilled
|
||||
|
||||
// Given
|
||||
|
@ -999,7 +1064,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
homeFee,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
).should.be.fulfilled
|
||||
|
||||
// Given
|
||||
|
@ -1023,7 +1089,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
homeFee,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
).should.be.fulfilled
|
||||
|
||||
// Given
|
||||
|
@ -1056,7 +1123,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
homeFee,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
).should.be.fulfilled
|
||||
|
||||
// Then
|
||||
|
@ -1098,7 +1166,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
feeInWei,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
).should.be.fulfilled
|
||||
await token.transferOwnership(foreignBridge.address)
|
||||
|
||||
|
@ -1156,7 +1225,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
feeInWei,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
).should.be.fulfilled
|
||||
await token.transferOwnership(foreignBridge.address)
|
||||
|
||||
|
@ -1242,7 +1312,8 @@ contract('ForeignBridge', async accounts => {
|
|||
owner,
|
||||
feeManager.address,
|
||||
feeInWei,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
otherSideBridgeAddress
|
||||
).should.be.fulfilled
|
||||
await token.transferOwnership(foreignBridge.address)
|
||||
|
||||
|
@ -1322,7 +1393,8 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo
|
||||
decimalShiftTwo,
|
||||
otherSideBridgeAddress
|
||||
)
|
||||
await erc20Token.transferOwnership(foreignBridgeWithThreeSigs.address)
|
||||
|
||||
|
@ -1371,12 +1443,13 @@ contract('ForeignBridge', async accounts => {
|
|||
requireBlockConfirmations,
|
||||
[homeDailyLimit, homeMaxPerTx],
|
||||
owner,
|
||||
decimalShiftTwo
|
||||
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, '0x00', { from: user })
|
||||
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)
|
||||
|
|
|
@ -364,6 +364,98 @@ contract('HomeBridge', async accounts => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('#relayTokens', async () => {
|
||||
const user = accounts[1]
|
||||
const user2 = accounts[2]
|
||||
beforeEach(async () => {
|
||||
homeContract = await HomeBridge.new()
|
||||
await homeContract.initialize(
|
||||
validatorContract.address,
|
||||
['3', '2', '1'],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
)
|
||||
})
|
||||
it('should accept native coins and alternative receiver', async () => {
|
||||
const currentDay = await homeContract.getCurrentDay()
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO)
|
||||
|
||||
const { logs } = await homeContract.relayTokens(user2, {
|
||||
from: user,
|
||||
value: 1
|
||||
}).should.be.fulfilled
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('1')
|
||||
|
||||
expectEventInLogs(logs, 'UserRequestForSignature', { recipient: user2, value: toBN(1) })
|
||||
|
||||
await homeContract
|
||||
.relayTokens(user2, {
|
||||
from: user,
|
||||
value: 3
|
||||
})
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
await homeContract.setDailyLimit(4).should.be.fulfilled
|
||||
await homeContract.relayTokens(user2, {
|
||||
from: user,
|
||||
value: 1
|
||||
}).should.be.fulfilled
|
||||
|
||||
expect(await homeContract.totalSpentPerDay(currentDay)).to.be.bignumber.equal('2')
|
||||
})
|
||||
|
||||
it('doesnt let you send more than max amount per tx', async () => {
|
||||
await homeContract.relayTokens(user2, {
|
||||
from: user,
|
||||
value: 1
|
||||
}).should.be.fulfilled
|
||||
await homeContract
|
||||
.relayTokens(user2, {
|
||||
from: user,
|
||||
value: 3
|
||||
})
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await homeContract.setMaxPerTx(100).should.be.rejectedWith(ERROR_MSG)
|
||||
await homeContract.setDailyLimit(100).should.be.fulfilled
|
||||
await homeContract.setMaxPerTx(99).should.be.fulfilled
|
||||
// meets max per tx and daily limit
|
||||
await homeContract.relayTokens(user2, {
|
||||
from: user,
|
||||
value: 99
|
||||
}).should.be.fulfilled
|
||||
// above daily limit
|
||||
await homeContract
|
||||
.relayTokens(user2, {
|
||||
from: user,
|
||||
value: 1
|
||||
})
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
|
||||
it('should not let to deposit less than minPerTx', async () => {
|
||||
const newDailyLimit = 100
|
||||
const newMaxPerTx = 50
|
||||
const newMinPerTx = 20
|
||||
await homeContract.setDailyLimit(newDailyLimit).should.be.fulfilled
|
||||
await homeContract.setMaxPerTx(newMaxPerTx).should.be.fulfilled
|
||||
await homeContract.setMinPerTx(newMinPerTx).should.be.fulfilled
|
||||
|
||||
await homeContract.relayTokens(user2, {
|
||||
from: user,
|
||||
value: newMinPerTx
|
||||
}).should.be.fulfilled
|
||||
await homeContract
|
||||
.relayTokens(user2, {
|
||||
from: user,
|
||||
value: newMinPerTx - 1
|
||||
})
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#setting limits', async () => {
|
||||
let homeContract
|
||||
beforeEach(async () => {
|
||||
|
@ -1281,6 +1373,55 @@ contract('HomeBridge', async accounts => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('#feeManager_OneDirection_relayRequest', () => {
|
||||
it('should not subtract fee from value', async () => {
|
||||
// Initialize
|
||||
const user = accounts[0]
|
||||
const user2 = accounts[4]
|
||||
const owner = accounts[9]
|
||||
const validators = [accounts[1]]
|
||||
const rewards = [accounts[2]]
|
||||
const requiredSignatures = 1
|
||||
const rewardableValidators = await RewardableValidators.new()
|
||||
const homeBridge = await HomeBridge.new()
|
||||
await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner, {
|
||||
from: owner
|
||||
}).should.be.fulfilled
|
||||
const feeManager = await FeeManagerNativeToErc.new()
|
||||
|
||||
// Given
|
||||
// 0.1% fee
|
||||
const fee = 0.001
|
||||
const feeInWei = ether(fee.toString())
|
||||
const notUsedFee = ZERO
|
||||
const value = halfEther
|
||||
|
||||
await homeBridge.rewardableInitialize(
|
||||
rewardableValidators.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
feeManager.address,
|
||||
[notUsedFee, feeInWei],
|
||||
decimalShiftZero
|
||||
).should.be.fulfilled
|
||||
|
||||
// When
|
||||
const { logs } = await homeBridge.relayTokens(user2, {
|
||||
from: user,
|
||||
value
|
||||
}).should.be.fulfilled
|
||||
|
||||
// Then
|
||||
expectEventInLogs(logs, 'UserRequestForSignature', {
|
||||
recipient: user2,
|
||||
value
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('#feeManager_OneDirection_submitSignature', () => {
|
||||
it('should not distribute fee to validator', async () => {
|
||||
// Initialize
|
||||
|
@ -1659,6 +1800,56 @@ contract('HomeBridge', async accounts => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('#feeManager_BothDirections_relayRequest', () => {
|
||||
it('should subtract fee from value', async () => {
|
||||
// Initialize
|
||||
const user = accounts[0]
|
||||
const user2 = accounts[4]
|
||||
const owner = accounts[9]
|
||||
const validators = [accounts[1]]
|
||||
const rewards = [accounts[2]]
|
||||
const requiredSignatures = 1
|
||||
const rewardableValidators = await RewardableValidators.new()
|
||||
const homeBridge = await HomeBridge.new()
|
||||
await rewardableValidators.initialize(requiredSignatures, validators, rewards, owner, {
|
||||
from: owner
|
||||
}).should.be.fulfilled
|
||||
const feeManager = await FeeManagerNativeToErcBothDirections.new()
|
||||
|
||||
// Given
|
||||
// 0.1% fee
|
||||
const fee = 0.001
|
||||
const feeInWei = ether(fee.toString())
|
||||
const value = halfEther
|
||||
|
||||
await homeBridge.rewardableInitialize(
|
||||
rewardableValidators.address,
|
||||
[oneEther, halfEther, minPerTx],
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
[foreignDailyLimit, foreignMaxPerTx],
|
||||
owner,
|
||||
feeManager.address,
|
||||
[feeInWei, feeInWei],
|
||||
decimalShiftZero
|
||||
).should.be.fulfilled
|
||||
|
||||
// When
|
||||
const { logs } = await homeBridge.relayTokens(user2, {
|
||||
from: user,
|
||||
value
|
||||
}).should.be.fulfilled
|
||||
|
||||
// Then
|
||||
const valueCalc = 0.5 * (1 - fee)
|
||||
const finalValue = ether(valueCalc.toString())
|
||||
expectEventInLogs(logs, 'UserRequestForSignature', {
|
||||
recipient: user2,
|
||||
value: finalValue
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('#feeManager_BothDirections_submitSignature', () => {
|
||||
it('should distribute fee to validator', async () => {
|
||||
// Initialize
|
||||
|
|
|
@ -247,7 +247,8 @@ async function testERC677BridgeToken(accounts, rewardable) {
|
|||
requireBlockConfirmations,
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
homeErcToErcContract.address
|
||||
)
|
||||
})
|
||||
it('sends tokens to recipient', async () => {
|
||||
|
@ -424,7 +425,8 @@ async function testERC677BridgeToken(accounts, rewardable) {
|
|||
requireBlockConfirmations,
|
||||
[executionDailyLimit, executionMaxPerTx],
|
||||
owner,
|
||||
decimalShiftZero
|
||||
decimalShiftZero,
|
||||
homeErcToErcContract.address
|
||||
)
|
||||
})
|
||||
it('calls contractFallback', async () => {
|
||||
|
|
Loading…
Reference in New Issue