Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
30211b7e
Commit
30211b7e
authored
Apr 03, 2023
by
James Kim
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
install Multicall3 using forge install
parent
0fd4ba77
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
46 additions
and
268 deletions
+46
-268
.gitmodules
.gitmodules
+5
-0
.gitmodules
packages/contracts-periphery/.gitmodules
+0
-0
MulticallContractCompiler.t.sol
...y/contracts/foundry-tests/MulticallContractCompiler.t.sol
+11
-0
Optimist.t.sol
...ontracts-periphery/contracts/foundry-tests/Optimist.t.sol
+25
-7
ExternalContractCompiler.sol
...ry/contracts/testing/helpers/ExternalContractCompiler.sol
+1
-0
Multicall3.sol
...tracts-periphery/contracts/testing/helpers/Multicall3.sol
+0
-261
foundry.toml
packages/contracts-periphery/foundry.toml
+4
-0
No files found.
.gitmodules
View file @
30211b7e
[submodule "tests"]
path = l2geth/tests/testdata
url = https://github.com/ethereum/tests
[submodule "packages/contracts-periphery/lib/multicall"]
path = packages/contracts-periphery/lib/multicall
url = https://github.com/mds1/multicall
[submodule "lib/multicall"]
branch = v3.1.0
packages/contracts-periphery/.gitmodules
0 → 100644
View file @
30211b7e
packages/contracts-periphery/contracts/foundry-tests/MulticallContractCompiler.t.sol
0 → 100644
View file @
30211b7e
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Multicall3 } from "multicall/src/Multicall3.sol";
/**
* Just exists so we can compile this contract.
*/
contract MulticallContractCompiler {
}
packages/contracts-periphery/contracts/foundry-tests/Optimist.t.sol
View file @
30211b7e
//SPDX-License-Identifier: MIT
pragma solidity
0.8.15
;
pragma solidity
>=0.6.2 <0.9.0
;
/* Testing utilities */
import { Test } from "forge-std/Test.sol";
...
...
@@ -8,10 +8,27 @@ import { Optimist } from "../universal/op-nft/Optimist.sol";
import { OptimistAllowlist } from "../universal/op-nft/OptimistAllowlist.sol";
import { OptimistInviter } from "../universal/op-nft/OptimistInviter.sol";
import { OptimistInviterHelper } from "../testing/helpers/OptimistInviterHelper.sol";
import { Multicall3 } from "../testing/helpers/Multicall3.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IMulticall3 {
struct Call3 {
address target;
bool allowFailure;
bytes callData;
}
struct Result {
bool success;
bytes returnData;
}
function aggregate3(Call3[] calldata calls)
external
payable
returns (Result[] memory returnData);
}
contract Optimist_Initializer is Test {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Initialized(uint8);
...
...
@@ -35,7 +52,7 @@ contract Optimist_Initializer is Test {
OptimistInviterHelper optimistInviterHelper;
// To test multicall for claiming and minting in one call
Multicall3 multicall3;
I
Multicall3 multicall3;
address internal carol_baseURIAttestor;
address internal alice_allowlistAttestor;
...
...
@@ -216,7 +233,8 @@ contract Optimist_Initializer is Test {
_optimistAllowlist: optimistAllowlist
});
multicall3 = new Multicall3();
// address test = deployCode("Multicall3.sol");
multicall3 = IMulticall3(deployCode("Multicall3.sol"));
}
}
...
...
@@ -599,10 +617,10 @@ contract OptimistTest is Optimist_Initializer {
// wait minimum commitment period
vm.warp(optimistInviter.MIN_COMMITMENT_PERIOD() + block.timestamp);
Multicall3.Call3[] memory calls = new
Multicall3.Call3[](2);
IMulticall3.Call3[] memory calls = new I
Multicall3.Call3[](2);
// First call is to claim the invite, receiving the attestation
calls[0] = Multicall3.Call3({
calls[0] =
I
Multicall3.Call3({
target: address(optimistInviter),
callData: abi.encodeWithSelector(
optimistInviter.claimInvite.selector,
...
...
@@ -614,7 +632,7 @@ contract OptimistTest is Optimist_Initializer {
});
// Second call is to mint the Optimist NFT
calls[1] = Multicall3.Call3({
calls[1] =
I
Multicall3.Call3({
target: address(optimist),
callData: abi.encodeWithSelector(optimist.mint.selector, bob),
allowFailure: false
...
...
packages/contracts-periphery/contracts/testing/helpers/ExternalContractCompiler.sol
View file @
30211b7e
...
...
@@ -3,6 +3,7 @@ pragma solidity ^0.8.0;
import { ProxyAdmin } from "@eth-optimism/contracts-bedrock/contracts/universal/ProxyAdmin.sol";
import { Proxy } from "@eth-optimism/contracts-bedrock/contracts/universal/Proxy.sol";
import { Multicall3 } from "multicall/src/Multicall3.sol";
/**
* Just exists so we can compile external contracts.
...
...
packages/contracts-periphery/contracts/testing/helpers/Multicall3.sol
deleted
100644 → 0
View file @
0fd4ba77
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol
/// @title Multicall3
/// @notice Aggregate results from multiple function calls
/// @dev Multicall & Multicall2 backwards-compatible
/// @dev Aggregate methods are marked `payable` to save 24 gas per call
/// @author Michael Elliot <mike@makerdao.com>
/// @author Joshua Levine <joshua@makerdao.com>
/// @author Nick Johnson <arachnid@notdot.net>
/// @author Andreas Bigger <andreas@nascent.xyz>
/// @author Matt Solomon <matt@mattsolomon.dev>
contract Multicall3 {
struct Call {
address target;
bytes callData;
}
struct Call3 {
address target;
bool allowFailure;
bytes callData;
}
struct Call3Value {
address target;
bool allowFailure;
uint256 value;
bytes callData;
}
struct Result {
bool success;
bytes returnData;
}
/// @notice Backwards-compatible call aggregation with Multicall
/// @param calls An array of Call structs
/// @return blockNumber The block number where the calls were executed
/// @return returnData An array of bytes containing the responses
function aggregate(Call[] calldata calls)
public
payable
returns (uint256 blockNumber, bytes[] memory returnData)
{
blockNumber = block.number;
uint256 length = calls.length;
returnData = new bytes[](length);
Call calldata call;
for (uint256 i = 0; i < length; ) {
bool success;
call = calls[i];
(success, returnData[i]) = call.target.call(call.callData);
require(success, "Multicall3: call failed");
unchecked {
++i;
}
}
}
/// @notice Backwards-compatible with Multicall2
/// @notice Aggregate calls without requiring success
/// @param requireSuccess If true, require all calls to succeed
/// @param calls An array of Call structs
/// @return returnData An array of Result structs
function tryAggregate(bool requireSuccess, Call[] calldata calls)
public
payable
returns (Result[] memory returnData)
{
uint256 length = calls.length;
returnData = new Result[](length);
Call calldata call;
for (uint256 i = 0; i < length; ) {
Result memory result = returnData[i];
call = calls[i];
(result.success, result.returnData) = call.target.call(call.callData);
if (requireSuccess) require(result.success, "Multicall3: call failed");
unchecked {
++i;
}
}
}
/// @notice Backwards-compatible with Multicall2
/// @notice Aggregate calls and allow failures using tryAggregate
/// @param calls An array of Call structs
/// @return blockNumber The block number where the calls were executed
/// @return blockHash The hash of the block where the calls were executed
/// @return returnData An array of Result structs
function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)
public
payable
returns (
uint256 blockNumber,
bytes32 blockHash,
Result[] memory returnData
)
{
blockNumber = block.number;
blockHash = blockhash(block.number);
returnData = tryAggregate(requireSuccess, calls);
}
/// @notice Backwards-compatible with Multicall2
/// @notice Aggregate calls and allow failures using tryAggregate
/// @param calls An array of Call structs
/// @return blockNumber The block number where the calls were executed
/// @return blockHash The hash of the block where the calls were executed
/// @return returnData An array of Result structs
function blockAndAggregate(Call[] calldata calls)
public
payable
returns (
uint256 blockNumber,
bytes32 blockHash,
Result[] memory returnData
)
{
(blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);
}
/// @notice Aggregate calls, ensuring each returns success if required
/// @param calls An array of Call3 structs
/// @return returnData An array of Result structs
function aggregate3(Call3[] calldata calls)
public
payable
returns (Result[] memory returnData)
{
uint256 length = calls.length;
returnData = new Result[](length);
Call3 calldata calli;
for (uint256 i = 0; i < length; ) {
Result memory result = returnData[i];
calli = calls[i];
(result.success, result.returnData) = calli.target.call(calli.callData);
assembly {
// Revert if the call fails and failure is not allowed
// `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`
if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {
// set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)
// set data offset
mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
// set length of revert string
mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)
// set revert string: bytes32(abi.encodePacked("Multicall3: call failed"))
mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)
revert(0x00, 0x64)
}
}
unchecked {
++i;
}
}
}
/// @notice Aggregate calls with a msg value
/// @notice Reverts if msg.value is less than the sum of the call values
/// @param calls An array of Call3Value structs
/// @return returnData An array of Result structs
function aggregate3Value(Call3Value[] calldata calls)
public
payable
returns (Result[] memory returnData)
{
uint256 valAccumulator;
uint256 length = calls.length;
returnData = new Result[](length);
Call3Value calldata calli;
for (uint256 i = 0; i < length; ) {
Result memory result = returnData[i];
calli = calls[i];
uint256 val = calli.value;
// Humanity will be a Type V Kardashev Civilization before this overflows - andreas
// ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256
unchecked {
valAccumulator += val;
}
(result.success, result.returnData) = calli.target.call{ value: val }(calli.callData);
assembly {
// Revert if the call fails and failure is not allowed
// `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`
if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {
// set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)")))
mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)
// set data offset
mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)
// set length of revert string
mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)
// set revert string: bytes32(abi.encodePacked("Multicall3: call failed"))
mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)
revert(0x00, 0x84)
}
}
unchecked {
++i;
}
}
// Finally, make sure the msg.value = SUM(call[0...i].value)
require(msg.value == valAccumulator, "Multicall3: value mismatch");
}
/// @notice Returns the block hash for the given block number
/// @param blockNumber The block number
function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
blockHash = blockhash(blockNumber);
}
/// @notice Returns the block number
function getBlockNumber() public view returns (uint256 blockNumber) {
blockNumber = block.number;
}
/// @notice Returns the block coinbase
function getCurrentBlockCoinbase() public view returns (address coinbase) {
coinbase = block.coinbase;
}
/// @notice Returns the block difficulty
function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
difficulty = block.difficulty;
}
/// @notice Returns the block gas limit
function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
gaslimit = block.gaslimit;
}
/// @notice Returns the block timestamp
function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
timestamp = block.timestamp;
}
/// @notice Returns the (ETH) balance of a given address
function getEthBalance(address addr) public view returns (uint256 balance) {
balance = addr.balance;
}
/// @notice Returns the block hash of the last block
function getLastBlockHash() public view returns (bytes32 blockHash) {
unchecked {
blockHash = blockhash(block.number - 1);
}
}
/// @notice Gets the base fee of the given block
/// @notice Can revert if the BASEFEE opcode is not implemented by the given chain
function getBasefee() public view returns (uint256 basefee) {
basefee = block.basefee;
}
/// @notice Returns the chain id
function getChainId() public view returns (uint256 chainid) {
chainid = block.chainid;
}
}
packages/contracts-periphery/foundry.toml
View file @
30211b7e
...
...
@@ -16,9 +16,13 @@ remappings = [
'@rari-capital/solmate/=node_modules/@rari-capital/solmate'
,
'forge-std/=node_modules/forge-std/src'
,
'ds-test/=node_modules/ds-test/src'
,
'multicall/=lib/multicall'
,
'@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/'
,
'@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/'
,
'@eth-optimism/contracts-bedrock/=../../node_modules/@eth-optimism/contracts-bedrock'
,
]
# The metadata hash can be removed from the bytecode by setting "none"
bytecode_hash
=
"none"
libs
=
[
"node_modules"
,
"lib"
]
# Required to use `deployCode` to deploy the multicall contract which has incompatible version
fs_permissions
=
[
{
access
=
"read"
,
path
=
"./forge-artifacts/Multicall3.sol/Multicall3.json"
}
]
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment