-
Notifications
You must be signed in to change notification settings - Fork 608
Removes web3 from the purge script #1341
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6436229
3217cb3
c5fca4b
c94dc18
d0aa5b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
const ethers = require('ethers'); | ||
const { appendOwnerActionGenerator, confirmAction, stringify } = require('../util'); | ||
const { gray, yellow, green, redBright } = require('chalk'); | ||
|
||
let _dryRunCounter = 0; | ||
|
||
/** | ||
* Run a single transaction step, first checking to see if the value needs | ||
* changing at all, and then whether or not its the owner running it. | ||
* | ||
* @returns transaction hash if successful, true if user completed, or falsy otherwise | ||
*/ | ||
const performTransactionalStep = async ({ | ||
account, | ||
contract, | ||
target, | ||
read, | ||
readArg, // none, 1 or an array of args, array will be spread into params | ||
expected, | ||
write, | ||
writeArg, // none, 1 or an array of args, array will be spread into params | ||
gasLimit, | ||
gasPrice, | ||
etherscanLinkPrefix, | ||
ownerActions, | ||
ownerActionsFile, | ||
dryRun, | ||
encodeABI, | ||
nonceManager, | ||
publiclyCallable, | ||
}) => { | ||
const argumentsForWriteFunction = [].concat(writeArg).filter(entry => entry !== undefined); // reduce to array of args | ||
const action = `${contract}.${write}(${argumentsForWriteFunction.map(arg => | ||
arg.length === 66 ? ethers.utils.toUtf8String(arg) : arg | ||
)})`; | ||
|
||
// check to see if action required | ||
console.log(yellow(`Attempting action: ${action}`)); | ||
|
||
if (read) { | ||
const argumentsForReadFunction = [].concat(readArg).filter(entry => entry !== undefined); // reduce to array of args | ||
const response = await target[read](...argumentsForReadFunction); | ||
|
||
if (expected(response)) { | ||
console.log(gray(`Nothing required for this action.`)); | ||
return { noop: true }; | ||
} | ||
} | ||
// otherwise check the owner | ||
const owner = await target.owner(); | ||
if (owner === account.address || publiclyCallable) { | ||
// perform action | ||
let hash; | ||
let gasUsed = 0; | ||
if (dryRun) { | ||
_dryRunCounter++; | ||
hash = '0x' + _dryRunCounter.toString().padStart(64, '0'); | ||
} else { | ||
const params = { | ||
gasLimit, | ||
gasPrice: ethers.utils.parseUnits(gasPrice.toString(), 'gwei'), | ||
}; | ||
|
||
if (nonceManager) { | ||
params.nonce = await nonceManager.getNonce(); | ||
} | ||
|
||
target = target.connect(account); | ||
|
||
const tx = await target[write](...argumentsForWriteFunction, params); | ||
const receipt = await tx.wait(); | ||
|
||
hash = receipt.transactionHash; | ||
gasUsed = receipt.gasUsed; | ||
|
||
if (nonceManager) { | ||
nonceManager.incrementNonce(); | ||
} | ||
} | ||
|
||
console.log( | ||
green( | ||
`${ | ||
dryRun ? '[DRY RUN] ' : '' | ||
}Successfully completed ${action} in hash: ${hash}. Gas used: ${(gasUsed / 1e6).toFixed( | ||
2 | ||
)}m ` | ||
) | ||
); | ||
|
||
return { mined: true, hash }; | ||
} else { | ||
console.log(gray(` > Account ${account.address} is not owner ${owner}`)); | ||
} | ||
|
||
let data; | ||
if (ownerActions && ownerActionsFile) { | ||
// append to owner actions if supplied | ||
const appendOwnerAction = appendOwnerActionGenerator({ | ||
ownerActions, | ||
ownerActionsFile, | ||
etherscanLinkPrefix, | ||
}); | ||
|
||
data = target.interface.encodeFunctionData(write, argumentsForWriteFunction); | ||
|
||
const ownerAction = { | ||
key: action, | ||
target: target.address, | ||
action: `${write}(${argumentsForWriteFunction})`, | ||
data: data, | ||
}; | ||
|
||
if (dryRun) { | ||
console.log( | ||
gray(`[DRY RUN] Would append owner action of the following:\n${stringify(ownerAction)}`) | ||
); | ||
} else { | ||
appendOwnerAction(ownerAction); | ||
} | ||
return { pending: true }; | ||
} else { | ||
// otherwise wait for owner in real time | ||
try { | ||
data = target.interface.encodeFunctionData(write, argumentsForWriteFunction); | ||
if (encodeABI) { | ||
console.log(green(`Tx payload for target address ${target.address} - ${data}`)); | ||
return { pending: true }; | ||
} | ||
|
||
await confirmAction( | ||
redBright( | ||
`Confirm: Invoke ${write}(${argumentsForWriteFunction}) via https://gnosis-safe.io/app/#/safes/${owner}/transactions` + | ||
`to recipient ${target.address}` + | ||
`with data: ${data}` | ||
) + '\nPlease enter Y when the transaction has been mined and not earlier. ' | ||
); | ||
|
||
return { pending: true }; | ||
} catch (err) { | ||
console.log(gray('Cancelled')); | ||
return {}; | ||
} | ||
} | ||
}; | ||
|
||
module.exports = { | ||
performTransactionalStep, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
'use strict'; | ||
|
||
const { gray, green, yellow, red, cyan } = require('chalk'); | ||
const Web3 = require('web3'); | ||
const w3utils = require('web3-utils'); | ||
const ethers = require('ethers'); | ||
const axios = require('axios'); | ||
|
||
const { | ||
toBytes32, | ||
getUsers, | ||
constants: { CONFIG_FILENAME, DEPLOYMENT_FILENAME }, | ||
} = require('../../..'); | ||
|
||
|
@@ -17,9 +17,10 @@ const { | |
loadAndCheckRequiredSources, | ||
loadConnections, | ||
confirmAction, | ||
performTransactionalStep, | ||
} = require('../util'); | ||
|
||
const { performTransactionalStep } = require('../command-utils/transact'); | ||
|
||
const DEFAULTS = { | ||
network: 'kovan', | ||
gasLimit: 3e6, | ||
|
@@ -39,6 +40,7 @@ const purgeSynths = async ({ | |
addresses = [], | ||
batchSize = DEFAULTS.batchSize, | ||
proxyAddress, | ||
useFork, | ||
}) => { | ||
ensureNetwork(network); | ||
deploymentPath = deploymentPath || getDeploymentPathForNetwork({ network }); | ||
|
@@ -50,7 +52,7 @@ const purgeSynths = async ({ | |
}); | ||
|
||
if (synthsToPurge.length < 1) { | ||
console.log(gray('No synths provided. Please use --synths-to-remove option')); | ||
console.log(gray('No synths provided. Please use --synths-to-purge option')); | ||
return; | ||
} | ||
|
||
|
@@ -75,17 +77,27 @@ const purgeSynths = async ({ | |
|
||
const { providerUrl, privateKey: envPrivateKey, etherscanLinkPrefix } = loadConnections({ | ||
network, | ||
useFork, | ||
}); | ||
|
||
// allow local deployments to use the private key passed as a CLI option | ||
if (network !== 'local' || !privateKey) { | ||
privateKey = envPrivateKey; | ||
} | ||
|
||
const web3 = new Web3(new Web3.providers.HttpProvider(providerUrl)); | ||
web3.eth.accounts.wallet.add(privateKey); | ||
const account = web3.eth.accounts.wallet[0].address; | ||
console.log(gray(`Using account with public key ${account}`)); | ||
console.log(gray(`Provider url: ${providerUrl}`)); | ||
const provider = new ethers.providers.JsonRpcProvider(providerUrl); | ||
|
||
let wallet; | ||
if (useFork) { | ||
const account = getUsers({ network, user: 'owner' }).address; // protocolDAO | ||
wallet = provider.getSigner(account); | ||
} else { | ||
wallet = new ethers.Wallet(privateKey, provider); | ||
} | ||
console.log(wallet); | ||
if (!wallet.address) wallet.address = wallet._address; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @leomassazza we should probably think a little more about this. |
||
console.log(gray(`Using account with public key ${wallet.address}`)); | ||
console.log(gray(`Using gas of ${gasPrice} GWEI with a max of ${gasLimit}`)); | ||
|
||
console.log(gray('Dry-run:'), dryRun ? green('yes') : yellow('no')); | ||
|
@@ -109,7 +121,7 @@ const purgeSynths = async ({ | |
|
||
const { address: synthetixAddress, source } = deployment.targets['Synthetix']; | ||
const { abi: synthetixABI } = deployment.sources[source]; | ||
const Synthetix = new web3.eth.Contract(synthetixABI, synthetixAddress); | ||
const Synthetix = new ethers.Contract(synthetixAddress, synthetixABI, wallet); | ||
|
||
let totalBatches = 0; | ||
for (const currencyKey of synthsToPurge) { | ||
|
@@ -118,7 +130,7 @@ const purgeSynths = async ({ | |
]; | ||
|
||
const { abi: synthABI } = deployment.sources[synthSource]; | ||
const Synth = new web3.eth.Contract(synthABI, synthAddress); | ||
const Synth = new ethers.Contract(synthAddress, synthABI, wallet); | ||
proxyAddress = proxyAddress || deployment.targets[`Proxy${currencyKey}`].address; | ||
|
||
console.log( | ||
|
@@ -134,7 +146,7 @@ const purgeSynths = async ({ | |
) | ||
); | ||
|
||
const currentSynthInSNX = await Synthetix.methods.synths(toBytes32(currencyKey)).call(); | ||
const currentSynthInSNX = await Synthetix.synths(toBytes32(currencyKey)); | ||
|
||
if (synthAddress !== currentSynthInSNX) { | ||
console.error( | ||
|
@@ -162,13 +174,13 @@ const purgeSynths = async ({ | |
console.log(gray(`Found ${topTokenHolders.length} possible holders of ${currencyKey}`)); | ||
// Filter out any 0 holder | ||
const supplyPerEntry = await Promise.all( | ||
topTokenHolders.map(entry => Synth.methods.balanceOf(entry).call()) | ||
topTokenHolders.map(entry => Synth.balanceOf(entry)) | ||
); | ||
addresses = topTokenHolders.filter((e, i) => supplyPerEntry[i] !== '0'); | ||
console.log(gray(`Filtered to ${addresses.length} with supply`)); | ||
} | ||
|
||
const totalSupplyBefore = w3utils.fromWei(await Synth.methods.totalSupply().call()); | ||
const totalSupplyBefore = ethers.utils.formatEther(await Synth.totalSupply()); | ||
|
||
if (Number(totalSupplyBefore) === 0) { | ||
console.log(gray('Total supply is 0, exiting.')); | ||
|
@@ -192,7 +204,7 @@ const purgeSynths = async ({ | |
console.log(green('Would attempt to purge:', entries)); | ||
} else { | ||
await performTransactionalStep({ | ||
account, | ||
account: wallet, | ||
contract: `Synth${currencyKey}`, | ||
target: Synth, | ||
write: 'purge', | ||
|
@@ -206,7 +218,7 @@ const purgeSynths = async ({ | |
} | ||
|
||
// step 3. confirmation | ||
const totalSupply = w3utils.fromWei(await Synth.methods.totalSupply().call()); | ||
const totalSupply = ethers.utils.formatEther(await Synth.totalSupply()); | ||
if (Number(totalSupply) > 0) { | ||
console.log( | ||
yellow( | ||
|
@@ -261,6 +273,12 @@ module.exports = { | |
'-p, --proxy-address <value>', | ||
'Override the proxy address for the token (only works with a single synth given)' | ||
) | ||
.option( | ||
'-k, --use-fork', | ||
'Perform the deployment on a forked chain running on localhost (see fork command).', | ||
false | ||
) | ||
.option('-y, --yes', 'Dont prompt, just reply yes.') | ||
.option( | ||
'-s, --synths-to-purge <value>', | ||
'The list of synths to purge', | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