Transfer Gateway Solidity Contracts
These transfer gateway contracts support deposit & withdrawal of ETH, ERC20, ERC721, and ERC721X tokens.
Setup locally
cd mainnet
yarn install
yarn compile
cd ../dappchain
yarn install
yarn compile
cd ../
make deps
make deployer
In the case that you edit the smart contracts, make sure to always regenerate the go bindings for them, via make abigen
:)
Running the tests
To test the Mainnet Solidity contracts:
cd mainnet
npm run test
To run the e2e tests locally with a local DAppChain node & Ganache:
./loom_e2e_tests.sh --init \
--launch-dappchain --launch-ganache \
--deploy-dappchain-contracts --deploy-ethereum-contracts --map-contracts
If you wish to use locally built loom
set the LOOM_BIN
env var to point to the binary you wish
the tests to use, e.g.
export LOOM_BIN=/path/to/loom
./loom_e2e_tests.sh --init \
--launch-dappchain --launch-ganache \
--deploy-dappchain-contracts --deploy-ethereum-contracts --map-contracts
The test script will create the tmp/loom-123
directory to use as the DAppChain node working
directory (on Jenkins the suffix will correspond to the build number). This directory will be
automatically removed if all the tests pass, however, if you wish to inspect logs after a succesful
test run specify the --persist
option, e.g.
./loom_e2e_tests.sh --init --persist \
--launch-dappchain --launch-ganache \
--deploy-dappchain-contracts --deploy-ethereum-contracts --map-contracts
To run the e2e tests on the PlasmaChain Testnet & Rinkeby instead of spinning up local chains:
./loom_e2e_tests.sh --ethereum-network rinkeby --dappchain-network local
The e2e tests pull in configuration from e2e_config/${DAPPCHAIN_NETWORK}_${ETHEREUM_NETWORK}
:
loom_test_config.yml
- Local DAppChain & Transfer Gateway Oracle configurationcontracts.yml
- This file will contain the addresses of contracts deployed to Ethereum, it's initially generated by the Truffle migration in themainnet
directory, and updated by thedeployer
command when the test contracts are deployed. NOTE:ETHEREUM_NETWORK
will match the name specified by the--ethereum-network
option (ganache
by default).test_keys.yml
- This file contains the private keys used to sign txs sent by by the tests to the DAppChain & Ethereum. This file is not auto-generated.
Deployment to Rinkeby
Mainnet Gateway deployment settings can be tweaked by changing mainnet/secrets.json
:
mnemonic
- Used to generate the key for the account that will deploy the Mainnet Gateway contract.infuraAPIKey
- Infura API key that will be used to deploy the Mainnet Gateway contract.validators
- The Ethereum addresses of the oracles that should be registered with the Gateway.
The secrets.json
filename and path can be overriden by setting the SECRET_FILE
env var.
Step 1. Deploy the Mainnet Gateway contract to Rinkeby:
cd mainnet
SECRET_FILE=`pwd`/secrets.json npm migrate:rinkeby
If deployment is successful the Mainnet Gateway address will be displayed in the console, and also
written to e2e_config/rinkeby/contracts.yml
(note that Truffle will first do a dry run using rinkeby-fork
as the network).
By default the Mainnet Gateway will only allow deposits of tokens that have been whitelisted, if you wish to enable deposit of ANY ERC20/ERC721/X token there's a script that can be switch off the whitelist:
# pwd: mainnet
# disable whitelisting to allow any token to be deposited:
ACCOUNT=0x7292694902bcAF4E1620629E7198cDcb3f572A24 \
GATEWAY_ETH_ADDR=0xf5cAD0DB6415a71a5BC67403c87B56b629b4DdaA \
SECRET_FILE=`pwd`/secrets.json \
./node_modules/.bin/truffle exec scripts/toggle_allow_any_token.js true --network rinkeby
# enable whitelisting to only allow deposits of specific tokens (default):
ACCOUNT=0x7292694902bcAF4E1620629E7198cDcb3f572A24 \
GATEWAY_ETH_ADDR=0xf5cAD0DB6415a71a5BC67403c87B56b629b4DdaA \
SECRET_FILE=`pwd`/secrets.json \
./node_modules/.bin/truffle exec scripts/toggle_allow_any_token.js false --network rinkeby
Note that ACCOUNT
must match the address of the account that was used to deploy the contract to
Rinkeby (displayed as mainnet_gateway_creator_addr
in the console on deployment),
and GATEWAY_ETH_ADDR
must match the address of the deployed contract (displayed as
mainnet_gateway_addr
in the console).
Step 2. Update Oracle config
Set MainnetContractHexAddress
to point to the new Mainnet Gateway.
ChainID: "default"
TransferGateway:
EthereumURI: "https://rinkeby.infura.io/5Ic91y0T9nLh6qUg33K0"
MainnetContractHexAddress: "0x68943baa36f514042fca6e931d12076772fe3844"
MainnetPrivateKeyPath: "oracle_rinkeby_priv.key"
DAppChainPrivateKeyPath: "oracle_priv.key"
DAppChainReadURI: "http://localhost:46658/query"
DAppChainWriteURI: "http://localhost:46658/rpc"
DAppChainPollInterval: 60 # seconds
MainnetPollInterval: 60 # seconds
OracleLogLevel: "debug"
OracleLogDestination: "file://oracle.log"
OracleStartupDelay: 5
OracleReconnectInterval: 5
OracleQueryAddress: "0.0.0.0:9998"
Step 3. Reset DAppChain cluster
- Stop the cluster & oracle.
- Wipe cluster data.
- Restart the cluster & oracle with the new config.
Step 4. Deploy test contracts to Rinkeby & DAppChain
./loom_e2e_tests.sh --skip-tests \
--ethereum-network rinkeby --dappchain-network local \
--deploy-dappchain-contracts --deploy-ethereum-contracts
DAppChain Gateway & Oracle Setup
Node Genesis
Sample genesis can be found in rinkeby.genesis.json
, a excerpt can be found below with annotations
(note that comments aren't allowed in .json
files).
{
"vm": "plugin",
"format": "plugin",
"name": "ethcoin",
"location": "ethcoin:1.0.0",
"init": null
},
{
"vm": "plugin",
"format": "plugin",
"name": "addressmapper",
"location": "addressmapper:0.1.0",
"init": null
},
{
"vm": "plugin",
"format": "plugin",
"name": "gateway",
"location": "gateway:0.1.0",
"init": {
// This is the base64 encoded DAppChain address of the owner of the DAppChain Gateway contract,
// the corresponding private key can be found in `gateway_owner_priv.key`.
"owner": {
"chain_id": "default",
"local": "c/IFoEFkm4+D3wdqLmFU9F3t3Sk="
},
// This is a list of base64 encoded DAppChain addresses of the Oracles (the Mainnet Gateway
// knows them as validators). Currently for testing purposes we use a single Oracle, whose
// DAppChain private key can be found in `oracle_priv.key`, the corresponding Ethereum
// private key is in `oracle_rinkeby_priv.key` (the validator address in mainnet/secrets.json
// must match this private key).
"oracles": [
{
"chain_id": "default",
"local": "22nuyPPZ53/qAqFnhwD2EpNu9ss="
}
],
// This is the Ethereum block the Oracles will start scraping events from, it should be set
// to the block in which the Mainnet Gateway contract was deployed (you can find it on
// https://rinkeby.etherscan.io by plugging in the Ethereum address of the Mainnet Gateway).
"first_mainnet_block_num": "2863097"
}
}
Node Config
Sample node config can be found in e2e_config/local_ganache/loom.yml
(should be copied to loom.yaml
in the
node working dir before initializing the node), note that this particular config enables the
in-process Oracle. For now we should only run a single Oracle, since a multi-Oracle setup hasn't been
tested, so this config should only be used for one node in a cluster. The rest should have a config
similar to this:
RegistryVersion: 2
EVMAccountsEnabled: true
TransferGateway:
ContractEnabled: true
Test with YubiHSM
./loom_e2e_tests.sh --launch-dappchain --init --persist --run-test ERC721DepositAndWithdraw --launch-ganache --map-contracts --deploy-ethereum-contracts --deploy-dappchain-contracts --enable-hsm --hsmkey-address 0x2669Ff29f3D3e78DAFd2dB842Cb9d0dDb96D90f2