Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge the develop branch to the master branch, preparation to v4.0.0-rc0 #361

Merged
merged 6 commits into from
Jan 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 14 additions & 26 deletions contracts/libraries/Message.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,38 +96,26 @@ library Message {
}
}

function hasEnoughValidSignatures(
bytes _message,
uint8[] _vs,
bytes32[] _rs,
bytes32[] _ss,
IBridgeValidators _validatorContract,
bool isAMBMessage
) internal view {
require(isAMBMessage || (!isAMBMessage && isMessageValid(_message)));
uint256 requiredSignatures = _validatorContract.requiredSignatures();
// It is not necessary to check that arrays have the same length since it will be handled
// during attempt to access to the corresponding elements in the loop and the call will be reverted.
// It will save gas for the rational validators actions and still be safe enough from security point of view
require(_vs.length >= requiredSignatures);
bytes32 hash = hashMessage(_message, isAMBMessage);
address[] memory encounteredAddresses = new address[](requiredSignatures);

for (uint256 i = 0; i < requiredSignatures; i++) {
address recoveredAddress = ecrecover(hash, _vs[i], _rs[i], _ss[i]);
require(_validatorContract.isValidator(recoveredAddress));
require(!addressArrayContains(encounteredAddresses, recoveredAddress));
encounteredAddresses[i] = recoveredAddress;
}
}

