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

feat: Multicall context manager #1125

Merged
merged 34 commits into from
Jul 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
9a65d49
fix: failing test get_abi for uniswap
skellet0r Jul 13, 2021
3b01aeb
feat: add Multicall2 contract
skellet0r Jun 24, 2021
ff4b90d
feat: add modified Multicall2 abi
skellet0r Jun 24, 2021
e02a802
fix: update MANIFEST.in
skellet0r Jun 24, 2021
22774a3
feat: add multicall2 addresses to network config
skellet0r Jun 24, 2021
628cafb
fix(test): update optional keys in network config
skellet0r Jun 26, 2021
159901f
feat: add wrapt and lazy-object-proxy packages
skellet0r Jun 25, 2021
c94643f
test: multicall2 context manager
skellet0r Jun 26, 2021
33240e5
feat: add multicall2 context manager
skellet0r Jun 24, 2021
6d79ab4
feat: add multicall2 to brownie namespace
skellet0r Jun 26, 2021
d72d9a1
fix: rename ctx mgr from multicall2 to multicall
skellet0r Jun 26, 2021
742ce6c
test: additional test cases
skellet0r Jun 27, 2021
4ba02d0
feat: add deploy fn and handle specifying block_identifier
skellet0r Jun 27, 2021
b21807f
test: all calls come from the same block
skellet0r Jun 27, 2021
06ae659
fix: handle all calls are queried from the same block
skellet0r Jun 27, 2021
b087a74
fix: repr of lazy results
skellet0r Jun 27, 2021
25f2675
fix: remove aliasing Multicall class
skellet0r Jun 27, 2021
51334ba
test: multicall block_number getter + setter
skellet0r Jun 28, 2021
90479aa
feat: block number getter + setter
skellet0r Jun 28, 2021
18e4480
docs: add documentation for multicall
skellet0r Jun 30, 2021
33b0d84
test: modify test to simulate multi-instance safety
skellet0r Jun 30, 2021
781536c
fix: remove replacing original code object back
skellet0r Jun 30, 2021
afa3943
chore: update CHANGELOG
skellet0r Jun 30, 2021
0192311
docs: add docstrings to Multicall class
skellet0r Jul 1, 2021
3096c30
fix: update init fn
skellet0r Jul 13, 2021
7cda178
fix: update usage
skellet0r Jul 13, 2021
222b19f
fix: namespacing
skellet0r Jul 13, 2021
b1bc173
fix: attribute setting and calls
skellet0r Jul 13, 2021
a90415e
fix(test): update tests for correct usage
skellet0r Jul 13, 2021
9da7e5d
fix: public attributes
skellet0r Jul 13, 2021
8686817
docs: update with new usage
skellet0r Jul 13, 2021
dd30cef
chore: linting
skellet0r Jul 13, 2021
e85bf9f
chore: lint
skellet0r Jul 18, 2021
9868a76
fix: remove threading import in proxy fn
skellet0r Jul 18, 2021
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add polygon network integration ([#1119](https://github.com/eth-brownie/brownie/pull/1119))
- Fixed subcalls to empty accounts not appearing in the subcalls property of TransactionReceipts ([#1106](https://github.com/eth-brownie/brownie/pull/1106))
- Add support for `POLYGONSCAN_TOKEN` env var ([#1135](https://github.com/eth-brownie/brownie/pull/1135))
- Add Multicall context manager ([#1125](https://github.com/eth-brownie/brownie/pull/1125))

### Added
- Added `LocalAccount.sign_message` method to sign `EIP712Message` objects ([#1097](https://github.com/eth-brownie/brownie/pull/1097))
Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ include requirements*.in
include requirements*.txt
include brownie/data/*.yaml
include brownie/data/interfaces/*.json
include brownie/data/contracts/*.sol

recursive-exclude * __pycache__
recursive-exclude * *.py[co]
3 changes: 3 additions & 0 deletions brownie/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
from brownie.convert import Fixed, Wei
from brownie.network import accounts, alert, chain, history, rpc, web3
from brownie.network.contract import Contract # NOQA: F401
from brownie.network import multicall as _multicall

ETH_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"

config = _CONFIG.settings
multicall = _multicall.Multicall()

__all__ = [
"Contract",
Expand All @@ -22,6 +24,7 @@
"alert",
"chain",
"history", # history is a TxHistory singleton
"multicall",
"network",
"rpc", # rpc is a Rpc singleton
"web3", # web3 is a Web3 instance
Expand Down
2 changes: 1 addition & 1 deletion brownie/_cli/networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

DEV_REQUIRED = ("id", "host", "cmd", "cmd_settings")
PROD_REQUIRED = ("id", "host", "chainid")
OPTIONAL = ("name", "explorer", "timeout")
OPTIONAL = ("name", "explorer", "timeout", "multicall2")

DEV_CMD_SETTINGS = (
"port",
Expand Down
123 changes: 123 additions & 0 deletions brownie/data/contracts/Multicall2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
pragma experimental ABIEncoderV2;

/// @title Multicall2 - Aggregate results from multiple read-only function calls
/// @author Michael Elliot <mike@makerdao.com>
/// @author Joshua Levine <joshua@makerdao.com>
/// @author Nick Johnson <arachnid@notdot.net>

contract Multicall2 {
struct Call {
address target;
bytes callData;
}
struct Result {
bool success;
bytes returnData;
}

function aggregate(Call[] memory calls)
public
returns (uint256 blockNumber, bytes[] memory returnData)
{
blockNumber = block.number;
returnData = new bytes[](calls.length);
for (uint256 i = 0; i < calls.length; i++) {
(bool success, bytes memory ret) = calls[i].target.call(
calls[i].callData
);
require(success, "Multicall aggregate: call failed");
returnData[i] = ret;
}
}

function blockAndAggregate(Call[] memory calls)
public
returns (
uint256 blockNumber,
bytes32 blockHash,
Result[] memory returnData
)
{
(blockNumber, blockHash, returnData) = tryBlockAndAggregate(
true,
calls
);
}

function getBlockHash(uint256 blockNumber)
public
view
returns (bytes32 blockHash)
{
blockHash = blockhash(blockNumber);
}

function getBlockNumber() public view returns (uint256 blockNumber) {
blockNumber = block.number;
}

function getCurrentBlockCoinbase() public view returns (address coinbase) {
coinbase = block.coinbase;
}

function getCurrentBlockDifficulty()
public
view
returns (uint256 difficulty)
{
difficulty = block.difficulty;
}

function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
gaslimit = block.gaslimit;
}

function getCurrentBlockTimestamp()
public
view
returns (uint256 timestamp)
{
timestamp = block.timestamp;
}

function getEthBalance(address addr) public view returns (uint256 balance) {
balance = addr.balance;
}

function getLastBlockHash() public view returns (bytes32 blockHash) {
blockHash = blockhash(block.number - 1);
}

function tryAggregate(bool requireSuccess, Call[] memory calls)
public
returns (Result[] memory returnData)
{
returnData = new Result[](calls.length);
for (uint256 i = 0; i < calls.length; i++) {
(bool success, bytes memory ret) = calls[i].target.call(
calls[i].callData
);

if (requireSuccess) {
require(success, "Multicall2 aggregate: call failed");
}

returnData[i] = Result(success, ret);
}
}

function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls)
public
returns (
uint256 blockNumber,
bytes32 blockHash,
Result[] memory returnData
)
{
blockNumber = block.number;
blockHash = blockhash(block.number);
returnData = tryAggregate(requireSuccess, calls);
}
}
Loading