Interacting with the Blockchain
Accessing Block Information
The Chain
object, available as chain
, uses list-like syntax to provide access to block information:
>>> chain
<Chain object (chainid=1, height=12965000)>
>>> chain[12965000]
AttributeDict({
'baseFeePerGas': 1000000000,
'difficulty': 7742494561645080,
'extraData': HexBytes('0x68747470733a2f2f7777772e6b7279707465782e6f7267'),
'gasLimit': 30029122,
'gasUsed': 30025257,
'hash': HexBytes('0x9b83c12c69edb74f6c8dd5d052765c1adf940e320bd1291696e6fa07829eee71'),
'logsBloom': HexBytes('0x24e74ad77d9a2b27bdb8f6d6f7f1cffdd8cfb47fdebd433f011f7dfcfbb7db638fadd5ff66ed134ede2879ce61149797fbcdf7b74f6b7de153ec61bdaffeeb7b59c3ed771a2fe9eaed8ac70e335e63ff2bfe239eaff8f94ca642fdf7ee5537965be99a440f53d2ce057dbf9932be9a7b9a82ffdffe4eeee1a66c4cfb99fe4540fbff936f97dde9f6bfd9f8cefda2fc174d23dfdb7d6f7dfef5f754fe6a7eec92efdbff779b5feff3beafebd7fd6e973afebe4f5d86f3aafb1f73bf1e1d0cdd796d89827edeffe8fb6ae6d7bf639ec5f5ff4c32f31f6b525b676c7cdf5e5c75bfd5b7bd1928b6f43aac7fa0f6336576e5f7b7dfb9e8ebbe6f6efe2f9dfe8b3f56'),
'miner': '0x7777788200B672A42421017F65EDE4Fc759564C8',
'mixHash': HexBytes('0x9620b46a81a4795cf4449d48e3270419f58b09293a5421205f88179b563f815a'),
'nonce': HexBytes('0xb223da049adf2216'),
'number': 12965000,
'parentHash': HexBytes('0x3de6bb3849a138e6ab0b83a3a00dc7433f1e83f7fd488e4bba78f2fe2631a633'),
'receiptsRoot': HexBytes('0x8a8865cd785e2e9dfce7da83aca010b10b9af2abbd367114b236f149534c821d'),
'sha3Uncles': HexBytes('0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347'),
'size': 137049,
'stateRoot': HexBytes('0x41cf6e8e60fd087d2b00360dc29e5bfb21959bce1f4c242fd1ad7c4da968eb87'),
'timestamp': 1628166822,
'totalDifficulty': 28494409340649014490153,
'transactions': [
...
],
'transactionsRoot': HexBytes('0xdfcb68d3a3c41096f4a77569db7956e0a0e750fad185948e54789ea0e51779cb'),
'uncles': []
})
>>> web3.eth.block_number
12965000
>>> len(chain)
12965001 # always +1 to the current block number, because the first block is zero
>>> chain[0] == web3.eth.get_block(0)
True
# for negative index values, the block returned is relative to the most recently mined block
>>> chain[-1] == web3.eth.get_block('latest')
True
Accessing Transaction Data
Local Transaction History
The TxHistory
container, available as history
, holds all the transactions that have been broadcasted during the Brownie session. You can use it to access TransactionReceipt
objects if you did not assign them to a variable when making the call.
>>> history
[
<Transaction object '0xe803698b0ade1598c594b2c73ad6a656560a4a4292cc7211b53ffda4a1dbfbe8'>,
<Transaction object '0xa7616a96ef571f1791586f570017b37f4db9decb1a5f7888299a035653e8b44b'>
]
You can use history.filter
to filter for specific transactions, either with key-value pairs or a lambda function:
>>> history.filter(sender=accounts[0], value="1 ether")
[<Transaction object '0xe803698b0ade1598c594b2c73ad6a656560a4a4292cc7211b53ffda4a1dbfbe8'>]
>>> history.filter(key=lambda k: k.nonce < 2)
[<Transaction '0x03569ee152b04ba5b55c2bf05f99f7ec153db715acfe0c1600f144ded58f31fe'>, <Transaction '0x42193c0ff7007c6e2a5e5572a3c6b5706cd133d21e30e5826add3d971134504c'>]
Other Transactions
Use chain.get_transaction
to get a TransactionReceipt
object for any transaction:
>>> chain.get_transaction('0xf598d43ef34a48478f3bb0ad969c6735f416902c4eb1eb18ebebe0fca786105e')
<Transaction '0xf598d43ef34a48478f3bb0ad969c6735f416902c4eb1eb18ebebe0fca786105e'>
This also works for pending transactions. When the transaction has not yet confirmed, the transaction hash is displayed in yellow within the console.
Manipulating the Development Chain
Brownie is designed to use ganache-cli as a local development environment. Functionality such as mining, snapshotting and time travel is accessible via the Chain
object.
Mining New Blocks
Ganache’s default behavior is to mine a new block each time you broadcast a transaction. You can mine empty blocks with the chain.mine
method:
>>> web3.eth.block_number
0
>>> chain.mine(50)
50
>>> web3.eth.block_number
50
Time Travel
You can call chain.time
to view the current epoch time:
>>> chain.time()
1500000000
To fast forward the clock, call chain.sleep
.
>>> chain.sleep(31337)
>>> chain.time()
1500031337
Note that sleeping does not mine a new block. Contract view functions that rely on block.timestamp
will be unaffected until you perform a transaction or call chain.mine
.
Snapshots
Use chain.snapshot
to take a snapshot of the current state of the blockchain:
>>> chain.snapshot()
>>> accounts[0].balance()
100000000000000000000
>>> accounts[0].transfer(accounts[1], "10 ether")
Transaction sent: 0xd5d3b40eb298dfc48721807935eda48d03916a3f48b51f20bcded372113e1dca
Transaction confirmed - block: 5 gas used: 21000 (100.00%)
<Transaction object '0xd5d3b40eb298dfc48721807935eda48d03916a3f48b51f20bcded372113e1dca'>
You can then return to this state later using chain.revert
:
>>> accounts[0].balance()
89999580000000000000
>>> chain.revert()
4
>>> accounts[0].balance()
100000000000000000000
Reverting does not consume the snapshot; you can return to the same snapshot as many times as needed. However, if you take a new snapshot the previous one is no longer accessible.
To return to the genesis state, use chain.reset
.
>>> web3.eth.block_number
6
>>> chain.reset()
>>> web3.eth.block_number
0
Undo / Redo
Along with snapshotting, you can use chain.undo
and chain.redo
to move backward and forward through recent transactions. This is especially useful during interactive test debugging.
>>> accounts[0].transfer(accounts[1], "1 ether")
Transaction sent: 0x8c166b66b356ad7f5c58337973b89950f03105cdae896ac66f16cdd4fc395d05
Gas price: 0.0 gwei Gas limit: 6721975
Transaction confirmed - Block: 1 Gas used: 21000 (0.31%)
<Transaction '0x8c166b66b356ad7f5c58337973b89950f03105cdae896ac66f16cdd4fc395d05'>
>>> chain.undo()
0
>>> chain.redo()
Transaction sent: 0x8c166b66b356ad7f5c58337973b89950f03105cdae896ac66f16cdd4fc395d05
Gas price: 0.0 gwei Gas limit: 6721975
Transaction confirmed - Block: 1 Gas used: 21000 (0.31%)
Note that chain.snapshot
and chain.revert
clear the undo buffer.