diff --git a/.gitignore b/.gitignore index 3d03d8c49..6a89cf3f7 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ jspm_packages .DS_Store report + +.env diff --git a/buidler.config.js b/buidler.config.js index e7a79f713..08f11271d 100644 --- a/buidler.config.js +++ b/buidler.config.js @@ -151,4 +151,17 @@ module.exports = { mocha: { enableTimeouts: false } -}; \ No newline at end of file +}; + +require('dotenv').config() + +const INFURA_API_KEY = process.env.INFURA_API_KEY +const PRIVATE_KEY = process.env.PRIVATE_KEY + +if (INFURA_API_KEY != undefined && PRIVATE_KEY != undefined) { + module.exports.networks.ropsten = { + url: `https://ropsten.infura.io/v3/${INFURA_API_KEY}`, + accounts: [PRIVATE_KEY], + timeout: 20000 + } +} diff --git a/package-lock.json b/package-lock.json index 277dbb8ff..8de7462e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1303,6 +1303,44 @@ "xhr-request-promise": "^0.1.2" } }, + "ethers": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", + "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", + "dev": true, + "requires": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + }, + "dependencies": { + "@types/node": { + "version": "10.17.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.28.tgz", + "integrity": "sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ==", + "dev": true + }, + "elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + } + } + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -1804,44 +1842,6 @@ "ethers": "4.0.0-beta.3", "underscore": "1.9.1", "web3-utils": "1.2.2" - }, - "dependencies": { - "@types/node": { - "version": "10.17.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.21.tgz", - "integrity": "sha512-PQKsydPxYxF1DsAFWmunaxd3sOi3iMt6Zmx/tgaagHYmwJ/9cRH91hQkeJZaUGWbvn0K5HlSVEXkn5U/llWPpQ==", - "dev": true - }, - "elliptic": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", - "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" - } - }, - "ethers": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", - "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", - "dev": true, - "requires": { - "@types/node": "^10.3.2", - "aes-js": "3.0.0", - "bn.js": "^4.4.0", - "elliptic": "6.3.3", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.3", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - } - } } }, "web3-eth-accounts": { @@ -3418,6 +3418,11 @@ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, "download": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", diff --git a/package.json b/package.json index c9a0fdd75..db128127c 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "chai-as-promised": "7.1.1", "compare-versions": "3.5.1", "ethers": "5.0.4", + "dotenv": "^8.2.0", "ganache-cli": "6.8.2", "mathjs": "4.4.2", "rlp": "2.2.4", diff --git a/web3deployment/reserveDeploy/fpr/README.md b/web3deployment/reserveDeploy/fpr/README.md new file mode 100644 index 000000000..013704083 --- /dev/null +++ b/web3deployment/reserveDeploy/fpr/README.md @@ -0,0 +1,15 @@ + +# Step to deploy reserve: +### Tranditional way: +- config the .env variable *PRIVATE_KEY* +- run command +``` +node web3deployment/reserveDeploy/fpr/enhancedStepsDeployer2.js --rpcUrl https://ropsten.infura.io/v3/YOUR_INFURA_ID --gas-price-gwei 5 +``` + +### Buidler way: +- config the .env varialbe *PRIVATE_KEY* and *INFURA_API_KEY* +- run command +``` +npx buidler run --no-compile --network ropsten web3deployment/reserveDeploy/fpr/enhancedStepsDeployer.js +``` \ No newline at end of file diff --git a/web3deployment/reserveDeploy/fpr/enhancedStepsDeployer.js b/web3deployment/reserveDeploy/fpr/enhancedStepsDeployer.js new file mode 100644 index 000000000..42f5355b7 --- /dev/null +++ b/web3deployment/reserveDeploy/fpr/enhancedStepsDeployer.js @@ -0,0 +1,76 @@ +const KyberReserveHighRate = artifacts.require("KyberReserveHighRate.sol"); +const ConversionRateEnhancedSteps = artifacts.require("ConversionRateEnhancedSteps.sol"); +const WrapConversionRateEnhancedSteps = artifacts.require("WrapConversionRateEnhancedSteps.sol"); + +const BN = web3.utils.BN; + +let reserve; +let reserveAddr; +let conversionRate; +let conversionRateAddr; +let wrapper; +let wrapperAddr; + +let networkAddr = "0x920b322d4b8bab34fb6233646f5c87f87e79952b"; +let admin= "0xf3D872b9E8d314820dc8E99DAfBe1A3FeEDc27D5"; +let deployer; + +async function main() { + const accounts = await web3.eth.getAccounts(); + deployer = accounts[0]; + console.log(`deployer address at ${deployer}`); + + gasPrice = new BN(2).mul(new BN(10).pow(new BN(9))) + + if(conversionRateAddr == undefined) { + conversionRate = await ConversionRateEnhancedSteps.new(deployer, {gasPrice: gasPrice}); + console.log(`deploy conversionRate at ${conversionRate.address}`); + }else { + conversionRate = await ConversionRateEnhancedSteps.at(conversionRateAddr); + } + + if (reserveAddr == undefined){ + reserve = await KyberReserveHighRate.new( + networkAddr, + conversionRate.address, + deployer, + {gasPrice: gasPrice} + ); + console.log(`deploy reserve at ${reserve.address}`); + reserveAddr = reserve.address; + } else { + reserve = await KyberReserveHighRate.at(reserveAddr); + } + + if (wrapperAddr == undefined) { + wrapper = await WrapConversionRateEnhancedSteps.new(conversionRate.address, {gasPrice:gasPrice}); + console.log(`deploy wrapper at ${wrapper.address}`); + wrapperAddr = wrapper.address; + } else { + wrapper = await WrapConversionRateEnhancedSteps.at(wrapperAddr); + } + + if(await conversionRate.admin() != wrapperAddr) { + console.log(`set conversionRate admin to wrapper contract`); + await conversionRate.transferAdmin(wrapperAddr, {gasPrice: gasPrice}); + await wrapper.claimWrappedContractAdmin({gasPrice: gasPrice}); + } + + if(await reserve.admin() != admin) { + console.log(`set new admin to reserve ${admin}`); + await reserve.transferAdminQuickly(admin, {gasPrice: gasPrice}); + } + + if(await wrapper.admin() != admin) { + console.log(`set new admin to wrapper ${admin}`); + await wrapper.transferAdminQuickly(admin, {gasPrice: gasPrice}); + } +} + + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); diff --git a/web3deployment/reserveDeploy/fpr/enhancedStepsDeployer2.js b/web3deployment/reserveDeploy/fpr/enhancedStepsDeployer2.js new file mode 100644 index 000000000..1ebe46307 --- /dev/null +++ b/web3deployment/reserveDeploy/fpr/enhancedStepsDeployer2.js @@ -0,0 +1,191 @@ +const artifacts = require('@nomiclabs/buidler').artifacts + +const KyberReserveHighRate = artifacts.require('KyberReserveHighRate.sol') +const ConversionRateEnhancedSteps = artifacts.require( + 'ConversionRateEnhancedSteps.sol' +) +const WrapConversionRateEnhancedSteps = artifacts.require( + 'WrapConversionRateEnhancedSteps.sol' +) + +const Web3 = require('web3') +const fs = require('fs') +const RLP = require('rlp') +const { fromUtf8 } = require('web3-utils') +const BN = Web3.utils.BN + +const { + gasPriceGwei, + rpcUrl, + chainId: chainIdInput, + privateKey +} = require('yargs') + .usage( + 'Usage: PRIVATE_KEY=xxxx $0 --gas-price-gwei [gwei] --rpc-url [url] --chain-id' + ) + .demandOption(['gasPriceGwei', 'rpcUrl', 'privateKey']) + .env(true) + .boolean('dontSendTx').argv + +console.log(rpcUrl) + +let web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl)) + +let reserve +let reserveAddr //= "0xc4b5C2B1d8922B324024A8e7CA1216d1460376Bd" +let conversionRate +let conversionRateAddr // = "0x80a932DFd1DA618d1f6d446CC676F68Aac1b9f6C" +let wrapper +let wrapperAddr //= "0xc3Caa675F718E84e05EA0Da649987d3AafE17b96" + +let networkAddr = '0x9cb7bb6d4795a281860b9bfb7b1441361cc9a794' +let admin = '0xf3D872b9E8d314820dc8E99DAfBe1A3FeEDc27D5' +// let deployer + +const account = web3.eth.accounts.privateKeyToAccount(privateKey) +const sender = account.address +const gasPrice = new BN(gasPriceGwei).mul(new BN(10).pow(new BN(9))) +const signedTxs = [] +let nonce +let chainId = chainIdInput + +process.on('unhandledRejection', console.error.bind(console)) + +console.log('from', sender) + +async function sendTx (txObject, gasLimit) { + const txTo = txObject._parent.options.address + + try { + gasLimit = gasLimit == undefined ? await txObject.estimateGas() : gasLimit + gasLimit = Math.round(1.1 * gasLimit) + } catch (e) { + gasLimit = 800000 + } + + if (txTo !== null) { + gasLimit = 800000 + } + + const txData = txObject.encodeABI() + const txFrom = account.address + const txKey = account.privateKey + + const tx = { + from: txFrom, + to: txTo, + nonce: nonce, + data: txData, + gas: gasLimit, + chainId, + gasPrice + } + + const signedTx = await web3.eth.accounts.signTransaction(tx, txKey) + nonce++ + // don't wait for confirmation + signedTxs.push(signedTx.rawTransaction) + web3.eth.sendSignedTransaction(signedTx.rawTransaction, { + from: sender + }) +} + +async function deployContract (contract, ctorArgs) { + const bytecode = contract.bytecode + const abi = contract.abi + const myContract = new web3.eth.Contract(abi) + + const deploy = myContract.deploy({ data: bytecode, arguments: ctorArgs }) + let address = + '0x' + + web3.utils + .sha3(RLP.encode([sender, nonce])) + .slice(12) + .substring(14) + address = web3.utils.toChecksumAddress(address) + + await sendTx(deploy, 6500000) + + myContract.options.address = address + + return [address, myContract] +} + +const keypress = async () => { + process.stdin.setRawMode(true) + return new Promise(resolve => + process.stdin.once('data', data => { + const byteArray = [...data] + if (byteArray.length > 0 && byteArray[0] === 3) { + console.log('^C') + process.exit(1) + } + process.stdin.setRawMode(false) + resolve() + }) + ) +} + +async function main () { + nonce = await web3.eth.getTransactionCount(sender) + console.log('nonce', nonce) + chainId = chainId || (await web3.eth.net.getId()) + console.log('chainId', chainId) + + web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl)) + + if (conversionRateAddr == undefined) { + [conversionRateAddr, conversionRate] = await deployContract( + ConversionRateEnhancedSteps, + [sender] + ) + console.log(`deploy conversionRate at ${conversionRateAddr}`) + } else { + conversionRate = new web3.eth.Contract( + ConversionRateEnhancedSteps.abi, + conversionRateAddr + ) + } + + if (reserveAddr == undefined) { + [reserveAddr, reserve] = await deployContract(KyberReserveHighRate, [ + networkAddr, + conversionRateAddr, + sender + ]) + console.log(`deploy reserve at ${reserveAddr}`) + } else { + reserve = new web3.eth.Contract(KyberReserveHighRate.abi, reserveAddr) + } + + if (wrapperAddr == undefined) { + [wrapperAddr, wrapper] = await deployContract( + WrapConversionRateEnhancedSteps, + [conversionRateAddr] + ) + console.log(`deploy wrapper at ${wrapperAddr}`) + } else { + wrapper = new web3.eth.Contract( + WrapConversionRateEnhancedSteps.abi, + wrapperAddr + ) + } + + console.log(`set conversionRate admin to wrapper contract`) + await sendTx(conversionRate.methods.setReserveAddress(reserveAddr)) + await sendTx(conversionRate.methods.transferAdmin(wrapperAddr)) + await sendTx(wrapper.methods.claimWrappedContractAdmin()) + + console.log(`set admin to new admin`) + await sendTx(wrapper.methods.transferAdminQuickly(admin)) + await sendTx(reserve.methods.transferAdminQuickly(admin)) + + await keypress() +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error) + process.exit(1) + })