/**
* @dev Validates provided signatures, only first requiredSignatures() number
* of signatures are going to be validated, these signatures should be from different validators.
* @param _message bytes message used to generate signatures
* @param _signatures bytes blob with signatures to be validated.
* First byte X is a number of signatures in a blob,
* next X bytes are v components of signatures,
* next 32 * X bytes are r components of signatures,
* next 32 * X bytes are s components of signatures.
* @param _validatorContract contract, which conforms to the IBridgeValidators interface,
* where info about current validators and required signatures is stored.
* @param isAMBMessage true if _message is an AMB message with arbitrary length.
*/
function hasEnoughValidSignatures(
bytes _message,
bytes _signatures,
IBridgeValidators _validatorContract,
bool isAMBMessage
) internal view {
require(isAMBMessage || (!isAMBMessage && isMessageValid(_message)));
require(isAMBMessage || isMessageValid(_message));
uint256 requiredSignatures = _validatorContract.requiredSignatures();
uint256 amount;
assembly {
Expand Down
10 changes: 8 additions & 2 deletions contracts/upgradeable_contracts/BasicForeignBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@ contract BasicForeignBridge is EternalStorage, Validatable, BasicBridge, BasicTo
event RelayedMessage(address recipient, uint256 value, bytes32 transactionHash);
event UserRequestForAffirmation(address recipient, uint256 value);

function executeSignatures(uint8[] vs, bytes32[] rs, bytes32[] ss, bytes message) external {
Message.hasEnoughValidSignatures(message, vs, rs, ss, validatorContract(), false);
/**
* @dev Validates provided signatures and relays a given message
* @param message bytes to be relayed
* @param signatures bytes blob with signatures to be validated
*/
function executeSignatures(bytes message, bytes signatures) external {
Message.hasEnoughValidSignatures(message, signatures, validatorContract(), false);

address recipient;
uint256 amount;
bytes32 txHash;
Expand Down
2 changes: 1 addition & 1 deletion contracts/upgradeable_contracts/VersionableBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pragma solidity 0.4.24;

contract VersionableBridge {
function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
return (2, 5, 0);
return (3, 0, 0);
}

/* solcov ignore next */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ contract BasicAMB is BasicBridge {
address _owner
) external onlyRelevantSender returns (bool) {
require(!isInitialized());
require(_validatorContract != address(0) && AddressUtils.isContract(_validatorContract));
require(AddressUtils.isContract(_validatorContract));
require(_gasPrice > 0);
require(_requiredBlockConfirmations > 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import "./MessageProcessor.sol";
import "../MessageRelay.sol";

contract BasicForeignAMB is BasicAMB, MessageRelay, MessageDelivery, MessageProcessor {
/**
* @dev Validates provided signatures and relays a given message
* @param _data bytes to be relayed
* @param _signatures bytes blob with signatures to be validated
*/
function executeSignatures(bytes _data, bytes _signatures) external {
Message.hasEnoughValidSignatures(_data, _signatures, validatorContract(), true);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ contract MessageDelivery is BasicAMB {
function getMinimumGasUsage(bytes _data) public pure returns (uint256 gas) {
//From Ethereum Yellow Paper
// 68 gas is paid for every non-zero byte of data or code for a transaction
return _data.length.mul(68);
// Starting from Istanbul hardfork, 16 gas is paid (EIP-2028)
return _data.length.mul(16);
}

/* solcov ignore next */
Expand Down
49 changes: 25 additions & 24 deletions deploy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,10 @@ BRIDGE_MODE=ARBITRARY_MESSAGE
# deployments and initial configuration. The account's balance must contain
# funds from both networks.
DEPLOYMENT_ACCOUNT_PRIVATE_KEY=67..14
# The "gas" parameter set in every deployment/configuration transaction.
DEPLOYMENT_GAS_LIMIT=5000000
# Extra gas added to the estimated gas of a particular deployment/configuration transaction
# E.g. if estimated gas returns 100000 and the parameter is 0.2,
# the transaction gas limit will be (100000 + 100000 * 0.2) = 120000
DEPLOYMENT_GAS_LIMIT_EXTRA=0.2
# The "gasPrice" parameter set in every deployment/configuration transaction on
# Home network (in Wei).
HOME_DEPLOYMENT_GAS_PRICE=10000000000
Expand All @@ -484,17 +486,16 @@ GET_RECEIPT_INTERVAL_IN_MILLISECONDS=3000
# The RPC channel to a Home node able to handle deployment/configuration
# transactions.
HOME_RPC_URL=https://poa.infura.io
# The address of an administrator on the Home network who can change bridge
# parameters and a validator's contract. For extra security we recommended using
# a multi-sig wallet contract address here.
HOME_OWNER_MULTISIG=0x
# The address from which a validator's contract can be upgraded on Home.
HOME_UPGRADEABLE_ADMIN_VALIDATORS=0x
# The address from which the bridge's contract can be upgraded on Home.
HOME_UPGRADEABLE_ADMIN_BRIDGE=0x

# The maximum value of estimated gas for one transaction in Wei.
HOME_MAX_AMOUNT_PER_TX=1500000000000000000000000
# Address on Home network with permissions to change parameters of the bridge contract.
# For extra security we recommended using a multi-sig wallet contract address here.
HOME_BRIDGE_OWNER=0x
# Address on Home network with permissions to change parameters of bridge validator contract.
HOME_VALIDATORS_OWNER=0x
# Address on Home network with permissions to upgrade the bridge contract and the
# bridge validator contract.
HOME_UPGRADEABLE_ADMIN=0x
# The maximum value of gas for one call to be allowed for relaying.
HOME_MAX_AMOUNT_PER_TX=20000000
# The finalization threshold. The number of blocks issued after the block with
# the corresponding deposit transaction to guarantee the transaction will not be
# rolled back.
Expand All @@ -507,16 +508,16 @@ HOME_GAS_PRICE=1000000000
# The RPC channel to a Foreign node able to handle deployment/configuration
# transactions.
FOREIGN_RPC_URL=https://mainnet.infura.io
# The address of an administrator on the Foreign network who can change bridge
# parameters and the validator's contract. For extra security we recommended
# using a multi-sig wallet contract address here.
FOREIGN_OWNER_MULTISIG=0x
# The address from which a validator's contract can be upgraded on Foreign.
FOREIGN_UPGRADEABLE_ADMIN_VALIDATORS=0x
# The address from which the bridge's contract can be upgraded on Foreign.
FOREIGN_UPGRADEABLE_ADMIN_BRIDGE=0x
# The maximum value of estimated gas for one transaction in Wei.
FOREIGN_MAX_AMOUNT_PER_TX=1500000000000000000000000
# Address on Foreign network with permissions to change parameters of the bridge contract.
# For extra security we recommended using a multi-sig wallet contract address here.
FOREIGN_BRIDGE_OWNER=0x
# Address on Foreign network with permissions to change parameters of bridge validator contract.
FOREIGN_VALIDATORS_OWNER=0x
# Address on Foreign network with permissions to upgrade the bridge contract and the
# bridge validator contract.
FOREIGN_UPGRADEABLE_ADMIN=0x
# The maximum value of gas for one call to be allowed for relaying.
FOREIGN_MAX_AMOUNT_PER_TX=20000000
# The finalization threshold. The number of blocks issued after the block with
# the corresponding deposit transaction to guarantee the transaction will not be
# rolled back.
Expand All @@ -534,7 +535,7 @@ REQUIRED_NUMBER_OF_VALIDATORS=1
# addresses are collected on the Home side. The same addresses will be used on
# the Foreign network to confirm that the finalized agreement was transferred
# correctly to the Foreign network.
VALIDATORS="0x 0x 0x"
VALIDATORS=0x 0x 0x

# The api url of an explorer to verify all the deployed contracts in Home network. Supported explorers: Blockscout, etherscan
#HOME_EXPLORER_URL=https://blockscout.com/poa/core/api
Expand Down
20 changes: 9 additions & 11 deletions deploy/src/arbitrary_message/foreign.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@ async function initializeBridge({ validatorsBridge, bridge, initialNonce }) {
let nonce = initialNonce

console.log(`Foreign Validators: ${validatorsBridge.options.address},
FOREIGN_MAX_AMOUNT_PER_TX: ${FOREIGN_MAX_AMOUNT_PER_TX} which is ${Web3Utils.fromWei(
FOREIGN_MAX_AMOUNT_PER_TX
)} in eth,
HOME_GAS_PRICE: ${FOREIGN_GAS_PRICE}, HOME_REQUIRED_BLOCK_CONFIRMATIONS : ${FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS}
FOREIGN_MAX_AMOUNT_PER_TX (gas limit per call): ${FOREIGN_MAX_AMOUNT_PER_TX},
FOREIGN_GAS_PRICE: ${FOREIGN_GAS_PRICE}, FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS : ${FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS}
`)
const initializeFBridgeData = await bridge.methods
.initialize(
Expand Down Expand Up @@ -69,7 +67,7 @@ async function initializeBridge({ validatorsBridge, bridge, initialNonce }) {

async function deployForeign() {
console.log('========================================')
console.log('deploying ForeignBridge')
console.log('Deploying Arbitrary Message Bridge at Foreign')
console.log('========================================\n')

let nonce = await web3Foreign.eth.getTransactionCount(DEPLOYMENT_ACCOUNT_ADDRESS)
Expand Down Expand Up @@ -125,25 +123,25 @@ async function deployForeign() {
})
nonce++

console.log('\ndeploying foreignBridge storage\n')
console.log('\ndeploying ForeignAMBridge storage\n')
const foreignBridgeStorage = await deployContract(EternalStorageProxy, [], {
from: DEPLOYMENT_ACCOUNT_ADDRESS,
network: 'foreign',
nonce
})
nonce++
console.log('[Foreign] ForeignBridge Storage: ', foreignBridgeStorage.options.address)
console.log('[Foreign] ForeignAMBridge Storage: ', foreignBridgeStorage.options.address)

console.log('\ndeploying foreignBridge implementation\n')
console.log('\ndeploying ForeignAMBridge implementation\n')
const foreignBridgeImplementation = await deployContract(ForeignBridge, [], {
from: DEPLOYMENT_ACCOUNT_ADDRESS,
network: 'foreign',
nonce
})
nonce++
console.log('[Foreign] ForeignBridge Implementation: ', foreignBridgeImplementation.options.address)
console.log('[Foreign] ForeignAMBridge Implementation: ', foreignBridgeImplementation.options.address)

console.log('\nhooking up ForeignBridge storage to ForeignBridge implementation')
console.log('\nhooking up ForeignAMBridge storage to ForeignAMBridge implementation')
await upgradeProxy({
proxy: foreignBridgeStorage,
implementationAddress: foreignBridgeImplementation.options.address,
Expand All @@ -169,7 +167,7 @@ async function deployForeign() {
url: FOREIGN_RPC_URL
})

console.log('\nForeign Deployment Bridge completed\n')
console.log('\nDeployment of Arbitrary Message Bridge at Foreign completed\n')

return {
foreignBridge: {
Expand Down
16 changes: 8 additions & 8 deletions deploy/src/arbitrary_message/home.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ async function initializeBridge({ validatorsBridge, bridge, initialNonce }) {
let nonce = initialNonce
console.log('\ninitializing Home Bridge with following parameters:\n')
console.log(`Home Validators: ${validatorsBridge.options.address},
HOME_MAX_AMOUNT_PER_TX: ${HOME_MAX_AMOUNT_PER_TX} which is ${Web3Utils.fromWei(HOME_MAX_AMOUNT_PER_TX)} in eth,
HOME_MAX_AMOUNT_PER_TX (gas limit per call): ${HOME_MAX_AMOUNT_PER_TX},
HOME_GAS_PRICE: ${HOME_GAS_PRICE}, HOME_REQUIRED_BLOCK_CONFIRMATIONS : ${HOME_REQUIRED_BLOCK_CONFIRMATIONS}
`)
const initializeHomeBridgeData = await bridge.methods
Expand Down Expand Up @@ -67,7 +67,7 @@ async function initializeBridge({ validatorsBridge, bridge, initialNonce }) {

async function deployHome() {
console.log('========================================')
console.log('Deploying HomeBridge')
console.log('Deploying Arbitrary Message Bridge at Home')
console.log('========================================\n')

let nonce = await web3Home.eth.getTransactionCount(DEPLOYMENT_ACCOUNT_ADDRESS)
Expand Down Expand Up @@ -121,23 +121,23 @@ async function deployHome() {
})
nonce++

console.log('\ndeploying homeBridge storage\n')
console.log('\ndeploying HomeAMBridge storage\n')
const homeBridgeStorage = await deployContract(EternalStorageProxy, [], {
from: DEPLOYMENT_ACCOUNT_ADDRESS,
nonce
})
nonce++
console.log('[Home] HomeBridge Storage: ', homeBridgeStorage.options.address)
console.log('[Home] HomeAMBridge Storage: ', homeBridgeStorage.options.address)

console.log('\ndeploying homeBridge implementation\n')
console.log('\ndeploying HomeAMBridge implementation\n')
const homeBridgeImplementation = await deployContract(HomeBridge, [], {
from: DEPLOYMENT_ACCOUNT_ADDRESS,
nonce
})
nonce++
console.log('[Home] HomeBridge Implementation: ', homeBridgeImplementation.options.address)
console.log('[Home] HomeAMBridge Implementation: ', homeBridgeImplementation.options.address)

console.log('\nhooking up HomeBridge storage to HomeBridge implementation')
console.log('\nhooking up HomeAMBridge storage to HomeAMBridge implementation')
await upgradeProxy({
proxy: homeBridgeStorage,
implementationAddress: homeBridgeImplementation.options.address,
Expand All @@ -162,7 +162,7 @@ async function deployHome() {
url: HOME_RPC_URL
})

console.log('\nHome Deployment Bridge completed\n')
console.log('\nDeployment of Arbitrary Message Bridge at Home completed\n')
return {
homeBridge: {
address: homeBridgeStorage.options.address,
Expand Down
8 changes: 4 additions & 4 deletions deploy/src/loadEnv.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ if (BRIDGE_MODE === 'AMB_ERC_TO_ERC') {
BRIDGEABLE_TOKEN_DECIMALS: envalid.num(),
FOREIGN_MIN_AMOUNT_PER_TX: bigNumValidator(),
FOREIGN_DAILY_LIMIT: bigNumValidator(),
DEPLOY_REWARDABLE_TOKEN: envalid.bool()
DEPLOY_REWARDABLE_TOKEN: envalid.bool({default: false})
}

if (DEPLOY_REWARDABLE_TOKEN === 'true') {
Expand Down Expand Up @@ -202,7 +202,7 @@ if (BRIDGE_MODE === 'NATIVE_TO_ERC') {
BRIDGEABLE_TOKEN_SYMBOL: envalid.str(),
BRIDGEABLE_TOKEN_DECIMALS: envalid.num(),
FOREIGN_MIN_AMOUNT_PER_TX: bigNumValidator(),
DEPLOY_REWARDABLE_TOKEN: envalid.bool()
DEPLOY_REWARDABLE_TOKEN: envalid.bool({default: false})
}

if (DEPLOY_REWARDABLE_TOKEN === 'true') {
Expand All @@ -221,8 +221,8 @@ if (BRIDGE_MODE === 'ERC_TO_ERC') {
BRIDGEABLE_TOKEN_NAME: envalid.str(),
BRIDGEABLE_TOKEN_SYMBOL: envalid.str(),
BRIDGEABLE_TOKEN_DECIMALS: envalid.num(),
DEPLOY_REWARDABLE_TOKEN: envalid.bool(),
ERC20_EXTENDED_BY_ERC677: envalid.bool(),
DEPLOY_REWARDABLE_TOKEN: envalid.bool({default: false}),
ERC20_EXTENDED_BY_ERC677: envalid.bool({default: false}),
FOREIGN_MIN_AMOUNT_PER_TX: bigNumValidator()
}

Expand Down
Loading