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

Support alternative receiver in Oracle #221

Merged
merged 14 commits into from
Oct 29, 2019
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
2 changes: 1 addition & 1 deletion contracts
26 changes: 26 additions & 0 deletions deployment-e2e/molecule/ultimate-commons/oracle-docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,31 @@
content: "{{ docker_compose_parsed | to_yaml }}"
dest: "/home/poadocker/bridge/oracle/docker-compose.yml"

- name: Slurp docker compose extended file
slurp:
src: "/home/poadocker/bridge/oracle/docker-compose-transfer.yml"
register: docker_compose_extended_slurp
- name: Parse docker compose file
set_fact:
docker_compose_extended_parsed: "{{ docker_compose_extended_slurp['content'] | b64decode | from_yaml }}"

- name: Add the external network used to connect to Parity nodes in compose extended file
set_fact:
docker_compose_extended_parsed: "{{ docker_compose_extended_parsed |combine({'networks': {'ultimate': {'external': 'true'}}}, recursive=True) }}"

- name: Add all Oracle containers to the network in compose extended file
set_fact:
docker_compose_extended_parsed: "{{ docker_compose_extended_parsed | combine({'services': {item: {'networks': docker_compose_extended_parsed.services[item].networks | union(['ultimate'])}}}, recursive=True) }}"
with_items: "{{ docker_compose_extended_parsed.services }}"

- name: Expose Redis port to allow connecting from redis-cli in compose extended file
set_fact:
docker_compose_extended_parsed: "{{ docker_compose_extended_parsed | combine({'services': {'redis': {'ports': ['6379:6379']}}}, recursive=True) }}"

- name: Write new docker-compose extended file
copy:
content: "{{ docker_compose_extended_parsed | to_yaml }}"
dest: "/home/poadocker/bridge/oracle/docker-compose-transfer.yml"

- name: start the service
shell: service poabridge start
15 changes: 15 additions & 0 deletions deployment/roles/oracle/tasks/post_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,21 @@
set_fact:
ORACLE_VALIDATOR_ADDRESS: "{{ VADDRESS.stdout }}"

- name: Get foreign erc type
become_user: "{{ compose_service_user }}"
shell: docker-compose run --entrypoint "node scripts/initialChecks.js" bridge_affirmation
args:
chdir: "{{ bridge_path }}/oracle"
register: ERCTYPE

- name: Set FOREIGN_ERC_TYPE variable
set_fact:
FOREIGN_ERC_TYPE: "{{ (ERCTYPE.stdout).foreignERC | default('') }}"

- name: Extend docker compose file
set_fact: composefileoverride="-f docker-compose-transfer.yml"
when: ORACLE_BRIDGE_MODE == "ERC_TO_NATIVE" or ( ORACLE_BRIDGE_MODE == "ERC_TO_ERC" and FOREIGN_ERC_TYPE != "ERC677")

- name: Install .key config
template:
src: key.j2
Expand Down
17 changes: 9 additions & 8 deletions deployment/roles/oracle/templates/poabridge.j2
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ WORKDIR="{{ '/home/' + compose_service_user | default('poadocker') + '/' + bridg
keyfile="{{ keyfile_path }}"
vaddr="ORACLE_VALIDATOR_ADDRESS="
vkey="ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY="
composefileoverride="{{ composefileoverride | default('') }}"

#Parsing file content and add key to variable
while read -r line
Expand All @@ -33,30 +34,30 @@ done < $keyfile
start(){
echo "Starting bridge.."
cd $WORKDIR
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose down -v
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose rm -fv
sudo -u "{{ compose_service_user }}" ORACLE_VALIDATOR_ADDRESS=$vaddr ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=$vkey /usr/local/bin/docker-compose up --detach
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose $composefileoverride down -v
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose $composefileoverride rm -fv
sudo -u "{{ compose_service_user }}" ORACLE_VALIDATOR_ADDRESS=$vaddr ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=$vkey /usr/local/bin/docker-compose $composefileoverride up --detach
}

stop(){
echo "Stopping bridge.."
cd $WORKDIR
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose down -v
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose $composefileoverride down -v
sleep 2
}

status(){
echo "Bridge status:"
cd $WORKDIR
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose ps
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose $composefileoverride ps
}

rebuild(){
echo "Rebuild bridge.."
cd $WORKDIR
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose down -v
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose rm -fv
sudo -u "{{ compose_service_user }}" ORACLE_VALIDATOR_ADDRESS=$vaddr ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=$vkey /usr/local/bin/docker-compose up --detach --force-recreate --no-deps --build
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose $composefileoverride down -v
sudo -u "{{ compose_service_user }}" /usr/local/bin/docker-compose $composefileoverride rm -fv
sudo -u "{{ compose_service_user }}" ORACLE_VALIDATOR_ADDRESS=$vaddr ORACLE_VALIDATOR_ADDRESS_PRIVATE_KEY=$vkey /usr/local/bin/docker-compose $composefileoverride up --detach --force-recreate --no-deps --build
}


