-
Notifications
You must be signed in to change notification settings - Fork 83
/
Copy pathOmniBridgeL1.sol
108 lines (89 loc) · 3.77 KB
/
OmniBridgeL1.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.24;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { OmniBridgeCommon } from "./OmniBridgeCommon.sol";
import { IOmniPortal } from "../interfaces/IOmniPortal.sol";
import { XTypes } from "../libraries/XTypes.sol";
import { ConfLevel } from "../libraries/ConfLevel.sol";
import { Predeploys } from "../libraries/Predeploys.sol";
import { OmniBridgeNative } from "./OmniBridgeNative.sol";
/**
* @title OmniBridgeL1
* @notice The Ethereum side of Omni's native token bridge. Partner to OmniBridgeNative, which is
* deployed to Omni's EVM.
*/
contract OmniBridgeL1 is OmniBridgeCommon {
/**
* @notice Emitted when an account deposits OMNI, bridging it to Ethereum.
*/
event Bridge(address indexed payor, address indexed to, uint256 amount);
/**
* @notice Emitted when OMNI tokens are withdrawn for an account.
*/
event Withdraw(address indexed to, uint256 amount);
/**
* @notice xcall gas limit for OmniBridgeNative.withdraw
*/
uint64 public constant XCALL_WITHDRAW_GAS_LIMIT = 80_000;
/**
* @notice The OMNI token contract.
*/
IERC20 public immutable token;
/**
* @notice The OmniPortal contract.
*/
IOmniPortal public omni;
constructor(address token_) {
token = IERC20(token_);
_disableInitializers();
}
function initialize(address owner_, address omni_) external initializer {
require(omni_ != address(0), "OmniBridge: no zero addr");
__Ownable_init(owner_);
omni = IOmniPortal(omni_);
}
/**
* @notice Withdraw `amount` L1 OMNI to `to`. Only callable via xcall from OmniBridgeNative.
* @dev Omni native <> L1 bridge accounting rules ensure that this contract will always
* have enough balance to cover the withdrawal.
*/
function withdraw(address to, uint256 amount) external whenNotPaused(ACTION_WITHDRAW) {
XTypes.MsgContext memory xmsg = omni.xmsg();
require(msg.sender == address(omni), "OmniBridge: not xcall");
require(xmsg.sender == Predeploys.OmniBridgeNative, "OmniBridge: not bridge");
require(xmsg.sourceChainId == omni.omniChainId(), "OmniBridge: not omni");
token.transfer(to, amount);
emit Withdraw(to, amount);
}
/**
* @notice Bridge `amount` OMNI to `to` on Omni's EVM.
*/
function bridge(address to, uint256 amount) external payable whenNotPaused(ACTION_BRIDGE) {
_bridge(msg.sender, to, amount);
}
/**
* @dev Trigger a withdraw of `amount` OMNI to `to` on Omni's EVM, via xcall.
*/
function _bridge(address payor, address to, uint256 amount) internal {
require(amount > 0, "OmniBridge: amount must be > 0");
require(to != address(0), "OmniBridge: no bridge to zero");
uint64 omniChainId = omni.omniChainId();
bytes memory xcalldata = abi.encodeCall(OmniBridgeNative.withdraw, (payor, to, amount));
require(
msg.value >= omni.feeFor(omniChainId, xcalldata, XCALL_WITHDRAW_GAS_LIMIT), "OmniBridge: insufficient fee"
);
require(token.transferFrom(payor, address(this), amount), "OmniBridge: transfer failed");
omni.xcall{ value: msg.value }(
omniChainId, ConfLevel.Finalized, Predeploys.OmniBridgeNative, xcalldata, XCALL_WITHDRAW_GAS_LIMIT
);
emit Bridge(payor, to, amount);
}
/**
* @notice Return the xcall fee required to bridge `amount` to `to`.
*/
function bridgeFee(address payor, address to, uint256 amount) public view returns (uint256) {
return omni.feeFor(
omni.omniChainId(), abi.encodeCall(OmniBridgeNative.withdraw, (payor, to, amount)), XCALL_WITHDRAW_GAS_LIMIT
);
}
}