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
Changes from 1 commit
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
Next Next commit
Add support for zkevm. Add deployPriceCalculatorV2ZkEvm to create Pri…
…ceCalculator2 on zkevm
dvpublic committed Dec 29, 2023
commit 29ac03df4c2e8a527e96cacfd8cafae926a39a1b
34 changes: 31 additions & 3 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
@@ -48,6 +48,9 @@ const argv = require('yargs/yargs')()
type: "string",
default: ''
},
zkevmRpcUrl: {
type: "string",
},
infuraKey: {
type: "string",
},
@@ -63,6 +66,9 @@ const argv = require('yargs/yargs')()
networkScanKeyBsc: {
type: "string",
},
networkScanKeyZkevm: {
type: "string",
},
privateKey: {
type: "string",
default: "85bb5fa78d5c4ed1fde856e9d0d1fe19973d7a79ce9ed6c0358ee06a4550504e" // random account
@@ -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",
@@ -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
@@ -254,6 +273,7 @@ export default {
skale_test: 'any',
imm_test: 'any',
base: argv.networkScanKeyBase,
zkevm: argv.networkScanKeyZkevm || argv.networkScanKey,
},
customChains: [
{
@@ -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: {
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()


}
25 changes: 25 additions & 0 deletions scripts/deploy/DeployerUtils.ts
Original file line number Diff line number Diff line change
@@ -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");
@@ -294,6 +295,28 @@ 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;
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;
@@ -1152,6 +1175,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);
}
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);

@@ -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),
};
}
}
}
75 changes: 75 additions & 0 deletions test/tools/PriceCalculatorV2ZkevmTest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import chai from "chai";
import chaiAsPromised from "chai-as-promised";
import {SignerWithAddress} from "@nomiclabs/hardhat-ethers/signers";
import {DeployerUtils} from "../../scripts/deploy/DeployerUtils";
import {TimeUtils} from "../TimeUtils";
import {PriceCalculatorV2} from "../../typechain";
import {PriceCalculatorUtils} from "../PriceCalculatorUtils";
import {ZkevmAddresses} from "../../scripts/addresses/ZkevmAddresses";

const {expect} = chai;
chai.use(chaiAsPromised);

const NETWORK = 1101;

describe("PriceCalculatorV2ZkevmTest", function () {
let snapshot: string;
let snapshotForEach: string;
let signer: SignerWithAddress;
let calculator: PriceCalculatorV2;


before(async function () {
snapshot = await TimeUtils.snapshot();
if (!(await DeployerUtils.isNetwork(NETWORK))) {
return;
}
signer = await DeployerUtils.impersonate();
calculator = await DeployerUtils.deployPriceCalculatorV2ZkEvm(signer);
});

after(async function () {
await TimeUtils.rollback(snapshot);
});

beforeEach(async function () {
snapshotForEach = await TimeUtils.snapshot();
});

afterEach(async function () {
await TimeUtils.rollback(snapshotForEach);
});

it("calculate all prices", async () => {
if (!(await DeployerUtils.isNetwork(NETWORK))) {return;}
await PriceCalculatorUtils.getFormattedPrice(calculator, ZkevmAddresses.WETH_TOKEN, ZkevmAddresses.USDC_TOKEN);
await PriceCalculatorUtils.getFormattedPrice(calculator, ZkevmAddresses.TETU_TOKEN, ZkevmAddresses.USDC_TOKEN);
await PriceCalculatorUtils.getFormattedPrice(calculator, ZkevmAddresses.USDT_TOKEN, ZkevmAddresses.USDC_TOKEN);
// await PriceCalculatorUtils.getFormattedPrice(calculator, ZkevmAddresses.DAI_TOKEN, ZkevmAddresses.USDC_TOKEN);
await PriceCalculatorUtils.getFormattedPrice(calculator, ZkevmAddresses.USDC_TOKEN, ZkevmAddresses.USDT_TOKEN);
// await PriceCalculatorUtils.getFormattedPrice(calculator, ZkevmAddresses.WELL_TOKEN, ZkevmAddresses.USDT_TOKEN);
// await PriceCalculatorUtils.getFormattedPrice(calculator, ZkevmAddresses.axlUSDC_TOKEN, ZkevmAddresses.USDT_TOKEN);
// await PriceCalculatorUtils.getFormattedPrice(calculator, ZkevmAddresses.crvUSD_TOKEN, ZkevmAddresses.USDT_TOKEN);
// await PriceCalculatorUtils.getFormattedPrice(calculator, ZkevmAddresses.CRV_TOKEN, ZkevmAddresses.USDT_TOKEN);
// await PriceCalculatorUtils.getFormattedPrice(calculator, ZkevmAddresses.TETU_tUSDbC_AERODROME_LP, ZkevmAddresses.USDT_TOKEN);
// await PriceCalculatorUtils.getFormattedPrice(calculator, ZkevmAddresses.USDbC_tUSDbC_AERODROME_LP, ZkevmAddresses.USDT_TOKEN);
});


it("tetu price", async () => {
await checkPrice(calculator, ZkevmAddresses.TETU_TOKEN, 0.001, 1);
});

// it("TETU_tUSDbC_AERODROME_LP price", async () => {
// await checkPrice(calculator, ZkevmAddresses.TETU_tUSDbC_AERODROME_LP, 1000, 1000000);
// });

});


async function checkPrice(calculator: PriceCalculatorV2, token: string, minPrice: number, maxPrice: number) {
if (!(await DeployerUtils.isNetwork(NETWORK))) {return;}
const price = await PriceCalculatorUtils.getFormattedPrice(calculator, token, ZkevmAddresses.USDC_TOKEN);
expect(price).is.greaterThan(minPrice);
expect(price).is.lessThan(maxPrice);
}