Expand Down
2 changes: 2 additions & 0 deletions e2e-commons/up.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ while [ "$1" != "" ]; do
docker-compose run -d oracle-erc20 yarn watcher:signature-request
docker-compose run -d oracle-erc20 yarn watcher:collected-signatures
docker-compose run -d oracle-erc20 yarn watcher:affirmation-request
docker-compose run -d oracle-erc20 yarn watcher:transfer
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-erc20-native yarn watcher:transfer
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
Expand Down
49 changes: 46 additions & 3 deletions oracle-e2e/test/ercToErc.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const Web3 = require('web3')
const assert = require('assert')
const promiseRetry = require('promise-retry')
const { user, ercToErcBridge, homeRPC, foreignRPC } = require('../../e2e-commons/constants.json')
const { ERC677_BRIDGE_TOKEN_ABI } = require('../../commons')
const { user, secondUser, ercToErcBridge, homeRPC, foreignRPC } = require('../../e2e-commons/constants.json')
const { ERC677_BRIDGE_TOKEN_ABI, FOREIGN_ERC_TO_NATIVE_ABI } = require('../../commons')
const { generateNewBlock } = require('../../e2e-commons/utils')

const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
Expand All @@ -17,16 +17,57 @@ homeWeb3.eth.accounts.wallet.add(user.privateKey)
foreignWeb3.eth.accounts.wallet.add(user.privateKey)

const erc20Token = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, ercToErcBridge.foreignToken)
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)
const erc677Token = new homeWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, ercToErcBridge.homeToken)

describe('erc to erc', () => {
it('should convert tokens in foreign to tokens in home', async () => {
const balance = await erc20Token.methods.balanceOf(user.address).call()
assert(!toBN(balance).isZero(), 'Account should have tokens')

const firstTransferValue = homeWeb3.utils.toWei('0.01')

// approve tokens to foreign bridge
await erc20Token.methods
.approve(COMMON_FOREIGN_BRIDGE_ADDRESS, firstTransferValue)
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})

// call bridge method to transfer tokens to a different recipient
await foreignBridge.methods
.relayTokens(secondUser.address, firstTransferValue)
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})

// Send a trivial transaction to generate a new block since the watcher
// is configured to wait 1 confirmation block
await generateNewBlock(foreignWeb3, user.address)

// check that balance increases
await promiseRetry(async retry => {
const balance = await erc677Token.methods.balanceOf(user.address).call()
const recipientBalance = await erc677Token.methods.balanceOf(secondUser.address).call()
assert(toBN(balance).isZero(), 'User balance should be the same')
if (toBN(recipientBalance).isZero()) {
retry()
}
})

const secondTransferValue = homeWeb3.utils.toWei('0.05')

// send tokens to foreign bridge
await erc20Token.methods
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, homeWeb3.utils.toWei('0.01'))
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, secondTransferValue)
.send({
from: user.address,
gas: '1000000'
Expand All @@ -44,6 +85,8 @@ describe('erc to erc', () => {
const balance = await erc677Token.methods.balanceOf(user.address).call()
if (toBN(balance).isZero()) {
retry()
} else {
assert(toBN(balance).eq(toBN(secondTransferValue)), 'User balance should be increased only by second transfer')
}
})
})
Expand Down
51 changes: 48 additions & 3 deletions oracle-e2e/test/ercToNative.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const Web3 = require('web3')
const assert = require('assert')
const promiseRetry = require('promise-retry')
const { user, ercToNativeBridge, homeRPC, foreignRPC } = require('../../e2e-commons/constants.json')
const { ERC677_BRIDGE_TOKEN_ABI } = require('../../commons')
const { user, secondUser, ercToNativeBridge, homeRPC, foreignRPC } = require('../../e2e-commons/constants.json')
const { ERC677_BRIDGE_TOKEN_ABI, FOREIGN_ERC_TO_NATIVE_ABI } = require('../../commons')
const { generateNewBlock } = require('../../e2e-commons/utils')

const homeWeb3 = new Web3(new Web3.providers.HttpProvider(homeRPC.URL))
Expand All @@ -17,16 +17,56 @@ homeWeb3.eth.accounts.wallet.add(user.privateKey)
foreignWeb3.eth.accounts.wallet.add(user.privateKey)

const erc20Token = new foreignWeb3.eth.Contract(ERC677_BRIDGE_TOKEN_ABI, ercToNativeBridge.foreignToken)
const foreignBridge = new foreignWeb3.eth.Contract(FOREIGN_ERC_TO_NATIVE_ABI, COMMON_FOREIGN_BRIDGE_ADDRESS)

