POA – 侧链和主链之间的资产桥梁

介绍

POA Bridge是在两个以太坊链之间转移资产令牌(Native和ERC20 / ERC677令牌)的解决方案。

资产令牌通常有两个目的:

  • 货币用途,可以将代币交易,交易所或作为长期投资进行交易
  • 可以在Dapp上使用令牌的应用程序用途(投票,堆叠,播放等)

这两种用法都需要不同的网络属性来实现最佳体验,货币使用可能需要强大的网络安全性和活跃性以及访问大型资产网络以促进交易,而应用程序使用需要更快,更便宜的交易以获得更好的用户体验。

作为第2层可扩展性解决方案的一部分,侧链和桥接器为两种用途实现了这两种链的范例,并尝试解决可扩展性和UX问题,因为以太坊主网通常被认为太慢(15 tx / sec)而且过于昂贵为大多数用例(游戏或社交应用程序)提供良好的用户体验的汽油费。在这种情况下,一般流程如下:

  1. 用户在主链上购买令牌
  2. 用户通过桥将他的代币转移到侧链(双重表示:锁定在主链上并在侧链上铸造)
  3. 用户以快速有效的方式使用令牌。也许从其他用户那里赚取或丢失一些令牌
  4. 用户决定从侧链退出他的代币并通过桥将它们转移回主链(在主链上解锁并在侧链上烧掉的代币)
  5. 用户在主链上出售他的代币

在本教程中,我们将学习如何在两个网络上部署令牌(RinkeBy网络作为主链,POA Sokol作为侧链),然后部署并使用网桥(ERC20 <> ERC20)让用户从一个网络转移资产到另一个。


要求

要启动,您需要在计算机上安装以下程序:

  • Git
  • NodeJS / NPM
  • Yarn
  • Docker和Docker-Compose
  • Metamask(浏览器扩展)
  • Truffle
$npm install -g truffle

$truffle version
Truffle v5.0.20 (core: 5.0.20)
Solidity v0.5.0 (solc-js)
Node v8.15.1
Web3.js v1.0.0-beta.37

步骤1:BRT在主链(Rinkeby网络)上部署名为BRidge代币的ERC20令牌

  1. 让我们首先为我们的ERC20创建一个项目文件夹BRT并初始化一个Truffle项目。
$mkdir token
$cd token
$truffle init
  1. 然后我们将安装Open-Zeppelin Solidity库,其中包含许多高质量,经过全面测试和审核的可重用智能合约
$npm init -y
$npm install openzeppelin-solidity --save-exact
  1. 创建./contacts/BridgeToken.sol包含的合约文件
// BridgeToken.sol
pragma solidity ^0.5.8;

import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol";

contract BridgeToken is ERC20Mintable {
    string public constant name = "Bridge代币";
    string public constant symbol = "BRT";
    uint8 public constant decimals = 18;
}

这就是Zeppelin团队为以太坊所做的所有工作而感谢它。基本上我们的智能合约继承自MintableToken,它提供所有ERC-20标准功能以及薄荷令牌的功能。我们只需要指定我们的令牌名称“Bridge代币”,其符号“BRT”和小数位数(可分性)。

要确保智能合约编译,您可以执行该命令truffle compile

  1. 在RinkeBy网络上部署智能合约

注意:确保用于部署合约的帐户由RinkeBy ethers资助(请参阅水龙头)。

一旦我们的智能合约编译,我们需要部署它。为此,我们首先需要完成迁移脚本,创建一个文件./migrations/2_deploy_contract.js

// 2_deploy_contract.js
const BridgeToken = artifacts.require("./BridgeToken.sol");

module.exports = function(deployer, network, accounts) {
    // Deploy the smart contract
    deployer.deploy(BridgeToken, {from: accounts[0]}).then(function(instance) {
        // Mint 100 tokens
        return instance.mint(accounts[0], web3.utils.toBN("100000000000000000000"), {from: accounts[0]});
    }); 
};

