Skip to content

Commit 43e7da2

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 557b4f2 commit 43e7da2

File tree

19 files changed

+1412
-2
lines changed

19 files changed

+1412
-2
lines changed

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

1314
### Changed

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 { ERC677 } from "../../../v0.6/token/ERC677.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+
ERC677(destintion).transferAndCall(to, value, data);
18+
}
19+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >0.6.0 <0.8.0;
3+
4+
/* Library Imports */
5+
import { EnumerableSet } from "@openzeppelin/contracts/utils/EnumerableSet.sol";
6+
7+
/* Contract Imports */
8+
import { Initializable } from "@openzeppelin/contracts/proxy/Initializable.sol";
9+
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/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+
35+
function __OVM_EOACodeHashSet_init()
36+
internal
37+
initializer()
38+
{
39+
__Context_init_unchained();
40+
__Ownable_init_unchained();
41+
__OVM_EOACodeHashSet_init_unchained();
42+
}
43+
44+
/// @notice Adds genesis OVM_ProxyEOA.sol EXTCODEHASH to the default set.
45+
function __OVM_EOACodeHashSet_init_unchained()
46+
internal
47+
initializer()
48+
{
49+
s_codeHasheSet.add(OVM_EOA_CODE_HASH_V0);
50+
s_codeHasheSet.add(OVM_EOA_CODE_HASH_V1);
51+
s_codeHasheSet.add(OVM_EOA_CODE_HASH_V2);
52+
s_codeHasheSet.add(OVM_EOA_CODE_HASH_V3);
53+
}
54+
55+
/// @notice Reverts if called by anyone other than whitelisted EOA contracts.
56+
modifier onlyEOAContract() {
57+
require(_isEOAContract(msg.sender), "Only callable by whitelisted EOA");
58+
_;
59+
}
60+
61+
/**
62+
* @dev Returns true if the EOA contract code hash value is in the set. O(1).
63+
*
64+
* @param value EOA contract code hash to check
65+
*/
66+
function containsEOACodeHash(
67+
bytes32 value
68+
)
69+
public
70+
view
71+
returns (bool)
72+
{
73+
return s_codeHasheSet.contains(value);
74+
}
75+
76+
/**
77+
* @dev Adds a EOA contract code hash value to the set. O(1).
78+
*
79+
* Returns true if the value was added to the set, that is if it was not already present.
80+
* @param value EOA contract code hash to add
81+
*/
82+
function addEOACodeHash(
83+
bytes32 value
84+
)
85+
public
86+
onlyOwner()
87+
returns (bool)
88+
{
89+
return s_codeHasheSet.add(value);
90+
}
91+
92+
/**
93+
* @dev Removes a EOA contract code hash value from the set. O(1).
94+
*
95+
* Returns true if the value was removed from the set, that is if it was present.
96+
* @param value EOA contract code hash to remove
97+
*/
98+
function removeEOACodeHash(
99+
bytes32 value
100+
)
101+
public
102+
onlyOwner()
103+
returns (bool)
104+
{
105+
return s_codeHasheSet.remove(value);
106+
}
107+
108+
/**
109+
* @dev Returns true if `account` is a whitelisted EOA contract.
110+
* @param account Address to check
111+
*/
112+
function _isEOAContract(
113+
address account
114+
)
115+
internal
116+
view
117+
returns (bool)
118+
{
119+
bytes32 codehash;
120+
// solhint-disable-next-line no-inline-assembly
121+
assembly { codehash := extcodehash(account) }
122+
return s_codeHasheSet.contains(codehash);
123+
}
124+
}

0 commit comments

Comments
 (0)