diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..8bf44bfa Binary files /dev/null and b/.DS_Store differ diff --git a/src/adapters/router/assetForwarder.json b/src/adapters/router/assetForwarder.json new file mode 100644 index 00000000..b9b47a19 --- /dev/null +++ b/src/adapters/router/assetForwarder.json @@ -0,0 +1,1285 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "_wrappedNativeTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_gatewayContract", + "type": "address" + }, + { + "internalType": "address", + "name": "_usdcAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_tokenMessenger", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_routerMiddlewareBase", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_minGasThreshhold", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AmountTooLarge", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFee", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidGateway", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRefundData", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRequestSender", + "type": "error" + }, + { + "inputs": [], + "name": "MessageAlreadyExecuted", + "type": "error" + }, + { + "inputs": [], + "name": "MessageExcecutionFailedWithLowGas", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "pauser", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stakedAmount", + "type": "uint256" + } + ], + "name": "CommunityPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "srcToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "depositId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "eventNonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "initiatewithdrawal", + "type": "bool" + }, + { + "indexed": false, + "internalType": "address", + "name": "depositor", + "type": "address" + } + ], + "name": "DepositInfoUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "partnerId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "destChainIdBytes", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "destAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "depositId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "srcToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "recipient", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "destToken", + "type": "bytes" + } + ], + "name": "FundsDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "partnerId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "destChainIdBytes", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "destAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "depositId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "srcToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "recipient", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "address", + "name": "depositor", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "destToken", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "FundsDepositedWithMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "forwarder", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "FundsPaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "forwarder", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "execFlag", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "execData", + "type": "bytes" + } + ], + "name": "FundsPaidWithMessage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "Unpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "partnerId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "destChainIdBytes", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "usdcNonce", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "srcToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "depositor", + "type": "address" + } + ], + "name": "iUSDCDeposited", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_TRANSFER_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_GAS_THRESHHOLD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PAUSER", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESOURCE_SETTER", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "communityPause", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "depositNonce", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "destDetails", + "outputs": [ + { + "internalType": "uint32", + "name": "domainId", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isSet", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "executeRecord", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gatewayContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "partnerId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "destAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "srcToken", + "type": "address" + }, + { + "internalType": "address", + "name": "refundRecipient", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "destChainIdBytes", + "type": "bytes32" + } + ], + "internalType": "struct IAssetForwarder.DepositData", + "name": "depositData", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "destToken", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "recipient", + "type": "bytes" + } + ], + "name": "iDeposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "srcToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "depositId", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "initiatewithdrawal", + "type": "bool" + } + ], + "name": "iDepositInfoUpdate", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "partnerId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "destAmount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "srcToken", + "type": "address" + }, + { + "internalType": "address", + "name": "refundRecipient", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "destChainIdBytes", + "type": "bytes32" + } + ], + "internalType": "struct IAssetForwarder.DepositData", + "name": "depositData", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "destToken", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "recipient", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "iDepositMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "partnerId", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "destChainIdBytes", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "recipient", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "iDepositUSDC", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "requestSender", + "type": "string" + }, + { + "internalType": "bytes", + "name": "packet", + "type": "bytes" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "iReceive", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "srcChainId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "depositId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destToken", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "internalType": "struct IAssetForwarder.RelayData", + "name": "relayData", + "type": "tuple" + } + ], + "name": "iRelay", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "srcChainId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "depositId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "destToken", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "internalType": "struct IAssetForwarder.RelayDataMessage", + "name": "relayData", + "type": "tuple" + } + ], + "name": "iRelayMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "isCommunityPauseEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "data", + "type": "bytes[]" + } + ], + "name": "multicall", + "outputs": [ + { + "internalType": "bytes[]", + "name": "results", + "type": "bytes[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseStakeAmountMax", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauseStakeAmountMin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "rescue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "routerMiddlewareBase", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "_destChainIdBytes", + "type": "bytes32[]" + }, + { + "components": [ + { + "internalType": "uint32", + "name": "domainId", + "type": "uint32" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isSet", + "type": "bool" + } + ], + "internalType": "struct IAssetForwarder.DestDetails[]", + "name": "_destDetails", + "type": "tuple[]" + } + ], + "name": "setDestDetails", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "toggleCommunityPause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "tokenMessenger", + "outputs": [ + { + "internalType": "contract ITokenMessenger", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalStakedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_gatewayContract", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_routerMiddlewareBase", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "minPauseStakeAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxPauseStakeAmount", + "type": "uint256" + } + ], + "name": "update", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenMessenger", + "type": "address" + } + ], + "name": "updateTokenMessenger", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usdc", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawStakeAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "wrappedNativeToken", + "outputs": [ + { + "internalType": "contract IWETH", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] \ No newline at end of file diff --git a/src/adapters/router/index.ts b/src/adapters/router/index.ts index 10ab5fd7..b371ace5 100644 --- a/src/adapters/router/index.ts +++ b/src/adapters/router/index.ts @@ -1,6 +1,10 @@ import { Chain } from "@defillama/sdk/build/general"; import { BridgeAdapter, PartialContractEventParams } from "../../helpers/bridgeAdapter.type"; import { getTxDataFromEVMEventLogs } from "../../helpers/processTransactions"; +import { ethers } from "ethers"; +import assetForwarderAbi from "./assetForwarder.json" +import { getTxsBlockRangeEtherscan } from "../../helpers/etherscan"; +import { EventData } from "../../utils/types"; const bridgeAddresses = { ethereum: "0xc21e4ebd1d92036cb467b53fe3258f219d909eb9", @@ -14,34 +18,64 @@ const bridgeAddresses = { arbitrum: "0xef300fb4243a0ff3b90c8ccfa1264d78182adaa4", aurora: "0xc21e4ebd1d92036cb467b53fe3258f219d909eb9", tron: "0x9d25b8289c0f3789237c1b3a88264882eed6c610", - polygonzkevm: "0xc21e4ebd1d92036cb467b53fe3258f219d909eb9", - zksync: "0x8b6f1c18c866f37e6ea98aa539e0c117e70178a2", + polygon_zkevm: "0xc21e4ebd1d92036cb467b53fe3258f219d909eb9", + era: "0x8b6f1c18c866f37e6ea98aa539e0c117e70178a2", manta: "0x21c1e74caadf990e237920d5515955a024031109", mantle: "0xc21e4ebd1d92036cb467b53fe3258f219d909eb9", - rsk: "0xc21e4ebd1d92036cb467b53fe3258f219d909eb9" - } as { [chain: string]: string }; + rsk: "0xc21e4ebd1d92036cb467b53fe3258f219d909eb9", + optimism: "0x8201c02d4ab2214471e8c3ad6475c8b0cd9f2d06", +} as { [chain: string]: string }; + + +const signatures: { [key: string]: string } = { + "0x64778c1f": "iRelay", + "0x6fb003da": "iRelayMessage" +}; + +interface Transaction { + blockNumber: string; + timeStamp: string; + hash: string; + nonce: string; + blockHash: string; + transactionIndex: string; + from: string; + to: string; + value: string; + gas: string; + gasPrice: string; + isError: string; + txreceipt_status: string; + input: string; + contractAddress: string; + cumulativeGasUsed: string; + gasUsed: string; + confirmations: string; + methodId: string; + functionName: string; +} + - const constructParams = (chain: string) => { let eventParams = [] as PartialContractEventParams[]; const bridgeAddress = bridgeAddresses[chain]; - const withdrawParamsTransfer = { - target: bridgeAddress, - topic: "FundsPaid(bytes32,address,uint256)", - abi: [ - "event FundsPaid (bytes32 messageHash, address forwarder, uint256 nonce)", - ], - logKeys: { - blockNumber: "blockNumber", - txHash: "transactionHash", - }, - argKeys: { - }, - fixedEventData: { - from: bridgeAddress, - }, - isDeposit: false, - }; + // const withdrawParamsTransfer = { + // target: bridgeAddress, + // topic: "FundsPaid(bytes32,address,uint256)", + // abi: [ + // "event FundsPaid (bytes32 messageHash, address forwarder, uint256 nonce)", + // ], + // logKeys: { + // blockNumber: "blockNumber", + // txHash: "transactionHash", + // }, + // argKeys: { + // }, + // fixedEventData: { + // from: bridgeAddress, + // }, + // isDeposit: false, + // }; const depositParamsTransfer = { target: bridgeAddress, @@ -56,7 +90,8 @@ const constructParams = (chain: string) => { argKeys: { amount: "destAmount", token: "srcToken", - to: "recipient" + to: "recipient", + from: "depositor" }, fixedEventData: { from: bridgeAddress, @@ -64,23 +99,23 @@ const constructParams = (chain: string) => { isDeposit: true, }; - const withdrawParamsSwap = { - target: bridgeAddress, - topic: "FundsPaidWithMessage(bytes32,address,uint256,bool,bytes)", - abi: [ - "event FundsPaidWithMessage (bytes32 messageHash, address forwarder, uint256 nonce, bool execFlag, bytes execData)", - ], - logKeys: { - blockNumber: "blockNumber", - txHash: "transactionHash", - }, - argKeys: { - }, - fixedEventData: { - from: bridgeAddress, - }, - isDeposit: false, - }; + // const withdrawParamsSwap = { + // target: bridgeAddress, + // topic: "FundsPaidWithMessage(bytes32,address,uint256,bool,bytes)", + // abi: [ + // "event FundsPaidWithMessage (bytes32 messageHash, address forwarder, uint256 nonce, bool execFlag, bytes execData)", + // ], + // logKeys: { + // blockNumber: "blockNumber", + // txHash: "transactionHash", + // }, + // argKeys: { + // }, + // fixedEventData: { + // from: bridgeAddress, + // }, + // isDeposit: false, + // }; const depositParamsSwap = { target: bridgeAddress, @@ -103,30 +138,90 @@ const constructParams = (chain: string) => { isDeposit: true, }; - eventParams.push(depositParamsTransfer, withdrawParamsTransfer); - eventParams.push(depositParamsSwap, withdrawParamsSwap); - return async (fromBlock: number, toBlock: number) => - getTxDataFromEVMEventLogs("router", chain as Chain, fromBlock, toBlock, eventParams); + + eventParams.push(depositParamsTransfer, depositParamsSwap); + + return async (fromBlock: number, toBlock: number) => { + const eventLogData = (await getTxDataFromEVMEventLogs( + "router", + chain as Chain, + fromBlock, + toBlock, + eventParams + )) as EventData[]; + let withdrawalEventData: EventData[] = []; + const txs: Transaction[] = await getTxsBlockRangeEtherscan(chain, bridgeAddresses[chain], fromBlock, toBlock, { + includeSignatures: Object.keys(signatures), + }); + if (txs.length) { + // @todo handle internal txs as well + withdrawalEventData = txs.map((tx: any) => txnsDetailsToEventData(tx)); + } + return [...eventLogData, ...withdrawalEventData]; // @todo to be concatenated with txs + } }; const adapter: BridgeAdapter = { ethereum: constructParams("ethereum"), + polygon: constructParams("polygon"), avalanche: constructParams("avax"), bsc: constructParams("bsc"), fantom: constructParams("fantom"), - polygon: constructParams("polygon"), + arbitrum: constructParams("arbitrum"), + optimism: constructParams("optimism"), + aurora: constructParams("aurora"), linea: constructParams("linea"), scroll: constructParams("scroll"), base: constructParams("base"), - arbitrum: constructParams("arbitrum"), - aurora: constructParams("aurora"), - tron: constructParams("tron"), - "polygon zkevm": constructParams("polygonzkevm"), - "zksync era": constructParams("zksync"), - manta: constructParams("manta"), + "polygon zkevm": constructParams("polygon_zkevm"), + "zksync era": constructParams("era"), + // manta: constructParams("manta"), mantle: constructParams("mantle"), - rootstock: constructParams("rsk") + // rootstock: constructParams("rsk") }; -export default adapter; \ No newline at end of file +export default adapter; + + +// const methodId = "iRelay"; + +// converts calldata string to params using abi +const txnsDetailsToEventData = (txn: Transaction): EventData => { + const abi = assetForwarderAbi; + const methodAbi = new ethers.utils.Interface(abi); + const methodId = txn.input.slice(0, 10); + const decoded = methodAbi.decodeFunctionData(signatures[methodId], txn.input)[0]; + // console.log(decoded["amount"], decoded["recipient"]); + return { + blockNumber: Number(txn.blockNumber), + txHash: txn.hash, + from: txn.from, + isDeposit: false, + amount: decoded["amount"], + to: decoded["recipient"], + token: decoded["destToken"] + }; +} + +// const tryouts = async () => { +// console.log("tryouts"); +// const some = await getTxsBlockRangeEtherscan( +// "optimism", +// "0x8201c02d4ab2214471e8c3ad6475c8b0cd9f2d06", +// 117402264, +// 117402266, +// { +// includeSignatures: Object.keys(signatures), +// } +// ) +// console.log(some); + +// some.forEach((tx: any) => { +// txnsDetailsToEventData(tx); +// }); +// } + +// tryouts(); + + diff --git a/src/adapters/test.ts b/src/adapters/test.ts index 99481226..552ee2e6 100644 --- a/src/adapters/test.ts +++ b/src/adapters/test.ts @@ -50,6 +50,7 @@ const testAdapter = async () => { console.log(`Found ${eventLogs.length} event logs on chain ${contractsChain}.`); for (const log of eventLogs) { console.log(`[${contractsChain}] ${log.isDeposit ? "Deposit" : "Withdrawal"} ${log.txHash}`); + console.log(`From: ${log.from} To: ${log.to} `); } console.log(`${eventLogs.length} transactions found.`); const eventPromises = Promise.all( @@ -65,7 +66,7 @@ const testAdapter = async () => { } else if (!(log[key] !== null && typeof log[key] === logTypes[key])) { throw new Error( `${key} is missing, null, or wrong type in log. It is of type ${typeof log[ - key + key ]} and should be of type ${logTypes[key]}.` ); } @@ -82,8 +83,7 @@ const testAdapter = async () => { tokensForPricing = Object.keys(uniqueTokens); const llamaPrices = await getLlamaPrices(tokensForPricing, timestamp); console.log( - `Over the past ${numberOfBlocks} blocks, ${tokensForPricing.length} unique tokens were transferred and ${ - Object.keys(llamaPrices).length + `Over the past ${numberOfBlocks} blocks, ${tokensForPricing.length} unique tokens were transferred and ${Object.keys(llamaPrices).length } prices for them were found on ${chain}.` ); for (const token of tokensForPricing) { diff --git a/src/data/bridgeNetworkData.ts b/src/data/bridgeNetworkData.ts index e5221944..4fd07874 100644 --- a/src/data/bridgeNetworkData.ts +++ b/src/data/bridgeNetworkData.ts @@ -826,36 +826,35 @@ export default [ }, destinationChain: "Ethereum", }, - // { - // id: 54, - // displayName: "Nitro (by Router)", - // bridgeDbName: "router", - // iconLink: "protocols:router-protocol", - // largeTxThreshold: 10000, - // url: "https://www.routerprotocol.com/", - // chains: [ - // "Ethereum", - // "Avalanche", - // "BSC", - // "Fantom", - // "Linea", - // "Base", - // "Polygon", - // "Arbitrum", - // "Aurora", - // "Polygon zkEVM", - // "zkSync Era", - // "Manta", - // "Mantle", - // "Rootstock", - // ], - // chainMapping: { - // "zksync era": "era", - // "polygon zkevm": "polygon_zkevm", - // rootstock: "rsk", - // avalanche: "avax", - // }, - // }, + { + id: 54, + displayName: "Nitro (by Router Protocol)", + bridgeDbName: "router", + iconLink: "protocols:nitro", + url: "https://www.routerprotocol.com/", + largeTxThreshold: 10000, + chains: [ + "Ethereum", + "Arbitrum", + "Optimism", + "Base", + "Polygon", + "Linea", + // "Blast", + // "Arbitrum Nova", + "Scroll", + "zkSync Era", + // "Manta", + "Mantle", + // "Rootstock", + "Scroll" + ], + chainMapping: { + "arbitrum nova": "arbitrum_nova", + "zksync era": "era", + "polygon zkevm": "polygon_zkevm", + }, + }, { id: 55, displayName: "Fuse Bridge", @@ -943,4 +942,4 @@ export default [ avalanche: "avax", }, }, -] as BridgeNetwork[]; +] as BridgeNetwork[]; \ No newline at end of file diff --git a/src/helpers/blockscout.ts b/src/helpers/blockscout.ts new file mode 100644 index 00000000..dd09b753 --- /dev/null +++ b/src/helpers/blockscout.ts @@ -0,0 +1,7 @@ +const axios = require("axios"); + +const endpoints = { + manta: "https://pacific-explorer.manta.network/api/v2", + // mantle: "https://pacific-explorer.manta.network/api/v2", + rootstock: "", +} as { [chain: string]: string }; \ No newline at end of file diff --git a/src/helpers/etherscan.ts b/src/helpers/etherscan.ts index 05a56b57..a5f1c214 100644 --- a/src/helpers/etherscan.ts +++ b/src/helpers/etherscan.ts @@ -1,5 +1,6 @@ import { FunctionSignatureFilter } from "./bridgeAdapter.type"; const axios = require("axios"); +const retry = require("async-retry"); const endpoints = { ethereum: "https://api.etherscan.io", @@ -11,6 +12,8 @@ const endpoints = { optimism: "https://api-optimistic.etherscan.io", aurora: "https://explorer.mainnet.aurora.dev/api", celo: "https://api.celoscan.io", + "zksync era": "https://block-explorer-api.mainnet.zksync.io/api", + mantle: "https://explorer.mantle.xyz/api", base: "https://api.basescan.org", linea: "https://api.lineascan.build", scroll: "https://api.scrollscan.com", @@ -49,23 +52,32 @@ export const getTxsBlockRangeEtherscan = async ( const endpoint = endpoints[chain]; const apiKey = apiKeys[chain]; let res; - if (chain === "aurora") { + if (!apiKey) { res = ( - await axios.get( - `${endpoint}?module=account&action=txlist&address=${address}&startblock=${startBlock}&endblock=${endBlock}` + await retry( + () => + axios.get( + `${endpoint}?module=account&action=txlist&address=${address}&startblock=${startBlock}&endblock=${endBlock}` + ), + { factor: 1, retries: 3 } ) ).data as any; } else { res = ( - await axios.get( - `${endpoint}/api?module=account&action=txlist&address=${address}&startblock=${startBlock}&endblock=${endBlock}&apikey=${apiKey}` + await retry( + () => + axios.get( + `${endpoint}/api?module=account&action=txlist&address=${address}&startblock=${startBlock}&endblock=${endBlock}&apikey=${apiKey}` + ), + { factor: 1, retries: 3 } ) ).data as any; } if (res.message === "OK") { const filteredResults = res.result.filter((tx: any) => { if (functionSignatureFilter) { - const signature = tx.input.slice(0, 8); + const signature = tx.input.slice(0, 10); // 0x + 4 bytes of method id @todo bug to be reported + // alternatively, we can use the method signature like const signature = tx.methodId; if ( functionSignatureFilter.includeSignatures && !functionSignatureFilter.includeSignatures.includes(signature)