Skip to content

Instantly share code, notes, and snippets.

@ericlee42
Last active December 1, 2023 00:17
Show Gist options
  • Save ericlee42/8da4a27d2ef5c17cfb8b3c67846fa9f0 to your computer and use it in GitHub Desktop.
Save ericlee42/8da4a27d2ef5c17cfb8b3c67846fa9f0 to your computer and use it in GitHub Desktop.
Metis bridge example
import { ethers } from "ethers";
import { readFile } from "fs/promises";
import IL2StandardBridge from "./IL2StandardBridge.json" assert { type: "json" };
import OVM_GasPriceOracle from "./OVM_GasPriceOracle.json" assert { type: "json" };
import IERC20 from "./IERC20.json.json" assert { type: "json" };
const privateKey = await readFile("key.txt", { encoding: "utf-8" });
const rpcClient = new ethers.JsonRpcProvider(
"https://andromeda.metis.io"
);
const wallet = new ethers.Wallet(privateKey, rpcClient);
const l2BridgeAddress = "0x4200000000000000000000000000000000000010"
const l2Bridge = new ethers.Contract(
l1BridgeAddress,
IL2StandardBridge,
wallet
);
const oracle = new ethers.Contract("0x420000000000000000000000000000000000000F", OVM_GasPriceOracle, rpcClient)
const fee = await oracle.minErc20BridgeCost()
if (fee < 1e18){ // min to 1 Metis
fee = 1e18
}
// to withdraw
// if you want to withdraw ETH, use 0x420000000000000000000000000000000000000A instead
// or change it to another one
const metisERC20 = "0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000"
const metisToken = new ethers.Contract(
metisERC20,
IERC20,
wallet
);
const withdrawTokenValue = 1e16 // change it!
const withdrawToAddress = "__placeholder__"
// Approve your token to the bridge
await metisToken.approve(l2BridgeAddress, withdrawTokenValue)
const l1Gas = 20_0000 // your l1 gas limit
await l2Bridge.withdrawTo(metisERC20, withdrawToAddress, withdrawTokenValue, l1Gas, "", {value: fee})
import { ethers } from "ethers";
import { readFile } from "fs/promises";
import IL1StandardBridge from "./IL1StandardBridge.json" assert { type: "json" };
import Lib_AddressManager from "./Lib_AddressManager.json" assert { type: "json" };
import iMVM_DiscountOracle from "./iMVM_DiscountOracle.json" assert { type: "json" };
import IERC20 from "./IERC20.json" assert { type: "json" };
const privateKey = await readFile("key.txt", { encoding: "utf-8" });
const rpcClient = new ethers.JsonRpcProvider(
"https://eth.llamarpc.com"
);
const addrManger = new ethers.Contract("0x918778e825747a892b17C66fe7D24C618262867d", Lib_AddressManager, rpcClient)
const oracle = new ethers.Contract(
await addrManger.getAddress("MVM_DiscountOracle"),
iMVM_DiscountOracle,
rpcClient
);
const l2Gas = await oracle.getMinL2Gas() + 20_0000
const l2Fee = l2Gas * (await oracle.getDiscount())
const wallet = new ethers.Wallet(privateKey, rpcClient);
const l1BridgeAddress = "0x3980c9ed79d2c191A89E02Fa3529C60eD6e9c04b"
const l1Bridge = new ethers.Contract(
l1BridgeAddress,
IL1StandardBridge,
wallet
);
const l2ChainId = 1088
// to deposit Ether
const depositToAddress = "__placeholder__"
const depositEther = 1e16 // change it!
await l1Bridge.depositETHToByChainId(l2ChainId, depositToAddress, l2Gas, "", {value: l2Fee + depositEther})
// to deposit ERC20
const l1TokenAddress = "__placeholder__"
const l2TokenAddress = "__placeholder__"
const l1token = new ethers.Contract(
l1TokenAddress,
IERC20,
wallet
);
const depositTokenValue = 1e16 // change it!
// Approve your token to the bridge
await l1token.approve(l1BridgeAddress, depositTokenValue)
await l1Bridge.depositERC20ToByChainId(l2ChainId, l1TokenAddress, l2TokenAddress,depositToAddress, depositTokenValue, l2Gas, "", {value: l2Fee})
[
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"internalType": "address",
"name": "spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
]
[
{
"inputs": [
{
"internalType": "uint256",
"name": "_chainid",
"type": "uint256"
},
{
"internalType": "address",
"name": "_l1Token",
"type": "address"
},
{
"internalType": "address",
"name": "_l2Token",
"type": "address"
},
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint256",
"name": "_amount",
"type": "uint256"
},
{
"internalType": "uint32",
"name": "_l2Gas",
"type": "uint32"
},
{
"internalType": "bytes",
"name": "_data",
"type": "bytes"
}
],
"name": "depositERC20ToByChainId",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_chainId",
"type": "uint256"
},
{
"internalType": "address",
"name": "_to",
"type": "address"
},
{
"internalType": "uint32",
"name": "_l2Gas",
"type": "uint32"
},
{
"internalType": "bytes",
"name": "_data",
"type": "bytes"
}
],
"name": "depositETHToByChainId",
"outputs": [],
"stateMutability": "payable",
"type": "function"
}
]
[
{
"inputs": [],
"name": "getDiscount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "getMinL2Gas",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_sender",
"type": "address"
}
],
"name": "isXDomainSenderAllowed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "sender",
"type": "address"
},
{
"internalType": "uint256",
"name": "_chainId",
"type": "uint256"
}
],
"name": "processL2SeqGas",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_allowAllXDomainSenders",
"type": "bool"
}
],
"name": "setAllowAllXDomainSenders",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_discount",
"type": "uint256"
}
],
"name": "setDiscount",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_minL2Gas",
"type": "uint256"
}
],
"name": "setMinL2Gas",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_sender",
"type": "address"
},
{
"internalType": "bool",
"name": "_isWhitelisted",
"type": "bool"
}
],
"name": "setWhitelistedXDomainSender",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
[
{
"inputs": [
{
"internalType": "string",
"name": "_name",
"type": "string"
}
],
"name": "getAddress",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
}
]
[
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "gasPrice",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes",
"name": "_data",
"type": "bytes"
}
],
"name": "getL1Fee",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes",
"name": "_data",
"type": "bytes"
}
],
"name": "getL1GasUsed",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l1BaseFee",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "minErc20BridgeCost",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "overhead",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "scalar",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment