Add linter for unit tests

This commit is contained in:
Gerardo Nardelli 2019-05-14 12:36:34 -03:00
parent 6bad8be39d
commit 34d48efad7
18 changed files with 6074 additions and 2181 deletions

2
.eslintignore Normal file
View File

@ -0,0 +1,2 @@
node_modules
deploy

27
.eslintrc Normal file
View File

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

5
.prettierrc Normal file
View File

@ -0,0 +1,5 @@
{
"semi": false,
"singleQuote": true,
"printWidth": 120
}

View File

@ -14,4 +14,5 @@ matrix:
allow_failures:
- env: SOLIDITY_COVERAGE=true
script:
- yarn lint:js
- yarn test

1036
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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