diff --git a/src/adapters/index.ts b/src/adapters/index.ts index 425ce037..160e3459 100644 --- a/src/adapters/index.ts +++ b/src/adapters/index.ts @@ -58,6 +58,7 @@ import orbiter from "./orbiter"; import connext from "./connext"; import xswap from "./xswap"; import owlto from "./owlto" +import zkbridge from "./zkbridge" export default { polygon, @@ -118,6 +119,7 @@ export default { connext, xswap, owlto, + zkbridge, } as { [bridge: string]: BridgeAdapter; }; diff --git a/src/adapters/zkbridge/contants.ts b/src/adapters/zkbridge/contants.ts new file mode 100644 index 00000000..5a6d2f6e --- /dev/null +++ b/src/adapters/zkbridge/contants.ts @@ -0,0 +1,361 @@ +const nativeTokens: Record = { + ethereum: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + arbitrum: "0x82af49447d8a07e3bd95bd0d56f35241523fbab1", + optimism: "0x4200000000000000000000000000000000000006", + base: "0x4200000000000000000000000000000000000006", + linea: "0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f", + blast: "0x4300000000000000000000000000000000000004", + scroll: "0x5300000000000000000000000000000000000004", + polygon: "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", + bsc: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", + polygon_zkevm: "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", + era: "0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91", + arbitrum_nova: "0x722E8BdD2ce80A4422E880164f2079488e115365", + merlin: "0xF6D226f9Dc15d9bB51182815b320D3fBE324e1bA", + opbnb: "0x4200000000000000000000000000000000000006", + combo: "0x4200000000000000000000000000000000000006", + bouncebit: "0xF4c20e5004C6FDCDdA920bDD491ba8C98a9c5863", + bitlayer: "0xff204e2681a6fa0e2c3fade68a1b28fb90e4fc5f", + mantle: "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8" + }; + +const zkbridgeContractes = { + ethereum: { + "0x89a56FF41a4be1360f780c5abFBA8FD7EceD2c7A":{ + 1:{ + isNativeToken:true, + nativeToken:nativeTokens["ethereum"], + tokenDecimal:18, + shareDecimal:18, + }, + 3: { + tokenAddress:"0xdAC17F958D2ee523a2206206994597C13D831ec7", + tokenDecimal:6, + shareDecimal:6, + } + }, + "0xA4252F2A68b2A078c86E0569eB7Fb872A37864AF": { + 1: { + tokenAddress: "0xdAC17F958D2ee523a2206206994597C13D831ec7", + tokenDecimal: 6, + shareDecimal: 6, + }, + 2: { + tokenAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + tokenDecimal: 6, + shareDecimal: 6 + }, + 20: { + isNativeToken: true, + nativeToken: nativeTokens["ethereum"], + tokenDecimal: 18, + shareDecimal: 18 + } + }, + "0x04B9b6a1C41D1A7c98e5D2523460c39F4757e9A8": { + 1: { + tokenAddress:"0xF5e11df1ebCf78b6b6D26E04FF19cD786a1e81dC", + tokenDecimal: 18, + shareDecimal: 18 + }, + 2: { + tokenAddress: "0x77776b40C3d75cb07ce54dEA4b2Fd1D07F865222", + tokenDecimal: 18, + shareDecimal: 18 + } + }, + "0x00D38853127A2f84474353735eA3a4c3213DFF91": { + 1: { + tokenAddress: "0xd5F7838F5C461fefF7FE49ea5ebaF7728bB0ADfa", + tokenDecimal: 18, + shareDecimal: 18 + }, + 20: { + tokenAddress: "0x3c3a81e81dc49A522A592e7622A7E711c06bf354", + tokenDecimal: 20, + shareDecimal: 20 + } + } + }, + bsc: { + "0x51187757342914E7d94FFFD95cCCa4f440FE0E06": { + 1: { + tokenAddress: "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", + tokenDecimal: 18, + shareDecimal:18 + }, + 3: { + tokenAddress: "0x55d398326f99059fF775485246999027B3197955", + tokenDecimal: 18, + shareDecimal: 6 + }, + 10: { + isNativeToken: true, + nativeToken: nativeTokens["bsc"], + tokenDecimal: 18, + shareDecimal: 18, + } + }, + "0x1B60db9374EE8B9a7706B1D746259D8AFfbf4Cb9": { + 1: { + tokenAddress: "0xF5e11df1ebCf78b6b6D26E04FF19cD786a1e81dC", + tokenDecimal: 18, + shareDecimal: 18, + }, + 2: { + tokenAddress: "0x77776b40C3d75cb07ce54dEA4b2Fd1D07F865222", + tokenDecimal: 18, + shareDecimal: 18 + } + }, + "0x5F9d235289da95520d683F6C0E9F495D435C0300": { + 1: { + tokenAddress: "0xF4C8E32EaDEC4BFe97E0F595AdD0f4450a863a11", + tokenDecimal: 18, + shareDecimal: 18 + } + }, + "0xd00EE54eaCBf05c56dC5D183F6E7b3Bac5356244": { + 1: { + tokenAddress: "0x60D01EC2D5E98Ac51C8B4cF84DfCCE98D527c747", + tokenDecimal: 18, + shareDecimal: 18 + } + }, + "0x9BC19953839618bBA89f28aC4eC761d7051AF440": { + 1: { + tokenAddress: "0xc03fBF20A586fa89C2a5f6F941458E1Fbc40c661", + tokenDecimal: 18, + shareDecimal: 18 + } + } + }, + polygon: { + "0x104bc711530554F18936a12542192F8bd36166B1": { + 1: { + tokenDecimal: 18, + shareDecimal: 18, + tokenAddress: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + }, + 3: { + tokenDecimal: 6, + shareDecimal: 6, + tokenAddress: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F" + } + } + }, + optimism: { + "0x24bbC063DeF30Ae81AECC659B97A8b2562b2AFCd": { + 1: { + isNativeToken: true, + nativeToken: nativeTokens["optimism"], + tokenDecimal: 18, + shareDecimal: 18, + }, + 3: { + tokenAddress: "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58", + tokenDecimal: 6, + shareDecimal: 6, + } + } + }, + arbitrum: { + "0xC9D0b733AdAa1f851639cA47a9a2d8A6C8572BdB": { + 1: { + isNativeToken: true, + nativeToken: nativeTokens["arbitrum"], + tokenDecimal:18, + shareDecimal:18 + }, + 3: { + tokenAddress: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", + tokenDecimal: 6, + shareDecimal: 6 + } + } + }, + linea: { + "0x366C1B89aA0783d0886B9EF817d10c8729783dCb": { + 1: { + isNativeToken: true, + nativeToken: nativeTokens["linea"], + tokenDecimal: 18, + shareDecimal: 18 + }, + 3: { + tokenAddress: "0xA219439258ca9da29E9Cc4cE5596924745e12B93", + tokenDecimal: 6, + shareDecimal: 6 + } + }, + "0xAAe504413e6745FFC111447b1688940D62570126": { + 1: { + tokenAddress: "0x60D01EC2D5E98Ac51C8B4cF84DfCCE98D527c747", + tokenDecimal: 18, + shareDecimal: 18 + } + } + }, + mantle: { + "0xAFC153cF66F33C492d5b638Ee90f5eBd2673e4d3": { + 1: { + tokenAddress: "0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111", + tokenDecimal: 18, + shareDecimal: 18 + }, + 3: { + tokenAddress: "0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE", + tokenDecimal: 6, + shareDecimal: 6 + } + }, + "0x3843C95D9f8554baffdfc0C145Ce9DfB06Cd4E24": { + 1: { + tokenAddress: "0x60D01EC2D5E98Ac51C8B4cF84DfCCE98D527c747", + tokenDecimal: 18, + shareDecimal: 18 + } + }, + "0xf926f7D15c62eC18299bA817A73A2519fCC3Bfec": { + 1: { + tokenAddress: "0xcDA86A272531e8640cD7F1a92c01839911B90bb0", + tokenDecimal: 18, + shareDecimal: 18 + }, + 20: { + isNativeToken: true, + nativeToken: nativeTokens["mantle"], + tokenDecimal: 18, + shareDecimal: 18 + } + } + }, + base: { + "0x87A659d0433F21E257f5d252fe163E1341DdCe81": { + 1: { + isNativeToken: true, + nativeToken: nativeTokens["base"], + tokenDecimal: 18, + shareDecimal: 18, + } + } + }, + "op_bnb": { + "0x953a578c7Ce8F3A1BF625d182A8caf7181FD4BEB": { + 1: { + tokenAddress: "0xE7798f023fC62146e8Aa1b36Da45fb70855a77Ea", + tokenDecimal: 18, + shareDecimal: 18, + }, + 3: { + tokenAddress: "0x9e5AAC1Ba1a2e6aEd6b32689DFcF62A509Ca96f3", + tokenDecimal: 18, + shareDecimal: 6, + }, + 10: { + isNativeToken: true, + nativeToken: nativeTokens["opbnb"], + tokenDecimal: 18, + shareDecimal:18 + } + }, + "0xcdBCB231639dB01BAa1dCFBbB93c3264d921E0Fc": { + 1: { + tokenAddress:"0x9d94a7ff461e83f161c8c040e78557e31d8cba72", + tokenDecimal: 18, + shareDecimal: 18 + } + } + }, + scroll: { + "0xe69F676b2142FA05A3DC51A0E51d68a685AE7391": { + 1: { + isNativeToken: true, + nativeToken: nativeTokens["scroll"], + tokenDecimal: 18, + shareDecimal: 18, + }, + 3: { + tokenAddress: "0xf55BEC9cafDbE8730f096Aa55dad6D22d44099Df", + tokenDecimal: 6, + shareDecimal: 6, + } + }, + "0xb9fe89f0e2A18f3B2A0EB6A9747F1eAf0F499ff5": { + 1: { + tokenAddress: "0x60D01EC2D5E98Ac51C8B4cF84DfCCE98D527c747", + tokenDecimal: 18, + shareDecimal: 18 + } + } + }, + "combo-mainnet": { + "0x254010E880e04a27C98cBb8D241f8C3554d3784d": { + 3: { + tokenAddress: "0x7c6b91D9Be155A6Db01f749217d76fF02A7227F2", + tokenDecimal: 18, + shareDecimal: 6 + }, + 10: { + isNativeToken: true, + nativeToken: nativeTokens["combo"], + tokenDecimal: 18, + shareDecimal: 18, + } + }, + "0xA4121b1D357E94Fb29DF61a6EDBa118E7Ca27F05": { + 1: { + tokenAddress: "0xD08a2917653d4E460893203471f0000826fb4034", + tokenDecimal: 18, + shareDecimal: 18 + } + } + }, + "bouncebit-mainnet": { + "0xfbC7f3607cff8355dc5B0D3bF4f9614376389321": { + 1: { + tokenAddress: "0xf5e11df1ebcf78b6b6d26e04ff19cd786a1e81dc", + tokenDecimal:18, + shareDecimal: 18, + }, + 2: { + tokenAddress: "0x77776b40c3d75cb07ce54dea4b2fd1d07f865222", + tokenDecimal: 18, + shareDecimal: 18 + } + } + }, + "btr": { + "0x36cAE7b6b0B68c4dDb2BBD3CDeE34fd56f948aAe": { + 1: { + tokenAddress: "0xfe9f969faf8ad72a83b761138bf25de87eff9dd2", + tokenDecimal: 6, + shareDecimal: 6 + }, + 2: { + tokenAddress: "0x9827431e8b77e87c9894bd50b055d6be56be0030", + tokenDecimal: 6, + shareDecimal: 6 + }, + 20: { + tokenAddress: "0xef63d4e178b3180beec9b0e143e0f37f4c93f4c2", + tokenDecimal: 18, + shareDecimal: 18 + } + } + } + } as { + [chain: string]: { + [address:string]: { + [poolId:number]: { + isNativeToken?:boolean; + nativeToken?:string; + tokenAddress?: string; + tokenDecimal:number; + shareDecimal:number; + } + } + } + } + + export default zkbridgeContractes; \ No newline at end of file diff --git a/src/adapters/zkbridge/index.ts b/src/adapters/zkbridge/index.ts new file mode 100644 index 00000000..a1620045 --- /dev/null +++ b/src/adapters/zkbridge/index.ts @@ -0,0 +1,149 @@ +import { BridgeAdapter, PartialContractEventParams } from "../../helpers/bridgeAdapter.type"; +import { Chain } from "@defillama/sdk/build/general"; +import { getTxDataFromEVMEventLogs } from "../../helpers/processTransactions"; +import { getProvider } from "../../utils/provider"; +import zkbridgeContractes from "./contants"; +import {ethers} from "ethers"; + +const depositParams: PartialContractEventParams = { + target: "", + topic: "TransferToken(uint64,uint16,uint256,address,address,uint256)", + abi: ["event TransferToken(uint64 indexed sequence, uint16 indexed dstChainId, uint256 indexed poolId, address sender, address recipient, uint256 amount)"], + logKeys: { + blockNumber: "blockNumber", + txHash: "transactionHash" + }, + argKeys: { + from: "sender", + to: "recipient", + amount: "amount", + }, + isDeposit: true +}; + +const withdrawalParams: PartialContractEventParams = { + target: "", + topic: "ReceiveToken(uint64,uint16,uint256,address,uint256)", + abi: ["event ReceiveToken(uint64 indexed sequence, uint16 indexed srcChainId, uint256 indexed poolId, address recipient, uint256 amount)"], + logKeys: { + blockNumber: "blockNumber", + txHash: "transactionHash" + }, + argKeys: { + to: "recipient", + amount: "amount", + + }, + isDeposit: false +}; + + +const wait = (ms: number) => + new Promise((resolve, _reject) => { + setTimeout(() => { + resolve(""); + }, ms); + }); + +const newConstructParams = (chain: string) => { + + let eventParams = [] as any; + const bridges = zkbridgeContractes[chain]; + if (!bridges) { + return + } + Object.entries(bridges).map(([address, _]) => { + const finalDepositParams = { + ...depositParams, + target: address, + fixedEventData: { + to: address + } + }; + const finalWithdrawalParams = { + ...withdrawalParams, + target: address, + fixedEventData: { + from: address + } + }; + eventParams.push(finalDepositParams, finalWithdrawalParams); + }); + + return async (fromBlock: number, toBlock: number) => { + let eventLogDatas = await getTxDataFromEVMEventLogs("zkbridge", chain as Chain, fromBlock, toBlock, eventParams); + let res = []; + let j = 0; + for (let eventLogData of eventLogDatas) { + const provider = getProvider(chain) as any; + let txReceipt; + for (let i = 0; i < 5; i ++) { + + txReceipt = await provider.getTransactionReceipt(eventLogData.txHash); + if (txReceipt) { + break + } + await wait(500) + } + if (!txReceipt) { + break + } + let contractAddr; + if (eventLogData.isDeposit) { + contractAddr = eventLogData.to + } else { + contractAddr = eventLogData.from + } + let bridge = bridges[contractAddr] + + for (let log of txReceipt.logs) { + if (log.topics[0].slice(0, 8) === "0x302b3e" || log.topics[0].slice(0, 8) === "0xe0442d") { + let poolId = ethers.BigNumber.from(log.topics[3]); + let poolInfo = bridge[poolId.toNumber()]; + if (!poolInfo) { + continue + } + if (poolInfo.isNativeToken) {// native token + // @ts-ignore + eventLogData.token = poolInfo.nativeToken; + if (eventLogData.isDeposit) { + eventLogData.amount = ethers.BigNumber.from("0x" + log.data.slice(130, 194)); + } else { + eventLogData.amount = ethers.BigNumber.from("0x" + log.data.slice(66, 130)); + } + } else { // erc20 token + for (let log of txReceipt.logs) { + if (log.topics[0].slice(0, 8) === "0xddf252") { + eventLogData.token = log.address; + eventLogData.amount = ethers.BigNumber.from(log.data); + break; + } + } + } + break; + } + } + res[j] = eventLogData; + j++; + } + return res; + }; +}; + +const adapter: BridgeAdapter = { + ethereum: newConstructParams("ethereum"), + bsc: newConstructParams("bsc"), + polygon: newConstructParams("polygon"), + optimism: newConstructParams("optimism"), + arbitrum: newConstructParams("arbitrum"), + linea: newConstructParams("linea"), + mantle: newConstructParams("mantle"), + base: newConstructParams("base"), + scroll: newConstructParams("scroll"), + opbnb: newConstructParams("op_bnb"), + combo: newConstructParams("combo-mainnet"), + bouncebit: newConstructParams("bouncebit-mainnet"), + bitlayer: newConstructParams("btr") +}; + +export default adapter; \ No newline at end of file diff --git a/src/data/bridgeNetworkData.ts b/src/data/bridgeNetworkData.ts index cf934e5e..30a3edfd 100644 --- a/src/data/bridgeNetworkData.ts +++ b/src/data/bridgeNetworkData.ts @@ -1110,4 +1110,33 @@ export default [ "x layer": "xlayer", }, }, + { + id: 63, + displayName: "zkbridge", + bridgeDbName: "zkbridge", + iconLink: "icons:zkbridge", + largeTxThreshold: 10000, + url: "https://www.zkbridge.com/token", + chains: [ + "Ethereum", + "BSC", + "Polygon", + "Optimism", + "Arbitrum", + "Linea", + "Mantle", + "Base", + "Scroll", + "opBNB", + "Combo", + "Bouncebit", + "Bitlayer" + ], + chainMapping: { + combo: "combo-mainnet", + "bouncebit":"bouncebit-mainnet", + opbnb: "op_bnb", + "bitlayer":"btr", + }, + }, ] as BridgeNetwork[]; diff --git a/src/helpers/tokenMappings.ts b/src/helpers/tokenMappings.ts index 453e1645..bd370513 100644 --- a/src/helpers/tokenMappings.ts +++ b/src/helpers/tokenMappings.ts @@ -12,6 +12,8 @@ export const transformTokens = { "0x9cef9a0b1be0d289ac9f4a98ff317c33eaa84eb8": "ethereum:0x8d6cebd76f18e1558d4db88138e2defb3909fad6", "0xd8772edbf88bba2667ed011542343b0eddacda47": "ethereum:0x9e32b13ce7f2e80a01932b42553652e053d6ed8e", "0x430ebff5e3e80a6c58e7e6ada1d90f5c28aa116d": "ethereum:0xdac17f958d2ee523a2206206994597c13d831ec7", + "0xf5e11df1ebcf78b6b6d26e04ff19cd786a1e81dc": "ethereum:0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", + "0x77776b40c3d75cb07ce54dea4b2fd1d07f865222": "bsc:0xe9e7cea3dedca5984780bafc599bd69add087d56", }, bsc: { "0x98a5737749490856b401db5dc27f522fc314a4e1": "bsc:0xe9e7cea3dedca5984780bafc599bd69add087d56", @@ -20,6 +22,8 @@ export const transformTokens = { "0x7bfd7f2498c4796f10b6c611d9db393d3052510c": "bsc:0x3f56e0c36d275367b8c502090edf38289b3dea0d", "0xd4cec732b3b135ec52a3c0bc8ce4b8cfb9dace46": "bsc:0xe552fb52a4f19e44ef5a967632dbc320b0820639", "0x68c6c27fb0e02285829e69240be16f32c5f8befe": "bsc:0x55d398326f99059ff775485246999027b3197955", + "0xf5e11df1ebcf78b6b6d26e04ff19cd786a1e81dc": "bsc:0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c", + "0x77776b40c3d75cb07ce54dea4b2fd1d07f865222": "bsc:0xe9e7cea3dedca5984780bafc599bd69add087d56", }, avax: { "0x1205f31718499dbf1fca446663b532ef87481fe1": "avax:0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e", @@ -56,6 +60,19 @@ export const transformTokens = { fantom: { "0x12edea9cd262006cc3c4e77c90d2cd2dd4b1eb97": "fantom:0x04068da6c83afcfa0e13ba15a6696662335d5b75", }, + "bouncebit-mainnet": { + "0xf5e11df1ebcf78b6b6d26e04ff19cd786a1e81dc": "bsc:0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c", + "0x77776b40c3d75cb07ce54dea4b2fd1d07f865222": "bsc:0xe9e7cea3dedca5984780bafc599bd69add087d56", + }, + "combo-mainnet":{ + "0xd08a2917653d4e460893203471f0000826fb4034": "bsc:0xc03fbf20a586fa89c2a5f6f941458e1fbc40c661", + "0x7c6b91d9be155a6db01f749217d76ff02a7227f2": "bsc:0x55d398326f99059ff775485246999027b3197955", + "0x4200000000000000000000000000000000000006": "bsc:0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c", + }, + "op_bnb":{ + "0xe7798f023fc62146e8aa1b36da45fb70855a77ea": "ethereum:0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + "0x9d94a7ff461e83f161c8c040e78557e31d8cba72": "bsc:0xf4c8e32eadec4bfe97e0f595add0f4450a863a11", + } } as { [chain: string]: { [token: string]: string; @@ -76,6 +93,7 @@ export const transformTokenDecimals = { "0x9cef9a0b1be0d289ac9f4a98ff317c33eaa84eb8": 6, "0xd8772edbf88bba2667ed011542343b0eddacda47": 18, "0x430ebff5e3e80a6c58e7e6ada1d90f5c28aa116d": 6, + "0xf5e11df1ebcf78b6b6d26e04ff19cd786a1e81dc": 18, }, bsc: { "0x98a5737749490856b401db5dc27f522fc314a4e1": 6,