Skip to content

Commit

Permalink
Merge pull request #213 from Axis-Fi/deployment
Browse files Browse the repository at this point in the history
G-Uni Deployment Scripts
  • Loading branch information
Oighty authored Jul 8, 2024
2 parents 5c6c617 + 5d6d89b commit 90dc724
Show file tree
Hide file tree
Showing 22 changed files with 264 additions and 69 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ docs/
# Dotenv file
.env
.env.*
!.env.example

node_modules/

Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ Then, the test suite can be run with:
pnpm run test
```

#### Address Mismatch

Many of the contracts (e.g. callbacks) require a specific address prefix or have a deterministic address. If tests are failing for this reason, the cause is usually one of:

- The code of a callback contract has been changed
- This requires re-generating the salt for the contract. See the [test_salts.sh](/script/salts/test/test_salts.sh) script.
- There has been a change to the dependencies under `/lib`. The dependencies affect the build output, so any changes will affect the bytecode generated by the Solidity compiler.
- If the submodule change was inadvertent, this can be fixed by running `pnpm run full-install` to reset the changes.
- In some cases, such as the `g-uni-v1-core` dependency, installing npm packages will result in the remappings being changed. It is best to remove the dependency's respective dependencies in order to fix this.
- If the change to dependencies and invalidation of salts is expected, then new salts must be generated. In some cases (such as Uniswap V2 and V3 factories), the new addresses must be recorded in the `Constants.sol` file.

### Format

Combines `forge fmt` and `solhint`
Expand Down
3 changes: 3 additions & 0 deletions deployments/.arbitrum-sepolia-1719558304.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"axis.BatchUniswapV2DirectToLiquidity": "0xE676907Fa9a09dC1E3b67De11816665A1313524f"
}
3 changes: 3 additions & 0 deletions deployments/.base-sepolia-1719558588.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"axis.BatchUniswapV2DirectToLiquidity": "0xE66538D4EEbf830b1Dc791894af4709Af257764d"
}
3 changes: 3 additions & 0 deletions deployments/.blast-sepolia-1719558704.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"axis.BatchUniswapV2DirectToLiquidity": "0xE60007A0721A92f0eb538c360317d4808238700D"
}
3 changes: 3 additions & 0 deletions deployments/.mode-sepolia-1719558822.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"axis.BatchUniswapV2DirectToLiquidity": "0xE60FD6203AF5D5d43433952a033Cb70Ba21784E9"
}
3 changes: 3 additions & 0 deletions lib/g-uni-v1-core/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Wallets
ANVIL_PRIVATE_KEY=
DEPLOYER_PRIVATE_KEY=
41 changes: 41 additions & 0 deletions lib/g-uni-v1-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,44 @@ Arguments:
yarn

yarn test

## Setup

```shell
yarn install
```

Set up environment variables:

- Copy `.env.example` to `.env`
- Fill out environment variables

## Deployment

1. Ensure that the `Gelato`, `GelatoDevMultiSig` and `UniswapV3Factory` addresses are set in `src/addresses.ts` for the target chain.
1. Deploy the GUniPool, as that will serve as input to the GUniFactory:

```shell
HARDHAT_NETWORK="<chain name>" yarn run deploy:pool
```

1. Copy the address of the GUniPool (output to the terminal) into the value of the `GUniImplementation` key in `src/addresses.ts` for the target chain.
1. Deploy the GUniFactory:

```shell
HARDHAT_NETWORK="<chain name>" yarn run deploy:factory
```

Note that these scripts will not deploy to a particular chain if there have been no changes to the contracts since the last deployment on that chain. To override this, pass the `--reset` flag.

## Verification

1. Verify the contracts:

```shell
HARDHAT_NETWORK="<chain name>" yarn run verify
```

- If hardhat reports that a network is not supported, specify the API url using `--api-url <url>`

NOTE: The GUniFactory contract will require additional steps to enable it to be viewed as a proxy.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity 0.8.19;
import {OwnableUninitialized} from "./OwnableUninitialized.sol";
import {
Initializable
} from "@openzeppelin/contracts-upgradeable/utils/Initializable.sol";
} from "contracts/lib/Initializable.sol";
import {
EnumerableSet
} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
Expand Down
50 changes: 50 additions & 0 deletions lib/g-uni-v1-core/contracts/lib/Initializable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version
pragma solidity ^0.8.0;

/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* @dev Copied into repo from OpenZeppelin Contracts v4.1.0
*/
abstract contract Initializable {

/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;

/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;

/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");

bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}

_;

if (isTopLevelCall) {
_initializing = false;
}
}
}
16 changes: 15 additions & 1 deletion lib/g-uni-v1-core/deploy/GUniFactory.deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { deployments, getNamedAccounts } from "hardhat";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
import { getAddresses } from "../src/addresses";
import { isZeroAddress } from "./address";

const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
if (
Expand All @@ -19,7 +20,18 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
const { deployer } = await getNamedAccounts();
const addresses = getAddresses(hre.network.name);

await deploy("GUniFactory", {
// Validate input addresses
if (isZeroAddress(addresses.UniswapV3Factory)) {
throw new Error("UniswapV3Factory address not set");
}
if (isZeroAddress(addresses.GelatoDevMultiSig)) {
throw new Error("GelatoDevMultiSig address not set");
}
if (isZeroAddress(addresses.GUniImplementation)) {
throw new Error("GUniImplementation (pool implementation) address not set");
}

const result = await deploy("GUniFactory", {
from: deployer,
proxy: {
proxyContract: "EIP173Proxy",
Expand All @@ -37,6 +49,8 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
},
args: [addresses.UniswapV3Factory],
});

console.log("GUniFactory deployed to:", result.address);
};

func.skip = async (hre: HardhatRuntimeEnvironment) => {
Expand Down
13 changes: 12 additions & 1 deletion lib/g-uni-v1-core/deploy/GUniPool.deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { deployments, getNamedAccounts } from "hardhat";
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
import { getAddresses } from "../src/addresses";
import { isZeroAddress } from "./address";

const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
if (
Expand All @@ -19,10 +20,20 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
const { deployer } = await getNamedAccounts();
const addresses = getAddresses(hre.network.name);

await deploy("GUniPool", {
// Validate input addresses
if (isZeroAddress(addresses.Gelato)) {
throw new Error("Gelato address not set");
}
if (isZeroAddress(deployer)) {
throw new Error("Deployer address not set");
}

const result = await deploy("GUniPool", {
from: deployer,
args: [addresses.Gelato],
});

console.log("GUniPool deployed to:", result.address);
};

func.skip = async (hre: HardhatRuntimeEnvironment) => {
Expand Down
2 changes: 2 additions & 0 deletions lib/g-uni-v1-core/deploy/address.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

export const isZeroAddress = (address: string): boolean => !address || address === "" || address === "0x0000000000000000000000000000000000000000";
21 changes: 12 additions & 9 deletions lib/g-uni-v1-core/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,27 @@ const config: HardhatUserConfig = {
anvil: {
chainId: 31337,
url: "http://localhost:8545",
accounts: [process.env.ANVIL_PRIVATE_KEY ?? ""]
accounts: [process.env.ANVIL_PRIVATE_KEY ?? ""],
},
blastSepolia: {
chainId: 168587773,
url: process.env.BLAST_SEPOLIA_RPC,
accounts: [process.env.DEPLOYER_PRIVATE_KEY ?? ""]
url: process.env.BLAST_SEPOLIA_RPC || "https://sepolia.blast.io",
accounts: [process.env.DEPLOYER_PRIVATE_KEY ?? ""],
},
arbitrumSepolia: {
chainId: 421614,
url: process.env.ARBITRUM_SEPOLIA_RPC,
accounts: [process.env.DEPLOYER_PRIVATE_KEY ?? ""]
url: process.env.ARBITRUM_SEPOLIA_RPC || "https://sepolia-rollup.arbitrum.io/rpc",
accounts: [process.env.DEPLOYER_PRIVATE_KEY ?? ""],
},
modeSepolia: {
chainId: 919,
url: process.env.MODE_SEPOLIA_RPC,
accounts: [process.env.DEPLOYER_PRIVATE_KEY ?? ""]
url: process.env.MODE_SEPOLIA_RPC || "https://sepolia.mode.network",
accounts: [process.env.DEPLOYER_PRIVATE_KEY ?? ""],
},
baseSepolia: {
chainId: 84532,
url: process.env.BASE_SEPOLIA_RPC,
accounts: [process.env.DEPLOYER_PRIVATE_KEY ?? ""]
url: process.env.BASE_SEPOLIA_RPC || "https://sepolia.base.org",
accounts: [process.env.DEPLOYER_PRIVATE_KEY ?? ""],
},
mantleSepolia: {
chainId: 5003,
Expand Down Expand Up @@ -80,6 +80,9 @@ const config: HardhatUserConfig = {
outDir: "typechain",
target: "ethers-v5",
},
etherscan: {
apiKey: process.env[`${process.env.HARDHAT_NETWORK}_ETHERSCAN_API_KEY`],
}
};

export default config;
5 changes: 3 additions & 2 deletions lib/g-uni-v1-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"build": "yarn compile && npx tsc",
"compile": "npx hardhat compile",
"clean": "rm -rf dist && npx hardhat clean",
"deploy": "npx hardhat deploy ",
"deploy:pool": "npx hardhat deploy --tags GUniPool --write true",
"deploy:factory": "npx hardhat deploy --tags GUniFactory --write true",
"format": "prettier --write .",
"format:check": "prettier --check '*/**/*.{js,sol,json,md,ts}'",
"lint": "eslint --cache . && yarn lint:sol",
Expand Down Expand Up @@ -36,7 +37,7 @@
"ethereum-waffle": "3.3.0",
"ethers": "5.1.4",
"hardhat": "2.3.0",
"hardhat-deploy": "0.9.14",
"hardhat-deploy": "0.10.0",
"husky": "6.0.0",
"lint-staged": "11.0.0",
"node-fetch": "2.6.1",
Expand Down
8 changes: 4 additions & 4 deletions lib/g-uni-v1-core/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5120,10 +5120,10 @@ har-validator@~5.1.3:
ajv "^6.12.3"
har-schema "^2.0.0"

hardhat-deploy@0.9.14:
version "0.9.14"
resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.9.14.tgz#88c07497efd14cfca6f9fed1574f0bad65f0a8a0"
integrity sha512-mCwXeXdqtrQN8dL1gOnoGUh0z9Jylfsh56UNVZJC0c8AhjlwjLPgGE3pzNmMuyy88pj9OX4qo53X57bW2W7NJQ==
hardhat-deploy@0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.10.0.tgz#6b98790010dd3f1f362c4ad45207e43c8511eadd"
integrity sha512-C6p0IvdK2CK0fIsdUK0dM+nuhCmDvuL8fi19RUPeSMMfl7BityJArAzVbJt5f68VJ3CZRMa5WV7aSc8M8sNHvg==
dependencies:
"@ethersproject/abi" "^5.4.0"
"@ethersproject/abstract-signer" "^5.4.1"
Expand Down
15 changes: 15 additions & 0 deletions script/deploy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,18 @@ CHAIN="blast-sepolia" ./script/deploy/deploy.sh --deployFile ./script/deploy/seq
If the `verify` flag on `deploy.sh` is set, the contract should be verified automatically. If `VERIFIER` is blank or `etherscan`, then `ETHERSCAN_API_KEY` must be set as an environment variable. Additionally, `VERIFIER_URL` can be used to set a custom verifier URL (by default it uses the one configurd in ethers-rs).

If deploying against a Tenderly fork and verifying, [follow the instructions](https://docs.tenderly.co/contract-verification).

## External Dependencies

Note that for each chain Axis is to be deployed on, if the Uniswap V3 DTL callback is to be used, a deployment of G-UNI will be required.

Apart from first-party deployments, the `script/env.json` file contains the addresses of third-party dependencies. These have been sourced from the following locations:

- [Uniswap V2](https://github.com/Uniswap/docs/blob/65d3f21e6cb2879b0672ad791563de0e54fcc089/docs/contracts/v2/reference/smart-contracts/08-deployment-addresses.md)
- Exceptions
- Arbitrum Sepolia, Base Sepolia, Blast Sepolia and Mode Sepolia are custom deployments, due to the unavailability of the Uniswap V2 contracts.
- [Uniswap V3](https://github.com/Uniswap/docs/tree/65d3f21e6cb2879b0672ad791563de0e54fcc089/docs/contracts/v3/reference/deployments)
- Exceptions
- Arbitrum Sepolia and Blast Sepolia are custom deployments by Axis Finance alongside the G-UNI deployment.
- G-UNI
- All of the addresses mentioned are custom deployments by Axis Finance. This is because the addresses from the deployments recorded in the [g-uni-v1-core repository](https://github.com/gelatodigital/g-uni-v1-core/tree/bea63422e2155242b051896b635508b7a99d2a1a/deployments) point to proxies, which have since been upgraded to point to Arrakis contracts that have different interfaces.
Loading

0 comments on commit 90dc724

Please sign in to comment.