Commit 824fc0c9 authored by hezhengjun's avatar hezhengjun Committed by vipwzw

add cross2eth

parent 8b6584b9
# golang1.12 or latest
# 1. make help
# 2. make dep
# 3. make build
# ...
SRC_EBCLI := github.com/33cn/plugin/plugin/dapp/cross2eth/ebcli
SRC_EBRELAYER := github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer
CLI_A := build/ebcli_A
CLI_B := build/ebcli_B
CLI_C := build/ebcli_C
CLI_D := build/ebcli_D
EBRELAER := build/ebrelayer ##通过配置文件启动不同的ebrelayer
LDFLAGS := -ldflags "-w -s"
proj := "build"
.PHONY: default dep all build release cli linter race test fmt vet bench msan coverage coverhtml docker docker-compose protobuf clean help autotest
default: build
build:
@go build -v -i -o $(EBRELAER) $(SRC_EBRELAYER)
@go build -v -i -o $(CLI_A) $(SRC_EBCLI)
@go build -v -i -o $(CLI_B) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9902" $(SRC_EBCLI)
@go build -v -i -o $(CLI_C) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9903" $(SRC_EBCLI)
@go build -v -i -o $(CLI_D) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9904" $(SRC_EBCLI)
@cp ebrelayer/relayer.toml build/
rebuild:
make -C ebrelayer/ethcontract
make build
cli:
@go build -v -i -o $(CLI_A) $(SRC_EBCLI)
@go build -v -i -o $(CLI_B) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9902" $(SRC_EBCLI)
@go build -v -i -o $(CLI_C) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9903" $(SRC_EBCLI)
@go build -v -i -o $(CLI_D) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9904" $(SRC_EBCLI)
build_ci: depends ## Build the binary file for CI
@go build -v -i -o $(CLI) $(SRC_EBCLI)
@go build $(BUILD_FLAGS) -v -o $(APP)
@cp chain33.toml build/
para:
@go build -v -o build/$(NAME) -ldflags "-X $(SRC_EBCLI)/buildflags.ParaName=user.p.$(NAME). -X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:8901" $(SRC_EBCLI)
vet:
@go vet ${PKG_LIST_VET}
race: ## Run data race detector
@go test -race -short $(PKG_LIST)
test: ## Run unittests
@go test -race $(PKG_LIST)
fmt: fmt_proto fmt_shell ## go fmt
@go fmt ./...
@find . -name '*.go' -not -path "./vendor/*" | xargs goimports -l -w
.PHONY: fmt_proto fmt_shell
fmt_proto: ## go fmt protobuf file
#@find . -name '*.proto' -not -path "./vendor/*" | xargs clang-format -i
fmt_shell: ## check shell file
@find . -name '*.sh' -not -path "./vendor/*" | xargs shfmt -w -s -i 4 -ci -bn
fmt_go: fmt_shell ## go fmt
@go fmt ./...
@find . -name '*.go' -not -path "./vendor/*" | xargs goimports -l -w
docker: ## build docker image for chain33 run
@sudo docker build . -f ./build/Dockerfile-run -t chain33:latest
docker-compose: ## build docker-compose for chain33 run
@cd build && if ! [ -d ci ]; then \
make -C ../ ; \
fi; \
cp chain33* Dockerfile docker-compose* ci/ && cd ci/ && ./docker-compose-pre.sh run $(proj) $(dapp) && cd ../..
docker-compose-down: ## build docker-compose for chain33 run
@cd build && if [ -d ci ]; then \
cp chain33* Dockerfile docker-compose* ci/ && cd ci/ && ./docker-compose-pre.sh down $(proj) $(dapp) && cd .. ; \
fi; \
cd ..
clean: ## remove all the bins
@rm -rf $(CLI_A)
@rm -rf $(CLI_B)
@rm -rf $(CLI_C)
@rm -rf $(CLI_D)
@rm -rf $(EBRELAER)
@rm -rf build/*
proto:protobuf
protobuf: ## Generate protbuf file of types package
# @cd ${CHAIN33_PATH}/types/proto && ./create_protobuf.sh && cd ../..
@find ./plugin/dapp -maxdepth 2 -type d -name proto -exec make -C {} \;
help: ## Display this help screen
@printf "Help doc:\nUsage: make [command]\n"
@printf "[command]\n"
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
cleandata:
rm -rf build/datadir/addrbook
rm -rf build/datadir/blockchain.db
rm -rf build/datadir/mavltree
rm -rf build/chain33.log
.PHONY: checkgofmt
checkgofmt: ## get all go files and run go fmt on them
@files=$$(find . -name '*.go' -not -path "./vendor/*" | xargs gofmt -l -s); if [ -n "$$files" ]; then \
echo "Error: 'make fmt' needs to be run on:"; \
echo "${files}"; \
exit 1; \
fi;
@files=$$(find . -name '*.go' -not -path "./vendor/*" | xargs goimports -l -w); if [ -n "$$files" ]; then \
echo "Error: 'make fmt' needs to be run on:"; \
echo "${files}"; \
exit 1; \
fi;
proj := "build"
.PHONY: default build remote winset
SRC_CLI := 33cn/plugin/plugin/dapp/cross2eth/boss4x
OUT := build
default: build
build:
@go build -o ${OUT}/boss4x
remote:
@go build -v -o ${OUT}/boss4x_remote -ldflags "-X ${SRC_CLI}/buildFlags.RPCAddr4Chain33=http://183.129.226.74:8901"
winset:
@CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o ${OUT}/boss4x.exe -ldflags "-X ${SRC_CLI}/buildFlags.RPCAddr4Chain33=http://183.129.226.74:8901"
clean:
@rm ${OUT}/*
package buildFlags
var RPCAddr4Chain33 string
var RPCAddr4Ethereum string
var paraName string
package chain33
import (
"github.com/33cn/plugin/plugin/dapp/cross2eth/boss4x/chain33/offline"
"github.com/spf13/cobra"
)
func Chain33Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "chain33",
Short: "deploy to chain33",
}
cmd.AddCommand(
//deployCrossContractsCmd(),
offline.Boss4xOfflineCmd(),
)
return cmd
}
func deployCrossContractsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "deploy",
Short: "deploy all of the contracts for cross ",
Run: deployCrossContracts,
}
addDeployCrossContractsFlags(cmd)
return cmd
}
func addDeployCrossContractsFlags(cmd *cobra.Command) {
cmd.Flags().StringP("caller", "c", "", "the caller address")
cmd.MarkFlagRequired("caller")
cmd.Flags().StringP("expire", "", "120s", "transaction expire time (optional)")
cmd.Flags().StringP("note", "n", "", "transaction note info (optional)")
cmd.Flags().Float64P("fee", "f", 0, "contract gas fee (optional)")
}
func deployCrossContracts(cmd *cobra.Command, args []string) {
}
package offline
import (
"fmt"
"github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/contracts4chain33/generated"
ebTypes "github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/types"
utilsRelayer "github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/utils"
evmAbi "github.com/33cn/plugin/plugin/dapp/evm/executor/abi"
"github.com/spf13/cobra"
"math/big"
)
/*
./boss4x chain33 offline set_offline_token -c 1MaP3rrwiLV1wrxPhDwAfHggtei1ByaKrP -s BTY -m 100000000000 -p 50 -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae --chainID 33
./boss4x chain33 offline send -f chain33_set_offline_token.txt
*/
func ConfigLockedTokenOfflineSaveCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "set_offline_token",
Short: "set config offline locked token",
Run: ConfigMultisignLockedTokenOfflineSave,
}
addConfigLockedTokenOfflineSaveFlags(cmd)
return cmd
}
func addConfigLockedTokenOfflineSaveFlags(cmd *cobra.Command) {
cmd.Flags().StringP("contract", "c", "", "bridgebank contract address")
_ = cmd.MarkFlagRequired("contract")
cmd.Flags().StringP("token", "t", "", "token addr")
cmd.Flags().StringP("symbol", "s", "", "token symbol")
_ = cmd.MarkFlagRequired("symbol")
cmd.Flags().StringP("threshold", "m", "0", "threshold")
_ = cmd.MarkFlagRequired("threshold")
cmd.Flags().Uint8P("percents", "p", 50, "percents")
cmd.Flags().StringP("key", "k", "", "the deployer private key")
_ = cmd.MarkFlagRequired("key")
cmd.Flags().StringP("note", "n", "", "transaction note info (optional)")
cmd.Flags().Float64P("fee", "f", 0, "contract gas fee (optional)")
}
func ConfigMultisignLockedTokenOfflineSave(cmd *cobra.Command, _ []string) {
contract, _ := cmd.Flags().GetString("contract")
token, _ := cmd.Flags().GetString("token")
symbol, _ := cmd.Flags().GetString("symbol")
threshold, _ := cmd.Flags().GetString("threshold")
percents, _ := cmd.Flags().GetUint8("percents")
bn := big.NewInt(1)
bn, _ = bn.SetString(utilsRelayer.TrimZeroAndDot(threshold), 10)
if token == "" || symbol == "BTY" {
token = ebTypes.BTYAddrChain33
}
parameter := fmt.Sprintf("configLockedTokenOfflineSave(%s,%s,%d,%d)", token, symbol, bn, percents)
_, packData, err := evmAbi.Pack(parameter, generated.BridgeBankABI, false)
if nil != err {
fmt.Println("configOfflineSaveAccount", "Failed to do abi.Pack due to:", err.Error())
return
}
callContractAndSignWrite(cmd, packData, contract, "chain33_set_offline_token")
}
package offline
import (
"fmt"
"github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/contracts4chain33/generated"
evmAbi "github.com/33cn/plugin/plugin/dapp/evm/executor/abi"
"github.com/spf13/cobra"
)
/*
./boss4x chain33 offline set_offline_addr -a 16skyHQA4YPPnhrDSSpZnexDzasS8BNx1R -c 1QD5pHMKZ9QWiNb9AsH3G1aG3Hashye83o -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae --chainID 33
./boss4x chain33 offline send -f chain33_set_offline_addr.txt
*/
func ConfigOfflineSaveAccountCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "set_offline_addr",
Short: "save config offline account",
Run: ConfigMultisignOfflineSaveAccount, //配置账户
}
addConfigOfflineSaveAccountFlags(cmd)
return cmd
}
func addConfigOfflineSaveAccountFlags(cmd *cobra.Command) {
cmd.Flags().StringP("address", "a", "", "multisign address")
_ = cmd.MarkFlagRequired("address")
cmd.Flags().StringP("contract", "c", "", "bridgebank contract address")
_ = cmd.MarkFlagRequired("contract")
cmd.Flags().StringP("key", "k", "", "the deployer private key")
_ = cmd.MarkFlagRequired("key")
cmd.Flags().StringP("note", "n", "", "transaction note info (optional)")
cmd.Flags().Float64P("fee", "f", 0, "contract gas fee (optional)")
}
func ConfigMultisignOfflineSaveAccount(cmd *cobra.Command, _ []string) {
multisign, _ := cmd.Flags().GetString("address")
contract, _ := cmd.Flags().GetString("contract")
parameter := fmt.Sprintf("configOfflineSaveAccount(%s)", multisign)
_, packData, err := evmAbi.Pack(parameter, generated.BridgeBankABI, false)
if nil != err {
fmt.Println("configOfflineSaveAccount", "Failed to do abi.Pack due to:", err.Error())
return
}
callContractAndSignWrite(cmd, packData, contract, "chain33_set_offline_addr")
}
package offline
import (
"encoding/json"
"fmt"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/system/crypto/secp256k1"
"github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/contracts4chain33/generated"
erc20 "github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/erc20/generated"
"github.com/33cn/plugin/plugin/dapp/dex/utils"
evmAbi "github.com/33cn/plugin/plugin/dapp/evm/executor/abi"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
"github.com/spf13/cobra"
)
/*
./boss4x chain33 offline create_erc20 -s YCC -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae -o 1N6HstkyLFS8QCeVfdvYxx1xoryXoJtvvZ --chainID 33
./boss4x chain33 offline send -f deployErc20YCCChain33.txt
./boss4x chain33 offline approve_erc20 -a 330000000000 -s 1JmWVu1GEdQYSN1opxS9C39aS4NvG57yTr -c 1998HqVnt4JUirhC9KL5V71xYU8cFRn82c -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae --chainID 33
./boss4x chain33 offline send -f approve_erc20.txt
./boss4x chain33 offline create_add_lock_list -c 1JmWVu1GEdQYSN1opxS9C39aS4NvG57yTr -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae -t 1998HqVnt4JUirhC9KL5V71xYU8cFRn82c --chainID 33 -s YCC
./boss4x chain33 offline send -f create_add_lock_list.txt
./boss4x chain33 offline create_bridge_token -c 1JmWVu1GEdQYSN1opxS9C39aS4NvG57yTr -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae -s YCC --chainID 33
./boss4x chain33 offline send -f create_bridge_token.txt
${Chain33Cli} evm abi call -a "${chain33BridgeBank}" -c "${chain33DeployAddr}" -b "getToken2address(YCC)"
./chain33-cli evm abi call -a 1JmWVu1GEdQYSN1opxS9C39aS4NvG57yTr -c 1N6HstkyLFS8QCeVfdvYxx1xoryXoJtvvZ -b 'getToken2address(YCC)'
*/
func CreateERC20Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create_erc20",
Short: "create erc20 contracts and sign, default 3300*1e8 to be minted",
Run: CreateERC20,
}
CreateERC20Flags(cmd)
return cmd
}
//CreateERC20Flags ...
func CreateERC20Flags(cmd *cobra.Command) {
cmd.Flags().StringP("key", "k", "", "the deployer private key")
_ = cmd.MarkFlagRequired("key")
cmd.Flags().StringP("owner", "o", "", "owner address")
_ = cmd.MarkFlagRequired("owner")
cmd.Flags().StringP("symbol", "s", "", "token symbol")
_ = cmd.MarkFlagRequired("symbol")
cmd.Flags().Float64P("amount", "a", 0, "amount to be minted(optional),default to 3300*1e8")
}
func CreateERC20(cmd *cobra.Command, _ []string) {
symbol, _ := cmd.Flags().GetString("symbol")
owner, _ := cmd.Flags().GetString("owner")
amount, _ := cmd.Flags().GetFloat64("amount")
amountInt64 := int64(3300 * 1e8)
if 0 != int64(amount) {
amountInt64 = int64(amount)
}
privateKeyStr, _ := cmd.Flags().GetString("key")
var driver secp256k1.Driver
privateKeySli := common.FromHex(privateKeyStr)
privateKey, err := driver.PrivKeyFromBytes(privateKeySli)
if nil != err {
fmt.Println("Failed to do PrivKeyFromBytes")
return
}
fromAddr := address.PubKeyToAddress(privateKey.PubKey().Bytes())
from := common.Address{
Addr: fromAddr,
}
createPara := fmt.Sprintf("%s,%s,%s,%s", symbol, symbol, fmt.Sprintf("%d", amountInt64), owner)
content, txHash, err := utils.CreateContractAndSign(getTxInfo(cmd), erc20.ERC20Bin, erc20.ERC20ABI, createPara, "ERC20:"+symbol)
if nil != err {
fmt.Println("CreateContractAndSign erc20 fail")
return
}
newContractAddr := common.NewContractAddress(from, txHash).String()
Erc20Tx := &utils.Chain33OfflineTx{
ContractAddr: newContractAddr,
TxHash: common.Bytes2Hex(txHash),
SignedRawTx: content,
OperationName: "deploy ERC20:" + symbol,
}
data, err := json.MarshalIndent(Erc20Tx, "", " ")
if err != nil {
fmt.Println("MarshalIndent error", err.Error())
return
}
fmt.Println(string(data))
var txs []*utils.Chain33OfflineTx
txs = append(txs, Erc20Tx)
fileName := fmt.Sprintf("deployErc20%sChain33.txt", symbol)
fmt.Printf("Write all the txs to file: %s \n", fileName)
utils.WriteToFileInJson(fileName, txs)
}
func ApproveErc20Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "approve_erc20",
Short: "approve erc20",
Run: ApproveErc20, //配置账户
}
addApproveErc20Flags(cmd)
return cmd
}
func addApproveErc20Flags(cmd *cobra.Command) {
cmd.Flags().StringP("approve", "s", "", "approve addr")
_ = cmd.MarkFlagRequired("approve")
cmd.Flags().Float64P("amount", "a", 0, "approve amount")
_ = cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("contract", "c", "", "Erc20 contract address")
_ = cmd.MarkFlagRequired("contract")
cmd.Flags().StringP("key", "k", "", "the deployer private key")
_ = cmd.MarkFlagRequired("key")
cmd.Flags().StringP("note", "n", "", "transaction note info (optional)")
cmd.Flags().Float64P("fee", "f", 0, "contract gas fee (optional)")
}
func ApproveErc20(cmd *cobra.Command, _ []string) {
contract, _ := cmd.Flags().GetString("contract")
approve, _ := cmd.Flags().GetString("approve")
amount, _ := cmd.Flags().GetFloat64("amount")
parameter := fmt.Sprintf("approve(%s,%d)", approve, int64(amount))
_, packData, err := evmAbi.Pack(parameter, generated.BridgeTokenABI, false)
if nil != err {
fmt.Println("configOfflineSaveAccount", "Failed to do abi.Pack due to:", err.Error())
return
}
callContractAndSignWrite(cmd, packData, contract, "approve_erc20")
}
func AddToken2LockListCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create_add_lock_list",
Short: "add token to lock list",
Run: AddToken2LockList, //配置账户
}
addAddToken2LockListFlags(cmd)
return cmd
}
func addAddToken2LockListFlags(cmd *cobra.Command) {
cmd.Flags().StringP("symbol", "s", "", "token symbol")
_ = cmd.MarkFlagRequired("symbol")
cmd.Flags().StringP("token", "t", "", "token addr")
_ = cmd.MarkFlagRequired("token")
cmd.Flags().StringP("contract", "c", "", "bridgebank contract address")
_ = cmd.MarkFlagRequired("contract")
cmd.Flags().StringP("key", "k", "", "the deployer private key")
_ = cmd.MarkFlagRequired("key")
cmd.Flags().StringP("note", "n", "", "transaction note info (optional)")
cmd.Flags().Float64P("fee", "f", 0, "contract gas fee (optional)")
}
func AddToken2LockList(cmd *cobra.Command, _ []string) {
contract, _ := cmd.Flags().GetString("contract")
symbol, _ := cmd.Flags().GetString("symbol")
token, _ := cmd.Flags().GetString("token")
parameter := fmt.Sprintf("addToken2LockList(%s,%s)", token, symbol)
_, packData, err := evmAbi.Pack(parameter, generated.BridgeBankABI, false)
if nil != err {
fmt.Println("configOfflineSaveAccount", "Failed to do abi.Pack due to:", err.Error())
return
}
callContractAndSignWrite(cmd, packData, contract, "create_add_lock_list")
}
func CreateNewBridgeTokenCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create_bridge_token",
Short: "create new token as ethereum asset on chain33, and it's should be done by operator",
Run: CreateNewBridgeToken, //配置账户
}
addCreateNewBridgeTokenFlags(cmd)
return cmd
}
func addCreateNewBridgeTokenFlags(cmd *cobra.Command) {
cmd.Flags().StringP("symbol", "s", "", "token symbol")
_ = cmd.MarkFlagRequired("symbol")
cmd.Flags().StringP("contract", "c", "", "bridgebank contract address")
_ = cmd.MarkFlagRequired("contract")
cmd.Flags().StringP("key", "k", "", "the deployer private key")
_ = cmd.MarkFlagRequired("key")
cmd.Flags().StringP("note", "n", "", "transaction note info (optional)")
cmd.Flags().Float64P("fee", "f", 0, "contract gas fee (optional)")
}
func CreateNewBridgeToken(cmd *cobra.Command, _ []string) {
contract, _ := cmd.Flags().GetString("contract")
symbol, _ := cmd.Flags().GetString("symbol")
parameter := fmt.Sprintf("createNewBridgeToken(%s)", symbol)
_, packData, err := evmAbi.Pack(parameter, generated.BridgeBankABI, false)
if nil != err {
fmt.Println("configOfflineSaveAccount", "Failed to do abi.Pack due to:", err.Error())
return
}
callContractAndSignWrite(cmd, packData, contract, "create_bridge_token")
}
### 离线部署 chain33 跨链合约及各操作
***
#### 基础步骤
* 离线创建交易并签名 `./boss4x chain33 offline create ...`
* 在线发送签名后文件 `./boss4x chain33 offline send -f XXX.txt`
***
#### 离线部署 chain33 跨链合约
* 离线创建交易
```
交易1: 部署合约: Valset
交易2: 部署合约: chain33Bridge
交易3: 部署合约: Oracle
交易4: 部署合约: BridgeBank
交易5: 在合约chain33Bridge中设置BridgeBank合约地址
交易6: 在合约chain33Bridge中设置Oracle合约地址
交易7: 部署合约: BridgeRegistry
交易7: 部署合约: MulSign
命令:
./boss4x chain33 offline create -f 1 -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae -n 'deploy crossx to chain33' -r '1N6HstkyLFS8QCeVfdvYxx1xoryXoJtvvZ, [1N6HstkyLFS8QCeVfdvYxx1xoryXoJtvvZ, 155ooMPBTF8QQsGAknkK7ei5D78rwDEFe6, 13zBdQwuyDh7cKN79oT2odkxYuDbgQiXFv, 113ZzVamKfAtGt9dq45fX1mNsEoDiN95HG], [25, 25, 25, 25]' --chainID 33
参数说明:
-f, --fee float 交易费设置,因为只是少量几笔交易,且部署交易消耗gas较多,直接设置1个代币即可
-k, --key string 部署人的私钥,用于对交易签名
-n, --note string 备注信息
-r, --valset string 构造函数参数,严格按照该格式输入'addr, [addr, addr, addr, addr], [25, 25, 25, 25]',其中第一个地址为部署人私钥对应地址,后面4个地址为不同验证人的地址,4个数字为不同验证人的权重
--rpc_laddr string chain33 url 地址 (默认 "https://localhost:8801")
--chainID int32 平行链的chainID, 默认: 0(代表主链)
执行之后会将交易写入到文件:
deployCrossX2Chain33.txt
```
* 发送签名后文件
```
./boss4x chain33 offline send -f deployCrossX2Chain33.txt
```
***
#### 离线部署 ERC20 跨链合约
* 离线创建交易
```
命令:
./boss4x chain33 offline create_erc20 -s YCC -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae -o 1N6HstkyLFS8QCeVfdvYxx1xoryXoJtvvZ --chainID 33
参数说明:
-a, --amount float 铸币金额,默认 3300*1e8
-k, --key string 部署人的私钥,用于对交易签名
-o, --owner string 拥有者地址
-s, --symbol string token 标识
执行之后会将交易写入到文件:
deployErc20XXXChain33.txt 其中 XXX 为 token 标识
```
#### approve_erc20
* 离线创建交易
```
命令:
./boss4x chain33 offline approve_erc20 -a 330000000000 -s 1JmWVu1GEdQYSN1opxS9C39aS4NvG57yTr -c 1998HqVnt4JUirhC9KL5V71xYU8cFRn82c -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae --chainID 33
参数说明:
-a, --amount float 审批金额
-s, --approve string 审批地址, chain33 BridgeBank 合约地址
-c, --contract string Erc20 合约地址
-k, --key string 部署人的私钥,用于对交易签名
执行之后会将交易写入到文件:
approve_erc20.txt
```
#### create_add_lock_list
* 离线创建交易
```
命令:
./boss4x chain33 offline create_add_lock_list -c 1JmWVu1GEdQYSN1opxS9C39aS4NvG57yTr -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae -t 1998HqVnt4JUirhC9KL5V71xYU8cFRn82c --chainID 33 -s YCC
参数说明:
-c, --contract string bridgebank 合约地址
-k, --key string 部署人的私钥,用于对交易签名
-s, --symbol string token 标识
-t, --token string Erc20 合约地址
执行之后会将交易写入到文件:
create_add_lock_list.txt
```
#### create_bridge_token
* 离线创建交易
```
命令:
./boss4x chain33 offline create_bridge_token -c 1JmWVu1GEdQYSN1opxS9C39aS4NvG57yTr -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae -s YCC --chainID 33
参数说明:
-c, --contract string bridgebank 合约地址
-k, --key string 部署人的私钥,用于对交易签名
-s, --symbol string token 标识
执行之后会将交易写入到文件:
create_bridge_token.txt
```
* 获取 bridge_token 地址
```
命令:
./chain33-cli evm abi call -a 1JmWVu1GEdQYSN1opxS9C39aS4NvG57yTr -c 1N6HstkyLFS8QCeVfdvYxx1xoryXoJtvvZ -b 'getToken2address(YCC)'
参数说明:
-a, --address string evm 合约地址,这里是 chain33 BridgeBank 合约地址
-c, --caller string the caller address,这里是部署者地址
-b, --input string call params (abi format) like foobar(param1,param2),发送的函数
-t, --path string abi path(optional), default to .(current directory) (default "./"),abi文件地址,默认本地"./"
输出:
15XsGjTbV6SxQtDE1SC5oaHx8HbseQ4Lf9 -- bridge_token 地址
```
***
#### 设置离线多签地址信息
* 离线创建交易
```
命令:
./boss4x chain33 offline multisign_setup -m 1GrhufvPtnBCtfxDrFGcCoihmYMHJafuPn -o 168Sn1DXnLrZHTcAM9stD6t2P49fNuJfJ9,13KTf57aCkVVJYNJBXBBveiA5V811SrLcT,1JQwQWsShTHC4zxHzbUfYQK4kRBriUQdEe,1NHuKqoKe3hyv52PF8XBAyaTmJWAqA2Jbb -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae --chainID 33
参数说明:
-k, --key string 部署人私钥
-m, --multisign string 离线多签合约地址
-o, --owner string 多签的地址, 用','分隔
执行之后会将交易写入到文件:
multisign_setup.txt
```
***
#### 设置离线多签地址
* 离线创建交易
```
命令:
./boss4x chain33 offline set_offline_addr -a 16skyHQA4YPPnhrDSSpZnexDzasS8BNx1R -c 1QD5pHMKZ9QWiNb9AsH3G1aG3Hashye83o -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae --chainID 33
参数说明:
-a, --address string 离线多签地址
-c, --contract string bridgebank 合约地址
-f, --fee float 交易费
-k, --key string 部署者私钥
-n, --note string 备注
执行之后会将交易写入到文件:
chain33_set_offline_addr.txt
```
***
#### 离线多签设置
* 离线创建交易
```
命令:
./boss4x chain33 offline set_offline_token -c 1MaP3rrwiLV1wrxPhDwAfHggtei1ByaKrP -s BTY -m 100000000000 -p 50 -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae --chainID 33
参数说明:
-c, --contract string bridgebank 合约地址
-f, --fee float 交易费
-k, --key string 部署者私钥
-n, --note string 备注
-p, --percents uint8 百分比 (默认 50),达到阈值后默认转帐 50% 到离线多签的地址
-s, --symbol string token 标识
-m, --threshold string 阈值
-t, --token string token 地址
执行之后会将交易写入到文件:
chain33_set_offline_token.txt
```
***
#### 离线多签转帐
* 创建转帐交易--在线操作,需要重新获取 nonce 等信息
```
命令:
./boss4x chain33 offline create_multisign_transfer -a 10 -r 168Sn1DXnLrZHTcAM9stD6t2P49fNuJfJ9 -m 1NFDfEwne4kjuxAZrtYEh4kfSrnGSE7ap
参数说明:
-m, --address string 离线多签合约地址
-a, --amount float 转帐金额
-r, --receiver string 接收者地址
-t, --token string erc20 地址,空的话,默认转帐 BTY
执行之后会将交易写入到文件:
create_multisign_transfer.txt
```
* 离线多签地址签名交易--离线操作
```
命令:
./boss4x chain33 offline multisign_transfer -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262a -s 0xcd284cd17456b73619fa609bb9e3105e8eff5d059c5e0b6eb1effbebd4d64144,0xe892212221b3b58211b90194365f4662764b6d5474ef2961ef77c909e31eeed3,0x9d19a2e9a440187010634f4f08ce36e2bc7b521581436a99f05568be94dc66ea,0x45d4ce009e25e6d5e00d8d3a50565944b2e3604aa473680a656b242d9acbff35 --chainID 33
参数说明:
-f, --fee float 手续费
-t, --file string 签名交易文件, 默认: create_multisign_transfer.txt
-k, --key string 部署者私钥
-s, --keys string 离线多签的多个私钥, 用','分隔
-n, --note string 备注
执行之后会将交易写入到文件:
multisign_transfer.txt
```
package offline
import (
"fmt"
"github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/contracts4chain33/generated"
ebTypes "github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/types"
evmAbi "github.com/33cn/plugin/plugin/dapp/evm/executor/abi"
"github.com/spf13/cobra"
"strings"
)
/*
./boss4x chain33 offline multisign_setup -m 1GrhufvPtnBCtfxDrFGcCoihmYMHJafuPn -o 168Sn1DXnLrZHTcAM9stD6t2P49fNuJfJ9,13KTf57aCkVVJYNJBXBBveiA5V811SrLcT,1JQwQWsShTHC4zxHzbUfYQK4kRBriUQdEe,1NHuKqoKe3hyv52PF8XBAyaTmJWAqA2Jbb -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262ae --chainID 33
./boss4x chain33 offline send -f multisign_setup.txt
*/
func SetupCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "multisign_setup",
Short: "Setup owners to contract",
Run: SetupOwner,
}
SetupOwnerFlags(cmd)
return cmd
}
func SetupOwnerFlags(cmd *cobra.Command) {
cmd.Flags().StringP("owner", "o", "", "owners's address, separated by ','")
_ = cmd.MarkFlagRequired("owner")
cmd.Flags().StringP("key", "k", "", "operator private key")
_ = cmd.MarkFlagRequired("operator")
cmd.Flags().StringP("multisign", "m", "", "multisign contract address")
_ = cmd.MarkFlagRequired("multisign")
}
func SetupOwner(cmd *cobra.Command, _ []string) {
multisign, _ := cmd.Flags().GetString("multisign")
owner, _ := cmd.Flags().GetString("owner")
owners := strings.Split(owner, ",")
BTYAddrChain33 := ebTypes.BTYAddrChain33
parameter := "setup(["
parameter += fmt.Sprintf("%s", owners[0])
for _, owner := range owners[1:] {
parameter += fmt.Sprintf(",%s", owner)
}
parameter += "], "
parameter += fmt.Sprintf("%d, %s, 0102, %s, %s, 0, %s)", len(owners), BTYAddrChain33, BTYAddrChain33, BTYAddrChain33, BTYAddrChain33)
_, packData, err := evmAbi.Pack(parameter, generated.GnosisSafeABI, false)
if nil != err {
fmt.Println("multisign_setup", "Failed to do abi.Pack due to:", err.Error())
return
}
callContractAndSignWrite(cmd, packData, multisign, "multisign_setup")
}
package offline
import (
"fmt"
"math/big"
"strings"
chain33Common "github.com/33cn/chain33/common"
"github.com/33cn/chain33/system/crypto/secp256k1"
"github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/contracts4chain33/generated"
erc20 "github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/erc20/generated"
chain33Relayer "github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/relayer/chain33"
ebrelayerTypes "github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/types"
relayerutils "github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/utils"
evmAbi "github.com/33cn/plugin/plugin/dapp/evm/executor/abi"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common/math"
btcecsecp256k1 "github.com/btcsuite/btcd/btcec"
ethSecp256k1 "github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/spf13/cobra"
)
/*
./boss4x chain33 offline create_multisign_transfer -a 10 -r 168Sn1DXnLrZHTcAM9stD6t2P49fNuJfJ9 -m 1NFDfEwne4kjuxAZrtYEh4kfSrnGSE7ap
./boss4x chain33 offline multisign_transfer -k 0x027ca96466c71c7e7c5d73b7e1f43cb889b3bd65ebd2413eefd31c6709c262a -s 0xcd284cd17456b73619fa609bb9e3105e8eff5d059c5e0b6eb1effbebd4d64144,0xe892212221b3b58211b90194365f4662764b6d5474ef2961ef77c909e31eeed3,0x9d19a2e9a440187010634f4f08ce36e2bc7b521581436a99f05568be94dc66ea,0x45d4ce009e25e6d5e00d8d3a50565944b2e3604aa473680a656b242d9acbff35 --chainID 33
./boss4x chain33 offline send -f multisign_transfer.txt
*/
type transferTxData struct {
Receiver string
Token string
MultisignAddr string
Data string
Amount float64
name string
}
func CreateMultisignTransferCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create_multisign_transfer",
Short: "create multisign transfer tx",
Run: CreateMultisignTransfer,
}
addCreateMultisignTransferFlags(cmd)
return cmd
}
func addCreateMultisignTransferFlags(cmd *cobra.Command) {
cmd.Flags().StringP("receiver", "r", "", "receive address")
_ = cmd.MarkFlagRequired("receiver")
cmd.Flags().Float64P("amount", "a", 0, "amount to transfer")
_ = cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("token", "t", "", "erc20 address,not need to set for BTY(optional)")
//
cmd.Flags().StringP("address", "m", "", "multisign address")
_ = cmd.MarkFlagRequired("address")
}
func CreateMultisignTransfer(cmd *cobra.Command, _ []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
receiver, _ := cmd.Flags().GetString("receiver")
token, _ := cmd.Flags().GetString("token")
amount, _ := cmd.Flags().GetFloat64("amount")
multisign, _ := cmd.Flags().GetString("address")
//对于平台币转账,这个data只是个占位符,没有作用
dataStr := "0x"
safeTxGas := int64(10 * 10000)
baseGas := 0
gasPrice := 0
valueStr := relayerutils.ToWei(amount, 8).String()
//如果是bty转账,则直接将to地址设置为receiver,而如果是ERC20转账,则需要将其设置为token地址
to := receiver
//如果是erc20转账,则需要构建data数据
if "" != token {
parameter := fmt.Sprintf("transfer(%s, %s)", receiver, relayerutils.ToWei(amount, 8).String())
_, data, err := evmAbi.Pack(parameter, erc20.ERC20ABI, false)
if err != nil {
fmt.Println("Failed to do abi.Pack due to:", err.Error())
return
}
//对于其他erc20资产,直接将其设置为0
valueStr = "0"
to = token
dataStr = chain33Common.ToHex(data)
}
//获取nonce
nonce := getMulSignNonce(multisign, rpcLaddr)
parameter2getHash := fmt.Sprintf("getTransactionHash(%s, %s, %s, 0, %d, %d, %d, %s, %s, %d)", to, valueStr, dataStr,
safeTxGas, baseGas, gasPrice, ebrelayerTypes.NilAddrChain33, ebrelayerTypes.NilAddrChain33, nonce)
result := chain33Relayer.Query(multisign, parameter2getHash, multisign, rpcLaddr, generated.GnosisSafeABI)
if nil == result {
fmt.Println("Failed to getTransactionHash :", ebrelayerTypes.ErrGetTransactionHash)
return
}
contentHashArray := result.([32]byte)
contentHash := contentHashArray[:]
var txinfo transferTxData
txinfo.Receiver = receiver
txinfo.MultisignAddr = multisign
txinfo.Amount = amount
txinfo.Data = chain33Common.ToHex(contentHash)
txinfo.Token = token
txinfo.name = "create_multisign_transfer"
writeToFile(txinfo.name+".txt", txinfo)
}
func MultisignTransferCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "multisign_transfer",
Short: "create multisign transfer tx and sign",
Run: MultisignTransfer,
}
addMultisignTransferFlags(cmd)
return cmd
}
func addMultisignTransferFlags(cmd *cobra.Command) {
cmd.Flags().StringP("file", "t", "create_multisign_transfer.txt", "tx file, default: create_multisign_transfer.txt")
cmd.Flags().StringP("keys", "s", "", "owners' private key, separated by ','")
_ = cmd.MarkFlagRequired("keys")
cmd.Flags().StringP("key", "k", "", "the deployer private key")
_ = cmd.MarkFlagRequired("key")
cmd.Flags().StringP("note", "n", "", "transaction note info (optional)")
cmd.Flags().Float64P("fee", "f", 0, "contract gas fee (optional)")
}
func MultisignTransfer(cmd *cobra.Command, _ []string) {
keysStr, _ := cmd.Flags().GetString("keys")
keys := strings.Split(keysStr, ",")
txFilePath, _ := cmd.Flags().GetString("file")
var txinfo transferTxData
err := paraseFile(txFilePath, &txinfo)
if err != nil {
fmt.Println("paraseFile Err:", err)
return
}
//对于平台币转账,这个data只是个占位符,没有作用
dataStr := "0x"
contentHash, err := chain33Common.FromHex(txinfo.Data)
safeTxGas := int64(10 * 10000)
baseGas := 0
gasPrice := 0
valueStr := relayerutils.ToWei(txinfo.Amount, 8).String()
//如果是bty转账,则直接将to地址设置为receiver,而如果是ERC20转账,则需要将其设置为token地址
to := txinfo.Receiver
//如果是erc20转账,则需要构建data数据
if "" != txinfo.Token {
parameter := fmt.Sprintf("transfer(%s, %s)", txinfo.Receiver, relayerutils.ToWei(txinfo.Amount, 8).String())
_, data, err := evmAbi.Pack(parameter, erc20.ERC20ABI, false)
if err != nil {
fmt.Println("evmAbi.Pack(parameter, erc20.ERC20ABI, false)", "Failed", err.Error())
return
}
//对于其他erc20资产,直接将其设置为0
valueStr = "0"
to = txinfo.Token
dataStr = chain33Common.ToHex(data)
}
var sigs []byte
for _, privateKey := range keys {
var driver secp256k1.Driver
privateKeySli, err := chain33Common.FromHex(privateKey)
if nil != err {
fmt.Println("evmAbi.Pack(parameter, erc20.ERC20ABI, false)", "Failed", err.Error())
return
}
ownerPrivateKey, err := driver.PrivKeyFromBytes(privateKeySli)
if nil != err {
fmt.Println("evmAbi.Pack(parameter, erc20.ERC20ABI, false)", "Failed", err.Error())
return
}
temp, _ := btcecsecp256k1.PrivKeyFromBytes(btcecsecp256k1.S256(), ownerPrivateKey.Bytes())
privateKey4chain33Ecdsa := temp.ToECDSA()
sig, err := ethSecp256k1.Sign(contentHash, math.PaddedBigBytes(privateKey4chain33Ecdsa.D, 32))
if nil != err {
fmt.Println("evmAbi.Pack(parameter, erc20.ERC20ABI, false)", "Failed", err.Error())
return
}
sig[64] += 27
sigs = append(sigs, sig...)
}
//构造execTransaction参数
parameter2Exec := fmt.Sprintf("execTransaction(%s, %s, %s, 0, %d, %d, %d, %s, %s, %s)", to, valueStr, dataStr,
safeTxGas, baseGas, gasPrice, ebrelayerTypes.NilAddrChain33, ebrelayerTypes.NilAddrChain33, chain33Common.ToHex(sigs))
_, packData, err := evmAbi.Pack(parameter2Exec, generated.GnosisSafeABI, false)
if nil != err {
fmt.Println("execTransaction evmAbi.Pack", "Failed", err.Error())
return
}
callContractAndSignWrite(cmd, packData, txinfo.MultisignAddr, "multisign_transfer")
}
func getMulSignNonce(mulsign, rpcLaddr string) int64 {
parameter := fmt.Sprintf("nonce()")
result := chain33Relayer.Query(mulsign, parameter, mulsign, rpcLaddr, generated.GnosisSafeABI)
if nil == result {
return 0
}
nonce := result.(*big.Int)
return nonce.Int64()
}
package offline
import (
"encoding/json"
"fmt"
"github.com/33cn/plugin/plugin/dapp/dex/utils"
evmtypes "github.com/33cn/plugin/plugin/dapp/evm/types"
"github.com/ethereum/go-ethereum/common"
"github.com/spf13/cobra"
"io/ioutil"
"os"
)
var crossXfileName = "deployCrossX2Chain33.txt"
func Boss4xOfflineCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "offline",
Short: "create and sign offline tx to deploy and set cross contracts to chain33",
}
cmd.AddCommand(
CreateCrossBridgeCmd(),
SendSignTxs2Chain33Cmd(),
CreateERC20Cmd(),
ApproveErc20Cmd(),
AddToken2LockListCmd(),
CreateNewBridgeTokenCmd(),
SetupCmd(),
ConfigOfflineSaveAccountCmd(),
ConfigLockedTokenOfflineSaveCmd(),
CreateMultisignTransferCmd(),
MultisignTransferCmd(),
)
return cmd
}
func SendSignTxs2Chain33Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "send",
Short: "send all the crossX txs to chain33 in serial",
Run: sendSignTxs2Chain33,
}
addSendSignTxs2Chain33Flags(cmd)
return cmd
}
func addSendSignTxs2Chain33Flags(cmd *cobra.Command) {
cmd.Flags().StringP("file", "f", "", "signed tx file")
_ = cmd.MarkFlagRequired("file")
}
func sendSignTxs2Chain33(cmd *cobra.Command, _ []string) {
filePath, _ := cmd.Flags().GetString("file")
url, _ := cmd.Flags().GetString("rpc_laddr")
utils.SendSignTxs2Chain33(filePath, url)
}
func getTxInfo(cmd *cobra.Command) *utils.TxCreateInfo {
privateKey, _ := cmd.Flags().GetString("key")
expire, _ := cmd.Flags().GetString("expire")
note, _ := cmd.Flags().GetString("note")
fee, _ := cmd.Flags().GetFloat64("fee")
paraName, _ := cmd.Flags().GetString("paraName")
chainID, _ := cmd.Flags().GetInt32("chainID")
feeInt64 := int64(fee*1e4) * 1e4
info := &utils.TxCreateInfo{
PrivateKey: privateKey,
Expire: expire,
Note: note,
Fee: feeInt64,
ParaName: paraName,
ChainID: chainID,
}
return info
}
func writeToFile(fileName string, content interface{}) {
jbytes, err := json.MarshalIndent(content, "", "\t")
if err != nil {
panic(err)
}
err = ioutil.WriteFile(fileName, jbytes, 0666)
if err != nil {
fmt.Println("Failed to write to file:", fileName)
}
fmt.Println("tx is written to file: ", fileName)
}
func paraseFile(file string, result interface{}) error {
_, err := os.Stat(file)
if err != nil {
fmt.Println(err.Error())
return err
}
f, err := os.Open(file)
if err != nil {
panic(err)
}
b, err := ioutil.ReadAll(f)
if err != nil {
panic(err)
}
return json.Unmarshal(b, result)
}
func callContractAndSignWrite(cmd *cobra.Command, para []byte, contractAddr, name string) {
action := &evmtypes.EVMContractAction{Amount: 0, GasLimit: 0, GasPrice: 0, Note: name, Para: para, ContractAddr: contractAddr}
content, txHash, err := utils.CallContractAndSign(getTxInfo(cmd), action, contractAddr)
if nil != err {
fmt.Println("CallContractAndSign", "Failed", err.Error())
return
}
Tx := &utils.Chain33OfflineTx{
ContractAddr: contractAddr,
TxHash: common.Bytes2Hex(txHash),
SignedRawTx: content,
OperationName: name,
}
_, err = json.MarshalIndent(Tx, "", " ")
if err != nil {
fmt.Println("MarshalIndent error", err.Error())
return
}
var txs []*utils.Chain33OfflineTx
txs = append(txs, Tx)
fileName := fmt.Sprintf(Tx.OperationName + ".txt")
fmt.Printf("Write all the txs to file: %s \n", fileName)
utils.WriteToFileInJson(fileName, txs)
}
package main
import (
"fmt"
"net/http"
"os"
"strings"
"github.com/33cn/plugin/plugin/dapp/cross2eth/boss4x/buildFlags"
"github.com/33cn/plugin/plugin/dapp/cross2eth/boss4x/chain33"
"github.com/33cn/plugin/plugin/dapp/cross2eth/boss4x/ethereum"
"github.com/spf13/cobra"
)
func main() {
if buildFlags.RPCAddr4Chain33 == "" {
buildFlags.RPCAddr4Chain33 = "http://localhost:8801"
}
buildFlags.RPCAddr4Chain33 = testTLS(buildFlags.RPCAddr4Chain33)
if buildFlags.RPCAddr4Ethereum == "" {
buildFlags.RPCAddr4Ethereum = "http://localhost:7545"
}
rootCmd := RootCmd()
rootCmd.PersistentFlags().String("rpc_laddr", buildFlags.RPCAddr4Chain33, "http url")
rootCmd.PersistentFlags().String("rpc_laddr_ethereum", buildFlags.RPCAddr4Ethereum, "http url")
rootCmd.PersistentFlags().String("paraName", "", "para chain name,Eg:user.p.fzm.")
rootCmd.PersistentFlags().String("expire", "120m", "transaction expire time (optional)")
rootCmd.PersistentFlags().Int32("chainID", 0, "chain id, default to 0")
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
// RootCmd Cmd x2ethereum client command
func RootCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "boss",
Short: "manage create offline tx or deploy contracts(dex) for test",
}
cmd.AddCommand(
chain33.Chain33Cmd(),
ethereum.EthCmd(),
)
return cmd
}
func testTLS(RPCAddr string) string {
rpcaddr := RPCAddr
if !strings.HasPrefix(rpcaddr, "http://") {
return RPCAddr
}
// if http://
if rpcaddr[len(rpcaddr)-1] != '/' {
rpcaddr += "/"
}
rpcaddr += "test"
/* #nosec */
resp, err := http.Get(rpcaddr)
if err != nil {
return "https://" + RPCAddr[7:]
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
return RPCAddr
}
return "https://" + RPCAddr[7:]
}
package ethereum
import (
"crypto/ecdsa"
"fmt"
"github.com/33cn/plugin/plugin/dapp/cross2eth/boss4x/ethereum/offline"
"github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/relayer/ethereum/ethtxs"
tml "github.com/BurntSushi/toml"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/spf13/cobra"
"math/big"
"os"
)
type DepolyInfo struct {
OperatorAddr string `toml:"operatorAddr"`
DeployerPrivateKey string `toml:"deployerPrivateKey"`
ValidatorsAddr []string `toml:"validatorsAddr"`
InitPowers []int64 `toml:"initPowers"`
}
func EthCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "ethereum",
Short: "deploy to eth",
}
cmd.AddCommand(
//DeployContrctsCmd(),
offline.DeployOfflineContractsCmd(),
)
return cmd
}
//DeployContrctsCmd ...
func DeployContrctsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "deploy",
Short: "deploy the corresponding Ethereum contracts",
Run: DeployContrcts,
}
addDeployFlags(cmd)
return cmd
}
func addDeployFlags(cmd *cobra.Command) {
//私钥的优先权大于配置文件的
cmd.Flags().StringP("privkey", "p", "", "deployer privatekey")
_ = cmd.MarkFlagRequired("privkey")
cmd.Flags().StringP("file", "f", "", "deploy config")
_ = cmd.MarkFlagRequired("file")
}
//DeployContrcts ...
func DeployContrcts(cmd *cobra.Command, args []string) {
var deployKeystr string
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr_ethereum")
filepath, _ := cmd.Flags().GetString("file")
privkey, _ := cmd.Flags().GetString("privkey")
var deployCfg DepolyInfo
InitCfg(filepath, &deployCfg)
if privkey != "" {
deployKeystr = privkey
} else {
deployKeystr = deployCfg.DeployerPrivateKey
}
deployPrivateKey, err := crypto.ToECDSA(common.FromHex(deployKeystr))
if err != nil {
panic(err)
}
if len(deployCfg.InitPowers) != len(deployCfg.ValidatorsAddr) {
panic("not same number for validator address and power")
}
if len(deployCfg.ValidatorsAddr) < 3 {
panic("the number of validator must be not less than 3")
}
var validators []common.Address
var initPowers []*big.Int
for i, addr := range deployCfg.ValidatorsAddr {
validators = append(validators, common.HexToAddress(addr))
initPowers = append(initPowers, big.NewInt(deployCfg.InitPowers[i]))
}
deployerAddr := crypto.PubkeyToAddress(deployPrivateKey.PublicKey)
para := &ethtxs.DeployPara{
DeployPrivateKey: deployPrivateKey,
Deployer: deployerAddr,
Operator: deployerAddr,
InitValidators: validators,
ValidatorPriKey: []*ecdsa.PrivateKey{deployPrivateKey},
InitPowers: initPowers,
}
client, err := ethtxs.SetupWebsocketEthClient(rpcLaddr)
_, x2EthDeployInfo, err := ethtxs.DeployAndInit(client, para)
if err != nil {
fmt.Println("DeployAndInit,err:", err.Error())
return
}
bridgeRegistry := x2EthDeployInfo.BridgeRegistry.Address.String()
fmt.Println("the BridgeRegistry address is:", bridgeRegistry)
}
func InitCfg(filepath string, cfg interface{}) {
if _, err := tml.DecodeFile(filepath, cfg); err != nil {
fmt.Println(err)
os.Exit(-1)
}
return
}
#合约部署人员私钥,用于部署合约时签名使用
deployerPrivateKey="8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
#验证人地址,至少配置3个以上,即大于等于3个
validatorsAddr=["0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a", "0x0df9a824699bc5878232c9e612fe1a5346a5a368", "0xcb074cb21cdddf3ce9c3c0a7ac4497d633c9d9f1", "0xd9dab021e74ecf475788ed7b61356056b2095830"]
#验证人权重
initPowers=[96, 1, 1, 1]
package offline
import (
"context"
"fmt"
"math/big"
"strings"
"github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/contracts4eth/generated"
erc20 "github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/erc20/generated"
"github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/utils"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/spf13/cobra"
)
/*
./boss4x ethereum offline create_erc20 -m 33000000000000000000 -s YCC -o 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a
./boss4x ethereum offline sign -f deployErc20YCC.txt -k 8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230
./boss4x ethereum offline send -f deploysigntxs.txt
./boss4x ethereum offline create_add_lock_list -s YCC -t 0x20a32A5680EBf55740B0C98B54cDE8e6FD5a4FB0 -c 0xC65B02a22B714b55D708518E2426a22ffB79113d -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a
./boss4x ethereum offline sign -f create_add_lock_list.txt -k 8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230
./boss4x ethereum offline send -f deploysigntxs.txt
./boss4x ethereum offline create_bridge_token -s YCC -c 0xC65B02a22B714b55D708518E2426a22ffB79113d -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a
./boss4x ethereum offline sign -f create_bridge_token.txt -k 8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230
./boss4x ethereum offline send -f deploysigntxs.txt
*/
func DeployERC20Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create_erc20",
Short: "create ERC20 contracts",
Run: DeployERC20,
}
DeployERC20Flags(cmd)
return cmd
}
func DeployERC20Flags(cmd *cobra.Command) {
cmd.Flags().StringP("deployAddr", "d", "", "deploy contract addr")
_ = cmd.MarkFlagRequired("deployAddr")
cmd.Flags().StringP("owner", "o", "", "owner address")
_ = cmd.MarkFlagRequired("owner")
cmd.Flags().StringP("symbol", "s", "", "erc20 symbol")
_ = cmd.MarkFlagRequired("symbol")
cmd.Flags().StringP("amount", "m", "0", "amount")
_ = cmd.MarkFlagRequired("amount")
}
func DeployERC20(cmd *cobra.Command, _ []string) {
url, _ := cmd.Flags().GetString("rpc_laddr_ethereum")
deployerAddr, _ := cmd.Flags().GetString("deployAddr")
owner, _ := cmd.Flags().GetString("owner")
symbol, _ := cmd.Flags().GetString("symbol")
amount, _ := cmd.Flags().GetString("amount")
bnAmount := big.NewInt(1)
bnAmount, _ = bnAmount.SetString(utils.TrimZeroAndDot(amount), 10)
client, err := ethclient.Dial(url)
if err != nil {
fmt.Println("ethclient Dial error", err.Error())
return
}
ctx := context.Background()
startNonce, err := client.PendingNonceAt(ctx, common.HexToAddress(deployerAddr))
if nil != err {
fmt.Println("PendingNonceAt error", err.Error())
return
}
var infos []*DeployInfo
parsed, err := abi.JSON(strings.NewReader(erc20.ERC20ABI))
if err != nil {
fmt.Println("abi.JSON(strings.NewReader(erc20.ERC20ABI)) error", err.Error())
return
}
bin := common.FromHex(erc20.ERC20Bin)
Erc20OwnerAddr := common.HexToAddress(owner)
packdata, err := parsed.Pack("", symbol, symbol, bnAmount, Erc20OwnerAddr)
if err != nil {
fmt.Println("Pack error", err.Error())
return
}
Erc20Addr := crypto.CreateAddress(common.HexToAddress(deployerAddr), startNonce)
deployInfo := DeployInfo{
PackData: append(bin, packdata...),
ContractorAddr: Erc20Addr,
Name: "Erc20: " + symbol,
Nonce: startNonce,
To: nil,
}
infos = append(infos, &deployInfo)
fileName := fmt.Sprintf("deployErc20%s.txt", symbol)
err = NewTxWrite(infos, common.HexToAddress(deployerAddr), url, fileName)
if err != nil {
fmt.Println("NewTxWrite error", err.Error())
return
}
}
func CreateAddToken2LockListTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create_add_lock_list",
Short: "add token to lock list",
Run: AddToken2LockListTx,
}
AddToken2LockListTxFlags(cmd)
return cmd
}
func AddToken2LockListTxFlags(cmd *cobra.Command) {
cmd.Flags().StringP("deployAddr", "d", "", "deploy contract addr")
_ = cmd.MarkFlagRequired("deployAddr")
cmd.Flags().StringP("symbol", "s", "", "token symbol")
_ = cmd.MarkFlagRequired("symbol")
cmd.Flags().StringP("token", "t", "", "token addr")
_ = cmd.MarkFlagRequired("token")
cmd.Flags().StringP("contract", "c", "", "bridgebank contract address")
_ = cmd.MarkFlagRequired("contract")
}
func AddToken2LockListTx(cmd *cobra.Command, _ []string) {
url, _ := cmd.Flags().GetString("rpc_laddr_ethereum")
symbol, _ := cmd.Flags().GetString("symbol")
deployAddr, _ := cmd.Flags().GetString("deployAddr")
token, _ := cmd.Flags().GetString("token")
contract, _ := cmd.Flags().GetString("contract")
bridgeAbi, err := abi.JSON(strings.NewReader(generated.BridgeBankABI))
if err != nil {
fmt.Println("JSON NewReader Err:", err)
return
}
abiData, err := bridgeAbi.Pack("addToken2LockList", common.HexToAddress(token), symbol)
if err != nil {
fmt.Println("bridgeAbi.Pack addToken2LockList Err:", err)
return
}
CreateTxInfoAndWrite(abiData, deployAddr, contract, "create_add_lock_list", url)
}
func CreateBridgeTokenTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create_bridge_token",
Short: "create new token as chain33 asset on Ethereum, and it's should be done by operator",
Run: CreateBridgeTokenTx,
}
CreateBridgeTokenTxFlags(cmd)
return cmd
}
func CreateBridgeTokenTxFlags(cmd *cobra.Command) {
cmd.Flags().StringP("deployAddr", "d", "", "deploy contract addr")
_ = cmd.MarkFlagRequired("deployAddr")
cmd.Flags().StringP("symbol", "s", "", "token symbol")
_ = cmd.MarkFlagRequired("symbol")
cmd.Flags().StringP("contract", "c", "", "bridgebank contract address")
_ = cmd.MarkFlagRequired("contract")
}
func CreateBridgeTokenTx(cmd *cobra.Command, _ []string) {
url, _ := cmd.Flags().GetString("rpc_laddr_ethereum")
symbol, _ := cmd.Flags().GetString("symbol")
deployAddr, _ := cmd.Flags().GetString("deployAddr")
contract, _ := cmd.Flags().GetString("contract")
bridgeAbi, err := abi.JSON(strings.NewReader(generated.BridgeBankABI))
if err != nil {
fmt.Println("JSON NewReader Err:", err)
return
}
abiData, err := bridgeAbi.Pack("createNewBridgeToken", symbol)
if err != nil {
fmt.Println("bridgeAbi.Pack createNewBridgeToken Err:", err)
return
}
CreateTxInfoAndWrite(abiData, deployAddr, contract, "create_bridge_token", url)
}
package offline
import (
//"context"
"fmt"
"github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/contracts4eth/generated"
gnosis "github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/gnosis/generated"
ebTypes "github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/types"
"math/big"
//"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
//"github.com/ethereum/go-ethereum/core/types"
//"github.com/ethereum/go-ethereum/crypto"
//"github.com/ethereum/go-ethereum/ethclient"
"github.com/spf13/cobra"
//"math/big"
"strings"
)
/*
./boss4x ethereum offline set_offline_addr -a 0xbf271b2B23DA4fA8Dc93Ce86D27dd09796a7Bf54 -c 0xC65B02a22B714b55D708518E2426a22ffB79113d -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a
./boss4x ethereum offline sign -f set_offline_addr.txt -k 8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230
./boss4x ethereum offline send -f deploysigntxs.txt
./boss4x ethereum offline multisign_setup -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a -o 0x4c85848a7E2985B76f06a7Ed338FCB3aF94a7DCf,0x6F163E6daf0090D897AD7016484f10e0cE844994,0xbc333839E37bc7fAAD0137aBaE2275030555101f,0x495953A743ef169EC5D4aC7b5F786BF2Bd56aFd5 -m 0x871887bC6D9b21B82787a66145D38172cA816d09
tx is written to file: multisign_setup.txt
./boss4x ethereum offline sign -k 8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230 -f multisign_setup.txt
deployTxInfos size: 1
tx is written to file: deploysigntxs.txt
./boss4x ethereum offline send -f deploysigntxs.txt
*/
func CreateCfgAccountTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "set_offline_addr",
Short: "save config offline account",
Run: cfgAccountTx, //配置账户
}
addCfgTxFlags(cmd)
return cmd
}
func addCfgTxFlags(cmd *cobra.Command) {
cmd.Flags().StringP("address", "a", "", "multisign address")
_ = cmd.MarkFlagRequired("address")
cmd.Flags().StringP("deployAddr", "d", "", "deploy contract addr")
_ = cmd.MarkFlagRequired("deployAddr")
cmd.Flags().StringP("contract", "c", "", "bridgebank contract address")
_ = cmd.MarkFlagRequired("contract")
}
func cfgAccountTx(cmd *cobra.Command, _ []string) {
url, _ := cmd.Flags().GetString("rpc_laddr_ethereum")
address, _ := cmd.Flags().GetString("address")
deployAddr, _ := cmd.Flags().GetString("deployAddr")
contract, _ := cmd.Flags().GetString("contract")
bridgeAbi, err := abi.JSON(strings.NewReader(generated.BridgeBankABI))
if err != nil {
fmt.Println("JSON NewReader Err:", err)
return
}
abiData, err := bridgeAbi.Pack("configOfflineSaveAccount", common.HexToAddress(address))
if err != nil {
panic(err)
}
CreateTxInfoAndWrite(abiData, deployAddr, contract, "set_offline_addr", url)
}
func SetupCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "multisign_setup",
Short: "Setup owners to contract",
Run: SetupOwner,
}
SetupOwnerFlags(cmd)
return cmd
}
func SetupOwnerFlags(cmd *cobra.Command) {
cmd.Flags().StringP("owner", "o", "", "owners's address, separated by ','")
_ = cmd.MarkFlagRequired("owner")
cmd.Flags().StringP("deployAddr", "d", "", "deploy contract addr")
_ = cmd.MarkFlagRequired("deployAddr")
cmd.Flags().StringP("multisign", "m", "", "multisign contract address")
_ = cmd.MarkFlagRequired("multisign")
}
func SetupOwner(cmd *cobra.Command, _ []string) {
url, _ := cmd.Flags().GetString("rpc_laddr_ethereum")
multisign, _ := cmd.Flags().GetString("multisign")
deployAddr, _ := cmd.Flags().GetString("deployAddr")
owner, _ := cmd.Flags().GetString("owner")
owners := strings.Split(owner, ",")
var _owners []common.Address
for _, onwer := range owners {
_owners = append(_owners, common.HexToAddress(onwer))
}
AddressZero := common.HexToAddress(ebTypes.EthNilAddr)
gnoAbi, err := abi.JSON(strings.NewReader(gnosis.GnosisSafeABI))
if err != nil {
fmt.Println("JSON Err:", err)
return
}
abiData, err := gnoAbi.Pack("setup", _owners, big.NewInt(int64(len(_owners))), AddressZero, []byte{'0', 'x'},
AddressZero, AddressZero, big.NewInt(int64(0)), AddressZero)
if err != nil {
fmt.Println("Pack execTransaction Err:", err)
return
}
CreateTxInfoAndWrite(abiData, deployAddr, multisign, "multisign_setup", url)
}
package offline
import (
"fmt"
"github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/contracts4eth/generated"
ebTypes "github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/types"
"github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/utils"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/spf13/cobra"
"math/big"
"strings"
)
/*
./boss4x ethereum offline set_offline_token -s ETH -m 20 -c 0xC65B02a22B714b55D708518E2426a22ffB79113d -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a
./boss4x ethereum offline sign -f set_offline_token.txt -k 8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230
./boss4x ethereum offline send -f deploysigntxs.txt
*/
func ConfigLockedTokenOfflineSaveCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "set_offline_token",
Short: "set config offline locked token",
Run: ConfigLockedTokenOfflineSave,
}
ConfigLockedTokenOfflineSaveFlags(cmd)
return cmd
}
//ConfigLockedTokenOfflineSaveFlags ...
func ConfigLockedTokenOfflineSaveFlags(cmd *cobra.Command) {
cmd.Flags().StringP("token", "t", "", "token addr")
//_ = cmd.MarkFlagRequired("token")
cmd.Flags().StringP("symbol", "s", "", "token symbol")
_ = cmd.MarkFlagRequired("symbol")
cmd.Flags().Float64P("threshold", "m", 0, "threshold")
_ = cmd.MarkFlagRequired("threshold")
cmd.Flags().Uint8P("percents", "p", 50, "percents")
//_ = cmd.MarkFlagRequired("percents")
cmd.Flags().StringP("deployAddr", "d", "", "deploy contract addr")
_ = cmd.MarkFlagRequired("deployAddr")
cmd.Flags().StringP("contract", "c", "", "bridgebank contract address")
_ = cmd.MarkFlagRequired("contract")
}
func ConfigLockedTokenOfflineSave(cmd *cobra.Command, _ []string) {
url, _ := cmd.Flags().GetString("rpc_laddr_ethereum")
symbol, _ := cmd.Flags().GetString("symbol")
token, _ := cmd.Flags().GetString("token")
threshold, _ := cmd.Flags().GetFloat64("threshold")
percents, _ := cmd.Flags().GetUint8("percents")
deployAddr, _ := cmd.Flags().GetString("deployAddr")
contract, _ := cmd.Flags().GetString("contract")
d, err := utils.GetDecimalsFromNode(token, url)
if err != nil {
fmt.Println("get decimals error", err.Error())
return
}
realAmount := utils.ToWei(threshold, d)
bn := big.NewInt(1)
bn, _ = bn.SetString(utils.TrimZeroAndDot(realAmount.String()), 10)
if percents > 100 || percents < 0 {
fmt.Println("param percents err")
return
}
if token == "" || symbol == "ETH" {
token = ebTypes.EthNilAddr
}
tokenAddr := common.HexToAddress(token)
bridgeAbi, err := abi.JSON(strings.NewReader(generated.BridgeBankABI))
if err != nil {
fmt.Println("JSON NewReader Err:", err)
return
}
abiData, err := bridgeAbi.Pack("configLockedTokenOfflineSave", tokenAddr, symbol, bn, percents)
if err != nil {
panic(err)
}
CreateTxInfoAndWrite(abiData, deployAddr, contract, "set_offline_token", url)
}
### 离线部署 ethereum 跨链合约及各操作
***
#### 基础步骤
* 在线创建交易 `./boss4x ethereum offline create ...` 需要在线查询 nonce 等信息
* 离线签名交易 `./boss4x ethereum offline sign -f xxx.txt -k 8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230`
* 在线发送签名后文件 `./boss4x ethereum offline send -f deploysigntxs.txt` 默认签名后的文件名称都是 deploysigntxs.txt
***
#### 离线部署 ethereum 跨链合约
* 在线创建交易
```
交易1: 部署合约: Valset
交易2: 部署合约: EthereumBridge
交易3: 部署合约: Oracle
交易4: 部署合约: BridgeBank
交易5: 在合约EthereumBridge中设置BridgeBank合约地址
交易6: 在合约EthereumBridge中设置Oracle合约地址
交易7: 部署合约: BridgeRegistry
交易7: 部署合约: MulSign
命令:
./boss4x ethereum offline create -p 25,25,25,25 -o 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a -v 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a,0x0df9a824699bc5878232c9e612fe1a5346a5a368,0xcb074cb21cdddf3ce9c3c0a7ac4497d633c9d9f1,0xd9dab021e74ecf475788ed7b61356056b2095830
参数说明:
-p, --initPowers string 验证者权重, as: '25,25,25,25'
-o, --owner string 部署者地址
-v, --validatorsAddrs string 验证者地址, as: 'addr,addr,addr,addr'
--rpc_laddr_ethereum string ethereum url 地址 (默认 "http://localhost:7545")
输出:
tx is written to file: deploytxs.txt
把交易信息写入文件中
```
* 离线签名交易
```
./boss4x ethereum offline sign -k 8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230
参数说明:
-f, --file string 需要签名的文件, 默认:deploytxs.txt (default "deploytxs.txt")
-k, --key string 部署者的私钥
```
* 发送签名后文件
```
./boss4x ethereum offline send -f deploysigntxs.txt
```
***
#### 离线部署 ERC20 跨链合约
* 在线创建交易
```
命令:
./boss4x ethereum offline create_erc20 -m 33000000000000000000 -s YCC -o 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a
参数说明:
-m, --amount string 金额
-d, --deployAddr string 部署者地址
-o, --owner string 拥有者地址
-s, --symbol string erc20 symbol
输出
tx is written to file: deployErc20YCC.txt
把交易信息写入 deployErc20XXX.txt 文件中, 其中 XXX 为 erc20 symbol
```
* 离线签名交易
```
./boss4x ethereum offline sign -f deployErc20YCC.txt -k 8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230
```
* 发送签名后文件
```
./boss4x ethereum offline send -f deploysigntxs.txt
```
***
#### create_add_lock_list
* 在线创建交易
```
命令:
./boss4x ethereum offline create_add_lock_list -s YCC -t 0x20a32A5680EBf55740B0C98B54cDE8e6FD5a4FB0 -c 0xC65B02a22B714b55D708518E2426a22ffB79113d -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a
参数说明:
-c, --contract string bridgebank 合约地址
-d, --deployAddr string 部署者地址
-s, --symbol string token symbol
-t, --token string token addr
输出
tx is written to file: create_add_lock_list.txt
```
***
#### 创建 bridge token
* 在线创建交易
```
命令:
./boss4x ethereum offline create_bridge_token -s BTY -c 0xC65B02a22B714b55D708518E2426a22ffB79113d -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a
参数说明:
-c, --contract string bridgebank 合约地址
-d, --deployAddr string 部署者地址
-s, --symbol string token symbol
输出
tx is written to file: create_bridge_token.txt
```
***
#### 设置离线多签地址信息
* 在线创建交易
```
命令:
./boss4x ethereum offline multisign_setup -m 0xbf271b2B23DA4fA8Dc93Ce86D27dd09796a7Bf54 -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a -o 0x4c85848a7E2985B76f06a7Ed338FCB3aF94a7DCf,0x6F163E6daf0090D897AD7016484f10e0cE844994,0xbc333839E37bc7fAAD0137aBaE2275030555101f,0x495953A743ef169EC5D4aC7b5F786BF2Bd56aFd5
参数说明:
-d, --deployAddr string 部署者地址
-m, --multisign string 离线多签合约地址
-o, --owner string 多签的地址, 用','分隔
输出
tx is written to file: multisign_setup.txt
```
***
#### 设置离线多签地址
* 在线创建交易
```
命令:
./boss4x ethereum offline set_offline_addr -a 0xbf271b2B23DA4fA8Dc93Ce86D27dd09796a7Bf54 -c 0xC65B02a22B714b55D708518E2426a22ffB79113d -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a
参数说明:
-a, --address string 离线多签地址
-c, --contract string bridgebank 合约地址
-d, --deployAddr string 部署合约地址
输出
tx is written to file: set_offline_addr.txt
```
***
#### 离线多签设置
* 在线创建交易
```
命令:
./boss4x ethereum offline set_offline_token -s ETH -m 20 -c 0xC65B02a22B714b55D708518E2426a22ffB79113d -d 0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a
参数说明:
-c, --contract string bridgebank 合约地址
-d, --deployAddr string deploy 部署者地址
-p, --percents uint8 百分比 (默认 50),达到阈值后默认转帐 50% 到离线多签的地址
-s, --symbol string token 标识
-m, --threshold float 阈值
-t, --token string token 地址
输出
tx is written to file: set_offline_token.txt
```
***
#### 离线多签转帐
* 转帐预备交易--在线操作
```
命令:
./boss4x ethereum offline multisign_transfer_prepare -a 3 -r 0xC65B02a22B714b55D708518E2426a22ffB79113d -c 0xbf271b2B23DA4fA8Dc93Ce86D27dd09796a7Bf54 -d 0x0df9a824699bc5878232c9e612fe1a5346a5a368
参数说明:
-a, --amount float 转帐金额
-c, --contract string 离线多签合约地址
-r, --receiver string 接收者地址
-d, --sendAddr string 发送这笔交易的地址, 需要扣除部分手续费
-t, --token string erc20 地址,空的话,默认转帐 ETH
输出
tx is written to file: multisign_transfer_prepare.txt
```
* 离线多签地址签名交易--离线操作
```
命令:
./boss4x ethereum offline sign_multisign_tx -k 0x5e8aadb91eaa0fce4df0bcc8bd1af9e703a1d6db78e7a4ebffd6cf045e053574,0x0504bcb22b21874b85b15f1bfae19ad62fc2ad89caefc5344dc669c57efa60db,0x0c61f5a879d70807686e43eccc1f52987a15230ae0472902834af4d1933674f2,0x2809477ede1261da21270096776ba7dc68b89c9df5f029965eaa5fe7f0b80697
参数说明:
-f, --file string tx file, default: multisign_transfer_prepare.txt (default "multisign_transfer_prepare.txt")
-k, --keys string owners' private key, separated by ','
输出
tx is written to file: sign_multisign_tx.txt
```
* 创建转帐交易--在线操作,需要重新获取 nonce 等信息
```
命令:
./boss4x ethereum offline create_multisign_tx
输出
tx is written to file: create_multisign_tx.txt
```
* 离线签名交易
```
./boss4x ethereum offline sign -f create_multisign_tx.txt -k 8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230
```
* 发送签名后文件
```
./boss4x ethereum offline send -f deploysigntxs.txt
```
package offline
import (
"context"
"encoding/json"
"fmt"
//"github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/contracts4eth/generated"
//erc20 "github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/erc20/generated"
//"github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/utils"
tml "github.com/BurntSushi/toml"
"github.com/ethereum/go-ethereum"
//"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/spf13/cobra"
"io/ioutil"
"math/big"
"os"
//"strings"
//"time"
)
type DeployContractRet struct {
ContractAddr string
TxHash string
ContractName string
}
func DeployOfflineContractsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "offline",
Short: "deploy the corresponding Ethereum contracts",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
CreateCmd(), //构造交易
CreateWithFileCmd(),
DeployERC20Cmd(),
CreateCfgAccountTxCmd(), // set_offline_addr 设置离线多签地址
SetupCmd(),
ConfigLockedTokenOfflineSaveCmd(),
CreateAddToken2LockListTxCmd(),
CreateBridgeTokenTxCmd(),
PrepareCreateMultisignTransferTxCmd(), // 预备创建一个多签转帐交易 在线
PreliminarySignMultisignTransferTxCmd(), // 多签转帐交易 多签多个地址签名 离线
CreateMultisignTransferTxCmd(), // 创建多签转帐交易
SignCmd(), // 签名交易 sign deploy contract tx
SendTxsCmd(), // 发送交易 send all kinds of tx
)
return cmd
}
type DeployInfo struct {
Name string
PackData []byte
ContractorAddr common.Address
Nonce uint64
To *common.Address
RawTx string
TxHash string
Gas uint64
}
type DeployConfigInfo struct {
DeployerPrivateKey string `toml:"deployerPrivateKey"`
ValidatorsAddr []string `toml:"validatorsAddr"`
InitPowers []int64 `toml:"initPowers"`
}
func CreateTxInfoAndWrite(abiData []byte, deployAddr, contract, name, url string) {
client, err := ethclient.Dial(url)
if err != nil {
fmt.Println("Dial Err:", err)
return
}
gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {
fmt.Println("SuggestGasPrice Err:", err)
return
}
nonce, err := client.NonceAt(context.Background(), common.HexToAddress(deployAddr), nil)
if err != nil {
fmt.Println("NonceAt Err:", err)
return
}
contracAddr := common.HexToAddress(contract)
var msg ethereum.CallMsg
msg.Data = abiData
msg.From = common.HexToAddress(deployAddr)
msg.To = &contracAddr
msg.Value = big.NewInt(0)
//估算gas
gasLimit, err := client.EstimateGas(context.Background(), msg)
if err != nil {
fmt.Println("EstimateGas Err:", err)
return
}
if gasLimit < 100*10000 {
gasLimit = 100 * 10000
}
ntx := types.NewTx(&types.LegacyTx{
Nonce: nonce,
Gas: gasLimit,
GasPrice: gasPrice,
Data: abiData,
To: &contracAddr,
})
txBytes, err := ntx.MarshalBinary()
if err != nil {
fmt.Println("MarshalBinary Err:", err)
return
}
var info DeployInfo
info.RawTx = common.Bytes2Hex(txBytes)
info.ContractorAddr = crypto.CreateAddress(contracAddr, nonce)
info.PackData = abiData
info.Nonce = nonce
info.Gas = gasLimit
info.Name = name
var infos []*DeployInfo
infos = append(infos, &info)
writeToFile(info.Name+".txt", infos)
}
func paraseFile(file string, result interface{}) error {
_, err := os.Stat(file)
if err != nil {
fmt.Println(err.Error())
return err
}
f, err := os.Open(file)
if err != nil {
panic(err)
}
b, err := ioutil.ReadAll(f)
if err != nil {
panic(err)
}
return json.Unmarshal(b, result)
}
func writeToFile(fileName string, content interface{}) {
jbytes, err := json.MarshalIndent(content, "", "\t")
if err != nil {
panic(err)
}
err = ioutil.WriteFile(fileName, jbytes, 0666)
if err != nil {
fmt.Println("Failed to write to file:", fileName)
}
fmt.Println("tx is written to file: ", fileName)
}
func InitCfg(filepath string, cfg interface{}) {
if _, err := tml.DecodeFile(filepath, cfg); err != nil {
fmt.Println(err)
os.Exit(-1)
}
return
}
package offline
import (
"context"
"errors"
"fmt"
"github.com/ethereum/go-ethereum"
"math/big"
"strings"
erc20 "github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/erc20/generated"
gnosis "github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/gnosis/generated"
ebTypes "github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/types"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/spf13/cobra"
)
type safeTxData struct {
Content []byte //json.RawMessage
To common.Address
Value *big.Int
TransferData []byte //json.RawMessage
GasLimit int64
GasPrice *big.Int
Nonce uint64
TxNonce uint64
CrontractAddr string
SendAddr string
name string
}
/*
./boss4x ethereum offline multisign_transfer_prepare -a 3 -r 0xC65B02a22B714b55D708518E2426a22ffB79113d -c 0xbf271b2B23DA4fA8Dc93Ce86D27dd09796a7Bf54 -d 0xd9dab021e74ecf475788ed7b61356056b2095830
./boss4x ethereum offline sign_multisign_tx -k 0x5e8aadb91eaa0fce4df0bcc8bd1af9e703a1d6db78e7a4ebffd6cf045e053574,0x0504bcb22b21874b85b15f1bfae19ad62fc2ad89caefc5344dc669c57efa60db,0x0c61f5a879d70807686e43eccc1f52987a15230ae0472902834af4d1933674f2,0x2809477ede1261da21270096776ba7dc68b89c9df5f029965eaa5fe7f0b80697
./boss4x ethereum offline create_multisign_tx
./boss4x ethereum offline sign -f create_multisign_tx.txt -k c9fa31d7984edf81b8ef3b40c761f1847f6fcd5711ab2462da97dc458f1f896b
./boss4x ethereum offline send -f deploysigntxs.txt
*/
// PrepareCreateMultisignTransferTxCmd 预备创建一个多签转帐交易 在线
func PrepareCreateMultisignTransferTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "multisign_transfer_prepare", //first step
Short: "prepare create multisign transfer tx",
Run: prepareCreateMultisignTransferTx,
}
addPrepareCreateMultisignTransferTxFlags(cmd)
return cmd
}
func addPrepareCreateMultisignTransferTxFlags(cmd *cobra.Command) {
cmd.Flags().StringP("sendAddr", "d", "", "send addr")
_ = cmd.MarkFlagRequired("sendAddr")
cmd.Flags().StringP("contract", "c", "", "mulSignAddr contract address")
_ = cmd.MarkFlagRequired("contract")
cmd.Flags().StringP("receiver", "r", "", "receive address")
_ = cmd.MarkFlagRequired("receiver")
cmd.Flags().Float64P("amount", "a", 0, "amount to transfer")
_ = cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("token", "t", "", "erc20 address,not need to set for ETH(optional)")
}
func prepareCreateMultisignTransferTx(cmd *cobra.Command, _ []string) {
url, _ := cmd.Flags().GetString("rpc_laddr_ethereum")
receiver, _ := cmd.Flags().GetString("receiver")
tokenAddr, _ := cmd.Flags().GetString("token")
amount, _ := cmd.Flags().GetFloat64("amount")
sendAddr, _ := cmd.Flags().GetString("sendAddr")
multiSignAddrstr, _ := cmd.Flags().GetString("contract")
client, err := ethclient.Dial(url)
if err != nil {
fmt.Println("Dial Err:", err)
return
}
gnosisSafeAddr := common.HexToAddress(multiSignAddrstr)
gnosisSafeInt, err := gnosis.NewGnosisSafe(gnosisSafeAddr, client)
if nil != err {
fmt.Println("NewGnosisSafe Err:", err)
return
}
AddressZero := common.HexToAddress(ebTypes.EthNilAddr)
toAddr := common.HexToAddress(receiver)
sendData := []byte{'0', 'x'}
baseGas := big.NewInt(0)
value := big.NewInt(0)
safeTxGas := big.NewInt(10 * 10000)
opts := &bind.CallOpts{
From: common.HexToAddress(sendAddr),
Context: context.Background(),
}
txNonce, err := client.NonceAt(context.Background(), common.HexToAddress(sendAddr), nil)
if err != nil {
fmt.Println("NonceAt Err:", err)
return
}
gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {
fmt.Println("SuggestGasPrice Err:", err)
return
}
if tokenAddr == "" {
value.Mul(big.NewInt(int64(amount)), big.NewInt(int64(1e18)))
} else {
toAddr = common.HexToAddress(tokenAddr)
erc20Abi, err := abi.JSON(strings.NewReader(erc20.ERC20ABI))
if err != nil {
fmt.Println("strings.NewReader(erc20.ERC20ABI) Err:", err)
return
}
tokenInstance, err := erc20.NewERC20(toAddr, client)
if err != nil {
fmt.Println("NewERC20 Err:", err)
return
}
decimals, err := tokenInstance.Decimals(opts)
if err != nil {
fmt.Println("Decimals Err:", err)
return
}
dec, ok := ebTypes.DecimalsPrefix[decimals]
if !ok {
fmt.Println("dec Err:")
return
}
value.Mul(big.NewInt(int64(amount)), big.NewInt(dec))
sendData, err = erc20Abi.Pack("transfer", common.HexToAddress(receiver), value)
if err != nil {
fmt.Println("Pack Err:", err)
return
}
//对于erc20这种方式 最后需要将其设置为0
value = big.NewInt(0)
}
contracAddr := common.HexToAddress(multiSignAddrstr)
var msg ethereum.CallMsg
msg.Data = sendData
msg.From = common.HexToAddress(sendAddr)
msg.To = &contracAddr
msg.Value = big.NewInt(0)
//估算gas
gasLimit, err := client.EstimateGas(context.Background(), msg)
if err != nil {
fmt.Println("EstimateGas Err:", err)
return
}
if gasLimit < 100*10000 {
gasLimit = 100 * 10000
}
nonce, err := gnosisSafeInt.Nonce(opts)
if err != nil {
fmt.Println("NewGnosisSafe Err:", err)
return
}
signContent, err := gnosisSafeInt.GetTransactionHash(opts, toAddr, value, sendData, 0,
safeTxGas, baseGas, gasPrice, AddressZero, AddressZero, nonce)
if err != nil {
fmt.Println("GetTransactionHash Err:", err)
return
}
var txdata safeTxData
txdata.Content = signContent[:]
txdata.TransferData = sendData
txdata.GasLimit = int64(gasLimit)
txdata.GasPrice = gasPrice
txdata.To = toAddr
txdata.CrontractAddr = multiSignAddrstr
txdata.SendAddr = sendAddr
txdata.Value = value
txdata.TxNonce = txNonce
txdata.name = "multisign_transfer_prepare"
writeToFile(txdata.name+".txt", txdata)
}
// PreliminarySignMultisignTransferTxCmd 多签转帐交易 多签多个地址签名 离线
func PreliminarySignMultisignTransferTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "sign_multisign_tx", //first step
Short: "sign multisign tx",
Run: preliminarySignMultisignTransferTx,
}
addPreliminarySignMultisignTransferTxFlag(cmd)
return cmd
}
func addPreliminarySignMultisignTransferTxFlag(cmd *cobra.Command) {
cmd.Flags().StringP("file", "f", "multisign_transfer_prepare.txt", "tx file, default: multisign_transfer_prepare.txt")
cmd.Flags().StringP("keys", "k", "", "owners' private key, separated by ','")
_ = cmd.MarkFlagRequired("keys")
}
//签名交易
func preliminarySignMultisignTransferTx(cmd *cobra.Command, _ []string) {
txFilePath, _ := cmd.Flags().GetString("file")
keys, _ := cmd.Flags().GetString("keys")
privateKeys := strings.Split(keys, ",")
var txinfo safeTxData
err := paraseFile(txFilePath, &txinfo)
if err != nil {
fmt.Println("paraseFile Err:", err)
return
}
sigs, err := buildSigs(txinfo.Content, privateKeys)
if err != nil {
fmt.Println("buildSigs Err:", err)
return
}
txinfo.Content = sigs
writeToFile("sign_multisign_tx.txt", txinfo)
}
// CreateMultisignTransferTxCmd 创建多签转帐交易
func CreateMultisignTransferTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create_multisign_tx",
Short: "create multisign transfer tx",
Run: CreateMultisignTransferTx,
}
addCreateMultisignTransferTxFlags(cmd)
return cmd
}
func addCreateMultisignTransferTxFlags(cmd *cobra.Command) {
cmd.Flags().StringP("file", "f", "sign_multisign_tx.txt", "tx file, default: sign_multisign_tx.txt")
}
func CreateMultisignTransferTx(cmd *cobra.Command, _ []string) {
url, _ := cmd.Flags().GetString("rpc_laddr_ethereum")
txFilePath, _ := cmd.Flags().GetString("file")
client, err := ethclient.Dial(url)
if err != nil {
fmt.Println("Dial Err:", err)
return
}
var txinfo safeTxData
err = paraseFile(txFilePath, &txinfo)
if err != nil {
fmt.Println("paraseFile Err:", err)
return
}
gasPrice, err := client.SuggestGasPrice(context.Background())
if err != nil {
fmt.Println("SuggestGasPrice Err:", err)
return
}
gnoAbi, err := abi.JSON(strings.NewReader(gnosis.GnosisSafeABI))
if err != nil {
fmt.Println("JSON Err:", err)
return
}
zeroAddr := common.HexToAddress(ebTypes.EthNilAddr)
safeTxGas := big.NewInt(10 * 10000)
gnoData, err := gnoAbi.Pack("execTransaction", txinfo.To, txinfo.Value, txinfo.TransferData, uint8(0),
safeTxGas, big.NewInt(0), gasPrice, zeroAddr, zeroAddr, txinfo.Content)
if err != nil {
fmt.Println("Pack execTransaction Err:", err)
return
}
CreateTxInfoAndWrite(gnoData, txinfo.SendAddr, txinfo.CrontractAddr, "create_multisign_tx", url)
}
func buildSigs(data []byte, privateKeys []string) ([]byte, error) {
var sigs []byte
for _, privateKeyStr := range privateKeys {
privateKey, err := crypto.ToECDSA(common.FromHex(privateKeyStr))
if nil != err {
return nil, errors.New("paraseKey err:" + err.Error())
}
signature, err := crypto.Sign(data, privateKey)
if err != nil {
return nil, err
}
signature[64] += 27
sigs = append(sigs, signature[:]...)
}
return sigs, nil
}
package offline
import (
"context"
"encoding/json"
"fmt"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/spf13/cobra"
"os"
"time"
)
func SendTxsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "send", //first step
Short: "send signed raw tx",
Run: sendTxs,
}
sendTxsFlags(cmd)
return cmd
}
func sendTxsFlags(cmd *cobra.Command) {
cmd.Flags().StringP("file", "f", "", "signed tx file")
_ = cmd.MarkFlagRequired("file")
}
func sendTxs(cmd *cobra.Command, _ []string) {
url, _ := cmd.Flags().GetString("rpc_laddr_ethereum")
filePath, _ := cmd.Flags().GetString("file")
//解析文件数据
var rdata = make([]*DeployInfo, 0)
err := paraseFile(filePath, &rdata)
if err != nil {
fmt.Println("paraseFile,err", err.Error())
return
}
var respData = make([]*DeployContractRet, 0)
for _, deployInfo := range rdata {
tx := new(types.Transaction)
err = tx.UnmarshalBinary(common.FromHex(deployInfo.RawTx))
if err != nil {
panic(err)
}
client, err := ethclient.Dial(url)
if err != nil {
panic(err)
}
err = client.SendTransaction(context.Background(), tx)
if err != nil {
fmt.Println("err:", err)
panic(err)
}
ret := &DeployContractRet{ContractAddr: deployInfo.ContractorAddr.String(), TxHash: tx.Hash().String(), ContractName: deployInfo.Name}
respData = append(respData, ret)
if !checkTxStatus(client, tx.Hash().String(), deployInfo.Name) {
fmt.Println("FATAL ERROR! DEPLOY CONTRACTOR TERMINATION……:-(")
break
}
}
data, err := json.MarshalIndent(respData, "", "\t")
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
return
}
fmt.Println(string(data))
}
func checkTxStatus(client *ethclient.Client, txhash, txName string) bool {
var checkticket = time.NewTicker(time.Second * 3)
var timeout = time.NewTicker(time.Second * 300)
for {
select {
case <-timeout.C:
panic("Deploy timeout")
case <-checkticket.C:
receipt, err := client.TransactionReceipt(context.Background(), common.HexToHash(txhash))
if err == ethereum.NotFound {
fmt.Println("\n No receipt received yet for "+txName, " tx and continue to wait")
continue
} else if err != nil {
panic("failed due to" + err.Error())
}
if receipt.Status == types.ReceiptStatusSuccessful {
return true
}
if receipt.Status == types.ReceiptStatusFailed {
fmt.Println("tx status:", types.ReceiptStatusFailed)
return false
}
}
}
}
package offline
import (
"fmt"
eoff "github.com/33cn/plugin/plugin/dapp/dex/boss/deploy/ethereum/offline"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/spf13/cobra"
)
func SignCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "sign", //first step
Short: "sign tx",
Run: signTx,
}
addSignFlag(cmd)
return cmd
}
func addSignFlag(cmd *cobra.Command) {
cmd.Flags().StringP("key", "k", "", "private key ")
_ = cmd.MarkFlagRequired("key")
cmd.Flags().StringP("file", "f", "deploytxs.txt", "tx file, default:deploytxs.txt")
}
func signTx(cmd *cobra.Command, _ []string) {
privatekey, _ := cmd.Flags().GetString("key")
txFilePath, _ := cmd.Flags().GetString("file")
deployPrivateKey, err := crypto.ToECDSA(common.FromHex(privatekey))
if err != nil {
panic(err)
}
var deployTxInfos = make([]DeployInfo, 0)
err = paraseFile(txFilePath, &deployTxInfos)
if err != nil {
fmt.Println("paraseFile,err", err.Error())
return
}
fmt.Println("deployTxInfos size:", len(deployTxInfos))
for i, info := range deployTxInfos {
var tx types.Transaction
err = tx.UnmarshalBinary(common.FromHex(info.RawTx))
if err != nil {
panic(err)
}
signedTx, txHash, err := eoff.SignTx(deployPrivateKey, &tx)
if err != nil {
panic(err)
}
deployTxInfos[i].RawTx = signedTx
deployTxInfos[i].TxHash = txHash
}
//finsh write to file
writeToFile("deploysigntxs.txt", deployTxInfos)
}
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
#!/usr/bin/env bash
# 官方ci集成脚本
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
SRC_EBCLI=github.com/33cn/plugin/plugin/dapp/cross2eth/ebcli
SRC_EBRELAYER=github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer
SRC_BOSS4XCLI=github.com/33cn/plugin/plugin/dapp/cross2eth/boss4x
OUT_DIR="${1}/$strapp"
FLAG=$2
# shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/ebrelayer" "${SRC_EBRELAYER}"
# shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/ebcli_A" "${SRC_EBCLI}"
# shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/ebcli_B" -ldflags "-X ${SRC_EBCLI}/buildflags.RPCAddr=http://localhost:9902" "${SRC_EBCLI}"
# shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/ebcli_C" -ldflags "-X ${SRC_EBCLI}/buildflags.RPCAddr=http://localhost:9903" "${SRC_EBCLI}"
# shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/ebcli_D" -ldflags "-X ${SRC_EBCLI}/buildflags.RPCAddr=http://localhost:9904" "${SRC_EBCLI}"
# shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/boss4x" "${SRC_BOSS4XCLI}"
cp ../ebrelayer/relayer.toml "${OUT_DIR}/relayer.toml"
cp ./build/* "${OUT_DIR}"
cp ./build/abi/* "${OUT_DIR}"
cp ./build/public/* "${OUT_DIR}"
OUT_TESTDIR="${1}/dapptest/$strapp"
mkdir -p "${OUT_TESTDIR}"
cp ./test/* "${OUT_TESTDIR}"
FROM ubuntu:16.04
WORKDIR /root
COPY chain33 chain33
COPY chain33-cli chain33-cli
COPY chain33.toml chain33*.toml ./
COPY entrypoint.sh entrypoint.sh
CMD ["/root/chain33", "-f", "/root/chain33.toml"]
FROM ubuntu:16.04
WORKDIR /root
COPY ebrelayer ebrelayer
COPY ebcli_A ebcli_A
COPY boss4x boss4x
COPY sleep.sh sleep.sh
CMD ["/root/sleep.sh"]
[{"inputs":[{"internalType":"address","name":"_ethereumBridge","type":"address"},{"internalType":"address","name":"_bridgeBank","type":"address"},{"internalType":"address","name":"_oracle","type":"address"},{"internalType":"address","name":"_valset","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_ethereumBridge","type":"address"},{"indexed":false,"internalType":"address","name":"_bridgeBank","type":"address"},{"indexed":false,"internalType":"address","name":"_oracle","type":"address"},{"indexed":false,"internalType":"address","name":"_valset","type":"address"}],"name":"LogContractsRegistered","type":"event"},{"constant":true,"inputs":[],"name":"bridgeBank","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"deployHeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ethereumBridge","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oracle","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"valset","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]
\ No newline at end of file
[{"inputs":[{"internalType":"string","name":"_symbol","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
[{"inputs":[{"internalType":"address","name":"_operatorAddress","type":"address"},{"internalType":"address","name":"_oracleAddress","type":"address"},{"internalType":"address","name":"_ethereumBridgeAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_beneficiary","type":"address"}],"name":"LogBridgeTokenMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_ownerFrom","type":"address"},{"indexed":false,"internalType":"bytes","name":"_ethereumReceiver","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"LogEthereumTokenBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"bytes","name":"_to","type":"bytes"},{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"LogLock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"}],"name":"LogNewBridgeToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"LogUnlock","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"string","name":"_symbol","type":"string"}],"name":"addToken2LockList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"bridgeTokenCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeTokenCreated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bridgeTokenWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"_ethereumReceiver","type":"bytes"},{"internalType":"address","name":"_ethereumTokenAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burnBridgeTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_threshold","type":"uint256"},{"internalType":"uint8","name":"_percents","type":"uint8"}],"name":"configLockedTokenOfflineSave","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"addresspayable","name":"_offlineSave","type":"address"}],"name":"configOfflineSaveAccount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"_symbol","type":"string"}],"name":"createNewBridgeToken","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ethereumBridge","outputs":[{"internalType":"contractEthereumBridge","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_id","type":"bytes32"}],"name":"getEthereumDepositStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"string","name":"_symbol","type":"string"}],"name":"getLockedTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"string","name":"_symbol","type":"string"}],"name":"getToken2address","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getofflineSaveCfg","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"string","name":"_symbol","type":"string"}],"name":"hasBridgeTokenCreated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"highThreshold","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"_recipient","type":"bytes"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"lock","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"lockNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lockedFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lowThreshold","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"_ethereumSender","type":"bytes"},{"internalType":"addresspayable","name":"_intendedRecipient","type":"address"},{"internalType":"address","name":"_bridgeTokenAddress","type":"address"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintBridgeTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"offlineSave","outputs":[{"internalType":"addresspayable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"offlineSaveCfgs","outputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"_threshold","type":"uint256"},{"internalType":"uint8","name":"_percents","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"operator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oracle","outputs":[{"internalType":"contractOracle","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"token2address","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"tokenAllow2Lock","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"addresspayable","name":"_recipient","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_id","type":"bytes32"}],"name":"viewEthereumDeposit","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"addresspayable","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
\ No newline at end of file
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint256","name":"supply","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
\ No newline at end of file
[{"inputs":[{"internalType":"address","name":"_operatorAddress","type":"address"},{"internalType":"address","name":"_oracleAddress","type":"address"},{"internalType":"address","name":"_chain33BridgeAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_beneficiary","type":"address"}],"name":"LogBridgeTokenMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_ownerFrom","type":"address"},{"indexed":false,"internalType":"bytes","name":"_chain33Receiver","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"LogChain33TokenBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_from","type":"address"},{"indexed":false,"internalType":"bytes","name":"_to","type":"bytes"},{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"LogLock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"}],"name":"LogNewBridgeToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"string","name":"_symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"LogUnlock","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"string","name":"_symbol","type":"string"}],"name":"addToken2LockList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"bridgeTokenCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"bridgeTokenCreated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"bridgeTokenWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"_chain33Receiver","type":"bytes"},{"internalType":"address","name":"_chain33TokenAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burnBridgeTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"chain33Bridge","outputs":[{"internalType":"contractChain33Bridge","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_threshold","type":"uint256"},{"internalType":"uint8","name":"_percents","type":"uint8"}],"name":"configLockedTokenOfflineSave","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"addresspayable","name":"_offlineSave","type":"address"}],"name":"configOfflineSaveAccount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"_symbol","type":"string"}],"name":"createNewBridgeToken","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_id","type":"bytes32"}],"name":"getChain33DepositStatus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"string","name":"_symbol","type":"string"}],"name":"getLockedTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"string","name":"_symbol","type":"string"}],"name":"getToken2address","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"string","name":"_symbol","type":"string"}],"name":"getToken2addressV2","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getofflineSaveCfg","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"string","name":"_symbol","type":"string"}],"name":"hasBridgeTokenCreated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"highThreshold","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"_recipient","type":"bytes"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"lock","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"lockNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lockedFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lowThreshold","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"_chain33Sender","type":"bytes"},{"internalType":"addresspayable","name":"_intendedRecipient","type":"address"},{"internalType":"address","name":"_bridgeTokenAddress","type":"address"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintBridgeTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"offlineSave","outputs":[{"internalType":"addresspayable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"offlineSaveCfgs","outputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"_threshold","type":"uint256"},{"internalType":"uint8","name":"_percents","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"operator","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oracle","outputs":[{"internalType":"contractOracle","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"token2address","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"tokenAllow2Lock","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"addresspayable","name":"_recipient","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"_id","type":"bytes32"}],"name":"viewChain33Deposit","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"addresspayable","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]
\ No newline at end of file
Title="user.p.para."
TestNet=false
CoinSymbol="para"
EnableParaFork=true
ChainID=0
[crypto]
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
loglevel = "debug"
logConsoleLevel = "info"
# 日志文件名,可带目录,所有生成的日志文件都放到此目录下
logFile = "logs/chain33.para.log"
# 单个日志文件的最大值(单位:兆)
maxFileSize = 300
# 最多保存的历史日志文件个数
maxBackups = 100
# 最多保存的历史日志消息(单位:天)
maxAge = 28
# 日志文件名是否使用本地事件(否则使用UTC时间)
localTime = true
# 历史日志文件是否压缩(压缩格式为gz)
compress = true
# 是否打印调用源文件和行号
callerFile = false
# 是否打印调用方法
callerFunction = false
[blockchain]
defCacheSize=128
maxFetchBlockNum=128
timeoutSeconds=5
batchBlockNum=128
driver="leveldb"
dbPath="paradatadir"
dbCache=64
isStrongConsistency=true
singleMode=true
batchsync=false
#平行链钱包通过平行链区块seqence索引高度,缺省是true
isRecordBlockSequence=true
isParaChain = true
enableTxQuickIndex=true
# 升级storedb是否重新执行localdb,bityuan主链升级不需要开启,平行链升级需要开启
enableReExecLocal=true
# 使能精简localdb
enableReduceLocaldb=false
enablePushSubscribe=true
[p2p]
types=["dht"]
enable=false
driver="leveldb"
dbPath="paradatadir/addrbook"
dbCache=4
grpcLogFile="grpc33.log"
waitPid=true
[p2p.sub.dht]
DHTDataPath="paradatadir/p2pstore"
[rpc]
# 避免与主链配置冲突
jrpcBindAddr="localhost:8901"
grpcBindAddr="localhost:8902"
whitelist=["127.0.0.1"]
jrpcFuncWhitelist=["*"]
grpcFuncWhitelist=["*"]
[mempool]
name="para"
poolCacheSize=10240
minTxFeeRate=100000
maxTxNumPerAccount=10000
[consensus]
name="para"
genesisBlockTime=1514533390
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
minerExecs=["paracross"] #配置挖矿合约
[mver.consensus]
fundKeyAddr = "1BQXS6TxaYYG5mADaWij4AxhZZUTpw95a5"
powLimitBits = "0x1f00ffff"
maxTxNumber = 1600
[mver.consensus.paracross]
#超级节点挖矿奖励
coinReward=18
#发展基金奖励
coinDevFund=12
#如果超级节点上绑定了委托账户,则奖励超级节点coinBaseReward,其余部分(coinReward-coinBaseReward)按权重分给委托账户
coinBaseReward=3
#委托账户最少解绑定时间(按小时)
unBindTime=24
#支持挖矿奖励的1e8小数模式,比如18coin 需要配置成1800000000 以支持小数位后的配置,如果true,意味着已经打开即coinReward=1800000000
decimalMode=false
#挖矿模式, normal:缺省挖矿,其他自定义,注册名字需要和配置名字保持一致
minerMode="normal"
#挖矿减半周期,按高度减半
halvePeriod=1000
[consensus.sub.para]
#主链节点的grpc服务器ip,当前可以支持多ip负载均衡,如“118.31.177.1:8802,39.97.2.127:8802”
#ParaRemoteGrpcClient="118.31.177.1:8802,39.97.2.127:8802,120.77.111.44:8802,jiedian2.bityuan.com,cloud.bityuan.com"
ParaRemoteGrpcClient="localhost:8802"
#主链指定高度的区块开始同步
startHeight=345850
#打包时间间隔,单位秒
writeBlockSeconds=2
#验证账户,验证节点需要配置自己的账户,并且钱包导入对应种子,非验证节点留空
authAccount=""
#创世地址额度
genesisAmount=100000000
#主链计算blockhash forkheight,需要和主链保持严格一致,不可修改,209186是bityuan主链对应高度, ycc或其他按实际修改
mainBlockHashForkHeight=209186
#主链支持平行链共识tx分叉高度,需要和主链保持严格一致,不可修改,2270000是bityuan主链对应高度, ycc或其他按实际修改
mainForkParacrossCommitTx=2270000
#主链开启循环检查共识交易done的fork高度,需要和主链保持严格一致,不可修改,4320000是bityuan主链对应高度, ycc或其他按实际修改
mainLoopCheckCommitTxDoneForkHeight=4320000
#无平行链交易的主链区块间隔,平行链产生一个空块,从高度0开始,配置[blockHeight:interval],比如["0:50","1000:100"]
emptyBlockInterval=["0:50"]
[store]
name="kvmvccmavl"
driver="leveldb"
storedbVersion="2.0.0"
dbPath="paradatadir/mavltree"
dbCache=128
[store.sub.mavl]
enableMavlPrefix=false
enableMVCC=false
enableMavlPrune=false
pruneHeight=10000
# 是否使能mavl数据载入内存
enableMemTree=true
# 是否使能mavl叶子节点数据载入内存
enableMemVal=true
# 缓存close ticket数目,该缓存越大同步速度越快,最大设置到1500000
tkCloseCacheLen=100000
[store.sub.kvmvccmavl]
enableMVCCIter=true
enableMavlPrefix=false
enableMVCC=false
enableMavlPrune=false
pruneMavlHeight=10000
enableMVCCPrune=false
pruneMVCCHeight=10000
# 是否使能mavl数据载入内存
enableMemTree=true
# 是否使能mavl叶子节点数据载入内存
enableMemVal=true
# 缓存close ticket数目,该缓存越大同步速度越快,最大设置到1500000
tkCloseCacheLen=100000
# 该参数针对平行链,如果平行链的ForkKvmvccmavl高度不为0,需要开启此功能,开启此功能需要从0开始执行区块
enableEmptyBlockHandle=false
[wallet]
minFee=100000
driver="leveldb"
dbPath="parawallet"
dbCache=16
signType="secp256k1"
minerdisable=true
[exec]
enableStat=false
enableMVCC=false
[exec.sub.relay]
genesis="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
[exec.sub.manage]
superManager=["12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"]
[exec.sub.token]
saveTokenTxList=true
tokenApprs=[]
[exec.sub.paracross]
#平行链自共识停止n个空块的对应主链高度后,超级账户可以直接参与投票,这个高度只在主链有效
paraConsensusStopBlocks=30000
[exec.sub.autonomy]
total="16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp"
useBalance=false
[exec.sub.evm]
#平行链evm合约ETH资产映射的合约和资产类型(symbol)
ethMapFromExecutor="paracross"
ethMapFromSymbol="coins.bty"
#系统中所有的fork,默认用chain33的测试网络的
#但是我们可以替换
[fork.system]
ForkChainParamV1= 0
ForkCheckTxDup=0
ForkBlockHash= 1
ForkMinerTime= 0
ForkTransferExec=0
ForkExecKey=0
ForkTxGroup=0
ForkResetTx0=0
ForkWithdraw=0
ForkExecRollback=0
ForkCheckBlockTime=0
ForkTxHeight=0
ForkTxGroupPara=0
ForkChainParamV2=0
ForkMultiSignAddress=0
ForkStateDBSet=0
ForkLocalDBAccess=0
ForkBlockCheck=0
ForkBase58AddressCheck=0
#平行链上使能平行链执行器如user.p.x.coins执行器的注册,缺省为0,对已有的平行链需要设置一个fork高度
ForkEnableParaRegExec=0
ForkCacheDriver=0
ForkTicketFundAddrV1=-1 #fork6.3
#主链和平行链都使用同一个fork高度
ForkRootHash=7200000
[fork.sub.coins]
Enable=0
[fork.sub.coinsx]
Enable=0
[fork.sub.ticket]
Enable=0
ForkTicketId =0
ForkTicketVrf =0
[fork.sub.retrieve]
Enable=0
ForkRetrive=0
ForkRetriveAsset=0
[fork.sub.hashlock]
Enable=0
ForkBadRepeatSecret=0
[fork.sub.manage]
Enable=0
ForkManageExec=0
[fork.sub.token]
Enable=0
ForkTokenBlackList= 0
ForkBadTokenSymbol= 0
ForkTokenPrice=0
ForkTokenSymbolWithNumber=0
ForkTokenCheck= 0
[fork.sub.trade]
Enable=0
ForkTradeBuyLimit= 0
ForkTradeAsset= 0
ForkTradeID = 0
ForkTradeFixAssetDB = 0
ForkTradePrice = 0
[fork.sub.paracross]
Enable=0
ForkParacrossWithdrawFromParachain=0
ForkParacrossCommitTx=0
ForkLoopCheckCommitTxDone=0
#仅平行链适用,自共识分阶段开启,缺省是0,若对应主链高度7200000之前开启过自共识,需要重新配置此分叉,并为之前自共识设置selfConsensEnablePreContract配置项
ForkParaSelfConsStages=0
ForkParaAssetTransferRbk=0
#仅平行链适用,开启挖矿交易的高度,已有代码版本可能未在0高度开启挖矿,需要设置这个高度,新版本默认从0开启挖矿,通过交易配置分阶段奖励
ForkParaFullMinerHeight=0
[fork.sub.evm]
Enable=0
ForkEVMState=0
ForkEVMABI=0
ForkEVMFrozen=0
ForkEVMKVHash=0
ForkEVMYoloV1=0
ForkEVMTxGroup=0
[fork.sub.blackwhite]
Enable=0
ForkBlackWhiteV2=0
[fork.sub.cert]
Enable=0
[fork.sub.guess]
Enable=0
[fork.sub.lottery]
Enable=0
[fork.sub.oracle]
Enable=0
[fork.sub.relay]
Enable=0
[fork.sub.norm]
Enable=0
[fork.sub.pokerbull]
Enable=0
[fork.sub.privacy]
Enable=0
[fork.sub.game]
Enable=0
[fork.sub.vote]
Enable=0
[fork.sub.accountmanager]
Enable=0
[fork.sub.exchange]
Enable=0
[fork.sub.wasm]
Enable=0
[fork.sub.valnode]
Enable=0
[fork.sub.dpos]
Enable=0
[fork.sub.echo]
Enable=0
[fork.sub.storage]
Enable=0
ForkStorageLocalDB=0
[fork.sub.qbftNode]
Enable=0
[fork.sub.multisig]
Enable=0
[fork.sub.unfreeze]
Enable=0
ForkTerminatePart=0
ForkUnfreezeIDX= 0
[fork.sub.autonomy]
Enable=0
[fork.sub.jsvm]
Enable=0
[fork.sub.issuance]
Enable=0
ForkIssuanceTableUpdate=0
[fork.sub.collateralize]
Enable=0
ForkCollateralizeTableUpdate=0
#对已有的平行链如果不是从0开始同步数据,需要设置这个kvmvccmavl的对应平行链高度的fork,如果从0开始同步,statehash会跟以前mavl的不同
[fork.sub.store-kvmvccmavl]
ForkKvmvccmavl=0
[pprof]
listenAddr = "localhost:6061"
[metrics]
#是否使能发送metrics数据的发送
enableMetrics=false
#数据保存模式
dataEmitMode="influxdb"
[metrics.sub.influxdb]
#以纳秒为单位的发送间隔
duration=1000000000
url="http://influxdb:8086"
database="chain33metrics"
username=""
password=""
namespace=""
version: '3'
services:
ganachetest:
entrypoint: ["node", "/app/ganache-core.docker.cli.js", "-a", "20", "-b", "2", "--debug", "-m", "coast bar giraffe art venue decide symbol law visual crater vital fold"]
image: trufflesuite/ganache-cli:latest
ports:
- 8545:8545
ebrelayera:
build:
context: .
dockerfile: Dockerfile-cross2eth
ebrelayerb:
build:
context: .
dockerfile: Dockerfile-cross2eth
ebrelayerc:
build:
context: .
dockerfile: Dockerfile-cross2eth
ebrelayerd:
build:
context: .
dockerfile: Dockerfile-cross2eth
chain33:
entrypoint: /root/entrypoint.sh
environment:
PARAFILE: "/root/chain33.para33.toml"
ports:
- 8801:8801
- 8901:8901
expose:
- "8802"
chain32:
entrypoint: /root/entrypoint.sh
environment:
PARAFILE: "/root/chain33.para32.toml"
chain31:
entrypoint: /root/entrypoint.sh
environment:
PARAFILE: "/root/chain33.para31.toml"
chain30:
entrypoint: /root/entrypoint.sh
environment:
PARAFILE: "/root/chain33.para30.toml"
expose:
- "8802"
chain29:
entrypoint: /root/entrypoint.sh
environment:
PARAFILE: "/root/chain33.para29.toml"
nginx:
image: nginx:latest
depends_on:
- chain33
- chain30
- chain29
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
expose:
- "8803"
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
#!/usr/bin/env bash
/root/chain33 -f /root/chain33.toml &
# to wait nginx start
sleep 15
/root/chain33 -f "$PARAFILE"
This diff is collapsed.
This diff is collapsed.
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -x
set +e
source "./publicTest.sh"
source "./relayerPublic.sh"
# ETH 部署合约者的私钥 用于部署合约时签名使用
#ethDeployAddr="0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a"
ethDeployKey="8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
ethSendAddress=0x495953A743ef169EC5D4aC7b5F786BF2Bd56aFd5
ethSendPrivateKeys=0x2809477ede1261da21270096776ba7dc68b89c9df5f029965eaa5fe7f0b80697
# validatorsAddr=["0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a", "0x0df9a824699bc5878232c9e612fe1a5346a5a368", "0xcb074cb21cdddf3ce9c3c0a7ac4497d633c9d9f1", "0xd9dab021e74ecf475788ed7b61356056b2095830"]
#ethValidatorAddrKeyA="8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
# chain33 部署合约者的私钥 用于部署合约时签名使用
chain33DeployAddr="1N6HstkyLFS8QCeVfdvYxx1xoryXoJtvvZ"
#chain33DeployKey="0xcc38546e9e659d15e6b4893f0ab32a06d103931a8230b0bde71459d2b27d6944"
chain33ReceiverAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
chain33ReceiverAddrKey="4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01"
#maturityDegree=10
Chain33Cli="../../chain33-cli"
chain33BridgeBank=""
#ethBridgeBank=""
chain33BtyTokenAddr="1111111111111111111114oLvT2"
chain33EthTokenAddr=""
ethereumBtyTokenAddr=""
chain33YccTokenAddr=""
ethereumYccTokenAddr=""
CLIA="./ebcli_A"
chain33ID=0
# chain33 lock BTY, eth burn BTY
function LockTestChain33ToEthAssets() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# chain33 lock bty
hash=$(${Chain33Cli} evm call -f 1 -a 1 -c "${chain33DeployAddr}" -e "${chain33BridgeBank}" -p "lock(${ethSendAddress}, ${chain33BtyTokenAddr}, 100000000)" --chainID "${chain33ID}")
check_tx "${Chain33Cli}" "${hash}"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# chain33 lock BTY, eth burn BTY
function BurnTestChain33ToEthAssets() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# eth burn
result=$(${CLIA} ethereum burn -m 1 -k "${ethSendPrivateKeys}" -r "${chain33DeployAddr}" -t "${ethereumBtyTokenAddr}" ) #--node_addr https://ropsten.infura.io/v3/9e83f296716142ffbaeaafc05790f26c)
cli_ret "${result}" "burn"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# eth to chain33 在以太坊上锁定 ETH 资产,然后在 chain33 上 burn
function LockTestETH2Chain33Assets() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# ETH 这端 lock 11个
result=$(${CLIA} ethereum lock -m 2 -k "${ethSendPrivateKeys}" -r "${chain33ReceiverAddr}")
cli_ret "${result}" "lock"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# eth to chain33 在以太坊上锁定 ETH 资产,然后在 chain33 上 burn
function BurnTestETH2Chain33Assets() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
result=$(${CLIA} chain33 burn -m 2 -k "${chain33ReceiverAddrKey}" -r "${ethSendAddress}" -t "${chain33EthTokenAddr}")
cli_ret "${result}" "burn"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function LockTestETH2Chain33Ycc() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# ETH 这端 lock 7个 YCC
result=$(${CLIA} ethereum lock -m 3 -k "${ethSendPrivateKeys}" -r "${chain33ReceiverAddr}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "lock"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function BurnTestETH2Chain33Ycc() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
echo '#5.burn YCC from Chain33 YCC(Chain33)-----> Ethereum'
result=$(${CLIA} chain33 burn -m 3 -k "${chain33ReceiverAddrKey}" -r "${ethSendAddress}" -t "${chain33YccTokenAddr}")
cli_ret "${result}" "burn"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function mainTest() {
StartChain33
start_trufflesuite
AllRelayerStart
${CLIA} ethereum token token_transfer -k "${ethDeployKey}" -m 10000 -r "${ethSendAddress}" -t "${ethereumYccTokenAddr}"
for (( i = 0; i < 10; i++ )); do
LockTestChain33ToEthAssets
LockTestETH2Chain33Assets
LockTestETH2Chain33Ycc
sleep 1
done
while true ; do
LockTestChain33ToEthAssets
LockTestETH2Chain33Assets
LockTestETH2Chain33Ycc
eth_block_wait 2
BurnTestChain33ToEthAssets
BurnTestETH2Chain33Assets
BurnTestETH2Chain33Ycc
eth_block_wait 10
done
}
mainTest
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -x
set +e
source "./publicTest.sh"
source "./relayerPublic.sh"
# ETH 部署合约者的私钥 用于部署合约时签名使用
ethDeployAddr="0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a"
ethDeployKey="8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
# chain33 部署合约者的私钥 用于部署合约时签名使用
chain33DeployAddr="1N6HstkyLFS8QCeVfdvYxx1xoryXoJtvvZ"
#chain33DeployKey="0xcc38546e9e659d15e6b4893f0ab32a06d103931a8230b0bde71459d2b27d6944"
#maturityDegree=10
Chain33Cli="../../chain33-cli"
chain33BridgeBank=""
ethBridgeBank=""
chain33BtyTokenAddr="1111111111111111111114oLvT2"
#chain33EthTokenAddr=""
#ethereumBtyTokenAddr=""
#chain33YccTokenAddr=""
ethereumYccTokenAddr=""
multisignChain33Addr=""
multisignEthAddr=""
ethBridgeToeknYccAddr=""
chain33YccErc20Addr=""
CLIA="./ebcli_A"
chain33ID=0
chain33BridgeBank=16A3uxgPqCv5pVkKqtdVnv2As6DbfRVZRH
multisignChain33Addr=1b193HbfvVUunUL2DVXrqt9jnbAWwLjcT
function lockBty() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# echo '2:#配置自动转离线钱包(bty, 100, 50%)'
hash=$(${Chain33Cli} evm call -f 1 -c "${chain33DeployAddr}" -e ${chain33BridgeBank} -p "configLockedTokenOfflineSave(${chain33BtyTokenAddr},BTY,10000000000,50)" --chainID "${chain33ID}")
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a "${chain33BridgeBank}" -e evm)
# balance_ret "${result}" "0"
result=$(${Chain33Cli} account balance -a "${multisignChain33Addr}" -e evm)
# balance_ret "${result}" "0"
for (( i = 0; i < 1000; i++ )); do
echo "${i}"
lock_bty_multisign 1
sleep 1
done
result=$(${Chain33Cli} account balance -a "${chain33BridgeBank}" -e evm)
# balance_ret "${result}" "50"
result=$(${Chain33Cli} account balance -a "${multisignChain33Addr}" -e evm)
# balance_ret "${result}" "950"
# # transfer test
# hash=$(${CLIA} chain33 multisign transfer -a 100 -r "${chain33BridgeBank}" -k "${chain33MultisignKeyA},${chain33MultisignKeyB},${chain33MultisignKeyC},${chain33MultisignKeyD}" | jq -r ".msg")
# check_tx "${Chain33Cli}" "${hash}"
# sleep 2
# result=$(${Chain33Cli} account balance -a "${multisignChain33Addr}" -e evm)
# balance_ret "${result}" "997.5000"
# result=$(${Chain33Cli} account balance -a "${chain33BridgeBank}" -e evm)
# balance_ret "${result}" "632.5000"
#
# hash=$(${CLIA} chain33 multisign transfer -a 100 -r "${chain33MultisignA}" -k "${chain33MultisignKeyA},${chain33MultisignKeyB},${chain33MultisignKeyC},${chain33MultisignKeyD}" | jq -r ".msg")
# check_tx "${Chain33Cli}" "${hash}"
# sleep 2
# result=$(${Chain33Cli} account balance -a "${multisignChain33Addr}" -e evm)
# balance_ret "${result}" "897.5000"
# result=$(${Chain33Cli} account balance -a "${chain33MultisignA}" -e evm)
# balance_ret "${result}" "100.0000"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function lockChain33Ycc() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# echo '2:#配置自动转离线钱包(YCC, 100, 60%)'
hash=$(${Chain33Cli} evm call -f 1 -c "${chain33DeployAddr}" -e ${chain33BridgeBank} -p "configLockedTokenOfflineSave(${chain33YccErc20Addr},YCC,10000000000,60)" --chainID "${chain33ID}")
check_tx "${Chain33Cli}" "${hash}"
lock_chain33_ycc_multisign 30 30 0
lock_chain33_ycc_multisign 70 40 60
lock_chain33_ycc_multisign 260 120 240
lock_chain33_ycc_multisign 10 52 318
# transfer test
# shellcheck disable=SC2154
hash=$(${CLIA} chain33 multisign transfer -a 10 -r "${chain33BridgeBank}" -t "${chain33YccErc20Addr}" -k "${chain33MultisignKeyA},${chain33MultisignKeyB},${chain33MultisignKeyC},${chain33MultisignKeyD}" | jq -r ".msg")
check_tx "${Chain33Cli}" "${hash}"
sleep 2
result=$(${Chain33Cli} evm abi call -a "${chain33YccErc20Addr}" -c "${chain33BridgeBank}" -b "balanceOf(${chain33BridgeBank})")
is_equal "${result}" "6200000000"
result=$(${Chain33Cli} evm abi call -a "${chain33YccErc20Addr}" -c "${multisignChain33Addr}" -b "balanceOf(${multisignChain33Addr})")
is_equal "${result}" "30800000000"
# shellcheck disable=SC2154
hash=$(${CLIA} chain33 multisign transfer -a 5 -r "${chain33MultisignA}" -t "${chain33YccErc20Addr}" -k "${chain33MultisignKeyA},${chain33MultisignKeyB},${chain33MultisignKeyC},${chain33MultisignKeyD}" | jq -r ".msg")
check_tx "${Chain33Cli}" "${hash}"
sleep 2
result=$(${Chain33Cli} evm abi call -a "${chain33YccErc20Addr}" -c "${chain33MultisignA}" -b "balanceOf(${chain33MultisignA})")
is_equal "${result}" "500000000"
result=$(${Chain33Cli} evm abi call -a "${chain33YccErc20Addr}" -c "${multisignChain33Addr}" -b "balanceOf(${multisignChain33Addr})")
is_equal "${result}" "30300000000"
# 判断 ETH 这端是否金额一致
result=$(${CLIA} ethereum balance -o "${ethDeployAddr}" -t "${ethBridgeToeknYccAddr}" )
cli_ret "${result}" "balance" ".balance" "370"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function lockEth() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# echo '2:#配置自动转离线钱包(eth, 20, 50%)'
result=$(${CLIA} ethereum multisign set_offline_token -s ETH -m 20)
cli_ret "${result}" "set_offline_token -s ETH -m 20"
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" )
cli_ret "${result}" "balance" ".balance" "0"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}" )
cli_ret "${result}" "balance" ".balance" "0"
lock_eth_multisign 19 19 0
lock_eth_multisign 1 10 10
lock_eth_multisign 16 13 23
# transfer
# shellcheck disable=SC2154
${CLIA} ethereum multisign transfer -a 3 -r "${ethBridgeBank}" -k "${ethMultisignKeyA},${ethMultisignKeyB},${ethMultisignKeyC},${ethMultisignKeyD}"
sleep 2
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}")
cli_ret "${result}" "balance" ".balance" "16"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}")
cli_ret "${result}" "balance" ".balance" "20"
# transfer
# shellcheck disable=SC2154
${CLIA} ethereum multisign transfer -a 5 -r "${ethMultisignA}" -k "${ethMultisignKeyA},${ethMultisignKeyB},${ethMultisignKeyC},${ethMultisignKeyD}"
sleep 2
result=$(${CLIA} ethereum balance -o "${ethMultisignA}")
cli_ret "${result}" "balance" ".balance" "105"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}")
cli_ret "${result}" "balance" ".balance" "15"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function lockEthYcc() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# echo '2:#配置自动转离线钱包(ycc, 100, 40%)'
result=$(${CLIA} ethereum multisign set_offline_token -s YCC -m 100 -p 40 -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "set_offline_token -s YCC -m 100"
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
lock_ethereum_ycc_multisign 70 70 0
lock_ethereum_ycc_multisign 30 60 40
lock_ethereum_ycc_multisign 60 72 88
# transfer
# multisignEthAddr 要有手续费
./ebcli_A ethereum transfer -k "${ethDeployKey}" -m 10 -r "${multisignEthAddr}"
# transfer
${CLIA} ethereum multisign transfer -a 8 -r "${ethBridgeBank}" -t "${ethereumYccTokenAddr}" -k "${ethMultisignKeyA},${ethMultisignKeyB},${ethMultisignKeyC},${ethMultisignKeyD}"
sleep 2
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "balance" ".balance" "80"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "balance" ".balance" "80"
# transfer
${CLIA} ethereum multisign transfer -a 10 -r "${ethMultisignA}" -t "${ethereumYccTokenAddr}" -k "${ethMultisignKeyA},${ethMultisignKeyB},${ethMultisignKeyC},${ethMultisignKeyD}"
sleep 2
result=$(${CLIA} ethereum balance -o "${ethMultisignA}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "balance" ".balance" "10"
result=$(${CLIA} ethereum balance -o "${multisignEthAddr}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "balance" ".balance" "70"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# shellcheck disable=SC2120
function mainTest() {
if [[ $# -ge 1 && "${1}" != "" ]]; then
chain33ID="${1}"
fi
StartChain33
start_trufflesuite
AllRelayerStart
deployMultisign
lockBty
# lockChain33Ycc
# lockEth
# lockEthYcc
}
mainTest "${1}"
#lockBty
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -x
set +e
source "./publicTest.sh"
source "./relayerPublic.sh"
# chain33 部署合约者的私钥 用于部署合约时签名使用
chain33DeployAddr="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
#chain33DeployKey="0xcc38546e9e659d15e6b4893f0ab32a06d103931a8230b0bde71459d2b27d6944"
# ETH 部署合约者的私钥 用于部署合约时签名使用
ethDeployAddr="0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a"
ethDeployKey="8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
# validatorsAddr=["0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a", "0x0df9a824699bc5878232c9e612fe1a5346a5a368", "0xcb074cb21cdddf3ce9c3c0a7ac4497d633c9d9f1", "0xd9dab021e74ecf475788ed7b61356056b2095830"]
#ethValidatorAddrA="0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a"
ethValidatorAddrKeyA="8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
chain33ReceiverAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
chain33ReceiverAddrKey="4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01"
ethValidatorAddrB="0x0df9a824699bc5878232c9e612fe1a5346a5a368"
#ethValidatorAddrKeyB="a5f3063552f4483cfc20ac4f40f45b798791379862219de9e915c64722c1d400"
maturityDegree=10
Chain33Cli="../../chain33-cli"
CLIA="./ebcli_A"
chain33ID=0
#BridgeRegistryOnChain33=""
chain33BridgeBank=""
#BridgeRegistryOnEth=""
ethBridgeBank=""
chain33BtyTokenAddr="1111111111111111111114oLvT2"
chain33EthTokenAddr=""
ethereumBtyTokenAddr=""
chain33YccTokenAddr=""
ethereumYccTokenAddr=""
# chain33 lock BTY, eth burn BTY
function TestChain33ToEthAssets() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
result=$(${CLIA} ethereum balance -o "${ethDeployAddr}" -t "${ethereumBtyTokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
# 原来的地址金额
result=$(${Chain33Cli} account balance -a "${chain33DeployAddr}" -e evm)
# balance=$(cli_ret "${result}" "balance" ".balance")
# chain33 lock bty
hash=$(${Chain33Cli} evm call -f 1 -a 5 -c "${chain33DeployAddr}" -e "${chain33BridgeBank}" -p "lock(${ethDeployAddr}, ${chain33BtyTokenAddr}, 500000000)" --chainID "${chain33ID}")
check_tx "${Chain33Cli}" "${hash}"
# 原来的地址金额 减少了 5
result=$(${Chain33Cli} account balance -a "${chain33DeployAddr}" -e evm)
# cli_ret "${result}" "balance" ".balance" "$(echo "${balance}-5" | bc)"
#balance_ret "${result}" "195.0000"
# chain33BridgeBank 是否增加了 5
result=$(${Chain33Cli} account balance -a "${chain33BridgeBank}" -e evm)
balance_ret "${result}" "5.0000"
eth_block_wait 2
# eth 这端 金额是否增加了 5
result=$(${CLIA} ethereum balance -o "${ethDeployAddr}" -t "${ethereumBtyTokenAddr}")
cli_ret "${result}" "balance" ".balance" "5"
# eth burn
result=$(${CLIA} ethereum burn -m 3 -k "${ethDeployKey}" -r "${chain33ReceiverAddr}" -t "${ethereumBtyTokenAddr}" ) #--node_addr https://ropsten.infura.io/v3/9e83f296716142ffbaeaafc05790f26c)
cli_ret "${result}" "burn"
eth_block_wait 2
# eth 这端 金额是否减少了 3
result=$(${CLIA} ethereum balance -o "${ethDeployAddr}" -t "${ethereumBtyTokenAddr}")
cli_ret "${result}" "balance" ".balance" "2"
sleep ${maturityDegree}
# 接收的地址金额 变成了 3
result=$(${Chain33Cli} account balance -a "${chain33ReceiverAddr}" -e evm)
balance_ret "${result}" "3.0000"
# chain33BridgeBank 是否减少了 3
result=$(${Chain33Cli} account balance -a "${chain33BridgeBank}" -e evm)
balance_ret "${result}" "2.0000"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# eth to chain33 在以太坊上锁定 ETH 资产,然后在 chain33 上 burn
function TestETH2Chain33Assets() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# 查询 ETH 这端 bridgeBank 地址原来是 0
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" )
cli_ret "${result}" "balance" ".balance" "0"
# ETH 这端 lock 11个
result=$(${CLIA} ethereum lock -m 11 -k "${ethValidatorAddrKeyA}" -r "${chain33ReceiverAddr}")
cli_ret "${result}" "lock"
# eth 等待 10 个区块
eth_block_wait 2
# 查询 ETH 这端 bridgeBank 地址 11
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" )
cli_ret "${result}" "balance" ".balance" "11"
sleep ${maturityDegree}
# chain33 chain33EthTokenAddr(ETH合约中)查询 lock 金额
result=$(${Chain33Cli} evm abi call -a "${chain33EthTokenAddr}" -c "${chain33DeployAddr}" -b "balanceOf(${chain33ReceiverAddr})")
# 结果是 11 * le8
is_equal "${result}" "1100000000"
# 原来的数额
result=$(${CLIA} ethereum balance -o "${ethValidatorAddrB}")
cli_ret "${result}" "balance" ".balance" "100"
echo '#5.burn ETH from Chain33 ETH(Chain33)-----> Ethereum'
${CLIA} chain33 burn -m 5 -k "${chain33ReceiverAddrKey}" -r "${ethValidatorAddrB}" -t "${chain33EthTokenAddr}"
sleep ${maturityDegree}
echo "check the balance on chain33"
result=$(${Chain33Cli} evm abi call -a "${chain33EthTokenAddr}" -c "${chain33DeployAddr}" -b "balanceOf(${chain33ReceiverAddr})")
# 结果是 11-5 * le8
is_equal "${result}" "600000000"
# 查询 ETH 这端 bridgeBank 地址 0
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" )
cli_ret "${result}" "balance" ".balance" "6"
# 比之前多 5
result=$(${CLIA} ethereum balance -o "${ethValidatorAddrB}")
cli_ret "${result}" "balance" ".balance" "105"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function TestETH2Chain33Ycc() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# 查询 ETH 这端 bridgeBank 地址原来是 0
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
# ETH 这端 lock 7个 YCC
result=$(${CLIA} ethereum lock -m 7 -k "${ethDeployKey}" -r "${chain33ReceiverAddr}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "lock"
# eth 等待 10 个区块
eth_block_wait 2
# 查询 ETH 这端 bridgeBank 地址 7 YCC
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "balance" ".balance" "7"
sleep ${maturityDegree}
# chain33 chain33EthTokenAddr(ETH合约中)查询 lock 金额
result=$(${Chain33Cli} evm abi call -a "${chain33YccTokenAddr}" -c "${chain33DeployAddr}" -b "balanceOf(${chain33ReceiverAddr})")
# 结果是 7 * le8
is_equal "${result}" "700000000"
# 原来的数额 0
result=$(${CLIA} ethereum balance -o "${ethValidatorAddrB}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
echo '#5.burn YCC from Chain33 YCC(Chain33)-----> Ethereum'
${CLIA} chain33 burn -m 5 -k "${chain33ReceiverAddrKey}" -r "${ethValidatorAddrB}" -t "${chain33YccTokenAddr}"
sleep ${maturityDegree}
echo "check the balance on chain33"
result=$(${Chain33Cli} evm abi call -a "${chain33YccTokenAddr}" -c "${chain33DeployAddr}" -b "balanceOf(${chain33ReceiverAddr})")
# 结果是 7-5 * le8
is_equal "${result}" "200000000"
# 查询 ETH 这端 bridgeBank 地址 2
result=$(${CLIA} ethereum balance -o "${ethBridgeBank}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "balance" ".balance" "2"
# 更新后的金额 5
result=$(${CLIA} ethereum balance -o "${ethValidatorAddrB}" -t "${ethereumYccTokenAddr}")
cli_ret "${result}" "balance" ".balance" "5"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# shellcheck disable=SC2120
function mainTest() {
if [[ $# -ge 1 && "${1}" != "" ]]; then
chain33ID="${1}"
fi
StartChain33
start_trufflesuite
StartOneRelayer
TestChain33ToEthAssets
TestETH2Chain33Assets
TestETH2Chain33Ycc
}
mainTest "${1}"
\ No newline at end of file
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -x
set +e
# 只测试 lock 操作,不测试 burn
source "./publicTest.sh"
source "./relayerPublic.sh"
source "./multisignPublicTest.sh"
## ETH 部署合约者的私钥 用于部署合约时签名使用
#ethDeployAddr="0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a"
#ethDeployKey="8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
#
## chain33 部署合约者的私钥 用于部署合约时签名使用
#chain33DeployAddr="1N6HstkyLFS8QCeVfdvYxx1xoryXoJtvvZ"
#
#Chain33Cli="../../chain33-cli"
#chain33BridgeBank=""
#ethBridgeBank=""
#chain33BtyTokenAddr="1111111111111111111114oLvT2"
#ethereumYccTokenAddr=""
#multisignChain33Addr=""
#multisignEthAddr=""
#ethBridgeToeknYccAddr=""
#chain33YccErc20Addr=""
#
#CLIA="./ebcli_A"
chain33ID=0
function mainTest() {
if [[ $# -ge 1 && "${1}" != "" ]]; then
# shellcheck disable=SC2034
chain33ID="${1}"
fi
StartChain33
start_trufflesuite
AllRelayerStart
deployMultisign
lockBty
lockChain33Ycc
lockEth
lockEthYcc
}
mainTest "${1}"
This diff is collapsed.
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -x
set +e
source "./publicTest.sh"
source "./relayerPublic.sh"
# shellcheck disable=SC2120
function mainTest() {
kill_ebrelayer "chain33 -f"
sleep 2
# delete chain33 datadir
rm ../../datadir ../../logs -rf
local ganacheName=ganachetest
# shellcheck disable=SC2155
local isExit=$(docker inspect ${ganacheName} | jq ".[]" | jq ".Id")
if [[ ${isExit} != "" ]]; then
docker stop ${ganacheName}
docker rm ${ganacheName}
fi
kill_all_ebrelayer
cp ../../../plugin/dapp/cross2eth/ebrelayer/relayer.toml ./relayer.toml
}
mainTest "${1}"
#user nobody;
worker_processes 1;
events {
#worker_connections 1024 may not enough
worker_connections 204800;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 1000;
#gzip on;
upstream chain33url{
ip_hash;
server chain33:8802 weight=1;
#server chain30:8802 weight=1;
}
server {
listen 8803 http2;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
#proxy_pass http://yankerp;
grpc_pass grpc://chain33url;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#!/usr/bin/env bash
# shellcheck disable=SC2050
# shellcheck source=/dev/null
set -x
set +e
while [ 1 == 1 ]; do
sleep 100
done
Title="local"
TestNet=true
CoinSymbol="bty"
TxHeight=true
ChainID=33
# crypto模块配置
[crypto]
enableTypes=[] #设置启用的加密插件名称,不配置启用所有
[crypto.enableHeight] #配置已启用插件的启用高度,不配置采用默认高度0, 负数表示不启用
secp256k1=0
[crypto.sub.secp256k1] #支持插件子配置
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
loglevel = "debug"
logConsoleLevel = "info"
# 日志文件名,可带目录,所有生成的日志文件都放到此目录下
logFile = "logs/chain33.log"
# 单个日志文件的最大值(单位:兆)
maxFileSize = 20
# 最多保存的历史日志文件个数
maxBackups = 20
# 最多保存的历史日志消息(单位:天)
maxAge = 28
# 日志文件名是否使用本地事件(否则使用UTC时间)
localTime = true
# 历史日志文件是否压缩(压缩格式为gz)
compress = false
# 是否打印调用源文件和行号
callerFile = true
# 是否打印调用方法
callerFunction = true
[blockchain]
defCacheSize=128
maxFetchBlockNum=128
timeoutSeconds=5
batchBlockNum=128
driver="leveldb"
dbPath="datadir"
dbCache=64
isStrongConsistency=true
singleMode=true
batchsync=false
isRecordBlockSequence=true
isParaChain=false
enableTxQuickIndex=true
# 使能精简localdb
enableReduceLocaldb=false
# 关闭分片存储,默认false为开启分片存储;平行链不需要分片需要修改此默认参数为true
disableShard=false
# 分片存储中每个大块包含的区块数
chunkblockNum=1000
# 使能从P2pStore中获取数据
enableFetchP2pstore=false
# 使能假设已删除已归档数据后,获取数据情况
enableIfDelLocalChunk=false
# 开启推送功能
enablePushSubscribe=true
[p2p]
types=[ "dht"]
enable=true
driver="leveldb"
dbPath="datadir/addrbook"
dbCache=4
grpcLogFile="grpc33.log"
[p2p.sub.dht]
port=13803
[rpc]
jrpcBindAddr="localhost:8801"
grpcBindAddr="localhost:8802"
whitelist=["127.0.0.1"]
jrpcFuncWhitelist=["*"]
grpcFuncWhitelist=["*"]
enableTLS=false
certFile="cert.pem"
keyFile="key.pem"
[mempool]
name="timeline"
poolCacheSize=10240
# 最小得交易手续费率,这个没有默认值,必填,一般是0.001 coins
minTxFeeRate=100000
# 最大的交易手续费率, 0.1 coins
maxTxFeeRate=10000000
# 单笔交易最大的手续费, 10 coins
maxTxFee=1000000000
maxTxNumPerAccount=100
isLevelFee=false
[mempool.sub.timeline]
poolCacheSize=10240
[mempool.sub.score]
poolCacheSize=10240
timeParam=1 #时间占价格比例
priceConstant=1544 #手续费相对于时间的一个合适的常量,取当前unxi时间戳前四位数,排序时手续费高1e-5~=快1s
pricePower=1 #常量比例
[mempool.sub.price]
poolCacheSize=10240
[consensus]
name="solo"
minerstart=true
genesisBlockTime=1514533394
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
minerExecs=["ticket", "autonomy"]
[mver.consensus]
fundKeyAddr = "1BQXS6TxaYYG5mADaWij4AxhZZUTpw95a5"
powLimitBits = "0x1f00ffff"
maxTxNumber = 1600 #160
[mver.consensus.ForkChainParamV1]
maxTxNumber = 10000
[mver.consensus.ForkChainParamV2]
powLimitBits = "0x1f2fffff"
[mver.consensus.ForkTicketFundAddrV1]
fundKeyAddr = "1Ji3W12KGScCM7C2p8bg635sNkayDM8MGY"
[mver.consensus.ticket]
coinReward = 18
coinDevFund = 12
ticketPrice = 10000
retargetAdjustmentFactor = 4
futureBlockTime = 16
ticketFrozenTime = 5 #5s only for test
ticketWithdrawTime = 10 #10s only for test
ticketMinerWaitTime = 2 #2s only for test
targetTimespan = 2304
targetTimePerBlock = 16
[mver.consensus.ticket.ForkChainParamV1]
targetTimespan = 288 #only for test
targetTimePerBlock = 2
[consensus.sub.solo]
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
genesisBlockTime=1514533394
hotkeyAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
waitTxMs=10
[consensus.sub.ticket]
genesisBlockTime=1514533394
[[consensus.sub.ticket.genesis]]
minerAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
returnAddr="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
count=10000
[[consensus.sub.ticket.genesis]]
minerAddr="1PUiGcbsccfxW3zuvHXZBJfznziph5miAo"
returnAddr="1EbDHAXpoiewjPLX9uqoz38HsKqMXayZrF"
count=10000
[[consensus.sub.ticket.genesis]]
minerAddr="1EDnnePAZN48aC2hiTDzhkczfF39g1pZZX"
returnAddr="1KcCVZLSQYRUwE5EXTsAoQs9LuJW6xwfQa"
count=10000
[store]
name="mavl"
driver="leveldb"
dbPath="datadir/mavltree"
dbCache=128
[store.sub.mavl]
enableMavlPrefix=false
enableMVCC=false
enableMavlPrune=false
pruneHeight=10000
# 是否使能mavl数据载入内存
enableMemTree=false
# 是否使能mavl叶子节点数据载入内存
enableMemVal=false
# 缓存close ticket数目,该缓存越大同步速度越快,最大设置到1500000
tkCloseCacheLen=100000
[wallet]
minFee=1000000
driver="leveldb"
dbPath="datadir/wallet"
dbCache=16
signType="secp256k1"
coinType="bty"
[wallet.sub.ticket]
minerwhitelist=["*"]
[exec]
enableStat=false
enableMVCC=false
[exec.sub.token]
saveTokenTxList=true
tokenApprs = [
"1Bsg9j6gW83sShoee1fZAt9TkUjcrCgA9S",
"1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK",
"1LY8GFia5EiyoTodMLfkB5PHNNpXRqxhyB",
"1GCzJDS6HbgTQ2emade7mEJGGWFfA15pS9",
"1JYB8sxi4He5pZWHCd3Zi2nypQ4JMB6AxN",
"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv",
]
[exec.sub.relay]
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
[exec.sub.cert]
# 是否启用证书验证和签名
enable=false
# 加密文件路径
cryptoPath="authdir/crypto"
# 带证书签名类型,支持"auth_ecdsa", "auth_sm2"
signType="auth_ecdsa"
[exec.sub.manage]
superManager=[
"1Bsg9j6gW83sShoee1fZAt9TkUjcrCgA9S",
"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv",
"1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK"
]
[exec.sub.autonomy]
total="16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp"
useBalance=false
[health]
listenAddr="localhost:8805"
checkInterval=1
unSyncMaxTimes=2
[metrics]
#是否使能发送metrics数据的发送
enableMetrics=false
#数据保存模式
dataEmitMode="influxdb"
[metrics.sub.influxdb]
#以纳秒为单位的发送间隔
duration=1000000000
url="http://influxdb:8086"
database="chain33metrics"
username=""
password=""
namespace=""
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
source "./dockerRelayerTest.sh"
source "./paracrosstestcase.sh"
function cross2eth() {
if [ "${2}" == "init" ]; then
para_init "${3}"
elif [ "${2}" == "config" ]; then
para_set_wallet
para_transfer
elif [ "${2}" == "test" ]; then
echo "========================== cross2eth test =========================="
set +e
set -x
para_create_nodegroup
AllRelayerMainTest 10
# perf_test_main 1
echo "========================== cross2eth test end =========================="
fi
}
#!/usr/bin/env bash
#shellcheck disable=SC2128
#shellcheck source=/dev/null
set -x
source ../dapp-test-common.sh
MAIN_HTTP=""
function rpc_test() {
chain33_RpcTestBegin cross2eth
MAIN_HTTP="$1"
echo "main_ip=$MAIN_HTTP"
chain33_RpcTestRst cross2eth "$CASE_ERR"
}
chain33_debug_function rpc_test "$1" "$2"
##
##编译solidity,并产生bin文件,abi文件,和相应的go文件
SRC_CONTRACT0 := contracts4chain33
SRC_CONTRACT1 := contracts4eth
SRC_MULTISIGN := gnosis/safe-contracts/contracts
GO_OUT0 := ${SRC_CONTRACT0}/generated
GO_OUT1 := ${SRC_CONTRACT1}/generated
GO_OUT_MULTISIGN := gnosis/generated
PACKAGE := generated
proj := "build"
.PHONY: default build clean registry bridgeBank setup
default: depends build
build: depends
@abigen --sol $(SRC_CONTRACT0)/BridgeRegistry.sol --pkg $(PACKAGE) --out $(GO_OUT0)/BridgeRegistry.go
@abigen --sol $(SRC_CONTRACT0)/BridgeBank/BridgeBank.sol --pkg $(PACKAGE) --out $(GO_OUT0)/BridgeBank.go
@abigen --sol $(SRC_CONTRACT1)/BridgeRegistry.sol --pkg $(PACKAGE) --out $(GO_OUT1)/BridgeRegistry.go
@abigen --sol $(SRC_CONTRACT1)/BridgeBank/BridgeBank.sol --pkg $(PACKAGE) --out $(GO_OUT1)/BridgeBank.go
multisign:
@abigen --sol $(SRC_MULTISIGN)/GnosisSafe.sol --pkg $(PACKAGE) --out $(GO_OUT_MULTISIGN)/gnosisSafe.go
clean:
@rm -fr $(GO_OUT)/*
registry0:
@abigen --sol $(SRC_CONTRACT0)/BridgeRegistry.sol --pkg $(PACKAGE) --out $(GO_OUT0)/BridgeRegistry.go
bridgeBank0:
@abigen --sol $(SRC_CONTRACT0)/BridgeBank/BridgeBank.sol --pkg $(PACKAGE) --out $(GO_OUT0)/BridgeBank.go
asmExample:
@solc --asm --bin -o tmp/ valset-bin=./tmp/valset-bin Valset.sol
depends:
if ! [ -d openzeppelin-solidity ]; then \
echo "not exist openzeppelin-solidity and going to get" ; \
go get github.com/OpenZeppelin/openzeppelin-contracts@v2.5 ; \
mkdir openzeppelin-solidity ;\
cp -r ${GOPATH}/pkg/mod/github.com/\!open\!zeppelin/openzeppelin-contracts@v2.5.0+incompatible/contracts openzeppelin-solidity ; \
fi; \
pragma solidity ^0.5.0;
import "./EthereumBank.sol";
import "./Chain33Bank.sol";
import "../Oracle.sol";
import "../EthereumBridge.sol";
/**
* @title BridgeBank
* @dev Bank contract which coordinates asset-related functionality.
* EthereumBank manages the minting and burning of tokens which
* represent Ethereum based assets, while Chain33Bank manages
* the locking and unlocking of Chain33 and ERC20 token assets
* based on Chain33.
**/
contract BridgeBank is EthereumBank, Chain33Bank {
using SafeMath for uint256;
address public operator;
Oracle public oracle;
EthereumBridge public ethereumBridge;
/*
* @dev: Constructor, sets operator
*/
constructor (
address _operatorAddress,
address _oracleAddress,
address _ethereumBridgeAddress
)
public
{
operator = _operatorAddress;
oracle = Oracle(_oracleAddress);
ethereumBridge = EthereumBridge(_ethereumBridgeAddress);
}
/*
* @dev: Modifier to restrict access to operator
*/
modifier onlyOperator() {
require(
msg.sender == operator,
'Must be BridgeBank operator.'
);
_;
}
/*
* @dev: Modifier to restrict access to Offline
*/
modifier onlyOffline() {
require(
msg.sender == offlineSave,
'Must be onlyOffline.'
);
_;
}
/*
* @dev: Modifier to restrict access to the oracle
*/
modifier onlyOracle()
{
require(
msg.sender == address(oracle),
"Access restricted to the oracle"
);
_;
}
/*
* @dev: Modifier to restrict access to the ethereum bridge
*/
modifier onlyEthereumBridge()
{
require(
msg.sender == address(ethereumBridge),
"Access restricted to the ethereum bridge"
);
_;
}
/*
* @dev: Fallback function allows operator to send funds to the bank directly
* This feature is used for testing and is available at the operator's own risk.
*/
function() external payable onlyOffline {}
/*
* @dev: Creates a new BridgeToken
*
* @param _symbol: The new BridgeToken's symbol
* @return: The new BridgeToken contract's address
*/
function createNewBridgeToken(
string memory _symbol
)
public
onlyOperator
returns(address)
{
return deployNewBridgeToken(_symbol);
}
/*
* @dev: Mints new BankTokens
*
* @param _ethereumSender: The sender's Ethereum address in bytes.
* @param _chain33Recipient: The intended recipient's Chain33 address.
* @param _ethereumTokenAddress: The currency type
* @param _symbol: ethereum token symbol
* @param _amount: number of ethereum tokens to be minted
*/
function mintBridgeTokens(
bytes memory _ethereumSender,
address payable _intendedRecipient,
address _bridgeTokenAddress,
string memory _symbol,
uint256 _amount
)
public
onlyEthereumBridge
{
return mintNewBridgeTokens(
_ethereumSender,
_intendedRecipient,
_bridgeTokenAddress,
_symbol,
_amount
);
}
/*
* @dev: Burns bank tokens
*
* @param _ethereumReceiver: The _ethereum receiver address in bytes.
* @param _ethereumTokenAddress: The currency type
* @param _amount: number of ethereum tokens to be burned
*/
function burnBridgeTokens(
bytes memory _ethereumReceiver,
address _ethereumTokenAddress,
uint256 _amount
)
public
{
return burnEthereumTokens(
msg.sender,
_ethereumReceiver,
_ethereumTokenAddress,
_amount
);
}
/*
* @dev: addToken2LockList used to add token with the specified address to be
* allowed locked from Ethereum
*
* @param _token: token contract address
* @param _symbol: token symbol
*/
function addToken2LockList(
address _token,
string memory _symbol
)
public
onlyOperator
{
addToken2AllowLock(_token, _symbol);
}
/*
* @dev: configTokenOfflineSave used to config threshold to trigger tranfer token to offline account
* when the balance of locked token reaches
*
* @param _token: token contract address
* @param _symbol:token symbol,just used for double check that token address and symbol is consistent
* @param _threshold: _threshold to trigger transfer
* @param _percents: amount to transfer per percents of threshold
*/
function configLockedTokenOfflineSave(
address _token,
string memory _symbol,
uint256 _threshold,
uint8 _percents
)
public
onlyOperator
{
if (address(0) != _token) {
require(keccak256(bytes(BridgeToken(_token).symbol())) == keccak256(bytes(_symbol)), "token address and symbol is not consistent");
} else {
require(keccak256(bytes("BTY")) == keccak256(bytes(_symbol)), "token address and symbol is not consistent");
}
configOfflineSave4Lock(_token, _symbol, _threshold, _percents);
}
/*
* @dev: configOfflineSaveAccount used to config offline account to receive token
* when the balance of locked token reaches threshold
*
* @param _offlineSave: receiver address
*/
function configOfflineSaveAccount(address payable _offlineSave) public onlyOperator
{
offlineSave = _offlineSave;
}
/*
* @dev: Locks received Chain33 funds.
*
* @param _recipient: bytes representation of destination address.
* @param _token: token address in origin chain (0x0 if chain33)
* @param _amount: value of deposit
*/
function lock(
bytes memory _recipient,
address _token,
uint256 _amount
)
public
availableNonce()
payable
{
string memory symbol;
// Chain33 deposit
if (msg.value > 0) {
require(
_token == address(0),
"BTY deposits require the 'token' address to be the null address"
);
require(
msg.value == _amount,
"The transactions value must be equal the specified amount(BTY decimal is 8)"
);
// Set the the symbol to BTY
symbol = "BTY";
// ERC20 deposit
} else {
require(
BridgeToken(_token).transferFrom(msg.sender, address(this), _amount),
"Contract token allowances insufficient to complete this lock request"
);
// Set symbol to the ERC20 token's symbol
symbol = BridgeToken(_token).symbol();
require(
tokenAllow2Lock[keccak256(abi.encodePacked(symbol))] == _token,
'The token is not allowed to be locked from Chain33.'
);
}
lockFunds(
msg.sender,
_recipient,
_token,
symbol,
_amount
);
}
/*
* @dev: Unlocks Chain33 and ERC20 tokens held on the contract.
*
* @param _recipient: recipient's Chain33 address
* @param _token: token contract address
* @param _symbol: token symbol
* @param _amount: wei amount or ERC20 token count
\ */
function unlock(
address payable _recipient,
address _token,
string memory _symbol,
uint256 _amount
)
public
onlyEthereumBridge
hasLockedFunds(
_token,
_amount
)
canDeliver(
_token,
_amount
)
{
unlockFunds(
_recipient,
_token,
_symbol,
_amount
);
}
/*
* @dev: Exposes an item's current status.
*
* @param _id: The item in question.
* @return: Boolean indicating the lock status.
*/
function getEthereumDepositStatus(
bytes32 _id
)
public
view
returns(bool)
{
return isLockedEthereumDeposit(_id);
}
/*
* @dev: Allows access to a Ethereum deposit's information via its unique identifier.
*
* @param _id: The deposit to be viewed.
* @return: Original sender's Chain33 address.
* @return: Intended Ethereum recipient's address in bytes.
* @return: The lock deposit's currency, denoted by a token address.
* @return: The amount locked in the deposit.
* @return: The deposit's unique nonce.
*/
function viewEthereumDeposit(
bytes32 _id
)
public
view
returns(bytes memory, address payable, address, uint256)
{
return getEthereumDeposit(_id);
}
}
\ No newline at end of file
pragma solidity ^0.5.0;
import "../../openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol";
import "../../openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol";
import "../../openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol";
/**
* @title BridgeToken
* @dev Mintable, ERC20 compatible BankToken for use by BridgeBank
**/
contract BridgeToken is ERC20Mintable, ERC20Burnable, ERC20Detailed {
constructor(
string memory _symbol
)
public
ERC20Detailed(
_symbol,
_symbol,
8
)
{
// Intentionally left blank
}
}
\ No newline at end of file
pragma solidity ^0.5.0;
import "../../openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./BridgeToken.sol";
/*
* @title: Chain33Bank
* @dev: Chain33 bank which locks Chain33/ERC20 token deposits, and unlocks
* Chain33/ERC20 tokens once the prophecy has been successfully processed.
*/
contract Chain33Bank {
using SafeMath for uint256;
address payable public offlineSave;
uint256 public lockNonce;
mapping(address => uint256) public lockedFunds;
mapping(bytes32 => address) public tokenAllow2Lock;
mapping(address => OfflineSaveCfg) public offlineSaveCfgs;
uint8 public lowThreshold = 5;
uint8 public highThreshold = 80;
struct OfflineSaveCfg {
address token;
string symbol;
uint256 _threshold;
uint8 _percents;
}
/*
* @dev: Event declarations
*/
event LogLock(
address _from,
bytes _to,
address _token,
string _symbol,
uint256 _value,
uint256 _nonce
);
event LogUnlock(
address _to,
address _token,
string _symbol,
uint256 _value
);
/*
* @dev: Modifier declarations
*/
modifier hasLockedFunds(
address _token,
uint256 _amount
) {
require(
lockedFunds[_token] >= _amount,
"The Bank does not hold enough locked tokens to fulfill this request."
);
_;
}
modifier canDeliver(
address _token,
uint256 _amount
)
{
if(_token == address(0)) {
require(
address(this).balance >= _amount,
'Insufficient Chain33 balance for delivery.'
);
} else {
require(
BridgeToken(_token).balanceOf(address(this)) >= _amount,
'Insufficient ERC20 token balance for delivery.'
);
}
_;
}
modifier availableNonce() {
require(
lockNonce + 1 > lockNonce,
'No available nonces.'
);
_;
}
/*
* @dev: Constructor which sets the lock nonce
*/
constructor()
public
{
lockNonce = 0;
}
/*
* @dev: addToken2AllowLock used to add token with the specified address to be
* allowed locked from Ethereum
*
* @param _token: token contract address
* @param _symbol: token symbol
*/
function addToken2AllowLock(
address _token,
string memory _symbol
)
internal
{
bytes32 symHash = keccak256(abi.encodePacked(_symbol));
address tokenQuery = tokenAllow2Lock[symHash];
require(tokenQuery == address(0), 'The token with the same symbol has been added to lock allow list already.');
tokenAllow2Lock[symHash] = _token;
}
/*
* @dev: addToken2AllowLock used to add token with the specified address to be
* allowed locked from Ethereum
*
* @param _symbol: token symbol
*/
function getLockedTokenAddress(string memory _symbol) public view returns(address)
{
bytes32 symHash = keccak256(abi.encodePacked(_symbol));
return tokenAllow2Lock[symHash];
}
/*
* @dev: configOfflineSave4Lock used to config threshold to trigger tranfer token to offline account
* when the balance of locked token reaches
*
* @param _token: token contract address
* @param _symbol:token symbol,just used for double check that token address and symbol is consistent
* @param _threshold: _threshold to trigger transfer
* @param _percents: amount to transfer per percents of threshold
*/
function configOfflineSave4Lock(
address _token,
string memory _symbol,
uint256 _threshold,
uint8 _percents
)
internal
{
require(
_percents >= lowThreshold && _percents <= highThreshold,
"The percents to trigger should within range [5, 80]"
);
OfflineSaveCfg memory offlineSaveCfg = OfflineSaveCfg(
_token,
_symbol,
_threshold,
_percents
);
offlineSaveCfgs[_token] = offlineSaveCfg;
}
/*
* @dev: getofflineSaveCfg used to get token's offline save configuration
*
* @param _token: token contract address
*/
function getofflineSaveCfg(address _token) public view returns(uint256, uint8)
{
OfflineSaveCfg memory offlineSaveCfg = offlineSaveCfgs[_token];
return (offlineSaveCfg._threshold, offlineSaveCfg._percents);
}
/*
* @dev: Creates a new Chain33 deposit with a unique id.
*
* @param _sender: The sender's Chain33 address.
* @param _recipient: The intended recipient's Chain33 address.
* @param _token: The currency type, either erc20 or Chain33.
* @param _amount: The amount of erc20 tokens/ Chain33 (in wei) to be itemized.
*/
function lockFunds(
address payable _sender,
bytes memory _recipient,
address _token,
string memory _symbol,
uint256 _amount
)
internal
{
// Incerment the lock nonce
lockNonce = lockNonce.add(1);
// Increment locked funds by the amount of tokens to be locked
lockedFunds[_token] = lockedFunds[_token].add(_amount);
emit LogLock(
_sender,
_recipient,
_token,
_symbol,
_amount,
lockNonce
);
if (address(0) == offlineSave) {
return;
}
uint256 balance;
if (address(0) == _token) {
balance = address(this).balance;
} else {
balance = BridgeToken(_token).balanceOf(address(this));
}
OfflineSaveCfg memory offlineSaveCfg = offlineSaveCfgs[_token];
//check not zero,so configured already
if (offlineSaveCfg._percents < lowThreshold) {
return;
}
if (balance < offlineSaveCfg._threshold ) {
return;
}
uint256 amount = offlineSaveCfg._percents * balance / 100;
if (address(0) == _token) {
offlineSave.transfer(amount);
} else {
require(BridgeToken(_token).transfer(offlineSave, amount), "Erc20 Token Transfer to offline Save account failed");
}
}
/*
* @dev: Unlocks funds held on contract and sends them to the
* intended recipient
*
* @param _recipient: recipient's Chain33 address
* @param _token: token contract address
* @param _symbol: token symbol
* @param _amount: wei amount or ERC20 token count
*/
function unlockFunds(
address payable _recipient,
address _token,
string memory _symbol,
uint256 _amount
)
internal
{
// Decrement locked funds mapping by the amount of tokens to be unlocked
lockedFunds[_token] = lockedFunds[_token].sub(_amount);
// Transfer funds to intended recipient
if (_token == address(0)) {
_recipient.transfer(_amount);
} else {
require(
BridgeToken(_token).transfer(_recipient, _amount),
"Token transfer failed"
);
}
emit LogUnlock(
_recipient,
_token,
_symbol,
_amount
);
}
}
pragma solidity ^0.5.0;
contract BridgeRegistry {
address public ethereumBridge;
address public bridgeBank;
address public oracle;
address public valset;
uint256 public deployHeight;
event LogContractsRegistered(
address _ethereumBridge,
address _bridgeBank,
address _oracle,
address _valset
);
constructor(
address _ethereumBridge,
address _bridgeBank,
address _oracle,
address _valset
)
public
{
ethereumBridge = _ethereumBridge;
bridgeBank = _bridgeBank;
oracle = _oracle;
valset = _valset;
deployHeight = block.number;
emit LogContractsRegistered(
ethereumBridge,
bridgeBank,
oracle,
valset
);
}
}
\ No newline at end of file
pragma solidity ^0.5.0;
import "../openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./Valset.sol";
import "./BridgeBank/BridgeBank.sol";
contract EthereumBridge {
using SafeMath for uint256;
/*
* @dev: Public variable declarations
*/
address public operator;
Valset public valset;
address public oracle;
bool public hasOracle;
BridgeBank public bridgeBank;
bool public hasBridgeBank;
uint256 public prophecyClaimCount;
mapping(bytes32 => ProphecyClaim) public prophecyClaims;
enum Status {
Null,
Pending,
Success,
Failed
}
enum ClaimType {
Unsupported,
Burn,
Lock
}
struct ProphecyClaim {
ClaimType claimType;
bytes ethereumSender;
address payable chain33Receiver;
address originalValidator;
address tokenAddress;
string symbol;
uint256 amount;
Status status;
}
/*
* @dev: Event declarations
*/
event LogOracleSet(
address _oracle
);
event LogBridgeBankSet(
address _bridgeBank
);
event LogNewProphecyClaim(
uint256 _prophecyID,
ClaimType _claimType,
bytes _ethereumSender,
address payable _chain33Receiver,
address _validatorAddress,
address _tokenAddress,
string _symbol,
uint256 _amount
);
event LogProphecyCompleted(
bytes32 _claimID,
ClaimType _claimType
);
/*
* @dev: Modifier which only allows access to currently pending prophecies
*/
modifier isPending(
bytes32 _claimID
)
{
require(
isProphecyClaimActive(_claimID),
"Prophecy claim is not active"
);
_;
}
/*
* @dev: Modifier to restrict access to the operator.
*/
modifier onlyOperator()
{
require(
msg.sender == operator,
'Must be the operator.'
);
_;
}
/*
* @dev: Modifier to restrict access to the oracle.
*/
modifier onlyOracle()
{
require(
msg.sender == oracle,
'Must be the oracle.'
);
_;
}
/*
* @dev: The bridge is not active until oracle and bridge bank are set
*/
modifier isActive()
{
require(
hasOracle == true && hasBridgeBank == true,
"The Operator must set the oracle and bridge bank for bridge activation"
);
_;
}
/*
* @dev: Modifier to make sure the claim type is valid
*/
modifier validClaimType(
ClaimType _claimType
)
{
require(
_claimType == ClaimType.Burn || _claimType == ClaimType.Lock,
"The claim type must be ClaimType.Burn or ClaimType.Lock"
);
_;
}
/*
* @dev: Constructor
*/
constructor(
address _operator,
address _valset
)
public
{
prophecyClaimCount = 0;
operator = _operator;
valset = Valset(_valset);
hasOracle = false;
hasBridgeBank = false;
}
/*
* @dev: setOracle
*/
function setOracle(
address _oracle
)
public
onlyOperator
{
require(
!hasOracle,
"The Oracle cannot be updated once it has been set"
);
hasOracle = true;
oracle = _oracle;
emit LogOracleSet(
oracle
);
}
/*
* @dev: setBridgeBank
*/
function setBridgeBank(
address payable _bridgeBank
)
public
onlyOperator
{
require(
!hasBridgeBank,
"The Bridge Bank cannot be updated once it has been set"
);
hasBridgeBank = true;
bridgeBank = BridgeBank(_bridgeBank);
emit LogBridgeBankSet(
address(bridgeBank)
);
}
/*
* @dev: setNewProphecyClaim
* Sets a new burn or lock prophecy claim, adding it to the prophecyClaims mapping.
* Lock claims can only be created for BridgeTokens on BridgeBank's whitelist. The operator
* is responsible for adding them, and lock claims will fail until the operator has done so.
*/
function setNewProphecyClaim(
bytes32 _claimID,
uint8 _claimType,
bytes memory _ethereumSender,
address payable _chain33Receiver,
address _originalValidator,
address _tokenAddress,
string memory _symbol,
uint256 _amount
)
public
isActive
onlyOracle
{
// Increment the prophecy claim count
prophecyClaimCount = prophecyClaimCount.add(1);
ClaimType claimType = ClaimType(_claimType);
//overwrite the token address in case of lock
if (claimType == ClaimType.Lock) {
_tokenAddress = bridgeBank.getToken2address(_symbol);
}
// Create the new ProphecyClaim
ProphecyClaim memory prophecyClaim = ProphecyClaim(
claimType,
_ethereumSender,
_chain33Receiver,
_originalValidator,
_tokenAddress,
_symbol,
_amount,
Status.Pending
);
// Add the new ProphecyClaim to the mapping
prophecyClaims[_claimID] = prophecyClaim;
emit LogNewProphecyClaim(
prophecyClaimCount,
claimType,
_ethereumSender,
_chain33Receiver,
_originalValidator,
_tokenAddress,
_symbol,
_amount
);
}
/*
* @dev: completeClaim
* Allows for the completion of ProphecyClaims once processed by the Oracle.
* Burn claims unlock tokens stored by BridgeBank.
* Lock claims mint BridgeTokens on BridgeBank's token whitelist.
*/
function completeClaim(
bytes32 _claimID
)
public
isPending(_claimID)
{
require(
msg.sender == oracle,
"Only the Oracle may complete prophecies"
);
prophecyClaims[_claimID].status = Status.Success;
ClaimType claimType = prophecyClaims[_claimID].claimType;
if(claimType == ClaimType.Burn) {
unlockTokens(_claimID);
} else {
issueBridgeTokens(_claimID);
}
emit LogProphecyCompleted(
_claimID,
claimType
);
}
/*
* @dev: issueBridgeTokens
* Issues a request for the BridgeBank to mint new BridgeTokens
*/
function issueBridgeTokens(
bytes32 _claimID
)
internal
{
ProphecyClaim memory prophecyClaim = prophecyClaims[_claimID];
bridgeBank.mintBridgeTokens(
prophecyClaim.ethereumSender,
prophecyClaim.chain33Receiver,
prophecyClaim.tokenAddress,
prophecyClaim.symbol,
prophecyClaim.amount
);
}
/*
* @dev: unlockTokens
* Issues a request for the BridgeBank to unlock funds held on contract
*/
function unlockTokens(
bytes32 _claimID
)
internal
{
ProphecyClaim memory prophecyClaim = prophecyClaims[_claimID];
bridgeBank.unlock(
prophecyClaim.chain33Receiver,
prophecyClaim.tokenAddress,
prophecyClaim.symbol,
prophecyClaim.amount
);
}
/*
* @dev: isProphecyClaimActive
* Returns boolean indicating if the ProphecyClaim is active
*/
function isProphecyClaimActive(
bytes32 _claimID
)
public
view
returns(bool)
{
return prophecyClaims[_claimID].status == Status.Pending;
}
/*
* @dev: isProphecyValidatorActive
* Returns boolean indicating if the validator that originally
* submitted the ProphecyClaim is still an active validator
*/
function isProphecyClaimValidatorActive(
bytes32 _claimID
)
public
view
returns(bool)
{
return valset.isActiveValidator(
prophecyClaims[_claimID].originalValidator
);
}
/*
* @dev: Modifier to make sure the claim type is valid
*/
function isValidClaimType(uint8 _claimType) public pure returns(bool)
{
ClaimType claimType = ClaimType(_claimType);
if (claimType == ClaimType.Burn || claimType == ClaimType.Lock) {
return true;
}
return false;
}
}
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment