|
| 1 | +import { |
| 2 | + MapLevel, |
| 3 | + Chain, |
| 4 | + constMap, |
| 5 | + Network, |
| 6 | +} from '@wormhole-foundation/sdk-connect'; |
| 7 | +import { Contract, TransactionRequest, ZeroHash } from 'ethers'; |
| 8 | + |
| 9 | +const bundler3Contracts = [ |
| 10 | + ['Mainnet', [['Polygon', '0x2d9C3A9E67c966C711208cc78b34fB9E9f8db589']]], |
| 11 | +] as const satisfies MapLevel<Network, MapLevel<Chain, string>>; |
| 12 | + |
| 13 | +export const bundler3Contract = constMap(bundler3Contracts); |
| 14 | + |
| 15 | +export interface Call { |
| 16 | + to: string; |
| 17 | + data: string; |
| 18 | + value: bigint; |
| 19 | + skipRevert: boolean; |
| 20 | + callbackHash: string; // bytes32 |
| 21 | +} |
| 22 | + |
| 23 | +/** |
| 24 | + * Populates a transaction request with a multicall to the bundler3 contract |
| 25 | + * @param calls - Array of calls to be made in the multicall |
| 26 | + * @param bundler3Address - Address of the bundler3 contract |
| 27 | + * @returns Promise<TransactionRequest> |
| 28 | + * |
| 29 | + * See: https://docs.morpho.org/bundlers/tutorials/bundler3-solidity |
| 30 | + */ |
| 31 | +export async function populateMulticallTx( |
| 32 | + calls: Call[], |
| 33 | + bundler3Address: string, |
| 34 | +): Promise<TransactionRequest> { |
| 35 | + if (calls.length === 0) { |
| 36 | + throw new Error('No transactions provided'); |
| 37 | + } |
| 38 | + |
| 39 | + if (!bundler3Address) { |
| 40 | + throw new Error('bundler3 address required'); |
| 41 | + } |
| 42 | + |
| 43 | + const bundler3 = new Contract(bundler3Address, [ |
| 44 | + 'function multicall((address to, bytes data, uint256 value, bool skipRevert, bytes32 callbackHash)[]) external payable', |
| 45 | + ]); |
| 46 | + |
| 47 | + const tx = await bundler3.getFunction('multicall').populateTransaction(calls); |
| 48 | + |
| 49 | + tx.value = calls.reduce((acc, tx) => acc + tx.value, 0n); |
| 50 | + |
| 51 | + return tx; |
| 52 | +} |
| 53 | + |
| 54 | +export function txReqToCall( |
| 55 | + tx: TransactionRequest, |
| 56 | + skipRevert = false, |
| 57 | + callbackHash = ZeroHash, |
| 58 | +): Call { |
| 59 | + if (!tx.to) throw new Error('Invalid transaction: to required'); |
| 60 | + |
| 61 | + if (typeof tx.to !== 'string') |
| 62 | + throw new Error('Invalid transaction: to must be a string'); |
| 63 | + |
| 64 | + if (!tx.data) throw new Error('Invalid transaction: data required'); |
| 65 | + |
| 66 | + return { |
| 67 | + to: tx.to, |
| 68 | + data: tx.data, |
| 69 | + value: BigInt(tx.value ?? 0n), |
| 70 | + skipRevert, |
| 71 | + callbackHash, |
| 72 | + }; |
| 73 | +} |
0 commit comments