Skip to content

Commit 502fdc4

Browse files
authored
feat: Zora deployments (#572)
1 parent d721cce commit 502fdc4

17 files changed

+3438
-7
lines changed

contracts/Zora_SpokePool.sol

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.0;
3+
import "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol";
4+
5+
import "./Ovm_SpokePool.sol";
6+
import "./external/interfaces/CCTPInterfaces.sol";
7+
8+
/**
9+
* @notice Zora Spoke pool.
10+
* @custom:security-contact [email protected]
11+
*/
12+
contract Zora_SpokePool is Ovm_SpokePool {
13+
/// @custom:oz-upgrades-unsafe-allow constructor
14+
constructor(
15+
address _wrappedNativeTokenAddress,
16+
uint32 _depositQuoteTimeBuffer,
17+
uint32 _fillDeadlineBuffer,
18+
IERC20 _l2Usdc,
19+
ITokenMessenger _cctpTokenMessenger
20+
)
21+
Ovm_SpokePool(
22+
_wrappedNativeTokenAddress,
23+
_depositQuoteTimeBuffer,
24+
_fillDeadlineBuffer,
25+
_l2Usdc,
26+
_cctpTokenMessenger
27+
)
28+
{} // solhint-disable-line no-empty-blocks
29+
30+
/**
31+
* @notice Construct the OVM Zora SpokePool.
32+
* @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate
33+
* relay hash collisions.
34+
* @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.
35+
* @param _hubPool Hub pool address to set. Can be changed by admin.
36+
*/
37+
function initialize(
38+
uint32 _initialDepositId,
39+
address _crossDomainAdmin,
40+
address _hubPool
41+
) public initializer {
42+
__OvmSpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, Lib_PredeployAddresses.OVM_ETH);
43+
}
44+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.0;
3+
4+
import "./interfaces/AdapterInterface.sol";
5+
import "../external/interfaces/WETH9Interface.sol";
6+
7+
// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need
8+
// this contract's state variables to be `immutable` because of the delegateCall call.
9+
import "./CrossDomainEnabled.sol";
10+
import "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol";
11+
12+
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
13+
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
14+
15+
import "../libraries/CircleCCTPAdapter.sol";
16+
import "../external/interfaces/CCTPInterfaces.sol";
17+
18+
/**
19+
* @notice Contract containing logic to send messages from L1 to Zora. This is a clone of the Base/Mode adapter
20+
* @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be
21+
* called via delegatecall, which will execute this contract's logic within the context of the originating contract.
22+
* For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods
23+
* that call this contract's logic guard against reentrancy.
24+
* @custom:security-contact [email protected]
25+
*/
26+
27+
// solhint-disable-next-line contract-name-camelcase
28+
contract Zora_Adapter is CrossDomainEnabled, AdapterInterface, CircleCCTPAdapter {
29+
using SafeERC20 for IERC20;
30+
uint32 public constant L2_GAS_LIMIT = 200_000;
31+
32+
WETH9Interface public immutable L1_WETH;
33+
34+
IL1StandardBridge public immutable L1_STANDARD_BRIDGE;
35+
36+
/**
37+
* @notice Constructs new Adapter.
38+
* @param _l1Weth WETH address on L1.
39+
* @param _crossDomainMessenger XDomainMessenger Zora system contract.
40+
* @param _l1StandardBridge Standard bridge contract.
41+
* @param _l1Usdc USDC address on L1.
42+
*/
43+
constructor(
44+
WETH9Interface _l1Weth,
45+
address _crossDomainMessenger,
46+
IL1StandardBridge _l1StandardBridge,
47+
IERC20 _l1Usdc
48+
)
49+
CrossDomainEnabled(_crossDomainMessenger)
50+
CircleCCTPAdapter(
51+
_l1Usdc,
52+
// Hardcode cctp messenger to 0x0 to disable CCTP bridging.
53+
ITokenMessenger(address(0)),
54+
CircleDomainIds.UNINTIALIZED
55+
)
56+
{
57+
L1_WETH = _l1Weth;
58+
L1_STANDARD_BRIDGE = _l1StandardBridge;
59+
}
60+
61+
/**
62+
* @notice Send cross-chain message to target on Zora.
63+
* @param target Contract on Zora that will receive message.
64+
* @param message Data to send to target.
65+
*/
66+
function relayMessage(address target, bytes calldata message) external payable override {
67+
sendCrossDomainMessage(target, L2_GAS_LIMIT, message);
68+
emit MessageRelayed(target, message);
69+
}
70+
71+
/**
72+
* @notice Bridge tokens to Zora.
73+
* @param l1Token L1 token to deposit.
74+
* @param l2Token L2 token to receive.
75+
* @param amount Amount of L1 tokens to deposit and L2 tokens to receive.
76+
* @param to Bridge recipient.
77+
*/
78+
function relayTokens(
79+
address l1Token,
80+
address l2Token,
81+
uint256 amount,
82+
address to
83+
) external payable override {
84+
// If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.
85+
if (l1Token == address(L1_WETH)) {
86+
L1_WETH.withdraw(amount);
87+
L1_STANDARD_BRIDGE.depositETHTo{ value: amount }(to, L2_GAS_LIMIT, "");
88+
}
89+
// Check if this token is USDC, which requires a custom bridge via CCTP.
90+
else if (_isCCTPEnabled() && l1Token == address(usdcToken)) {
91+
_transferUsdc(to, amount);
92+
} else {
93+
IL1StandardBridge _l1StandardBridge = L1_STANDARD_BRIDGE;
94+
95+
IERC20(l1Token).safeIncreaseAllowance(address(_l1StandardBridge), amount);
96+
_l1StandardBridge.depositERC20To(l1Token, l2Token, to, amount, L2_GAS_LIMIT, "");
97+
}
98+
emit TokensRelayed(l1Token, l2Token, amount, to);
99+
}
100+
}

deploy/048_deploy_zora_adapter.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { ZERO_ADDRESS } from "@uma/common";
2+
import { DeployFunction } from "hardhat-deploy/types";
3+
import { HardhatRuntimeEnvironment } from "hardhat/types";
4+
import { L1_ADDRESS_MAP, WETH } from "./consts";
5+
6+
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
7+
const { deployments, getNamedAccounts, getChainId, network } = hre;
8+
const { deploy } = deployments;
9+
10+
const { deployer } = await getNamedAccounts();
11+
12+
const chainId = parseInt(await getChainId());
13+
14+
await deploy("Zora_Adapter", {
15+
from: deployer,
16+
log: true,
17+
skipIfAlreadyDeployed: true,
18+
args: [
19+
WETH[chainId],
20+
L1_ADDRESS_MAP[chainId].zoraCrossDomainMessenger,
21+
L1_ADDRESS_MAP[chainId].zoraStandardBridge,
22+
ZERO_ADDRESS,
23+
],
24+
});
25+
};
26+
27+
module.exports = func;
28+
func.tags = ["ZoraAdapter", "mainnet"];
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { DeployFunction } from "hardhat-deploy/types";
2+
import { HardhatRuntimeEnvironment } from "hardhat/types";
3+
import { ZERO_ADDRESS } from "@uma/common";
4+
import { deployNewProxy, getSpokePoolDeploymentInfo } from "../utils/utils.hre";
5+
import { CHAIN_IDs } from "../utils";
6+
import { WETH } from "./consts";
7+
8+
const { ZORA } = CHAIN_IDs;
9+
10+
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
11+
const { hubPool, spokeChainId } = await getSpokePoolDeploymentInfo(hre);
12+
13+
const initArgs = [
14+
1,
15+
// Set hub pool as cross domain admin since it delegatecalls the Adapter logic.
16+
hubPool.address,
17+
hubPool.address,
18+
];
19+
// Construct this spokepool with a:
20+
// * A WETH address of the WETH address
21+
// * A depositQuoteTimeBuffer of 1 hour
22+
// * A fillDeadlineBuffer of 6 hours
23+
// * Native USDC address on L2
24+
// * CCTP token messenger address on L2
25+
const constructorArgs = [
26+
WETH[spokeChainId],
27+
3600,
28+
21600,
29+
ZERO_ADDRESS,
30+
// L2_ADDRESS_MAP[spokeChainId].cctpTokenMessenger,
31+
// For now, we are not using the CCTP bridge and can disable by setting
32+
// the cctpTokenMessenger to the zero address.
33+
ZERO_ADDRESS,
34+
];
35+
await deployNewProxy("Zora_SpokePool", constructorArgs, initArgs, spokeChainId === ZORA);
36+
};
37+
module.exports = func;
38+
func.tags = ["spokepool", "zora"];

