Skip to content

Commit

Permalink
* Add privkeys to avash block in hardhat config.
Browse files Browse the repository at this point in the history
* Add `avalanche` dependency to package.json.
* Add `fund-cchain-addresses.js`.
* Add `fund-cchain-addresses` yarn script.
* Add typical avash workflow.
  • Loading branch information
cgcardona committed Mar 2, 2021
1 parent 9637097 commit ab16341
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 20 deletions.
99 changes: 88 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,28 @@

Avalanche is an open-source platform for launching decentralized applications and enterprise blockchain deployments in one interoperable, highly scalable ecosystem. Avalanche gives you complete control on both the network and application layers—helping you build anything you can imagine.

Avalanche can do anything a typical Ethereum client can by using the Ethereum-standard RPC calls. The immediate benefits of using the Avalanche rather than Ethereum are speed, scale and throughput. Avalanche offers thousands of transactions per second with sub-second finality at inexpensive fees. These properties will considerably improve the performance of DApps and the user experience of smart-contracts.
Avalanche can do anything a typical Ethereum client can by using the Ethereum-standard RPC calls. The immediate benefits of using Avalanche rather than Ethereum are speed, scale and throughput. Avalanche offers thousands of transactions per second with sub-second finality at inexpensive fees. These properties will considerably improve the performance of DApps and the user experience of smart-contracts.

The goal of this guide is to lay out a best-practices regarding writing, testing and deploying smart-contracts to Avalanche. We'll be building smart contracts with [Hardhat](https://hardhat.org) which is an Avalanche development environment for professionals.

## Prerequisites

