Skip to content

Commit 9830ea7

Browse files
committed
Add Optimism L2 bridge contracts
- Add Optimism L2 bridge contracts - Add Optimism specific OVM_EOACodeHashSet contract - Add ERC677Receiver functionality to L1/L2 gateways - Add L1-L2 deposit-withdraw bridge integration tests - Force compile OZ TransparentUpgradeableProxy.sol & ProxyAdmin.sol
1 parent 7c41212 commit 9830ea7

32 files changed

+1404
-14
lines changed

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,9 @@
44
[submodule "vendor/OpenZeppelin/openzeppelin-contracts"]
55
path = vendor/OpenZeppelin/openzeppelin-contracts
66
url = [email protected]:OpenZeppelin/openzeppelin-contracts.git
7+
[submodule "vendor/OpenZeppelin/openzeppelin-contracts-upgradeable"]
8+
path = vendor/OpenZeppelin/openzeppelin-contracts-upgradeable
9+
url = [email protected]:OpenZeppelin/openzeppelin-contracts-upgradeable.git
10+
[submodule "vendor/ethereum-optimism/optimism"]
11+
path = vendor/ethereum-optimism/optimism
12+
url = [email protected]:ethereum-optimism/optimism.git

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
88

99
### Added
1010

11+
- Optimism L2 bridge support
1112
- Access controlled mintable & burnable LinkToken, for use on sidechains and L2 networks.
1213
- Added versioning to v0.6 & v0.7 contracts
1314

contracts/v0.7/bridge/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
11
# LINK Token Bridge v0.7
22