deploy/consts.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export const L1_ADDRESS_MAP: { [key: number]: { [contractName: string]: string }
4343
blastDaiRetriever: "0x98Dd57048d7d5337e92D9102743528ea4Fea64aB",
4444
redstoneCrossDomainMessenger: "0x592C1299e0F8331D81A28C0FC7352Da24eDB444a",
4545
redstoneStandardBridge: "0xc473ca7E02af24c129c2eEf51F2aDf0411c1Df69",
46+
zoraCrossDomainMessenger: "0x363B4B1ADa52E50353f746999bd9E94395190d2C",
47+
zoraStandardBridge: "0xbF6acaF315477b15D638bf4d91eA48FA79b58335",
4648
},
4749
4: {
4850
weth: "0xc778417E063141139Fce010982780140Aa0cD5Ab",

deployments/deployments.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
"Scroll_Adapter": { "address": "0xb6129Ab69aEA75e6884c2D6ecf25293C343C519F", "blockNumber": 20318360 },
2626
"Blast_DaiRetriever": { "address": "0x98Dd57048d7d5337e92D9102743528ea4Fea64aB", "blockNumber": 20378862 },
2727
"Blast_RescueAdapter": { "address": "0xE5Dea263511F5caC27b15cBd58Ff103F4Ce90957", "blockNumber": 20378872 },
28-
"Redstone_Adapter": { "address": "0x188F8C95B7cfB7993B53a4F643efa687916f73fA", "blockNumber": 20432774 }
28+
"Redstone_Adapter": { "address": "0x188F8C95B7cfB7993B53a4F643efa687916f73fA", "blockNumber": 20432774 },
29+
"Zora_Adapter": { "address": "0xa27fb9f2A22F8dA4cBF155e9795A43488004AAc3", "blockNumber": 20468487 }
2930
},
3031
"4": {
3132
"Arbitrum_Adapter": { "address": "0x18F4D98C7CeA6Ab934F2976c2a98009A529d8F49", "blockNumber": 10367195 },
@@ -173,6 +174,11 @@
173174
"SpokePoolVerifier": { "address": "0xB4A8d45647445EA9FC3E1058096142390683dBC2", "blockNumber": 7490003 },
174175
"MulticallHandler": { "address": "0x924a9f036260DdD5808007E1AA95f08eD08aA569", "blockNumber": 7489978 }
175176
},
177+
"7777777": {
178+
"SpokePool": { "address": "0x09aea4b2242abC8bb4BB78D537A67a245A7bEC64", "blockNumber": 18119425 },
179+
"SpokePoolVerifier": { "address": "0xB4A8d45647445EA9FC3E1058096142390683dBC2", "blockNumber": 18120222 },
180+
"MulticallHandler": { "address": "0x924a9f036260DdD5808007E1AA95f08eD08aA569", "blockNumber": 18119854 }
181+
},
176182
"11155111": {
177183
"MulticallHandler": { "address": "0x924a9f036260DdD5808007E1AA95f08eD08aA569", "blockNumber": 6284508 },
178184
"AcrossConfigStore": { "address": "0xB3De1e212B49e68f4a68b5993f31f63946FCA2a6", "blockNumber": 4968255 },

deployments/zora/.chainId

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7777777

0 commit comments

Comments
 (0)