Add linter for unit tests
This commit is contained in:
parent
6bad8be39d
commit
34d48efad7
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
deploy
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"extends": [
|
||||
"plugin:node/recommended",
|
||||
"airbnb-base",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"plugins": ["node"],
|
||||
"env": {
|
||||
"node" : true,
|
||||
"mocha" : true
|
||||
},
|
||||
"globals" : {
|
||||
"artifacts": false,
|
||||
"contract": false,
|
||||
"assert": false,
|
||||
"web3": false
|
||||
},
|
||||
"rules": {
|
||||
"no-plusplus": "off",
|
||||
"no-await-in-loop": "off",
|
||||
"no-shadow": "off",
|
||||
"prefer-destructuring": "off",
|
||||
"no-use-before-define": ["error", { "functions": false }],
|
||||
"no-restricted-syntax": "off",
|
||||
"node/no-unpublished-require": "off"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 120
|
||||
}
|
|
@ -14,4 +14,5 @@ matrix:
|
|||
allow_failures:
|
||||
- env: SOLIDITY_COVERAGE=true
|
||||
script:
|
||||
- yarn lint:js
|
||||
- yarn test
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,6 +8,8 @@
|
|||
"test:gasreport": "GASREPORT=true npm run test",
|
||||
"compile": "truffle compile && truffle compile spuriousDragon",
|
||||
"flatten": "bash flatten.sh",
|
||||
"lint:js": "eslint .",
|
||||
"lint:js:fix": "eslint . --fix",
|
||||
"watch-tests": "./node_modules/.bin/nodemon ./node_modules/.bin/truffle test --network test"
|
||||
},
|
||||
"author": "POA network",
|
||||
|
@ -21,8 +23,15 @@
|
|||
"chai": "^4.2.0",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"chai-bn": "^0.1.1",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-airbnb-base": "^13.1.0",
|
||||
"eslint-config-prettier": "^4.2.0",
|
||||
"eslint-plugin-import": "^2.17.2",
|
||||
"eslint-plugin-node": "^9.0.1",
|
||||
"eslint-plugin-prettier": "^3.0.1",
|
||||
"eth-gas-reporter": "^0.1.12",
|
||||
"nodemon": "^1.17.3",
|
||||
"prettier": "^1.17.1",
|
||||
"solidity-coverage": "^0.5.11",
|
||||
"truffle-flattener": "^1.2.3"
|
||||
}
|
||||
|
|
|
@ -1,39 +1,41 @@
|
|||
const ForeignBridge = artifacts.require("ForeignBridgeErcToErc.sol");
|
||||
const ForeignBridgeErc677ToErc677 = artifacts.require("ForeignBridgeErc677ToErc677.sol");
|
||||
const ForeignBridgeV2 = artifacts.require("ForeignBridgeV2.sol");
|
||||
const BridgeValidators = artifacts.require("BridgeValidators.sol");
|
||||
const EternalStorageProxy = artifacts.require("EternalStorageProxy.sol");
|
||||
const ERC677BridgeToken = artifacts.require("ERC677BridgeToken.sol");
|
||||
const ForeignBridge = artifacts.require('ForeignBridgeErcToErc.sol')
|
||||
const ForeignBridgeErc677ToErc677 = artifacts.require('ForeignBridgeErc677ToErc677.sol')
|
||||
const ForeignBridgeV2 = artifacts.require('ForeignBridgeV2.sol')
|
||||
const BridgeValidators = artifacts.require('BridgeValidators.sol')
|
||||
const EternalStorageProxy = artifacts.require('EternalStorageProxy.sol')
|
||||
const ERC677BridgeToken = artifacts.require('ERC677BridgeToken.sol')
|
||||
|
||||
const { expect } = require('chai');
|
||||
const { ERROR_MSG, ZERO_ADDRESS, toBN } = require('../setup');
|
||||
const { createMessage, sign, signatureToVRS, ether, getEvents } = require('../helpers/helpers');
|
||||
const { expect } = require('chai')
|
||||
const { ERROR_MSG, ZERO_ADDRESS, toBN } = require('../setup')
|
||||
const { createMessage, sign, signatureToVRS, ether, getEvents } = require('../helpers/helpers')
|
||||
|
||||
const oneEther = ether('1');
|
||||
const halfEther = ether('0.5');
|
||||
const requireBlockConfirmations = 8;
|
||||
const oneEther = ether('1')
|
||||
const halfEther = ether('0.5')
|
||||
const requireBlockConfirmations = 8
|
||||
const gasPrice = web3.utils.toWei('1', 'gwei')
|
||||
const homeDailyLimit = oneEther
|
||||
const homeMaxPerTx = halfEther
|
||||
const maxPerTx = halfEther
|
||||
const minPerTx = ether('0.01');
|
||||
const minPerTx = ether('0.01')
|
||||
const dailyLimit = oneEther
|
||||
const ZERO = toBN(0)
|
||||
|
||||
|
||||
contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => {
|
||||
let validatorContract, authorities, owner, token;
|
||||
contract('ForeignBridge_ERC20_to_ERC20', async accounts => {
|
||||
let validatorContract
|
||||
let authorities
|
||||
let owner
|
||||
let token
|
||||
before(async () => {
|
||||
validatorContract = await BridgeValidators.new()
|
||||
authorities = [accounts[1], accounts[2]];
|
||||
authorities = [accounts[1], accounts[2]]
|
||||
owner = accounts[0]
|
||||
await validatorContract.initialize(1, authorities, owner)
|
||||
})
|
||||
|
||||
describe('#initialize', async () => {
|
||||
it('should initialize', async () => {
|
||||
token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
let foreignBridge = await ForeignBridge.new();
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
const foreignBridge = await ForeignBridge.new()
|
||||
|
||||
expect(await foreignBridge.erc20token()).to.be.equal(ZERO_ADDRESS)
|
||||
expect(await foreignBridge.validatorContract()).to.be.equal(ZERO_ADDRESS)
|
||||
|
@ -41,20 +43,97 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => {
|
|||
expect(await foreignBridge.isInitialized()).to.be.equal(false)
|
||||
expect(await foreignBridge.requiredBlockConfirmations()).to.be.bignumber.equal(ZERO)
|
||||
|
||||
await foreignBridge.initialize(ZERO_ADDRESS, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge.initialize(validatorContract.address, ZERO_ADDRESS, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge.initialize(validatorContract.address, owner, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, 0, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, 0, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge.initialize(owner, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
ZERO_ADDRESS,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
validatorContract.address,
|
||||
ZERO_ADDRESS,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
validatorContract.address,
|
||||
owner,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
0,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
0,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
owner,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
|
||||
expect(await foreignBridge.erc20token()).to.be.equal(token.address)
|
||||
expect(await foreignBridge.isInitialized()).to.be.equal(true)
|
||||
expect(await foreignBridge.validatorContract()).to.be.equal(validatorContract.address)
|
||||
expect(await foreignBridge.deployedAtBlock()).to.be.bignumber.above(ZERO)
|
||||
expect(await foreignBridge.requiredBlockConfirmations()).to.be.bignumber.equal(requireBlockConfirmations.toString())
|
||||
expect(await foreignBridge.requiredBlockConfirmations()).to.be.bignumber.equal(
|
||||
requireBlockConfirmations.toString()
|
||||
)
|
||||
expect(await foreignBridge.gasPrice()).to.be.bignumber.equal(gasPrice)
|
||||
const bridgeMode = '0xba4690f5' // 4 bytes of keccak256('erc-to-erc-core')
|
||||
expect(await foreignBridge.getBridgeMode()).to.be.equal(bridgeMode)
|
||||
|
@ -66,54 +145,63 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => {
|
|||
})
|
||||
|
||||
describe('#executeSignatures', async () => {
|
||||
const value = ether('0.25');
|
||||
const value = ether('0.25')
|
||||
let foreignBridge
|
||||
beforeEach(async () => {
|
||||
foreignBridge = await ForeignBridge.new()
|
||||
token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
await token.mint(foreignBridge.address,value);
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
await token.mint(foreignBridge.address, value)
|
||||
})
|
||||
it('should allow to executeSignatures', async () => {
|
||||
const recipientAccount = accounts[3];
|
||||
const recipientAccount = accounts[3]
|
||||
const balanceBefore = await token.balanceOf(recipientAccount)
|
||||
|
||||
const transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address);
|
||||
const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80'
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
const {logs} = await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
|
||||
logs[0].event.should.be.equal("RelayedMessage")
|
||||
const { logs } = await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).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(value)
|
||||
|
||||
const balanceAfter = await token.balanceOf(recipientAccount);
|
||||
const balanceAfterBridge = await token.balanceOf(foreignBridge.address);
|
||||
const balanceAfter = await token.balanceOf(recipientAccount)
|
||||
const balanceAfterBridge = await token.balanceOf(foreignBridge.address)
|
||||
balanceAfter.should.be.bignumber.equal(balanceBefore.add(value))
|
||||
balanceAfterBridge.should.be.bignumber.equal(ZERO)
|
||||
true.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
})
|
||||
it('should allow second withdrawal with different transactionHash but same recipient and value', async ()=> {
|
||||
const recipientAccount = accounts[3];
|
||||
it('should allow second withdrawal with different transactionHash but same recipient and value', async () => {
|
||||
const recipientAccount = accounts[3]
|
||||
const balanceBefore = await token.balanceOf(recipientAccount)
|
||||
// tx 1
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address);
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
|
||||
// tx 2
|
||||
await token.mint(foreignBridge.address,value);
|
||||
const transactionHash2 = "0x77a496628a776a03d58d7e6059a5937f04bebd8ba4ff89f76dd4bb8ba7e291ee";
|
||||
const message2 = createMessage(recipientAccount, value, transactionHash2, foreignBridge.address);
|
||||
await token.mint(foreignBridge.address, value)
|
||||
const transactionHash2 = '0x77a496628a776a03d58d7e6059a5937f04bebd8ba4ff89f76dd4bb8ba7e291ee'
|
||||
const message2 = createMessage(recipientAccount, value, transactionHash2, foreignBridge.address)
|
||||
const signature2 = await sign(authorities[0], message2)
|
||||
const vrs2 = signatureToVRS(signature2);
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash2))
|
||||
const {logs} = await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.fulfilled
|
||||
const { logs } = await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.fulfilled
|
||||
|
||||
logs[0].event.should.be.equal("RelayedMessage")
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipientAccount)
|
||||
logs[0].args.value.should.be.bignumber.equal(value)
|
||||
const balanceAfter = await token.balanceOf(recipientAccount)
|
||||
|
@ -123,104 +211,126 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => {
|
|||
})
|
||||
|
||||
it('should not allow second withdraw (replay attack) with same transactionHash but different recipient', async () => {
|
||||
const recipientAccount = accounts[3];
|
||||
const recipientAccount = accounts[3]
|
||||
// tx 1
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address);
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
|
||||
// tx 2
|
||||
await token.mint(foreignBridge.address,value);
|
||||
const message2 = createMessage(accounts[4], value, transactionHash, foreignBridge.address);
|
||||
await token.mint(foreignBridge.address, value)
|
||||
const message2 = createMessage(accounts[4], value, transactionHash, foreignBridge.address)
|
||||
const signature2 = await sign(authorities[0], message2)
|
||||
const vrs2 = signatureToVRS(signature2);
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
true.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
|
||||
it('should not allow withdraw over home max tx limit', async () => {
|
||||
const recipientAccount = accounts[3];
|
||||
const invalidValue = ether('0.75');
|
||||
await token.mint(foreignBridge.address, ether('5'));
|
||||
const recipientAccount = accounts[3]
|
||||
const invalidValue = ether('0.75')
|
||||
await token.mint(foreignBridge.address, ether('5'))
|
||||
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, invalidValue, transactionHash, foreignBridge.address);
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, invalidValue, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
|
||||
await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
|
||||
it('should not allow withdraw over daily home limit', async () => {
|
||||
const recipientAccount = accounts[3];
|
||||
await token.mint(foreignBridge.address, ether('5'));
|
||||
const recipientAccount = accounts[3]
|
||||
await token.mint(foreignBridge.address, ether('5'))
|
||||
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, halfEther, transactionHash, foreignBridge.address);
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, halfEther, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
|
||||
await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
|
||||
|
||||
const transactionHash2 = "0x69debd8fd1923c9cb3cd8ef6461e2740b2d037943b941729d5a47671a2bb8712";
|
||||
const message2 = createMessage(recipientAccount, halfEther, transactionHash2, foreignBridge.address);
|
||||
const transactionHash2 = '0x69debd8fd1923c9cb3cd8ef6461e2740b2d037943b941729d5a47671a2bb8712'
|
||||
const message2 = createMessage(recipientAccount, halfEther, transactionHash2, foreignBridge.address)
|
||||
const signature2 = await sign(authorities[0], message2)
|
||||
const vrs2 = signatureToVRS(signature2);
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
|
||||
await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.fulfilled
|
||||
|
||||
const transactionHash3 = "0x022695428093bb292db8e48bd1417c5e1b84c0bf673bd0fff23ed0fb6495b872";
|
||||
const message3 = createMessage(recipientAccount, halfEther, transactionHash3, foreignBridge.address);
|
||||
const transactionHash3 = '0x022695428093bb292db8e48bd1417c5e1b84c0bf673bd0fff23ed0fb6495b872'
|
||||
const message3 = createMessage(recipientAccount, halfEther, transactionHash3, foreignBridge.address)
|
||||
const signature3 = await sign(authorities[0], message3)
|
||||
const vrs3 = signatureToVRS(signature3);
|
||||
const vrs3 = signatureToVRS(signature3)
|
||||
|
||||
await foreignBridge.executeSignatures([vrs3.v], [vrs3.r], [vrs3.s], message3).should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
})
|
||||
describe('#withdraw with 2 minimum signatures', async () => {
|
||||
let multisigValidatorContract, twoAuthorities, ownerOfValidatorContract, foreignBridgeWithMultiSignatures
|
||||
let multisigValidatorContract
|
||||
let twoAuthorities
|
||||
let ownerOfValidatorContract
|
||||
let foreignBridgeWithMultiSignatures
|
||||
const value = halfEther
|
||||
beforeEach(async () => {
|
||||
multisigValidatorContract = await BridgeValidators.new()
|
||||
token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
twoAuthorities = [accounts[0], accounts[1]];
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
twoAuthorities = [accounts[0], accounts[1]]
|
||||
ownerOfValidatorContract = accounts[3]
|
||||
await multisigValidatorContract.initialize(2, twoAuthorities, ownerOfValidatorContract, {from: ownerOfValidatorContract})
|
||||
await multisigValidatorContract.initialize(2, twoAuthorities, ownerOfValidatorContract, {
|
||||
from: ownerOfValidatorContract
|
||||
})
|
||||
foreignBridgeWithMultiSignatures = await ForeignBridge.new()
|
||||
await foreignBridgeWithMultiSignatures.initialize(multisigValidatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner, {from: ownerOfValidatorContract});
|
||||
await token.mint(foreignBridgeWithMultiSignatures.address,value);
|
||||
await foreignBridgeWithMultiSignatures.initialize(
|
||||
multisigValidatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner,
|
||||
{ from: ownerOfValidatorContract }
|
||||
)
|
||||
await token.mint(foreignBridgeWithMultiSignatures.address, value)
|
||||
})
|
||||
it('withdraw should fail if not enough signatures are provided', async () => {
|
||||
|
||||
const recipientAccount = accounts[4];
|
||||
const recipientAccount = accounts[4]
|
||||
// msg 1
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridgeWithMultiSignatures.address);
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridgeWithMultiSignatures.address)
|
||||
const signature = await sign(twoAuthorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
false.should.be.equal(await foreignBridgeWithMultiSignatures.relayedMessages(transactionHash))
|
||||
await foreignBridgeWithMultiSignatures.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridgeWithMultiSignatures
|
||||
.executeSignatures([vrs.v], [vrs.r], [vrs.s], message)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
// msg 2
|
||||
const signature2 = await sign(twoAuthorities[1], message)
|
||||
const vrs2 = signatureToVRS(signature2);
|
||||
const {logs} = await foreignBridgeWithMultiSignatures.executeSignatures([vrs.v, vrs2.v], [vrs.r, vrs2.r], [vrs.s, vrs2.s], message).should.be.fulfilled;
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
const { logs } = await foreignBridgeWithMultiSignatures.executeSignatures(
|
||||
[vrs.v, vrs2.v],
|
||||
[vrs.r, vrs2.r],
|
||||
[vrs.s, vrs2.s],
|
||||
message
|
||||
).should.be.fulfilled
|
||||
|
||||
logs[0].event.should.be.equal("RelayedMessage")
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipientAccount)
|
||||
logs[0].args.value.should.be.bignumber.equal(value)
|
||||
true.should.be.equal(await foreignBridgeWithMultiSignatures.relayedMessages(transactionHash))
|
||||
|
||||
})
|
||||
it('withdraw should fail if duplicate signature is provided', async () => {
|
||||
const recipientAccount = accounts[4];
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridgeWithMultiSignatures.address);
|
||||
const recipientAccount = accounts[4]
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridgeWithMultiSignatures.address)
|
||||
const signature = await sign(twoAuthorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
false.should.be.equal(await foreignBridgeWithMultiSignatures.relayedMessages(transactionHash))
|
||||
await foreignBridgeWithMultiSignatures.executeSignatures([vrs.v, vrs.v], [vrs.r, vrs.r], [vrs.s, vrs.s], message).should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridgeWithMultiSignatures
|
||||
.executeSignatures([vrs.v, vrs.v], [vrs.r, vrs.r], [vrs.s, vrs.s], message)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
|
||||
it('works with 5 validators and 3 required signatures', async () => {
|
||||
|
@ -229,31 +339,44 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => {
|
|||
const ownerOfValidators = accounts[0]
|
||||
const validatorContractWith3Signatures = await BridgeValidators.new()
|
||||
await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators)
|
||||
const erc20Token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
const erc20Token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
const value = halfEther
|
||||
const foreignBridgeWithThreeSigs = await ForeignBridge.new()
|
||||
|
||||
await foreignBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, erc20Token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
await erc20Token.mint(foreignBridgeWithThreeSigs.address, value);
|
||||
await foreignBridgeWithThreeSigs.initialize(
|
||||
validatorContractWith3Signatures.address,
|
||||
erc20Token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
await erc20Token.mint(foreignBridgeWithThreeSigs.address, value)
|
||||
|
||||
const txHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipient, value, txHash, foreignBridgeWithThreeSigs.address);
|
||||
const txHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipient, value, txHash, foreignBridgeWithThreeSigs.address)
|
||||
|
||||
// signature 1
|
||||
const signature = await sign(authoritiesFiveAccs[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
|
||||
// signature 2
|
||||
const signature2 = await sign(authoritiesFiveAccs[1], message)
|
||||
const vrs2 = signatureToVRS(signature2);
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
|
||||
// signature 3
|
||||
const signature3 = await sign(authoritiesFiveAccs[2], message)
|
||||
const vrs3 = signatureToVRS(signature3);
|
||||
const vrs3 = signatureToVRS(signature3)
|
||||
|
||||
|
||||
const {logs} = await foreignBridgeWithThreeSigs.executeSignatures([vrs.v, vrs2.v, vrs3.v], [vrs.r, vrs2.r, vrs3.r], [vrs.s, vrs2.s, vrs3.s], message).should.be.fulfilled;
|
||||
logs[0].event.should.be.equal("RelayedMessage")
|
||||
const { logs } = await foreignBridgeWithThreeSigs.executeSignatures(
|
||||
[vrs.v, vrs2.v, vrs3.v],
|
||||
[vrs.r, vrs2.r, vrs3.r],
|
||||
[vrs.s, vrs2.s, vrs3.s],
|
||||
message
|
||||
).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(value)
|
||||
true.should.be.equal(await foreignBridgeWithThreeSigs.relayedMessages(txHash))
|
||||
|
@ -263,173 +386,241 @@ contract('ForeignBridge_ERC20_to_ERC20', async (accounts) => {
|
|||
it('can be upgraded', async () => {
|
||||
const REQUIRED_NUMBER_OF_VALIDATORS = 1
|
||||
const VALIDATORS = [accounts[1]]
|
||||
const PROXY_OWNER = accounts[0]
|
||||
const PROXY_OWNER = accounts[0]
|
||||
// Validators Contract
|
||||
let validatorsProxy = await EternalStorageProxy.new().should.be.fulfilled;
|
||||
const validatorsContractImpl = await BridgeValidators.new().should.be.fulfilled;
|
||||
await validatorsProxy.upgradeTo('1', validatorsContractImpl.address).should.be.fulfilled;
|
||||
let validatorsProxy = await EternalStorageProxy.new().should.be.fulfilled
|
||||
const validatorsContractImpl = await BridgeValidators.new().should.be.fulfilled
|
||||
await validatorsProxy.upgradeTo('1', validatorsContractImpl.address).should.be.fulfilled
|
||||
validatorsContractImpl.address.should.be.equal(await validatorsProxy.implementation())
|
||||
|
||||
validatorsProxy = await BridgeValidators.at(validatorsProxy.address);
|
||||
await validatorsProxy.initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, PROXY_OWNER).should.be.fulfilled;
|
||||
let token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
validatorsProxy = await BridgeValidators.at(validatorsProxy.address)
|
||||
await validatorsProxy.initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, PROXY_OWNER).should.be.fulfilled
|
||||
const token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
|
||||
// ForeignBridge V1 Contract
|
||||
|
||||
let foreignBridgeProxy = await EternalStorageProxy.new().should.be.fulfilled;
|
||||
const foreignBridgeImpl = await ForeignBridge.new().should.be.fulfilled;
|
||||
await foreignBridgeProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled;
|
||||
let foreignBridgeProxy = await EternalStorageProxy.new().should.be.fulfilled
|
||||
const foreignBridgeImpl = await ForeignBridge.new().should.be.fulfilled
|
||||
await foreignBridgeProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled
|
||||
|
||||
foreignBridgeProxy = await ForeignBridge.at(foreignBridgeProxy.address);
|
||||
await foreignBridgeProxy.initialize(validatorsProxy.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner)
|
||||
foreignBridgeProxy = await ForeignBridge.at(foreignBridgeProxy.address)
|
||||
await foreignBridgeProxy.initialize(
|
||||
validatorsProxy.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
|
||||
// Deploy V2
|
||||
let foreignImplV2 = await ForeignBridgeV2.new();
|
||||
let foreignBridgeProxyUpgrade = await EternalStorageProxy.at(foreignBridgeProxy.address);
|
||||
await foreignBridgeProxyUpgrade.upgradeTo('2', foreignImplV2.address).should.be.fulfilled;
|
||||
const foreignImplV2 = await ForeignBridgeV2.new()
|
||||
const foreignBridgeProxyUpgrade = await EternalStorageProxy.at(foreignBridgeProxy.address)
|
||||
await foreignBridgeProxyUpgrade.upgradeTo('2', foreignImplV2.address).should.be.fulfilled
|
||||
foreignImplV2.address.should.be.equal(await foreignBridgeProxyUpgrade.implementation())
|
||||
|
||||
let foreignBridgeV2Proxy = await ForeignBridgeV2.at(foreignBridgeProxy.address)
|
||||
await foreignBridgeV2Proxy.doSomething(accounts[2], {from: accounts[4]}).should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridgeV2Proxy.doSomething(accounts[2], {from: PROXY_OWNER}).should.be.fulfilled;
|
||||
(await foreignBridgeV2Proxy.something()).should.be.equal(accounts[2])
|
||||
const foreignBridgeV2Proxy = await ForeignBridgeV2.at(foreignBridgeProxy.address)
|
||||
await foreignBridgeV2Proxy.doSomething(accounts[2], { from: accounts[4] }).should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridgeV2Proxy.doSomething(accounts[2], { from: PROXY_OWNER }).should.be.fulfilled
|
||||
;(await foreignBridgeV2Proxy.something()).should.be.equal(accounts[2])
|
||||
})
|
||||
it('can be deployed via upgradeToAndCall', async () => {
|
||||
const tokenAddress = token.address
|
||||
const validatorsAddress = validatorContract.address
|
||||
|
||||
let storageProxy = await EternalStorageProxy.new().should.be.fulfilled;
|
||||
let foreignBridge = await ForeignBridge.new();
|
||||
const data = foreignBridge.contract.methods.initialize(
|
||||
validatorsAddress, tokenAddress, requireBlockConfirmations, gasPrice, '2', '3', '2', owner).encodeABI()
|
||||
await storageProxy.upgradeToAndCall('1', foreignBridge.address, data).should.be.fulfilled;
|
||||
let finalContract = await ForeignBridge.at(storageProxy.address);
|
||||
true.should.be.equal(await finalContract.isInitialized());
|
||||
const storageProxy = await EternalStorageProxy.new().should.be.fulfilled
|
||||
const foreignBridge = await ForeignBridge.new()
|
||||
const data = foreignBridge.contract.methods
|
||||
.initialize(validatorsAddress, tokenAddress, requireBlockConfirmations, gasPrice, '2', '3', '2', owner)
|
||||
.encodeABI()
|
||||
await storageProxy.upgradeToAndCall('1', foreignBridge.address, data).should.be.fulfilled
|
||||
const finalContract = await ForeignBridge.at(storageProxy.address)
|
||||
true.should.be.equal(await finalContract.isInitialized())
|
||||
validatorsAddress.should.be.equal(await finalContract.validatorContract())
|
||||
})
|
||||
})
|
||||
describe('#claimTokens', async () => {
|
||||
it('can send erc20', async () => {
|
||||
const owner = accounts[0];
|
||||
token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
const foreignBridgeImpl = await ForeignBridge.new();
|
||||
const storageProxy = await EternalStorageProxy.new().should.be.fulfilled;
|
||||
const owner = accounts[0]
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
const foreignBridgeImpl = await ForeignBridge.new()
|
||||
const storageProxy = await EternalStorageProxy.new().should.be.fulfilled
|
||||
await storageProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled
|
||||
const foreignBridge = await ForeignBridge.at(storageProxy.address);
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
const foreignBridge = await ForeignBridge.at(storageProxy.address)
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
|
||||
let tokenSecond = await ERC677BridgeToken.new("Roman Token", "RST", 18);
|
||||
const tokenSecond = await ERC677BridgeToken.new('Roman Token', 'RST', 18)
|
||||
|
||||
await tokenSecond.mint(accounts[0], halfEther).should.be.fulfilled;
|
||||
await tokenSecond.mint(accounts[0], halfEther).should.be.fulfilled
|
||||
expect(await tokenSecond.balanceOf(accounts[0])).to.be.bignumber.equal(halfEther)
|
||||
|
||||
await tokenSecond.transfer(foreignBridge.address, halfEther);
|
||||
await tokenSecond.transfer(foreignBridge.address, halfEther)
|
||||
expect(await tokenSecond.balanceOf(accounts[0])).to.be.bignumber.equal(ZERO)
|
||||
expect(await tokenSecond.balanceOf(foreignBridge.address)).to.be.bignumber.equal(halfEther)
|
||||
|
||||
await foreignBridge.claimTokens(tokenSecond.address, accounts[3], {from: owner});
|
||||
await foreignBridge.claimTokens(tokenSecond.address, accounts[3], { from: owner })
|
||||
expect(await tokenSecond.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO)
|
||||
expect(await tokenSecond.balanceOf(accounts[3])).to.be.bignumber.equal(halfEther)
|
||||
})
|
||||
})
|
||||
describe('#ForeignBridgeErc677ToErc677_onTokenTransfer', async () => {
|
||||
it('can only be called from token contract', async ()=> {
|
||||
it('can only be called from token contract', async () => {
|
||||
const owner = accounts[3]
|
||||
const user = accounts[4]
|
||||
token = await ERC677BridgeToken.new("TEST", "TST", 18, {from: owner});
|
||||
const foreignBridge = await ForeignBridgeErc677ToErc677.new();
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, dailyLimit, maxPerTx, minPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
token = await ERC677BridgeToken.new('TEST', 'TST', 18, { from: owner })
|
||||
const foreignBridge = await ForeignBridgeErc677ToErc677.new()
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
dailyLimit,
|
||||
maxPerTx,
|
||||
minPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
|
||||
await token.mint(user, halfEther, {from: owner }).should.be.fulfilled;
|
||||
await token.transferOwnership(foreignBridge.address, {from: owner});
|
||||
await foreignBridge.onTokenTransfer(user, halfEther, '0x00', {from: owner}).should.be.rejectedWith(ERROR_MSG);
|
||||
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 token.transferAndCall(foreignBridge.address, halfEther, '0x00', { from: user }).should.be.fulfilled
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(halfEther)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(foreignBridge.address)).to.be.bignumber.equal(halfEther)
|
||||
|
||||
const events = await getEvents(foreignBridge, {event: 'UserRequestForAffirmation'});
|
||||
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(halfEther)
|
||||
})
|
||||
it('should not allow to transfer more than maxPerTx limit', async () => {
|
||||
const owner = accounts[3]
|
||||
const user = accounts[4]
|
||||
const valueMoreThanLimit = halfEther.add(toBN(1));
|
||||
token = await ERC677BridgeToken.new("TEST", "TST", 18, {from: owner});
|
||||
const foreignBridge = await ForeignBridgeErc677ToErc677.new();
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, dailyLimit, maxPerTx, minPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
const valueMoreThanLimit = halfEther.add(toBN(1))
|
||||
token = await ERC677BridgeToken.new('TEST', 'TST', 18, { from: owner })
|
||||
const foreignBridge = await ForeignBridgeErc677ToErc677.new()
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
dailyLimit,
|
||||
maxPerTx,
|
||||
minPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
|
||||
await token.mint(user, valueMoreThanLimit, {from: owner }).should.be.fulfilled;
|
||||
await token.transferOwnership(foreignBridge.address, {from: owner});
|
||||
await token.mint(user, valueMoreThanLimit, { from: owner }).should.be.fulfilled
|
||||
await token.transferOwnership(foreignBridge.address, { from: owner })
|
||||
|
||||
await token.transferAndCall(foreignBridge.address, valueMoreThanLimit, '0x00', {from: user}).should.be.rejectedWith(ERROR_MSG);
|
||||
valueMoreThanLimit.should.be.bignumber.equal(await token.totalSupply());
|
||||
valueMoreThanLimit.should.be.bignumber.equal(await token.balanceOf(user));
|
||||
await token
|
||||
.transferAndCall(foreignBridge.address, valueMoreThanLimit, '0x00', { 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, '0x00', { from: user }).should.be.fulfilled
|
||||
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(valueMoreThanLimit)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('1')
|
||||
expect(await token.balanceOf(foreignBridge.address)).to.be.bignumber.equal(halfEther)
|
||||
const events = await getEvents(foreignBridge, {event: 'UserRequestForAffirmation'});
|
||||
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(halfEther)
|
||||
})
|
||||
it('should only let to transfer within daily limit', async () => {
|
||||
const owner = accounts[3]
|
||||
const user = accounts[4]
|
||||
const valueMoreThanLimit = halfEther.add(toBN(1));
|
||||
token = await ERC677BridgeToken.new("TEST", "TST", 18, {from: owner});
|
||||
const foreignBridge = await ForeignBridgeErc677ToErc677.new();
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, dailyLimit, maxPerTx, minPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
const valueMoreThanLimit = halfEther.add(toBN(1))
|
||||
token = await ERC677BridgeToken.new('TEST', 'TST', 18, { from: owner })
|
||||
const foreignBridge = await ForeignBridgeErc677ToErc677.new()
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
dailyLimit,
|
||||
maxPerTx,
|
||||
minPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
|
||||
await token.mint(user, oneEther.add(toBN(1)), {from: owner }).should.be.fulfilled;
|
||||
await token.transferOwnership(foreignBridge.address, {from: owner});
|
||||
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}).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, valueMoreThanLimit, '0x00', { 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;
|
||||
oneEther.add(toBN(1)).should.be.bignumber.equal(await token.totalSupply());
|
||||
valueMoreThanLimit.should.be.bignumber.equal(await token.balanceOf(user));
|
||||
const events = await getEvents(foreignBridge, {event: 'UserRequestForAffirmation'});
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, '0x00', { from: user }).should.be.fulfilled
|
||||
oneEther.add(toBN(1)).should.be.bignumber.equal(await token.totalSupply())
|
||||
valueMoreThanLimit.should.be.bignumber.equal(await token.balanceOf(user))
|
||||
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(halfEther)
|
||||
|
||||
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, '0x00', {from: user}).should.be.fulfilled;
|
||||
await token.transferAndCall(foreignBridge.address, halfEther, '0x00', { from: user }).should.be.fulfilled
|
||||
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(oneEther.add(toBN(1)))
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('1')
|
||||
expect(await token.balanceOf(foreignBridge.address)).to.be.bignumber.equal(oneEther)
|
||||
|
||||
await token.transferAndCall(foreignBridge.address, '1', '0x00', {from: user}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.transferAndCall(foreignBridge.address, '1', '0x00', { from: user }).should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
it('should not let to transfer less than minPerTx', async () => {
|
||||
const owner = accounts[3]
|
||||
const user = accounts[4]
|
||||
const valueLessThanMinPerTx = minPerTx.sub(toBN(1));
|
||||
token = await ERC677BridgeToken.new("TEST", "TST", 18, {from: owner});
|
||||
const foreignBridge = await ForeignBridgeErc677ToErc677.new();
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, dailyLimit, maxPerTx, minPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
const valueLessThanMinPerTx = minPerTx.sub(toBN(1))
|
||||
token = await ERC677BridgeToken.new('TEST', 'TST', 18, { from: owner })
|
||||
const foreignBridge = await ForeignBridgeErc677ToErc677.new()
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
dailyLimit,
|
||||
maxPerTx,
|
||||
minPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
|
||||
await token.mint(user, oneEther, {from: owner }).should.be.fulfilled;
|
||||
await token.transferOwnership(foreignBridge.address, {from: owner});
|
||||
await token.mint(user, oneEther, { from: owner }).should.be.fulfilled
|
||||
await token.transferOwnership(foreignBridge.address, { from: owner })
|
||||
|
||||
await token.transferAndCall(foreignBridge.address, valueLessThanMinPerTx, '0x00', {from: user}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token
|
||||
.transferAndCall(foreignBridge.address, valueLessThanMinPerTx, '0x00', { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(oneEther)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(oneEther)
|
||||
|
||||
await token.transferAndCall(foreignBridge.address, minPerTx, '0x00', {from: user}).should.be.fulfilled;
|
||||
await token.transferAndCall(foreignBridge.address, minPerTx, '0x00', { from: user }).should.be.fulfilled
|
||||
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(oneEther)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(oneEther.sub(minPerTx))
|
||||
expect(await token.balanceOf(foreignBridge.address)).to.be.bignumber.equal(minPerTx)
|
||||
|
||||
const events = await getEvents(foreignBridge, {event: 'UserRequestForAffirmation'});
|
||||
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(minPerTx)
|
||||
})
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,35 +1,38 @@
|
|||
const ForeignBridge = artifacts.require("ForeignBridgeErcToNative.sol");
|
||||
const ForeignBridgeV2 = artifacts.require("ForeignBridgeV2.sol");
|
||||
const BridgeValidators = artifacts.require("BridgeValidators.sol");
|
||||
const EternalStorageProxy = artifacts.require("EternalStorageProxy.sol");
|
||||
const ERC677BridgeToken = artifacts.require("ERC677BridgeToken.sol");
|
||||
const ForeignBridge = artifacts.require('ForeignBridgeErcToNative.sol')
|
||||
const ForeignBridgeV2 = artifacts.require('ForeignBridgeV2.sol')
|
||||
const BridgeValidators = artifacts.require('BridgeValidators.sol')
|
||||
const EternalStorageProxy = artifacts.require('EternalStorageProxy.sol')
|
||||
const ERC677BridgeToken = artifacts.require('ERC677BridgeToken.sol')
|
||||
|
||||
const { expect } = require('chai');
|
||||
const { ERROR_MSG, ZERO_ADDRESS, toBN } = require('../setup');
|
||||
const { createMessage, sign, signatureToVRS, ether } = require('../helpers/helpers');
|
||||
const { expect } = require('chai')
|
||||
const { ERROR_MSG, ZERO_ADDRESS, toBN } = require('../setup')
|
||||
const { createMessage, sign, signatureToVRS, ether } = require('../helpers/helpers')
|
||||
|
||||
const halfEther = ether('0.5');
|
||||
const requireBlockConfirmations = 8;
|
||||
const gasPrice = web3.utils.toWei('1', 'gwei');
|
||||
const oneEther = ether('1');
|
||||
const halfEther = ether('0.5')
|
||||
const requireBlockConfirmations = 8
|
||||
const gasPrice = web3.utils.toWei('1', 'gwei')
|
||||
const oneEther = ether('1')
|
||||
const homeDailyLimit = oneEther
|
||||
const homeMaxPerTx = halfEther
|
||||
const maxPerTx = halfEther
|
||||
const ZERO = toBN(0)
|
||||
|
||||
contract('ForeignBridge_ERC20_to_Native', async (accounts) => {
|
||||
let validatorContract, authorities, owner, token;
|
||||
contract('ForeignBridge_ERC20_to_Native', async accounts => {
|
||||
let validatorContract
|
||||
let authorities
|
||||
let owner
|
||||
let token
|
||||
before(async () => {
|
||||
validatorContract = await BridgeValidators.new()
|
||||
authorities = [accounts[1], accounts[2]];
|
||||
authorities = [accounts[1], accounts[2]]
|
||||
owner = accounts[0]
|
||||
await validatorContract.initialize(1, authorities, owner)
|
||||
})
|
||||
|
||||
describe('#initialize', async () => {
|
||||
it('should initialize', async () => {
|
||||
token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
let foreignBridge = await ForeignBridge.new();
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
const foreignBridge = await ForeignBridge.new()
|
||||
|
||||
expect(await foreignBridge.erc20token()).to.be.equal(ZERO_ADDRESS)
|
||||
expect(await foreignBridge.validatorContract()).to.be.equal(ZERO_ADDRESS)
|
||||
|
@ -37,21 +40,109 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => {
|
|||
expect(await foreignBridge.isInitialized()).to.be.equal(false)
|
||||
expect(await foreignBridge.requiredBlockConfirmations()).to.be.bignumber.equal(ZERO)
|
||||
|
||||
await foreignBridge.initialize(ZERO_ADDRESS, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge.initialize(validatorContract.address, ZERO_ADDRESS, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, 0, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, 0, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge.initialize(validatorContract.address, owner, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge.initialize(owner, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, halfEther, homeMaxPerTx, owner).should.be.rejectedWith(ERROR_MSG);
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
ZERO_ADDRESS,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
validatorContract.address,
|
||||
ZERO_ADDRESS,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
0,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
0,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
validatorContract.address,
|
||||
owner,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
owner,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridge
|
||||
.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
halfEther,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
|
||||
expect(await foreignBridge.erc20token()).to.be.equal(token.address)
|
||||
expect(await foreignBridge.isInitialized()).to.be.equal(true)
|
||||
expect(await foreignBridge.validatorContract()).to.be.equal(validatorContract.address)
|
||||
expect(await foreignBridge.deployedAtBlock()).to.be.bignumber.above(ZERO)
|
||||
expect(await foreignBridge.requiredBlockConfirmations()).to.be.bignumber.equal(requireBlockConfirmations.toString())
|
||||
expect(await foreignBridge.requiredBlockConfirmations()).to.be.bignumber.equal(
|
||||
requireBlockConfirmations.toString()
|
||||
)
|
||||
expect(await foreignBridge.gasPrice()).to.be.bignumber.equal(gasPrice)
|
||||
const bridgeMode = '0x18762d46' // 4 bytes of keccak256('erc-to-native-core')
|
||||
expect(await foreignBridge.getBridgeMode()).to.be.equal(bridgeMode)
|
||||
|
@ -63,62 +154,71 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => {
|
|||
})
|
||||
|
||||
describe('#executeSignatures', async () => {
|
||||
const value = ether('0.25');
|
||||
const value = ether('0.25')
|
||||
let foreignBridge
|
||||
beforeEach(async () => {
|
||||
foreignBridge = await ForeignBridge.new()
|
||||
token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
await token.mint(foreignBridge.address,value);
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
await token.mint(foreignBridge.address, value)
|
||||
})
|
||||
|
||||
it('should allow to executeSignatures', async () => {
|
||||
const recipientAccount = accounts[3];
|
||||
const recipientAccount = accounts[3]
|
||||
const balanceBefore = await token.balanceOf(recipientAccount)
|
||||
|
||||
const transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address);
|
||||
const transactionHash = '0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80'
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
|
||||
const { logs } = await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
|
||||
|
||||
logs[0].event.should.be.equal("RelayedMessage")
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipientAccount)
|
||||
logs[0].args.value.should.be.bignumber.equal(value)
|
||||
const balanceAfter = await token.balanceOf(recipientAccount);
|
||||
const balanceAfterBridge = await token.balanceOf(foreignBridge.address);
|
||||
const balanceAfter = await token.balanceOf(recipientAccount)
|
||||
const balanceAfterBridge = await token.balanceOf(foreignBridge.address)
|
||||
balanceAfter.should.be.bignumber.equal(balanceBefore.add(value))
|
||||
balanceAfterBridge.should.be.bignumber.equal(ZERO)
|
||||
true.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
})
|
||||
|
||||
it('should allow second withdrawal with different transactionHash but same recipient and value', async ()=> {
|
||||
const recipientAccount = accounts[3];
|
||||
it('should allow second withdrawal with different transactionHash but same recipient and value', async () => {
|
||||
const recipientAccount = accounts[3]
|
||||
const balanceBefore = await token.balanceOf(recipientAccount)
|
||||
|
||||
// tx 1
|
||||
const value = ether('0.25');
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address);
|
||||
const value = ether('0.25')
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
|
||||
await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
|
||||
|
||||
// tx 2
|
||||
await token.mint(foreignBridge.address,value);
|
||||
const transactionHash2 = "0x77a496628a776a03d58d7e6059a5937f04bebd8ba4ff89f76dd4bb8ba7e291ee";
|
||||
const message2 = createMessage(recipientAccount, value, transactionHash2, foreignBridge.address);
|
||||
await token.mint(foreignBridge.address, value)
|
||||
const transactionHash2 = '0x77a496628a776a03d58d7e6059a5937f04bebd8ba4ff89f76dd4bb8ba7e291ee'
|
||||
const message2 = createMessage(recipientAccount, value, transactionHash2, foreignBridge.address)
|
||||
const signature2 = await sign(authorities[0], message2)
|
||||
const vrs2 = signatureToVRS(signature2);
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash2))
|
||||
|
||||
const {logs} = await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.fulfilled
|
||||
const { logs } = await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.fulfilled
|
||||
|
||||
logs[0].event.should.be.equal("RelayedMessage")
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipientAccount)
|
||||
logs[0].args.value.should.be.bignumber.equal(value)
|
||||
const balanceAfter = await token.balanceOf(recipientAccount)
|
||||
|
@ -128,114 +228,138 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => {
|
|||
})
|
||||
|
||||
it('should not allow second withdraw (replay attack) with same transactionHash but different recipient', async () => {
|
||||
const recipientAccount = accounts[3];
|
||||
const recipientAccount = accounts[3]
|
||||
|
||||
// tx 1
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address);
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
false.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
|
||||
await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
|
||||
|
||||
// tx 2
|
||||
await token.mint(foreignBridge.address,value);
|
||||
const message2 = createMessage(accounts[4], value, transactionHash, foreignBridge.address);
|
||||
await token.mint(foreignBridge.address, value)
|
||||
const message2 = createMessage(accounts[4], value, transactionHash, foreignBridge.address)
|
||||
const signature2 = await sign(authorities[0], message2)
|
||||
const vrs2 = signatureToVRS(signature2);
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
true.should.be.equal(await foreignBridge.relayedMessages(transactionHash))
|
||||
|
||||
await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
|
||||
it('should not allow withdraw over home max tx limit', async () => {
|
||||
const recipientAccount = accounts[3];
|
||||
const invalidValue = ether('0.75');
|
||||
await token.mint(foreignBridge.address, ether('5'));
|
||||
const recipientAccount = accounts[3]
|
||||
const invalidValue = ether('0.75')
|
||||
await token.mint(foreignBridge.address, ether('5'))
|
||||
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, invalidValue, transactionHash, foreignBridge.address);
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, invalidValue, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
|
||||
await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
|
||||
it('should not allow withdraw over daily home limit', async () => {
|
||||
const recipientAccount = accounts[3];
|
||||
await token.mint(foreignBridge.address, ether('5'));
|
||||
const recipientAccount = accounts[3]
|
||||
await token.mint(foreignBridge.address, ether('5'))
|
||||
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, halfEther, transactionHash, foreignBridge.address);
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, halfEther, transactionHash, foreignBridge.address)
|
||||
const signature = await sign(authorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
|
||||
await foreignBridge.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
|
||||
|
||||
const transactionHash2 = "0x69debd8fd1923c9cb3cd8ef6461e2740b2d037943b941729d5a47671a2bb8712";
|
||||
const message2 = createMessage(recipientAccount, halfEther, transactionHash2, foreignBridge.address);
|
||||
const transactionHash2 = '0x69debd8fd1923c9cb3cd8ef6461e2740b2d037943b941729d5a47671a2bb8712'
|
||||
const message2 = createMessage(recipientAccount, halfEther, transactionHash2, foreignBridge.address)
|
||||
const signature2 = await sign(authorities[0], message2)
|
||||
const vrs2 = signatureToVRS(signature2);
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
|
||||
await foreignBridge.executeSignatures([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.fulfilled
|
||||
|
||||
const transactionHash3 = "0x022695428093bb292db8e48bd1417c5e1b84c0bf673bd0fff23ed0fb6495b872";
|
||||
const message3 = createMessage(recipientAccount, halfEther, transactionHash3, foreignBridge.address);
|
||||
const transactionHash3 = '0x022695428093bb292db8e48bd1417c5e1b84c0bf673bd0fff23ed0fb6495b872'
|
||||
const message3 = createMessage(recipientAccount, halfEther, transactionHash3, foreignBridge.address)
|
||||
const signature3 = await sign(authorities[0], message3)
|
||||
const vrs3 = signatureToVRS(signature3);
|
||||
const vrs3 = signatureToVRS(signature3)
|
||||
|
||||
await foreignBridge.executeSignatures([vrs3.v], [vrs3.r], [vrs3.s], message3).should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#withdraw with 2 minimum signatures', async () => {
|
||||
let multisigValidatorContract, twoAuthorities, ownerOfValidatorContract, foreignBridgeWithMultiSignatures
|
||||
let multisigValidatorContract
|
||||
let twoAuthorities
|
||||
let ownerOfValidatorContract
|
||||
let foreignBridgeWithMultiSignatures
|
||||
const value = halfEther
|
||||
beforeEach(async () => {
|
||||
multisigValidatorContract = await BridgeValidators.new()
|
||||
token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
twoAuthorities = [accounts[0], accounts[1]];
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
twoAuthorities = [accounts[0], accounts[1]]
|
||||
ownerOfValidatorContract = accounts[3]
|
||||
await multisigValidatorContract.initialize(2, twoAuthorities, ownerOfValidatorContract, {from: ownerOfValidatorContract})
|
||||
await multisigValidatorContract.initialize(2, twoAuthorities, ownerOfValidatorContract, {
|
||||
from: ownerOfValidatorContract
|
||||
})
|
||||
foreignBridgeWithMultiSignatures = await ForeignBridge.new()
|
||||
await foreignBridgeWithMultiSignatures.initialize(multisigValidatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner, {from: ownerOfValidatorContract});
|
||||
await token.mint(foreignBridgeWithMultiSignatures.address,value);
|
||||
await foreignBridgeWithMultiSignatures.initialize(
|
||||
multisigValidatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner,
|
||||
{ from: ownerOfValidatorContract }
|
||||
)
|
||||
await token.mint(foreignBridgeWithMultiSignatures.address, value)
|
||||
})
|
||||
|
||||
it('withdraw should fail if not enough signatures are provided', async () => {
|
||||
const recipientAccount = accounts[4];
|
||||
const recipientAccount = accounts[4]
|
||||
|
||||
// msg 1
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridgeWithMultiSignatures.address);
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridgeWithMultiSignatures.address)
|
||||
const signature = await sign(twoAuthorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
false.should.be.equal(await foreignBridgeWithMultiSignatures.relayedMessages(transactionHash))
|
||||
|
||||
await foreignBridgeWithMultiSignatures.executeSignatures([vrs.v], [vrs.r], [vrs.s], message).should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridgeWithMultiSignatures
|
||||
.executeSignatures([vrs.v], [vrs.r], [vrs.s], message)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
// msg 2
|
||||
const signature2 = await sign(twoAuthorities[1], message)
|
||||
const vrs2 = signatureToVRS(signature2);
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
|
||||
const {logs} = await foreignBridgeWithMultiSignatures.executeSignatures([vrs.v, vrs2.v], [vrs.r, vrs2.r], [vrs.s, vrs2.s], message).should.be.fulfilled;
|
||||
const { logs } = await foreignBridgeWithMultiSignatures.executeSignatures(
|
||||
[vrs.v, vrs2.v],
|
||||
[vrs.r, vrs2.r],
|
||||
[vrs.s, vrs2.s],
|
||||
message
|
||||
).should.be.fulfilled
|
||||
|
||||
logs[0].event.should.be.equal("RelayedMessage")
|
||||
logs[0].event.should.be.equal('RelayedMessage')
|
||||
logs[0].args.recipient.should.be.equal(recipientAccount)
|
||||
logs[0].args.value.should.be.bignumber.equal(value)
|
||||
true.should.be.equal(await foreignBridgeWithMultiSignatures.relayedMessages(transactionHash))
|
||||
})
|
||||
|
||||
it('withdraw should fail if duplicate signature is provided', async () => {
|
||||
const recipientAccount = accounts[4];
|
||||
const transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridgeWithMultiSignatures.address);
|
||||
const recipientAccount = accounts[4]
|
||||
const transactionHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipientAccount, value, transactionHash, foreignBridgeWithMultiSignatures.address)
|
||||
const signature = await sign(twoAuthorities[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
false.should.be.equal(await foreignBridgeWithMultiSignatures.relayedMessages(transactionHash))
|
||||
|
||||
await foreignBridgeWithMultiSignatures.executeSignatures([vrs.v, vrs.v], [vrs.r, vrs.r], [vrs.s, vrs.s], message).should.be.rejectedWith(ERROR_MSG)
|
||||
await foreignBridgeWithMultiSignatures
|
||||
.executeSignatures([vrs.v, vrs.v], [vrs.r, vrs.r], [vrs.s, vrs.s], message)
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
it('works with 5 validators and 3 required signatures', async () => {
|
||||
const recipient = accounts[8]
|
||||
|
@ -243,31 +367,44 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => {
|
|||
const ownerOfValidators = accounts[0]
|
||||
const validatorContractWith3Signatures = await BridgeValidators.new()
|
||||
await validatorContractWith3Signatures.initialize(3, authoritiesFiveAccs, ownerOfValidators)
|
||||
const erc20Token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
const erc20Token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
const value = halfEther
|
||||
const foreignBridgeWithThreeSigs = await ForeignBridge.new()
|
||||
|
||||
await foreignBridgeWithThreeSigs.initialize(validatorContractWith3Signatures.address, erc20Token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
await erc20Token.mint(foreignBridgeWithThreeSigs.address, value);
|
||||
await foreignBridgeWithThreeSigs.initialize(
|
||||
validatorContractWith3Signatures.address,
|
||||
erc20Token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
await erc20Token.mint(foreignBridgeWithThreeSigs.address, value)
|
||||
|
||||
const txHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
|
||||
const message = createMessage(recipient, value, txHash, foreignBridgeWithThreeSigs.address);
|
||||
const txHash = '0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121'
|
||||
const message = createMessage(recipient, value, txHash, foreignBridgeWithThreeSigs.address)
|
||||
|
||||
// signature 1
|
||||
const signature = await sign(authoritiesFiveAccs[0], message)
|
||||
const vrs = signatureToVRS(signature);
|
||||
const vrs = signatureToVRS(signature)
|
||||
|
||||
// signature 2
|
||||
const signature2 = await sign(authoritiesFiveAccs[1], message)
|
||||
const vrs2 = signatureToVRS(signature2);
|
||||
const vrs2 = signatureToVRS(signature2)
|
||||
|
||||
// signature 3
|
||||
const signature3 = await sign(authoritiesFiveAccs[2], message)
|
||||
const vrs3 = signatureToVRS(signature3);
|
||||
const vrs3 = signatureToVRS(signature3)
|
||||
|
||||
|
||||
const {logs} = await foreignBridgeWithThreeSigs.executeSignatures([vrs.v, vrs2.v, vrs3.v], [vrs.r, vrs2.r, vrs3.r], [vrs.s, vrs2.s, vrs3.s], message).should.be.fulfilled;
|
||||
logs[0].event.should.be.equal("RelayedMessage")
|
||||
const { logs } = await foreignBridgeWithThreeSigs.executeSignatures(
|
||||
[vrs.v, vrs2.v, vrs3.v],
|
||||
[vrs.r, vrs2.r, vrs3.r],
|
||||
[vrs.s, vrs2.s, vrs3.s],
|
||||
message
|
||||
).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(value)
|
||||
true.should.be.equal(await foreignBridgeWithThreeSigs.relayedMessages(txHash))
|
||||
|
@ -278,30 +415,39 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => {
|
|||
it('can be upgraded', async () => {
|
||||
const REQUIRED_NUMBER_OF_VALIDATORS = 1
|
||||
const VALIDATORS = [accounts[1]]
|
||||
const PROXY_OWNER = accounts[0]
|
||||
const PROXY_OWNER = accounts[0]
|
||||
// Validators Contract
|
||||
let validatorsProxy = await EternalStorageProxy.new().should.be.fulfilled;
|
||||
const validatorsContractImpl = await BridgeValidators.new().should.be.fulfilled;
|
||||
await validatorsProxy.upgradeTo('1', validatorsContractImpl.address).should.be.fulfilled;
|
||||
let validatorsProxy = await EternalStorageProxy.new().should.be.fulfilled
|
||||
const validatorsContractImpl = await BridgeValidators.new().should.be.fulfilled
|
||||
await validatorsProxy.upgradeTo('1', validatorsContractImpl.address).should.be.fulfilled
|
||||
validatorsContractImpl.address.should.be.equal(await validatorsProxy.implementation())
|
||||
|
||||
validatorsProxy = await BridgeValidators.at(validatorsProxy.address);
|
||||
await validatorsProxy.initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, PROXY_OWNER).should.be.fulfilled;
|
||||
let token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
validatorsProxy = await BridgeValidators.at(validatorsProxy.address)
|
||||
await validatorsProxy.initialize(REQUIRED_NUMBER_OF_VALIDATORS, VALIDATORS, PROXY_OWNER).should.be.fulfilled
|
||||
const token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
|
||||
// ForeignBridge V1 Contract
|
||||
|
||||
let foreignBridgeProxy = await EternalStorageProxy.new().should.be.fulfilled;
|
||||
const foreignBridgeImpl = await ForeignBridge.new().should.be.fulfilled;
|
||||
await foreignBridgeProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled;
|
||||
let foreignBridgeProxy = await EternalStorageProxy.new().should.be.fulfilled
|
||||
const foreignBridgeImpl = await ForeignBridge.new().should.be.fulfilled
|
||||
await foreignBridgeProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled
|
||||
|
||||
foreignBridgeProxy = await ForeignBridge.at(foreignBridgeProxy.address);
|
||||
await foreignBridgeProxy.initialize(validatorsProxy.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner)
|
||||
foreignBridgeProxy = await ForeignBridge.at(foreignBridgeProxy.address)
|
||||
await foreignBridgeProxy.initialize(
|
||||
validatorsProxy.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
|
||||
// Deploy V2
|
||||
let foreignImplV2 = await ForeignBridgeV2.new();
|
||||
let foreignBridgeProxyUpgrade = await EternalStorageProxy.at(foreignBridgeProxy.address);
|
||||
await foreignBridgeProxyUpgrade.upgradeTo('2', foreignImplV2.address).should.be.fulfilled;
|
||||
const foreignImplV2 = await ForeignBridgeV2.new()
|
||||
const foreignBridgeProxyUpgrade = await EternalStorageProxy.at(foreignBridgeProxy.address)
|
||||
await foreignBridgeProxyUpgrade.upgradeTo('2', foreignImplV2.address).should.be.fulfilled
|
||||
foreignImplV2.address.should.be.equal(await foreignBridgeProxyUpgrade.implementation())
|
||||
})
|
||||
|
||||
|
@ -309,38 +455,49 @@ contract('ForeignBridge_ERC20_to_Native', async (accounts) => {
|
|||
const tokenAddress = token.address
|
||||
const validatorsAddress = validatorContract.address
|
||||
|
||||
const storageProxy = await EternalStorageProxy.new().should.be.fulfilled;
|
||||
const foreignBridge = await ForeignBridge.new();
|
||||
const data = foreignBridge.contract.methods.initialize(validatorsAddress, tokenAddress, requireBlockConfirmations, gasPrice, '2', '3', '2', owner).encodeABI()
|
||||
const storageProxy = await EternalStorageProxy.new().should.be.fulfilled
|
||||
const foreignBridge = await ForeignBridge.new()
|
||||
const data = foreignBridge.contract.methods
|
||||
.initialize(validatorsAddress, tokenAddress, requireBlockConfirmations, gasPrice, '2', '3', '2', owner)
|
||||
.encodeABI()
|
||||
|
||||
await storageProxy.upgradeToAndCall('1', foreignBridge.address, data).should.be.fulfilled;
|
||||
await storageProxy.upgradeToAndCall('1', foreignBridge.address, data).should.be.fulfilled
|
||||
|
||||
let finalContract = await ForeignBridge.at(storageProxy.address);
|
||||
true.should.be.equal(await finalContract.isInitialized());
|
||||
const finalContract = await ForeignBridge.at(storageProxy.address)
|
||||
true.should.be.equal(await finalContract.isInitialized())
|
||||
validatorsAddress.should.be.equal(await finalContract.validatorContract())
|
||||
})
|
||||
})
|
||||
|
||||
describe('#claimTokens', async () => {
|
||||
it('can send erc20', async () => {
|
||||
const owner = accounts[0];
|
||||
token = await ERC677BridgeToken.new("Some ERC20", "RSZT", 18);
|
||||
const foreignBridgeImpl = await ForeignBridge.new();
|
||||
const storageProxy = await EternalStorageProxy.new().should.be.fulfilled;
|
||||
const owner = accounts[0]
|
||||
token = await ERC677BridgeToken.new('Some ERC20', 'RSZT', 18)
|
||||
const foreignBridgeImpl = await ForeignBridge.new()
|
||||
const storageProxy = await EternalStorageProxy.new().should.be.fulfilled
|
||||
await storageProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled
|
||||
const foreignBridge = await ForeignBridge.at(storageProxy.address);
|
||||
const foreignBridge = await ForeignBridge.at(storageProxy.address)
|
||||
|
||||
await foreignBridge.initialize(validatorContract.address, token.address, requireBlockConfirmations, gasPrice, maxPerTx, homeDailyLimit, homeMaxPerTx, owner);
|
||||
const tokenSecond = await ERC677BridgeToken.new("Roman Token", "RST", 18);
|
||||
await foreignBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
requireBlockConfirmations,
|
||||
gasPrice,
|
||||
maxPerTx,
|
||||
homeDailyLimit,
|
||||
homeMaxPerTx,
|
||||
owner
|
||||
)
|
||||
const tokenSecond = await ERC677BridgeToken.new('Roman Token', 'RST', 18)
|
||||
|
||||
await tokenSecond.mint(accounts[0], halfEther).should.be.fulfilled;
|
||||
await tokenSecond.mint(accounts[0], halfEther).should.be.fulfilled
|
||||
expect(await tokenSecond.balanceOf(accounts[0])).to.be.bignumber.equal(halfEther)
|
||||
|
||||
await tokenSecond.transfer(foreignBridge.address, halfEther);
|
||||
await tokenSecond.transfer(foreignBridge.address, halfEther)
|
||||
expect(await tokenSecond.balanceOf(accounts[0])).to.be.bignumber.equal(ZERO)
|
||||
expect(await tokenSecond.balanceOf(foreignBridge.address)).to.be.bignumber.equal(halfEther)
|
||||
|
||||
await foreignBridge.claimTokens(tokenSecond.address, accounts[3], {from: owner});
|
||||
await foreignBridge.claimTokens(tokenSecond.address, accounts[3], { from: owner })
|
||||
expect(await tokenSecond.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO)
|
||||
expect(await tokenSecond.balanceOf(accounts[3])).to.be.bignumber.equal(halfEther)
|
||||
})
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,164 +1,164 @@
|
|||
const { BN } = require('../setup');
|
||||
const { expect } = require('chai');
|
||||
const { expect } = require('chai')
|
||||
const { BN } = require('../setup')
|
||||
|
||||
// returns a Promise that resolves with a hex string that is the signature of
|
||||
// `data` signed with the key of `address`
|
||||
function sign(address, data) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
web3.eth.sign(data, address, function(err, result) {
|
||||
return new Promise((resolve, reject) => {
|
||||
web3.eth.sign(data, address, (err, result) => {
|
||||
if (err !== null) {
|
||||
return reject(err);
|
||||
} else {
|
||||
return resolve(normalizeSignature(result));
|
||||
//return resolve(result);
|
||||
return reject(err)
|
||||
}
|
||||
return resolve(normalizeSignature(result))
|
||||
// return resolve(result);
|
||||
})
|
||||
})
|
||||
}
|
||||
module.exports.sign = sign;
|
||||
module.exports.sign = sign
|
||||
|
||||
// geth && testrpc has different output of eth_sign than parity
|
||||
// https://github.com/ethereumjs/testrpc/issues/243#issuecomment-326750236
|
||||
function normalizeSignature(signature) {
|
||||
signature = strip0x(signature);
|
||||
function normalizeSignature(rawSignature) {
|
||||
const signature = strip0x(rawSignature)
|
||||
|
||||
// increase v by 27...
|
||||
return "0x" + signature.substr(0, 128) + (parseInt(signature.substr(128), 16) + 27).toString(16);
|
||||
return `0x${signature.substr(0, 128)}${(parseInt(signature.substr(128), 16) + 27).toString(16)}`
|
||||
}
|
||||
module.exports.normalizeSignature = normalizeSignature;
|
||||
module.exports.normalizeSignature = normalizeSignature
|
||||
|
||||
// strips leading "0x" if present
|
||||
function strip0x(input) {
|
||||
return input.replace(/^0x/, "");
|
||||
return input.replace(/^0x/, '')
|
||||
}
|
||||
module.exports.strip0x = strip0x;
|
||||
module.exports.strip0x = strip0x
|
||||
|
||||
// extracts and returns the `v`, `r` and `s` values from a `signature`.
|
||||
// all inputs and outputs are hex strings with leading '0x'.
|
||||
function signatureToVRS(signature) {
|
||||
assert.equal(signature.length, 2 + 32 * 2 + 32 * 2 + 2);
|
||||
signature = strip0x(signature);
|
||||
var v = parseInt(signature.substr(64 * 2), 16);
|
||||
var r = "0x" + signature.substr(0, 32 * 2);
|
||||
var s = "0x" + signature.substr(32 * 2, 32 * 2);
|
||||
return {v: v, r: r, s: s};
|
||||
function signatureToVRS(rawSignature) {
|
||||
assert.equal(rawSignature.length, 2 + 32 * 2 + 32 * 2 + 2)
|
||||
const signature = strip0x(rawSignature)
|
||||
const v = parseInt(signature.substr(64 * 2), 16)
|
||||
const r = `0x${signature.substr(0, 32 * 2)}`
|
||||
const s = `0x${signature.substr(32 * 2, 32 * 2)}`
|
||||
return { v, r, s }
|
||||
}
|
||||
module.exports.signatureToVRS = signatureToVRS;
|
||||
module.exports.signatureToVRS = signatureToVRS
|
||||
|
||||
// returns BigNumber `num` converted to a little endian hex string
|
||||
// that is exactly 32 bytes long.
|
||||
// `num` must represent an unsigned integer
|
||||
function bigNumberToPaddedBytes32(num) {
|
||||
var result = strip0x(num.toString(16));
|
||||
let result = strip0x(num.toString(16))
|
||||
while (result.length < 64) {
|
||||
result = "0" + result;
|
||||
result = `0${result}`
|
||||
}
|
||||
return "0x" + result;
|
||||
return `0x${result}`
|
||||
}
|
||||
module.exports.bigNumberToPaddedBytes32 = bigNumberToPaddedBytes32;
|
||||
module.exports.bigNumberToPaddedBytes32 = bigNumberToPaddedBytes32
|
||||
|
||||
// returns an promise that resolves to an object
|
||||
// that maps `addresses` to their current balances
|
||||
function getBalances(addresses) {
|
||||
return Promise.all(addresses.map(function(address) {
|
||||
return web3.eth.getBalance(address);
|
||||
})).then(function(balancesArray) {
|
||||
let addressToBalance = {};
|
||||
addresses.forEach(function(address, index) {
|
||||
addressToBalance[address] = balancesArray[index];
|
||||
});
|
||||
return addressToBalance;
|
||||
return Promise.all(
|
||||
addresses.map(address => {
|
||||
return web3.eth.getBalance(address)
|
||||
})
|
||||
).then(balancesArray => {
|
||||
const addressToBalance = {}
|
||||
addresses.forEach((address, index) => {
|
||||
addressToBalance[address] = balancesArray[index]
|
||||
})
|
||||
return addressToBalance
|
||||
})
|
||||
}
|
||||
module.exports.getBalances = getBalances;
|
||||
|
||||
module.exports.getBalances = getBalances
|
||||
|
||||
// returns hex string of the bytes of the message
|
||||
// composed from `recipient`, `value` and `transactionHash`
|
||||
// that is relayed from `foreign` to `home` on withdraw
|
||||
function createMessage(recipient, value, transactionHash, contractAddress) {
|
||||
recipient = strip0x(recipient);
|
||||
assert.equal(recipient.length, 20 * 2);
|
||||
function createMessage(rawRecipient, rawValue, rawTransactionHash, rawContractAddress) {
|
||||
const recipient = strip0x(rawRecipient)
|
||||
assert.equal(recipient.length, 20 * 2)
|
||||
|
||||
var value = strip0x(bigNumberToPaddedBytes32(value));
|
||||
assert.equal(value.length, 64);
|
||||
const value = strip0x(bigNumberToPaddedBytes32(rawValue))
|
||||
assert.equal(value.length, 64)
|
||||
|
||||
transactionHash = strip0x(transactionHash);
|
||||
assert.equal(transactionHash.length, 32 * 2);
|
||||
const transactionHash = strip0x(rawTransactionHash)
|
||||
assert.equal(transactionHash.length, 32 * 2)
|
||||
|
||||
contractAddress = strip0x(contractAddress);
|
||||
assert.equal(contractAddress.length, 20 * 2);
|
||||
const contractAddress = strip0x(rawContractAddress)
|
||||
assert.equal(contractAddress.length, 20 * 2)
|
||||
|
||||
var message = "0x" + recipient + value + transactionHash + contractAddress;
|
||||
var expectedMessageLength = (20 + 32 + 32 + 20) * 2 + 2;
|
||||
assert.equal(message.length, expectedMessageLength);
|
||||
return message;
|
||||
const message = `0x${recipient}${value}${transactionHash}${contractAddress}`
|
||||
const expectedMessageLength = (20 + 32 + 32 + 20) * 2 + 2
|
||||
assert.equal(message.length, expectedMessageLength)
|
||||
return message
|
||||
}
|
||||
module.exports.createMessage = createMessage;
|
||||
module.exports.createMessage = createMessage
|
||||
|
||||
// returns array of integers progressing from `start` up to, but not including, `end`
|
||||
function range(start, end) {
|
||||
var result = [];
|
||||
for (var i = start; i < end; i++) {
|
||||
result.push(i);
|
||||
const result = []
|
||||
for (let i = start; i < end; i++) {
|
||||
result.push(i)
|
||||
}
|
||||
return result;
|
||||
return result
|
||||
}
|
||||
module.exports.range = range;
|
||||
module.exports.range = range
|
||||
|
||||
// just used to signal/document that we're explicitely ignoring/expecting an error
|
||||
function ignoreExpectedError() {
|
||||
}
|
||||
module.exports.ignoreExpectedError = ignoreExpectedError;
|
||||
function ignoreExpectedError() {}
|
||||
module.exports.ignoreExpectedError = ignoreExpectedError
|
||||
|
||||
const getEvents = (truffleInstance, filter, fromBlock = 0, toBlock = 'latest') => truffleInstance.contract.getPastEvents(filter.event, { fromBlock, toBlock })
|
||||
const getEvents = (truffleInstance, filter, fromBlock = 0, toBlock = 'latest') =>
|
||||
truffleInstance.contract.getPastEvents(filter.event, { fromBlock, toBlock })
|
||||
|
||||
module.exports.getEvents = getEvents;
|
||||
module.exports.getEvents = getEvents
|
||||
|
||||
function ether (n) {
|
||||
return new BN(web3.utils.toWei(n, 'ether'));
|
||||
function ether(n) {
|
||||
return new BN(web3.utils.toWei(n, 'ether'))
|
||||
}
|
||||
|
||||
module.exports.ether = ether;
|
||||
module.exports.ether = ether
|
||||
|
||||
function expectEventInLogs (logs, eventName, eventArgs = {}) {
|
||||
const events = logs.filter(e => e.event === eventName);
|
||||
expect(events.length > 0).to.equal(true, `There is no '${eventName}'`);
|
||||
function expectEventInLogs(logs, eventName, eventArgs = {}) {
|
||||
const events = logs.filter(e => e.event === eventName)
|
||||
expect(events.length > 0).to.equal(true, `There is no '${eventName}'`)
|
||||
|
||||
const exception = [];
|
||||
const event = events.find(function (e) {
|
||||
const exception = []
|
||||
const event = events.find(e => {
|
||||
for (const [k, v] of Object.entries(eventArgs)) {
|
||||
try {
|
||||
contains(e.args, k, v);
|
||||
contains(e.args, k, v)
|
||||
} catch (error) {
|
||||
exception.push(error);
|
||||
return false;
|
||||
exception.push(error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return true
|
||||
})
|
||||
|
||||
if (event === undefined) {
|
||||
throw exception[0];
|
||||
throw exception[0]
|
||||
}
|
||||
|
||||
return event;
|
||||
return event
|
||||
}
|
||||
|
||||
function contains (args, key, value) {
|
||||
expect(key in args).to.equal(true, `Unknown event argument '${key}'`);
|
||||
function contains(args, key, value) {
|
||||
expect(key in args).to.equal(true, `Unknown event argument '${key}'`)
|
||||
|
||||
if (value === null) {
|
||||
expect(args[key]).to.equal(null);
|
||||
expect(args[key]).to.equal(null)
|
||||
} else if (isBN(args[key])) {
|
||||
expect(args[key]).to.be.bignumber.equal(value);
|
||||
expect(args[key]).to.be.bignumber.equal(value)
|
||||
} else {
|
||||
expect(args[key]).to.be.equal(value);
|
||||
expect(args[key]).to.be.equal(value)
|
||||
}
|
||||
}
|
||||
|
||||
function isBN (object) {
|
||||
return BN.isBN(object) || object instanceof BN;
|
||||
function isBN(object) {
|
||||
return BN.isBN(object) || object instanceof BN
|
||||
}
|
||||
|
||||
module.exports.expectEventInLogs = expectEventInLogs;
|
||||
module.exports.expectEventInLogs = expectEventInLogs
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,18 +1,18 @@
|
|||
const POA20 = artifacts.require("ERC677BridgeToken.sol");
|
||||
const POA20RewardableMock = artifacts.require("./mockContracts/ERC677BridgeTokenRewardableMock");
|
||||
const ERC677ReceiverTest = artifacts.require("ERC677ReceiverTest.sol")
|
||||
const BlockRewardTest = artifacts.require("BlockReward.sol")
|
||||
const StakingTest = artifacts.require("Staking.sol")
|
||||
const HomeErcToErcBridge = artifacts.require("HomeBridgeErcToErc.sol");
|
||||
const ForeignNativeToErcBridge = artifacts.require("ForeignBridgeNativeToErc.sol");
|
||||
const BridgeValidators = artifacts.require("BridgeValidators.sol");
|
||||
const POA20 = artifacts.require('ERC677BridgeToken.sol')
|
||||
const POA20RewardableMock = artifacts.require('./mockContracts/ERC677BridgeTokenRewardableMock')
|
||||
const ERC677ReceiverTest = artifacts.require('ERC677ReceiverTest.sol')
|
||||
const BlockRewardTest = artifacts.require('BlockReward.sol')
|
||||
const StakingTest = artifacts.require('Staking.sol')
|
||||
const HomeErcToErcBridge = artifacts.require('HomeBridgeErcToErc.sol')
|
||||
const ForeignNativeToErcBridge = artifacts.require('ForeignBridgeNativeToErc.sol')
|
||||
const BridgeValidators = artifacts.require('BridgeValidators.sol')
|
||||
|
||||
const { ERROR_MSG, ZERO_ADDRESS, BN } = require('./setup');
|
||||
const { ether, expectEventInLogs } = require('./helpers/helpers');
|
||||
const { expect } = require('chai');
|
||||
const { expect } = require('chai')
|
||||
const { ERROR_MSG, ZERO_ADDRESS, BN } = require('./setup')
|
||||
const { ether, expectEventInLogs } = require('./helpers/helpers')
|
||||
|
||||
const minPerTx = ether('0.01')
|
||||
const requireBlockConfirmations = 8;
|
||||
const requireBlockConfirmations = 8
|
||||
const gasPrice = web3.utils.toWei('1', 'gwei')
|
||||
const oneEther = ether('1')
|
||||
const halfEther = ether('0.5')
|
||||
|
@ -22,11 +22,11 @@ const ZERO = new BN(0)
|
|||
|
||||
async function testERC677BridgeToken(accounts, rewardable) {
|
||||
let token
|
||||
let owner = accounts[0]
|
||||
const user = accounts[1];
|
||||
const tokenContract = rewardable ? POA20RewardableMock : POA20;
|
||||
const owner = accounts[0]
|
||||
const user = accounts[1]
|
||||
const tokenContract = rewardable ? POA20RewardableMock : POA20
|
||||
beforeEach(async () => {
|
||||
token = await tokenContract.new("POA ERC20 Foundation", "POA20", 18);
|
||||
token = await tokenContract.new('POA ERC20 Foundation', 'POA20', 18)
|
||||
})
|
||||
it('default values', async () => {
|
||||
expect(await token.symbol()).to.be.equal('POA20')
|
||||
|
@ -41,199 +41,198 @@ async function testERC677BridgeToken(accounts, rewardable) {
|
|||
expect(patch).to.be.bignumber.gte(ZERO)
|
||||
})
|
||||
|
||||
describe('#bridgeContract', async() => {
|
||||
describe('#bridgeContract', async () => {
|
||||
it('can set bridge contract', async () => {
|
||||
const homeErcToErcContract = await HomeErcToErcBridge.new();
|
||||
(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS);
|
||||
const homeErcToErcContract = await HomeErcToErcBridge.new()
|
||||
;(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled;
|
||||
|
||||
(await token.bridgeContract()).should.be.equal(homeErcToErcContract.address);
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled
|
||||
;(await token.bridgeContract()).should.be.equal(homeErcToErcContract.address)
|
||||
})
|
||||
|
||||
it('only owner can set bridge contract', async () => {
|
||||
const homeErcToErcContract = await HomeErcToErcBridge.new();
|
||||
(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS);
|
||||
const homeErcToErcContract = await HomeErcToErcBridge.new()
|
||||
;(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setBridgeContract(homeErcToErcContract.address, {from: user }).should.be.rejectedWith(ERROR_MSG);
|
||||
(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS);
|
||||
await token.setBridgeContract(homeErcToErcContract.address, { from: user }).should.be.rejectedWith(ERROR_MSG)
|
||||
;(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setBridgeContract(homeErcToErcContract.address, {from: owner }).should.be.fulfilled;
|
||||
(await token.bridgeContract()).should.be.equal(homeErcToErcContract.address);
|
||||
await token.setBridgeContract(homeErcToErcContract.address, { from: owner }).should.be.fulfilled
|
||||
;(await token.bridgeContract()).should.be.equal(homeErcToErcContract.address)
|
||||
})
|
||||
|
||||
it('fail to set invalid bridge contract address', async () => {
|
||||
const invalidContractAddress = '0xaaB52d66283F7A1D5978bcFcB55721ACB467384b';
|
||||
(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS);
|
||||
const invalidContractAddress = '0xaaB52d66283F7A1D5978bcFcB55721ACB467384b'
|
||||
;(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setBridgeContract(invalidContractAddress).should.be.rejectedWith(ERROR_MSG);
|
||||
(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS);
|
||||
await token.setBridgeContract(invalidContractAddress).should.be.rejectedWith(ERROR_MSG)
|
||||
;(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setBridgeContract(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG);
|
||||
(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS);
|
||||
await token.setBridgeContract(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG)
|
||||
;(await token.bridgeContract()).should.be.equal(ZERO_ADDRESS)
|
||||
})
|
||||
})
|
||||
|
||||
if (rewardable) {
|
||||
describe('#blockRewardContract', async() => {
|
||||
describe('#blockRewardContract', async () => {
|
||||
it('can set BlockReward contract', async () => {
|
||||
const blockRewardContract = await BlockRewardTest.new();
|
||||
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
|
||||
const blockRewardContract = await BlockRewardTest.new()
|
||||
;(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setBlockRewardContract(blockRewardContract.address).should.be.fulfilled;
|
||||
|
||||
(await token.blockRewardContract()).should.be.equal(blockRewardContract.address);
|
||||
await token.setBlockRewardContract(blockRewardContract.address).should.be.fulfilled
|
||||
;(await token.blockRewardContract()).should.be.equal(blockRewardContract.address)
|
||||
})
|
||||
|
||||
it('only owner can set BlockReward contract', async () => {
|
||||
const blockRewardContract = await BlockRewardTest.new();
|
||||
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
|
||||
const blockRewardContract = await BlockRewardTest.new()
|
||||
;(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setBlockRewardContract(blockRewardContract.address, {from: user }).should.be.rejectedWith(ERROR_MSG);
|
||||
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
|
||||
await token
|
||||
.setBlockRewardContract(blockRewardContract.address, { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
;(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setBlockRewardContract(blockRewardContract.address, {from: owner }).should.be.fulfilled;
|
||||
(await token.blockRewardContract()).should.be.equal(blockRewardContract.address);
|
||||
await token.setBlockRewardContract(blockRewardContract.address, { from: owner }).should.be.fulfilled
|
||||
;(await token.blockRewardContract()).should.be.equal(blockRewardContract.address)
|
||||
})
|
||||
|
||||
it('fail to set invalid BlockReward contract address', async () => {
|
||||
const invalidContractAddress = '0xaaB52d66283F7A1D5978bcFcB55721ACB467384b';
|
||||
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
|
||||
const invalidContractAddress = '0xaaB52d66283F7A1D5978bcFcB55721ACB467384b'
|
||||
;(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setBlockRewardContract(invalidContractAddress).should.be.rejectedWith(ERROR_MSG);
|
||||
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
|
||||
await token.setBlockRewardContract(invalidContractAddress).should.be.rejectedWith(ERROR_MSG)
|
||||
;(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setBlockRewardContract(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG);
|
||||
(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS);
|
||||
await token.setBlockRewardContract(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG)
|
||||
;(await token.blockRewardContract()).should.be.equal(ZERO_ADDRESS)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#stakingContract', async() => {
|
||||
describe('#stakingContract', async () => {
|
||||
it('can set Staking contract', async () => {
|
||||
const stakingContract = await StakingTest.new();
|
||||
(await token.stakingContract()).should.be.equal(ZERO_ADDRESS);
|
||||
const stakingContract = await StakingTest.new()
|
||||
;(await token.stakingContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setStakingContract(stakingContract.address).should.be.fulfilled;
|
||||
|
||||
(await token.stakingContract()).should.be.equal(stakingContract.address);
|
||||
await token.setStakingContract(stakingContract.address).should.be.fulfilled
|
||||
;(await token.stakingContract()).should.be.equal(stakingContract.address)
|
||||
})
|
||||
|
||||
it('only owner can set Staking contract', async () => {
|
||||
const stakingContract = await StakingTest.new();
|
||||
(await token.stakingContract()).should.be.equal(ZERO_ADDRESS);
|
||||
const stakingContract = await StakingTest.new()
|
||||
;(await token.stakingContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setStakingContract(stakingContract.address, {from: user }).should.be.rejectedWith(ERROR_MSG);
|
||||
(await token.stakingContract()).should.be.equal(ZERO_ADDRESS);
|
||||
await token.setStakingContract(stakingContract.address, { from: user }).should.be.rejectedWith(ERROR_MSG)
|
||||
;(await token.stakingContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setStakingContract(stakingContract.address, {from: owner }).should.be.fulfilled;
|
||||
(await token.stakingContract()).should.be.equal(stakingContract.address);
|
||||
await token.setStakingContract(stakingContract.address, { from: owner }).should.be.fulfilled
|
||||
;(await token.stakingContract()).should.be.equal(stakingContract.address)
|
||||
})
|
||||
|
||||
it('fail to set invalid Staking contract address', async () => {
|
||||
const invalidContractAddress = '0xaaB52d66283F7A1D5978bcFcB55721ACB467384b';
|
||||
(await token.stakingContract()).should.be.equal(ZERO_ADDRESS);
|
||||
const invalidContractAddress = '0xaaB52d66283F7A1D5978bcFcB55721ACB467384b'
|
||||
;(await token.stakingContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setStakingContract(invalidContractAddress).should.be.rejectedWith(ERROR_MSG);
|
||||
(await token.stakingContract()).should.be.equal(ZERO_ADDRESS);
|
||||
await token.setStakingContract(invalidContractAddress).should.be.rejectedWith(ERROR_MSG)
|
||||
;(await token.stakingContract()).should.be.equal(ZERO_ADDRESS)
|
||||
|
||||
await token.setStakingContract(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG);
|
||||
(await token.stakingContract()).should.be.equal(ZERO_ADDRESS);
|
||||
await token.setStakingContract(ZERO_ADDRESS).should.be.rejectedWith(ERROR_MSG)
|
||||
;(await token.stakingContract()).should.be.equal(ZERO_ADDRESS)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#mintReward', async() => {
|
||||
describe('#mintReward', async () => {
|
||||
it('can only be called by BlockReward contract', async () => {
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
|
||||
await token.mintReward([], [], {from: user }).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.mintReward([], [], {from: accounts[2] }).should.be.fulfilled;
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled
|
||||
await token.mintReward([], [], { from: user }).should.be.rejectedWith(ERROR_MSG)
|
||||
await token.mintReward([], [], { from: accounts[2] }).should.be.fulfilled
|
||||
})
|
||||
it('should increase totalSupply and balances', async () => {
|
||||
const user1 = accounts[1];
|
||||
const user2 = accounts[2];
|
||||
const user3 = accounts[3];
|
||||
const user1 = accounts[1]
|
||||
const user2 = accounts[2]
|
||||
const user3 = accounts[3]
|
||||
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO);
|
||||
expect(await token.balanceOf(user1)).to.be.bignumber.equal(ZERO);
|
||||
expect(await token.balanceOf(user2)).to.be.bignumber.equal(ZERO);
|
||||
expect(await token.balanceOf(user3)).to.be.bignumber.equal(ZERO);
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(user1)).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(user2)).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(user3)).to.be.bignumber.equal(ZERO)
|
||||
|
||||
await token.setBlockRewardContractMock(accounts[4]).should.be.fulfilled;
|
||||
await token.mintReward([user1, user2, user3], [100, 200, 300], {from: accounts[4] }).should.be.fulfilled;
|
||||
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal('600');
|
||||
expect(await token.balanceOf(user1)).to.be.bignumber.equal('100');
|
||||
expect(await token.balanceOf(user2)).to.be.bignumber.equal('200');
|
||||
expect(await token.balanceOf(user3)).to.be.bignumber.equal('300');
|
||||
await token.setBlockRewardContractMock(accounts[4]).should.be.fulfilled
|
||||
await token.mintReward([user1, user2, user3], [100, 200, 300], { from: accounts[4] }).should.be.fulfilled
|
||||
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal('600')
|
||||
expect(await token.balanceOf(user1)).to.be.bignumber.equal('100')
|
||||
expect(await token.balanceOf(user2)).to.be.bignumber.equal('200')
|
||||
expect(await token.balanceOf(user3)).to.be.bignumber.equal('300')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#stake', async() => {
|
||||
describe('#stake', async () => {
|
||||
it('can only be called by Staking contract', async () => {
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
|
||||
await token.mintReward([user], ['100'], {from: accounts[2] }).should.be.fulfilled;
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled;
|
||||
await token.stake(user, '100', {from: accounts[4] }).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.stake(user, '100', {from: accounts[3] }).should.be.fulfilled;
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled
|
||||
await token.mintReward([user], ['100'], { from: accounts[2] }).should.be.fulfilled
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled
|
||||
await token.stake(user, '100', { from: accounts[4] }).should.be.rejectedWith(ERROR_MSG)
|
||||
await token.stake(user, '100', { from: accounts[3] }).should.be.fulfilled
|
||||
})
|
||||
it('should revert if user doesn\'t have enough balance', async () => {
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
|
||||
await token.mintReward([user], ['99'], {from: accounts[2] }).should.be.fulfilled;
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('99');
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled;
|
||||
await token.stake(user, '100', {from: accounts[3] }).should.be.rejectedWith(ERROR_MSG);
|
||||
it("should revert if user doesn't have enough balance", async () => {
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled
|
||||
await token.mintReward([user], ['99'], { from: accounts[2] }).should.be.fulfilled
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('99')
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled
|
||||
await token.stake(user, '100', { from: accounts[3] }).should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
it('should decrease user\'s balance and increase Staking\'s balance', async () => {
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
|
||||
await token.mintReward([user], ['100'], {from: accounts[2] }).should.be.fulfilled;
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('100');
|
||||
expect(await token.balanceOf(accounts[3])).to.be.bignumber.equal(ZERO);
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled;
|
||||
await token.stake(user, '100', {from: accounts[3] }).should.be.fulfilled;
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO);
|
||||
expect(await token.balanceOf(accounts[3])).to.be.bignumber.equal('100');
|
||||
it("should decrease user's balance and increase Staking's balance", async () => {
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled
|
||||
await token.mintReward([user], ['100'], { from: accounts[2] }).should.be.fulfilled
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('100')
|
||||
expect(await token.balanceOf(accounts[3])).to.be.bignumber.equal(ZERO)
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled
|
||||
await token.stake(user, '100', { from: accounts[3] }).should.be.fulfilled
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(accounts[3])).to.be.bignumber.equal('100')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#withdraw', async() => {
|
||||
describe('#withdraw', async () => {
|
||||
it('can only be called by Staking contract', async () => {
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
|
||||
await token.mintReward([user], ['100'], {from: accounts[2] }).should.be.fulfilled;
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled;
|
||||
await token.stake(user, '100', {from: accounts[3] }).should.be.fulfilled;
|
||||
await token.withdraw(user, '100', {from: accounts[4] }).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.withdraw(user, '100', {from: accounts[3] }).should.be.fulfilled;
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled
|
||||
await token.mintReward([user], ['100'], { from: accounts[2] }).should.be.fulfilled
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled
|
||||
await token.stake(user, '100', { from: accounts[3] }).should.be.fulfilled
|
||||
await token.withdraw(user, '100', { from: accounts[4] }).should.be.rejectedWith(ERROR_MSG)
|
||||
await token.withdraw(user, '100', { from: accounts[3] }).should.be.fulfilled
|
||||
})
|
||||
it('should revert if Staking doesn\'t have enough balance', async () => {
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
|
||||
await token.mintReward([user], ['100'], {from: accounts[2] }).should.be.fulfilled;
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('100');
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled;
|
||||
await token.stake(user, '100', {from: accounts[3] }).should.be.fulfilled;
|
||||
await token.withdraw(user, '101', {from: accounts[3] }).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.withdraw(user, '100', {from: accounts[3] }).should.be.fulfilled;
|
||||
it("should revert if Staking doesn't have enough balance", async () => {
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled
|
||||
await token.mintReward([user], ['100'], { from: accounts[2] }).should.be.fulfilled
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('100')
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled
|
||||
await token.stake(user, '100', { from: accounts[3] }).should.be.fulfilled
|
||||
await token.withdraw(user, '101', { from: accounts[3] }).should.be.rejectedWith(ERROR_MSG)
|
||||
await token.withdraw(user, '100', { from: accounts[3] }).should.be.fulfilled
|
||||
})
|
||||
it('should decrease Staking\'s balance and increase user\'s balance', async () => {
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled;
|
||||
await token.mintReward([user], ['100'], {from: accounts[2] }).should.be.fulfilled;
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('100');
|
||||
expect(await token.balanceOf(accounts[3])).to.be.bignumber.equal(ZERO);
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled;
|
||||
await token.stake(user, '100', {from: accounts[3] }).should.be.fulfilled;
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('0');
|
||||
expect(await token.balanceOf(accounts[3])).to.be.bignumber.equal('100');
|
||||
await token.withdraw(user, 60, {from: accounts[3] }).should.be.fulfilled;
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('60');
|
||||
expect(await token.balanceOf(accounts[3])).to.be.bignumber.equal('40');
|
||||
it("should decrease Staking's balance and increase user's balance", async () => {
|
||||
await token.setBlockRewardContractMock(accounts[2]).should.be.fulfilled
|
||||
await token.mintReward([user], ['100'], { from: accounts[2] }).should.be.fulfilled
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('100')
|
||||
expect(await token.balanceOf(accounts[3])).to.be.bignumber.equal(ZERO)
|
||||
await token.setStakingContractMock(accounts[3]).should.be.fulfilled
|
||||
await token.stake(user, '100', { from: accounts[3] }).should.be.fulfilled
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('0')
|
||||
expect(await token.balanceOf(accounts[3])).to.be.bignumber.equal('100')
|
||||
await token.withdraw(user, 60, { from: accounts[3] }).should.be.fulfilled
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('60')
|
||||
expect(await token.balanceOf(accounts[3])).to.be.bignumber.equal('40')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
describe('#mint', async() => {
|
||||
describe('#mint', async () => {
|
||||
it('can mint by owner', async () => {
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO);
|
||||
await token.mint(user, 1, {from: owner }).should.be.fulfilled;
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal('1');
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('1');
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO)
|
||||
await token.mint(user, 1, { from: owner }).should.be.fulfilled
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal('1')
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal('1')
|
||||
})
|
||||
|
||||
it('no one can call finishMinting', async () => {
|
||||
|
@ -241,30 +240,54 @@ async function testERC677BridgeToken(accounts, rewardable) {
|
|||
})
|
||||
|
||||
it('cannot mint by non-owner', async () => {
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO);
|
||||
await token.mint(user, 1, {from: user }).should.be.rejectedWith(ERROR_MSG);
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO);
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO);
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO)
|
||||
await token.mint(user, 1, { from: user }).should.be.rejectedWith(ERROR_MSG)
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#transfer', async() => {
|
||||
let homeErcToErcContract, foreignNativeToErcBridge, validatorContract
|
||||
describe('#transfer', async () => {
|
||||
let homeErcToErcContract
|
||||
let foreignNativeToErcBridge
|
||||
let validatorContract
|
||||
beforeEach(async () => {
|
||||
validatorContract = await BridgeValidators.new()
|
||||
const authorities = [accounts[2]];
|
||||
const authorities = [accounts[2]]
|
||||
await validatorContract.initialize(1, authorities, owner)
|
||||
homeErcToErcContract = await HomeErcToErcBridge.new()
|
||||
await homeErcToErcContract.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, executionDailyLimit, executionMaxPerTx, owner)
|
||||
await homeErcToErcContract.initialize(
|
||||
validatorContract.address,
|
||||
oneEther,
|
||||
halfEther,
|
||||
minPerTx,
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
token.address,
|
||||
executionDailyLimit,
|
||||
executionMaxPerTx,
|
||||
owner
|
||||
)
|
||||
foreignNativeToErcBridge = await ForeignNativeToErcBridge.new()
|
||||
await foreignNativeToErcBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, executionDailyLimit, executionMaxPerTx, owner);
|
||||
await foreignNativeToErcBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
oneEther,
|
||||
halfEther,
|
||||
minPerTx,
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
executionDailyLimit,
|
||||
executionMaxPerTx,
|
||||
owner
|
||||
)
|
||||
})
|
||||
it('sends tokens to recipient', async () => {
|
||||
await token.mint(user, '1', {from: owner }).should.be.fulfilled;
|
||||
await token.transfer(user, 1, {from: owner}).should.be.rejectedWith(ERROR_MSG);
|
||||
const {logs} = await token.transfer(owner, 1, {from: user}).should.be.fulfilled;
|
||||
expect(await token.balanceOf(owner)).to.be.bignumber.equal('1');
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO);
|
||||
await token.mint(user, '1', { from: owner }).should.be.fulfilled
|
||||
await token.transfer(user, 1, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
const { logs } = await token.transfer(owner, 1, { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(owner)).to.be.bignumber.equal('1')
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
expectEventInLogs(logs, 'Transfer', {
|
||||
from: user,
|
||||
to: owner,
|
||||
|
@ -273,18 +296,20 @@ async function testERC677BridgeToken(accounts, rewardable) {
|
|||
})
|
||||
|
||||
it('sends tokens to bridge contract', async () => {
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled;
|
||||
await token.mint(user, oneEther, {from: owner }).should.be.fulfilled;
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled
|
||||
await token.mint(user, oneEther, { from: owner }).should.be.fulfilled
|
||||
|
||||
const result = await token.transfer(homeErcToErcContract.address, minPerTx, {from: user}).should.be.fulfilled;
|
||||
const result = await token.transfer(homeErcToErcContract.address, minPerTx, { from: user }).should.be.fulfilled
|
||||
expectEventInLogs(result.logs, 'Transfer', {
|
||||
from: user,
|
||||
to: homeErcToErcContract.address,
|
||||
value: minPerTx
|
||||
})
|
||||
|
||||
await token.setBridgeContract(foreignNativeToErcBridge.address).should.be.fulfilled;
|
||||
const result2 = await token.transfer(foreignNativeToErcBridge.address, minPerTx, {from: user}).should.be.fulfilled;
|
||||
await token.setBridgeContract(foreignNativeToErcBridge.address).should.be.fulfilled
|
||||
const result2 = await token.transfer(foreignNativeToErcBridge.address, minPerTx, {
|
||||
from: user
|
||||
}).should.be.fulfilled
|
||||
expectEventInLogs(result2.logs, 'Transfer', {
|
||||
from: user,
|
||||
to: foreignNativeToErcBridge.address,
|
||||
|
@ -293,10 +318,10 @@ async function testERC677BridgeToken(accounts, rewardable) {
|
|||
})
|
||||
|
||||
it('sends tokens to contract that does not contains onTokenTransfer method', async () => {
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled;
|
||||
await token.mint(user, oneEther, {from: owner }).should.be.fulfilled;
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled
|
||||
await token.mint(user, oneEther, { from: owner }).should.be.fulfilled
|
||||
|
||||
const result = await token.transfer(validatorContract.address, minPerTx, {from: user}).should.be.fulfilled;
|
||||
const result = await token.transfer(validatorContract.address, minPerTx, { from: user }).should.be.fulfilled
|
||||
expectEventInLogs(result.logs, 'Transfer', {
|
||||
from: user,
|
||||
to: validatorContract.address,
|
||||
|
@ -311,98 +336,133 @@ async function testERC677BridgeToken(accounts, rewardable) {
|
|||
|
||||
it('fail to send tokens to bridge contract out of limits', async () => {
|
||||
const lessThanMin = ether('0.0001')
|
||||
await token.mint(user, oneEther, {from: owner }).should.be.fulfilled;
|
||||
await token.mint(user, oneEther, { from: owner }).should.be.fulfilled
|
||||
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled;
|
||||
await token.transfer(homeErcToErcContract.address, lessThanMin, {from: user}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled
|
||||
await token.transfer(homeErcToErcContract.address, lessThanMin, { from: user }).should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
await token.setBridgeContract(foreignNativeToErcBridge.address).should.be.fulfilled;
|
||||
await token.transfer(foreignNativeToErcBridge.address, lessThanMin, {from: user}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.setBridgeContract(foreignNativeToErcBridge.address).should.be.fulfilled
|
||||
await token
|
||||
.transfer(foreignNativeToErcBridge.address, lessThanMin, { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
|
||||
if (rewardable) {
|
||||
it('fail to send tokens to Staking contract directly', async () => {
|
||||
const amount = ether('1');
|
||||
const stakingContractAddress = accounts[2];
|
||||
const arbitraryAccountAddress = accounts[3];
|
||||
await token.setStakingContractMock(stakingContractAddress, {from: owner}).should.be.fulfilled;
|
||||
await token.mint(user, amount, {from: owner}).should.be.fulfilled;
|
||||
await token.transfer(stakingContractAddress, amount, {from: user}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.transfer(arbitraryAccountAddress, amount, {from: user}).should.be.fulfilled;
|
||||
});
|
||||
const amount = ether('1')
|
||||
const stakingContractAddress = accounts[2]
|
||||
const arbitraryAccountAddress = accounts[3]
|
||||
await token.setStakingContractMock(stakingContractAddress, { from: owner }).should.be.fulfilled
|
||||
await token.mint(user, amount, { from: owner }).should.be.fulfilled
|
||||
await token.transfer(stakingContractAddress, amount, { from: user }).should.be.rejectedWith(ERROR_MSG)
|
||||
await token.transfer(arbitraryAccountAddress, amount, { from: user }).should.be.fulfilled
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (rewardable) {
|
||||
describe('#transferFrom', async() => {
|
||||
describe('#transferFrom', async () => {
|
||||
it('fail to send tokens to Staking contract directly', async () => {
|
||||
const amount = ether('1');
|
||||
const user2 = accounts[2];
|
||||
const stakingContractAddress = accounts[3];
|
||||
const arbitraryAccountAddress = accounts[4];
|
||||
await token.setStakingContractMock(stakingContractAddress, {from: owner}).should.be.fulfilled;
|
||||
await token.mint(user, amount, {from: owner}).should.be.fulfilled;
|
||||
await token.approve(user2, amount, {from: user}).should.be.fulfilled;
|
||||
await token.transferFrom(user, stakingContractAddress, amount, {from: user2}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.transferFrom(user, arbitraryAccountAddress, amount, {from: user2}).should.be.fulfilled;
|
||||
});
|
||||
});
|
||||
const amount = ether('1')
|
||||
const user2 = accounts[2]
|
||||
const stakingContractAddress = accounts[3]
|
||||
const arbitraryAccountAddress = accounts[4]
|
||||
await token.setStakingContractMock(stakingContractAddress, { from: owner }).should.be.fulfilled
|
||||
await token.mint(user, amount, { from: owner }).should.be.fulfilled
|
||||
await token.approve(user2, amount, { from: user }).should.be.fulfilled
|
||||
await token
|
||||
.transferFrom(user, stakingContractAddress, amount, { from: user2 })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await token.transferFrom(user, arbitraryAccountAddress, amount, { from: user2 }).should.be.fulfilled
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
describe("#burn", async () => {
|
||||
it('can burn', async() => {
|
||||
await token.burn(100, {from: owner}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.mint(user, 1, {from: owner }).should.be.fulfilled;
|
||||
await token.burn(1, {from: user}).should.be.fulfilled;
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO);
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO);
|
||||
describe('#burn', async () => {
|
||||
it('can burn', async () => {
|
||||
await token.burn(100, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
await token.mint(user, 1, { from: owner }).should.be.fulfilled
|
||||
await token.burn(1, { from: user }).should.be.fulfilled
|
||||
expect(await token.totalSupply()).to.be.bignumber.equal(ZERO)
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#transferAndCall', () => {
|
||||
let homeErcToErcContract, foreignNativeToErcBridge, validatorContract
|
||||
let homeErcToErcContract
|
||||
let foreignNativeToErcBridge
|
||||
let validatorContract
|
||||
beforeEach(async () => {
|
||||
validatorContract = await BridgeValidators.new()
|
||||
const authorities = [accounts[2]];
|
||||
const authorities = [accounts[2]]
|
||||
await validatorContract.initialize(1, authorities, owner)
|
||||
homeErcToErcContract = await HomeErcToErcBridge.new()
|
||||
await homeErcToErcContract.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, token.address, executionDailyLimit, executionMaxPerTx, owner)
|
||||
await homeErcToErcContract.initialize(
|
||||
validatorContract.address,
|
||||
oneEther,
|
||||
halfEther,
|
||||
minPerTx,
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
token.address,
|
||||
executionDailyLimit,
|
||||
executionMaxPerTx,
|
||||
owner
|
||||
)
|
||||
foreignNativeToErcBridge = await ForeignNativeToErcBridge.new()
|
||||
await foreignNativeToErcBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, executionDailyLimit, executionMaxPerTx, owner);
|
||||
await foreignNativeToErcBridge.initialize(
|
||||
validatorContract.address,
|
||||
token.address,
|
||||
oneEther,
|
||||
halfEther,
|
||||
minPerTx,
|
||||
gasPrice,
|
||||
requireBlockConfirmations,
|
||||
executionDailyLimit,
|
||||
executionMaxPerTx,
|
||||
owner
|
||||
)
|
||||
})
|
||||
it('calls contractFallback', async () => {
|
||||
const receiver = await ERC677ReceiverTest.new();
|
||||
expect(await receiver.from()).to.be.equal(ZERO_ADDRESS);
|
||||
expect(await receiver.value()).to.be.bignumber.equal(ZERO);
|
||||
expect(await receiver.data()).to.be.equal(null);
|
||||
expect(await receiver.someVar()).to.be.bignumber.equal(ZERO);
|
||||
const receiver = await ERC677ReceiverTest.new()
|
||||
expect(await receiver.from()).to.be.equal(ZERO_ADDRESS)
|
||||
expect(await receiver.value()).to.be.bignumber.equal(ZERO)
|
||||
expect(await receiver.data()).to.be.equal(null)
|
||||
expect(await receiver.someVar()).to.be.bignumber.equal(ZERO)
|
||||
|
||||
const callDoSomething123 = receiver.contract.methods.doSomething(123).encodeABI()
|
||||
await token.mint(user, '1', {from: owner }).should.be.fulfilled;
|
||||
await token.transferAndCall(token.address, '1', callDoSomething123, {from: user}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.transferAndCall(ZERO_ADDRESS, '1', callDoSomething123, {from: user}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.transferAndCall(receiver.address, '1', callDoSomething123, {from: user}).should.be.fulfilled;
|
||||
expect(await token.balanceOf(receiver.address)).to.be.bignumber.equal('1');
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO);
|
||||
expect(await receiver.from()).to.be.equal(user);
|
||||
expect(await receiver.value()).to.be.bignumber.equal('1');
|
||||
expect(await receiver.data()).to.be.equal(callDoSomething123);
|
||||
expect(await receiver.someVar()).to.be.bignumber.equal('123');
|
||||
await token.mint(user, '1', { from: owner }).should.be.fulfilled
|
||||
await token
|
||||
.transferAndCall(token.address, '1', callDoSomething123, { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await token
|
||||
.transferAndCall(ZERO_ADDRESS, '1', callDoSomething123, { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await token.transferAndCall(receiver.address, '1', callDoSomething123, { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(receiver.address)).to.be.bignumber.equal('1')
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
expect(await receiver.from()).to.be.equal(user)
|
||||
expect(await receiver.value()).to.be.bignumber.equal('1')
|
||||
expect(await receiver.data()).to.be.equal(callDoSomething123)
|
||||
expect(await receiver.someVar()).to.be.bignumber.equal('123')
|
||||
})
|
||||
|
||||
it('sends tokens to bridge contract', async () => {
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled;
|
||||
await token.mint(user, oneEther, {from: owner }).should.be.fulfilled;
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled
|
||||
await token.mint(user, oneEther, { from: owner }).should.be.fulfilled
|
||||
|
||||
const result = await token.transferAndCall(homeErcToErcContract.address, minPerTx, '0x', {from: user}).should.be.fulfilled;
|
||||
const result = await token.transferAndCall(homeErcToErcContract.address, minPerTx, '0x', {
|
||||
from: user
|
||||
}).should.be.fulfilled
|
||||
expectEventInLogs(result.logs, 'Transfer', {
|
||||
from: user,
|
||||
to: homeErcToErcContract.address,
|
||||
value: minPerTx
|
||||
})
|
||||
|
||||
await token.setBridgeContract(foreignNativeToErcBridge.address).should.be.fulfilled;
|
||||
const result2 = await token.transferAndCall(foreignNativeToErcBridge.address, minPerTx, '0x', {from: user}).should.be.fulfilled;
|
||||
await token.setBridgeContract(foreignNativeToErcBridge.address).should.be.fulfilled
|
||||
const result2 = await token.transferAndCall(foreignNativeToErcBridge.address, minPerTx, '0x', { from: user })
|
||||
.should.be.fulfilled
|
||||
expectEventInLogs(result2.logs, 'Transfer', {
|
||||
from: user,
|
||||
to: foreignNativeToErcBridge.address,
|
||||
|
@ -411,75 +471,81 @@ async function testERC677BridgeToken(accounts, rewardable) {
|
|||
})
|
||||
|
||||
it('fail to sends tokens to contract that does not contains onTokenTransfer method', async () => {
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled;
|
||||
await token.mint(user, oneEther, {from: owner }).should.be.fulfilled;
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled
|
||||
await token.mint(user, oneEther, { from: owner }).should.be.fulfilled
|
||||
|
||||
await token.transferAndCall(validatorContract.address, minPerTx, '0x', {from: user}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token
|
||||
.transferAndCall(validatorContract.address, minPerTx, '0x', { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
|
||||
it('fail to send tokens to bridge contract out of limits', async () => {
|
||||
const lessThanMin = ether('0.0001')
|
||||
await token.mint(user, oneEther, {from: owner }).should.be.fulfilled;
|
||||
await token.mint(user, oneEther, { from: owner }).should.be.fulfilled
|
||||
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled;
|
||||
await token.transferAndCall(homeErcToErcContract.address, lessThanMin, '0x', {from: user}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.setBridgeContract(homeErcToErcContract.address).should.be.fulfilled
|
||||
await token
|
||||
.transferAndCall(homeErcToErcContract.address, lessThanMin, '0x', { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
await token.setBridgeContract(foreignNativeToErcBridge.address).should.be.fulfilled;
|
||||
await token.transferAndCall(foreignNativeToErcBridge.address, lessThanMin, '0x', {from: user}).should.be.rejectedWith(ERROR_MSG);
|
||||
await token.setBridgeContract(foreignNativeToErcBridge.address).should.be.fulfilled
|
||||
await token
|
||||
.transferAndCall(foreignNativeToErcBridge.address, lessThanMin, '0x', { from: user })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
})
|
||||
describe('#claimtokens', async () => {
|
||||
it('can take send ERC20 tokens', async ()=> {
|
||||
const owner = accounts[0];
|
||||
const halfEther = ether('0.5');
|
||||
let tokenSecond = await tokenContract.new("Roman Token", "RST", 18);
|
||||
it('can take send ERC20 tokens', async () => {
|
||||
const owner = accounts[0]
|
||||
const halfEther = ether('0.5')
|
||||
const tokenSecond = await tokenContract.new('Roman Token', 'RST', 18)
|
||||
|
||||
await tokenSecond.mint(accounts[0], halfEther).should.be.fulfilled;
|
||||
await tokenSecond.mint(accounts[0], halfEther).should.be.fulfilled
|
||||
halfEther.should.be.bignumber.equal(await tokenSecond.balanceOf(accounts[0]))
|
||||
await tokenSecond.transfer(token.address, halfEther);
|
||||
await tokenSecond.transfer(token.address, halfEther)
|
||||
expect(await tokenSecond.balanceOf(accounts[0])).to.be.bignumber.equal(ZERO)
|
||||
expect(await tokenSecond.balanceOf(token.address)).to.be.bignumber.equal(halfEther)
|
||||
|
||||
await token.claimTokens(tokenSecond.address, accounts[3], {from: owner});
|
||||
await token.claimTokens(tokenSecond.address, accounts[3], { from: owner })
|
||||
expect(await tokenSecond.balanceOf(token.address)).to.be.bignumber.equal(ZERO)
|
||||
halfEther.should.be.bignumber.equal(await tokenSecond.balanceOf(accounts[3]))
|
||||
})
|
||||
})
|
||||
describe('#transfer', async () => {
|
||||
it('if transfer called on contract, onTokenTransfer is also invoked', async () => {
|
||||
const receiver = await ERC677ReceiverTest.new();
|
||||
expect(await receiver.from()).to.be.equal(ZERO_ADDRESS);
|
||||
expect(await receiver.value()).to.be.bignumber.equal(ZERO);
|
||||
expect(await receiver.data()).to.be.equal(null);
|
||||
expect(await receiver.someVar()).to.be.bignumber.equal(ZERO);
|
||||
const receiver = await ERC677ReceiverTest.new()
|
||||
expect(await receiver.from()).to.be.equal(ZERO_ADDRESS)
|
||||
expect(await receiver.value()).to.be.bignumber.equal(ZERO)
|
||||
expect(await receiver.data()).to.be.equal(null)
|
||||
expect(await receiver.someVar()).to.be.bignumber.equal(ZERO)
|
||||
|
||||
await token.mint(user, 1, {from: owner }).should.be.fulfilled;
|
||||
const {logs} = await token.transfer(receiver.address, '1', {from: user}).should.be.fulfilled;
|
||||
await token.mint(user, 1, { from: owner }).should.be.fulfilled
|
||||
const { logs } = await token.transfer(receiver.address, '1', { from: user }).should.be.fulfilled
|
||||
|
||||
expect(await token.balanceOf(receiver.address)).to.be.bignumber.equal('1');
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO);
|
||||
expect(await receiver.from()).to.be.equal(user);
|
||||
expect(await receiver.value()).to.be.bignumber.equal('1');
|
||||
expect(await receiver.data()).to.be.equal(null);
|
||||
expect(logs[0].event).to.be.equal("Transfer")
|
||||
expect(await token.balanceOf(receiver.address)).to.be.bignumber.equal('1')
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
expect(await receiver.from()).to.be.equal(user)
|
||||
expect(await receiver.value()).to.be.bignumber.equal('1')
|
||||
expect(await receiver.data()).to.be.equal(null)
|
||||
expect(logs[0].event).to.be.equal('Transfer')
|
||||
})
|
||||
it('if transfer called on contract, still works even if onTokenTransfer doesnot exist', async () => {
|
||||
const someContract = await tokenContract.new("Some", "Token", 18);
|
||||
await token.mint(user, '2', {from: owner }).should.be.fulfilled;
|
||||
const tokenTransfer = await token.transfer(someContract.address, '1', {from: user}).should.be.fulfilled;
|
||||
const tokenTransfer2 = await token.transfer(accounts[0], '1', {from: user}).should.be.fulfilled;
|
||||
expect(await token.balanceOf(someContract.address)).to.be.bignumber.equal('1');
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO);
|
||||
tokenTransfer.logs[0].event.should.be.equal("Transfer")
|
||||
tokenTransfer2.logs[0].event.should.be.equal("Transfer")
|
||||
const someContract = await tokenContract.new('Some', 'Token', 18)
|
||||
await token.mint(user, '2', { from: owner }).should.be.fulfilled
|
||||
const tokenTransfer = await token.transfer(someContract.address, '1', { from: user }).should.be.fulfilled
|
||||
const tokenTransfer2 = await token.transfer(accounts[0], '1', { from: user }).should.be.fulfilled
|
||||
expect(await token.balanceOf(someContract.address)).to.be.bignumber.equal('1')
|
||||
expect(await token.balanceOf(user)).to.be.bignumber.equal(ZERO)
|
||||
tokenTransfer.logs[0].event.should.be.equal('Transfer')
|
||||
tokenTransfer2.logs[0].event.should.be.equal('Transfer')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
contract('ERC677BridgeToken', async (accounts) => {
|
||||
await testERC677BridgeToken(accounts, false);
|
||||
contract('ERC677BridgeToken', async accounts => {
|
||||
await testERC677BridgeToken(accounts, false)
|
||||
})
|
||||
|
||||
contract('ERC677BridgeTokenRewardable', async (accounts) => {
|
||||
await testERC677BridgeToken(accounts, true);
|
||||
contract('ERC677BridgeTokenRewardable', async accounts => {
|
||||
await testERC677BridgeToken(accounts, true)
|
||||
})
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
const BridgeValidators = artifacts.require("RewardableValidators.sol");
|
||||
const EternalStorageProxy = artifacts.require("EternalStorageProxy.sol");
|
||||
const BridgeValidators = artifacts.require('RewardableValidators.sol')
|
||||
const EternalStorageProxy = artifacts.require('EternalStorageProxy.sol')
|
||||
|
||||
const { ERROR_MSG, ZERO_ADDRESS, F_ADDRESS, BN } = require('./setup');
|
||||
const { expectEventInLogs } = require('./helpers/helpers');
|
||||
const { expect } = require('chai');
|
||||
const { expect } = require('chai')
|
||||
const { ERROR_MSG, ZERO_ADDRESS, F_ADDRESS, BN } = require('./setup')
|
||||
const { expectEventInLogs } = require('./helpers/helpers')
|
||||
|
||||
const ZERO = new BN(0)
|
||||
|
||||
contract('RewardableValidators', async (accounts) => {
|
||||
contract('RewardableValidators', async accounts => {
|
||||
let bridgeValidators
|
||||
let owner = accounts[0]
|
||||
const owner = accounts[0]
|
||||
|
||||
beforeEach(async () => {
|
||||
bridgeValidators = await BridgeValidators.new();
|
||||
bridgeValidators = await BridgeValidators.new()
|
||||
})
|
||||
|
||||
describe('#initialize', async () => {
|
||||
|
@ -25,12 +25,28 @@ contract('RewardableValidators', async (accounts) => {
|
|||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal(ZERO)
|
||||
expect(await bridgeValidators.deployedAtBlock()).to.be.bignumber.equal(ZERO)
|
||||
|
||||
await bridgeValidators.initialize(3, accounts.slice(0, 3), accounts.slice(3, 5), accounts[2], {from: accounts[2]}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.initialize(1, [accounts[0]], [ZERO_ADDRESS], accounts[1], { from: accounts[1] }).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.initialize(1, [ZERO_ADDRESS], [accounts[0]], accounts[1], { from: accounts[1] }).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.initialize(1, [F_ADDRESS], [accounts[0]], accounts[1], { from: accounts[1] }).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.initialize(2, accounts.slice(0, 2), accounts.slice(2, 4), accounts[2], {from: accounts[2]}).should.be.fulfilled;
|
||||
await bridgeValidators.initialize(2, accounts.slice(0, 2), accounts.slice(2, 4), accounts[2], {from: accounts[2]}).should.be.rejectedWith(ERROR_MSG);
|
||||
await bridgeValidators
|
||||
.initialize(3, accounts.slice(0, 3), accounts.slice(3, 5), accounts[2], {
|
||||
from: accounts[2]
|
||||
})
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators
|
||||
.initialize(1, [accounts[0]], [ZERO_ADDRESS], accounts[1], { from: accounts[1] })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators
|
||||
.initialize(1, [ZERO_ADDRESS], [accounts[0]], accounts[1], { from: accounts[1] })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators
|
||||
.initialize(1, [F_ADDRESS], [accounts[0]], accounts[1], { from: accounts[1] })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.initialize(2, accounts.slice(0, 2), accounts.slice(2, 4), accounts[2], {
|
||||
from: accounts[2]
|
||||
}).should.be.fulfilled
|
||||
await bridgeValidators
|
||||
.initialize(2, accounts.slice(0, 2), accounts.slice(2, 4), accounts[2], {
|
||||
from: accounts[2]
|
||||
})
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
expect(await bridgeValidators.isInitialized()).to.be.equal(true)
|
||||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal('2')
|
||||
|
@ -47,21 +63,27 @@ contract('RewardableValidators', async (accounts) => {
|
|||
})
|
||||
|
||||
describe('#addValidator', async () => {
|
||||
let owner = accounts[2];
|
||||
let validators = [accounts[0], accounts[1]];
|
||||
let rewards = accounts.slice(2, 4)
|
||||
let requiredSignatures = 2;
|
||||
const owner = accounts[2]
|
||||
const validators = [accounts[0], accounts[1]]
|
||||
const rewards = accounts.slice(2, 4)
|
||||
const requiredSignatures = 2
|
||||
beforeEach(async () => {
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, rewards, owner, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, rewards, owner, {
|
||||
from: owner
|
||||
}).should.be.fulfilled
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('2')
|
||||
})
|
||||
it('adds validator', async () => {
|
||||
let newValidator = accounts[4];
|
||||
let newReward = accounts[5];
|
||||
const newValidator = accounts[4]
|
||||
const newReward = accounts[5]
|
||||
|
||||
false.should.be.equal(await bridgeValidators.isValidator(newValidator))
|
||||
await bridgeValidators.addRewardableValidator(newValidator, newReward, {from: validators[0]}).should.be.rejectedWith(ERROR_MSG)
|
||||
const {logs} = await bridgeValidators.addRewardableValidator(newValidator, newReward, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators
|
||||
.addRewardableValidator(newValidator, newReward, { from: validators[0] })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
const { logs } = await bridgeValidators.addRewardableValidator(newValidator, newReward, {
|
||||
from: owner
|
||||
}).should.be.fulfilled
|
||||
expect(await bridgeValidators.isValidator(newValidator)).to.be.equal(true)
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('3')
|
||||
expectEventInLogs(logs, 'ValidatorAdded', { validator: newValidator })
|
||||
|
@ -72,51 +94,61 @@ contract('RewardableValidators', async (accounts) => {
|
|||
|
||||
it('cannot add already existing validator', async () => {
|
||||
true.should.be.equal(await bridgeValidators.isValidator(validators[0]))
|
||||
await bridgeValidators.addRewardableValidator(validators[0], rewards[0], {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators
|
||||
.addRewardableValidator(validators[0], rewards[0], { from: owner })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('2')
|
||||
})
|
||||
|
||||
it(`cannot add 0xf as validator address`, async () => {
|
||||
// Given
|
||||
await bridgeValidators.addRewardableValidator(F_ADDRESS, rewards[0], { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators
|
||||
.addRewardableValidator(F_ADDRESS, rewards[0], { from: owner })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
|
||||
it(`cannot add 0x0 as validator address`, async () => {
|
||||
await bridgeValidators.addRewardableValidator(ZERO_ADDRESS, rewards[0], {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators
|
||||
.addRewardableValidator(ZERO_ADDRESS, rewards[0], { from: owner })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
|
||||
it(`cannot add 0x0 as reward address`, async () => {
|
||||
await bridgeValidators.addRewardableValidator(accounts[4], ZERO_ADDRESS, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators
|
||||
.addRewardableValidator(accounts[4], ZERO_ADDRESS, { from: owner })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#removeValidator', async () => {
|
||||
let owner = accounts[2];
|
||||
let validators = [accounts[0], accounts[1], accounts[3]];
|
||||
let rewards = accounts.slice(4, 7);
|
||||
let requiredSignatures = 2;
|
||||
const owner = accounts[2]
|
||||
const validators = [accounts[0], accounts[1], accounts[3]]
|
||||
const rewards = accounts.slice(4, 7)
|
||||
const requiredSignatures = 2
|
||||
beforeEach(async () => {
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, rewards, owner, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, rewards, owner, {
|
||||
from: owner
|
||||
}).should.be.fulfilled
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('3')
|
||||
})
|
||||
|
||||
it('removes validator', async () => {
|
||||
let toRemove = validators[0];
|
||||
const toRemove = validators[0]
|
||||
expect(await bridgeValidators.isValidator(toRemove)).to.be.equal(true)
|
||||
await bridgeValidators.removeValidator(toRemove, {from: validators[0]}).should.be.rejectedWith(ERROR_MSG)
|
||||
const {logs} = await bridgeValidators.removeValidator(toRemove, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.removeValidator(toRemove, { from: validators[0] }).should.be.rejectedWith(ERROR_MSG)
|
||||
const { logs } = await bridgeValidators.removeValidator(toRemove, { from: owner }).should.be.fulfilled
|
||||
expect(await bridgeValidators.isValidator(toRemove)).to.be.equal(false)
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('2')
|
||||
expectEventInLogs(logs, 'ValidatorRemoved', { validator: toRemove })
|
||||
})
|
||||
|
||||
it('cannot remove if it will break requiredSignatures', async () => {
|
||||
let toRemove = validators[0];
|
||||
let toRemove2 = validators[1];
|
||||
const toRemove = validators[0]
|
||||
const toRemove2 = validators[1]
|
||||
true.should.be.equal(await bridgeValidators.isValidator(toRemove))
|
||||
true.should.be.equal(await bridgeValidators.isValidator(toRemove))
|
||||
await bridgeValidators.removeValidator(toRemove, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.removeValidator(toRemove2, {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.removeValidator(toRemove, { from: owner }).should.be.fulfilled
|
||||
await bridgeValidators.removeValidator(toRemove2, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
false.should.be.equal(await bridgeValidators.isValidator(toRemove))
|
||||
true.should.be.equal(await bridgeValidators.isValidator(toRemove2))
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('2')
|
||||
|
@ -124,49 +156,53 @@ contract('RewardableValidators', async (accounts) => {
|
|||
|
||||
it('cannot remove non-existent validator', async () => {
|
||||
false.should.be.equal(await bridgeValidators.isValidator(accounts[4]))
|
||||
await bridgeValidators.removeValidator(accounts[4], {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.removeValidator(ZERO_ADDRESS, {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.removeValidator(accounts[4], { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.removeValidator(ZERO_ADDRESS, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('3')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#setRequiredSignatures', async () => {
|
||||
let owner = accounts[2];
|
||||
let validators = [accounts[0], accounts[1], accounts[3]];
|
||||
let rewards = accounts.slice(4, 7)
|
||||
let requiredSignatures = '2';
|
||||
const owner = accounts[2]
|
||||
const validators = [accounts[0], accounts[1], accounts[3]]
|
||||
const rewards = accounts.slice(4, 7)
|
||||
const requiredSignatures = '2'
|
||||
beforeEach(async () => {
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, rewards, owner, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, rewards, owner, {
|
||||
from: owner
|
||||
}).should.be.fulfilled
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('3')
|
||||
})
|
||||
|
||||
it('sets req signatures', async () => {
|
||||
let newReqSig = '3';
|
||||
const newReqSig = '3'
|
||||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal(requiredSignatures)
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, {from: validators[0]}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, { from: validators[0] }).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, { from: owner }).should.be.fulfilled
|
||||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal(newReqSig)
|
||||
})
|
||||
it('cannot set more than validators count', async () => {
|
||||
let newReqSig = '4';
|
||||
const newReqSig = '4'
|
||||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal(requiredSignatures)
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal(requiredSignatures)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#upgradable', async () => {
|
||||
it('can be upgraded via upgradeToAndCall', async () => {
|
||||
let storageProxy = await EternalStorageProxy.new().should.be.fulfilled;
|
||||
let required_signatures = '2';
|
||||
let validators = [accounts[0], accounts[1]];
|
||||
let rewards = accounts.slice(3, 5);
|
||||
let owner = accounts[2]
|
||||
const data = bridgeValidators.contract.methods.initialize(required_signatures, validators,rewards, owner).encodeABI()
|
||||
await storageProxy.upgradeToAndCall('1', bridgeValidators.address, data).should.be.fulfilled;
|
||||
let finalContract = await BridgeValidators.at(storageProxy.address);
|
||||
true.should.be.equal(await finalContract.isInitialized());
|
||||
expect(await finalContract.requiredSignatures()).to.be.bignumber.equal(required_signatures)
|
||||
const storageProxy = await EternalStorageProxy.new().should.be.fulfilled
|
||||
const requiredSignatures = '2'
|
||||
const validators = [accounts[0], accounts[1]]
|
||||
const rewards = accounts.slice(3, 5)
|
||||
const owner = accounts[2]
|
||||
const data = bridgeValidators.contract.methods
|
||||
.initialize(requiredSignatures, validators, rewards, owner)
|
||||
.encodeABI()
|
||||
await storageProxy.upgradeToAndCall('1', bridgeValidators.address, data).should.be.fulfilled
|
||||
const finalContract = await BridgeValidators.at(storageProxy.address)
|
||||
true.should.be.equal(await finalContract.isInitialized())
|
||||
expect(await finalContract.requiredSignatures()).to.be.bignumber.equal(requiredSignatures)
|
||||
|
||||
true.should.be.equal(await finalContract.isValidator(validators[0]))
|
||||
true.should.be.equal(await finalContract.isValidator(validators[1]))
|
||||
|
@ -216,20 +252,11 @@ contract('RewardableValidators', async (accounts) => {
|
|||
await proxy.upgradeTo('1', bridgeValidatorsImpl.address)
|
||||
bridgeValidators = await BridgeValidators.at(proxy.address)
|
||||
const { initialize, isInitialized, removeValidator } = bridgeValidators
|
||||
await initialize(
|
||||
1,
|
||||
accounts.slice(0, 5),
|
||||
accounts.slice(5),
|
||||
owner,
|
||||
{ from: owner }
|
||||
).should.be.fulfilled
|
||||
await initialize(1, accounts.slice(0, 5), accounts.slice(5), owner, { from: owner }).should.be.fulfilled
|
||||
true.should.be.equal(await isInitialized())
|
||||
|
||||
// When
|
||||
const { logs } = await removeValidator(
|
||||
validator,
|
||||
{ from: owner }
|
||||
).should.be.fulfilled
|
||||
const { logs } = await removeValidator(validator, { from: owner }).should.be.fulfilled
|
||||
|
||||
// Then
|
||||
expectEventInLogs(logs, 'ValidatorRemoved', { validator })
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
const BN = web3.utils.BN;
|
||||
const { BN } = web3.utils
|
||||
|
||||
require('chai')
|
||||
.use(require('chai-as-promised'))
|
||||
.use(require('chai-bn')(BN))
|
||||
|
||||
require('chai/register-should');
|
||||
require('chai/register-should')
|
||||
|
||||
exports.BN = BN
|
||||
exports.toBN = web3.utils.toBN
|
||||
exports.ERROR_MSG = 'VM Exception while processing transaction: revert';
|
||||
exports.ERROR_MSG_OPCODE = 'VM Exception while processing transaction: invalid opcode';
|
||||
exports.ERROR_MSG = 'VM Exception while processing transaction: revert'
|
||||
exports.ERROR_MSG_OPCODE = 'VM Exception while processing transaction: invalid opcode'
|
||||
exports.ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
||||
exports.F_ADDRESS = '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF'
|
||||
exports.INVALID_ARGUMENTS = 'Invalid number of arguments to Solidity function'
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
const BridgeValidators = artifacts.require("BridgeValidators.sol");
|
||||
const EternalStorageProxy = artifacts.require("EternalStorageProxy.sol");
|
||||
const BridgeValidators = artifacts.require('BridgeValidators.sol')
|
||||
const EternalStorageProxy = artifacts.require('EternalStorageProxy.sol')
|
||||
|
||||
const { ERROR_MSG, ZERO_ADDRESS, F_ADDRESS, BN } = require('./setup');
|
||||
const { expectEventInLogs } = require('./helpers/helpers');
|
||||
const { expect } = require('chai');
|
||||
const { expect } = require('chai')
|
||||
const { ERROR_MSG, ZERO_ADDRESS, F_ADDRESS, BN } = require('./setup')
|
||||
const { expectEventInLogs } = require('./helpers/helpers')
|
||||
|
||||
const ZERO = new BN(0)
|
||||
|
||||
contract('BridgeValidators', async (accounts) => {
|
||||
contract('BridgeValidators', async accounts => {
|
||||
let bridgeValidators
|
||||
let owner = accounts[0]
|
||||
const owner = accounts[0]
|
||||
|
||||
beforeEach(async () => {
|
||||
bridgeValidators = await BridgeValidators.new();
|
||||
bridgeValidators = await BridgeValidators.new()
|
||||
})
|
||||
|
||||
describe('#initialize', async () => {
|
||||
|
@ -25,10 +25,16 @@ contract('BridgeValidators', async (accounts) => {
|
|||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal(ZERO)
|
||||
expect(await bridgeValidators.deployedAtBlock()).to.be.bignumber.equal(ZERO)
|
||||
|
||||
await bridgeValidators.initialize(1, [ZERO_ADDRESS], accounts[1], { from: accounts[1] }).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.initialize(1, [F_ADDRESS], accounts[1], { from: accounts[1] }).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.initialize(2, accounts.slice(0, 2), accounts[2], {from: accounts[2]}).should.be.fulfilled;
|
||||
await bridgeValidators.initialize(2, accounts.slice(0, 2), accounts[2], {from: accounts[2]}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators
|
||||
.initialize(1, [ZERO_ADDRESS], accounts[1], { from: accounts[1] })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators
|
||||
.initialize(1, [F_ADDRESS], accounts[1], { from: accounts[1] })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.initialize(2, accounts.slice(0, 2), accounts[2], { from: accounts[2] }).should.be.fulfilled
|
||||
await bridgeValidators
|
||||
.initialize(2, accounts.slice(0, 2), accounts[2], { from: accounts[2] })
|
||||
.should.be.rejectedWith(ERROR_MSG)
|
||||
|
||||
expect(await bridgeValidators.isInitialized()).to.be.equal(true)
|
||||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal('2')
|
||||
|
@ -45,19 +51,19 @@ contract('BridgeValidators', async (accounts) => {
|
|||
})
|
||||
|
||||
describe('#addValidator', async () => {
|
||||
let owner = accounts[2];
|
||||
let validators = [accounts[0], accounts[1]];
|
||||
let requiredSignatures = 2;
|
||||
const owner = accounts[2]
|
||||
const validators = [accounts[0], accounts[1]]
|
||||
const requiredSignatures = 2
|
||||
beforeEach(async () => {
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, owner, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, owner, { from: owner }).should.be.fulfilled
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('2')
|
||||
})
|
||||
it('adds validator', async () => {
|
||||
let newValidator = accounts[4];
|
||||
const newValidator = accounts[4]
|
||||
|
||||
false.should.be.equal(await bridgeValidators.isValidator(newValidator))
|
||||
await bridgeValidators.addValidator(newValidator, {from: validators[0]}).should.be.rejectedWith(ERROR_MSG)
|
||||
const {logs} = await bridgeValidators.addValidator(newValidator, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.addValidator(newValidator, { from: validators[0] }).should.be.rejectedWith(ERROR_MSG)
|
||||
const { logs } = await bridgeValidators.addValidator(newValidator, { from: owner }).should.be.fulfilled
|
||||
expect(await bridgeValidators.isValidator(newValidator)).to.be.equal(true)
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('3')
|
||||
expectEventInLogs(logs, 'ValidatorAdded', { validator: newValidator })
|
||||
|
@ -65,7 +71,7 @@ contract('BridgeValidators', async (accounts) => {
|
|||
|
||||
it('cannot add already existing validator', async () => {
|
||||
true.should.be.equal(await bridgeValidators.isValidator(validators[0]))
|
||||
await bridgeValidators.addValidator(validators[0], {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.addValidator(validators[0], { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('2')
|
||||
})
|
||||
|
||||
|
@ -75,36 +81,36 @@ contract('BridgeValidators', async (accounts) => {
|
|||
})
|
||||
|
||||
it(`cannot add 0x0 as validator address`, async () => {
|
||||
await bridgeValidators.addValidator(ZERO_ADDRESS, {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.addValidator(ZERO_ADDRESS, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#removeValidator', async () => {
|
||||
let owner = accounts[2];
|
||||
let validators = [accounts[0], accounts[1], accounts[3]];
|
||||
let requiredSignatures = 2;
|
||||
const owner = accounts[2]
|
||||
const validators = [accounts[0], accounts[1], accounts[3]]
|
||||
const requiredSignatures = 2
|
||||
beforeEach(async () => {
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, owner, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, owner, { from: owner }).should.be.fulfilled
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('3')
|
||||
})
|
||||
|
||||
it('removes validator', async () => {
|
||||
let toRemove = validators[0];
|
||||
const toRemove = validators[0]
|
||||
expect(await bridgeValidators.isValidator(toRemove)).to.be.equal(true)
|
||||
await bridgeValidators.removeValidator(toRemove, {from: validators[0]}).should.be.rejectedWith(ERROR_MSG)
|
||||
const {logs} = await bridgeValidators.removeValidator(toRemove, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.removeValidator(toRemove, { from: validators[0] }).should.be.rejectedWith(ERROR_MSG)
|
||||
const { logs } = await bridgeValidators.removeValidator(toRemove, { from: owner }).should.be.fulfilled
|
||||
expect(await bridgeValidators.isValidator(toRemove)).to.be.equal(false)
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('2')
|
||||
expectEventInLogs(logs, 'ValidatorRemoved', { validator: toRemove })
|
||||
})
|
||||
|
||||
it('cannot remove if it will break requiredSignatures', async () => {
|
||||
let toRemove = validators[0];
|
||||
let toRemove2 = validators[1];
|
||||
const toRemove = validators[0]
|
||||
const toRemove2 = validators[1]
|
||||
true.should.be.equal(await bridgeValidators.isValidator(toRemove))
|
||||
true.should.be.equal(await bridgeValidators.isValidator(toRemove))
|
||||
await bridgeValidators.removeValidator(toRemove, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.removeValidator(toRemove2, {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.removeValidator(toRemove, { from: owner }).should.be.fulfilled
|
||||
await bridgeValidators.removeValidator(toRemove2, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
false.should.be.equal(await bridgeValidators.isValidator(toRemove))
|
||||
true.should.be.equal(await bridgeValidators.isValidator(toRemove2))
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('2')
|
||||
|
@ -112,47 +118,47 @@ contract('BridgeValidators', async (accounts) => {
|
|||
|
||||
it('cannot remove non-existent validator', async () => {
|
||||
false.should.be.equal(await bridgeValidators.isValidator(accounts[4]))
|
||||
await bridgeValidators.removeValidator(accounts[4], {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.removeValidator(ZERO_ADDRESS, {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.removeValidator(accounts[4], { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.removeValidator(ZERO_ADDRESS, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('3')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#setRequiredSignatures', async () => {
|
||||
let owner = accounts[2];
|
||||
let validators = [accounts[0], accounts[1], accounts[3]];
|
||||
let requiredSignatures = '2';
|
||||
const owner = accounts[2]
|
||||
const validators = [accounts[0], accounts[1], accounts[3]]
|
||||
const requiredSignatures = '2'
|
||||
beforeEach(async () => {
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, owner, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.initialize(requiredSignatures, validators, owner, { from: owner }).should.be.fulfilled
|
||||
expect(await bridgeValidators.validatorCount()).to.be.bignumber.equal('3')
|
||||
})
|
||||
|
||||
it('sets req signatures', async () => {
|
||||
let newReqSig = '3';
|
||||
const newReqSig = '3'
|
||||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal(requiredSignatures)
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, {from: validators[0]}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, {from: owner}).should.be.fulfilled
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, { from: validators[0] }).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, { from: owner }).should.be.fulfilled
|
||||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal(newReqSig)
|
||||
})
|
||||
it('cannot set more than validators count', async () => {
|
||||
let newReqSig = '4';
|
||||
const newReqSig = '4'
|
||||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal(requiredSignatures)
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, {from: owner}).should.be.rejectedWith(ERROR_MSG)
|
||||
await bridgeValidators.setRequiredSignatures(newReqSig, { from: owner }).should.be.rejectedWith(ERROR_MSG)
|
||||
expect(await bridgeValidators.requiredSignatures()).to.be.bignumber.equal(requiredSignatures)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#upgradable', async () => {
|
||||
it('can be upgraded via upgradeToAndCall', async () => {
|
||||
let storageProxy = await EternalStorageProxy.new().should.be.fulfilled;
|
||||
let required_signatures = '2';
|
||||
let validators = [accounts[0], accounts[1]];
|
||||
let owner = accounts[2]
|
||||
const data = bridgeValidators.contract.methods.initialize(required_signatures, validators, owner).encodeABI()
|
||||
await storageProxy.upgradeToAndCall('1', bridgeValidators.address, data).should.be.fulfilled;
|
||||
let finalContract = await BridgeValidators.at(storageProxy.address);
|
||||
true.should.be.equal(await finalContract.isInitialized());
|
||||
expect(await finalContract.requiredSignatures()).to.be.bignumber.equal(required_signatures)
|
||||
const storageProxy = await EternalStorageProxy.new().should.be.fulfilled
|
||||
const requiredSignatures = '2'
|
||||
const validators = [accounts[0], accounts[1]]
|
||||
const owner = accounts[2]
|
||||
const data = bridgeValidators.contract.methods.initialize(requiredSignatures, validators, owner).encodeABI()
|
||||
await storageProxy.upgradeToAndCall('1', bridgeValidators.address, data).should.be.fulfilled
|
||||
const finalContract = await BridgeValidators.at(storageProxy.address)
|
||||
true.should.be.equal(await finalContract.isInitialized())
|
||||
expect(await finalContract.requiredSignatures()).to.be.bignumber.equal(requiredSignatures)
|
||||
|
||||
true.should.be.equal(await finalContract.isValidator(validators[0]))
|
||||
true.should.be.equal(await finalContract.isValidator(validators[1]))
|
||||
|
@ -202,19 +208,11 @@ contract('BridgeValidators', async (accounts) => {
|
|||
await proxy.upgradeTo('1', bridgeValidatorsImpl.address)
|
||||
bridgeValidators = await BridgeValidators.at(proxy.address)
|
||||
const { initialize, isInitialized, removeValidator } = bridgeValidators
|
||||
await initialize(
|
||||
1,
|
||||
accounts.slice(0, 5),
|
||||
owner,
|
||||
{ from: owner }
|
||||
).should.be.fulfilled
|
||||
await initialize(1, accounts.slice(0, 5), owner, { from: owner }).should.be.fulfilled
|
||||
true.should.be.equal(await isInitialized())
|
||||
|
||||
// When
|
||||
const { logs } = await removeValidator(
|
||||
validator,
|
||||
{ from: owner }
|
||||
).should.be.fulfilled
|
||||
const { logs } = await removeValidator(validator, { from: owner }).should.be.fulfilled
|
||||
|
||||
// Then
|
||||
expectEventInLogs(logs, 'ValidatorRemoved', { validator })
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
const spuriousDragonVersion = process.argv[3] === 'spuriousDragon'
|
||||
const contractsBuildDirectory = spuriousDragonVersion ? './build/spuriousDragon' : './build/contracts'
|
||||
const evmVersion = spuriousDragonVersion ? 'spuriousDragon' : 'byzantium'
|
||||
const mochaOptions = process.env.GASREPORT === 'true'
|
||||
? {
|
||||
reporter: 'eth-gas-reporter',
|
||||
reporterOptions : {
|
||||
currency: 'USD',
|
||||
gasPrice: 1
|
||||
}
|
||||
}
|
||||
: {}
|
||||
const mochaOptions =
|
||||
process.env.GASREPORT === 'true'
|
||||
? {
|
||||
reporter: 'eth-gas-reporter',
|
||||
reporterOptions: {
|
||||
currency: 'USD',
|
||||
gasPrice: 1
|
||||
}
|
||||
}
|
||||
: {}
|
||||
|
||||
module.exports = {
|
||||
contracts_build_directory: contractsBuildDirectory,
|
||||
|
@ -19,7 +20,7 @@ module.exports = {
|
|||
network_id: '*', // eslint-disable-line camelcase
|
||||
port: 8555,
|
||||
gas: 0xfffffffffff,
|
||||
gasPrice: 0x01,
|
||||
gasPrice: 0x01
|
||||
},
|
||||
ganache: {
|
||||
host: '127.0.0.1',
|
||||
|
@ -30,15 +31,15 @@ module.exports = {
|
|||
},
|
||||
compilers: {
|
||||
solc: {
|
||||
version: "0.4.24",
|
||||
version: '0.4.24',
|
||||
settings: {
|
||||
optimizer: {
|
||||
enabled: true,
|
||||
runs: 200
|
||||
},
|
||||
evmVersion: evmVersion
|
||||
evmVersion
|
||||
}
|
||||
}
|
||||
},
|
||||
mocha: mochaOptions
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue