Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Multicall module #2608

Merged
merged 18 commits into from
Apr 7, 2021
Merged
Prev Previous commit
Next Next commit
add documentation
martriay committed Mar 25, 2021
commit 874d7b2c0b06bf404d95a41de7b0deaf2e55a4e8
7 changes: 5 additions & 2 deletions contracts/utils/BatchCall.sol
Original file line number Diff line number Diff line change
@@ -5,10 +5,13 @@ pragma solidity ^0.8.0;
import "./Address.sol";

/*
frangio marked this conversation as resolved.
Show resolved Hide resolved
* @dev Provides a way to batch together multiple function calls in a single external call.
* @dev Provides a function to batch together multiple calls in a single external call.
*/
abstract contract BatchCall {
function batchCall(bytes[] calldata data) external returns(bytes[] memory results) {
/**
* @dev Receives and executes a batch of function calls on this contract.
*/
function batchCall(bytes[] calldata data) external returns(bytes[] memory results) {
results = new bytes[](data.length);
for (uint i = 0; i < data.length; i++) {
results[i] = Address.functionDelegateCall(address(this), data[i]);
3 changes: 3 additions & 0 deletions contracts/utils/README.adoc
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/
Miscellaneous contracts and libraries containing utility functions you can use to improve security, work with new data types, or safely use low-level primitives.

The {Address}, {Arrays} and {Strings} libraries provide more operations related to these native data types, while {SafeCast} adds ways to safely convert between the different signed and unsigned numeric types.
{BatchCall} provides a function to batch together multiple calls in a single external call.

For new data types:

@@ -92,3 +93,5 @@ Note that, in all cases, accounts simply _declare_ their interfaces, but they ar
{{Counters}}

{{Strings}}

{{BatchCall}}
40 changes: 40 additions & 0 deletions docs/modules/ROOT/pages/utilities.adoc
Original file line number Diff line number Diff line change
@@ -99,3 +99,43 @@ Want to check if an address is a contract? Use xref:api:utils.adoc#Address[`Addr

Want to keep track of some numbers that increment by 1 every time you want another one? Check out xref:api:utils.adoc#Counters[`Counters`]. This is useful for lots of things, like creating incremental identifiers, as shown on the xref:erc721.adoc[ERC721 guide].

=== BatchCall

The `BatchCall` abstract contract comes with a `batchCall` function that bundles together multiple calls in a single external call. With it, external accounts may perform atomic operations comprising several function calls.

This is not only useful for EOAs to make multiple calls in a single transaction, it's also a way to revert a previous call if a later one fails.

Consider this dummy contract:

[source,solidity]
----
// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/BatchCall.sol";
contract Box is BatchCall {
function foo() public {
...
}
function bar() public {
...
}
}
----

This is how to call the `batchCall` function using Truffle, allowing `foo` and `bar` to be called in a single transaction:
[source,javascript]
----
// scripts/foobar.js
const Box = artifacts.require('Box');
const instance = await Box.new();
await instance.batchCall([
instance.contract.methods.foo().encodeABI(),
instance.contract.methods.bar().encodeABI()
], { from: deployer });
----