Skip to content

Commit

Permalink
feat: identify chain from signed tx during broadcast (#92)
Browse files Browse the repository at this point in the history
* feat: identify chain from signed tx during broadcast

* lint
  • Loading branch information
milapsheth authored Oct 24, 2023
1 parent 981764c commit c835241
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 20 deletions.
48 changes: 31 additions & 17 deletions evm/broadcast-transactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,38 @@ const {
providers: { getDefaultProvider },
} = ethers;

const { printError, printInfo, printWarn, prompt, mainProcessor } = require('./utils');
const { printError, printInfo, printWarn, getConfigByChainId, prompt, loadConfig } = require('./utils');
const { sendTransaction, getSignedTx, storeSignedTx } = require('./sign-utils');

async function processCommand(_, chain, options) {
const { filePath, rpc } = options;
async function processCommand(config, _, options, file) {
const { rpc } = options;

const transaction = await getSignedTx(file);
const parsedTx = ethers.utils.parseTransaction(transaction.signedTx);

const chain = getConfigByChainId(parsedTx.chainId, config);

const provider = getDefaultProvider(rpc || chain.rpc);

if (parsedTx.chainId !== transaction.unsignedTx.chainId) {
printError(
`ChainId mismatch: signed tx chain id ${parsedTx.chainId} doesn't match unsigned tx chain id ${transaction.unsignedTx.chainId}`,
);
return;
}

if (
prompt(
`Proceed with the broadcasting of all pending signed transactions for file ${chalk.green(
options.filePath,
)} on chain ${chalk.green(chain.name)}`,
`Proceed with the broadcasting of all pending signed transactions for file ${chalk.green(file)} on chain ${chalk.green(
chain.name,
)}`,
options.yes,
)
) {
return;
}

if (!filePath) {
throw new Error('FilePath is not provided in user info');
}

const transaction = await getSignedTx(filePath);

if (transaction.status === 'PENDING') {
if (transaction.status !== 'SUCCESS') {
printInfo('Broadcasting transaction', JSON.stringify(transaction.unsignedTx, null, 2));

// Send the signed transaction
Expand All @@ -46,29 +52,37 @@ async function processCommand(_, chain, options) {
printError('Error broadcasting tx', error);
}

storeSignedTx(filePath, transaction);
storeSignedTx(file, transaction);
} else {
printWarn('Skipping broadcast, transaction status is', transaction.status);
}
}

async function main(options) {
await mainProcessor(options, processCommand);
const config = loadConfig(options.env);
const { files } = options;

if (!files || files.length === 0) {
throw new Error('FilePath is not provided in user info');
}

for (const file of files) {
await processCommand(config, null, options, file);
}
}

const program = new Command();

program.name('broadcast-transactions').description('Broadcast all the pending signed transactions of the signer');

program.addOption(new Option('--filePath <filePath>', 'The file where the signed tx are stored').makeOptionMandatory(true));
program.addOption(new Option('--files [files...]', 'The file where the signed tx are stored').makeOptionMandatory(true));
program.addOption(
new Option('-e, --env <env>', 'environment')
.choices(['local', 'devnet', 'stagenet', 'testnet', 'mainnet'])
.default('testnet')
.makeOptionMandatory(true)
.env('ENV'),
);
program.addOption(new Option('-n, --chainName <chainName>', 'chain names').makeOptionMandatory(true));
program.addOption(new Option('-r, --rpc <rpc>', 'The chain rpc'));
program.addOption(new Option('-y, --yes', 'skip prompts'));

Expand Down
3 changes: 2 additions & 1 deletion evm/deploy-contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const {
printInfo,
printWarn,
printError,
copyObject,
isString,
isNumber,
isAddressArray,
Expand Down Expand Up @@ -258,7 +259,7 @@ async function processCommand(config, chain, options) {
printInfo('Pre-deploy Contract bytecode hash', predeployCodehash);

const constructorArgs = await getConstructorArgs(contractName, chain, wallet, options);
const gasOptions = JSON.parse(JSON.stringify(contractConfig.gasOptions || chain.gasOptions || {}));
const gasOptions = copyObject(contractConfig.gasOptions || chain.gasOptions || {});

// Some chains require a gas adjustment
if (env === 'mainnet' && !gasOptions.gasPrice && (chain.name === 'Fantom' || chain.name === 'Binance' || chain.name === 'Polygon')) {
Expand Down
11 changes: 9 additions & 2 deletions evm/governance.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {
const { Command, Option } = require('commander');
const {
printInfo,
copyObject,
printWalletInfo,
isValidTimeFormat,
dateToEta,
Expand Down Expand Up @@ -62,7 +63,7 @@ async function getGatewaySetupParams(governance, gateway, contracts, options) {
}

async function processCommand(_, chain, options) {
const { contractName, address, action, date, privateKey, yes } = options;
const { env, contractName, address, action, date, privateKey, yes } = options;

const contracts = chain.contracts;
const contractConfig = contracts[contractName];
Expand Down Expand Up @@ -103,7 +104,13 @@ async function processCommand(_, chain, options) {

const governance = new Contract(governanceAddress, IGovernance.abi, wallet);

const gasOptions = contractConfig?.gasOptions || chain?.gasOptions || { gasLimit: 5e6 };
const gasOptions = copyObject(contractConfig?.gasOptions || chain?.gasOptions || { gasLimit: 5e6 });

// Some chains require a gas adjustment
if (env === 'mainnet' && !gasOptions.gasPrice && (chain.name === 'Fantom' || chain.name === 'Binance' || chain.name === 'Polygon')) {
gasOptions.gasPrice = Math.floor((await provider.getGasPrice()) * 1.4);
}

printInfo('Gas options', JSON.stringify(gasOptions, null, 2));

printInfo('Proposal Action', action);
Expand Down
16 changes: 16 additions & 0 deletions evm/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,10 @@ function isValidAddress(address, allowZeroAddress) {
return isAddress(address);
}

function copyObject(obj) {
return JSON.parse(JSON.stringify(obj));
}

const mainProcessor = async (options, processCommand, save = true, catchErr = false) => {
if (!options.env) {
throw new Error('Environment was not provided');
Expand Down Expand Up @@ -763,12 +767,23 @@ const prompt = (question, yes = false) => {
return answer !== 'y';
};

function getConfigByChainId(chainId, config) {
for (const chain of Object.values(config.chains)) {
if (chain.chainId === chainId) {
return chain;
}
}

throw new Error(`Chain with chainId ${chainId} not found in the config`);
}

module.exports = {
deployCreate,
deployCreate2,
deployCreate3,
deployContract,
writeJSON,
copyObject,
httpGet,
printObj,
printLog,
Expand All @@ -791,6 +806,7 @@ module.exports = {
getProxy,
getEVMBatch,
getEVMAddresses,
getConfigByChainId,
sleep,
loadConfig,
saveConfig,
Expand Down

0 comments on commit c835241

Please sign in to comment.