Skip to content
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

feat: offline signing using ledger [AXE-1805] #52

Merged
merged 46 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
818489d
wip: intitial changes for adding ledger utils
Sep 12, 2023
eae0544
removed ledger utils from utils.js and created new offline sign utils…
Sep 14, 2023
4361f68
add new ledger packages
Sep 14, 2023
87f8507
wip: update script for using ledger for signer sendTokens call
Sep 14, 2023
fc74097
run prettier
Sep 14, 2023
c8c0f95
refactor logic for signing, and remove unused functions
Sep 14, 2023
09434f7
update getNonce logic, remove extra consoles
Sep 14, 2023
2887a53
resolved errors and updated logic
Sep 14, 2023
b5de227
refactor transactions storing logic
Sep 15, 2023
641222c
add util functions for broadcasting signed txscript
Sep 15, 2023
aff63ff
add script for broadcasting pending signed tx
Sep 15, 2023
ec1b627
refactored code for broadcast script and utils, include more info abo…
Sep 15, 2023
41022ff
use hardhat ethers in scripts
Sep 15, 2023
646c17d
offline signing logic for upgrade
Sep 15, 2023
0dbe734
print object for error, modify util names, remove console logs
Sep 15, 2023
ce926e6
update optional fileName
Sep 15, 2023
418ec0a
refactored util function name, and optional directory path
Sep 15, 2023
2c17bbc
add: package lock
Sep 15, 2023
07450ff
adding more logs for info
Sep 15, 2023
00b3b41
chore: improved error handling
Sep 15, 2023
1388c23
update: print logs info
Sep 15, 2023
6d6d6d2
fix: error catching for offline txs
Sep 15, 2023
c688c03
use ethers from hardhat
milapsheth Sep 16, 2023
2ff7f55
fixes
milapsheth Sep 18, 2023
c3d2a5d
Update --offline option to remove arg
blockchainguyy Sep 18, 2023
b330e2d
addressed pr comments
Sep 18, 2023
a4b6848
use offline in if condition, remove extra logs
Sep 18, 2023
add0c02
combine tx creation and ledger signing, code refactoring
Sep 18, 2023
67aca95
refactor code for unused imports, correct nonce usage
Sep 19, 2023
767d75a
moced nonce logic inside if
Sep 19, 2023
043b0d3
store nonce in chain config, update static gasOptions to be store and…
Sep 19, 2023
3a42056
made gasLimit static to 130000 in confifg for offline signing
Sep 19, 2023
54e6cc0
add script to check address has minimum required balance
Sep 20, 2023
1746ce7
refactor deployv5 and send-tokens script logic to store single signed…
Sep 20, 2023
c17d727
refactor broadcast logic to only sign single tx from the file
Sep 20, 2023
350fcd4
update logic to only update gasLimit if not already set
Sep 20, 2023
176a53e
refactored code to remove unused functions/vars, use const where poss…
Sep 20, 2023
bd34f1a
resolve overflow error using BigNumber
Sep 20, 2023
a911e81
Merge branch 'main' into add/ledger-utilities
milapsheth Sep 21, 2023
4b6f320
rename update nonces script
milapsheth Sep 21, 2023
ca1aac8
minor refactor of broadcast script
milapsheth Sep 21, 2023
16438ea
address comments
milapsheth Sep 26, 2023
18a8d83
fix online signing
milapsheth Sep 27, 2023
ae3b51a
simplify broadcast
milapsheth Sep 27, 2023
45fd73e
prettier
milapsheth Sep 27, 2023
450ddd5
throw exception
milapsheth Sep 27, 2023
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
2 changes: 1 addition & 1 deletion evm/.example.hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
require('@nomicfoundation/hardhat-toolbox');

const env = process.env.ENV || 'testnet';
const { importNetworks, readJSON } = require('@axelar-network/axelar-contract-deployments');
const { importNetworks, readJSON } = require('@axelar-network/axelar-chains-config');
const chains = require(`@axelar-network/axelar-chains-config/info/${env}.json`);
const keys = readJSON(`${__dirname}/keys.json`);
const { networks, etherscan } = importNetworks(chains, keys);
Expand Down
78 changes: 78 additions & 0 deletions evm/broadcast-transactions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'use strict';

const chalk = require('chalk');
const { Command, Option } = require('commander');
const { ethers } = require('hardhat');
const {
providers: { getDefaultProvider },
} = ethers;
const readlineSync = require('readline-sync');

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

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

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

if (!options.yes) {
const anwser = readlineSync.question(
`Proceed with the broadcasting of all pending signed transactions for file ${chalk.green(
options.filePath,
)} on chain ${chalk.green(chain.name)} ${chalk.green('(y/n)')} `,
);
if (anwser !== 'y') return;
}

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

const transaction = await getSignedTx(filePath);

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

// Send the signed transaction
try {
const { response } = await sendTransaction(transaction.signedTx, provider, chain.confirmations);
transaction.status = 'SUCCESS';
transaction.hash = response.hash;
printInfo('Transaction executed successfully', response.hash);
} catch (error) {
transaction.status = 'FAILED';
printError('Error broadcasting tx', error);
}

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

async function main(options) {
await mainProcessor(options, processCommand);
}

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('-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'));

