diff --git a/scripts/socket-helpers/arb-estimate.ts b/scripts/socket-helpers/arb-estimate.ts index e8fbb5fae..ca67a480f 100644 --- a/scripts/socket-helpers/arb-estimate.ts +++ b/scripts/socket-helpers/arb-estimate.ts @@ -1,24 +1,17 @@ -require("dotenv").config(); -import { utils, BigNumber, providers } from "ethers"; +import { utils, BigNumber } from "ethers"; import { ArbGasInfo__factory } from "@arbitrum/sdk/dist/lib/abi/factories/ArbGasInfo__factory"; import { NodeInterface__factory } from "@arbitrum/sdk/dist/lib/abi/factories/NodeInterface__factory"; import { ARB_GAS_INFO, NODE_INTERFACE_ADDRESS, } from "@arbitrum/sdk/dist/lib/dataEntities/constants"; -import { defaultAbiCoder } from "ethers/lib/utils"; -import { DeploymentMode, getAddresses } from "@socket.tech/dl-core"; -import PlugABI from "@socket.tech/dl-core/artifacts/abi/IPlug.json"; -import { addresses, dstChainSlug, srcChainSlug } from "./config"; +import { TxData } from "./utils"; +import { StaticJsonRpcProvider } from "@ethersproject/providers"; -const dstChainRPC = process.env.ARBITRUM_RPC; - -export const getArbitrumGasEstimate = async ( - amount: string, - receiver: string +export const getArbitrumGasLimitEstimate = async ( + provider: StaticJsonRpcProvider, + txData: TxData ): Promise => { - const provider = new providers.StaticJsonRpcProvider(dstChainRPC); - const arbGasInfo = ArbGasInfo__factory.connect(ARB_GAS_INFO, provider); const nodeInterface = NodeInterface__factory.connect( NODE_INTERFACE_ADDRESS, @@ -26,30 +19,25 @@ export const getArbitrumGasEstimate = async ( ); // Getting the gas prices from ArbGasInfo.getPricesInWei() const gasComponents = await arbGasInfo.callStatic.getPricesInWei(); - - const payload = defaultAbiCoder.encode( - ["address", "uint256"], - [receiver, amount] - ); - const abiInterface = new utils.Interface(PlugABI); - const txData = abiInterface.encodeFunctionData("inbound", [ - srcChainSlug, - payload, - ]); - const gasEstimateComponents = await nodeInterface.callStatic.gasEstimateComponents( - addresses[dstChainSlug].USDC.connectors[srcChainSlug].FAST, + txData.to, false, - txData, - { from: getAddresses(dstChainSlug, DeploymentMode.PROD).Socket } + txData.data, + { from: txData.from } ); const l2GasUsed = gasEstimateComponents.gasEstimate.sub( gasEstimateComponents.gasEstimateForL1 ); - const L1S = 140 + utils.hexDataLength(txData); + + // Size in bytes of the calldata to post on L1 + const L1S = 140 + utils.hexDataLength(txData.data); + + // Estimated L1 gas cost const L1C = gasComponents[1].mul(L1S); + + // Extra buffer const B = L1C.div(gasComponents[5]); // G (Gas Limit) = l2GasUsed + B diff --git a/scripts/socket-helpers/config.ts b/scripts/socket-helpers/config.ts deleted file mode 100644 index 7a658a513..000000000 --- a/scripts/socket-helpers/config.ts +++ /dev/null @@ -1,35 +0,0 @@ -export const addresses = { - "10": { - USDC: { - connectors: { - "2999": { - FAST: "0x1812ff6bd726934f18159164e2927B34949B16a8", - }, - }, - }, - }, - "2999": { - USDC: { - connectors: { - "10": { - FAST: "0x7b9ed5C43E87DAFB03211651d4FA41fEa1Eb9b3D", - }, - "42161": { - FAST: "0x73019b64e31e699fFd27d54E91D686313C14191C", - }, - }, - }, - }, - "42161": { - USDC: { - connectors: { - "2999": { - FAST: "0x69Adf49285c25d9f840c577A0e3cb134caF944D3", - }, - }, - }, - }, -}; - -export const srcChainSlug = 2999; -export const dstChainSlug = 42161; diff --git a/scripts/socket-helpers/main.ts b/scripts/socket-helpers/main.ts new file mode 100644 index 000000000..9fbd54d33 --- /dev/null +++ b/scripts/socket-helpers/main.ts @@ -0,0 +1,60 @@ +require("dotenv").config(); +import { BigNumber, providers, utils } from "ethers"; +import { DeploymentMode } from "@socket.tech/dl-core"; +import PlugABI from "@socket.tech/dl-core/artifacts/abi/IPlug.json"; + +import { ChainDetails, Inputs, getPayload } from "./utils"; +import { getJsonRpcUrl } from "../constants"; +import { arbChains, arbL3Chains, getAddresses } from "../../src"; +import { getArbitrumGasLimitEstimate } from "./arb-estimate"; +import { getOpAndEthGasLimitEstimate } from "./op-n-eth-estimate"; + +export const main = async ( + chainDetails: ChainDetails, + inputs: Inputs, + withoutHook?: boolean +): Promise => { + const srcChainSlug = chainDetails.srcChainSlug; + const dstChainSlug = chainDetails.dstChainSlug; + + const provider = new providers.StaticJsonRpcProvider( + getJsonRpcUrl(dstChainSlug) + ); + const payload = await getPayload(inputs, provider, withoutHook); + + const abiInterface = new utils.Interface(PlugABI); + const data = abiInterface.encodeFunctionData("inbound", [ + srcChainSlug, + payload, + ]); + + const txData = { + from: getAddresses(dstChainSlug, DeploymentMode.PROD).Socket, + to: inputs.connectorPlug, + data, + }; + + if ( + arbChains.includes(chainDetails.dstChainSlug) || + arbL3Chains.includes(chainDetails.dstChainSlug) + ) { + return await getArbitrumGasLimitEstimate(provider, txData); + } else { + // works for opt and eth like chains + return await getOpAndEthGasLimitEstimate(provider, txData); + } +}; + +main( + { + srcChainSlug: 42161, + dstChainSlug: 1324967486, + }, + { + amount: "2000000000", + connectorPlug: "0x663dc7e91157c58079f55c1bf5ee1bdb6401ca7a", + executionData: "0x", + receiver: "0x663dc7e91157c58079f55c1bf5ee1bdb6401ca7a", + }, + false +); diff --git a/scripts/socket-helpers/op-n-eth-estimate.ts b/scripts/socket-helpers/op-n-eth-estimate.ts new file mode 100644 index 000000000..b7806187b --- /dev/null +++ b/scripts/socket-helpers/op-n-eth-estimate.ts @@ -0,0 +1,14 @@ +import { BigNumber } from "ethers"; +import { StaticJsonRpcProvider } from "@ethersproject/providers"; +import { asL2Provider } from "@eth-optimism/sdk"; +import { TxData } from "./utils"; + +// Get optimism gas limit from the SDK +export const getOpAndEthGasLimitEstimate = async ( + provider: StaticJsonRpcProvider, + txData: TxData +): Promise => { + const l2Provider = asL2Provider(provider); + const gasLimit = await l2Provider.estimateGas(txData); + return gasLimit; +}; diff --git a/scripts/socket-helpers/opt-estimate.ts b/scripts/socket-helpers/opt-estimate.ts deleted file mode 100644 index cd7c4ad37..000000000 --- a/scripts/socket-helpers/opt-estimate.ts +++ /dev/null @@ -1,35 +0,0 @@ -require("dotenv").config(); -import { BigNumber, providers, utils } from "ethers"; -import { asL2Provider } from "@eth-optimism/sdk"; -import { defaultAbiCoder } from "ethers/lib/utils"; -import PlugABI from "@socket.tech/dl-core/artifacts/abi/IPlug.json"; -import { addresses, dstChainSlug, srcChainSlug } from "./config"; -import { DeploymentMode, getAddresses } from "@socket.tech/dl-core"; - -const dstChainRPC = process.env.OPTIMISM_RPC; - -// Get optimism gas limit from the SDK -export const getOptimismGasEstimate = async ( - amount: string, - receiver: string -): Promise => { - const provider = new providers.StaticJsonRpcProvider(dstChainRPC); - const l2Provider = asL2Provider(provider); - - const payload = defaultAbiCoder.encode( - ["address", "uint256"], - [receiver, amount] - ); - const abiInterface = new utils.Interface(PlugABI); - const data = abiInterface.encodeFunctionData("inbound", [ - srcChainSlug, - payload, - ]); - - const gasLimit = await l2Provider.estimateGas({ - data, - to: addresses[dstChainSlug].USDC.connectors[srcChainSlug].FAST, - from: getAddresses(dstChainSlug, DeploymentMode.PROD).Socket, - }); - return gasLimit; -}; diff --git a/scripts/socket-helpers/utils.ts b/scripts/socket-helpers/utils.ts new file mode 100644 index 000000000..cd3cbb1b9 --- /dev/null +++ b/scripts/socket-helpers/utils.ts @@ -0,0 +1,68 @@ +import { Contract, utils } from "ethers"; +import { defaultAbiCoder } from "ethers/lib/utils"; +import { StaticJsonRpcProvider } from "@ethersproject/providers"; +import PlugABI from "@socket.tech/dl-core/artifacts/abi/IPlug.json"; +import { ChainSlug } from "../../src"; + +export type TxData = { + from: string; + to: string; + data: string; +}; + +export type Inputs = { + amount: string; + receiver: string; + executionData: string; + connectorPlug: string; +}; + +export type ChainDetails = { + srcChainSlug: ChainSlug; + dstChainSlug: ChainSlug; +}; + +export const abiInterface = new utils.Interface(PlugABI); + +const ConnectorABI = [ + { + inputs: [], + name: "getMessageId", + outputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + stateMutability: "view", + type: "function", + }, +]; + +export const getPayload = async ( + inputs: Inputs, + provider: StaticJsonRpcProvider, + withoutHook?: boolean +) => { + let payload; + if (withoutHook) { + payload = defaultAbiCoder.encode( + ["address", "uint256"], + [inputs.receiver, inputs.amount] + ); + } else { + const connectorContract = new Contract( + inputs.connectorPlug, + ConnectorABI, + provider + ); + const msgId = await connectorContract.getMessageId(); + payload = defaultAbiCoder.encode( + ["address", "uint256", "bytes32", "bytes"], + [inputs.receiver, inputs.amount, msgId, inputs.executionData] + ); + } + + return payload; +};