Skip to content
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

feat: integrate wstETH bridge addresses #166

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions composables/zksync/deposit/useTransaction.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { DepositFeeValues } from "@/composables/zksync/deposit/useFee";
import type { Token } from "@/types";
import type { BigNumberish } from "ethers";
import type { L1Signer } from "zksync-ethers";

Expand All @@ -13,7 +14,7 @@ export default (getL1Signer: () => Promise<L1Signer | undefined>) => {
const commitTransaction = async (
transaction: {
to: string;
tokenAddress: string;
token: Token;
amount: BigNumberish;
},
fee: DepositFeeValues
Expand All @@ -39,11 +40,14 @@ export default (getL1Signer: () => Promise<L1Signer | undefined>) => {
}

status.value = "waiting-for-signature";
const isCustomBridge = isExternalBridgeToken(transaction.token);
const bridgeAddress = isCustomBridge ? EXTERNAL_BRIDGES[transaction.token.address] : "";
const depositResponse = await wallet.deposit({
to: transaction.to,
token: transaction.tokenAddress,
token: transaction.token.address,
amount: transaction.amount,
l2GasLimit: fee.l2GasLimit,
...(isCustomBridge ? { bridgeAddress } : {}),
overrides,
});

Expand Down
9 changes: 6 additions & 3 deletions composables/zksync/useFee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type FeeEstimationParams = {
type: "transfer" | "withdrawal";
from: string;
to: string;
tokenAddress: string;
token: Token;
};

export default (
Expand Down Expand Up @@ -51,15 +51,18 @@ export default (
if (!params) throw new Error("Params are not available");

const provider = getProvider();
const tokenBalance = balances.value.find((e) => e.address === params!.tokenAddress)?.amount || "1";
const tokenBalance = balances.value.find((e) => e.address === params!.token.address)?.amount || "1";
const [price, limit] = await Promise.all([
retry(() => provider.getGasPrice()),
retry(() => {
const isCustomBridge = isExternalBridgeToken(params!.token);
const bridgeAddress = isCustomBridge ? EXTERNAL_BRIDGES[params!.token.address] : "";
return provider[params!.type === "transfer" ? "estimateGasTransfer" : "estimateGasWithdraw"]({
from: params!.from,
to: params!.to,
token: params!.tokenAddress === ETH_TOKEN.address ? ETH_TOKEN.l1Address! : params!.tokenAddress,
token: params!.token.address === ETH_TOKEN.address ? ETH_TOKEN.l1Address! : params!.token.address,
amount: tokenBalance,
...(isCustomBridge ? { bridgeAddress } : {}),
});
}),
]);
Expand Down
10 changes: 6 additions & 4 deletions composables/zksync/useTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { type BigNumberish } from "ethers";

import { isCustomNode } from "@/data/networks";

import type { TokenAmount } from "@/types";
import type { Token, TokenAmount } from "@/types";
import type { Provider, Signer } from "zksync-ethers";

type TransactionParams = {
type: "transfer" | "withdrawal";
to: string;
tokenAddress: string;
token: Token;
amount: BigNumberish;
};

Expand Down Expand Up @@ -38,7 +38,9 @@ export default (getSigner: () => Promise<Signer | undefined>, getProvider: () =>
if (!signer) throw new Error("zkSync Signer is not available");

const getRequiredBridgeAddress = async () => {
if (transaction.tokenAddress === ETH_TOKEN.address) return undefined;
if (transaction.token.address === ETH_TOKEN.address) return undefined;
const isCustomBridge = isExternalBridgeToken(transaction.token);
if (isCustomBridge) return EXTERNAL_BRIDGES[transaction.token.address];
const bridgeAddresses = await retrieveBridgeAddresses();
return bridgeAddresses.erc20L2;
};
Expand All @@ -50,7 +52,7 @@ export default (getSigner: () => Promise<Signer | undefined>, getProvider: () =>
status.value = "waiting-for-signature";
const tx = await signer[transaction.type === "transfer" ? "transfer" : "withdraw"]({
to: transaction.to,
token: transaction.tokenAddress === ETH_TOKEN.address ? ETH_TOKEN.l1Address! : transaction.tokenAddress,
token: transaction.token.address === ETH_TOKEN.address ? ETH_TOKEN.l1Address! : transaction.token.address,
amount: transaction.amount,
bridgeAddress,
overrides: {
Expand Down
12 changes: 8 additions & 4 deletions composables/zksync/useWithdrawalFinalization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ export default (transactionInfo: ComputedRef<TransactionInfo>) => {
const { isCorrectNetworkSet } = storeToRefs(onboardStore);
const { tokens } = storeToRefs(tokensStore);

const retrieveBridgeAddress = useMemoize(() =>
providerStore
const retrieveBridgeAddress = useMemoize(() => {
const isCustomBridge = isExternalBridgeToken(transactionInfo.value.token);
if (isCustomBridge) {
return EXTERNAL_BRIDGES[transactionInfo.value.token.address];
}
return providerStore
.requestProvider()
.getDefaultBridgeAddresses()
.then((e) => e.erc20L1)
);
.then((e) => e.erc20L1);
});
const retrieveMainContractAddress = useMemoize(() => providerStore.requestProvider().getMainContractAddress());

const gasLimit = ref<BigNumberish | undefined>();
Expand Down
12 changes: 1 addition & 11 deletions data/customBridgeTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,4 @@ type CustomBridgeToken = {
symbol: string;
};

export const customBridgeTokens: CustomBridgeToken[] = [
{
chainId: 1,
l1Address: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0",
l2Address: "0x703b52F2b28fEbcB60E1372858AF5b18849FE867",
bridgeName: "txSync Bridge",
bridgeUrlDeposit: "https://portal.txsync.io/bridge/?token=0x703b52F2b28fEbcB60E1372858AF5b18849FE867",
bridgeUrlWithdraw: "https://portal.txsync.io/bridge/withdraw/?token=0x703b52F2b28fEbcB60E1372858AF5b18849FE867",
symbol: "wstETH",
},
];
export const customBridgeTokens: CustomBridgeToken[] = [];
15 changes: 15 additions & 0 deletions utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,18 @@ export const ETH_TOKEN: Token = {
decimals: 18,
iconUrl: "/img/eth.svg",
};

export const WST_ETH_TOKEN: Token = {
address: "0x703b52F2b28fEbcB60E1372858AF5b18849FE867",
l1Address: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0",
symbol: "wstETH",
name: "Wrapped liquid staked Ether 2.0",
decimals: 18,
iconUrl: "https://assets.coingecko.com/coins/images/18834/large/wstETH.png",
};

// External non-native bridge addresses:
export const EXTERNAL_BRIDGES = {
[WST_ETH_TOKEN.l1Address!]: "0x41527B2d03844dB6b0945f25702cB958b6d55989",
[WST_ETH_TOKEN.address]: "0xE1D6A50E7101c8f8db77352897Ee3f1AC53f782B",
};
8 changes: 7 additions & 1 deletion utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { BigNumber } from "ethers";

import { EXTERNAL_BRIDGES } from "./constants";

import type { ZkSyncNetwork } from "@/data/networks";
import type { TokenAmount } from "@/types";
import type { Token, TokenAmount } from "@/types";
import type { BigNumberish } from "ethers";

export function isOnlyZeroes(value: string) {
Expand Down Expand Up @@ -52,3 +54,7 @@ export async function retry<T>(func: () => Promise<T>, options: RetryOptions = {
}
}
}

export const isExternalBridgeToken = (token: Token) => {
return Object.hasOwn(EXTERNAL_BRIDGES, token.address);
};
6 changes: 6 additions & 0 deletions utils/mappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ export const mapApiToken = (token: Api.Response.Token): Token => {
};
}

// TODO: Update the address on the Block explorer API side
// Update the old wstETH address with new one
if (token.l1Address === WST_ETH_TOKEN.l1Address) {
token.l2Address = WST_ETH_TOKEN.address;
}

return {
l1Address: token.l1Address || undefined,
address: token.l2Address,
Expand Down
15 changes: 13 additions & 2 deletions views/transactions/Deposit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,17 @@ const tokenBalance = computed<BigNumberish | undefined>(() => {
return balance.value?.find((e) => e.address === selectedToken.value?.address)?.amount;
});

const getContractAddress = async () => {
if (selectedToken.value) {
const isExternalBridge = isExternalBridgeToken(selectedToken.value);
if (isExternalBridge) {
return EXTERNAL_BRIDGES[selectedToken.value.address];
} else {
return (await providerStore.requestProvider().getDefaultBridgeAddresses()).erc20L1;
}
}
};

const {
result: allowance,
inProgress: allowanceRequestInProgress,
Expand All @@ -477,7 +488,7 @@ const {
} = useAllowance(
computed(() => account.value.address),
computed(() => selectedToken.value?.address),
async () => (await providerStore.requestProvider().getDefaultBridgeAddresses()).erc20L1
getContractAddress
);
const enoughAllowance = computed(() => {
if (!allowance.value || !selectedToken.value) {
Expand Down Expand Up @@ -681,7 +692,7 @@ const makeTransaction = async () => {
const tx = await commitTransaction(
{
to: transaction.value!.to.address,
tokenAddress: transaction.value!.token.address,
token: transaction.value!.token,
amount: transaction.value!.token.amount,
},
feeValues.value!
Expand Down
4 changes: 2 additions & 2 deletions views/transactions/Transfer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ const estimate = async () => {
type: props.type,
from: transaction.value.from.address,
to: transaction.value.to.address,
tokenAddress: selectedToken.value.address,
token: selectedToken.value,
});
};
watch(
Expand Down Expand Up @@ -606,7 +606,7 @@ const makeTransaction = async () => {
{
type: props.type,
to: transaction.value!.to.address,
tokenAddress: transaction.value!.token.address,
token: transaction.value!.token,
amount: transaction.value!.token.amount,
},
{
Expand Down
Loading