Skip to content

Commit

Permalink
fix: Tenderly integration (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
Whytecrowe authored Jul 5, 2023
2 parents cc30cdf + 19e1ba7 commit 7bf2ecf
Show file tree
Hide file tree
Showing 19 changed files with 459 additions and 147 deletions.
7 changes: 7 additions & 0 deletions contracts/oz-proxies/ERC1967ProxyAcc.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";


abstract contract ERC1967ProxyAcc is ERC1967Proxy {}
7 changes: 7 additions & 0 deletions contracts/oz-proxies/TransparentUpgradeableProxyAcc.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";


abstract contract TransparentUpgradeableProxyAcc is TransparentUpgradeableProxy {}
43 changes: 31 additions & 12 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ import "@nomicfoundation/hardhat-chai-matchers";
import "@openzeppelin/hardhat-upgrades";
import "solidity-coverage";

// This call is needed to initialize Tenderly with Hardhat,
// the automatic verifications, though, don't seem to work,
// needing us to verify explicitly in code, however,
// for Tenderly to work properly with Hardhat this method
// needs to be called. The call below is commented out
// because if we leave it here, solidity-coverage
// does not work properly locally or in CI, so we
// keep it commented out and uncomment when using DevNet
// locally.
// !!! Uncomment this when using Tenderly DevNet !!!
tenderly.setup({ automaticVerifications: false });

const config : HardhatUserConfig = {
solidity: {
Expand All @@ -24,6 +35,26 @@ const config : HardhatUserConfig = {
},
},
],
overrides: {
"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": {
version: "0.8.9",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
"@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol": {
version: "0.8.9",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},
},
},
paths: {
sources: "./contracts",
Expand Down Expand Up @@ -61,16 +92,4 @@ const config : HardhatUserConfig = {
},
};

// This call is needed to initialize Tenderly with Hardhat,
// the automatic verifications, though, don't seem to work,
// needing us to verify explicitly in code, however,
// for Tenderly to work properly with Hardhat this method
// needs to be called. The call below is commented out
// because if we leave it here, solidity-coverage
// does not work properly locally or in CI, so we
// keep it commented out and uncomment when using DevNet
// locally.
// !!! Uncomment this when using Tenderly DevNet !!!
// tenderly.setup({ automaticVerifications: true });

export default config;
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"semantic-release": "semantic-release --tag-format='v${version}-dev'",
"coverage": "hardhat coverage",
"check-coverage": "istanbul check-coverage --statements 90 --branches 87 --functions 89 --lines 90",
"devnet": "ts-node src/tenderly/devnet-execute.ts"
"devnet": "ts-node src/tenderly/devnet/devnet-execute.ts",
"gas-cost": "ts-node src/utils/gas-costs.ts"
},
"pre-commit": [
"lint"
Expand All @@ -37,8 +38,8 @@
"@openzeppelin/contracts": "4.8.3",
"@openzeppelin/contracts-upgradeable": "4.8.3",
"@openzeppelin/hardhat-upgrades": "1.26.0",
"@tenderly/hardhat-tenderly": "^1.7.4",
"@semantic-release/git": "^10.0.1",
"@tenderly/hardhat-tenderly": "^1.7.4",
"@typechain/ethers-v5": "10.1.0",
"@typechain/hardhat": "6.1.2",
"@types/chai": "4.2.0",
Expand All @@ -60,6 +61,7 @@
"typescript": "^5.0.2"
},
"dependencies": {
"axios": "^1.4.0",
"dotenv": "16.0.3"
},
"resolutions": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { exec } from "child_process";

const execAsync = promisify(exec);

const spawnCommand = "ts-node src/tenderly/spawn-devnet.ts";
const spawnCommand = "ts-node src/tenderly/devnet/spawn-devnet.ts";
const opCommandBase = "npx hardhat run";
const networkArg = "--network devnet";
const opsPath = "src/tenderly/run-all-flows.ts";
const opsPath = "src/tenderly/devnet/run-all-flows.ts";

/**
* Top level function to execute everything on the DevNet.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import * as hre from "hardhat";
import * as ethers from "ethers";
import { deployZNS, hashDomainLabel } from "../../test/helpers";
import { BigNumber } from "ethers";
import {
deployZNS,
hashDomainLabel,
} from "../../../test/helpers";


const domainName = "wilder";
Expand All @@ -19,7 +22,7 @@ export const runAllFlows = async () => {
deployer: governor,
governorAddresses: [governor.address],
adminAddresses: [governor.address],
logAddresses: true,
isTenderlyRun: true,
});

// get some funds for the user
Expand Down
File renamed without changes.
19 changes: 19 additions & 0 deletions src/tenderly/playground/create-playground.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { forkNetwork } from "./fork";
import * as ethers from "ethers";


export const forkRpcUrlBase = "https://rpc.tenderly.co/fork";

export const createPlayground = async ({
networkId = "1",
blockNumber = 14537885,
} = {}) => {
const forkId = await forkNetwork({
networkId,
blockNumber,
});

const forkURL = `${forkRpcUrlBase}/${forkId}`;

return new ethers.providers.JsonRpcProvider(forkURL);
};
31 changes: 31 additions & 0 deletions src/tenderly/playground/fork-execute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { deleteFork, forkNetwork } from "./fork";

// Arguments for direct execution:
// no argument or "new" - to create a new fork
// "del" + "forkURL" - to delete the fork
const operation = process.argv[2];

if (operation === "new" || !operation) {
forkNetwork()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
} else if (operation === "del") {
const forkURL = process.argv[3];
if (!forkURL) {
console.error("Fork URL is required to delete a fork");
process.exit(1);
}

deleteFork(forkURL)
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
} else {
console.error("Invalid operation. Make sure you pass the correct arguments.");
process.exit(1);
}
48 changes: 48 additions & 0 deletions src/tenderly/playground/fork.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// TODO: Move all the Tenderly related logic from here to it's own repo/package

import axios from "axios";
import dotenv from "dotenv";

dotenv.config();

const {
TENDERLY_ACCOUNT_ID,
TENDERLY_PROJECT_SLUG,
TENDERLY_ACCESS_KEY,
} = process.env;

const TENDERLY_FORK_API =
`http://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT_SLUG}/fork`;

const opts = {
headers: {
"X-Access-Key": TENDERLY_ACCESS_KEY as string,
},
};


export const forkNetwork = async ({
networkId = "1",
blockNumber = 14537885,
} = {}) => {
const body = {
"network_id": networkId,
"block_number": blockNumber,
};

const {
data: {
simulation_fork: {
id: forkId,
},
},
} = await axios.post(TENDERLY_FORK_API, body, opts);

const forkURL = `${TENDERLY_FORK_API}/${forkId}`;
console.log(`FORK URL: ${forkURL}`);

return forkId;
};

export const deleteFork = async (forkURL : string) =>
axios.delete(forkURL, opts);
14 changes: 14 additions & 0 deletions src/tenderly/playground/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ethers } from "ethers";

export const getEther = async (
walletAddress : string,
amountHex = ethers.utils.hexValue(100), // hex encoded wei amount
provider : ethers.providers.JsonRpcProvider,
) : Promise<void> => {
const params = [
[walletAddress],
amountHex,
];

await provider.send("tenderly_addBalance", params);
};
43 changes: 43 additions & 0 deletions src/utils/gas-costs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { BigNumber } from "ethers";


export const ethMultiplier = BigNumber.from(10).pow(18);

export const calcGasCostInCurrency = (
gas : string,
gasPriceInGwei : string,
ethPriceInUSD : string,
) => {
let cost;
let currency = "WEI";
cost = BigNumber.from(gas)
.mul(BigNumber.from(gasPriceInGwei))
.mul(ethMultiplier)
.div(BigNumber.from(10).pow(9));

if (!!ethPriceInUSD) {
currency = "USD WEI";
cost = cost.mul(BigNumber.from(ethPriceInUSD));
}

return { cost, currency };
};


// Execute
const [
gasArg,
gasPriceArg,
ethPriceArg,
] = process.argv.slice(2);

const {
cost: totalCost,
currency: costCurrency,
} = calcGasCostInCurrency(gasArg, gasPriceArg, ethPriceArg);

console.log(`Total cost: ${totalCost.toString()} ${costCurrency}`);

// register (14 gwei, $1856) = $8.84 (ENS = $8.49)
// reclaim (14 gwei, $1856) = $1.71
// revoke (14 gwei, $1856) = $3.03
4 changes: 2 additions & 2 deletions tenderly.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
account_id: e750f9f2-65bc-4765-84a8-7f8dbddd73ee
exports:
hardhat:
project_slug: zer0-os/zns
project_slug: zer0-os/zns-1
rpc_address: 127.0.0.1:8545
protocol: ""
forked_network: Mainnet
Expand All @@ -17,5 +17,5 @@ exports:
istanbul_block: 0
berlin_block: 0
london_block: 0
project_slug: zns
project_slug: zer0-os/zns-1
provider: ""
24 changes: 0 additions & 24 deletions test/helpers/access.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { ZNSAccessController, ZNSAccessController__factory } from "../../typechain";
import { ethers } from "ethers";


Expand All @@ -22,25 +20,3 @@ export const EXECUTOR_ROLE = ethers.utils.solidityKeccak256(
["EXECUTOR_ROLE"]
);

export const deployAccessController = async ({
deployer,
governorAddresses,
adminAddresses,
logAddress,
} : {
deployer : SignerWithAddress;
governorAddresses : Array<string>;
adminAddresses : Array<string>;
logAddress : boolean;
}) : Promise<ZNSAccessController> => {
const accessControllerFactory = new ZNSAccessController__factory(deployer);
const controller = await accessControllerFactory.deploy();

await controller.deployed();

await controller.initialize(governorAddresses, adminAddresses);

if (logAddress) console.log(`AccessController deployed at: ${controller.address}`);

return controller;
};
5 changes: 3 additions & 2 deletions test/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ export const implSlotErc1967 = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735
export const accessControllerName = "ZNSAccessController";
export const registryName = "ZNSRegistry";
export const domainTokenName = "ZNSDomainToken";
export const zeroTokenMockName = "ZeroTokenMock";
export const zeroTokenMockName = "ZeroToken";
export const addressResolverName = "ZNSAddressResolver";
export const priceOracleName = "ZNSPriceOracle";
export const treasuryName = "ZNSTreasury";
export const registrarName = "ZNSRegistrar";

export const erc1967ProxyName = "ERC1967Proxy";
export const transparentProxyName = "TransparentUpgradeableProxy";
Loading

0 comments on commit 7bf2ecf

Please sign in to comment.