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: migrate truffle scripts to hardhat tasks #289

Closed
wants to merge 2 commits into from
Closed
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
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 ?? "https://public-node.testnet.rsk.co",
timeout: rpcDefaultTimeout,
chainId: 31,
accounts: getAccounts("development"),
},
rskTestnet: {
url: TESTNET_RPC_URL ?? "https://public-node.testnet.rsk.co",
timeout: rpcDefaultTimeout,
chainId: 31,
accounts: getAccounts("testnet"),
},
rskMainnet: {
url: MAINNET_RPC_URL ?? "https://public-node.rsk.co",
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
Loading