Skip to content
This repository was archived by the owner on Jun 8, 2024. It is now read-only.
Open
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
},
"dependencies": {
"@ethersproject/abi": "^5.0.0",
"@ethersproject/abstract-signer": "^5.7.0",
"@ethersproject/bytes": "^5.0.0",
"@ethersproject/contracts": "^5.0.0",
"@ethersproject/providers": "^5.0.0",
Expand Down
3 changes: 1 addition & 2 deletions src/abi/multicall.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@
"type": "bytes[]"
}
],
"payable": false,
"stateMutability": "view",
"stateMutability": "nonpayable",
"type": "function"
},
{
Expand Down
6 changes: 2 additions & 4 deletions src/abi/multicall2.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@
"type": "bytes[]"
}
],
"payable": false,
"stateMutability": "view",
"stateMutability": "nonpayable",
"type": "function"
},
{
Expand Down Expand Up @@ -250,8 +249,7 @@
"type": "tuple[]"
}
],
"payable": false,
"stateMutability": "view",
"stateMutability": "nonpayable",
"type": "function"
},
{
Expand Down
6 changes: 3 additions & 3 deletions src/abi/multicall3.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"type": "bytes[]"
}
],
"stateMutability": "view",
"stateMutability": "payable",
"type": "function"
},
{
Expand Down Expand Up @@ -80,7 +80,7 @@
"type": "tuple[]"
}
],
"stateMutability": "view",
"stateMutability": "payable",
"type": "function"
},
{
Expand Down Expand Up @@ -376,7 +376,7 @@
"type": "tuple[]"
}
],
"stateMutability": "view",
"stateMutability": "payable",
"type": "function"
},
{
Expand Down
41 changes: 35 additions & 6 deletions src/call.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { JsonFragment, JsonFragmentType, Result } from '@ethersproject/abi';
import { Signer } from '@ethersproject/abstract-signer';
import { hexConcat } from '@ethersproject/bytes';
import { Contract } from '@ethersproject/contracts';
import { BaseProvider } from '@ethersproject/providers';
import { BaseProvider, TransactionReceipt } from '@ethersproject/providers';

import Abi, { Params } from './abi';
import deploylessMulticallAbi from './abi/deploylessMulticall.json';
Expand All @@ -12,9 +13,9 @@ import multicall2Abi from './abi/multicall2.json';
import multicall3Abi from './abi/multicall3.json';
import {
Multicall,
deploylessMulticallBytecode,
deploylessMulticall2Bytecode,
deploylessMulticall3Bytecode,
deploylessMulticallBytecode,
} from './multicall';
import { BlockTag } from './provider';

Expand Down Expand Up @@ -63,7 +64,7 @@ async function all<T>(
from: multicall?.address,
};
const response = contract
? await contract.aggregate(callRequests, overrides)
? await contract.callStatic.aggregate(callRequests, overrides)
: await callDeployless(provider, callRequests, block);
const callCount = calls.length;
const callResult: T[] = [];
Expand Down Expand Up @@ -99,7 +100,7 @@ async function tryAll<T>(
from: multicall2?.address,
};
const response: CallResult[] = contract
? await contract.tryAggregate(false, callRequests, overrides)
? await contract.callStatic.tryAggregate(false, callRequests, overrides)
: await callDeployless2(provider, callRequests, block);
const callCount = calls.length;
const callResult: (T | null)[] = [];
Expand All @@ -123,6 +124,32 @@ async function tryAll<T>(
return callResult;
}

async function writeTryAll<T>(
provider: BaseProvider,
multicall2: Multicall | null,
calls: Call[],
signer: Signer,
overrides?: Record<string, unknown>,
): Promise<TransactionReceipt> {
const contract = multicall2
? new Contract(multicall2.address, multicall2Abi, provider)
: null;
const callRequests = calls.map((call) => {
const callData = Abi.encode(call.name, call.inputs, call.params);
return {
target: call.contract.address,
callData,
};
});
const txn = contract
? await contract
.connect(signer)
.tryAggregate(false, callRequests, overrides)
: await callDeployless2(provider, callRequests, undefined, signer);
const receipt = await txn.wait();
return receipt;
}

async function tryEach<T>(
provider: BaseProvider,
multicall3: Multicall | null,
Expand Down Expand Up @@ -199,13 +226,15 @@ async function callDeployless2(
provider: BaseProvider,
callRequests: CallRequest[],
block?: BlockTag,
signer?: Signer,
): Promise<Result> {
const inputAbi: JsonFragment[] = deploylessMulticall2Abi;
const constructor = inputAbi.find((f) => f.type === 'constructor');
const inputs = constructor?.inputs || [];
const args = Abi.encodeConstructor(inputs, [false, callRequests]);
const data = hexConcat([deploylessMulticall2Bytecode, args]);
const callData = await provider.call(
const caller = signer ?? provider;
const callData = await caller.call(
{
data,
},
Expand Down Expand Up @@ -249,4 +278,4 @@ async function callDeployless3(
return response as CallResult[];
}

export { Call, CallResult, all, tryAll, tryEach };
export { Call, CallResult, all, tryAll, tryEach, writeTryAll };
5 changes: 1 addition & 4 deletions src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,8 @@ class Contract {
this.abi = abi;

this.functions = abi.filter((x) => x.type === 'function');
const callFunctions = this.functions.filter(
(x) => x.stateMutability === 'pure' || x.stateMutability === 'view',
);

for (const callFunction of callFunctions) {
for (const callFunction of this.functions) {
const name = callFunction.name;
if (!name) {
continue;
Expand Down
27 changes: 27 additions & 0 deletions src/provider.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { Signer } from '@ethersproject/abstract-signer';
import {
BaseProvider,
Provider as EthersProvider,
TransactionReceipt,
} from '@ethersproject/providers';

import {
Call,
all as callAll,
tryAll as callTryAll,
tryEach as callTryEach,
writeTryAll as callWriteTryAll,
} from './call';
import getEthBalance from './calls';
import {
Expand Down Expand Up @@ -109,6 +112,30 @@ class Provider {
return await callTryAll<T>(provider, multicall, calls, block);
}

async writeTryAll<T>(
calls: Call[],
signer: Signer,
overrides?: Record<string, unknown>,
): Promise<TransactionReceipt> {
if (!this.provider) {
throw Error('Provider should be initialized before use.');
}
const multicall = this.getContract('TRY_ALL');
if (!multicall) {
console.warn(
'Multicall2 contract is not available on this network, using deployless version.',
);
}
const provider = this.provider as BaseProvider;
return await callWriteTryAll<T>(
provider,
multicall,
calls,
signer,
overrides,
);
}

/**
* Aggregates multiple calls into one call.
* If any of the calls that are allowed to fail do fail,
Expand Down
Loading