Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.idea/
node_modules/
chainbridge-solidity/
chainbridge-solidity/
.DS_Store
deploy/env.sh
deploy/test.env.sh
8 changes: 4 additions & 4 deletions cb-sol-cli/Makefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
SOL_URL=https://github.com/ChainSafe/chainbridge-solidity
SOL_VERSION="v1.0.0"
SOL_URL=https://github.com/RelayChain/chainbridge-solidity
SOL_VERSION="17556d196fc3649afe022320abf085cdbaf1826b"

fetch-contracts:
@echo " > \033[32mFetching chainbridge-solidity contracts... \033[0m "
git clone ${SOL_URL} && cd chainbridge-solidity && git checkout ${SOL_VERSION}

compile:
cd chainbridge-solidity && npm install && npx truffle compile
cd chainbridge-solidity && npm install && npm run compile

install: fetch-contracts compile
@echo " > \033[32mInstalling cb-sol-cli... \033[0m "
npm link .

clean:
rm -rf chainbridge-solidity/
rm -rf chainbridge-solidity/
62 changes: 52 additions & 10 deletions cb-sol-cli/cmd/deploy.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
const ethers = require('ethers');
const {Command} = require('commander');
const constants = require('../constants');
const {setupParentArgs, splitCommaList} = require("./utils")
const {setupParentArgs, splitCommaList, encodeConstructorArgs} = require("./utils")