迁移脚本部署合约并另外注释并分配100个BRT令牌到部署者帐户。

下一步是配置与RinkeBy网络的连接以部署智能合约。

安装以下依赖项(dotenv用于管理环境变量,而truffle-hdwallet-provider用于从来自助记符的帐户签署事务)

$npm install --save dotenv truffle-hdwallet-provider

创建一个文件./.env来存储一些私人信息,我们不想在任何地方共享(gitignore这个文件

  • Infura是通往以太坊的公共门户。如果您还没有帐户,我建议您在此文件中创建一个并通过您的API密钥(PROJECT ID)。
  • 一个助记符,一个12字的短语,象征着私钥。你可以在Metamask中找到它(设置/显示种子词
// .env
INFURA_API_KEY=044443611111111e19e03433333309923
MNEMONIC=twelve words you can find in metamask/settings/reveal seed words 

最后,让我们配置与RinkeBy网络的连接。编辑文件./truffle.js

// truffle.js
require('dotenv').config();
const HDWalletProvider = require("truffle-hdwallet-provider");

module.exports = {
  networks: {
    development: {
      host: "localhost",
      port: 8545,
      network_id: "*"
    },
    rinkeby: {
        provider: new HDWalletProvider(process.env.MNEMONIC, "https://rinkeby.infura.io/v3/" + process.env.INFURA_API_KEY),
        network_id: 4,
        gas: 4500000
    }
  }
};

要在RinkeBy网络上部署智能合约,请运行该命令(这可能需要一段时间):

$truffle migrate --network rinkeby

Compiling your contracts...
===========================
> Compiling ./contracts/BridgeToken.sol
> Compiling ./contracts/Migrations.sol
> Compiling openzeppelin-solidity/contracts/access/Roles.sol
> Compiling openzeppelin-solidity/contracts/access/roles/MinterRole.sol
> Compiling openzeppelin-solidity/contracts/math/SafeMath.sol
> Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
> Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol
> Compiling openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
> Artifacts written to /home/gjeanmart/workspace/tutorials/bridge_token/build/contracts
> Compiled successfully using:
   - solc: 0.5.8+commit.23d335f2.Emscripten.clang


Migrations dry-run (simulation)
===============================
> Network name:    'rinkeby-fork'
> Network id:      4
> Block gas limit: 0x7244c0


1_initial_migration.js
======================

   Deploying 'Migrations'
   ----------------------
   > block number:        4502550
   > block timestamp:     1559667907
   > account:             0xF0f15Cedc719B5A55470877B0710d5c7816916b1
   > balance:             33.578282390129999997
   > gas used:            246393
   > gas price:           2 gwei
   > value sent:          0 ETH
   > total cost:          0.000492786 ETH

   -------------------------------------
   > Total cost:         0.000492786 ETH


2_deploy_contract.js
====================

   Deploying 'BridgeToken'
   -----------------------
   > block number:        4502552
   > block timestamp:     1559667919
   > account:             0xe9B0E206C8cA079bca49F0120abfD02760093612
   > balance:             99.996785462
   > gas used:            1607269
   > gas price:           2 gwei
   > value sent:          0 ETH
   > total cost:          0.003214538 ETH

   -------------------------------------
   > Total cost:         0.003214538 ETH


Summary
=======
> Total deployments:   2
> Final cost:          0.003707324 ETH


Starting migrations...
======================
> Network name:    'rinkeby'
> Network id:      4
> Block gas limit: 0x724802


1_initial_migration.js
======================

   Deploying 'Migrations'
   ----------------------
   > transaction hash:    0x44dbbf18d316adb29143d1b3341c1e28b297d144411ee98cb23017270f77b9ed
   > Blocks: 1            Seconds: 9
   > contract address:    0xAC96dc3AC9baB86c7d89a5868096394CB708a6a0
   > block number:        4502551
   > block timestamp:     1559667943
   > account:             0xF0f15Cedc719B5A55470877B0710d5c7816916b1
   > balance:             33.573547316129999997
   > gas used:            261393
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00522786 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:          0.00522786 ETH


2_deploy_contract.js
====================

   Deploying 'BridgeToken'
   -----------------------
   > transaction hash:    0x80dc122178131cbd040e90b667cc1d11a47d21abf8ebf17c80232b1c4c5f33df
   > Blocks: 2            Seconds: 21
   > contract address:    0x40A6a864133985E1146DDfEb48c7391CD07596F5
   > block number:        4502554
   > block timestamp:     1559667988
   > account:             0xF0f15Cedc719B5A55470877B0710d5c7816916b1
   > balance:             33.540261476129999997
   > gas used:            1622269
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.03244538 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:          0.03244538 ETH


Summary
=======
> Total deployments:   2
> Final cost:          0.03767324 ETH

因此,我们可以识别我们BridgeToken在地址部署的智能合约0x40A6a864133985E1146DDfEb48c7391CD07596F5(参见block explorer

第2步:初始化monorepo tokenbridge

在第二步中,我们将初始化GitHub mono-repository,以便按以下步骤安装每个组件。

  1. 克隆回购
$cd ../
$git clone --recursive https://github.com/poanetwork/tokenbridge
$cd ./tokenbridge/
  1. 安装depandancies
$yarn install && yarn install:deploy

第3步:配置和部署桥接合约

在第三步中,我们将部署必要的合约以启用ERC20到ERC20桥。

  1. 转到该contracts文件夹
$cd ./contracts/
  1. 编译智能合约
$npm run compile
  1. 在中创建配置文件 ./deploy/.env

注1:要更改以下属性

  •  负责部署,管理合约和验证转移的帐户
  •  负责部署,管理合约和验证转移的帐户。
  •  上面部署的ERC20令牌的地址。

注2:出于本教程的原因,我们决定尽可能简化配置(一个帐户管理和验证)

注3:确保该帐户ACCOUNT_ADMINRinkeByetherPOA Sokolether资助。

注4:未配置块奖励(可奖励令牌)。

BRIDGE_MODE=ERC_TO_ERC
#BRIDGE_MODE=NATIVE_TO_ERC

# If Home network does not support byzantium fork, should use contracts compiled for spuriousDragon
#HOME_EVM_VERSION=spuriousDragon

# If Foreign network does not support byzantium fork, should use contracts compiled for spuriousDragon
#FOREIGN_EVM_VERSION=spuriousDragon

DEPLOYMENT_ACCOUNT_PRIVATE_KEY=
DEPLOYMENT_GAS_LIMIT_EXTRA=0.2
HOME_DEPLOYMENT_GAS_PRICE=10000000000
FOREIGN_DEPLOYMENT_GAS_PRICE=10000000000
GET_RECEIPT_INTERVAL_IN_MILLISECONDS=3000

BRIDGEABLE_TOKEN_NAME="Bridge代币"
BRIDGEABLE_TOKEN_SYMBOL=BRT
BRIDGEABLE_TOKEN_DECIMALS=18

HOME_RPC_URL=https://sokol.poa.network
HOME_BRIDGE_OWNER=
HOME_VALIDATORS_OWNER=
HOME_UPGRADEABLE_ADMIN=
HOME_DAILY_LIMIT=30000000000000000000000000
HOME_MAX_AMOUNT_PER_TX=1500000000000000000000000
HOME_MIN_AMOUNT_PER_TX=500000000000000000
HOME_REQUIRED_BLOCK_CONFIRMATIONS=1
HOME_GAS_PRICE=1000000000

BLOCK_REWARD_ADDRESS=0x0000000000000000000000000000000000000000

FOREIGN_RPC_URL=https://rinkeby.infura.io
FOREIGN_BRIDGE_OWNER=
FOREIGN_VALIDATORS_OWNER=
FOREIGN_UPGRADEABLE_ADMIN=
FOREIGN_DAILY_LIMIT=15000000000000000000000000
FOREIGN_MAX_AMOUNT_PER_TX=750000000000000000000000
FOREIGN_MIN_AMOUNT_PER_TX=500000000000000000
FOREIGN_REQUIRED_BLOCK_CONFIRMATIONS=8
FOREIGN_GAS_PRICE=10000000000
#for bridge erc_to_erc and erc_to_native mode
ERC20_TOKEN_ADDRESS=
# Only for for erc_to_erc mode
ERC20_EXTENDED_BY_ERC677=false

REQUIRED_NUMBER_OF_VALIDATORS=1
#If several validators are used, list them separated by space without quotes
#E.g. VALIDATORS=0x 0x 0x
VALIDATORS=
#Set to ONE_DIRECTION or BOTH_DIRECTIONS if fee will be charged on home side, set to false otherwise
HOME_REWARDABLE=false
# Valid only for rewards on erc_to_native mode. Supported values are BRIDGE_VALIDATORS_REWARD and POSDAO_REWARD
HOME_FEE_MANAGER_TYPE=
#Set to ONE_DIRECTION or BOTH_DIRECTIONS if fee will be charged on foreign side, set to false otherwise
FOREIGN_REWARDABLE=false
#If HOME_REWARDABLE or FOREIGN_REWARDABLE set to true, list validators accounts were rewards should be transferred separated by space without quotes
#E.g. VALIDATORS_REWARD_ACCOUNTS=0x 0x 0x
VALIDATORS_REWARD_ACCOUNTS=0x

# Fee to be taken for every transaction directed from the Home network to the Foreign network
# E.g. 0.1% fee
HOME_TRANSACTIONS_FEE=0.001
# Fee to be taken for every transaction directed from the Foreign network to the Home network
FOREIGN_TRANSACTIONS_FEE=0.001
#for bridge native_to_erc, erc_to_erc mode
DEPLOY_REWARDABLE_TOKEN=false
DPOS_STAKING_ADDRESS=0x0000000000000000000000000000000000000000
  1. 部署Bridge配置
$./deploy.sh
(...)
Deployment has been completed.

[   Home  ] HomeBridge: 0xc4e7cA947521f331969e41CC7c99ADa22F2C7F9C at block 9044640
[   Home  ] ERC677 Bridgeable代币: 0xEa3acD04DdaF1F1A5Ae1B9f5f690123aA4E19B36
[ Foreign ] ForeignBridge: 0xeb2dbC5AB9380A3517AcA9d8CA0c39873e569a93 at block 4503560
[ Foreign ] ERC20代币: 0x40A6a864133985E1146DDfEb48c7391CD07596F5
Contracts Deployment have been saved to `bridgeDeploymentResults.json`
{
    "homeBridge": {
        "address": "0xc4e7cA947521f331969e41CC7c99ADa22F2C7F9C",
        "deployedBlockNumber": 9044640,
        "erc677": {
            "address": "0xEa3acD04DdaF1F1A5Ae1B9f5f690123aA4E19B36"
        }
    },
    "foreignBridge": {
        "address": "0xeb2dbC5AB9380A3517AcA9d8CA0c39873e569a93",
        "deployedBlockNumber": 4503560
    }
}

保存上面的JSON信息。

步骤4:配置和部署Bridge Oracle

  1. 转到`oracle文件夹
$cd ../oracle
  1. 在中创建配置文件 ./.env

注意1:打开保存的JSON文件bridgeDeploymentResults.json以获取本地和外部桥接合约地址和部署块编号。

{
    "homeBridge": {
        "address": "0xc4e7cA947521f331969e41CC7c99ADa22F2C7F9C",
        "deployedBlockNumber": 9044640,
        "erc677": {
            "address": "0xEa3acD04DdaF1F1A5Ae1B9f5f690123aA4E19B36"
        }
    },
    "foreignBridge": {
        "address": "0xeb2dbC5AB9380A3517AcA9d8CA0c39873e569a93",
        "deployedBlockNumber": 4503560
    }
}

注2:要更改以下属性

  •  负责部署,管理合约和验证转移的帐户
  •  负责部署,管理合约和验证转移的帐户
  •  上面部署的ERC20令牌的地址。

注3:出于本教程的原因,我们决定尽可能简化配置(一个帐户管理和验证)

注4:确保该帐户ACCOUNT_ADMIN由RinkeByether和POA sokolether资助。

BRIDGE_MODE=ERC_TO_ERC
HOME_POLLING_INTERVAL=5000
FOREIGN_POLLING_INTERVAL=1000
ALLOW_HTTP=yes
HOME_RPC_URL=https://sokol.poa.network
FOREIGN_RPC_URL=https://rinkeby.infura.io
HOME_BRIDGE_ADDRESS=address>
FOREIGN_BRIDGE_ADDRESS=address>
ERC20_TOKEN_ADDRESS=

VALIDATOR_ADDRESS=
VALIDATOR_ADDRESS_PRIVATE_KEY=

HOME_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/
HOME_GAS_PRICE_SPEED_TYPE=standard
HOME_GAS_PRICE_FALLBACK=1000000000
HOME_GAS_PRICE_UPDATE_INTERVAL=600000

FOREIGN_GAS_PRICE_ORACLE_URL=https://gasprice.poa.network/
FOREIGN_GAS_PRICE_SPEED_TYPE=standard
FOREIGN_GAS_PRICE_FALLBACK=1000000000
FOREIGN_GAS_PRICE_UPDATE_INTERVAL=600000

QUEUE_URL=amqp://rabbit
REDIS_URL=redis://redis:6379
REDIS_LOCK_TTL=1000

HOME_START_BLOCK=
FOREIGN_START_BLOCK=

LOG_LEVEL=info
MAX_PROCESSING_TIME=20000
  1. 构建并运行Bridge Oracle(使用Docker和Docker-compose)

这个docker包由Reddit数据库,Rabbit MQ代理和NodeJS工作者组成。

$docker-compose up --build

使用该标志-d在后台运行Bridge Oracle(守护进程)

步骤5:配置和部署桥UI

最后一步是部署用户界面以在侧链和主链之间传输令牌。

  1. 导航到该文件夹 ui
$cd ../ui
  1. 在中创建配置文件 ./.env

注意1:打开保存的JSON文件bridgeDeploymentResults.json以获取本地和外部桥接合约地址和部署块编号。

{
    "homeBridge": {
        "address": "0xc4e7cA947521f331969e41CC7c99ADa22F2C7F9C",
        "deployedBlockNumber": 9044640,
        "erc677": {
            "address": "0xEa3acD04DdaF1F1A5Ae1B9f5f690123aA4E19B36"
        }
    },
    "foreignBridge": {
        "address": "0xeb2dbC5AB9380A3517AcA9d8CA0c39873e569a93",
        "deployedBlockNumber": 4503560
    }
}
REACT_APP_HOME_BRIDGE_ADDRESS=address>
REACT_APP_FOREIGN_BRIDGE_ADDRESS=address>

REACT_APP_HOME_HTTP_PARITY_URL=https://sokol.poa.network
REACT_APP_FOREIGN_HTTP_PARITY_URL=https://rinkeby.infura.io/mew
  1. 运行Bridge UI
$npm start
  1. 打开您的Internet浏览器,使用用于部署BRT令牌的帐户解锁Rinkeby网络上的Metamask,然后转到http:// localhost:3000 /

如果您在RinkeBy网络上,您应该看到您在主链(RinkeBy)上拥有100 BRT令牌而在侧链上拥有0(POA Sokol)

您现在可以在主链和侧链之间传输BRT令牌:

参考文献:

提示:投资有风险,入市需谨慎,本资讯不作为投资理财建议。请理性投资,切实提高风险防范意识;如有发现的违法犯罪线索,可积极向有关部门举报反映。
你可能还喜欢