diff --git a/evm/cli-utils.js b/evm/cli-utils.js index cbc84bd5..6ce17f32 100644 --- a/evm/cli-utils.js +++ b/evm/cli-utils.js @@ -10,13 +10,13 @@ const addBaseOptions = (program, options = {}) => { .makeOptionMandatory(true) .env('ENV'), ); - program.addOption(new Option('--skipChains ', 'chains to skip over')); program.addOption(new Option('-y, --yes', 'skip deployment prompt confirmation').env('YES')); if (!options.ignoreChainNames) { program.addOption( new Option('-n, --chainNames ', 'chains to run the script over').makeOptionMandatory(true).env('CHAINS'), ); + program.addOption(new Option('--skipChains ', 'chains to skip over')); } if (!options.ignorePrivateKey) { @@ -35,15 +35,25 @@ const addExtendedOptions = (program, options = {}) => { program.addOption(new Option('-v, --verify', 'verify the deployed contract on the explorer').env('VERIFY')); - if (options.artifactPath) program.addOption(new Option('-a, --artifactPath ', 'artifact path')); - if (options.contractName) program.addOption(new Option('-c, --contractName ', 'contract name').makeOptionMandatory(true)); - if (options.salt) program.addOption(new Option('-s, --salt ', 'salt to use for create2 deployment').env('SALT')); + if (options.artifactPath) { + program.addOption(new Option('-a, --artifactPath ', 'artifact path')); + } + + if (options.contractName) { + program.addOption(new Option('-c, --contractName ', 'contract name').makeOptionMandatory(true)); + } + + if (options.salt) { + program.addOption(new Option('-s, --salt ', 'salt to use for create2 deployment').env('SALT')); + } if (options.skipExisting) { program.addOption(new Option('-x, --skipExisting', 'skip existing if contract was already deployed on chain').env('SKIP_EXISTING')); } - if (options.upgrade) program.addOption(new Option('-u, --upgrade', 'upgrade a deployed contract').env('UPGRADE')); + if (options.upgrade) { + program.addOption(new Option('-u, --upgrade', 'upgrade a deployed contract').env('UPGRADE')); + } return program; }; diff --git a/evm/deploy-contract.js b/evm/deploy-contract.js index f8ecacd1..5c84d522 100644 --- a/evm/deploy-contract.js +++ b/evm/deploy-contract.js @@ -25,7 +25,7 @@ const { prompt, mainProcessor, isContract, - getContractPath, + getContractJSON, } = require('./utils'); const { addExtendedOptions } = require('./cli-utils'); @@ -251,17 +251,7 @@ async function processCommand(config, chain, options) { printInfo('Contract name', contractName); - let contractPath; - - if (artifactPath) { - contractPath = artifactPath.charAt(0) === '@' ? artifactPath : artifactPath + contractName + '.sol/' + contractName + '.json'; - } else { - contractPath = getContractPath(contractName); - } - - printInfo('Contract path', contractPath); - - const contractJson = require(contractPath); + const contractJson = getContractJSON(contractName, artifactPath); const predeployCodehash = await getBytecodeHash(contractJson, chain.id); printInfo('Pre-deploy Contract bytecode hash', predeployCodehash); diff --git a/evm/execute-contract.js b/evm/execute-contract.js index ae429b5d..e7603b7c 100644 --- a/evm/execute-contract.js +++ b/evm/execute-contract.js @@ -12,7 +12,7 @@ const { const readlineSync = require('readline-sync'); const { Command, Option } = require('commander'); -const { isNumber, isString, loadConfig, saveConfig, printObj, printLog, printError, printInfo } = require('./utils'); +const { isNumber, isString, loadConfig, saveConfig, printObj, printLog, printError, getContractJSON } = require('./utils'); const { addBaseOptions } = require('./cli-utils'); async function getCallData(methodName, targetContract, inputRecipient, inputAmount) { @@ -137,11 +137,7 @@ async function executeContract(options, chain, wallet) { throw new Error('Missing native value from user info'); } - var contractPath = - callContractPath.charAt(0) === '@' ? callContractPath : callContractPath + callContractName + '.sol/' + callContractName + '.json'; - printInfo('Call Contract path', contractPath); - - const IContractExecutor = require(contractPath); + const IContractExecutor = getContractJSON(callContractName, callContractPath); const contract = new Contract(callContractAddress, IContractExecutor.abi, wallet); var finalCallData, finalNativeValue; @@ -149,12 +145,7 @@ async function executeContract(options, chain, wallet) { finalCallData = callData; finalNativeValue = nativeValue; } else { - contractPath = - targetContractPath.charAt(0) === '@' - ? targetContractPath - : targetContractPath + targetContractName + '.sol/' + targetContractName + '.json'; - printInfo('Target Contract path', contractPath); - const ITargetContract = require(contractPath); + const ITargetContract = getContractJSON(targetContractName, targetContractPath); const targetContract = new Contract(targetContractAddress, ITargetContract.abi, wallet); finalCallData = await getCallData(methodName, targetContract, recipientAddress, Number(amount)); finalNativeValue = Number(0); @@ -207,21 +198,16 @@ if (require.main === module) { addBaseOptions(program); + program.addOption(new Option('-c, --callContractName ', 'name of the called contract').makeOptionMandatory(true)); + program.addOption(new Option('--callContractPath ', 'artifact path for the called contract')); + program.addOption(new Option('--targetContractPath ', 'artifact path for the target contract')); program.addOption( - new Option('-pc, --callContractPath ', 'artifact path for the called contract').makeOptionMandatory(true), - ); - program.addOption(new Option('-cn, --callContractName ', 'name of the called contract').makeOptionMandatory(true)); - program.addOption( - new Option('-pt, --targetContractPath ', 'artifact path for the target contract').makeOptionMandatory(true), - ); - program.addOption( - new Option( - '-tn, --targetContractName ', - 'name of the target contract that is called through executeContract', - ).makeOptionMandatory(false), + new Option('-t, --targetContractName ', 'target contract name called by executeContract').makeOptionMandatory( + true, + ), ); program.addOption( - new Option('-ta, --targetContractAddress ', 'The address of the contract to be called') + new Option('-a, --targetContractAddress ', 'target contract address') .makeOptionMandatory(true) .env('TARGET_ADDR'), ); @@ -229,17 +215,13 @@ if (require.main === module) { new Option('-v, --nativeValue ', 'The amount of native token (e.g., Ether) to be sent along with the call').default(0), ); program.addOption( - new Option('-m, --methodName ', 'method name to call in executeContract') + new Option('--action ', 'executeContract action') .choices(['withdraw', 'transfer', 'approve', 'default']) .default('default'), ); - program.addOption(new Option('-c, --callData ', 'The calldata to be sent').env('CALL_DATA').default('0x')); - program.addOption( - new Option('-ra, --recipientAddress ', 'The recipient address for the tokens').env('RECIPIENT_ADDR'), - ); - program.addOption( - new Option('-am, --amount ', 'The amount of tokens to transfer/withdraw/provide allowance etc.').env('AMOUNT'), - ); + program.addOption(new Option('--callData ', 'The calldata to be sent').env('CALL_DATA').default('0x')); + program.addOption(new Option('--recipientAddress ', 'The recipient address for the tokens').env('RECIPIENT_ADDR')); + program.addOption(new Option('--amount ', 'The amount of tokens to transfer/withdraw/provide allowance etc.').env('AMOUNT')); program.action((options) => { main(options); diff --git a/evm/utils.js b/evm/utils.js index 3c10a494..7703d592 100644 --- a/evm/utils.js +++ b/evm/utils.js @@ -789,7 +789,6 @@ function findProjectRoot(startDir) { return currentDir; } - // Move up a directory currentDir = path.resolve(currentDir, '..'); } @@ -805,7 +804,10 @@ function findContractPath(dir, contractName) { if (stat && stat.isDirectory()) { const recursivePath = findContractPath(filePath, contractName); - if (recursivePath) return recursivePath; + + if (recursivePath) { + return recursivePath; + } } else if (file === `${contractName}.json`) { return filePath; } @@ -816,20 +818,42 @@ function getContractPath(contractName) { const projectRoot = findProjectRoot(__dirname); const searchDirs = [ - path.join(projectRoot, 'node_modules', '@axelar-network/axelar-gmp-sdk-solidity/artifacts/contracts'), - path.join(projectRoot, 'node_modules', '@axelar-network/axelar-cgp-solidity/artifacts/contracts'), + path.join(projectRoot, 'node_modules', '@axelar-network', 'axelar-gmp-sdk-solidity', 'artifacts', 'contracts'), + path.join(projectRoot, 'node_modules', '@axelar-network', 'axelar-cgp-solidity', 'artifacts', 'contracts'), ]; for (const dir of searchDirs) { if (fs.existsSync(dir)) { const contractPath = findContractPath(dir, contractName); - if (contractPath) return contractPath; + + if (contractPath) { + return contractPath; + } } } throw new Error(`Contract path for ${contractName} must be entered manually.`); } +function getContractJSON(contractName, artifactPath) { + let contractPath; + + if (artifactPath) { + contractPath = artifactPath.charAt(0) === '@' ? artifactPath : artifactPath + contractName + '.sol/' + contractName + '.json'; + } else { + contractPath = getContractPath(contractName); + } + + printInfo('Contract path', contractPath); + + try { + const contractJson = require(contractPath); + return contractJson; + } catch (err) { + throw new Error(`Failed to load contract JSON for ${contractName} at path ${contractPath}`); + } +} + module.exports = { deployCreate, deployCreate2, @@ -876,4 +900,5 @@ module.exports = { prompt, mainProcessor, getContractPath, + getContractJSON, };