First install the LTS of [nodejs](https://nodejs.org/en) which is `14.15.4` at the time of writing. NodeJS bundles `npm`. Next install [yarn](https://yarnpkg.com)
### NodeJS and Yarn

First install the LTS of [nodejs](https://nodejs.org/en) which is `14.15.4` at the time of writing. NodeJS bundles `npm`.

Next install [yarn](https://yarnpkg.com):

```zsh
npm install -g yarn
```

### AvalancheGo and Avash

[AvalancheGo](https://github.com/ava-labs/avalanchego) is our full node written in Golang. [Avash](https://docs.avax.network/build/tools/avash) is our local test network. Together, you can deploy private local networks and run tests on them.

### Solidity and Avalanche

It is also helpful to have a basic understanding of [Solidity](https://docs.soliditylang.org) and [Avalanche](https://docs.avax.network).

## Dependencies
Expand Down Expand Up @@ -46,23 +56,22 @@ Run `yarn compile` to make sure your project compiles.

Edit the deployment script in `scripts/deploy.js`

## Deploy to the hardhat test network
## Deploy

In [`package.json`](./package.json) there are scripts for deploying to [avash](https://github.com/ava-labs/avash), `fuji` and `mainnet`.
Hardhat enables deploying to multiple environments. In [`package.json`](./package.json) there are scripts for deploying to the [hardhat network](https://hardhat.org/hardhat-network), [avash](https://github.com/ava-labs/avash), `fuji` and `mainnet`.

```json
"test-deploy": "npx hardhat run scripts/deploy.js",
"deploy": "npx hardhat run scripts/deploy.js --network mainnet",
"deploy-hardhat-network": "npx hardhat run scripts/deploy.js",
"deploy-avash": "npx hardhat run scripts/deploy.js --network avash",
"deploy-fuji": "npx hardhat run scripts/deploy.js --network fuji",
"deploy": "npx hardhat run scripts/deploy.js --network mainnet",
```

Deploy your contract to the hardhat network with `yarn test-deploy`.
Deploy your contract to the Avalanche `fuji` testnet with `yarn deploy-fuji`.

## Deploy to Fuji or Mainnet
To deploy to avash, `fuji` or `mainnet` you need to add your private key(s) to the `accounts` field in [hardhat.config.js](./hardhat.config.js).

You need to add your private key to the accounts field in [hardhat.config.js](./hardhat.config.js).

Then run `yarn deploy` for mainnet or `yarn deploy-fuji` for fuji.
Then run `yarn deploy` for mainnet, `yarn deploy-fuji` for fuji, `yarn deploy-avash` for avash and `yarn deploy-hardhat-network` for the hardhat network.

## Hardhat Tasks

Expand All @@ -88,3 +97,71 @@ Run it with `yarn send-avax`.
## Hardhat Help

You can run `yarn hardhat` to list hardhat version, usage instructions, global options and available tasks.

## Typical avash workflow

First confirm you have the latest and greatest AvalancheGo built.

```zsh
cd /path/to/avalanchego
git fetch -p
git checkout master
./scripts/build.sh
```

Next fire up avash and run a script to configure your network.

```zsh
cd /path/to/avash
git fetch -p
git checkout master
go build
./avash
Config file set: /Users/username/.avash.yaml
Avash successfully configured.
avash> runscript scripts/five_node_staking.lua
RunScript: Running scripts/five_node_staking.lua
RunScript: Successfully ran scripts/five_node_staking.lua
```

Now you have a local avalanche network with 5 staking nodes. Next transfer 1000 AVAX from the X-Chain to each of the 10 avash accounts in `hardhat.config.js`.

```zsh
cd /path/to/avalanche-smart-contract-quickstart
yarn fund-cchain-addresses
yarn run v1.22.4
$ npx hardhat run scripts/fund-cchain-addresses.js --network avash
Exporting 1000 AVAX to each address on the C-Chain...
2b75ae74ScLkWe5GVFTYJoP2EniMywkcZySQUoFGN2EJLiPDgp
Importing AVAX to the C-Chain...
2dyXcQGiCk1ckCX4Fs8nLgL8GJgsM72f9Ga13rX5v9TAguVJYM
✨ Done in 5.03s.
```

Confirm each of the accounts are funded with 1000 AVAX.

```zsh
yarn balances
yarn run v1.22.4
$ npx hardhat balances
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has balance 10000000000000000000000
0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has balance 10000000000000000000000
0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has balance 10000000000000000000000
0x90F79bf6EB2c4f870365E785982E1f101E93b906 has balance 10000000000000000000000
0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has balance 10000000000000000000000
0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc has balance 10000000000000000000000
0x976EA74026E726554dB657fA54763abd0C3a0aa9 has balance 10000000000000000000000
0x14dC79964da2C08b23698B3D3cc7Ca32193d9955 has balance 10000000000000000000000
0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f has balance 10000000000000000000000
0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 has balance 10000000000000000000000
0xBcd4042DE499D14e55001CcbB24a551F3b954096 has balance 10000000000000000000000
0x71bE63f3384f5fb98995898A86B02Fb2426c5788 has balance 10000000000000000000000
0xFABB0ac9d68B0B445fB7357272Ff202C5651694a has balance 10000000000000000000000
0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec has balance 10000000000000000000000
0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097 has balance 10000000000000000000000
0xcd3B766CCDd6AE721141F452C550Ca635964ce71 has balance 10000000000000000000000
0x2546BcD3c84621e976D8185a91A922aE77ECEc30 has balance 10000000000000000000000
0xbDA5747bFD65F08deb54cb465eB87D40e51B197E has balance 10000000000000000000000
0xdD2FD4581271e230360230F9337D5c0430Bf44C0 has balance 10000000000000000000000
0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199 has balance 10000000000000000000000
```
20 changes: 14 additions & 6 deletions hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,30 @@ module.exports = {
url: 'http://localhost:9650/ext/bc/C/rpc',
gasPrice: 470000000000,
chainId: 43112,
accounts: ["0x56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027",
]
accounts: [
"0x56289e99c94b6912bfc12adc093c9b51124f0dc54ac7a766b2bc5ccf558d8027",
"0x7b4198529994b0dc604278c99d153cfd069d594753d471171a1d102a10438e07",
"0x15614556be13730e9e8d6eacc1603143e7b96987429df8726384c2ec4502ef6e",
"0x31b571bf6894a248831ff937bb49f7754509fe93bbd2517c9c73c4144c0e97dc",
"0x6934bef917e01692b789da754a0eae31a8536eb465e7bff752ea291dad88c675",
"0xe700bdbdbc279b808b1ec45f8c2370e4616d3a02c336e68d85d4668e08f53cff",
"0xbbc2865b76ba28016bc2255c7504d000e046ae01934b04c694592a6276988630",
"0xcdbfd34f687ced8c6968854f8a99ae47712c4f4183b78dcc4a903d1bfe8cbf60",
"0x86f78c5416151fe3546dece84fda4b4b1e36089f2dbc48496faf3a950f16157c",
"0x750839e9dbbd2a0910efe40f50b2f3b2f2f59f5580bb4b83bd8c1201cf9a010a"
]
},
fuji: {
url: 'https://api.avax-test.network/ext/bc/C/rpc',
gasPrice: 470000000000,
chainId: 43113,
accounts: [
]
accounts: []
},
mainnet: {
url: 'https://api.avax.network/ext/bc/C/rpc',
gasPrice: 470000000000,
chainId: 43114,
accounts: [
]
accounts: []
}
}
};
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"@nomiclabs/hardhat-ethers": "^2.0.1",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@openzeppelin/contracts": "^3.3.0",
"avalanche": "3.2.0",
"chai": "^4.2.0",
"ethereum-waffle": "^3.2.1",
"ethereumjs-tx": "^2.1.2",
Expand All @@ -21,14 +22,16 @@
"compile": "npx hardhat compile",
"pretest": "yarn compile",
"test": "npx hardhat test",
"test-deploy": "npx hardhat run scripts/deploy.js",
"deploy": "npx hardhat run scripts/deploy.js --network mainnet",
"deploy-hardhat-network": "npx hardhat run scripts/deploy.js",
"deploy-avash": "npx hardhat run scripts/deploy.js --network avash",
"deploy-fuji": "npx hardhat run scripts/deploy.js --network fuji",
"deploy": "npx hardhat run scripts/deploy.js --network mainnet",
"send-avax": "npx hardhat run scripts/sendAvax.js",
"lint": "prettier ./test/**/*.ts --check",
"prepublishOnly": "yarn test",
"hardhat": "npx hardhat",
"accounts": "npx hardhat accounts",
"balances": "npx hardhat balances"
"balances": "npx hardhat balances",
"fund-cchain-addresses": "npx hardhat run scripts/fund-cchain-addresses.js --network avash"
}
}
123 changes: 123 additions & 0 deletions scripts/fund-cchain-addresses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const avalanche_1 = require("avalanche");
const avm_1 = require("avalanche/dist/apis/avm");
const evm_1 = require("avalanche/dist/apis/evm");
const utils_1 = require("avalanche/dist/utils");
const sleep = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms));
};
const ip = "localhost";
const port = 9650;
const protocol = "http";
const networkID = 12345;
const avalanche = new avalanche_1.Avalanche(ip, port, protocol, networkID);
const mstimeout = 3000;
const xchain = avalanche.XChain();
const cchain = avalanche.CChain();
const bintools = avalanche_1.BinTools.getInstance();
const xKeychain = xchain.keyChain();
const cKeychain = cchain.keyChain();
const privKeys = [
"PrivateKey-ewoqjP7PxY4yr3iLTpLisriqt94hdyDFNgchSxGGztUrTXtNN",
"PrivateKey-wHR4zmr9am94KVYnV2aRR4QXt78cuGebt1GpYNwJYEbfAGonj",
"PrivateKey-AR874kuHtHpDk7ntffuEQ9cwiQLL2dz1DmJankW1EyXnz5fc7",
"PrivateKey-Ntk8vV7zaWzAot2wuDXK4e9ZGFUnU49AYTDew5XUyYaNz2u9d",
"PrivateKey-oLM8XbXxXmBHVbdKm2tRYQ1WdMj3b2NggftQpvDUXWSMtdY4i",
"PrivateKey-2kjfDc9RVUQJnu3HQDGiVdxvhM9BmR3UTx7Aq8AJ82G2MspATy",
"PrivateKey-2Rh5Gtu28ca7PS6rLfN6uou9ext8Y5xhoAJDdWPU7GESBLHtv6",
"PrivateKey-2ZcbEPKkXjswsNRBGViGzruReAtTAxW9hsGeMc2GgppnJnDgne",
"PrivateKey-22SYvqaRgFtPJfiZmswrCyE57UcssLVnNPDJ48PYAiCjKVAGy7",
"PrivateKey-tYRsRPijLo6KD2azMLzkcB2ZUndU3a2dJ8kEqBtqesa85pWhB",
];
privKeys.forEach((privKey) => {
xKeychain.importKey(privKey);
cKeychain.importKey(privKey);
});
const xAddresses = xchain.keyChain().getAddresses();
const xAddressStrings = xchain.keyChain().getAddressStrings();
const cAddressStrings = cchain.keyChain().getAddressStrings();
const cAddresses = cchain.keyChain().getAddresses();
const cHexAddresses = [
"0x8db97C7cEcE249c2b98bDC0226Cc4C2A57BF52FC",
"0x9632a79656af553f58738b0fb750320158495942",
"0x55ee05df718f1a5c1441e76190eb1a19ee2c9430",
"0x4cf2ed3665f6bfa95ce6a11cfdb7a2ef5fc1c7e4",
"0x0b891db1901d4875056896f28b6665083935c7a8",
"0x01f253be2ebf0bd64649fa468bf7b95ca933bde2",
"0x78A23300E04FB5d5D2820E23cc679738982e1fd5",
"0x3c7dae394bbf8e9ee1359ad14c1c47003bd06293",
"0x61e0b3cd93f36847abbd5d40d6f00a8ec6f3cffb",
"0x0fa8ea536be85f32724d57a37758761b86416123",
];
const cChainBlockchainID = utils_1.Defaults.network['12345'].C.blockchainID;
const cChainBlockchainIdBuf = bintools.cb58Decode(cChainBlockchainID);
const xChainBlockchainID = utils_1.Defaults.network['12345'].X.blockchainID;
const xChainBlockchainIdBuf = bintools.cb58Decode(xChainBlockchainID);
const exportedOuts = [];
const outputs = [];
const inputs = [];
const importedIns = [];
const evmOutputs = [];
const fee = xchain.getDefaultTxFee();
const locktime = new avalanche_1.BN(0);
const threshold = 1;
const memo = bintools.stringToBuffer("AVM utility method buildExportTx to export AVAX to the C-Chain from the X-Chain");
const main = async () => {
const avaxAssetID = await xchain.getAVAXAssetID();
const getBalanceResponse = await xchain.getBalance(xAddressStrings[0], bintools.cb58Encode(avaxAssetID));
const balance = new avalanche_1.BN(getBalanceResponse.balance);
const avmUTXOResponse = await xchain.getUTXOs(xAddressStrings);
const avmUTXOSet = avmUTXOResponse.utxos;
const avmUTXOs = avmUTXOSet.getAllUTXOs();
// 1,000 AVAX
const amount = new avalanche_1.BN(1000000000000);
console.log("Exporting 1000 AVAX to each address on the C-Chain...");
let secpTransferOutput = new avm_1.SECPTransferOutput(amount.mul(new avalanche_1.BN(10)), [cAddresses[0]], locktime, threshold);
let transferableOutput = new avm_1.TransferableOutput(avaxAssetID, secpTransferOutput);
exportedOuts.push(transferableOutput);
secpTransferOutput = new avm_1.SECPTransferOutput(balance.sub(amount.mul(new avalanche_1.BN(10))).sub(fee), xAddresses, locktime, threshold);
transferableOutput = new avm_1.TransferableOutput(avaxAssetID, secpTransferOutput);
outputs.push(transferableOutput);
avmUTXOs.forEach((utxo) => {
const amountOutput = utxo.getOutput();
const amt = amountOutput.getAmount().clone();
const txid = utxo.getTxID();
const outputidx = utxo.getOutputIdx();
const secpTransferInput = new avm_1.SECPTransferInput(amt);
secpTransferInput.addSignatureIdx(0, xAddresses[0]);
const input = new avm_1.TransferableInput(txid, outputidx, avaxAssetID, secpTransferInput);
inputs.push(input);
});
const exportTx = new avm_1.ExportTx(networkID, bintools.cb58Decode(xChainBlockchainID), outputs, inputs, memo, bintools.cb58Decode(cChainBlockchainID), exportedOuts);
const avmUnsignedTx = new avm_1.UnsignedTx(exportTx);
const avmTx = avmUnsignedTx.sign(xKeychain);
const avmTXID = await xchain.issueTx(avmTx);
console.log(avmTXID);
await sleep(mstimeout);
console.log("Importing AVAX to the C-Chain...");
const u = await cchain.getUTXOs(cAddressStrings[0], "X");
const utxoSet = u.utxos;
const utxos = utxoSet.getAllUTXOs();
utxos.forEach((utxo, index) => {
const assetID = utxo.getAssetID();
const txid = utxo.getTxID();
const outputidx = utxo.getOutputIdx();
const output = utxo.getOutput();
const amt = output.getAmount().clone();
const input = new evm_1.SECPTransferInput(amt);
input.addSignatureIdx(0, cAddresses[0]);
const xferin = new evm_1.TransferableInput(txid, outputidx, assetID, input);
importedIns.push(xferin);
cHexAddresses.forEach((cHexAddress) => {
const evmOutput = new evm_1.EVMOutput(cHexAddress, amt.div(new avalanche_1.BN(10)), assetID);
evmOutputs.push(evmOutput);
});
});
const importTx = new evm_1.ImportTx(networkID, cChainBlockchainIdBuf, xChainBlockchainIdBuf, importedIns, evmOutputs);
const evmUnsignedTx = new evm_1.UnsignedTx(importTx);
const evmTx = evmUnsignedTx.sign(cKeychain);
const evmTXID = await cchain.issueTx(evmTx);
console.log(evmTXID);
};
main();

0 comments on commit ab16341

Please sign in to comment.