Skip to content

Commit 8fd6d62

Browse files
authored
Merge pull request #42 from smartcontractkit/feature/oe-token-v2
Add LinkToken on Optimism [bridge v2]
2 parents 7ab441d + d5ea666 commit 8fd6d62

5 files changed

Lines changed: 176 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7-
## [Unreleased] - Apr 2021
7+
## [Unreleased] - Jun 2021
88

99
### Added
1010

1111
- Access controlled mintable & burnable LinkToken, for use on sidechains and L2 networks.
12+
- Documentation and token implementation for the Optimism bridge v2.
1213
- Added versioning to v0.6 & v0.7 contracts
1314

1415
### Changed

contracts/v0.7/bridge/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@ NOTICE: Current implementation of LinkTokenChild contract requires some addition
2323
gets defined, and once online transfer the ownership (bridge gateway role) to the new bridge.
2424

2525
TODO: Potentially create an upgradeable `LinkTokenChild.sol` and limit gateway support to only one (owner)!
26+
27+
- `./token/optimism/`: Documentation and token implementation for the Optimism bridge v2.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >0.6.0 <0.8.0;
3+
4+
/* Interface Imports */
5+
import { IERC20 } from "../../../../../vendor/OpenZeppelin/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
6+
import { IERC165 } from "../../../../../vendor/OpenZeppelin/openzeppelin-contracts/contracts/introspection/IERC165.sol";
7+
8+
/// @dev Interface for the bridged ERC20 token expected by the Optimism standard bridge L2 gateway.
9+
interface IERC20Optimism is IERC20, IERC165 {
10+
/// @dev Returns the address of an L1 token contract linked to this L2 token contract
11+
function l1Token()
12+
external
13+
returns (address);
14+
15+
/**
16+
* @dev Creates `_amount` tokens `_to` account.
17+
* @notice Called by L2 gateway to deposit tokens.
18+
* @param _to Address of the recipient.
19+
* @param _amount Number of tokens to mint.
20+
*/
21+
function mint(
22+
address _to,
23+
uint256 _amount
24+
)
25+
external;
26+
27+
/**
28+
* @dev Destroys `_amount` tokens `_from` account.
29+
* @notice Called by L2 gateway to withdraw tokens.
30+
* @param _from Address of the account holding the tokens to be burnt.
31+
* @param _amount Number of tokens to burn.
32+
*/
33+
function burn(
34+
address _from,
35+
uint256 _amount
36+
)
37+
external;
38+
39+
/// @dev Emitted when `_amount` tokens are deposited from L1 to L2.
40+
event Mint(
41+
address indexed _account,
42+
uint256 _amount
43+
);
44+
45+
/// @dev Emitted when `_amount` tokens are withdrawn from L2 to L1.
46+
event Burn(
47+
address indexed _account,
48+
uint256 _amount
49+
);
50+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity >0.6.0 <0.8.0;
3+
4+
/* Interface Imports */
5+
import { IERC165 } from "../../../../../vendor/OpenZeppelin/openzeppelin-contracts/contracts/introspection/IERC165.sol";
6+
import { ITypeAndVersion } from "../../../../v0.6/ITypeAndVersion.sol";
7+
import { IERC20Optimism } from "./IERC20Optimism.sol";
8+
9+
/* Contract Imports */
10+
import { ERC20 } from "../../../../../vendor/OpenZeppelin/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
11+
import { LinkToken } from "../../../../v0.6/LinkToken.sol";
12+
13+
/// @dev Access controlled mintable & burnable LinkToken, for use on Optimism L2 network.
14+
contract LinkTokenOptimism is ITypeAndVersion, IERC20Optimism, LinkToken {
15+
/// @dev Returns the address of an L2 bridge contract that has access to mint & burn
16+
address public immutable l2Bridge;
17+
/// @inheritdoc IERC20Optimism
18+
address public immutable override l1Token;
19+
20+
/**
21+
* @dev Creates an L2 token connected to a specific L2 bridge gateway & L1 token
22+
* @param l2BridgeAddr Address of the corresponding L2 bridge gateway.
23+
* @param l1TokenAddr Address of the corresponding L1 token.
24+
*/
25+
constructor(
26+
address l2BridgeAddr,
27+
address l1TokenAddr
28+
) {
29+
l2Bridge = l2BridgeAddr;
30+
l1Token = l1TokenAddr;
31+
}
32+
33+
/**
34+
* @notice versions:
35+
*
36+
* - LinkTokenOptimism 0.0.1: initial release
37+
*
38+
* @inheritdoc ITypeAndVersion
39+
*/
40+
function typeAndVersion()
41+
external
42+
pure
43+
override(ITypeAndVersion, LinkToken)
44+
virtual
45+
returns (string memory)
46+
{
47+
return "LinkTokenOptimism 0.0.1";
48+
}
49+
50+
/// @dev Checks that message sender is the L2 bridge contract (locked access to mint & burn)
51+
modifier onlyL2Bridge {
52+
require(msg.sender == l2Bridge, "Only L2 Bridge can mint and burn");
53+
_;
54+
}
55+
56+
/**
57+
* @dev Optimism standard bridge L2 gateway uses ERC165 to confirm the required interface
58+
* @inheritdoc IERC165
59+
*/
60+
function supportsInterface(
61+
bytes4 interfaceId
62+
)
63+
public
64+
override
65+
pure
66+
returns (bool)
67+
{
68+
bytes4 firstSupportedInterface = bytes4(keccak256("supportsInterface(bytes4)")); // ERC165
69+
bytes4 secondSupportedInterface = IERC20Optimism.l1Token.selector
70+
^ IERC20Optimism.mint.selector
71+
^ IERC20Optimism.burn.selector;
72+
return interfaceId == firstSupportedInterface || interfaceId == secondSupportedInterface;
73+
}
74+
75+
/// @inheritdoc IERC20Optimism
76+
function mint(
77+
address _to,
78+
uint256 _amount
79+
)
80+
public
81+
override
82+
onlyL2Bridge()
83+
{
84+
_mint(_to, _amount);
85+
emit Mint(_to, _amount);
86+
}
87+
88+
/// @inheritdoc IERC20Optimism
89+
function burn(
90+
address _from,
91+
uint256 _amount
92+
)
93+
public
94+
override
95+
onlyL2Bridge()
96+
{
97+
_burn(_from, _amount);
98+
emit Burn(_from, _amount);
99+
}
100+
101+
/**
102+
* @dev Overrides parent contract so no tokens are minted on deployment.
103+
* @inheritdoc LinkToken
104+
*/
105+
function _onCreate()
106+
internal
107+
override
108+
{}
109+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# LINK Token on Optimism
2+
3+
- `./token/IERC20Optimism.sol`: Interface for the bridged ERC20 token expected by the Optimism standard bridge L2 gateway.
4+
- `./token/LinkTokenOptimism.sol`: Access controlled mintable & burnable LinkToken, for use on Optimism L2 network.
5+
6+
`LinkTokenOptimism.sol` is a slightly modified version of Optimism's [`L2StandardERC20.sol`](https://github.com/ethereum-optimism/optimism/blob/master/packages/contracts/contracts/optimistic-ethereum/libraries/standards/L2StandardERC20.sol) and will be connected to the [`OVM_L2StandardBridge.sol`](https://github.com/ethereum-optimism/optimism/blob/master/packages/contracts/contracts/optimistic-ethereum/OVM/bridge/tokens/OVM_L2StandardBridge.sol). Modifications include:
7+
8+
- Contract versioning via `ITypeAndVersion` interface
9+
- ERC677 support by extending the `LinkToken` contract
10+
- Transfers & approves to the contract itself blocked (provided by `LinkToken` contract)
11+
- `l2Bridge` & `l1Token` were changed from storage vars to immutable vars, which provides some gas savings
12+
13+
The [Optimism Gateway](https://gateway.optimism.io) bridge UI can be used to move the tokens between networks.

0 commit comments

Comments
 (0)