Skip to content

Commit

Permalink
feat: migrate truffle scripts to hardhat tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
Luisfc68 committed Dec 26, 2024
1 parent be458fd commit b626b5a
Show file tree
Hide file tree
Showing 11 changed files with 553 additions and 6 deletions.
94 changes: 94 additions & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,55 @@
import dotenv from "dotenv";
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import "@openzeppelin/hardhat-upgrades";
import "./tasks/get-versions";
import "./tasks/btc-best-height";
import "./tasks/hash-quote";
import "./tasks/refund-user-pegout";
import "./tasks/register-pegin";

dotenv.config();

const {
MAINNET_RPC_URL,
TESTNET_RPC_URL,
MAINNET_SIGNER_PRIVATE_KEY,
MAINNET_MNEMONIC,
TESTNET_SIGNER_PRIVATE_KEY,
TESTNET_MNEMONIC,
DEV_SIGNER_PRIVATE_KEY,
DEV_MNEMONIC,
} = process.env;

const rskMainnetDerivationPath = "m/44'/137'/0'/0/0";
const rskTestnetDerivationPath = "m/44'/37310'/0'/0/0";

const rpcDefaultTimeout = 3 * 60 * 1000; // 3 minutes

const config: HardhatUserConfig = {
networks: {
rskRegtest: {
url: "http://localhost:4444",
chainId: 33,
},
rskDevelopment: {
url: TESTNET_RPC_URL,
timeout: rpcDefaultTimeout,
chainId: 31,
accounts: getAccounts("development"),
},
rskTestnet: {
url: TESTNET_RPC_URL,
timeout: rpcDefaultTimeout,
chainId: 31,
accounts: getAccounts("testnet"),
},
rskMainnet: {
url: MAINNET_RPC_URL,
timeout: rpcDefaultTimeout,
chainId: 30,
accounts: getAccounts("mainnet"),
},
},
solidity: {
version: "0.8.18",
Expand All @@ -21,3 +63,55 @@ const config: HardhatUserConfig = {
};

export default config;

function getAccounts(network: "mainnet" | "testnet" | "development") {
switch (network) {
case "mainnet":
return getMainnetAccounts();
case "testnet":
return getTestnetAccounts();
case "development":
return getDevAccounts();
default:
return undefined;
}
}

function getMainnetAccounts() {
if (MAINNET_MNEMONIC) {
return {
mnemonic: MAINNET_MNEMONIC,
path: rskMainnetDerivationPath,
};
} else if (MAINNET_SIGNER_PRIVATE_KEY) {
return [MAINNET_SIGNER_PRIVATE_KEY];
} else {
return undefined;
}
}

function getTestnetAccounts() {
if (TESTNET_MNEMONIC) {
return {
mnemonic: TESTNET_MNEMONIC,
path: rskTestnetDerivationPath,
};
} else if (TESTNET_SIGNER_PRIVATE_KEY) {
return [TESTNET_SIGNER_PRIVATE_KEY];
} else {
return undefined;
}
}

function getDevAccounts() {
if (DEV_MNEMONIC) {
return {
mnemonic: DEV_MNEMONIC,
path: rskTestnetDerivationPath,
};
} else if (DEV_SIGNER_PRIVATE_KEY) {
return [DEV_SIGNER_PRIVATE_KEY];
} else {
return undefined;
}
}
1 change: 1 addition & 0 deletions scripts/deployment-utils/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const BRIDGE_ADDRESS = "0x0000000000000000000000000000000001000006";
3 changes: 1 addition & 2 deletions scripts/deployment-utils/deploy-proxy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ethers, upgrades } from "hardhat";
import { deploy, DeployedContractInfo, LOCAL_NETWORK } from "./deploy";
import { deployContract, REMOTE_NETWORKS, TEST_NETWORKS } from "./utils";
import { BRIDGE_ADDRESS } from "./constants";

interface LiquidityBridgeContractInitParams {
bridgeAddress: string;
Expand All @@ -20,8 +21,6 @@ interface LiquidityBridgeContractLibraries {
bridge: string;
}

export const BRIDGE_ADDRESS = "0x0000000000000000000000000000000001000006";

async function deployProxyLibraries(
network: string
): Promise<LiquidityBridgeContractLibraries> {
Expand Down
15 changes: 15 additions & 0 deletions tasks/btc-best-height.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { task } from "hardhat/config";
import { BRIDGE_ADDRESS } from "../scripts/deployment-utils/constants";

task("btc-best-height")
.setDescription(
"Prints the best height of the Bitcoin network seen by the Rootstock Bridge"
)
.setAction(async (_, hre) => {
const { ethers } = hre;
const bridge = await ethers.getContractAt("Bridge", BRIDGE_ADDRESS);
const bestHeight = await bridge.getBtcBlockchainBestChainHeight();
console.info(
`Best BTC blockchain height: \x1b[32m${bestHeight.toString()}\x1b[0m`
);
});
43 changes: 43 additions & 0 deletions tasks/get-versions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { task } from "hardhat/config";
import { DeploymentConfig, read } from "../scripts/deployment-utils/deploy";

task("get-versions")
.setDescription(
"Prints the versions of the LiquidityBridgeContract and its libraries where applicable"
)
.setAction(async (_, hre) => {
const { ethers, network } = hre;
const addresses: Partial<DeploymentConfig> = read();
const networkDeployments: Partial<DeploymentConfig[string]> | undefined =
addresses[network.name];

if (!networkDeployments?.LiquidityBridgeContract?.address) {
throw new Error(
"LiquidityBridgeContract proxy deployment info not found"
);
}
const lbcAddress = networkDeployments.LiquidityBridgeContract.address;

if (!networkDeployments.BtcUtils?.address) {
throw new Error(
"LiquidityBridgeContract proxy deployment info not found"
);
}
const btcUtilsAddress = networkDeployments.BtcUtils.address;

const lbc = await ethers.getContractAt(
"LiquidityBridgeContractV2",
lbcAddress
);
const lbcVersion = await lbc.version().catch(() => "Not found");

const btcUtils = await ethers.getContractAt("BtcUtils", btcUtilsAddress);
const btcUtilsVersion = await btcUtils.version().catch(() => "Not found");

console.info("=======================================");
console.info(
`LiquidityBridgeContract version: \x1b[32m${lbcVersion}\x1b[0m`
);
console.info(`BtcUtils version: \x1b[32m${btcUtilsVersion}\x1b[0m`);
console.info("=======================================");
});
22 changes: 22 additions & 0 deletions tasks/hash-quote.example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"fedBTCAddr": "2N9uY615Mxk6KSSjv6F3FnvSPgZMer7FF39",
"lbcAddr": "0x18D8212bC00106b93070123f325021C723D503a3",
"lpRSKAddr": "0xdfcf32644e6cc5badd1188cddf66f66e21b24375",
"btcRefundAddr": "mfWxJ45yp2SFn7UciZyNpvDKrzbhyfKrY8",
"rskRefundAddr": "0x8dcCD82443B80DDdE3690aF86746BfD9D766f8d2",
"lpBTCAddr": "mwEceC31MwWmF6hc5SSQ8FmbgdsSoBSnbm",
"callFee": 150000000000000,
"penaltyFee": 10000000000000,
"contractAddr": "0x8dcCD82443B80DDdE3690aF86746BfD9D766f8d2",
"data": "0x",
"gasLimit": 21000,
"nonce": "3307065858190946360",
"value": "5000000000000000",
"agreementTimestamp": 1735243258,
"timeForDeposit": 9800,
"lpCallTime": 10800,
"confirmations": 2,
"callOnRegister": false,
"gasFee": 114524739000,
"productFeeAmount": 0
}
64 changes: 64 additions & 0 deletions tasks/hash-quote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { task, types } from "hardhat/config";
import { readFileSync } from "fs";
import { DeploymentConfig, read } from "../scripts/deployment-utils/deploy";
import {
ApiPeginQuote,
ApiPegoutQuote,
parsePeginQuote,
parsePegoutQuote,
} from "./utils/quote";

task("hash-quote")
.setDescription("Prints the hash of the quote provided in the input file")
.addParam(
"file",
"The file containing the quote to hash",
undefined,
types.inputFile
)
.addParam(
"type",
"Wether the quote is a PegIn or PegOut quote",
undefined,
types.string
)
.setAction(async (args, hre) => {
const { network, ethers } = hre;
const typedArgs = args as { file: string; type: string };
const type: string = typedArgs.type.toLowerCase();
const inputFile: string = typedArgs.file;

if (!["pegin", "pegout"].includes(type)) {
throw new Error("Invalid type. Must be 'pegin' or 'pegout'");
}
const fileContent = readFileSync(inputFile);
const quote: unknown = JSON.parse(fileContent.toString());

const addresses: Partial<DeploymentConfig> = read();
const networkDeployments: Partial<DeploymentConfig[string]> | undefined =
addresses[network.name];
const lbcAddress = networkDeployments?.LiquidityBridgeContract?.address;
if (!lbcAddress) {
throw new Error(
"LiquidityBridgeContract proxy deployment info not found"
);
}
const lbc = await ethers.getContractAt(
"LiquidityBridgeContractV2",
lbcAddress
);

if (type === "pegin") {
const hash = await lbc.hashQuote(parsePeginQuote(quote as ApiPeginQuote));
console.info(
`Hash of the provided PegIn quote: \x1b[32m${hash.slice(2)}\x1b[0m`
);
} else {
const hash = await lbc.hashPegoutQuote(
parsePegoutQuote(quote as ApiPegoutQuote)
);
console.info(
`Hash of the provided PegOut quote: \x1b[32m${hash.slice(2)}\x1b[0m`
);
}
});
42 changes: 42 additions & 0 deletions tasks/refund-user-pegout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { task, types } from "hardhat/config";
import { DeploymentConfig, read } from "../scripts/deployment-utils/deploy";

task("refund-user-pegout")
.setDescription(
"Refund a user that didn't receive their PegOut in the agreed time"
)
.addParam(
"quotehash",
"The hash of the accepted PegOut quote",
undefined,
types.string
)
.setAction(async (args, hre) => {
const { ethers, network } = hre;
const typedArgs = args as { quotehash: string };
const quoteHash: string = "0x" + typedArgs.quotehash;

const addresses: Partial<DeploymentConfig> = read();
const networkDeployments: Partial<DeploymentConfig[string]> | undefined =
addresses[network.name];

const lbcAddress = networkDeployments?.LiquidityBridgeContract?.address;
if (!lbcAddress) {
throw new Error(
"LiquidityBridgeContract proxy deployment info not found"
);
}
const lbc = await ethers.getContractAt(
"LiquidityBridgeContractV2",
lbcAddress
);

const gasEstimation = await lbc.refundUserPegOut.estimateGas(quoteHash);
console.info("Gas estimation for refundUserPegOut:", gasEstimation);

const tx = await lbc.refundUserPegOut(quoteHash);
const receipt = await tx.wait();
console.info(`Transaction hash: ${receipt!.hash}`);
console.info("Transaction receipt: ");
console.info(receipt);
});
Loading

0 comments on commit b626b5a

Please sign in to comment.