program.action((options) => {
main(options);
});

program.parse();
68 changes: 68 additions & 0 deletions evm/check-wallet-balance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use strict';

const { Command, Option } = require('commander');
const { ethers } = require('hardhat');
const { getDefaultProvider, BigNumber } = ethers;

const { printError, mainProcessor } = require('./utils');
const { getNonceFileData } = require('./offline-sign-utils');

async function processCommand(_, chain, options) {
const { rpc } = options;
let { addresses } = options;

const chainName = chain.name.toLowerCase();
const provider = getDefaultProvider(rpc || chain.rpc);
const staticGasOptions = chain.staticGasOptions;

if (!staticGasOptions) {
printError('Could not find staticGasOptions for chain', chain.name);
return;
}

const gasLimit = BigNumber.from(staticGasOptions.gasLimit);
const gasPrice = BigNumber.from(staticGasOptions.gasPrice);
const minRequiredBalance = gasLimit * gasPrice;
const nonceData = getNonceFileData();
const nonces = nonceData[options.env][chainName];

if (addresses) {
addresses = JSON.parse(addresses);
} else {
addresses = Object.entries(nonces);
}

for (const address of addresses) {
const balance = await provider.getBalance(address);

if (balance < minRequiredBalance) {
printError('Minimum required Balance is', `${minRequiredBalance / 1e18}`);
printError(`Wallet Balance for address ${address} is`, `${balance / 1e18}`);
}
}
}

async function main(options) {
await mainProcessor(options, processCommand);
}

const program = new Command();

program.name('check-wallet-balance').description('Before offline signing checks if each signer has minimum required wallet balance');

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, --chainNames <chainNames>', 'chain names').makeOptionMandatory(true));
program.addOption(new Option('-r, --rpc <rpc>', 'The rpc url for creating a provider to fetch gasOptions'));
program.addOption(new Option('--addresses <addresses>', 'The Array of addresses for which the balance to check').env('ADDRESSES'));

program.action((options) => {
main(options);
});

program.parse();
2 changes: 1 addition & 1 deletion evm/deploy-const-address-deployer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require('dotenv').config();

const { ethers } = require('hardhat');
const { Wallet, getDefaultProvider, ContractFactory } = require('ethers');
const { Wallet, getDefaultProvider, ContractFactory } = ethers;
const readlineSync = require('readline-sync');
const { Command, Option } = require('commander');
const chalk = require('chalk');
Expand Down
3 changes: 2 additions & 1 deletion evm/deploy-contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

require('dotenv').config();

const { ethers } = require('hardhat');
const {
Wallet,
getDefaultProvider,
utils: { isAddress },
} = require('ethers');
} = ethers;
const readlineSync = require('readline-sync');
const { Command, Option } = require('commander');
const chalk = require('chalk');
Expand Down
19 changes: 16 additions & 3 deletions evm/deploy-gateway-v4.3.x.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const {
saveConfig,
loadConfig,
printWalletInfo,
isAddressArray,
isNumber,
} = require('./utils');
const { ethers } = require('hardhat');
const {
Expand All @@ -26,8 +28,8 @@ const { Command, Option } = require('commander');
const chalk = require('chalk');

async function getAuthParams(config, chain) {
const { addresses, weights, threshold } = await getEVMAddresses(config, chain);
printObj(JSON.stringify({ addresses, weights, threshold }));
const { addresses, weights, threshold, keyID } = await getEVMAddresses(config, chain);
printObj(JSON.stringify({ status: 'latest', keyID, addresses, weights, threshold }));
const paramsAuth = [defaultAbiCoder.encode(['address[]', 'uint256[]', 'uint256'], [addresses, weights, threshold])];
return paramsAuth;
}
Expand Down Expand Up @@ -63,7 +65,7 @@ async function deploy(config, options) {
});
printInfo('Predicted proxy address', proxyAddress);

const gasOptions = contractConfig.gasOptions || chain.gasOptions || {};
const gasOptions = contractConfig.gasOptions || chain.gasOptions || { gasLimit: 6e6 };
printInfo('Gas override', JSON.stringify(gasOptions, null, 2));
printInfo('Is verification enabled?', verify ? 'y' : 'n');
printInfo('Skip existing contracts?', skipExisting ? 'y' : 'n');
Expand All @@ -73,6 +75,16 @@ async function deploy(config, options) {
const tokenDeployerFactory = await getContractFactory('TokenDeployer', wallet);
const gatewayProxyFactory = await getContractFactory('AxelarGatewayProxy', wallet);

if (!adminAddresses || !isAddressArray(JSON.parse(adminAddresses))) {
printError('Invalid admin addresses', `${adminAddresses}`);
return;
}

if (!adminThreshold || !isNumber(parseInt(adminThreshold))) {
printError('Invalid admin threshold', `${adminThreshold}`);
return;
}

let gateway;
let auth;
let tokenDeployer;
Expand Down Expand Up @@ -219,6 +231,7 @@ async function deploy(config, options) {

contractConfig.address = gateway.address;
contractConfig.implementation = implementation.address;
contractConfig.implementationCodehash = implementationCodehash;
contractConfig.authModule = auth.address;
contractConfig.tokenDeployer = tokenDeployer.address;

Expand Down
Loading