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

Add support for zkevm #214

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
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
34 changes: 31 additions & 3 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ const argv = require('yargs/yargs')()
type: "string",
default: ''
},
zkevmRpcUrl: {
type: "string",
},
infuraKey: {
type: "string",
},
Expand All @@ -63,6 +66,9 @@ const argv = require('yargs/yargs')()
networkScanKeyBsc: {
type: "string",
},
networkScanKeyZkevm: {
type: "string",
},
privateKey: {
type: "string",
default: "85bb5fa78d5c4ed1fde856e9d0d1fe19973d7a79ce9ed6c0358ee06a4550504e" // random account
Expand Down Expand Up @@ -122,13 +128,15 @@ export default {
argv.hardhatChainId === 250 ? argv.ftmRpcUrl :
argv.hardhatChainId === 56 ? argv.bscRpcUrl :
argv.hardhatChainId === 8453 ? argv.baseRpcUrl :
undefined,
argv.hardhatChainId === 1101 ? argv.zkevmRpcUrl :
undefined,
blockNumber:
argv.hardhatChainId === 1 ? argv.ethForkBlock !== 0 ? argv.ethForkBlock : undefined :
argv.hardhatChainId === 137 ? argv.maticForkBlock !== 0 ? argv.maticForkBlock : undefined :
argv.hardhatChainId === 250 ? argv.ftmForkBlock !== 0 ? argv.ftmForkBlock : undefined :
argv.hardhatChainId === 56 ? argv.bscForkBlock !== 0 ? argv.bscForkBlock : undefined :
undefined
argv.hardhatChainId === 1101 ? argv.zkevmForkBlock !== 0 ? argv.zkevmForkBlock : undefined :
undefined
} : undefined,
accounts: {
mnemonic: "test test test test test test test test test test test junk",
Expand Down Expand Up @@ -241,6 +249,17 @@ export default {
// gas: 50_000_000_000,
accounts: [argv.privateKey],
},
zkevm: {
url: argv.zkevmRpcUrl || '',
chainId: 1101,
accounts: [argv.privateKey],
gasPrice: 1000000000,
verify: {
etherscan: {
apiKey: argv.networkScanKeyZkevm
}
}
},
},
etherscan: {
// https://hardhat.org/plugins/nomiclabs-hardhat-etherscan.html#multiple-api-keys-and-alternative-block-explorers
Expand All @@ -254,6 +273,7 @@ export default {
skale_test: 'any',
imm_test: 'any',
base: argv.networkScanKeyBase,
zkevm: argv.networkScanKeyZkevm || argv.networkScanKey,
},
customChains: [
{
Expand All @@ -279,7 +299,15 @@ export default {
apiURL: "https://api.basescan.org/api",
browserURL: "https://basescan.org"
}
}
},
{
network: "zkevm",
chainId: 1101,
urls: {
apiURL: "https://api-zkevm.polygonscan.com/api",
browserURL: "https://zkevm.polygonscan.com/"
}
},
]
},
solidity: {
Expand Down
32 changes: 32 additions & 0 deletions scripts/addresses/ZkevmAddresses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* tslint:disable:variable-name */

// noinspection JSUnusedGlobalSymbols

export class ZkevmAddresses {

public static ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
public static GOV_ADDRESS = "0xbbbbb8C4364eC2ce52c59D2Ed3E56F307E529a94".toLowerCase();
public static TETU_LIQUIDATOR = "0xBcda73B7184D5974F77721db79ff8BA190b342ce".toLowerCase();
public static PRICE_CALCULATOR = "".toLowerCase();
public static CONTRACT_READER_V2 = "".toLowerCase();

// tokens
public static TETU_TOKEN = "0x7C1B24c139a3EdA18Ab77C8Fa04A0F816C23e6D4".toLowerCase();
public static WETH_TOKEN = '0x4F9A0e7FD2Bf6067db6994CF12E4495Df938E6e9'.toLowerCase();
public static USDC_TOKEN = '0xA8CE8aee21bC2A48a5EF670afCc9274C7bbbC035'.toLowerCase();
public static USDT_TOKEN = '0x1E4a5963aBFD975d8c9021ce480b42188849D41d'.toLowerCase();
public static WBTC_TOKEN = '0xEA034fb02eB1808C2cc3adbC15f447B93CbE08e1'.toLowerCase();
public static DAI_TOKEN = '0xC5015b9d9161Dca7e18e32f6f25C4aD850731Fd4'.toLowerCase();

// LPs
public static TETU_tUSDbC_AERODROME_LP = "".toLowerCase();
public static USDbC_tUSDbC_AERODROME_LP = "".toLowerCase();
public static USDbC_tUSDbC_UNI3_POOL = "".toLowerCase();

// DEXs

public static AERODROME_FACTORY = "".toLowerCase()
public static UNI3_FACTORY = "".toLowerCase()


}
76 changes: 26 additions & 50 deletions scripts/deploy/DeployContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import {Logger} from "tslog";
import logSettings from "../../log_settings";
import {formatUnits, parseUnits} from "ethers/lib/utils";
import {HardhatRuntimeEnvironment} from "hardhat/types";
import {ethers} from "hardhat";

const log: Logger<undefined> = new Logger(logSettings);

export const WAIT_BLOCKS_BETWEEN_DEPLOY = 5;

const libraries = new Map<string, string[]>([
['SmartVault', ['VaultLibrary',]],
['SmartVaultV110', ['VaultLibrary',]],
Expand All @@ -23,33 +26,15 @@ export async function deployContract<T extends ContractFactory>(
...args: any[]
) {
if (hre.network.name !== 'hardhat') {
await hre.run('compile');
await hre.run("compile")
}
const web3 = hre.web3;

const ethers = hre.ethers;
log.info(`Deploying ${name}`);
log.info("Account balance: " + utils.formatUnits(await signer.getBalance(), 18));

let gasPrice = await web3.eth.getGasPrice();
if (hre.network.name === 'custom') {
gasPrice = BigNumber.from(1);
}
const gasPrice = await ethers.provider.getGasPrice();
log.info("Gas price: " + formatUnits(gasPrice, 9));

if (hre.network.name === 'eth') {
while (true) {
if (+formatUnits(gasPrice, 9) < 30) {
break;
} else {
console.log('Wait for good gas price');
await delay(60_000);
}
gasPrice = await web3.eth.getGasPrice();
log.info("Gas price: " + formatUnits(gasPrice, 9));
}
}


const libs: string[] | undefined = libraries.get(name);
let _factory;
if (libs) {
Expand All @@ -63,40 +48,38 @@ export async function deployContract<T extends ContractFactory>(
name,
{
signer,
libraries: librariesObj
}
libraries: librariesObj,
},
)) as T;
} else {
_factory = (await ethers.getContractFactory(
name,
signer
signer,
)) as T;
}
// let gas = 5_000_000;
// if (hre.network.name === 'hardhat') {
// gas = 999_999_999;
// } else if (hre.network.name === 'mumbai') {
// gas = 5_000_000;
// }
// const instance = await _factory.deploy(...args, {gasLimit: gas, gasPrice: Math.floor(+gasPrice * 1.1)});
let gasLimit = 25_000_000
if (hre.network.name === 'matic' || hre.network.name === 'mumbai') {
gasLimit = 15_000_000
} else if (hre.network.name === 'ftm') {
gasLimit = 7_000_000
let gas = 5_000_000;
if (hre.network.name === 'hardhat') {
gas = 999_999_999;
} else if (hre.network.name === 'mumbai') {
gas = 5_000_000;
}

const instance = await _factory.deploy(...args, {
gasLimit,
gasPrice: Math.floor(+gasPrice * 1.1)
// large gas limit is required for npm run coverage
// see https://github.com/NomicFoundation/hardhat/issues/3121
gasLimit: hre.network.name === 'hardhat' ? 29_000_000 : undefined,
...(await txParams(hre, signer.provider as providers.Provider))
});

// const instance = await _factory.deploy(...args);
log.info('Deploy tx:', instance.deployTransaction.hash);
await instance.deployed();

const receipt = await ethers.provider.getTransactionReceipt(instance.deployTransaction.hash);
console.log('DEPLOYED: ', name, receipt.contractAddress);

if (hre.network.name !== 'hardhat' && hre.network.name !== 'zktest') {
await wait(hre, 10);
if (hre.network.name !== 'hardhat') {
await wait(hre, WAIT_BLOCKS_BETWEEN_DEPLOY);
if (args.length === 0) {
await verify(hre, receipt.contractAddress);
} else {
Expand Down Expand Up @@ -148,9 +131,11 @@ async function verifyWithArgs(hre: any, address: string, args: any[]) {
}
}



export async function txParams(hre: HardhatRuntimeEnvironment, provider: providers.Provider) {

let gasPrice = (await provider.getGasPrice()).toNumber();
const gasPrice = (await provider.getGasPrice()).toNumber();
console.log('Gas price:', formatUnits(gasPrice, 9));
const maxFee = '0x' + Math.floor(gasPrice * 1.5).toString(16);
if (hre.network.name === 'hardhat') {
Expand All @@ -168,17 +153,8 @@ export async function txParams(hre: HardhatRuntimeEnvironment, provider: provide
maxPriorityFeePerGas: parseUnits('1', 9).toHexString(),
maxFeePerGas: maxFee,
};
} else if (hre.network.config.chainId === 250) {
gasPrice = Math.floor(Math.min(gasPrice * 1.5, 9_000));
// gasPrice = 200;
// console.log('Gas price:', gasPrice);
return {
// gasPrice: '0x' + gasPrice.toString(16),
// gasLimit: 7_000_000,
};
}
return {
gasPrice: '0x' + Math.floor(gasPrice * 1.1).toString(16),
};
}

27 changes: 27 additions & 0 deletions scripts/deploy/DeployerUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import {deployContract} from "./DeployContract";
import {BscAddresses} from "../addresses/BscAddresses";
import {ToolsContractsWrapper} from "../../test/ToolsContractsWrapper";
import {BaseAddresses} from "../addresses/BaseAddresses";
import {ZkevmAddresses} from "../addresses/ZkevmAddresses";

// tslint:disable-next-line:no-var-requires
const hre = require("hardhat");
Expand Down Expand Up @@ -294,6 +295,30 @@ export class DeployerUtils {
return calculator;
}

public static async deployPriceCalculatorV2ZkEvm(signer: SignerWithAddress): Promise<PriceCalculatorV2> {
const logic = await DeployerUtils.deployContract(signer, "PriceCalculatorV2");
const proxy = await DeployerUtils.deployContract(signer, "TetuProxyGov", logic.address) as TetuProxyGov;
console.log("Deployed logic", logic.address);
console.log("Deployed proxy", proxy.address);
const calculator = PriceCalculatorV2__factory.connect(proxy.address, signer);
await RunHelper.runAndWait2ExplicitSigner(signer, calculator.populateTransaction.initialize());

await RunHelper.runAndWait2ExplicitSigner(signer, calculator.populateTransaction.changeKeyTokens([
ZkevmAddresses.USDC_TOKEN,
ZkevmAddresses.WETH_TOKEN,
// ZkevmAddresses.DAI_TOKEN,
ZkevmAddresses.USDT_TOKEN,
], true));

await RunHelper.runAndWait2ExplicitSigner(signer, calculator.populateTransaction.setDefaultToken(ZkevmAddresses.USDC_TOKEN));

// await RunHelper.runAndWait(() => calculator.changeSolidlyFactory(ZkevmAddresses.AERODROME_FACTORY, true));
// await RunHelper.runAndWait(() => calculator.changeUni3Factory(ZkevmAddresses.UNI3_FACTORY, true));
await RunHelper.runAndWait2ExplicitSigner(signer, calculator.populateTransaction.setTetuLiquidator(ZkevmAddresses.TETU_LIQUIDATOR));

return calculator;
}

public static async deployPriceCalculatorFantom(signer: SignerWithAddress, controller: string, wait = false): Promise<[PriceCalculator, TetuProxyGov, PriceCalculator]> {
const logic = await DeployerUtils.deployContract(signer, "PriceCalculator") as PriceCalculator;
const proxy = await DeployerUtils.deployContract(signer, "TetuProxyGov", logic.address) as TetuProxyGov;
Expand Down Expand Up @@ -1152,6 +1177,8 @@ export class DeployerUtils {
return '0xbbbbb8C4364eC2ce52c59D2Ed3E56F307E529a94';
} else if (net.chainId === 8453) {
return BaseAddresses.GOV_ADDRESS;
} else if (net.chainId === 1101) {
return ZkevmAddresses.GOV_ADDRESS;
} else {
throw Error('No config for ' + net.chainId);
}
Expand Down
61 changes: 60 additions & 1 deletion scripts/utils/tools/RunHelper.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {ethers} from "hardhat";
import {ContractTransaction} from "ethers";
import {BigNumber, ContractTransaction, PopulatedTransaction} from "ethers";
import {DeployerUtils} from "../../deploy/DeployerUtils";
import {Logger} from "tslog";
import logSettings from "../../../log_settings";
import {Misc} from "./Misc";
import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
import {formatUnits} from "ethers/lib/utils";

const log: Logger<undefined> = new Logger(logSettings);

Expand Down Expand Up @@ -38,4 +40,61 @@ export class RunHelper {
Misc.printDuration('runAndWait completed', start);
}

public static async runAndWait2(txPopulated: Promise<PopulatedTransaction>, stopOnError = true, wait = true) {
console.log('prepare run and wait2')
const tx = await txPopulated;
const signer = (await ethers.getSigners())[0];
const gas = (await signer.estimateGas(tx)).toNumber()

const params = await RunHelper.txParams();
console.log('params', params)

tx.gasLimit = BigNumber.from(gas).mul(15).div(10);

if (params?.maxFeePerGas) tx.maxFeePerGas = BigNumber.from(params.maxFeePerGas);
if (params?.maxPriorityFeePerGas) tx.maxPriorityFeePerGas = BigNumber.from(params.maxPriorityFeePerGas);
if (params?.gasPrice) tx.gasPrice = BigNumber.from(params.gasPrice);

return RunHelper.runAndWait(() => signer.sendTransaction(tx), stopOnError, wait);
}

public static async runAndWait2ExplicitSigner(signer: SignerWithAddress, txPopulated: Promise<PopulatedTransaction>, stopOnError = true, wait = true) {
console.log('prepare run and wait2')
const tx = await txPopulated;
const gas = (await signer.estimateGas(tx)).toNumber()

const params = await RunHelper.txParams();
console.log('params', params)

tx.gasLimit = BigNumber.from(gas).mul(15).div(10);

if (params?.maxFeePerGas) tx.maxFeePerGas = BigNumber.from(params.maxFeePerGas);
if (params?.maxPriorityFeePerGas) tx.maxPriorityFeePerGas = BigNumber.from(params.maxPriorityFeePerGas);
if (params?.gasPrice) tx.gasPrice = BigNumber.from(params.gasPrice);

return RunHelper.runAndWait(() => signer.sendTransaction(tx), stopOnError, wait);
}

public static async txParams() {
const provider = ethers.provider;
const feeData = await provider.getFeeData();


console.log('maxPriorityFeePerGas', formatUnits(feeData.maxPriorityFeePerGas?.toString() ?? '0', 9));
console.log('maxFeePerGas', formatUnits(feeData.maxFeePerGas?.toString() ?? '0', 9));
console.log('gas price:', formatUnits(feeData.gasPrice?.toString() ?? '0', 9));

if (feeData.maxFeePerGas && feeData.maxPriorityFeePerGas) {
const maxPriorityFeePerGas = Math.max(feeData.maxPriorityFeePerGas?.toNumber() ?? 1, feeData.lastBaseFeePerGas?.toNumber() ?? 1);
const maxFeePerGas = (feeData.maxFeePerGas?.toNumber() ?? 1) * 2;
return {
maxPriorityFeePerGas: maxPriorityFeePerGas.toFixed(0),
maxFeePerGas: maxFeePerGas.toFixed(0),
};
} else {
return {
gasPrice: ((feeData.gasPrice?.toNumber() ?? 1) * 1.2).toFixed(0),
};
}
}
}
Loading
Loading