Skip to content

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

Merged
merged 5 commits into from
Jun 16, 2021
Merged
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
149 changes: 149 additions & 0 deletions publish/src/command-utils/transact.js
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,
};
4 changes: 2 additions & 2 deletions publish/src/commands/deploy-shorting-rewards.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const {
loadConnections,
confirmAction,
parameterNotice,
performTransactionalStep,
performTransactionalStepWeb3,
} = require('../util');

const {
Expand Down Expand Up @@ -246,7 +246,7 @@ const deployShortingRewards = async ({
const manageNonces = deployer.manageNonces;

const runStep = async opts =>
performTransactionalStep({
performTransactionalStepWeb3({
gasLimit: methodCallGasLimit, // allow overriding of gasLimit
...opts,
deployer,
Expand Down
4 changes: 2 additions & 2 deletions publish/src/commands/deploy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const {
getDeploymentPathForNetwork,
loadAndCheckRequiredSources,
loadConnections,
performTransactionalStep,
performTransactionalStepWeb3,
reportDeployedContracts,
} = require('../../util');

Expand Down Expand Up @@ -253,7 +253,7 @@ const deploy = async ({
);

const runStep = async opts =>
performTransactionalStep({
performTransactionalStepWeb3({
gasLimit: methodCallGasLimit, // allow overriding of gasLimit
...opts,
account,
Expand Down
48 changes: 33 additions & 15 deletions publish/src/commands/purge-synths.js
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('../../..');

Expand All @@ -17,9 +17,10 @@ const {
loadAndCheckRequiredSources,
loadConnections,
confirmAction,
performTransactionalStep,
} = require('../util');

const { performTransactionalStep } = require('../command-utils/transact');

const DEFAULTS = {
network: 'kovan',
gasLimit: 3e6,
Expand All @@ -39,6 +40,7 @@ const purgeSynths = async ({
addresses = [],
batchSize = DEFAULTS.batchSize,
proxyAddress,
useFork,
}) => {
ensureNetwork(network);
deploymentPath = deploymentPath || getDeploymentPathForNetwork({ network });
Expand All @@ -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'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

return;
}

Expand All @@ -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;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leomassazza we should probably think a little more about this.
In one case, wallet will have .address and be read only, in the other, it will have ._address. Not sure if we should raise this to ethers.js, and/or make sure we always do this so that wallet.address is available with a util or something.

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'));
Expand All @@ -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) {
Expand All @@ -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(
Expand All @@ -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(
Expand Down Expand Up @@ -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.'));
Expand All @@ -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',
Expand All @@ -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(
Expand Down Expand Up @@ -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',
Expand Down
4 changes: 2 additions & 2 deletions publish/src/commands/remove-synths.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const {
loadConnections,
confirmAction,
stringify,
performTransactionalStep,
performTransactionalStepWeb3,
} = require('../util');

const DEFAULTS = {
Expand Down Expand Up @@ -155,7 +155,7 @@ const removeSynths = async ({
}

// perform transaction if owner of Synthetix or append to owner actions list
await performTransactionalStep({
await performTransactionalStepWeb3({
account,
contract: 'Issuer',
target: Issuer,
Expand Down
4 changes: 2 additions & 2 deletions publish/src/commands/replace-synths.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const {
loadConnections,
confirmAction,
stringify,
performTransactionalStep,
performTransactionalStepWeb3,
} = require('../util');

const DEFAULTS = {
Expand Down Expand Up @@ -220,7 +220,7 @@ const replaceSynths = async ({
const updatedSynths = JSON.parse(fs.readFileSync(synthsFile));

const runStep = async opts =>
performTransactionalStep({
performTransactionalStepWeb3({
...opts,
account,
gasLimit: methodCallGasLimit,
Expand Down
4 changes: 2 additions & 2 deletions publish/src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ let _dryRunCounter = 0;
*
* @returns transaction hash if successful, true if user completed, or falsy otherwise
*/
const performTransactionalStep = async ({
const performTransactionalStepWeb3 = async ({
account,
contract,
target,
Expand Down Expand Up @@ -371,7 +371,7 @@ module.exports = {
confirmAction,
appendOwnerActionGenerator,
stringify,
performTransactionalStep,
performTransactionalStepWeb3,
parameterNotice,
reportDeployedContracts,
};