EVM deployment scripts and documentation (#141)
* Make Migrations contract Ownable * Add prod deployment migrations * Add BSC Testnet deployment configuration * Add documentation for deploying contracts to production * Fix test environment script for deployment to development network * Fix tilt issues + refactor Co-authored-by: Ali Behjati <bahjatia@gmail.com>
This commit is contained in:
parent
941017de4b
commit
4f4bec508e
|
@ -73,9 +73,9 @@ spec:
|
|||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- "npm run migrate &&
|
||||
npx truffle test test/pyth.js 2>&1 &&
|
||||
nc -lkp 2000 0.0.0.0"
|
||||
- "npm run migrate --network development &&
|
||||
npx truffle test test/pyth.js 2>&1 &&
|
||||
nc -lkp 2000 0.0.0.0"
|
||||
readinessProbe:
|
||||
periodSeconds: 1
|
||||
failureThreshold: 300
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
node_modules
|
||||
build
|
||||
.openzeppelin
|
||||
networks
|
||||
.env
|
|
@ -0,0 +1,7 @@
|
|||
MIGRATIONS_DIR=./migrations/prod
|
||||
MIGRATIONS_NETWORK=binance_testnet
|
||||
|
||||
#Pyth
|
||||
WORMHOME_BRIDGE_ADDRESS=0x68605AD7b15c732a30b1BbC62BE8F2A509D74b4D
|
||||
PYTH_TO_WORMHOLE_CHAIN_ID=0x1
|
||||
PYTH_TO_WORMHOLE_EMITTER=0xf346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0
|
|
@ -0,0 +1,8 @@
|
|||
# Migrations Metadata
|
||||
MIGRATIONS_DIR=./migrations/prod
|
||||
MIGRATIONS_NETWORK=development
|
||||
|
||||
#Pyth
|
||||
WORMHOME_BRIDGE_ADDRESS=0x68605AD7b15c732a30b1BbC62BE8F2A509D74b4D
|
||||
PYTH_TO_WORMHOLE_CHAIN_ID=0x1
|
||||
PYTH_TO_WORMHOLE_EMITTER=0x6bb14509a612f01fbbc4cffeebd4bbfb492a86df717ebe92eb6df432a3f00a25
|
|
@ -14,6 +14,6 @@ BRIDGE_INIT_GOV_CHAIN_ID=0x1
|
|||
BRIDGE_INIT_GOV_CONTRACT=0x0000000000000000000000000000000000000000000000000000000000000004
|
||||
BRIDGE_INIT_WETH=0xDDb64fE46a91D46ee29420539FC25FD07c5FEa3E
|
||||
|
||||
#Pyth Migrations
|
||||
#Pyth
|
||||
PYTH_TO_WORMHOLE_CHAIN_ID=0x1
|
||||
PYTH_TO_WORMHOLE_EMITTER=8fuAZUxHecYLMC76ZNjYzwRybUiDv9LhkRQsAccEykLr
|
||||
PYTH_TO_WORMHOLE_EMITTER=0x71f8dcb863d176e2c420ad6610cf687359612b6fb392e0642b0ca6b1f186aa3b
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# Deploying Contracts to Production
|
||||
|
||||
Running the Truffle migrations in [`migrations/prod`](migrations/prod) will deploy the contracts to production. Truffle stores the address of the deployed contracts in the build artifacts, which can make local development difficult. We use [`truffle-deploy-registry`](https://github.com/MedXProtocol/truffle-deploy-registry) to store the addresses separately from the artifacts, in the [`networks`](networks) directory. When we need to perform operations on the deployed contracts, such as performing additional migrations, we can run `apply-registry -n networks/$NETWORK` to populate the artifacts with the correct addresses.
|
||||
|
||||
An example deployment process, for deploying to Binance Smart Chain Testnet:
|
||||
|
||||
```bash
|
||||
# Load the configuration environment variables for deploying to BSC Testnet.
|
||||
rm -f .env; ln -s .env.prod.binance_testnet .env && set -o allexport && source .env set && set +o allexport
|
||||
|
||||
# The Secret Recovery Phrase for the wallet the contract will be deployed from.
|
||||
export MNEMONIC=...
|
||||
|
||||
# Ensure that we deploy a fresh build with up-to-date dependencies.
|
||||
rm -rf build .openzeppelin node_modules && npm install && npx truffle compile --all
|
||||
|
||||
# Merge the network addresses into the artifacts, if some contracts are already deployed.
|
||||
npx apply-registry -n networks/$MIGRATIONS_NETWORK
|
||||
|
||||
# Perform the migration
|
||||
npx truffle migrate --network $MIGRATIONS_NETWORK
|
||||
|
||||
# Running the migration will cause a JSON file to be written to the networks/
|
||||
# directory, with a filename like 1648198934288.json (the Truffle network ID).
|
||||
# To make it more obvious which network this corresponds to, move this file
|
||||
# to networks/$MIGRATIONS_NETWORK.
|
||||
mkdir -p networks/$MIGRATIONS_NETWORK && mv networks/NETWORK__ID.json networks/$MIGRATIONS_NETWORK
|
||||
```
|
||||
|
||||
As a sanity check, it is recommended to deploy the migrations in `migrations/prod` to the Truffle `development` network first. You can do this by using the configuration values in [`.env.prod.development`](.env.prod.development).
|
|
@ -1,19 +1,14 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity >=0.4.22 <0.9.0;
|
||||
|
||||
contract Migrations {
|
||||
address public owner = msg.sender;
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
|
||||
// Needed for truffle migrate to work correctly.
|
||||
// Simply stores the last completed migration.
|
||||
contract Migrations is Ownable {
|
||||
uint public last_completed_migration;
|
||||
|
||||
modifier restricted() {
|
||||
require(
|
||||
msg.sender == owner,
|
||||
"This function is restricted to the contract's owner"
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
function setCompleted(uint completed) public restricted {
|
||||
function setCompleted(uint completed) public onlyOwner {
|
||||
last_completed_migration = completed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
const Migrations = artifacts.require("Migrations");
|
||||
|
||||
const tdr = require('truffle-deploy-registry');
|
||||
|
||||
module.exports = async function (deployer, network) {
|
||||
await deployer.deploy(Migrations);
|
||||
let migrationsInstance = await Migrations.deployed();
|
||||
|
||||
if (!tdr.isDryRunNetworkName(network)) {
|
||||
await tdr.appendInstance(migrationsInstance);
|
||||
}
|
||||
};
|
|
@ -0,0 +1,35 @@
|
|||
require('dotenv').config({ path: "../.env" });
|
||||
const bs58 = require("bs58");
|
||||
|
||||
const PythUpgradable = artifacts.require("PythUpgradable");
|
||||
|
||||
const wormholeBridgeAddress = process.env.WORMHOME_BRIDGE_ADDRESS;
|
||||
const pyth2WormholeChainId = process.env.PYTH_TO_WORMHOLE_CHAIN_ID;
|
||||
const pyth2WormholeEmitter = process.env.PYTH_TO_WORMHOLE_EMITTER;
|
||||
|
||||
const { deployProxy } = require("@openzeppelin/truffle-upgrades");
|
||||
const tdr = require('truffle-deploy-registry');
|
||||
|
||||
console.log("Wormhole bridge address: " + wormholeBridgeAddress)
|
||||
console.log("pyth2WormholeEmitter: " + pyth2WormholeEmitter)
|
||||
console.log("pyth2WormholeChainId: " + pyth2WormholeChainId)
|
||||
|
||||
module.exports = async function (deployer, network) {
|
||||
// Deploy the proxy. This will return an instance of PythUpgradable,
|
||||
// with the address field corresponding to the fronting ERC1967Proxy.
|
||||
let proxyInstance = await deployProxy(PythUpgradable,
|
||||
[
|
||||
wormholeBridgeAddress,
|
||||
pyth2WormholeChainId,
|
||||
pyth2WormholeEmitter
|
||||
],
|
||||
{ deployer });
|
||||
|
||||
// Add the ERC1967Proxy address to the PythUpgradable contract's
|
||||
// entry in the registry. This allows us to call upgradeProxy
|
||||
// functions with the value of PythUpgradable.deployed().address:
|
||||
// e.g. upgradeProxy(PythUpgradable.deployed().address, NewImplementation)
|
||||
if (!tdr.isDryRunNetworkName(network)) {
|
||||
await tdr.appendInstance(proxyInstance);
|
||||
}
|
||||
};
|
|
@ -5,7 +5,7 @@ const PythUpgradable = artifacts.require("PythUpgradable");
|
|||
const Wormhole = artifacts.require("Wormhole");
|
||||
|
||||
const pyth2WormholeChainId = process.env.PYTH_TO_WORMHOLE_CHAIN_ID;
|
||||
const pyth2WormholeEmitter = bs58.decode(process.env.PYTH_TO_WORMHOLE_EMITTER); // base58, must fit into bytes32
|
||||
const pyth2WormholeEmitter = process.env.PYTH_TO_WORMHOLE_EMITTER;
|
||||
|
||||
const { deployProxy } = require("@openzeppelin/truffle-upgrades");
|
||||
|
||||
|
@ -17,7 +17,7 @@ module.exports = async function (deployer) {
|
|||
[
|
||||
(await Wormhole.deployed()).address,
|
||||
pyth2WormholeChainId,
|
||||
"0x" + pyth2WormholeEmitter.toString("hex")
|
||||
pyth2WormholeEmitter
|
||||
],
|
||||
{ deployer });
|
||||
};
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@openzeppelin/contracts": "^4.5.0",
|
||||
"@openzeppelin/contracts-upgradeable": "^4.5.2",
|
||||
"@pythnetwork/pyth-sdk-solidity": "0.0.3",
|
||||
"dotenv": "^10.0.0",
|
||||
"elliptic": "^6.5.2",
|
||||
"ganache-cli": "^6.12.1",
|
||||
|
@ -19,7 +21,6 @@
|
|||
"devDependencies": {
|
||||
"@chainsafe/truffle-plugin-abigen": "0.0.1",
|
||||
"@openzeppelin/cli": "^2.8.2",
|
||||
"@openzeppelin/contracts": "^4.5.0",
|
||||
"@openzeppelin/test-environment": "^0.1.9",
|
||||
"@openzeppelin/test-helpers": "^0.5.15",
|
||||
"@openzeppelin/truffle-upgrades": "^1.14.0",
|
||||
|
@ -29,6 +30,7 @@
|
|||
"mocha": "^8.2.1",
|
||||
"truffle": "^5.5.5",
|
||||
"truffle-assertions": "^0.9.2",
|
||||
"truffle-deploy-registry": "^0.5.1",
|
||||
"truffle-plugin-verify": "^0.5.11"
|
||||
}
|
||||
},
|
||||
|
@ -2030,8 +2032,7 @@
|
|||
"node_modules/@openzeppelin/contracts": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.5.0.tgz",
|
||||
"integrity": "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA=="
|
||||
},
|
||||
"node_modules/@openzeppelin/contracts-upgradeable": {
|
||||
"version": "4.5.2",
|
||||
|
@ -3672,6 +3673,11 @@
|
|||
"integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@pythnetwork/pyth-sdk-solidity": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-solidity/-/pyth-sdk-solidity-0.0.3.tgz",
|
||||
"integrity": "sha512-4FaoGD4Sizvdm0+8KuQsYzARHa+myNwmFE2GBYxmMcw3zMtwvD7PH0RWM8nK9UyExJ+vyAAth7SbVzyLfN4Yow=="
|
||||
},
|
||||
"node_modules/@redux-saga/core": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.1.3.tgz",
|
||||
|
@ -32672,6 +32678,27 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/truffle-deploy-registry": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/truffle-deploy-registry/-/truffle-deploy-registry-0.5.1.tgz",
|
||||
"integrity": "sha512-ZvyRpn67J67cWTfN5Z+sIryOirzxOuvpS7WO1WJYx3V1GcJR0gWWEM38KTBoPQ5L98/n7XxWC8+TtkOypKEp6A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chalk": "^2.4.2",
|
||||
"commander": "^2.19.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"rimraf": "^2.6.3"
|
||||
},
|
||||
"bin": {
|
||||
"apply-registry": "lib/command.js"
|
||||
}
|
||||
},
|
||||
"node_modules/truffle-deploy-registry/node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/truffle-error": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/truffle-error/-/truffle-error-0.0.5.tgz",
|
||||
|
@ -38580,8 +38607,7 @@
|
|||
"@openzeppelin/contracts": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.5.0.tgz",
|
||||
"integrity": "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-fdkzKPYMjrRiPK6K4y64e6GzULR7R7RwxSigHS8DDp7aWDeoReqsQI+cxHV1UuhAqX69L1lAaWDxenfP+xiqzA=="
|
||||
},
|
||||
"@openzeppelin/contracts-upgradeable": {
|
||||
"version": "4.5.2",
|
||||
|
@ -39972,9 +39998,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"@pythnetwork/pyth-sdk-solidity": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-solidity/-/pyth-sdk-solidity-0.0.2.tgz",
|
||||
"integrity": "sha512-/nxo+HqikNFDbi2dW/GQFJQYLjbe/PZL9x3ILxT4AdM1Nd76ykd+AK5aq08Giz6H4FGGrjsjJH4TtmgPJsUpDw=="
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-solidity/-/pyth-sdk-solidity-0.0.3.tgz",
|
||||
"integrity": "sha512-4FaoGD4Sizvdm0+8KuQsYzARHa+myNwmFE2GBYxmMcw3zMtwvD7PH0RWM8nK9UyExJ+vyAAth7SbVzyLfN4Yow=="
|
||||
},
|
||||
"@redux-saga/core": {
|
||||
"version": "1.1.3",
|
||||
|
@ -66512,6 +66538,26 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"truffle-deploy-registry": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/truffle-deploy-registry/-/truffle-deploy-registry-0.5.1.tgz",
|
||||
"integrity": "sha512-ZvyRpn67J67cWTfN5Z+sIryOirzxOuvpS7WO1WJYx3V1GcJR0gWWEM38KTBoPQ5L98/n7XxWC8+TtkOypKEp6A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.4.2",
|
||||
"commander": "^2.19.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"rimraf": "^2.6.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"truffle-error": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/truffle-error/-/truffle-error-0.0.5.tgz",
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
"devDependencies": {
|
||||
"@chainsafe/truffle-plugin-abigen": "0.0.1",
|
||||
"@openzeppelin/cli": "^2.8.2",
|
||||
"@openzeppelin/contracts": "^4.5.0",
|
||||
"@openzeppelin/test-environment": "^0.1.9",
|
||||
"@openzeppelin/test-helpers": "^0.5.15",
|
||||
"@openzeppelin/truffle-upgrades": "^1.14.0",
|
||||
|
@ -16,6 +15,7 @@
|
|||
"mocha": "^8.2.1",
|
||||
"truffle": "^5.5.5",
|
||||
"truffle-assertions": "^0.9.2",
|
||||
"truffle-deploy-registry": "^0.5.1",
|
||||
"truffle-plugin-verify": "^0.5.11"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -30,6 +30,7 @@
|
|||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@openzeppelin/contracts": "^4.5.0",
|
||||
"@openzeppelin/contracts-upgradeable": "^4.5.2",
|
||||
"@pythnetwork/pyth-sdk-solidity": "0.0.3",
|
||||
"dotenv": "^10.0.0",
|
||||
|
|
|
@ -59,11 +59,13 @@ module.exports = {
|
|||
binance_testnet: {
|
||||
provider: () => new HDWalletProvider(
|
||||
process.env.MNEMONIC,
|
||||
"https://data-seed-prebsc-1-s1.binance.org:8545/"
|
||||
"https://data-seed-prebsc-1-s1.binance.org:8545"
|
||||
),
|
||||
network_id: "97",
|
||||
gas: 70000000,
|
||||
gasPrice: 8000000000,
|
||||
confirmations: 10,
|
||||
networkCheckTimeout: 1000000,
|
||||
timeoutBlocks: 1000,
|
||||
skipDryRun: true,
|
||||
},
|
||||
polygon: {
|
||||
provider: () => {
|
||||
|
|
Loading…
Reference in New Issue