-
Notifications
You must be signed in to change notification settings - Fork 358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WETH Bridge Implementation #5
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity ^0.8.0; | ||
|
||
import { IWETH9 } from "./interfaces/IWETH9.sol"; | ||
|
||
contract WETH9 is IWETH9 { | ||
string public name; | ||
string public symbol; | ||
uint8 public decimals; | ||
|
||
mapping(address => uint) public override balanceOf; | ||
mapping(address => mapping(address => uint)) public override allowance; | ||
|
||
constructor() public { | ||
name = "Wrapped Ether"; | ||
symbol = "WETH"; | ||
decimals = 18; | ||
} | ||
|
||
function deposit() public payable { | ||
balanceOf[msg.sender] += msg.value; | ||
emit Deposit(msg.sender, msg.value); | ||
} | ||
|
||
function withdraw(uint value) external override { | ||
balanceOf[msg.sender] -= value; | ||
(bool success, ) = msg.sender.call{value: value}(""); | ||
if (!success) { | ||
revert WETH_ETHTransferFailed(); | ||
} | ||
emit Withdrawal(msg.sender, value); | ||
} | ||
|
||
function totalSupply() external view override returns (uint) { | ||
return address(this).balance; | ||
} | ||
|
||
function approve( | ||
address spender, | ||
uint value | ||
) external override returns (bool) { | ||
allowance[msg.sender][spender] = value; | ||
emit Approval(msg.sender, spender, value); | ||
return true; | ||
} | ||
|
||
function transfer( | ||
address to, | ||
uint value | ||
) external override ensuresRecipient(to) returns (bool) { | ||
balanceOf[msg.sender] -= value; | ||
balanceOf[to] += value; | ||
|
||
emit Transfer(msg.sender, to, value); | ||
return true; | ||
} | ||
|
||
function transferFrom( | ||
address from, | ||
address to, | ||
uint value | ||
) external override ensuresRecipient(to) returns (bool) { | ||
if (from != msg.sender) { | ||
uint _allowance = allowance[from][msg.sender]; | ||
if (_allowance != type(uint).max) { | ||
allowance[from][msg.sender] -= value; | ||
} | ||
} | ||
|
||
balanceOf[from] -= value; | ||
balanceOf[to] += value; | ||
|
||
emit Transfer(from, to, value); | ||
return true; | ||
} | ||
|
||
modifier ensuresRecipient(address to) { | ||
// Prevents from burning or sending WETH tokens to the contract. | ||
if (to == address(0)) { | ||
revert WETH_InvalidTransferRecipient(); | ||
} | ||
if (to == address(this)) { | ||
revert WETH_InvalidTransferRecipient(); | ||
} | ||
_; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
/// @author Matter Labs | ||
interface IL1WethBridge { | ||
struct FinalizeWithdrawalL2MessageIndexes { | ||
uint256 ethL2MessageIndex; | ||
uint256 wethL2MessageIndex; | ||
} | ||
|
||
struct FinalizeWithdrawalMessages { | ||
bytes ethMessage; | ||
bytes wethMessage; | ||
} | ||
|
||
struct FinalizeWithdrawalMerkleProofs { | ||
bytes32[] ethProof; | ||
bytes32[] wethProof; | ||
} | ||
|
||
event DepositInitiated(address indexed from, address indexed to, address indexed l1Token, uint256 amount); | ||
|
||
event WithdrawalFinalized(address indexed to, address indexed l1Token, uint256 amount); | ||
|
||
event ClaimedFailedDeposit(address indexed to, address indexed l1Token, uint256 amount); | ||
|
||
function isWithdrawalFinalized(uint256 _l2BlockNumber, uint256 _l2MessageIndex) external view returns (bool); | ||
|
||
function deposit( | ||
address _l2Receiver, | ||
uint256 _amount, | ||
uint256 _l2TxGasLimit, | ||
uint256 _l2TxGasPerPubdataByte | ||
) external payable returns (bytes32 txHash); | ||
|
||
function claimFailedDeposit( | ||
address _depositSender, | ||
bytes32 _l2TxHash, | ||
uint256 _l2BlockNumber, | ||
uint256 _l2MessageIndex, | ||
uint16 _l2TxNumberInBlock, | ||
bytes32[] calldata _merkleProof | ||
) external; | ||
|
||
function finalizeWithdrawal( | ||
uint256 _l2BlockNumber, | ||
FinalizeWithdrawalL2MessageIndexes calldata _l2MessageIndexes, | ||
uint16 _l2TxNumberInBlock, | ||
FinalizeWithdrawalMessages calldata _messages, | ||
FinalizeWithdrawalMerkleProofs calldata _merkleProofs | ||
) external; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
/// @author Matter Labs | ||
interface IL2WethBridge { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, please don't create another interface, but use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as here #5 (comment). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then make a |
||
function initialize( | ||
address _l1Bridge, | ||
address _l1WethAddress, | ||
address _governor | ||
) external; | ||
|
||
event FinalizeDeposit( | ||
address indexed l1Sender, | ||
address indexed l2Receiver, | ||
address indexed l2Weth, | ||
uint256 amount | ||
); | ||
|
||
event WithdrawalInitiated( | ||
address indexed l2Sender, | ||
address indexed l1Receiver, | ||
address indexed l2Weth, | ||
uint256 amount | ||
); | ||
|
||
function finalizeDeposit( | ||
address _l1Sender, | ||
address _l2Receiver, | ||
uint256 _amount | ||
) external payable; | ||
|
||
function withdraw( | ||
address _l1Receiver, | ||
uint256 _amount | ||
) external; | ||
|
||
function l1WethAddress() external view returns (address); | ||
|
||
function l2WethAddress() external view returns (address); | ||
|
||
function l1WethBridge() external view returns (address); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity ^0.8.0; | ||
|
||
interface IWETH9 { | ||
function deposit() external payable; | ||
|
||
function withdraw(uint wad) external; | ||
|
||
event Deposit(address indexed dst, uint wad); | ||
event Withdrawal(address indexed src, uint wad); | ||
|
||
error WETH_ETHTransferFailed(); | ||
error WETH_InvalidTransferRecipient(); | ||
|
||
// ERC20 | ||
// function name() external view returns (string memory); | ||
|
||
// function symbol() external view returns (string memory); | ||
|
||
// function decimals() external view returns (uint8); | ||
|
||
function totalSupply() external view returns (uint); | ||
|
||
function balanceOf(address guy) external view returns (uint); | ||
|
||
function allowance(address src, address dst) external view returns (uint); | ||
|
||
function approve(address spender, uint wad) external returns (bool); | ||
|
||
function transfer(address dst, uint wad) external returns (bool); | ||
|
||
function transferFrom( | ||
address src, | ||
address dst, | ||
uint wad | ||
) external returns (bool); | ||
|
||
event Approval(address indexed src, address indexed dst, uint wad); | ||
event Transfer(address indexed src, address indexed dst, uint wad); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { Command } from 'commander'; | ||
import { Wallet, ethers } from 'ethers'; | ||
import { Deployer } from '../src.ts/deploy'; | ||
import { formatUnits, parseUnits } from 'ethers/lib/utils'; | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
import { web3Provider } from './utils'; | ||
|
||
const provider = web3Provider(); | ||
const testConfigPath = path.join(process.env.ZKSYNC_HOME as string, `etc/test_config/constant`); | ||
const ethTestConfig = JSON.parse(fs.readFileSync(`${testConfigPath}/eth.json`, { encoding: 'utf-8' })); | ||
|
||
async function main() { | ||
const program = new Command(); | ||
|
||
program.version('0.1.0').name('deploy').description('deploy weth bridges'); | ||
|
||
program | ||
.option('--private-key <private-key>') | ||
.option('--gas-price <gas-price>') | ||
.option('--nonce <nonce>') | ||
.option('--governor-address <governor-address>') | ||
.option('--create2-salt <create2-salt>') | ||
.action(async (cmd) => { | ||
const deployWallet = cmd.privateKey | ||
? new Wallet(cmd.privateKey, provider) | ||
: Wallet.fromMnemonic( | ||
process.env.MNEMONIC ? process.env.MNEMONIC : ethTestConfig.mnemonic, | ||
"m/44'/60'/0'/0/0" | ||
).connect(provider); | ||
console.log(`Using deployer wallet: ${deployWallet.address}`); | ||
|
||
const governorAddress = cmd.governorAddress ? cmd.governorAddress : deployWallet.address; | ||
console.log(`Using governor address: ${governorAddress}`); | ||
|
||
const gasPrice = cmd.gasPrice ? parseUnits(cmd.gasPrice, 'gwei') : await provider.getGasPrice(); | ||
console.log(`Using gas price: ${formatUnits(gasPrice, 'gwei')} gwei`); | ||
|
||
let nonce = cmd.nonce ? parseInt(cmd.nonce) : await deployWallet.getTransactionCount(); | ||
console.log(`Using nonce: ${nonce}`); | ||
|
||
const create2Salt = cmd.create2Salt ? cmd.create2Salt : ethers.utils.hexlify(ethers.utils.randomBytes(32)); | ||
|
||
const deployer = new Deployer({ | ||
deployWallet, | ||
governorAddress, | ||
verbose: true | ||
}); | ||
|
||
await deployer.deployWethBridgeContracts(create2Salt, gasPrice); | ||
}) | ||
await program.parseAsync(process.argv); | ||
} | ||
|
||
main() | ||
.then(() => process.exit(0)) | ||
.catch((err) => { | ||
console.error('Error:', err); | ||
process.exit(1); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All bridges supposed to inherit the same interface as default bridge, so all the same functions/events should be inherit from the
IL1Bridge
. And all weth-spefic functions fine to be here.