describe('erc to native', () => {
it('should convert tokens in foreign to coins in home', async () => {
const balance = await erc20Token.methods.balanceOf(user.address).call()
const originalBalanceOnHome = await homeWeb3.eth.getBalance(user.address)
const initialBalanceSecondUser = await homeWeb3.eth.getBalance(secondUser.address)
assert(!toBN(balance).isZero(), 'Account should have tokens')

// approve tokens to foreign bridge
await erc20Token.methods
.approve(COMMON_FOREIGN_BRIDGE_ADDRESS, homeWeb3.utils.toWei('0.01'))
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})

// call bridge method to transfer tokens to a different recipient
await foreignBridge.methods
.relayTokens(secondUser.address, homeWeb3.utils.toWei('0.01'))
.send({
from: user.address,
gas: '1000000'
})
.catch(e => {
console.error(e)
})

// Send a trivial transaction to generate a new block since the watcher
// is configured to wait 1 confirmation block
await generateNewBlock(foreignWeb3, user.address)

// check that balance increases
await promiseRetry(async retry => {
const balance = await homeWeb3.eth.getBalance(user.address)
const secondUserbalance = await homeWeb3.eth.getBalance(secondUser.address)
assert(toBN(balance).lte(toBN(originalBalanceOnHome)), 'User balance should be the same')
if (toBN(secondUserbalance).lte(toBN(initialBalanceSecondUser))) {
retry()
}
})

const transferValue = homeWeb3.utils.toWei('0.05')

// send tokens to foreign bridge
await erc20Token.methods
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, homeWeb3.utils.toWei('0.01'))
.transfer(COMMON_FOREIGN_BRIDGE_ADDRESS, transferValue)
.send({
from: user.address,
gas: '1000000'
Expand All @@ -44,6 +84,11 @@ describe('erc to native', () => {
const balance = await homeWeb3.eth.getBalance(user.address)
if (toBN(balance).lte(toBN(originalBalanceOnHome))) {
retry()
} else {
assert(
toBN(balance).eq(toBN(originalBalanceOnHome).add(toBN(transferValue))),
'User balance should be increased only by second transfer'
)
}
})
})
Expand Down
31 changes: 9 additions & 22 deletions oracle/config/affirmation-request-watcher.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const baseConfig = require('./base.config')
const { ERC20_ABI, ERC_TYPES } = require('../../commons')
const { ERC_TYPES } = require('../../commons')

const initialChecksJson = process.argv[3]

Expand All @@ -20,24 +20,11 @@ if (baseConfig.id === 'erc-erc' && initialChecks.foreignERC === ERC_TYPES.ERC677

const id = `${baseConfig.id}-affirmation-request`

module.exports =
(baseConfig.id === 'erc-erc' && initialChecks.foreignERC === ERC_TYPES.ERC20) || baseConfig.id === 'erc-native'
? {
...baseConfig.bridgeConfig,
...baseConfig.foreignConfig,
event: 'Transfer',
eventContractAddress: initialChecks.bridgeableTokenAddress,
eventAbi: ERC20_ABI,
eventFilter: { to: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS },
queue: 'home',
name: `watcher-${id}`,
id
}
: {
...baseConfig.bridgeConfig,
...baseConfig.foreignConfig,
event: 'UserRequestForAffirmation',
queue: 'home',
name: `watcher-${id}`,
id
}
module.exports = {
...baseConfig.bridgeConfig,
...baseConfig.foreignConfig,
event: 'UserRequestForAffirmation',
queue: 'home',
name: `watcher-${id}`,
id
}
42 changes: 42 additions & 0 deletions oracle/config/transfer-watcher.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const baseConfig = require('./base.config')
const { ERC20_ABI, ERC_TYPES } = require('../../commons')
const { EXIT_CODES } = require('../src/utils/constants')

const initialChecksJson = process.argv[3]

if (!initialChecksJson) {
throw new Error('initial check parameter was not provided.')
}

let initialChecks
try {
initialChecks = JSON.parse(initialChecksJson)
} catch (e) {
throw new Error('Error on decoding values from initial checks.')
}

if (baseConfig.id === 'erc-erc' && initialChecks.foreignERC === ERC_TYPES.ERC677) {
baseConfig.id = 'erc677-erc677'
}

const id = `${baseConfig.id}-transfer`

const transferWatcherRequired =
(baseConfig.id === 'erc-erc' && initialChecks.foreignERC === ERC_TYPES.ERC20) || baseConfig.id === 'erc-native'

if (!transferWatcherRequired) {
console.error(`Transfer watcher not required for bridge mode ${process.env.ORACLE_BRIDGE_MODE}`)
process.exit(EXIT_CODES.WATCHER_NOT_REQUIRED)
}

module.exports = {
...baseConfig.bridgeConfig,
...baseConfig.foreignConfig,
event: 'Transfer',
eventContractAddress: initialChecks.bridgeableTokenAddress,
eventAbi: ERC20_ABI,
eventFilter: { to: process.env.COMMON_FOREIGN_BRIDGE_ADDRESS },
queue: 'home',
name: `watcher-${id}`,
id
}
Loading