Skip to content

Commit

Permalink
Add support for AMB contracts (#199)
Browse files Browse the repository at this point in the history
  • Loading branch information
akolotov authored Oct 21, 2019
1 parent 803f007 commit 9884b4b
Show file tree
Hide file tree
Showing 35 changed files with 1,018 additions and 133 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ Additionally there are [Smart Contracts](https://github.com/poanetwork/poa-bridg

## Operational Modes

The POA TokenBridge provides three operational modes:
The POA TokenBridge provides four operational modes:

- [x] `Native-to-ERC20` **Coins** on a Home network can be converted to ERC20-compatible **tokens** on a Foreign network. Coins are locked on the Home side and the corresponding amount of ERC20 tokens are minted on the Foreign side. When the operation is reversed, tokens are burnt on the Foreign side and unlocked in the Home network. **More Information: [POA-to-POA20 Bridge](https://medium.com/poa-network/introducing-poa-bridge-and-poa20-55d8b78058ac)**
- [x] `ERC20-to-ERC20` ERC20-compatible tokens on the Foreign network are locked and minted as ERC20-compatible tokens (ERC677 tokens) on the Home network. When transferred from Home to Foreign, they are burnt on the Home side and unlocked in the Foreign network. This can be considered a form of atomic swap when a user swaps the token "X" in network "A" to the token "Y" in network "B". **More Information: [ERC20-to-ERC20](https://medium.com/poa-network/introducing-the-erc20-to-erc20-tokenbridge-ce266cc1a2d0)**
- [x] `ERC20-to-Native`: Pre-existing **tokens** in the Foreign network are locked and **coins** are minted in the `Home` network. In this mode, the Home network consensus engine invokes [Parity's Block Reward contract](https://wiki.parity.io/Block-Reward-Contract.html) to mint coins per the bridge contract request. **More Information: [xDai Chain](https://medium.com/poa-network/poa-network-partners-with-makerdao-on-xdai-chain-the-first-ever-usd-stable-blockchain-65a078c41e6a)**
- [x] `Arbitrary-Message`: Transfer arbitrary data between two networks as so the data could be interpreted as an arbitrary contract method invocation.

## Initializing the monorepository

Expand Down
11 changes: 10 additions & 1 deletion commons/abis.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const ERC677_BRIDGE_TOKEN_ABI = require('../contracts/build/contracts/ERC677Brid
const BLOCK_REWARD_ABI = require('../contracts/build/contracts/IBlockReward').abi
const BRIDGE_VALIDATORS_ABI = require('../contracts/build/contracts/BridgeValidators').abi
const REWARDABLE_VALIDATORS_ABI = require('../contracts/build/contracts/RewardableValidators').abi
const HOME_AMB_ABI = require('../contracts/build/contracts/HomeAMB').abi
const FOREIGN_AMB_ABI = require('../contracts/build/contracts/ForeignAMB').abi
const BOX_ABI = require('../contracts/build/contracts/Box').abi

const { HOME_V1_ABI, FOREIGN_V1_ABI } = require('./v1Abis')
const { BRIDGE_MODES } = require('./constants')
Expand Down Expand Up @@ -60,6 +63,9 @@ function getBridgeABIs(bridgeMode) {
} else if (bridgeMode === BRIDGE_MODES.NATIVE_TO_ERC_V1) {
HOME_ABI = HOME_V1_ABI
FOREIGN_ABI = FOREIGN_V1_ABI
} else if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
HOME_ABI = HOME_AMB_ABI
FOREIGN_ABI = FOREIGN_AMB_ABI
} else {
throw new Error(`Unrecognized bridge mode: ${bridgeMode}`)
}
Expand All @@ -83,5 +89,8 @@ module.exports = {
REWARDABLE_VALIDATORS_ABI,
HOME_V1_ABI,
FOREIGN_V1_ABI,
ERC20_BYTES32_ABI
ERC20_BYTES32_ABI,
HOME_AMB_ABI,
FOREIGN_AMB_ABI,
BOX_ABI
}
9 changes: 7 additions & 2 deletions commons/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ const BRIDGE_MODES = {
NATIVE_TO_ERC: 'NATIVE_TO_ERC',
ERC_TO_ERC: 'ERC_TO_ERC',
ERC_TO_NATIVE: 'ERC_TO_NATIVE',
NATIVE_TO_ERC_V1: 'NATIVE_TO_ERC_V1'
NATIVE_TO_ERC_V1: 'NATIVE_TO_ERC_V1',
ARBITRARY_MESSAGE: 'ARBITRARY_MESSAGE'
}

const ERC_TYPES = {
Expand All @@ -16,4 +17,8 @@ const FEE_MANAGER_MODE = {
UNDEFINED: 'UNDEFINED'
}

module.exports = { BRIDGE_MODES, ERC_TYPES, FEE_MANAGER_MODE }
module.exports = {
BRIDGE_MODES,
ERC_TYPES,
FEE_MANAGER_MODE
}
4 changes: 3 additions & 1 deletion commons/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const constants = require('./constants')
const abis = require('./abis')
const utils = require('./utils')
const message = require('./message')

module.exports = {
...constants,
...abis,
...utils
...utils,
...message
}
27 changes: 27 additions & 0 deletions commons/message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
function strip0x(input) {
return input.replace(/^0x/, '')
}

function addTxHashToData({ encodedData, transactionHash }) {
return encodedData.slice(0, 2) + strip0x(transactionHash) + encodedData.slice(2)
}

function parseAMBMessage(message) {
message = strip0x(message)

const txHash = `0x${message.slice(0, 64)}`
const sender = `0x${message.slice(64, 104)}`
const executor = `0x${message.slice(104, 144)}`

return {
sender,
executor,
txHash
}
}

module.exports = {
addTxHashToData,
parseAMBMessage,
strip0x
}
6 changes: 5 additions & 1 deletion commons/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
"test": "NODE_ENV=test mocha"
},
"dependencies": {
"web3-utils": "1.0.0-beta.30"
"web3-utils": "1.0.0-beta.34"
},
"devDependencies": {
"bn-chai": "^1.0.1",
"chai": "^4.2.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { BRIDGE_MODES, ERC_TYPES } = require('../constants')

describe('constants', () => {
it('should contain correct number of bridge types', () => {
expect(Object.keys(BRIDGE_MODES).length).to.be.equal(4)
expect(Object.keys(BRIDGE_MODES).length).to.be.equal(5)
})

it('should contain correct number of erc types', () => {
Expand Down
69 changes: 69 additions & 0 deletions commons/test/message.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
const { BN } = require('web3-utils')
const { expect } = require('chai').use(require('bn-chai')(BN))
const { parseAMBMessage, strip0x, addTxHashToData } = require('../message')

describe('strip0x', () => {
it('should remove 0x from input', () => {
// Given
const input = '0x12345'

// When
const result = strip0x(input)

// Then
expect(result).to.be.equal('12345')
})
it('should not modify input if 0x is not present', () => {
// Given
const input = '12345'

// When
const result = strip0x(input)

// Then
expect(result).to.be.equal(input)
})
})
describe('addTxHashToData', () => {
it('should add txHash to encoded data at position 2', () => {
// Given
const msgSender = '0x003667154bb32e42bb9e1e6532f19d187fa0082e'
const msgExecutor = '0xf4bef13f9f4f2b203faf0c3cbbaabe1afe056955'
const msgGasLimit = '000000000000000000000000000000000000000000000000000000005b877705'
const msgDataType = '00'
const msgData = '0xb1591967aed668a4b27645ff40c444892d91bf5951b382995d4d4f6ee3a2ce03'
const encodedData = `0x${strip0x(msgSender)}${strip0x(msgExecutor)}${msgGasLimit}${msgDataType}${strip0x(msgData)}`

const transactionHash = '0xbdceda9d8c94838aca10c687da1411a07b1390e88239c0638cb9cc264219cc10'
const message = `0x${strip0x(transactionHash)}${strip0x(msgSender)}${strip0x(
msgExecutor
)}${msgGasLimit}${msgDataType}${strip0x(msgData)}`

// When
const result = addTxHashToData({ encodedData, transactionHash })

// Then
expect(result).to.be.equal(message)
})
})
describe('parseAMBMessage', () => {
it('should parse data type 00', () => {
const msgSender = '0x003667154bb32e42bb9e1e6532f19d187fa0082e'
const msgExecutor = '0xf4bef13f9f4f2b203faf0c3cbbaabe1afe056955'
const msgTxHash = '0xbdceda9d8c94838aca10c687da1411a07b1390e88239c0638cb9cc264219cc10'
const msgGasLimit = '000000000000000000000000000000000000000000000000000000005b877705'
const msgDataType = '00'
const msgData = '0xb1591967aed668a4b27645ff40c444892d91bf5951b382995d4d4f6ee3a2ce03'
const message = `0x${strip0x(msgTxHash)}${strip0x(msgSender)}${strip0x(
msgExecutor
)}${msgGasLimit}${msgDataType}${strip0x(msgData)}`

// when
const { sender, executor, txHash } = parseAMBMessage(message)

// then
expect(sender).to.be.equal(msgSender)
expect(executor).to.be.equal(msgExecutor)
expect(txHash).to.be.equal(msgTxHash)
})
})
2 changes: 2 additions & 0 deletions commons/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ function decodeBridgeMode(bridgeModeHash) {
return BRIDGE_MODES.ERC_TO_ERC
case '0x18762d46':
return BRIDGE_MODES.ERC_TO_NATIVE
case '0x2544fbb9':
return BRIDGE_MODES.ARBITRARY_MESSAGE
default:
throw new Error(`Unrecognized bridge mode hash: '${bridgeModeHash}'`)
}
Expand Down
23 changes: 23 additions & 0 deletions e2e-commons/components-envs/oracle-amb.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

ORACLE_BRIDGE_MODE=ARBITRARY_MESSAGE
ORACLE_QUEUE_URL=amqp://rabbit
ORACLE_REDIS_URL=redis://redis
COMMON_HOME_RPC_URL=http://parity1:8545
COMMON_FOREIGN_RPC_URL=http://parity2:8545
COMMON_HOME_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0
COMMON_FOREIGN_BRIDGE_ADDRESS=0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0
ORACLE_VALIDATOR_ADDRESS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9
COMMON_HOME_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
COMMON_HOME_GAS_PRICE_SPEED_TYPE=standard
COMMON_HOME_GAS_PRICE_FALLBACK=1000000000
ORACLE_HOME_GAS_PRICE_UPDATE_INTERVAL=600000
COMMON_HOME_GAS_PRICE_FACTOR=1
COMMON_FOREIGN_GAS_PRICE_SUPPLIER_URL=https://gasprice.poa.network/
COMMON_FOREIGN_GAS_PRICE_SPEED_TYPE=standard
COMMON_FOREIGN_GAS_PRICE_FALLBACK=10000000000
ORACLE_FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000
COMMON_FOREIGN_GAS_PRICE_FACTOR=1
ORACLE_HOME_RPC_POLLING_INTERVAL=500
ORACLE_FOREIGN_RPC_POLLING_INTERVAL=500
ORACLE_ALLOW_HTTP_FOR_RPC=yes
6 changes: 6 additions & 0 deletions e2e-commons/constants.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
"ui": "http://localhost:3002",
"monitor": "http://monitor-erc20-native:3012"
},
"amb": {
"home": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0",
"foreign": "0x0AEe1FCD12dDFab6265F7f8956e6E012A9Fe4Aa0",
"homeBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1",
"foreignBox": "0x6C4EaAb8756d53Bf599FFe2347FAFF1123D6C8A1"
},
"homeRPC": {
"URL": "http://parity1:8545",
"ID": "77"
Expand Down
25 changes: 25 additions & 0 deletions e2e-commons/contracts-envs/amb.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
BRIDGE_MODE=ARBITRARY_MESSAGE
DEPLOYMENT_ACCOUNT_PRIVATE_KEY=8e829f695aed89a154550f30262f1529582cc49dc30eff74a6b491359e0230f9
HOME_DEPLOYMENT_GAS_PRICE=10000000000
FOREIGN_DEPLOYMENT_GAS_PRICE=10000000000
GET_RECEIPT_INTERVAL_IN_MILLISECONDS=50
DEPLOYMENT_GAS_LIMIT_EXTRA=0.2

HOME_RPC_URL=http://parity1:8545
HOME_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
HOME_MAX_AMOUNT_PER_TX=8000000
HOME_REQUIRED_BLOCK_CONFIRMATIONS=1
HOME_GAS_PRICE=1000000000

FOREIGN_RPC_URL=http://parity2:8545
FOREIGN_BRIDGE_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_VALIDATORS_OWNER=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_UPGRADEABLE_ADMIN=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
FOREIGN_MAX_AMOUNT_PER_TX=8000000
FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=1
FOREIGN_GAS_PRICE=10000000000

REQUIRED_NUMBER_OF_VALIDATORS=1
VALIDATORS=0xaaB52d66283F7A1D5978bcFcB55721ACB467384b
11 changes: 11 additions & 0 deletions e2e-commons/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ services:
command: "true"
networks:
- ultimate
oracle-amb:
build:
context: ..
dockerfile: oracle/Dockerfile
args:
DOT_ENV_PATH: e2e-commons/components-envs/oracle-amb.env
environment:
- NODE_ENV=production
command: "true"
networks:
- ultimate
ui:
build:
context: ..
Expand Down
11 changes: 11 additions & 0 deletions e2e-commons/scripts/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,14 @@ cp "$ENVS_PATH/erc-to-native.env" "$DEPLOY_PATH/.env"
cd "$DEPLOY_PATH"
node deploy.js
cd - > /dev/null

echo -e "\n\n############ Deploying amb ############\n"
cp "$ENVS_PATH/amb.env" "$DEPLOY_PATH/.env"
cd "$DEPLOY_PATH"
node deploy.js
cd - > /dev/null

echo -e "\n\n############ Deploying test contract for amb ############\n"
cd "$DEPLOY_PATH"
node src/utils/deployTestBox.js
cd - > /dev/null
5 changes: 4 additions & 1 deletion e2e-commons/up.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ docker-compose up -d parity1 parity2 e2e

while [ "$1" != "" ]; do
if [ "$1" == "oracle" ]; then
docker-compose up -d redis rabbit oracle oracle-erc20 oracle-erc20-native
docker-compose up -d redis rabbit oracle oracle-erc20 oracle-erc20-native oracle-amb

docker-compose run -d oracle yarn watcher:signature-request
docker-compose run -d oracle yarn watcher:collected-signatures
Expand All @@ -20,6 +20,9 @@ while [ "$1" != "" ]; do
docker-compose run -d oracle-erc20-native yarn watcher:signature-request
docker-compose run -d oracle-erc20-native yarn watcher:collected-signatures
docker-compose run -d oracle-erc20-native yarn watcher:affirmation-request
docker-compose run -d oracle-amb yarn watcher:signature-request
docker-compose run -d oracle-amb yarn watcher:collected-signatures
docker-compose run -d oracle-amb yarn watcher:affirmation-request
docker-compose run -d oracle yarn sender:home
docker-compose run -d oracle yarn sender:foreign
fi
Expand Down
23 changes: 19 additions & 4 deletions monitor/alerts.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const Web3 = require('web3')
const logger = require('./logger')('alerts')
const eventsInfo = require('./utils/events')
const { getBlockNumber } = require('./utils/contract')
const { processedMsgNotDelivered } = require('./utils/message')
const { BRIDGE_MODES } = require('../commons')

const { COMMON_HOME_RPC_URL, COMMON_FOREIGN_RPC_URL } = process.env

Expand All @@ -13,10 +15,23 @@ const foreignProvider = new Web3.providers.HttpProvider(COMMON_FOREIGN_RPC_URL)
const web3Foreign = new Web3(foreignProvider)

async function main() {
const { foreignDeposits, homeDeposits, homeWithdrawals, foreignWithdrawals } = await eventsInfo()

const xSignatures = foreignDeposits.filter(findDifferences(homeDeposits))
const xAffirmations = homeWithdrawals.filter(findDifferences(foreignWithdrawals))
const {
homeToForeignRequests,
homeToForeignConfirmations,
foreignToHomeConfirmations,
foreignToHomeRequests,
bridgeMode
} = await eventsInfo()

let xSignatures
let xAffirmations
if (bridgeMode === BRIDGE_MODES.ARBITRARY_MESSAGE) {
xSignatures = homeToForeignConfirmations.filter(processedMsgNotDelivered(homeToForeignRequests))
xAffirmations = foreignToHomeConfirmations.filter(processedMsgNotDelivered(foreignToHomeRequests))
} else {
xSignatures = homeToForeignConfirmations.filter(findDifferences(homeToForeignRequests))
xAffirmations = foreignToHomeConfirmations.filter(findDifferences(foreignToHomeRequests))
}

logger.debug('building misbehavior blocks')
const [homeBlockNumber, foreignBlockNumber] = await getBlockNumber(web3Home, web3Foreign)
Expand Down
Loading

0 comments on commit 9884b4b

Please sign in to comment.