33
- `./token/LinkTokenChild.sol`: A mintable & burnable child LinkToken contract to be used on child networks.
4+
5+
## Optimism L2 bridge
6+
7+
The Optimistic Virtual Machine (OVM) is a scalable form of the EVM. Optimistic Rollup, by [Optimism](https://optimism.io), is the core scaling solution which enables the off-chain OVM to achieve cheap, instant transactions that still inherit L1 security. The OVM is an EVM-based VM which supports optimistically executing EVM smart contracts on a layer 1 blockchain like Ethereum. It is structured in such a way that it is possible to verify individual steps of its computation on Ethereum mainnet. This allows the mainnet to enforce validity of state roots with fraud proofs in the layer 2 Optimistic Rollup chain. For more information consult the [Optimism developer documentation](https://community.optimism.io/docs/).
8+
9+
The set of contracts needed for the Optimism L2 LinkToken bridge can be found in the [./optimism](./optimism) dir.
10+
11+
- `./optimism/OVM_EOACodeHashSet.sol`: Abstract helper contract used to keep track of OVM EOA contract set (OVM specific)
12+
- `./optimism/OVM_L1ERC20Gateway.sol`: Contract which stores deposited L1 funds that are in use on L2, and unlocks/transfers L1 funds on withdrawal. It synchronizes a corresponding L2 ERC20 Gateway, informing it of deposits, and listening to it for newly finalized withdrawals. (delegate proxy deployment)
13+
- `./optimism/OVM_L2ERC20Gateway.sol`: Contract which mints deposited L2 funds that are locked on L1, and burns L2 funds on withdrawal. It synchronizes a corresponding L1 ERC20 Gateway, informing it of withdrawals, and listening to it for newly finalized deposits. (delegate proxy deployment)
14+
15+
These contracts are an implementation of [abstracts bridge contracts provided by Optimism](https://github.com/ethereum-optimism/optimism/tree/master/packages/contracts/contracts/optimistic-ethereum/OVM/bridge/tokens).
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >0.6.0 <0.8.0;
3+
4+
/* Interface Imports */
5+
import { IERC677 } from "../../../v0.6/token/IERC677.sol";
6+
7+
contract ERC677CallerMock {
8+
/// @dev Forward transferAndCall to destination contract
9+
function callTransferAndCall(
10+
address destintion,
11+
address to,
12+
uint value,
13+
bytes memory data
14+
)
15+
external
16+
{
17+
IERC677(destintion).transferAndCall(to, value, data);
18+
}
19+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >0.6.0 <0.8.0;
3+
4+
/* Library Imports */
5+
import { EnumerableSet } from "../../../../vendor/OpenZeppelin/openzeppelin-contracts/contracts/utils/EnumerableSet.sol";
6+
7+
/* Contract Imports */
8+
import { Initializable } from "../../../../vendor/OpenZeppelin/openzeppelin-contracts-upgradeable/contracts/proxy/Initializable.sol";
9+
import { OwnableUpgradeable } from "../../../../vendor/OpenZeppelin/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol";
10+
11+
/**
12+
* @dev Abstract helper contract used to keep track of OVM EOA contract set (OVM specific)
13+
*
14+
* The OVM implements a basic form of account abstraction. In effect, this means
15+
* that the only type of account is a smart contract (no EOAs), and all user wallets
16+
* are in fact smart contract wallets. So to check for EOA, we need to actually check if
17+
* the sender is an OVM_ProxyEOA contract, which gets deployed by the ovmCREATEEOA opcode.
18+
*
19+
* As the OVM_ProxyEOA.sol contract source could potentially change in the future (i.e., due to a fork),
20+
* here we actually track a set of possible EOA proxy contracts.
21+
*/
22+
abstract contract OVM_EOACodeHashSet is /* Initializable, */ OwnableUpgradeable {
23+
// Add the EnumerableSet library
24+
using EnumerableSet for EnumerableSet.Bytes32Set;
25+
26+
// Declare a Bytes32Set of code hashes
27+
EnumerableSet.Bytes32Set private s_codeHasheSet;
28+
29+
// Declare the genesis OVM_ProxyEOA.sol EXTCODEHASH
30+
bytes32 constant OVM_EOA_CODE_HASH_V0 = 0x93bb081a7dd92bde63b4d0aa9b8612352b2ec585176a80efc0a2a277ecfc010e;
31+
bytes32 constant OVM_EOA_CODE_HASH_V1 = 0x8b4ea2cb36c232a7bab9d385b7054ff04752ec4c0fad5dc2ed4b1c18d982154c;
32+
bytes32 constant OVM_EOA_CODE_HASH_V2 = 0xb6268ee2707994607682cc0e3b288cdd71acc63df8de0e6baa39a31a2b91d0ad;
33+
bytes32 constant OVM_EOA_CODE_HASH_V3 = 0x93fae832274ff6aa942fa0c287fc0d8fe180f26b36c92e83d9be7e39309d3464;
34+
// Optimism v0.3.0-rc
35+
bytes32 constant OVM_EOA_CODE_HASH_V4 = 0xef2ab076db773ffc554c9f287134123439a5228e92f5b3194a28fec0a0afafe3;
36+
37+
function __OVM_EOACodeHashSet_init()
38+
internal
39+
initializer()
40+
{
41+
__Context_init_unchained();
42+
__Ownable_init_unchained();
43+
__OVM_EOACodeHashSet_init_unchained();
44+
}
45+
46+
/// @notice Adds genesis OVM_ProxyEOA.sol EXTCODEHASH to the default set.
47+
function __OVM_EOACodeHashSet_init_unchained()
48+
internal
49+
initializer()
50+
{
51+
s_codeHasheSet.add(OVM_EOA_CODE_HASH_V0);
52+
s_codeHasheSet.add(OVM_EOA_CODE_HASH_V1);
53+
s_codeHasheSet.add(OVM_EOA_CODE_HASH_V2);
54+
s_codeHasheSet.add(OVM_EOA_CODE_HASH_V3);
55+
s_codeHasheSet.add(OVM_EOA_CODE_HASH_V4);
56+
}
57+
58+
/// @notice Reverts if called by anyone other than whitelisted EOA contracts.
59+
modifier onlyEOAContract() {
60+
require(_isEOAContract(msg.sender), "Only callable by whitelisted EOA");
61+
_;
62+
}
63+
64+
/**
65+
* @dev Returns true if the EOA contract code hash value is in the set. O(1).
66+
*
67+
* @param value EOA contract code hash to check
68+
*/
69+
function containsEOACodeHash(
70+
bytes32 value
71+
)
72+
public
73+
view
74+
returns (bool)
75+
{
76+
return s_codeHasheSet.contains(value);
77+
}
78+
79+
/**
80+
* @dev Adds a EOA contract code hash value to the set. O(1).
81+
*
82+
* Returns true if the value was added to the set, that is if it was not already present.
83+
* @param value EOA contract code hash to add
84+
*/
85+
function addEOACodeHash(
86+
bytes32 value
87+
)
88+
public
89+
onlyOwner()
90+
returns (bool)
91+
{
92+
return s_codeHasheSet.add(value);
93+
}
94+
95+
/**
96+
* @dev Removes a EOA contract code hash value from the set. O(1).
97+
*
98+
* Returns true if the value was removed from the set, that is if it was present.
99+
* @param value EOA contract code hash to remove
100+
*/
101+
function removeEOACodeHash(
102+
bytes32 value
103+
)
104+
public
105+
onlyOwner()
106+
returns (bool)
107+
{
108+
return s_codeHasheSet.remove(value);
109+
}
110+
111+
/**
112+
* @dev Returns true if `account` is a whitelisted EOA contract.
113+
* @param account Address to check
114+
*/
115+
function _isEOAContract(
116+
address account
117+
)
118+
internal
119+
view
120+
returns (bool)
121+
{
122+
bytes32 codehash;
123+
// solhint-disable-next-line no-inline-assembly
124+
assembly { codehash := extcodehash(account) }
125+
return s_codeHasheSet.contains(codehash);
126+
}
127+
}

0 commit comments

Comments
 (0)