Skip to content

Commit 2a0cd59

Browse files
authored
✨ V1.1.0 (#12)
1 parent a18dbb4 commit 2a0cd59

10 files changed

Lines changed: 347 additions & 218 deletions

.gas-snapshot

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
MulticallerTest:testMulticallerForwardsMessageValue() (gas: 2450761)
2-
MulticallerTest:testMulticallerGetNames() (gas: 2334984)
3-
MulticallerTest:testMulticallerReentrancyGuard() (gas: 2111963)
4-
MulticallerTest:testMulticallerReturnDataIsProperlyEncoded() (gas: 2290123)
5-
MulticallerTest:testMulticallerReturnDataIsProperlyEncoded(string,string,uint256) (runs: 256, μ: 2448241, ~: 2454984)
6-
MulticallerTest:testMulticallerReturnDataIsProperlyEncoded(uint256,uint256,uint256,uint256) (runs: 256, μ: 2290225, ~: 2290225)
7-
MulticallerTest:testMulticallerRevertWithCustomError() (gas: 2120768)
8-
MulticallerTest:testMulticallerRevertWithMessage() (gas: 2126144)
9-
MulticallerTest:testMulticallerRevertWithMessage(string) (runs: 256, μ: 2127399, ~: 2127589)
10-
MulticallerTest:testMulticallerRevertWithNothing() (gas: 2120453)
11-
MulticallerTest:testMulticallerSenderDoesNotRevertWithoutMulticallerDeployed() (gas: 3352)
12-
MulticallerTest:testMulticallerTargetGetMulticallerSender() (gas: 2133323)
13-
MulticallerTest:testMulticallerWithNoData() (gas: 2101526)
14-
MulticallerTest:test__codesize() (gas: 23211)
1+
MulticallerTest:testMulticallerForwardsMessageValue() (gas: 2289495)
2+
MulticallerTest:testMulticallerGetNames() (gas: 2174099)
3+
MulticallerTest:testMulticallerReentrancyGuard() (gas: 1946480)
4+
MulticallerTest:testMulticallerReturnDataIsProperlyEncoded() (gas: 2129174)
5+
MulticallerTest:testMulticallerReturnDataIsProperlyEncoded(string,string,uint256) (runs: 256, μ: 2288240, ~: 2293927)
6+
MulticallerTest:testMulticallerReturnDataIsProperlyEncoded(uint256,uint256,uint256,uint256) (runs: 256, μ: 2129276, ~: 2129276)
7+
MulticallerTest:testMulticallerRevertWithCustomError() (gas: 1959779)
8+
MulticallerTest:testMulticallerRevertWithMessage() (gas: 1965111)
9+
MulticallerTest:testMulticallerRevertWithMessage(string) (runs: 256, μ: 1966366, ~: 1966556)
10+
MulticallerTest:testMulticallerRevertWithNothing() (gas: 1959421)
11+
MulticallerTest:testMulticallerSenderDoesNotRevertWithoutMulticallerDeployed() (gas: 3395)
12+
MulticallerTest:testMulticallerTargetGetMulticallerSender() (gas: 1950399)
13+
MulticallerTest:testMulticallerWithNoData() (gas: 1940500)
14+
MulticallerTest:test__codesize() (gas: 23110)
1515
TestPlus:test__codesize() (gas: 1102)

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,5 @@ lcov.info
2828

2929
# Build files for CREATE2 deployments
3030
/multicaller
31+
/multicaller_with_sender
3132
.tmp

README.md

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@
66

77
Efficiently call multiple contracts in a single transaction.
88

9-
Allows for optional "forwarding" of `msg.sender` to the contracts called.
9+
Enables "forwarding" of `msg.sender` to the contracts called.
1010

1111
## Deployments
1212

13-
| Chain | Multicaller |
14-
|---|---|
15-
| Ethereum | [`0x00000000000015bF55A34241Bbf73Ec4f4b080B2`](https://etherscan.io/address/0x00000000000015bF55A34241Bbf73Ec4f4b080B2) |
16-
| Goerli | [`0x00000000000015bF55A34241Bbf73Ec4f4b080B2`](https://goerli.etherscan.io/address/0x00000000000015bF55A34241Bbf73Ec4f4b080B2) |
17-
| Sepolia | [`0x00000000000015bF55A34241Bbf73Ec4f4b080B2`](https://sepolia.etherscan.io/address/0x00000000000015bF55A34241Bbf73Ec4f4b080B2) |
18-
| Polygon | [`0x00000000000015bF55A34241Bbf73Ec4f4b080B2`](https://polygonscan.com/address/0x00000000000015bF55A34241Bbf73Ec4f4b080B2) |
19-
| Mumbai | [`0x00000000000015bF55A34241Bbf73Ec4f4b080B2`](https://mumbai.polygonscan.com/address/0x00000000000015bF55A34241Bbf73Ec4f4b080B2) |
20-
| Optimism | [`0x00000000000015bF55A34241Bbf73Ec4f4b080B2`](https://optimistic.etherscan.io/address/0x00000000000015bF55A34241Bbf73Ec4f4b080B2) |
21-
| Arbitrum | [`0x00000000000015bF55A34241Bbf73Ec4f4b080B2`](https://arbiscan.io/address/0x00000000000015bF55A34241Bbf73Ec4f4b080B2) |
13+
| Chain | Multicaller | MulticallerWithSender |
14+
|---|---|---|
15+
| Ethereum | [`0x0000000000Fb21e1322c03884Aa754002339F983`](https://etherscan.io/address/0x0000000000Fb21e1322c03884Aa754002339F983) | [`0x0000000000D593850Ac7C4ff4D944DD8081abdB1`](https://etherscan.io/address/0x0000000000D593850Ac7C4ff4D944DD8081abdB1) |
16+
| Goerli | [`0x0000000000Fb21e1322c03884Aa754002339F983`](https://goerli.etherscan.io/address/0x0000000000Fb21e1322c03884Aa754002339F983) | [`0x0000000000D593850Ac7C4ff4D944DD8081abdB1`](https://goerli.etherscan.io/address/0x0000000000D593850Ac7C4ff4D944DD8081abdB1) |
17+
| Sepolia | [`0x0000000000Fb21e1322c03884Aa754002339F983`](https://sepolia.etherscan.io/address/0x0000000000Fb21e1322c03884Aa754002339F983) | [`0x0000000000D593850Ac7C4ff4D944DD8081abdB1`](https://sepolia.etherscan.io/address/0x0000000000D593850Ac7C4ff4D944DD8081abdB1) |
18+
| Polygon | [`0x0000000000Fb21e1322c03884Aa754002339F983`](https://polygonscan.com/address/0x0000000000Fb21e1322c03884Aa754002339F983) | [`0x0000000000D593850Ac7C4ff4D944DD8081abdB1`](https://polygonscan.com/address/0x0000000000D593850Ac7C4ff4D944DD8081abdB1) |
19+
| Mumbai | [`0x0000000000Fb21e1322c03884Aa754002339F983`](https://mumbai.polygonscan.com/address/0x0000000000Fb21e1322c03884Aa754002339F983) | [`0x0000000000D593850Ac7C4ff4D944DD8081abdB1`](https://mumbai.polygonscan.com/address/0x0000000000D593850Ac7C4ff4D944DD8081abdB1) |
20+
| Optimism | [`0x0000000000Fb21e1322c03884Aa754002339F983`](https://optimistic.etherscan.io/address/0x0000000000Fb21e1322c03884Aa754002339F983) | [`0x0000000000D593850Ac7C4ff4D944DD8081abdB1`](https://optimistic.etherscan.io/address/0x0000000000D593850Ac7C4ff4D944DD8081abdB1) |
21+
| Arbitrum | [`0x0000000000Fb21e1322c03884Aa754002339F983`](https://arbiscan.io/address/0x0000000000Fb21e1322c03884Aa754002339F983) | [`0x0000000000D593850Ac7C4ff4D944DD8081abdB1`](https://arbiscan.io/address/0x0000000000D593850Ac7C4ff4D944DD8081abdB1) |
2222

2323
Please open an issue if you need help to deploy to an EVM chain of your choice.
2424

@@ -27,12 +27,13 @@ Please open an issue if you need help to deploy to an EVM chain of your choice.
2727
```ml
2828
src
2929
├─ Multicaller.sol — "The multicaller contract"
30-
└─ MulticallerReader.sol — "Library to read the `msg.sender` of the multicaller contract"
30+
├─ MulticallerWithSender.sol — "The multicaller with sender contract"
31+
└─ LibMulticaller.sol — "Library to read the multicaller with sender contract"
3132
```
3233

3334
## Installation
3435

35-
You can use the [`src/MulticallerReader.sol`](./src/MulticallerReader.sol) library in your contracts to query the Multicaller efficiently.
36+
You can use the [`src/LibMulticaller.sol`](./src/LibMulticaller.sol) library in your contracts to query the multicaller with sender contract efficiently.
3637

3738
To install with [**Foundry**](https://github.com/gakonst/foundry):
3839

@@ -61,6 +62,8 @@ Aggregates multiple calls in a single transaction.
6162

6263
The `msg.value` will be forwarded to the last call.
6364

65+
### MulticallerWithSender
66+
6467
#### `aggregateWithSender`
6568
```solidity
6669
function aggregateWithSender(address[] calldata targets, bytes[] calldata data)
@@ -84,21 +87,21 @@ Returns the address that called `aggregateWithSender` on the contract.
8487

8588
The value is always the zero address outside a transaction.
8689

87-
### MulticallerReader
90+
### LibMulticaller
8891

89-
Library to read the `msg.sender` of the multicaller contract.
92+
Library to read the multicaller with sender contract.
9093

9194
#### `multicallerSender`
9295
```solidity
9396
function multicallerSender() internal view returns (address)
9497
```
95-
Returns the address that called `aggregateWithSender` on the multicaller.
98+
Returns the address that called `aggregateWithSender` on the multicaller with sender contract.
9699

97100
#### `sender`
98101
```solidity
99102
function sender() internal view returns (address result)
100103
```
101-
Returns the address that called `aggregateWithSender` on the multicaller, if `msg.sender` is the multicaller.
104+
Returns the address that called `aggregateWithSender` on the multicaller with sender contract, if `msg.sender` is the multicaller with sender contract.
102105

103106
Otherwise, returns `msg.sender`.
104107

@@ -114,7 +117,7 @@ The contracts are designed with a priority on efficiency and minimalism.
114117

115118
For the following, the contracts called must read the `msg.sender` from the multicaller contract.
116119

117-
The `MulticallerReader` library can be used for efficient reading.
120+
The `LibMulticaller` library can be used for efficient reading.
118121

119122
**Example use cases:**
120123

build_multicaller.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,6 @@ fs.writeFileSync(
5656
node .tmp/generate_initcodehash.js;
5757

5858
rm .tmp/*.sol .tmp/*.js > /dev/null 2>&1;
59+
60+
cat multicaller/initcodehash.txt; echo;
61+
cat multicaller/initcode.txt; echo;

build_multicaller_with_sender.sh

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
mkdir .tmp > /dev/null 2>&1;
2+
3+
forge fmt;
4+
5+
cp src/MulticallerWithSender.sol .tmp;
6+
7+
echo 'const fs = require("fs"), rfs = s => fs.readFileSync(s, { encoding: "utf8", flag: "r" });
8+
const p = ".tmp/MulticallerWithSender.sol";
9+
fs.writeFileSync(
10+
p,
11+
rfs(p).replace(/import\s*?\"\.\/utils/, "import \".")
12+
)' > .tmp/replace_imports.js;
13+
node .tmp/replace_imports.js;
14+
15+
rm .tmp/foundry.toml > /dev/null 2>&1;
16+
17+
forge build --out="out" --root=".tmp" --contracts="." --via-ir --optimize --optimizer-runs=1000000 --use=0.8.18;
18+
19+
mkdir multicaller_with_sender > /dev/null 2>&1;
20+
21+
echo 'const fs = require("fs"), rfs = s => fs.readFileSync(s, { encoding: "utf8", flag: "r" });
22+
fs.writeFileSync(
23+
"multicaller_with_sender/initcode.txt",
24+
JSON.parse(rfs(".tmp/out/MulticallerWithSender.sol/MulticallerWithSender.json"))["bytecode"]["object"].slice(2)
25+
)' > .tmp/extract_initcode.js;
26+
node .tmp/extract_initcode.js;
27+
28+
echo 'const fs = require("fs"), rfs = s => fs.readFileSync(s, { encoding: "utf8", flag: "r" });
29+
fs.writeFileSync(
30+
"multicaller_with_sender/input.json",
31+
JSON.stringify({
32+
"language": "Solidity",
33+
"sources": {
34+
"MulticallerWithSender.sol": {
35+
"content": rfs(".tmp/MulticallerWithSender.sol")
36+
}
37+
},
38+
"settings": {
39+
"optimizer": { "enabled": true, "runs": 1000000 },
40+
"viaIR": true,
41+
"outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }
42+
}
43+
})
44+
)' > .tmp/generate_input_json.js;
45+
node .tmp/generate_input_json.js;
46+
47+
echo '{ "devDependencies": { "@ethersproject/keccak256": "5.7.0" } }' > .tmp/package.json;
48+
49+
if [ ! -f .tmp/package-lock.json ]; then cd .tmp; npm install; cd ..; fi
50+
51+
echo 'const fs = require("fs"), rfs = s => fs.readFileSync(s, { encoding: "utf8", flag: "r" });
52+
fs.writeFileSync(
53+
"multicaller_with_sender/initcodehash.txt",
54+
require("@ethersproject/keccak256").keccak256("0x" + rfs("multicaller_with_sender/initcode.txt"))
55+
)' > .tmp/generate_initcodehash.js;
56+
node .tmp/generate_initcodehash.js;
57+
58+
rm .tmp/*.sol .tmp/*.js > /dev/null 2>&1;
59+
60+
cat multicaller_with_sender/initcodehash.txt; echo;
61+
cat multicaller_with_sender/initcode.txt; echo;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "multicaller",
33
"license": "MIT",
4-
"version": "1.0.2",
4+
"version": "1.1.0",
55
"description": "Efficient multicaller contract",
66
"files": [
77
"src/**/*.sol"
Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,31 @@
22
pragma solidity ^0.8.4;
33

44
/**
5-
* @title MulticallerReader
5+
* @title LibMulticaller
66
* @author vectorized.eth
7-
* @notice Library to read the `msg.sender` of the multicaller contract.
7+
* @notice Library to read the `msg.sender` of the multicaller with sender contract.
88
*/
9-
library MulticallerReader {
9+
library LibMulticaller {
1010
/**
1111
* @dev The address of the multicaller contract.
1212
*/
13-
address internal constant MULTICALLER = 0x00000000000015bF55A34241Bbf73Ec4f4b080B2;
13+
address internal constant MULTICALLER = 0x0000000000Fb21e1322c03884Aa754002339F983;
1414

1515
/**
16-
* @dev Returns the caller of `aggregateWithSender` on the multicaller.
16+
* @dev The address of the multicaller with sender contract.
17+
*/
18+
address internal constant MULTICALLER_WITH_SENDER = 0x0000000000D593850Ac7C4ff4D944DD8081abdB1;
19+
20+
/**
21+
* @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`.
1722
*/
1823
function multicallerSender() internal view returns (address result) {
1924
/// @solidity memory-safe-assembly
2025
assembly {
2126
if iszero(
2227
staticcall(
2328
gas(), // Remaining gas.
24-
MULTICALLER, // The multicaller.
29+
MULTICALLER_WITH_SENDER, // The multicaller.
2530
0x00, // Start of calldata in memory.
2631
0x00, // Length of calldata.
2732
0x00, // Start of returndata in memory.
@@ -34,19 +39,19 @@ library MulticallerReader {
3439
}
3540

3641
/**
37-
* @dev Returns the caller of `aggregateWithSender` on the multicaller,
38-
* if the current context's `msg.sender` is the multicaller.
42+
* @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`,
43+
* if the current context's `msg.sender` is `MULTICALLER_WITH_SENDER`.
3944
* Otherwise, returns `msg.sender`.
4045
*/
4146
function sender() internal view returns (address result) {
4247
/// @solidity memory-safe-assembly
4348
assembly {
4449
result := caller()
45-
if eq(result, MULTICALLER) {
50+
if eq(result, MULTICALLER_WITH_SENDER) {
4651
if iszero(
4752
staticcall(
4853
gas(), // Remaining gas.
49-
MULTICALLER, // The multicaller.
54+
MULTICALLER_WITH_SENDER, // The multicaller with sender.
5055
0x00, // Start of calldata in memory.
5156
0x00, // Length of calldata.
5257
0x00, // Start of returndata in memory.

0 commit comments

Comments
 (0)