Skip to content

Commit

Permalink
feat: add base deployments (#4729)
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Maldonado <[email protected]>
  • Loading branch information
md0x authored Mar 27, 2024
1 parent 4ca19ec commit 36e740d
Show file tree
Hide file tree
Showing 16 changed files with 242 additions and 29 deletions.
16 changes: 15 additions & 1 deletion packages/common/src/HardhatConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export function getHardhatConfig(
chainId: 1,
url: getNodeUrl("mainnet", true, 1),
accounts: { mnemonic },
companionNetworks: { arbitrum: "arbitrum", optimism: "optimism", boba: "boba", xdai: "xdai" },
companionNetworks: { arbitrum: "arbitrum", optimism: "optimism", boba: "boba", xdai: "xdai", base: "base" },
},
rinkeby: { chainId: 4, url: getNodeUrl("rinkeby", true, 4), accounts: { mnemonic } },
goerli: { chainId: 5, url: getNodeUrl("goerli", true, 5), accounts: { mnemonic } },
Expand All @@ -118,6 +118,12 @@ export function getHardhatConfig(
url: getNodeUrl("blast-sepolia", true, 168587773),
accounts: { mnemonic },
},
base: {
chainId: 8453,
url: getNodeUrl("base", true, 8453),
accounts: { mnemonic },
companionNetworks: { mainnet: "mainnet" },
},
kovan: { chainId: 42, url: getNodeUrl("kovan", true, 42), accounts: { mnemonic } },
optimism: {
chainId: 10,
Expand Down Expand Up @@ -213,6 +219,14 @@ export function getHardhatConfig(
browserURL: "https://goerli.basescan.org",
},
},
{
network: "base",
chainId: 8453,
urls: {
apiURL: "https://api.basescan.org/api",
browserURL: "https://basescan.org",
},
},
{
network: "blast-sepolia",
chainId: 168587773,
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/ProviderUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export function getNodeUrl(networkName: string, useHttps = false, chainId: numbe
if (name === "blast-sepolia") return overrideUrl || "https://sepolia.blast.io";
if (name === "core") return overrideUrl || "https://rpc.coredao.org/";
if (name === "base-goerli") return overrideUrl || "https://goerli.base.org";
if (name === "base") return overrideUrl || "https://mainnet.base.org";
return (
overrideUrl ||
(useHttps ? `https://${name}.infura.io/v3/${infuraApiKey}` : `wss://${name}.infura.io/ws/v3/${infuraApiKey}`)
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/TimeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export async function averageBlockTimeSeconds(chainId?: number): Promise<number>
return 3;
case 1116:
return 3;
case 8453:
return 2;
case 1:
return defaultBlockTimeSeconds;
default:
Expand Down
18 changes: 18 additions & 0 deletions packages/common/src/hardhat/tasks/collateralWhitelist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,12 @@ async function findL2TokenForL1Token(l1Web3: Web3, l2Web3: Web3, l2chainid: numb
return await _findL2TokenForOvmChain(l2Web3, l1TokenAddress);
}

if (l2chainid == 8453) {
const foundOnChain = await _findL2TokenForOvmChain(l2Web3, l1TokenAddress);
if (foundOnChain != ZERO_ADDRESS) return foundOnChain;
else return await _findL2TokenFromTokenList(l1Web3, l2chainid, l1TokenAddress);
}

if (l2chainid == 42161) {
return await _findL2TokenFromTokenList(l1Web3, l2chainid, l1TokenAddress);
}
Expand All @@ -283,6 +289,18 @@ async function _findL2TokenFromTokenList(l1Web3: Web3, l2chainid: number, l1Toke
if (!searchSymbol) return ZERO_ADDRESS;
return tokenList.find((element: any) => element.chainId == 10 && element.symbol == searchSymbol).address;
}
if (l2chainid == 8453) {
// See https://docs.base.org/tokens/list/ for more information
const response = await fetch("https://static.optimism.io/optimism.tokenlist.json");
const body = await response.text();
const tokenList = JSON.parse(body).tokens;
const searchSymbol = tokenList.find(
(element: any) => element.chainId == 1 && element.address.toLowerCase() == l1TokenAddress.toLowerCase()
)?.symbol;
if (!searchSymbol) return ZERO_ADDRESS;
const found = tokenList.find((element: any) => element.chainId == 8453 && element.symbol == searchSymbol);
return found?.address ?? ZERO_ADDRESS;
}
if (l2chainid == 42161) {
const response = await fetch("https://bridge.arbitrum.io/token-list-42161.json");
const body = await response.text();
Expand Down
57 changes: 51 additions & 6 deletions packages/common/src/hardhat/tasks/xchainSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Web3 from "web3";
const { utf8ToHex, toBN } = Web3.utils;
const assert = require("assert");

const L2_CHAIN_NAMES = ["arbitrum", "optimism", "boba"];
const L2_CHAIN_NAMES = ["arbitrum", "optimism", "boba", "base"];
L2_CHAIN_NAMES.forEach((chainName) =>
assert(isPublicNetwork(chainName), "L2_CHAIN_NAMES contains invalid public network name")
);
Expand Down Expand Up @@ -156,9 +156,11 @@ async function setupOvmBasedL1Chain(hre_: any, chainId: number) {
console.log(`Found OracleHub @ ${oracleHub.options.address}`);
console.log(`Found GovernorHub @ ${governorHub.options.address}`);

const OracleSpoke = await companionNetworks.optimism.deployments.get("OracleSpoke");
const ChildMessenger = await companionNetworks.optimism.deployments.get(`${chainName}_ChildMessenger`);
const GovernorSpoke = await companionNetworks.optimism.deployments.get("GovernorSpoke");
const OracleSpoke = await companionNetworks[chainName.toLowerCase()].deployments.get("OracleSpoke");
const ChildMessenger = await companionNetworks[chainName.toLowerCase()].deployments.get(
`${chainName}_ChildMessenger`
);
const GovernorSpoke = await companionNetworks[chainName.toLowerCase()].deployments.get("GovernorSpoke");

await setupParentMessenger(messenger, deployer, ChildMessenger, OracleHub, GovernorHub, OracleSpoke, GovernorSpoke);

Expand Down Expand Up @@ -277,6 +279,13 @@ task("setup-l1-boba-xchain", "Configures L1 cross chain smart contracts for Boba
await setupOvmBasedL1Chain(hre_, 288);
});

task("setup-l1-base-xchain", "Configures L1 cross chain smart contracts for Base bridge").setAction(async function (
_,
hre_
) {
await setupOvmBasedL1Chain(hre_, 8453);
});

task("setup-l1-optimism-xchain", "Configures L1 cross chain smart contracts for Optimism bridge").setAction(
async function (_, hre_) {
await setupOvmBasedL1Chain(hre_, 10);
Expand Down Expand Up @@ -353,11 +362,13 @@ task("verify-xchain", "Checks ownership state of cross chain smart contracts")
l2IdentifierWhitelist,
l2AddressWhitelist,
l2OptimisticOracle,
l2OptimisticOracleV2,
l2OptimisticOracleV3,
l2Finder,
] = await Promise.all([
deployments.get("GovernorHub"),
deployments.get("OracleHub"),
deployments.get("Governor"),
deployments.get("GovernorV2"),
deployments.get(`${l2ChainName}_ParentMessenger`),
companionNetworkGet(`${l2ChainName}_ChildMessenger`),
companionNetworkGet(`OracleSpoke`),
Expand All @@ -368,6 +379,8 @@ task("verify-xchain", "Checks ownership state of cross chain smart contracts")
companionNetworkGet(`IdentifierWhitelist`),
companionNetworkGet(`AddressWhitelist`),
companionNetworkGet(`OptimisticOracle`),
companionNetworkGet(`OptimisticOracleV2`),
companionNetworkGet(`OptimisticOracleV3`),
companionNetworkGet(`Finder`),
]);

Expand Down Expand Up @@ -456,11 +469,20 @@ task("verify-xchain", "Checks ownership state of cross chain smart contracts")

console.group("Registry");
const l2RegistryContract = new l2Web3.eth.Contract(l2Registry.abi, l2Registry.address);
const [optimisticOracleRegistered, l2RegistryOwner] = await Promise.all([
const [
optimisticOracleRegistered,
optimisticOracleV2Registered,
optimisticOracleV3Registered,
l2RegistryOwner,
] = await Promise.all([
l2RegistryContract.methods.isContractRegistered(l2OptimisticOracle.address).call(),
l2RegistryContract.methods.isContractRegistered(l2OptimisticOracleV2.address).call(),
l2RegistryContract.methods.isContractRegistered(l2OptimisticOracleV3.address).call(),
l2RegistryContract.methods.getMember(0).call(),
]);
console.log(`- OptimisticOracle registered: ${optimisticOracleRegistered ? "✅" : "❌"}`);
console.log(`- OptimisticOracleV2 registered: ${optimisticOracleV2Registered ? "✅" : "❌"}`);
console.log(`- OptimisticOracleV3 registered: ${optimisticOracleV3Registered ? "✅" : "❌"}`);
console.log(`- Owned by GovernorSpoke: ${l2RegistryOwner === governorSpoke.address ? "✅" : "❌"}`);
console.groupEnd();

Expand All @@ -479,6 +501,15 @@ task("verify-xchain", "Checks ownership state of cross chain smart contracts")
console.log(`- Owned by GovernorSpoke: ${l2IdentifierWhitelistOwner === governorSpoke.address ? "✅" : "❌"}`);
console.groupEnd();

console.group("OptimisticOracleV3");
const l2OptimisticOracleV3Contract = new l2Web3.eth.Contract(
l2OptimisticOracleV3.abi,
l2OptimisticOracleV3.address
);
const [l2OptimisticOracleV3Owner] = await Promise.all([l2OptimisticOracleV3Contract.methods.owner().call()]);
console.log(`- Owned by GovernorSpoke: ${l2OptimisticOracleV3Owner === governorSpoke.address ? "✅" : "❌"}`);
console.groupEnd();

console.group("AddressWhitelist");
const l2AddressWhitelistContract = new l2Web3.eth.Contract(l2AddressWhitelist.abi, l2AddressWhitelist.address);
const [l2AddressWhitelistOwner] = await Promise.all([l2AddressWhitelistContract.methods.owner().call()]);
Expand All @@ -504,6 +535,8 @@ task("verify-xchain", "Checks ownership state of cross chain smart contracts")
l2FinderAddressWhitelist,
l2FinderOracle,
l2FinderOptimisticOracle,
l2FinderOptimisticOracleV2,
l2FinderOptimisticOracleV3,
l2FinderChildMessenger,
] = await Promise.all([
l2FinderContract.methods.owner().call(),
Expand All @@ -512,6 +545,8 @@ task("verify-xchain", "Checks ownership state of cross chain smart contracts")
l2FinderContract.methods.interfacesImplemented(utf8ToHex(interfaceName.CollateralWhitelist)).call(),
l2FinderContract.methods.interfacesImplemented(utf8ToHex(interfaceName.Oracle)).call(),
l2FinderContract.methods.interfacesImplemented(utf8ToHex(interfaceName.OptimisticOracle)).call(),
l2FinderContract.methods.interfacesImplemented(utf8ToHex(interfaceName.OptimisticOracleV2)).call(),
l2FinderContract.methods.interfacesImplemented(utf8ToHex(interfaceName.OptimisticOracleV3)).call(),
l2FinderContract.methods.interfacesImplemented(utf8ToHex(interfaceName.ChildMessenger)).call(),
]);
console.log(`- Owned by GovernorSpoke: ${l2FinderOwner === governorSpoke.address ? "✅" : "❌"}`);
Expand All @@ -536,6 +571,16 @@ task("verify-xchain", "Checks ownership state of cross chain smart contracts")
l2FinderOptimisticOracle === l2OptimisticOracle.address ? "✅" : "❌"
}`
);
console.log(
`- Set "${interfaceName.OptimisticOracleV2}" in Finder: ${
l2FinderOptimisticOracleV2 === l2OptimisticOracleV2.address ? "✅" : "❌"
}`
);
console.log(
`- Set "${interfaceName.OptimisticOracleV3}" in Finder: ${
l2FinderOptimisticOracleV3 === l2OptimisticOracleV3.address ? "✅" : "❌"
}`
);
console.log(
`- Set "${interfaceName.ChildMessenger}" in Finder: ${
l2FinderChildMessenger === childMessenger.address ? "✅" : "❌"
Expand Down
51 changes: 34 additions & 17 deletions packages/core/contracts/cross-chain-oracle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Note: in the commands below, you'll need to set the relevant `NODE_URL_X` enviro

If you're having trouble redeploying contracts because `hardhat` wants to "reuse" contracts, then run `yarn clean && yarn` in the `core` package to reset `deployments`.

## Step-by-step guide to deployments on rollups: Arbitrum, Boba and Optimism
## Step-by-step guide to deployments on rollups: Arbitrum, Boba, Optimism and Base

The steps below explain how to deploy the cross-chain oracle onto supported rollups.

Expand All @@ -39,25 +39,26 @@ export NODE_URL_1=<MAINNET_URL>
export NODE_URL_42161=<ARBITRUM_URL>
export NODE_URL_288=<BOBA_URL>
export NODE_URL_10=<OPTIMISM_URL>
export NODE_URL_8453=<BASE_URL>
export MNEMONIC="Your 12-word mnemonic here"
```

2. Deploy mainnet contracts. Note that the following commands are slightly different based on which L2 you're deploying to.

```sh
yarn hardhat deploy --network mainnet --tags [l1-arbitrum-xchain/l1-boba-xchain/l1-optimism-xchain]
yarn hardhat deploy --network mainnet --tags [l1-arbitrum-xchain/l1-boba-xchain/l1-optimism-xchain/l1-base-xchain]
```

Add the deployed [Arbitrum/Boba/Optimism]\_ParentMessenger contract to the associated networks file.
Add the deployed [Arbitrum/Boba/Optimism/Base]\_ParentMessenger contract to the associated networks file.

3. Deploy l2 contracts:

```sh
yarn hardhat deploy --network [arbitrum/boba/optimism] --tags [l2-arbitrum-xchain/l2-boba-xchain/l2-optimism-xchain],Registry
yarn hardhat deploy --network [arbitrum/boba/optimism/base] --tags [l2-arbitrum-xchain/l2-boba-xchain/l2-optimism-xchain/l2-base-xchain],Registry

```

Add the deployed [Arbitrum/Boba/Optimism] Registry, finder, OracleSpoke, GovernorSpoke and x_ChildMessenger contracts to the associated networks file.
Add the deployed [Arbitrum/Boba/Optimism/Base] Registry, finder, OracleSpoke, GovernorSpoke and x_ChildMessenger contracts to the associated networks file.

4. Verify contracts:

Expand All @@ -70,24 +71,26 @@ yarn hardhat --network arbitrum etherscan-verify --api-key <ETHERSCAN_KEY> --lic
yarn hardhat --network boba sourcify
# Optimism (etherscan-verify does not work on Optimism so we use hardhat verify)
yarn hardhat --network optimism verify <EACH-DEPLOYED ADDRESS IN STEP 3> <ASSOCIATED CONSTRUCTOR PARAMS FROM 3>
# Base
yarn hardhat --network base verify <EACH-DEPLOYED ADDRESS IN STEP 3> <ASSOCIATED CONSTRUCTOR PARAMS FROM 3>
```

5. Setup mainnet contracts

```sh
yarn hardhat [setup-l1-arbitrum-xchain/setup-l1-boba-xchain/setup-l1-optimism-xchain] --network mainnet
yarn hardhat [setup-l1-arbitrum-xchain/setup-l1-boba-xchain/setup-l1-optimism-xchain/setup-l1-base-xchain] --network mainnet
```

6. Setup l2 contracts

```sh
yarn hardhat setup-l2-xchain --network [arbitrum/boba/optimism]
yarn hardhat setup-l2-xchain --network [arbitrum/boba/optimism/base]
```

7. At this point, the cross chain contract suite setup is complete. We will now deploy the `OptimisticOracle` and required contracts to the L2.
7. At this point, the cross chain contract suite setup is complete. We will now deploy the `OptimisticOracle,OptimisticOracleV2` and required contracts to the L2, the `OptimisticOracleV3` contract is deployed in a later step.

```sh
yarn hardhat deploy --network [arbitrum/boba/optimism] --tags OptimisticOracle,IdentifierWhitelist,AddressWhitelist,Store
yarn hardhat deploy --network [arbitrum/boba/optimism/base] --tags OptimisticOracle,OptimisticOracleV2,OptimisticOracleV3,IdentifierWhitelist,AddressWhitelist,Store
```

8. Verify contracts:
Expand All @@ -99,27 +102,39 @@ yarn hardhat --network arbitrum etherscan-verify --api-key <ETHERSCAN_KEY> --lic
yarn hardhat --network boba sourcify
# Optimism (etherscan-verify does not work on Optimism so we use hardhat verify)
yarn hardhat --network optimism verify <EACH-DEPLOYED ADDRESS IN STEP 7> <ASSOCIATED CONSTRUCTOR PARAMS FROM 7>
# Base
yarn hardhat --network base verify <EACH-DEPLOYED ADDRESS IN STEP 7> <ASSOCIATED CONSTRUCTOR PARAMS FROM 7>
```

9. Setup l2 optimistic oracle:

```sh
# Seed IdentifierWhitelist with all identifiers already approved on mainnet. Note the --from address is the IdentifierWhitelist deployed on mainnet.
CROSS_CHAIN_NODE_URL=<MAINNET_URL> yarn hardhat migrate-identifiers --network [arbitrum/boba/optimism] --from 0xcF649d9Da4D1362C4DAEa67573430Bd6f945e570 --crosschain true
CROSS_CHAIN_NODE_URL=<MAINNET_URL> yarn hardhat migrate-identifiers --network [arbitrum/boba/optimism/base] --from 0xcF649d9Da4D1362C4DAEa67573430Bd6f945e570 --crosschain true

# Seed Collateral whitelist with all collaterals already approved on Mainnet. This will also pull the final fee from the L1 store and set it in the L2 Store.
yarn hardhat --network [arbitrum/boba/optimism] migrate-collateral-whitelist --l1chainid 1 --l2chainid [42161/288/10]
yarn hardhat --network [arbitrum/boba/optimism/base] migrate-collateral-whitelist --l1chainid 1 --l2chainid [42161/288/10/8453]

# Point L2 Finder to remaining Optimistic Oracle system contracts.
yarn hardhat setup-finder --oraclespoke --identifierwhitelist --addresswhitelist --optimisticoracle --store --network [arbitrum/boba/optimism]
# Register OptimisticOracle as registered contract.
yarn hardhat register-accounts --network [arbitrum/boba/optimism] --account <OPTIMISTIC_ORACLE_ADDRESS>
yarn hardhat setup-finder --oraclespoke --identifierwhitelist --addresswhitelist --optimisticoracle --optimisticoraclev2 --store --network [arbitrum/boba/optimism/base]
# Register OptimisticOracles as registered contract.
yarn hardhat register-accounts --network [arbitrum/boba/optimism/base] --account <OPTIMISTIC_ORACLE_ADDRESS>
yarn hardhat register-accounts --network [arbitrum/boba/optimism/base] --account <OPTIMISTIC_ORACLEV2_ADDRESS>
yarn hardhat register-accounts --network [arbitrum/boba/optimism/base] --account <OPTIMISTIC_ORACLEV3_ADDRESS>
```

10. Perform other set up when appropriate such as transferring ownership to the Governor and Governor spokes. Run the following script to check all required steps:
10. At this point we can deploy the `OptimisticOracleV3` contract to the L2:

- First deploy the `OptimisticOracleV3` contract with the required constructor arguments.
- Then run again the `setup-finder` script to point the L2 Finder to the `OptimisticOracleV3` contract.
- Run: `yarn hardhat setup-finder --optimisticoraclev3 --network [arbitrum/boba/optimism/base]`
- Finally, register the `OptimisticOracleV3` contract as a registered contract.
- Run: `yarn hardhat register-accounts --network [arbitrum/boba/optimism/base] --account <OPTIMISTIC_ORACLE_V3_ADDRESS>`

11. Perform other set up when appropriate such as transferring ownership to the Governor and Governor spokes. Run the following script to check all required steps:

```sh
yarn hardhat verify-xchain --network mainnet --l2 [arbitrum/boba/optimism]
yarn hardhat verify-xchain --network mainnet --l2 [arbitrum/boba/optimism/base]
```

## L2->L1 Message passing and finalization
Expand All @@ -128,7 +143,9 @@ The cross-chain-oracle contracts send messages from L1<->L2 under different situ

To finalize **Arbitrum** transactions see the docs [here](https://github.com/OffchainLabs/arbitrum-tutorials/tree/master/packages/outbox-execute) on how to do this. Alternatively, Arbiscan provides a list of L2->L1 transactions and a UI for finalizing those that have passed liveness. This can also be used if you don't want to run the `outbox-execute` script. The relevant page can be found [here](https://arbiscan.io/txsExit).

To finalize **Optimism** transactions see the equivalent script [here](https://github.com/ethereum-optimism/optimism/blob/develop/packages/message-relayer/src/exec/withdraw.ts). Optimism's Etherscan also provides a UI, similar to Arbitrum, which can be found [here](https://optimistic.etherscan.io/txsExit).
To finalize **Optimism** transactions see the equivalent script [here](https://github.com/ethereum-optimism/optimism/blob/34e7450873548f65bf3160ca58eed2328907310a/packages/sdk/tasks/finalize-withdrawal.ts#L14). Optimism's Etherscan also provides a UI, similar to Arbitrum, which can be found [here](https://optimistic.etherscan.io/txsExit).

To finalize **Base** transactions see the equivalent script [here](https://github.com/ethereum-optimism/optimism/blob/develop/packages/message-relayer/src/exec/withdraw.ts). Base's Etherscan also provides a UI, similar to Optimism, which can be found [here](https://basescan.org/txsExit).

**Boba** at present auto-finalizes all L2->L1 transactions without any required user intervention.

Expand Down
9 changes: 8 additions & 1 deletion packages/core/deploy/038_deploy_oracle_spoke.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,12 @@ const func = async function (hre) {
await deploy("OracleSpoke", { from: deployer, args: [finder.address], log: true, skipIfAlreadyDeployed: true });
};
module.exports = func;
func.tags = ["OracleSpoke", "l2-arbitrum-xchain", "l2-boba-xchain", "l2-optimism-xchain", "l2-admin-xchain"];
func.tags = [
"OracleSpoke",
"l2-arbitrum-xchain",
"l2-boba-xchain",
"l2-optimism-xchain",
"l2-admin-xchain",
"l2-base-xchain",
];
func.dependencies = ["Finder"];
2 changes: 1 addition & 1 deletion packages/core/deploy/039_deploy_oracle_hub.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ const func = async function (hre) {
});
};
module.exports = func;
func.tags = ["OracleHub", "l1-arbitrum-xchain", "l1-boba-xchain", "l1-optimism-xchain"];
func.tags = ["OracleHub", "l1-arbitrum-xchain", "l1-boba-xchain", "l1-optimism-xchain", "l1-base-xchain"];
func.dependencies = ["Finder", "VotingToken"];
Loading

0 comments on commit 36e740d

Please sign in to comment.