const deployCmd = new Command("deploy")
.description("Deploys contracts via RPC")
Expand All @@ -18,9 +19,11 @@ const deployCmd = new Command("deploy")
.option('--erc20', 'Deploy erc20 contract')
.option('--erc20Symbol <symbol>', 'Name for the erc20 contract', "")
.option('--erc20Name <name>', 'Symbol for the erc20 contract', "")
.option('--erc20Decimals <number>', 'Number of decimals for ERC20 token', 18)
.option('--erc721', 'Deploy erc721 contract')
.option('--centAsset', 'Deploy centrifuge asset contract')
.option('--wetc', 'Deploy wrapped ETC Erc20 contract')
.option('--zero', 'Deploy Zero contract (not the one from Ethereum, the one we deploy on other chains)')
.option('--config', 'Logs the configuration based on the deployment', false)
.action(async (args) => {
await setupParentArgs(args, args.parent)
Expand Down Expand Up @@ -67,6 +70,10 @@ const deployCmd = new Command("deploy")
await deployWETC(args)
deployed = true
}
if (args.zero) {
await deployZERO(args);
deployed = true;
}

if (!deployed) {
throw new Error("must specify --all or specific contracts to deploy")
Expand All @@ -89,14 +96,33 @@ const createConfig = (args) => {
config.erc20Handler = args.erc20HandlerContract;
config.erc721Handler = args.erc721HandlerContract;
config.genericHandler = args.genericHandlerContract;
config.gasLimit = args.gasLimit.toNumber();
config.maxGasPrice = args.gasPrice.toNumber();
config.gasLimit = eval(args.gasLimit)
config.maxGasPrice = eval(args.gasPrice)
config.startBlock = "0"
config.http = "false"
config.relayers = args.relayers;
const configReady = {
name: "eth",
type: "ethereum",
id: args.chainId,
endpoint: args.url,
from: args.relayers[0],
opts: {
bridge: args.bridgeContract,
erc20Handler: args.erc20HandlerContract,
erc721Handler: args.erc721HandlerContract,
genericHandler: args.genericHandlerContract,
gasLimit: eval(args.gasLimit),
maxGasPrice: eval(args.gasPrice),
startBlock: "0",
http: true,
},
};
const data = JSON.stringify(config, null, 4);
console.log("EVM Configuration, please copy this into your ChainBridge config file:")
console.log(data)
console.log("\nOr maybe this:");
console.log(JSON.stringify(configReady, null, 4));
}

const displayLog = (args) => {
Expand Down Expand Up @@ -133,6 +159,8 @@ Erc721: ${args.erc721Contract ? args.erc721Contract : "Not Deployed"
Centrifuge Asset: ${args.centrifugeAssetStoreContract ? args.centrifugeAssetStoreContract : "Not Deployed"}
----------------------------------------------------------------
WETC: ${args.WETCContract ? args.WETCContract : "Not Deployed"}
----------------------------------------------------------------
ZERO: ${args.ZEROContract ? args.ZEROContract : "Not Deployed"}
================================================================
`)
}
Expand All @@ -142,13 +170,19 @@ async function deployBridgeContract(args) {
// Create an instance of a Contract Factory
let factory = new ethers.ContractFactory(constants.ContractABIs.Bridge.abi, constants.ContractABIs.Bridge.bytecode, args.wallet);

// Deploy
let contract = await factory.deploy(
const arguments = [
args.chainId,
args.relayers,
args.relayerThreshold,
ethers.utils.parseEther(args.fee.toString()),
args.expiry,
args.relayerThreshold
];

const encodedArgs = encodeConstructorArgs(constants.ContractABIs.Bridge, arguments);
console.log('Bridge args:');
console.log(encodedArgs);

// Deploy
let contract = await factory.deploy(
...arguments,
{ gasPrice: args.gasPrice, gasLimit: args.gasLimit}
);
await contract.deployed();
Expand All @@ -158,7 +192,7 @@ async function deployBridgeContract(args) {

async function deployERC20(args) {
const factory = new ethers.ContractFactory(constants.ContractABIs.Erc20Mintable.abi, constants.ContractABIs.Erc20Mintable.bytecode, args.wallet);
const contract = await factory.deploy(args.erc20Name, args.erc20Symbol, { gasPrice: args.gasPrice, gasLimit: args.gasLimit});
const contract = await factory.deploy(args.erc20Name, args.erc20Symbol, args.erc20Decimals, { gasPrice: args.gasPrice, gasLimit: args.gasLimit});
await contract.deployed();
args.erc20Contract = contract.address
console.log("✓ ERC20 contract deployed")
Expand Down Expand Up @@ -214,4 +248,12 @@ async function deployWETC(args) {
console.log("✓ WETC contract deployed")
}

module.exports = deployCmd
async function deployZERO(args) {
const factory = new ethers.ContractFactory(constants.ContractABIs.ZERO.abi, constants.ContractABIs.ZERO.bytecode, args.wallet);
const contract = await factory.deploy({ gasPrice: args.gasPrice, gasLimit: args.gasLimit});
await contract.deployed();
args.ZEROContract = contract.address
console.log("✓ ZERO contract deployed")
}

module.exports = deployCmd
93 changes: 91 additions & 2 deletions cb-sol-cli/cmd/erc20.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,70 @@ const addMinterCmd = new Command("add-minter")
await waitForTx(args.provider, tx.hash)
})

const isMinterCmd = new Command("is-minter")
.description("Check if address is minter to the contract")
.option('--erc20Address <address>', 'ERC20 contract address', constants.ERC20_ADDRESS)
.option('--minter <address>', 'Minter address', constants.relayerAddresses[1])
.action(async function(args) {
await setupParentArgs(args, args.parent.parent)
const erc20Instance = new ethers.Contract(args.erc20Address, constants.ContractABIs.Erc20Mintable.abi, args.wallet);
let MINTER_ROLE = await erc20Instance.MINTER_ROLE();
const res = await erc20Instance.hasRole(MINTER_ROLE, args.minter);
console.log(`${args.minter} ${res ? 'IS' : 'is NOT'} minter for ${args.erc20Address}`);
})

const removeMinterCmd = new Command("remove-minter")
.description("Remove a minter to the contract")
.option('--erc20Address <address>', 'ERC20 contract address', constants.ERC20_ADDRESS)
.option('--minter <address>', 'Minter address', constants.relayerAddresses[1])
.action(async function(args) {
await setupParentArgs(args, args.parent.parent)
const erc20Instance = new ethers.Contract(args.erc20Address, constants.ContractABIs.Erc20Mintable.abi, args.wallet);
let MINTER_ROLE = await erc20Instance.MINTER_ROLE();
log(args, `Removing ${args.minter} as a minter on contract ${args.erc20Address}`);
const tx = await erc20Instance.revokeRole(MINTER_ROLE, args.minter);
await waitForTx(args.provider, tx.hash)
})

const addAdminCmd = new Command("add-admin")
.description("Add a new admin to the contract")
.option('--erc20Address <address>', 'ERC20 contract address', constants.ERC20_ADDRESS)
.option('--admin <address>', 'New admin address', constants.relayerAddresses[1])
.action(async function(args) {
await setupParentArgs(args, args.parent.parent)
const erc20Instance = new ethers.Contract(args.erc20Address, constants.ContractABIs.Erc20Mintable.abi, args.wallet);
const ADMIN_ROLE = await erc20Instance.DEFAULT_ADMIN_ROLE();
log(args, `Adding ${args.admin} as a admin on contract ${args.erc20Address}`);
const tx = await erc20Instance.grantRole(ADMIN_ROLE, args.admin);
await waitForTx(args.provider, tx.hash)
})

const removeAdminCmd = new Command("remove-admin")
.description("Remove admin from the contract")
.option('--erc20Address <address>', 'ERC20 contract address', constants.ERC20_ADDRESS)
.option('--admin <address>', 'admin address to be removed', constants.relayerAddresses[1])
.action(async function(args) {
await setupParentArgs(args, args.parent.parent)
const erc20Instance = new ethers.Contract(args.erc20Address, constants.ContractABIs.Erc20Mintable.abi, args.wallet);
const ADMIN_ROLE = await erc20Instance.DEFAULT_ADMIN_ROLE();
log(args, `Removing ${args.admin} as a admin on contract ${args.erc20Address}`);
const tx = await erc20Instance.revokeRole(ADMIN_ROLE, args.admin);
await waitForTx(args.provider, tx.hash)
})

const isAdminCmd = new Command("is-admin")
.description("Check if address is admin to the contract")
.option('--erc20Address <address>', 'ERC20 contract address', constants.ERC20_ADDRESS)
.option('--admin <address>', 'admin address', constants.relayerAddresses[1])
.action(async function(args) {
await setupParentArgs(args, args.parent.parent)
const erc20Instance = new ethers.Contract(args.erc20Address, constants.ContractABIs.Erc20Mintable.abi, args.wallet);
const ADMIN_ROLE = await erc20Instance.DEFAULT_ADMIN_ROLE();
const res = await erc20Instance.hasRole(ADMIN_ROLE, args.admin);
console.log(`${args.admin} ${res ? 'IS' : 'is NOT'} admin for ${args.erc20Address}`);
})


const approveCmd = new Command("approve")
.description("Approve tokens for transfer")
.option('--amount <value>', "Amount to transfer", 1)
Expand Down Expand Up @@ -62,9 +126,12 @@ const depositCmd = new Command("deposit")
ethers.utils.hexZeroPad(ethers.utils.hexlify((args.recipient.length - 2)/2), 32).substr(2) + // len(recipientAddress) (32 bytes)
args.recipient.substr(2); // recipientAddress (?? bytes)

const fee = await bridgeInstance._fee();

log(args, `Constructed deposit:`)
log(args, ` Resource Id: ${args.resourceId}`)
log(args, ` Amount: ${expandDecimals(args.amount, args.parent.decimals).toHexString()}`)
log(args, ` Fee: ${ethers.utils.formatEther(fee)}`)
log(args, ` len(recipient): ${(args.recipient.length - 2)/ 2}`)
log(args, ` Recipient: ${args.recipient}`)
log(args, ` Raw: ${data}`)
Expand All @@ -75,7 +142,7 @@ const depositCmd = new Command("deposit")
args.dest, // destination chain id
args.resourceId,
data,
{ gasPrice: args.gasPrice, gasLimit: args.gasLimit}
{ value: fee, gasPrice: args.gasPrice, gasLimit: args.gasLimit}
);

await waitForTx(args.provider, tx.hash)
Expand Down Expand Up @@ -143,7 +210,22 @@ const proposalDataHashCmd = new Command("data-hash")
const hash = ethers.utils.solidityKeccak256(["address", "bytes"], [args.handler, data])

log(args, `Hash: ${hash} Data: ${data}`)
})
});

const zeroChangeMinterCmd = new Command("zero-change-minter")
.description("Change minter for ZERO token")
.option('--tokenAddr <address>', 'Address of ZERO token')
.option('--newMinter <address>', 'Address of the new minter')
.action(async args => {
await setupParentArgs(args, args.parent.parent)

console.log(`Setting new minter ${args.newMinter} for ZERO token ${args.tokenAddr}...`);
const zeroToken = new ethers.Contract(args.tokenAddr, constants.ContractABIs.ZERO.abi, args.wallet);
const tx = await zeroToken.changeMinter(args.newMinter, { gasPrice: args.gasPrice, gasLimit: args.gasLimit });
console.log(`Waiting for tx ${tx.hash}...`);
await tx.wait(1);
console.log(`Successfully set new minter ${args.newMinter} for ZERO token ${args.tokenAddr}`);
});

const erc20Cmd = new Command("erc20")
.option('-d, decimals <number>', "The number of decimal places for the erc20 token", 18)
Expand All @@ -156,5 +238,12 @@ erc20Cmd.addCommand(balanceCmd)
erc20Cmd.addCommand(allowanceCmd)
erc20Cmd.addCommand(wetcDepositCmd)
erc20Cmd.addCommand(proposalDataHashCmd)
erc20Cmd.addCommand(removeMinterCmd)
erc20Cmd.addCommand(addAdminCmd)
erc20Cmd.addCommand(removeAdminCmd)
erc20Cmd.addCommand(isMinterCmd)
erc20Cmd.addCommand(isAdminCmd)
erc20Cmd.addCommand(zeroChangeMinterCmd)


module.exports = erc20Cmd
13 changes: 11 additions & 2 deletions cb-sol-cli/cmd/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,20 @@ const expandDecimals = (amount, decimals = 18) => {

const log = (args, msg) => console.log(`[${args.parent._name}/${args._name}] ${msg}`)

function encodeConstructorArgs(contractCode, args) {
const iface = contractCode.abi.filter((i) => i.type === "constructor");
if (iface.length === 0) {
return "0x";
}
return ethers.utils.defaultAbiCoder.encode(iface[0].inputs, args);
}

module.exports = {
setupParentArgs,
splitCommaList,
getFunctionBytes,
waitForTx,
log,
expandDecimals
}
expandDecimals,
encodeConstructorArgs,
}
3 changes: 2 additions & 1 deletion cb-sol-cli/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ const ContractABIs = {
Erc721Mintable: require(CONTRACT_PATH + "/ERC721MinterBurnerPauser.json"),
GenericHandler: require(CONTRACT_PATH + "/GenericHandler.json"),
CentrifugeAssetStore: require(CONTRACT_PATH + "/CentrifugeAsset.json"),
ZERO: require(CONTRACT_PATH + "/ZERO.json"),
WETC: require("./contracts/WETC.json"),
HandlerHelpers: require(CONTRACT_PATH + "/HandlerHelpers.json")
HandlerHelpers: require(CONTRACT_PATH + "/HandlerHelpers.json"),
}

module.exports.ContractABIs = ContractABIs
Expand Down
Loading