dirty reverse bridge for v2

This commit is contained in:
Roman Storm 2018-05-10 16:53:19 -04:00
parent 93969cd934
commit 188357798c
4 changed files with 527 additions and 515 deletions

View File

@ -122,68 +122,25 @@ contract ForeignBridge is ERC677Receiver, BasicBridge {
emit GasConsumptionLimitsUpdated(gasLimitDepositRelay(), gasLimitWithdrawConfirm());
}
function deposit(address recipient, uint256 value, bytes32 transactionHash) external onlyValidator {
bytes32 hashMsg = keccak256(recipient, value, transactionHash);
bytes32 hashSender = keccak256(msg.sender, hashMsg);
// Duplicated deposits
require(!depositsSigned(hashSender));
setDepositsSigned(hashSender, true);
function deposit(uint8[] vs, bytes32[] rs, bytes32[] ss, bytes message) external {
Message.hasEnoughValidSignatures(message, vs, rs, ss, validatorContract());
address recipient;
uint256 amount;
bytes32 txHash;
(recipient, amount, txHash) = Message.parseMessage(message);
require(!deposits(txHash));
setDeposits(txHash, true);
uint256 signed = numDepositsSigned(hashMsg);
require(!isAlreadyProcessed(signed));
// the check above assumes that the case when the value could be overflew will not happen in the addition operation below
signed = signed + 1;
setNumDepositsSigned(hashMsg, signed);
emit SignedForDeposit(msg.sender, transactionHash);
if (signed >= validatorContract().requiredSignatures()) {
// If the bridge contract does not own enough tokens to transfer
// it will couse funds lock on the home side of the bridge
setNumDepositsSigned(hashMsg, markAsProcessed(signed));
erc677token().mint(recipient, value);
emit Deposit(recipient, value, transactionHash);
}
erc677token().mint(recipient, amount);
emit Deposit(recipient, amount, txHash);
}
/// Should be used as sync tool
///
/// Message is a message that should be relayed to main chain once authorities sign it.
///
/// for withdraw message contains:
/// withdrawal recipient (bytes20)
/// withdrawal value (uint)
/// foreign transaction hash (bytes32) // to avoid transaction duplication
function submitSignature(bytes signature, bytes message) external onlyValidator {
// ensure that `signature` is really `message` signed by `msg.sender`
require(Message.isMessageValid(message));
require(msg.sender == Message.recoverAddressFromSignedMessage(signature, message));
bytes32 hashMsg = keccak256(message);
bytes32 hashSender = keccak256(msg.sender, hashMsg);
function deposits(bytes32 _withdraw) public view returns(bool) {
return boolStorage[keccak256("deposits", _withdraw)];
}
uint256 signed = numMessagesSigned(hashMsg);
require(!isAlreadyProcessed(signed));
// the check above assumes that the case when the value could be overflew will not happen in the addition operation below
signed = signed + 1;
if (signed > 1) {
// Duplicated signatures
require(!messagesSigned(hashSender));
} else {
setMessages(hashMsg, message);
}
setMessagesSigned(hashSender, true);
bytes32 signIdx = keccak256(hashMsg, (signed-1));
setSignatures(signIdx, signature);
setNumMessagesSigned(hashMsg, signed);
emit SignedForWithdraw(msg.sender, hashMsg);
if (signed >= validatorContract().requiredSignatures()) {
setNumMessagesSigned(hashMsg, markAsProcessed(signed));
emit CollectedSignatures(msg.sender, hashMsg);
}
function setDeposits(bytes32 _withdraw, bool _status) private {
boolStorage[keccak256("deposits", _withdraw)] = _status;
}
function gasPriceForCompensationAtHomeSide() public pure returns(uint256) {
@ -194,16 +151,6 @@ contract ForeignBridge is ERC677Receiver, BasicBridge {
return _number & 2**255 == 2**255;
}
function signature(bytes32 _hash, uint256 _index) public view returns (bytes) {
bytes32 signIdx = keccak256(_hash, _index);
return signatures(signIdx);
}
/// Get message
function message(bytes32 _hash) public view returns (bytes) {
return messages(_hash);
}
function getCurrentDay() public view returns(uint256) {
return now / 1 days;
}
@ -222,58 +169,10 @@ contract ForeignBridge is ERC677Receiver, BasicBridge {
return boolStorage[keccak256("isInitialized")];
}
function messages(bytes32 _hash) private view returns(bytes) {
return bytesStorage[keccak256("messages", _hash)];
}
function setMessages(bytes32 _hash, bytes _message) private {
bytesStorage[keccak256("messages", _hash)] = _message;
}
function signatures(bytes32 _hash) private view returns(bytes) {
return bytesStorage[keccak256("signatures", _hash)];
}
function setSignatures(bytes32 _hash, bytes _signature) private {
bytesStorage[keccak256("signatures", _hash)] = _signature;
}
function messagesSigned(bytes32 _message) public view returns(bool) {
return boolStorage[keccak256("messagesSigned", _message)];
}
function depositsSigned(bytes32 _deposit) public view returns(bool) {
return boolStorage[keccak256("depositsSigned", _deposit)];
}
function markAsProcessed(uint256 _v) private pure returns(uint256) {
return _v | 2 ** 255;
}
function numMessagesSigned(bytes32 _message) private view returns(uint256) {
return uintStorage[keccak256("numMessagesSigned", _message)];
}
function numDepositsSigned(bytes32 _deposit) private view returns(uint256) {
return uintStorage[keccak256("numDepositsSigned", _deposit)];
}
function setMessagesSigned(bytes32 _hash, bool _status) private {
boolStorage[keccak256("messagesSigned", _hash)] = _status;
}
function setDepositsSigned(bytes32 _deposit, bool _status) private {
boolStorage[keccak256("depositsSigned", _deposit)] = _status;
}
function setNumMessagesSigned(bytes32 _message, uint256 _number) private {
uintStorage[keccak256("numMessagesSigned", _message)] = _number;
}
function setNumDepositsSigned(bytes32 _deposit, uint256 _number) private {
uintStorage[keccak256("numDepositsSigned", _deposit)] = _number;
}
function setTotalSpentPerDay(uint256 _day, uint256 _value) private {
uintStorage[keccak256("totalSpentPerDay", _day)] = _value;
}

View File

@ -11,6 +11,9 @@ contract HomeBridge is EternalStorage, BasicBridge {
event Deposit (address recipient, uint256 value);
event Withdraw (address recipient, uint256 value, bytes32 transactionHash);
event DailyLimit(uint256 newLimit);
event SignedForDeposit(address indexed signer, bytes32 messageHash);
event CollectedSignatures(address authorityResponsibleForRelay, bytes32 messageHash);
function initialize (
address _validatorContract,
@ -71,19 +74,46 @@ contract HomeBridge is EternalStorage, BasicBridge {
emit GasConsumptionLimitsUpdated(_gas);
}
function withdraw(uint8[] vs, bytes32[] rs, bytes32[] ss, bytes message) external {
Message.hasEnoughValidSignatures(message, vs, rs, ss, validatorContract());
address recipient;
uint256 amount;
bytes32 txHash;
(recipient, amount, txHash) = Message.parseMessage(message);
require(!withdraws(txHash));
setWithdraws(txHash, true);
function withdraw(address recipient, uint256 value, bytes32 transactionHash) external onlyValidator {
bytes32 hashMsg = keccak256(recipient, value, transactionHash);
bytes32 hashSender = keccak256(msg.sender, hashMsg);
// Duplicated deposits
require(!depositsSigned(hashSender));
setDepositsSigned(hashSender, true);
// pay out recipient
recipient.transfer(amount);
uint256 signed = numDepositsSigned(hashMsg);
require(!isAlreadyProcessed(signed));
// the check above assumes that the case when the value could be overflew will not happen in the addition operation below
signed = signed + 1;
emit Withdraw(recipient, amount, txHash);
setNumDepositsSigned(hashMsg, signed);
emit SignedForDeposit(msg.sender, transactionHash);
if (signed >= validatorContract().requiredSignatures()) {
// If the bridge contract does not own enough tokens to transfer
// it will couse funds lock on the home side of the bridge
setNumDepositsSigned(hashMsg, markAsProcessed(signed));
recipient.transfer(value);
emit Withdraw(recipient, value, transactionHash);
}
}
function numDepositsSigned(bytes32 _deposit) private view returns(uint256) {
return uintStorage[keccak256("numDepositsSigned", _deposit)];
}
function setDepositsSigned(bytes32 _deposit, bool _status) private {
boolStorage[keccak256("depositsSigned", _deposit)] = _status;
}
function setNumDepositsSigned(bytes32 _deposit, uint256 _number) private {
uintStorage[keccak256("numDepositsSigned", _deposit)] = _number;
}
function depositsSigned(bytes32 _deposit) public view returns(bool) {
return boolStorage[keccak256("depositsSigned", _deposit)];
}
function setHomeDailyLimit(uint256 _homeDailyLimit) external onlyOwner {
@ -133,4 +163,87 @@ contract HomeBridge is EternalStorage, BasicBridge {
function setInitialize(bool _status) private {
boolStorage[keccak256("isInitialized")] = _status;
}
function submitSignature(bytes signature, bytes message) external onlyValidator {
// ensure that `signature` is really `message` signed by `msg.sender`
require(Message.isMessageValid(message));
require(msg.sender == Message.recoverAddressFromSignedMessage(signature, message));
bytes32 hashMsg = keccak256(message);
bytes32 hashSender = keccak256(msg.sender, hashMsg);
uint256 signed = numMessagesSigned(hashMsg);
require(!isAlreadyProcessed(signed));
// the check above assumes that the case when the value could be overflew will not happen in the addition operation below
signed = signed + 1;
if (signed > 1) {
// Duplicated signatures
require(!messagesSigned(hashSender));
} else {
setMessages(hashMsg, message);
}
setMessagesSigned(hashSender, true);
bytes32 signIdx = keccak256(hashMsg, (signed-1));
setSignatures(signIdx, signature);
setNumMessagesSigned(hashMsg, signed);
emit SignedForDeposit(msg.sender, hashMsg);
if (signed >= validatorContract().requiredSignatures()) {
setNumMessagesSigned(hashMsg, markAsProcessed(signed));
emit CollectedSignatures(msg.sender, hashMsg);
}
}
function setMessagesSigned(bytes32 _hash, bool _status) private {
boolStorage[keccak256("messagesSigned", _hash)] = _status;
}
function signature(bytes32 _hash, uint256 _index) public view returns (bytes) {
bytes32 signIdx = keccak256(_hash, _index);
return signatures(signIdx);
}
function messagesSigned(bytes32 _message) public view returns(bool) {
return boolStorage[keccak256("messagesSigned", _message)];
}
function messages(bytes32 _hash) private view returns(bytes) {
return bytesStorage[keccak256("messages", _hash)];
}
function signatures(bytes32 _hash) private view returns(bytes) {
return bytesStorage[keccak256("signatures", _hash)];
}
function setSignatures(bytes32 _hash, bytes _signature) private {
bytesStorage[keccak256("signatures", _hash)] = _signature;
}
function setMessages(bytes32 _hash, bytes _message) private {
bytesStorage[keccak256("messages", _hash)] = _message;
}
function message(bytes32 _hash) public view returns (bytes) {
return messages(_hash);
}
function setNumMessagesSigned(bytes32 _message, uint256 _number) private {
uintStorage[keccak256("numMessagesSigned", _message)] = _number;
}
function markAsProcessed(uint256 _v) private pure returns(uint256) {
return _v | 2 ** 255;
}
function isAlreadyProcessed(uint256 _number) public pure returns(bool) {
return _number & 2**255 == 2**255;
}
function numMessagesSigned(bytes32 _message) private view returns(uint256) {
return uintStorage[keccak256("numMessagesSigned", _message)];
}
}

View File

@ -57,154 +57,154 @@ contract('ForeignBridge', async (accounts) => {
})
})
describe('#deposit', async () => {
let foreignBridge;
beforeEach(async () => {
token = await POA20.new("POA ERC20 Foundation", "POA20", 18);
foreignBridge = await ForeignBridge.new();
await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
await token.transferOwnership(foreignBridge.address)
})
it('should allow validator to deposit', async () => {
const recipient = accounts[5];
const value = oneEther;
const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
const {logs} = await foreignBridge.deposit(recipient, value, transactionHash, {from: authorities[0]})
logs[0].event.should.be.equal("SignedForDeposit");
logs[0].args.should.be.deep.equal({
signer: authorities[0],
transactionHash
});
logs[1].event.should.be.equal("Deposit");
logs[1].args.should.be.deep.equal({
recipient,
value,
transactionHash
})
oneEther.should.be.bignumber.equal(await token.totalSupply());
oneEther.should.be.bignumber.equal(await token.balanceOf(recipient));
// describe('#deposit', async () => {
// let foreignBridge;
// beforeEach(async () => {
// token = await POA20.new("POA ERC20 Foundation", "POA20", 18);
// foreignBridge = await ForeignBridge.new();
// await foreignBridge.initialize(validatorContract.address, token.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
// await token.transferOwnership(foreignBridge.address)
// })
// it('should allow validator to deposit', async () => {
// const recipient = accounts[5];
// const value = oneEther;
// const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
// const {logs} = await foreignBridge.deposit(recipient, value, transactionHash, {from: authorities[0]})
// logs[0].event.should.be.equal("SignedForDeposit");
// logs[0].args.should.be.deep.equal({
// signer: authorities[0],
// transactionHash
// });
// logs[1].event.should.be.equal("Deposit");
// logs[1].args.should.be.deep.equal({
// recipient,
// value,
// transactionHash
// })
// oneEther.should.be.bignumber.equal(await token.totalSupply());
// oneEther.should.be.bignumber.equal(await token.balanceOf(recipient));
const msgHash = Web3Utils.soliditySha3(recipient, value, transactionHash);
const senderHash = Web3Utils.soliditySha3(authorities[0], msgHash)
true.should.be.equal(await foreignBridge.depositsSigned(senderHash))
})
it('test with 2 signatures required', async () => {
let validatorContractWith2Signatures = await BridgeValidators.new()
let authoritiesTwoAccs = [accounts[1], accounts[2], accounts[3]];
let ownerOfValidators = accounts[0]
await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators)
let tokenPOA20 = await POA20.new("POA ERC20 Foundation", "POA20", 18);
let foreignBridgeWithTwoSigs = await ForeignBridge.new();
await foreignBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, tokenPOA20.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
await tokenPOA20.transferOwnership(foreignBridgeWithTwoSigs.address)
// const msgHash = Web3Utils.soliditySha3(recipient, value, transactionHash);
// const senderHash = Web3Utils.soliditySha3(authorities[0], msgHash)
// true.should.be.equal(await foreignBridge.depositsSigned(senderHash))
// })
// it('test with 2 signatures required', async () => {
// let validatorContractWith2Signatures = await BridgeValidators.new()
// let authoritiesTwoAccs = [accounts[1], accounts[2], accounts[3]];
// let ownerOfValidators = accounts[0]
// await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators)
// let tokenPOA20 = await POA20.new("POA ERC20 Foundation", "POA20", 18);
// let foreignBridgeWithTwoSigs = await ForeignBridge.new();
// await foreignBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, tokenPOA20.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
// await tokenPOA20.transferOwnership(foreignBridgeWithTwoSigs.address)
const recipient = accounts[5];
const value = oneEther;
const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
const {logs} = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[0]}).should.be.fulfilled;
logs[0].event.should.be.equal("SignedForDeposit");
logs[0].args.should.be.deep.equal({
signer: authorities[0],
transactionHash
});
'0'.should.be.bignumber.equal(await tokenPOA20.totalSupply());
'0'.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
const secondDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[1]}).should.be.fulfilled;
oneEther.should.be.bignumber.equal(await tokenPOA20.totalSupply());
oneEther.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
secondDeposit.logs[1].event.should.be.equal("Deposit");
secondDeposit.logs[1].args.should.be.deep.equal({
recipient,
value,
transactionHash
})
const thirdDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[2]}).should.be.rejectedWith(ERROR_MSG);
oneEther.should.be.bignumber.equal(await tokenPOA20.totalSupply());
oneEther.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
})
it('should not allow to double submit', async () => {
const recipient = accounts[5];
const value = oneEther;
const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
await foreignBridge.deposit(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled;
await foreignBridge.deposit(recipient, value, transactionHash, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG);
// const recipient = accounts[5];
// const value = oneEther;
// const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
// const {logs} = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[0]}).should.be.fulfilled;
// logs[0].event.should.be.equal("SignedForDeposit");
// logs[0].args.should.be.deep.equal({
// signer: authorities[0],
// transactionHash
// });
// '0'.should.be.bignumber.equal(await tokenPOA20.totalSupply());
// '0'.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
// const secondDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[1]}).should.be.fulfilled;
// oneEther.should.be.bignumber.equal(await tokenPOA20.totalSupply());
// oneEther.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
// secondDeposit.logs[1].event.should.be.equal("Deposit");
// secondDeposit.logs[1].args.should.be.deep.equal({
// recipient,
// value,
// transactionHash
// })
// const thirdDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[2]}).should.be.rejectedWith(ERROR_MSG);
// oneEther.should.be.bignumber.equal(await tokenPOA20.totalSupply());
// oneEther.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
// })
// it('should not allow to double submit', async () => {
// const recipient = accounts[5];
// const value = oneEther;
// const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
// await foreignBridge.deposit(recipient, value, transactionHash, {from: authorities[0]}).should.be.fulfilled;
// await foreignBridge.deposit(recipient, value, transactionHash, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG);
})
it('should not allow non-authorities to execute deposit', async () => {
const recipient = accounts[5];
const value = oneEther;
const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
await foreignBridge.deposit(recipient, value, transactionHash, {from: accounts[7]}).should.be.rejectedWith(ERROR_MSG);
})
it('doesnt allow to mint if requiredSignatures has changed', async () => {
let validatorContractWith2Signatures = await BridgeValidators.new()
let authoritiesTwoAccs = [accounts[1], accounts[2], accounts[3]];
let ownerOfValidators = accounts[0]
await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators)
let tokenPOA20 = await POA20.new("POA ERC20 Foundation", "POA20", 18);
let foreignBridgeWithTwoSigs = await ForeignBridge.new();
await foreignBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, tokenPOA20.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
await tokenPOA20.transferOwnership(foreignBridgeWithTwoSigs.address)
// })
// it('should not allow non-authorities to execute deposit', async () => {
// const recipient = accounts[5];
// const value = oneEther;
// const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
// await foreignBridge.deposit(recipient, value, transactionHash, {from: accounts[7]}).should.be.rejectedWith(ERROR_MSG);
// })
// it('doesnt allow to mint if requiredSignatures has changed', async () => {
// let validatorContractWith2Signatures = await BridgeValidators.new()
// let authoritiesTwoAccs = [accounts[1], accounts[2], accounts[3]];
// let ownerOfValidators = accounts[0]
// await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators)
// let tokenPOA20 = await POA20.new("POA ERC20 Foundation", "POA20", 18);
// let foreignBridgeWithTwoSigs = await ForeignBridge.new();
// await foreignBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, tokenPOA20.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
// await tokenPOA20.transferOwnership(foreignBridgeWithTwoSigs.address)
const recipient = accounts[5];
const value = oneEther;
const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
const {logs} = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[0]}).should.be.fulfilled;
logs[0].event.should.be.equal("SignedForDeposit");
logs[0].args.should.be.deep.equal({
signer: authorities[0],
transactionHash
});
'0'.should.be.bignumber.equal(await tokenPOA20.totalSupply());
'0'.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
const secondDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[1]}).should.be.fulfilled;
oneEther.should.be.bignumber.equal(await tokenPOA20.totalSupply());
oneEther.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
secondDeposit.logs[1].event.should.be.equal("Deposit");
secondDeposit.logs[1].args.should.be.deep.equal({
recipient,
value,
transactionHash
})
await validatorContractWith2Signatures.setRequiredSignatures(3).should.be.fulfilled;
const thirdDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[2]}).should.be.rejectedWith(ERROR_MSG);
oneEther.should.be.bignumber.equal(await tokenPOA20.totalSupply());
oneEther.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
})
it('attack when decreasing requiredSignatures', async () => {
let validatorContractWith2Signatures = await BridgeValidators.new()
let authoritiesTwoAccs = [accounts[1], accounts[2], accounts[3]];
let ownerOfValidators = accounts[0]
await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators)
let tokenPOA20 = await POA20.new("POA ERC20 Foundation", "POA20", 18);
let foreignBridgeWithTwoSigs = await ForeignBridge.new();
await foreignBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, tokenPOA20.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
await tokenPOA20.transferOwnership(foreignBridgeWithTwoSigs.address)
// const recipient = accounts[5];
// const value = oneEther;
// const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
// const {logs} = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[0]}).should.be.fulfilled;
// logs[0].event.should.be.equal("SignedForDeposit");
// logs[0].args.should.be.deep.equal({
// signer: authorities[0],
// transactionHash
// });
// '0'.should.be.bignumber.equal(await tokenPOA20.totalSupply());
// '0'.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
// const secondDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[1]}).should.be.fulfilled;
// oneEther.should.be.bignumber.equal(await tokenPOA20.totalSupply());
// oneEther.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
// secondDeposit.logs[1].event.should.be.equal("Deposit");
// secondDeposit.logs[1].args.should.be.deep.equal({
// recipient,
// value,
// transactionHash
// })
// await validatorContractWith2Signatures.setRequiredSignatures(3).should.be.fulfilled;
// const thirdDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[2]}).should.be.rejectedWith(ERROR_MSG);
// oneEther.should.be.bignumber.equal(await tokenPOA20.totalSupply());
// oneEther.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
// })
// it('attack when decreasing requiredSignatures', async () => {
// let validatorContractWith2Signatures = await BridgeValidators.new()
// let authoritiesTwoAccs = [accounts[1], accounts[2], accounts[3]];
// let ownerOfValidators = accounts[0]
// await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators)
// let tokenPOA20 = await POA20.new("POA ERC20 Foundation", "POA20", 18);
// let foreignBridgeWithTwoSigs = await ForeignBridge.new();
// await foreignBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, tokenPOA20.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
// await tokenPOA20.transferOwnership(foreignBridgeWithTwoSigs.address)
const recipient = accounts[5];
const value = oneEther;
const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
const {logs} = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[0]}).should.be.fulfilled;
logs[0].event.should.be.equal("SignedForDeposit");
logs[0].args.should.be.deep.equal({
signer: authorities[0],
transactionHash
});
'0'.should.be.bignumber.equal(await tokenPOA20.totalSupply());
'0'.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
await validatorContractWith2Signatures.setRequiredSignatures(1).should.be.fulfilled;
const secondDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[1]}).should.be.fulfilled;
const thirdDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[2]}).should.be.rejectedWith(ERROR_MSG);
oneEther.should.be.bignumber.equal(await tokenPOA20.totalSupply());
oneEther.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
secondDeposit.logs[1].event.should.be.equal("Deposit");
secondDeposit.logs[1].args.should.be.deep.equal({
recipient,
value,
transactionHash
})
})
})
// const recipient = accounts[5];
// const value = oneEther;
// const transactionHash = "0x806335163828a8eda675cff9c84fa6e6c7cf06bb44cc6ec832e42fe789d01415";
// const {logs} = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[0]}).should.be.fulfilled;
// logs[0].event.should.be.equal("SignedForDeposit");
// logs[0].args.should.be.deep.equal({
// signer: authorities[0],
// transactionHash
// });
// '0'.should.be.bignumber.equal(await tokenPOA20.totalSupply());
// '0'.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
// await validatorContractWith2Signatures.setRequiredSignatures(1).should.be.fulfilled;
// const secondDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[1]}).should.be.fulfilled;
// const thirdDeposit = await foreignBridgeWithTwoSigs.deposit(recipient, value, transactionHash, {from: authoritiesTwoAccs[2]}).should.be.rejectedWith(ERROR_MSG);
// oneEther.should.be.bignumber.equal(await tokenPOA20.totalSupply());
// oneEther.should.be.bignumber.equal(await tokenPOA20.balanceOf(recipient));
// secondDeposit.logs[1].event.should.be.equal("Deposit");
// secondDeposit.logs[1].args.should.be.deep.equal({
// recipient,
// value,
// transactionHash
// })
// })
// })
describe('#onTokenTransfer', async () => {
it('can only be called from token contract', async ()=> {
@ -281,94 +281,94 @@ contract('ForeignBridge', async (accounts) => {
})
})
describe('#submitSignature', async () => {
let validatorContractWith2Signatures,authoritiesTwoAccs,ownerOfValidators,tokenPOA20,foreignBridgeWithTwoSigs
beforeEach(async () => {
validatorContractWith2Signatures = await BridgeValidators.new()
authoritiesTwoAccs = [accounts[1], accounts[2], accounts[3]];
ownerOfValidators = accounts[0]
await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators)
tokenPOA20 = await POA20.new("POA ERC20 Foundation", "POA20", 18);
foreignBridgeWithTwoSigs = await ForeignBridge.new();
await foreignBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, tokenPOA20.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
await tokenPOA20.transferOwnership(foreignBridgeWithTwoSigs.address)
// describe('#submitSignature', async () => {
// let validatorContractWith2Signatures,authoritiesTwoAccs,ownerOfValidators,tokenPOA20,foreignBridgeWithTwoSigs
// beforeEach(async () => {
// validatorContractWith2Signatures = await BridgeValidators.new()
// authoritiesTwoAccs = [accounts[1], accounts[2], accounts[3]];
// ownerOfValidators = accounts[0]
// await validatorContractWith2Signatures.initialize(2, authoritiesTwoAccs, ownerOfValidators)
// tokenPOA20 = await POA20.new("POA ERC20 Foundation", "POA20", 18);
// foreignBridgeWithTwoSigs = await ForeignBridge.new();
// await foreignBridgeWithTwoSigs.initialize(validatorContractWith2Signatures.address, tokenPOA20.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
// await tokenPOA20.transferOwnership(foreignBridgeWithTwoSigs.address)
})
it('allows a validator to submit a signature', async () => {
var recipientAccount = accounts[8]
var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
var homeGasPrice = web3.toBigNumber(0);
var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
var signature = await sign(authoritiesTwoAccs[0], message)
const {logs} = await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authorities[0]}).should.be.fulfilled;
logs[0].event.should.be.equal('SignedForWithdraw')
const msgHashFromLog = logs[0].args.messageHash
const signatureFromContract = await foreignBridgeWithTwoSigs.signature(msgHashFromLog, 0);
const messageFromContract = await foreignBridgeWithTwoSigs.message(msgHashFromLog);
signature.should.be.equal(signatureFromContract);
messageFromContract.should.be.equal(messageFromContract);
const hashMsg = Web3Utils.soliditySha3(message);
const hashSenderMsg = Web3Utils.soliditySha3(authorities[0], hashMsg)
true.should.be.equal(await foreignBridgeWithTwoSigs.messagesSigned(hashSenderMsg));
})
it('when enough requiredSignatures are collected, CollectedSignatures event is emitted', async () => {
var recipientAccount = accounts[8]
var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
var homeGasPrice = web3.toBigNumber(0);
var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
var signature = await sign(authoritiesTwoAccs[0], message)
var signature2 = await sign(authoritiesTwoAccs[1], message)
'2'.should.be.bignumber.equal(await validatorContractWith2Signatures.requiredSignatures());
await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authorities[0]}).should.be.fulfilled;
await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG);
await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authorities[1]}).should.be.rejectedWith(ERROR_MSG);
const {logs} = await foreignBridgeWithTwoSigs.submitSignature(signature2, message, {from: authorities[1]}).should.be.fulfilled;
logs.length.should.be.equal(2)
logs[1].event.should.be.equal('CollectedSignatures')
logs[1].args.authorityResponsibleForRelay.should.be.equal(authorities[1])
})
it('attack when increasing requiredSignatures', async () => {
var recipientAccount = accounts[8]
var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
var homeGasPrice = web3.toBigNumber(0);
var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
var signature = await sign(authoritiesTwoAccs[0], message)
var signature2 = await sign(authoritiesTwoAccs[1], message)
var signature3 = await sign(authoritiesTwoAccs[2], message)
'2'.should.be.bignumber.equal(await validatorContractWith2Signatures.requiredSignatures());
await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authoritiesTwoAccs[0]}).should.be.fulfilled;
await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authoritiesTwoAccs[0]}).should.be.rejectedWith(ERROR_MSG);
await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authoritiesTwoAccs[1]}).should.be.rejectedWith(ERROR_MSG);
const {logs} = await foreignBridgeWithTwoSigs.submitSignature(signature2, message, {from: authoritiesTwoAccs[1]}).should.be.fulfilled;
logs.length.should.be.equal(2)
logs[1].event.should.be.equal('CollectedSignatures')
logs[1].args.authorityResponsibleForRelay.should.be.equal(authorities[1])
await validatorContractWith2Signatures.setRequiredSignatures(3).should.be.fulfilled;
'3'.should.be.bignumber.equal(await validatorContractWith2Signatures.requiredSignatures());
const attackerTx = await foreignBridgeWithTwoSigs.submitSignature(signature3, message, {from: authoritiesTwoAccs[2]}).should.be.rejectedWith(ERROR_MSG);
})
it('attack when decreasing requiredSignatures', async () => {
var recipientAccount = accounts[8]
var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
var homeGasPrice = web3.toBigNumber(0);
var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
var signature = await sign(authoritiesTwoAccs[0], message)
var signature2 = await sign(authoritiesTwoAccs[1], message)
var signature3 = await sign(authoritiesTwoAccs[2], message)
'2'.should.be.bignumber.equal(await validatorContractWith2Signatures.requiredSignatures());
await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authoritiesTwoAccs[0]}).should.be.fulfilled;
await validatorContractWith2Signatures.setRequiredSignatures(1).should.be.fulfilled;
'1'.should.be.bignumber.equal(await validatorContractWith2Signatures.requiredSignatures());
const {logs} = await foreignBridgeWithTwoSigs.submitSignature(signature2, message, {from: authoritiesTwoAccs[1]}).should.be.fulfilled;
logs.length.should.be.equal(2)
logs[1].event.should.be.equal('CollectedSignatures')
logs[1].args.authorityResponsibleForRelay.should.be.equal(authorities[1])
})
})
// })
// it('allows a validator to submit a signature', async () => {
// var recipientAccount = accounts[8]
// var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
// var homeGasPrice = web3.toBigNumber(0);
// var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
// var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
// var signature = await sign(authoritiesTwoAccs[0], message)
// const {logs} = await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authorities[0]}).should.be.fulfilled;
// logs[0].event.should.be.equal('SignedForWithdraw')
// const msgHashFromLog = logs[0].args.messageHash
// const signatureFromContract = await foreignBridgeWithTwoSigs.signature(msgHashFromLog, 0);
// const messageFromContract = await foreignBridgeWithTwoSigs.message(msgHashFromLog);
// signature.should.be.equal(signatureFromContract);
// messageFromContract.should.be.equal(messageFromContract);
// const hashMsg = Web3Utils.soliditySha3(message);
// const hashSenderMsg = Web3Utils.soliditySha3(authorities[0], hashMsg)
// true.should.be.equal(await foreignBridgeWithTwoSigs.messagesSigned(hashSenderMsg));
// })
// it('when enough requiredSignatures are collected, CollectedSignatures event is emitted', async () => {
// var recipientAccount = accounts[8]
// var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
// var homeGasPrice = web3.toBigNumber(0);
// var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
// var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
// var signature = await sign(authoritiesTwoAccs[0], message)
// var signature2 = await sign(authoritiesTwoAccs[1], message)
// '2'.should.be.bignumber.equal(await validatorContractWith2Signatures.requiredSignatures());
// await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authorities[0]}).should.be.fulfilled;
// await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authorities[0]}).should.be.rejectedWith(ERROR_MSG);
// await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authorities[1]}).should.be.rejectedWith(ERROR_MSG);
// const {logs} = await foreignBridgeWithTwoSigs.submitSignature(signature2, message, {from: authorities[1]}).should.be.fulfilled;
// logs.length.should.be.equal(2)
// logs[1].event.should.be.equal('CollectedSignatures')
// logs[1].args.authorityResponsibleForRelay.should.be.equal(authorities[1])
// })
// it('attack when increasing requiredSignatures', async () => {
// var recipientAccount = accounts[8]
// var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
// var homeGasPrice = web3.toBigNumber(0);
// var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
// var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
// var signature = await sign(authoritiesTwoAccs[0], message)
// var signature2 = await sign(authoritiesTwoAccs[1], message)
// var signature3 = await sign(authoritiesTwoAccs[2], message)
// '2'.should.be.bignumber.equal(await validatorContractWith2Signatures.requiredSignatures());
// await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authoritiesTwoAccs[0]}).should.be.fulfilled;
// await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authoritiesTwoAccs[0]}).should.be.rejectedWith(ERROR_MSG);
// await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authoritiesTwoAccs[1]}).should.be.rejectedWith(ERROR_MSG);
// const {logs} = await foreignBridgeWithTwoSigs.submitSignature(signature2, message, {from: authoritiesTwoAccs[1]}).should.be.fulfilled;
// logs.length.should.be.equal(2)
// logs[1].event.should.be.equal('CollectedSignatures')
// logs[1].args.authorityResponsibleForRelay.should.be.equal(authorities[1])
// await validatorContractWith2Signatures.setRequiredSignatures(3).should.be.fulfilled;
// '3'.should.be.bignumber.equal(await validatorContractWith2Signatures.requiredSignatures());
// const attackerTx = await foreignBridgeWithTwoSigs.submitSignature(signature3, message, {from: authoritiesTwoAccs[2]}).should.be.rejectedWith(ERROR_MSG);
// })
// it('attack when decreasing requiredSignatures', async () => {
// var recipientAccount = accounts[8]
// var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
// var homeGasPrice = web3.toBigNumber(0);
// var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
// var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
// var signature = await sign(authoritiesTwoAccs[0], message)
// var signature2 = await sign(authoritiesTwoAccs[1], message)
// var signature3 = await sign(authoritiesTwoAccs[2], message)
// '2'.should.be.bignumber.equal(await validatorContractWith2Signatures.requiredSignatures());
// await foreignBridgeWithTwoSigs.submitSignature(signature, message, {from: authoritiesTwoAccs[0]}).should.be.fulfilled;
// await validatorContractWith2Signatures.setRequiredSignatures(1).should.be.fulfilled;
// '1'.should.be.bignumber.equal(await validatorContractWith2Signatures.requiredSignatures());
// const {logs} = await foreignBridgeWithTwoSigs.submitSignature(signature2, message, {from: authoritiesTwoAccs[1]}).should.be.fulfilled;
// logs.length.should.be.equal(2)
// logs[1].event.should.be.equal('CollectedSignatures')
// logs[1].args.authorityResponsibleForRelay.should.be.equal(authorities[1])
// })
// })
describe('#setting limits', async () => {
let foreignBridge;

View File

@ -127,171 +127,171 @@ contract('HomeBridge', async (accounts) => {
}).should.be.rejectedWith(ERROR_MSG)
})
})
describe('#withdraw', async () => {
beforeEach(async () => {
homeContract = await HomeBridge.new()
const oneEther = web3.toBigNumber(web3.toWei(1, "ether"));
const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether"));
await homeContract.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
oneEther.should.be.bignumber.equal(await homeContract.homeDailyLimit());
await homeContract.sendTransaction({
from: accounts[1],
value: halfEther
}).should.be.fulfilled
})
it('should allow to withdraw', async () => {
var recipientAccount = accounts[3];
const balanceBefore = await web3.eth.getBalance(recipientAccount)
const homeBalanceBefore = await web3.eth.getBalance(homeContract.address)
var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
var homeGasPrice = web3.toBigNumber(0);
var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
var signature = await sign(authorities[0], message)
var vrs = signatureToVRS(signature);
false.should.be.equal(await homeContract.withdraws(transactionHash))
const {logs} = await homeContract.withdraw([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
logs[0].event.should.be.equal("Withdraw")
logs[0].args.recipient.should.be.equal(recipientAccount)
logs[0].args.value.should.be.bignumber.equal(value)
logs[0].args.transactionHash.should.be.equal(transactionHash);
const balanceAfter = await web3.eth.getBalance(recipientAccount)
const homeBalanceAfter = await web3.eth.getBalance(homeContract.address)
balanceAfter.should.be.bignumber.equal(balanceBefore.add(value))
homeBalanceAfter.should.be.bignumber.equal(homeBalanceBefore.sub(value))
true.should.be.equal(await homeContract.withdraws(transactionHash))
})
it('should allow second withdraw with different transactionHash but same recipient and value', async ()=> {
var recipientAccount = accounts[3];
const balanceBefore = await web3.eth.getBalance(recipientAccount)
const homeBalanceBefore = await web3.eth.getBalance(homeContract.address)
// tx 1
var value = web3.toBigNumber(web3.toWei(0.25, "ether"));
var homeGasPrice = web3.toBigNumber(0);
var transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
var signature = await sign(authorities[0], message)
var vrs = signatureToVRS(signature);
false.should.be.equal(await homeContract.withdraws(transactionHash))
await homeContract.withdraw([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
// tx 2
var transactionHash2 = "0x77a496628a776a03d58d7e6059a5937f04bebd8ba4ff89f76dd4bb8ba7e291ee";
var message2 = createMessage(recipientAccount, value, transactionHash2, homeGasPrice);
var signature2 = await sign(authorities[0], message2)
var vrs2 = signatureToVRS(signature2);
false.should.be.equal(await homeContract.withdraws(transactionHash2))
const {logs} = await homeContract.withdraw([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.fulfilled
// describe('#withdraw', async () => {
// beforeEach(async () => {
// homeContract = await HomeBridge.new()
// const oneEther = web3.toBigNumber(web3.toWei(1, "ether"));
// const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether"));
// await homeContract.initialize(validatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations);
// oneEther.should.be.bignumber.equal(await homeContract.homeDailyLimit());
// await homeContract.sendTransaction({
// from: accounts[1],
// value: halfEther
// }).should.be.fulfilled
// })
// it('should allow to withdraw', async () => {
// var recipientAccount = accounts[3];
// const balanceBefore = await web3.eth.getBalance(recipientAccount)
// const homeBalanceBefore = await web3.eth.getBalance(homeContract.address)
// var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
// var homeGasPrice = web3.toBigNumber(0);
// var transactionHash = "0x1045bfe274b88120a6b1e5d01b5ec00ab5d01098346e90e7c7a3c9b8f0181c80";
// var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
// var signature = await sign(authorities[0], message)
// var vrs = signatureToVRS(signature);
// false.should.be.equal(await homeContract.withdraws(transactionHash))
// const {logs} = await homeContract.withdraw([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
// logs[0].event.should.be.equal("Withdraw")
// logs[0].args.recipient.should.be.equal(recipientAccount)
// logs[0].args.value.should.be.bignumber.equal(value)
// logs[0].args.transactionHash.should.be.equal(transactionHash);
// const balanceAfter = await web3.eth.getBalance(recipientAccount)
// const homeBalanceAfter = await web3.eth.getBalance(homeContract.address)
// balanceAfter.should.be.bignumber.equal(balanceBefore.add(value))
// homeBalanceAfter.should.be.bignumber.equal(homeBalanceBefore.sub(value))
// true.should.be.equal(await homeContract.withdraws(transactionHash))
// })
// it('should allow second withdraw with different transactionHash but same recipient and value', async ()=> {
// var recipientAccount = accounts[3];
// const balanceBefore = await web3.eth.getBalance(recipientAccount)
// const homeBalanceBefore = await web3.eth.getBalance(homeContract.address)
// // tx 1
// var value = web3.toBigNumber(web3.toWei(0.25, "ether"));
// var homeGasPrice = web3.toBigNumber(0);
// var transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
// var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
// var signature = await sign(authorities[0], message)
// var vrs = signatureToVRS(signature);
// false.should.be.equal(await homeContract.withdraws(transactionHash))
// await homeContract.withdraw([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
// // tx 2
// var transactionHash2 = "0x77a496628a776a03d58d7e6059a5937f04bebd8ba4ff89f76dd4bb8ba7e291ee";
// var message2 = createMessage(recipientAccount, value, transactionHash2, homeGasPrice);
// var signature2 = await sign(authorities[0], message2)
// var vrs2 = signatureToVRS(signature2);
// false.should.be.equal(await homeContract.withdraws(transactionHash2))
// const {logs} = await homeContract.withdraw([vrs2.v], [vrs2.r], [vrs2.s], message2).should.be.fulfilled
logs[0].event.should.be.equal("Withdraw")
logs[0].args.recipient.should.be.equal(recipientAccount)
logs[0].args.value.should.be.bignumber.equal(value)
logs[0].args.transactionHash.should.be.equal(transactionHash2);
const balanceAfter = await web3.eth.getBalance(recipientAccount)
const homeBalanceAfter = await web3.eth.getBalance(homeContract.address)
balanceAfter.should.be.bignumber.equal(balanceBefore.add(value.mul(2)))
homeBalanceAfter.should.be.bignumber.equal(0)
true.should.be.equal(await homeContract.withdraws(transactionHash))
true.should.be.equal(await homeContract.withdraws(transactionHash2))
})
// logs[0].event.should.be.equal("Withdraw")
// logs[0].args.recipient.should.be.equal(recipientAccount)
// logs[0].args.value.should.be.bignumber.equal(value)
// logs[0].args.transactionHash.should.be.equal(transactionHash2);
// const balanceAfter = await web3.eth.getBalance(recipientAccount)
// const homeBalanceAfter = await web3.eth.getBalance(homeContract.address)
// balanceAfter.should.be.bignumber.equal(balanceBefore.add(value.mul(2)))
// homeBalanceAfter.should.be.bignumber.equal(0)
// true.should.be.equal(await homeContract.withdraws(transactionHash))
// true.should.be.equal(await homeContract.withdraws(transactionHash2))
// })
it('should not allow if there are not enough funds in the contract', async () => {
var recipientAccount = accounts[3];
const balanceBefore = await web3.eth.getBalance(recipientAccount)
const homeBalanceBefore = await web3.eth.getBalance(homeContract.address)
// tx 1
var value = web3.toBigNumber(web3.toWei(1.01, "ether"));
var homeGasPrice = web3.toBigNumber(0);
var transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
var signature = await sign(authorities[0], message)
var vrs = signatureToVRS(signature);
false.should.be.equal(await homeContract.withdraws(transactionHash))
await homeContract.withdraw([vrs.v], [vrs.r], [vrs.s], message).should.be.rejectedWith(ERROR_MSG)
// it('should not allow if there are not enough funds in the contract', async () => {
// var recipientAccount = accounts[3];
// const balanceBefore = await web3.eth.getBalance(recipientAccount)
// const homeBalanceBefore = await web3.eth.getBalance(homeContract.address)
// // tx 1
// var value = web3.toBigNumber(web3.toWei(1.01, "ether"));
// var homeGasPrice = web3.toBigNumber(0);
// var transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
// var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
// var signature = await sign(authorities[0], message)
// var vrs = signatureToVRS(signature);
// false.should.be.equal(await homeContract.withdraws(transactionHash))
// await homeContract.withdraw([vrs.v], [vrs.r], [vrs.s], message).should.be.rejectedWith(ERROR_MSG)
})
it('should not allow second withdraw (replay attack) with same transactionHash but different recipient', async () => {
var recipientAccount = accounts[3];
const balanceBefore = await web3.eth.getBalance(recipientAccount)
const homeBalanceBefore = await web3.eth.getBalance(homeContract.address)
// tx 1
var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
var homeGasPrice = web3.toBigNumber(0);
var transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
var signature = await sign(authorities[0], message)
var vrs = signatureToVRS(signature);
false.should.be.equal(await homeContract.withdraws(transactionHash))
await homeContract.withdraw([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
// tx 2
var message2 = createMessage(accounts[4], value, transactionHash, homeGasPrice);
var signature2 = await sign(authorities[0], message2)
var vrs = signatureToVRS(signature2);
true.should.be.equal(await homeContract.withdraws(transactionHash))
await homeContract.withdraw([vrs.v], [vrs.r], [vrs.s], message2).should.be.rejectedWith(ERROR_MSG)
})
})
// })
// it('should not allow second withdraw (replay attack) with same transactionHash but different recipient', async () => {
// var recipientAccount = accounts[3];
// const balanceBefore = await web3.eth.getBalance(recipientAccount)
// const homeBalanceBefore = await web3.eth.getBalance(homeContract.address)
// // tx 1
// var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
// var homeGasPrice = web3.toBigNumber(0);
// var transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
// var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
// var signature = await sign(authorities[0], message)
// var vrs = signatureToVRS(signature);
// false.should.be.equal(await homeContract.withdraws(transactionHash))
// await homeContract.withdraw([vrs.v], [vrs.r], [vrs.s], message).should.be.fulfilled
// // tx 2
// var message2 = createMessage(accounts[4], value, transactionHash, homeGasPrice);
// var signature2 = await sign(authorities[0], message2)
// var vrs = signatureToVRS(signature2);
// true.should.be.equal(await homeContract.withdraws(transactionHash))
// await homeContract.withdraw([vrs.v], [vrs.r], [vrs.s], message2).should.be.rejectedWith(ERROR_MSG)
// })
// })
describe('#withdraw with 2 minimum signatures', async () => {
let multisigValidatorContract, twoAuthorities, ownerOfValidatorContract, homeContractWithMultiSignatures
beforeEach(async () => {
multisigValidatorContract = await BridgeValidators.new()
twoAuthorities = [accounts[0], accounts[1]];
ownerOfValidatorContract = accounts[3]
const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether"));
await multisigValidatorContract.initialize(2, twoAuthorities, ownerOfValidatorContract, {from: ownerOfValidatorContract})
homeContractWithMultiSignatures = await HomeBridge.new()
const oneEther = web3.toBigNumber(web3.toWei(1, "ether"));
await homeContractWithMultiSignatures.initialize(multisigValidatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, {from: ownerOfValidatorContract});
await homeContractWithMultiSignatures.sendTransaction({
from: accounts[1],
value: halfEther
}).should.be.fulfilled
})
it('withdraw should fail if not enough signatures are provided', async () => {
// describe('#withdraw with 2 minimum signatures', async () => {
// let multisigValidatorContract, twoAuthorities, ownerOfValidatorContract, homeContractWithMultiSignatures
// beforeEach(async () => {
// multisigValidatorContract = await BridgeValidators.new()
// twoAuthorities = [accounts[0], accounts[1]];
// ownerOfValidatorContract = accounts[3]
// const halfEther = web3.toBigNumber(web3.toWei(0.5, "ether"));
// await multisigValidatorContract.initialize(2, twoAuthorities, ownerOfValidatorContract, {from: ownerOfValidatorContract})
// homeContractWithMultiSignatures = await HomeBridge.new()
// const oneEther = web3.toBigNumber(web3.toWei(1, "ether"));
// await homeContractWithMultiSignatures.initialize(multisigValidatorContract.address, oneEther, halfEther, minPerTx, gasPrice, requireBlockConfirmations, {from: ownerOfValidatorContract});
// await homeContractWithMultiSignatures.sendTransaction({
// from: accounts[1],
// value: halfEther
// }).should.be.fulfilled
// })
// it('withdraw should fail if not enough signatures are provided', async () => {
var recipientAccount = accounts[4];
const balanceBefore = await web3.eth.getBalance(recipientAccount)
const homeBalanceBefore = await web3.eth.getBalance(homeContractWithMultiSignatures.address)
// msg 1
var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
var homeGasPrice = web3.toBigNumber(0);
var transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
var signature = await sign(twoAuthorities[0], message)
var vrs = signatureToVRS(signature);
false.should.be.equal(await homeContractWithMultiSignatures.withdraws(transactionHash))
await homeContractWithMultiSignatures.withdraw([vrs.v], [vrs.r], [vrs.s], message).should.be.rejectedWith(ERROR_MSG)
// msg 2
var signature2 = await sign(twoAuthorities[1], message)
var vrs2 = signatureToVRS(signature2);
const {logs} = await homeContractWithMultiSignatures.withdraw([vrs.v, vrs2.v], [vrs.r, vrs2.r], [vrs.s, vrs2.s], message).should.be.fulfilled;
// var recipientAccount = accounts[4];
// const balanceBefore = await web3.eth.getBalance(recipientAccount)
// const homeBalanceBefore = await web3.eth.getBalance(homeContractWithMultiSignatures.address)
// // msg 1
// var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
// var homeGasPrice = web3.toBigNumber(0);
// var transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
// var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
// var signature = await sign(twoAuthorities[0], message)
// var vrs = signatureToVRS(signature);
// false.should.be.equal(await homeContractWithMultiSignatures.withdraws(transactionHash))
// await homeContractWithMultiSignatures.withdraw([vrs.v], [vrs.r], [vrs.s], message).should.be.rejectedWith(ERROR_MSG)
// // msg 2
// var signature2 = await sign(twoAuthorities[1], message)
// var vrs2 = signatureToVRS(signature2);
// const {logs} = await homeContractWithMultiSignatures.withdraw([vrs.v, vrs2.v], [vrs.r, vrs2.r], [vrs.s, vrs2.s], message).should.be.fulfilled;
logs[0].event.should.be.equal("Withdraw")
logs[0].args.recipient.should.be.equal(recipientAccount)
logs[0].args.value.should.be.bignumber.equal(value)
logs[0].args.transactionHash.should.be.equal(transactionHash);
const balanceAfter = await web3.eth.getBalance(recipientAccount)
const homeBalanceAfter = await web3.eth.getBalance(homeContractWithMultiSignatures.address)
balanceAfter.should.be.bignumber.equal(balanceBefore.add(value))
homeBalanceAfter.should.be.bignumber.equal(homeBalanceBefore.sub(value))
true.should.be.equal(await homeContractWithMultiSignatures.withdraws(transactionHash))
// logs[0].event.should.be.equal("Withdraw")
// logs[0].args.recipient.should.be.equal(recipientAccount)
// logs[0].args.value.should.be.bignumber.equal(value)
// logs[0].args.transactionHash.should.be.equal(transactionHash);
// const balanceAfter = await web3.eth.getBalance(recipientAccount)
// const homeBalanceAfter = await web3.eth.getBalance(homeContractWithMultiSignatures.address)
// balanceAfter.should.be.bignumber.equal(balanceBefore.add(value))
// homeBalanceAfter.should.be.bignumber.equal(homeBalanceBefore.sub(value))
// true.should.be.equal(await homeContractWithMultiSignatures.withdraws(transactionHash))
})
it('withdraw should fail if duplicate signature is provided', async () => {
var recipientAccount = accounts[4];
const balanceBefore = await web3.eth.getBalance(recipientAccount)
const homeBalanceBefore = await web3.eth.getBalance(homeContractWithMultiSignatures.address)
// msg 1
var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
var homeGasPrice = web3.toBigNumber(0);
var transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
var signature = await sign(twoAuthorities[0], message)
var vrs = signatureToVRS(signature);
false.should.be.equal(await homeContractWithMultiSignatures.withdraws(transactionHash))
await homeContractWithMultiSignatures.withdraw([vrs.v, vrs.v], [vrs.r, vrs.r], [vrs.s, vrs.s], message).should.be.rejectedWith(ERROR_MSG)
})
})
// })
// it('withdraw should fail if duplicate signature is provided', async () => {
// var recipientAccount = accounts[4];
// const balanceBefore = await web3.eth.getBalance(recipientAccount)
// const homeBalanceBefore = await web3.eth.getBalance(homeContractWithMultiSignatures.address)
// // msg 1
// var value = web3.toBigNumber(web3.toWei(0.5, "ether"));
// var homeGasPrice = web3.toBigNumber(0);
// var transactionHash = "0x35d3818e50234655f6aebb2a1cfbf30f59568d8a4ec72066fac5a25dbe7b8121";
// var message = createMessage(recipientAccount, value, transactionHash, homeGasPrice);
// var signature = await sign(twoAuthorities[0], message)
// var vrs = signatureToVRS(signature);
// false.should.be.equal(await homeContractWithMultiSignatures.withdraws(transactionHash))
// await homeContractWithMultiSignatures.withdraw([vrs.v, vrs.v], [vrs.r, vrs.r], [vrs.s, vrs.s], message).should.be.rejectedWith(ERROR_MSG)
// })
// })
describe('#setting limits', async () => {
let homeContract;
beforeEach(async () => {