web3swift
web3swift copied to clipboard
Multicall - how to encode a function and passing parameters
I am new to this and I really need help on how to make a multicall request. I will appreciate for following helps.
- How can I encode a ABI function to send to the parameters to "aggregate" ABI?
- How to pass parameters as tuple[]?
Below is multicall ABI in json:
{ "constant": true, "inputs": [ { "components": [ { "name": "target", "type": "address" }, { "name": "callData", "type": "bytes" } ], "name": "calls", "type": "tuple[]" } ], "name": "aggregate", "outputs": [ { "name": "blockNumber", "type": "uint256" }, { "name": "returnData", "type": "bytes[]" } ], "payable": false, "stateMutability": "view", "type": "function" }
Hereunder is my test code to encode the "decimals" ABI of the ERC20 and then pass to the "aggregate" but it is not luck. The readTx at the last line is returning nil for me and I wasn't able to call that transaction.
I am using latest web3swift version 2.5.0
`let anAddress = "" let ethereumAddress = EthereumAddress("anAddress")! let erc20Contract = web3.contract(Web3.Utils.erc20ABI, at: ethereumAddress, abiVersion: 2)
let decimalsFunc = erc20Contract.read("decimals") let encodedFunc = decimalsFunc.transaction.encode()
let params = [[(anAddress, encodedFunc)]] as [AnyObject] let readTx = multiCallContract.read("aggregate", parameters: params)`
this would work
let requests: [[AnyObject]] = ....compactMap { some in let contract = EthereumContract(Your_ABIString) let methodName = "methodName"
guard let data = contract?.methods[methodName]?.encodeParameters([parameterOfMethod as AnyObject]) else {
return nil
}
return ["address_for_ABI", data] as [AnyObject]
}
guard let aggregated = multiCall2Contract?.read("aggregate", parameters: [requests] as [AnyObject]) else { return }
aggregated.call....
So, web3swift is support multicall contract? I try many way but can't not call muticall.
So, web3swift is support multicall contract? I try many way but can't not call muticall.
Yes, it works well, what's the problem?
Can you post a clear example for multicall? In my case: I want to get all tokenId
over tokenOfOwnerByIndex
of NFTs. But I don't understand the parameters pass to mutiCallContract
.
For example, when I get a token ID I will create ReadOperation like this:
let ethContractAddress = EthereumAddress(contractAddress, ignoreChecksum: true)!
let enumerableContract = web3.contract(enumerableABI, at: ethContractAddress)!
let readOp = enumerableContract.createReadOperation(TokenOfOwnerByIndexOperation, parameters: [ownerWalletAddress, BigUInt(index)] as [AnyObject])!
readOp.transaction.from = EthereumAddress(ownerWalletAddress)
let response = try await readOp.callContractMethod()
How about when I get all at once.
Can you post a clear example for multicall? In my case: I want to get all
tokenId
overtokenOfOwnerByIndex
of NFTs. But I don't understand the parameters pass tomutiCallContract
.For example, when I get a token ID I will create ReadOperation like this:
let ethContractAddress = EthereumAddress(contractAddress, ignoreChecksum: true)! let enumerableContract = web3.contract(enumerableABI, at: ethContractAddress)! let readOp = enumerableContract.createReadOperation(TokenOfOwnerByIndexOperation, parameters: [ownerWalletAddress, BigUInt(index)] as [AnyObject])! readOp.transaction.from = EthereumAddress(ownerWalletAddress) let response = try await readOp.callContractMethod()
How about when I get all at once.
You need multicall smart contract in network you want, than take ABI from it, create Web3.Contract and this multicall contract to multicall-contract address in your network
Use function like "aggregate(Call[] calldata calls)" from multicall-contract with parameters like - array of calls - [Call] as [AnyObject], where Call is tupples - [AnyObject] with address of call and binary data of encoded function with parameters
Binary data get from EthereumContract (not web3.Contract) created from ABI of contracts from your network - like "enumerableABI", or another contracts
like this let contract = EthereumContract(enumerableABI) let method = contract?.methods[TokenOfOwnerByIndexOperation]?.first Call = [contractAddress, method?.encodeParameters([walletAddress as AnyObject]) ?? Data()] as [AnyObject] ......
let multicallContractAddress = EthereumAddress(multicallAddress, ignoreChecksum: true) let multicallContract = web3.contract(multicallABI, at: multicallContractAddress) let readMulticall = multicallContract?.createReadOperation("aggregate", parameters: [[Call]] as [AnyObject]) ....
let responseData = try readMulticall?.callContractMethod() let encodedResponses = responseData["returnData"] as? [Data] /// count equal calls count ....
for decode responses use method?.decodeReturnData(response) in the same order as requests
responseDictionary[i] = method[i].decodeReturnData(encodedResponses[i])
This is my implement
let web3 = try await Web3.new(urlRPC)
var methodEncode = [ABI.Element.Function]()
var multiRequest = [[AnyObject]]()
for i in 0..<numberOfCall {
let contract = try EthereumContract(enumerableABI)
let method = contract.methods[TokenOfOwnerByIndexOperation]?.first
let call = [contractAddress, method?.encodeParameters([ownerWalletAddress, BigUInt(i)] as [AnyObject]) ?? Data()] as [AnyObject]
methodEncode.append(method!)
multiRequest.append(call)
}
let multicallContractAddress = EthereumAddress(MulticallContractAddress, ignoreChecksum: true)
let multicallContract = web3.contract(multicallABI, at: multicallContractAddress)
let readMulticall = multicallContract?.createReadOperation(AggregateOperation, parameters: multiRequest as [AnyObject])
let responseData = try await readMulticall?.callContractMethod() -> still return nil
print("multiCallGetNFTIDs... responseData: \(responseData)")
But still get responseData
= nil. Have I been wrong in any step?
try one more [] in parameters of multicallContract?.createReadOperation(AggregateOperation
like this let readMulticall = multicallContract?.createReadOperation(AggregateOperation, parameters: [multiRequest] as [AnyObject])
Because Calls is array of tuples, and tuple in this representation is array too Tell me please what result you have now
Because Calls is array of tuples, and tuple in this representation is array too Tell me please what result you have now
Thank you very much. I got it. 💯
@yaroslavyaroslav
Great, thank you for your support! @6od9i I've labeled this issue as FAQ one, so other folks could reach it more easily.