diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index 60dea4760a9c8116985490b66012175f5ee9350a..d76d02c7f65a53163808b90a6aada69ea0c1c833 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -47,12 +47,17 @@ import (
 var _ bind.ContractBackend = (*SimulatedBackend)(nil)
 
 var (
-	errBlockNumberUnsupported = errors.New("simulatedBackend cannot access blocks other than the latest block")
-	errGasEstimationFailed    = errors.New("gas required exceeds allowance or always failing transaction")
+	errBlockNumberUnsupported  = errors.New("simulatedBackend cannot access blocks other than the latest block")
+	errBlockDoesNotExist       = errors.New("block does not exist in blockchain")
+	errTransactionDoesNotExist = errors.New("transaction does not exist")
+	errGasEstimationFailed     = errors.New("gas required exceeds allowance or always failing transaction")
 )
 
 // SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
 // the background. Its main purpose is to allow easily testing contract bindings.
+// Simulated backend implements the following interfaces:
+// ChainReader, ChainStateReader, ContractBackend, ContractCaller, ContractFilterer, ContractTransactor,
+// DeployBackend, GasEstimator, GasPricer, LogFilterer, PendingContractCaller, TransactionReader, and TransactionSender
 type SimulatedBackend struct {
 	prependDb  ethdb.Database
 	database   ethdb.Database // In memory database to store our testing data
@@ -240,6 +245,9 @@ func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Addres
 
 // TransactionReceipt returns the receipt of a transaction.
 func (b *SimulatedBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+
 	receipt, _, _, _ := rawdb.ReadReceipt(b.database, txHash, b.config)
 	return receipt, nil
 }
@@ -263,6 +271,115 @@ func (b *SimulatedBackend) TransactionByHash(ctx context.Context, txHash common.
 	return nil, false, ethereum.NotFound
 }
 
+// BlockByHash retrieves a block based on the block hash
+func (b *SimulatedBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+
+	if hash == b.pendingBlock.Hash() {
+		return b.pendingBlock, nil
+	}
+
+	block := b.blockchain.GetBlockByHash(hash)
+	if block != nil {
+		return block, nil
+	}
+
+	return nil, errBlockDoesNotExist
+}
+
+// BlockByNumber retrieves a block from the database by number, caching it
+// (associated with its hash) if found.
+func (b *SimulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+
+	if number == nil || number.Cmp(b.pendingBlock.Number()) == 0 {
+		return b.blockchain.CurrentBlock(), nil
+	}
+
+	block := b.blockchain.GetBlockByNumber(uint64(number.Int64()))
+	if block == nil {
+		return nil, errBlockDoesNotExist
+	}
+
+	return block, nil
+}
+
+// HeaderByHash returns a block header from the current canonical chain.
+func (b *SimulatedBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+
+	if hash == b.pendingBlock.Hash() {
+		return b.pendingBlock.Header(), nil
+	}
+
+	header := b.blockchain.GetHeaderByHash(hash)
+	if header == nil {
+		return nil, errBlockDoesNotExist
+	}
+
+	return header, nil
+}
+
+// HeaderByNumber returns a block header from the current canonical chain. If number is
+// nil, the latest known header is returned.
+func (b *SimulatedBackend) HeaderByNumber(ctx context.Context, block *big.Int) (*types.Header, error) {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+
+	if block == nil || block.Cmp(b.pendingBlock.Number()) == 0 {
+		return b.blockchain.CurrentHeader(), nil
+	}
+
+	return b.blockchain.GetHeaderByNumber(uint64(block.Int64())), nil
+}
+
+// TransactionCount returns the number of transactions in a given block
+func (b *SimulatedBackend) TransactionCount(ctx context.Context, blockHash common.Hash) (uint, error) {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+
+	if blockHash == b.pendingBlock.Hash() {
+		return uint(b.pendingBlock.Transactions().Len()), nil
+	}
+
+	block := b.blockchain.GetBlockByHash(blockHash)
+	if block == nil {
+		return uint(0), errBlockDoesNotExist
+	}
+
+	return uint(block.Transactions().Len()), nil
+}
+
+// TransactionInBlock returns the transaction for a specific block at a specific index
+func (b *SimulatedBackend) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+
+	if blockHash == b.pendingBlock.Hash() {
+		transactions := b.pendingBlock.Transactions()
+		if uint(len(transactions)) < index+1 {
+			return nil, errTransactionDoesNotExist
+		}
+
+		return transactions[index], nil
+	}
+
+	block := b.blockchain.GetBlockByHash(blockHash)
+	if block == nil {
+		return nil, errBlockDoesNotExist
+	}
+
+	transactions := block.Transactions()
+	if uint(len(transactions)) < index+1 {
+		return nil, errTransactionDoesNotExist
+	}
+
+	return transactions[index], nil
+}
+
 // PendingCodeAt returns the code associated with an account in the pending state.
 func (b *SimulatedBackend) PendingCodeAt(ctx context.Context, contract common.Address) ([]byte, error) {
 	b.mu.Lock()
@@ -496,10 +613,38 @@ func (b *SimulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethere
 	}), nil
 }
 
+// SubscribeNewHead returns an event subscription for a new header
+func (b *SimulatedBackend) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
+	// subscribe to a new head
+	sink := make(chan *types.Header)
+	sub := b.events.SubscribeNewHeads(sink)
+
+	return event.NewSubscription(func(quit <-chan struct{}) error {
+		defer sub.Unsubscribe()
+		for {
+			select {
+			case head := <-sink:
+				select {
+				case ch <- head:
+				case err := <-sub.Err():
+					return err
+				case <-quit:
+					return nil
+				}
+			case err := <-sub.Err():
+				return err
+			case <-quit:
+				return nil
+			}
+		}
+	}), nil
+}
+
 // AdjustTime adds a time shift to the simulated clock.
 func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
 	b.mu.Lock()
 	defer b.mu.Unlock()
+
 	ctx := b.blockchain.WithContext(context.Background(), big.NewInt(b.prependBlock.Number().Int64()+1))
 	blocks, _ := core.GenerateChain(ctx, b.config, b.prependBlock, ethash.NewFaker(), b.prependDb.MemCopy(), 1, func(number int, block *core.BlockGen) {
 		for _, tx := range b.pendingBlock.Transactions() {
diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go
index ee5f516b2449879aea00d4d9fe423d0afcdbdb4d..4bf3e56589cfd882284073c1ac844994eafd3f79 100644
--- a/accounts/abi/bind/backends/simulated_test.go
+++ b/accounts/abi/bind/backends/simulated_test.go
@@ -14,20 +14,24 @@
 // You should have received a copy of the GNU Lesser General Public License
 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 
-package backends_test
+package backends
 
 import (
+	"bytes"
 	"context"
 	"math/big"
+	"strings"
 	"testing"
+	"time"
 
 	ethereum "github.com/ledgerwatch/turbo-geth"
+	"github.com/ledgerwatch/turbo-geth/accounts/abi"
 	"github.com/ledgerwatch/turbo-geth/accounts/abi/bind"
-	"github.com/ledgerwatch/turbo-geth/accounts/abi/bind/backends"
 	"github.com/ledgerwatch/turbo-geth/common"
 	"github.com/ledgerwatch/turbo-geth/core"
 	"github.com/ledgerwatch/turbo-geth/core/types"
 	"github.com/ledgerwatch/turbo-geth/crypto"
+	"github.com/ledgerwatch/turbo-geth/params"
 )
 
 func TestSimulatedBackend(t *testing.T) {
@@ -37,7 +41,7 @@ func TestSimulatedBackend(t *testing.T) {
 	genAlloc := make(core.GenesisAlloc)
 	genAlloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(9223372036854775807)}
 
-	sim := backends.NewSimulatedBackend(genAlloc, gasLimit)
+	sim := NewSimulatedBackend(genAlloc, gasLimit)
 	defer sim.Close()
 
 	// should return an error if the tx is not found
@@ -79,5 +83,760 @@ func TestSimulatedBackend(t *testing.T) {
 	if isPending {
 		t.Fatal("transaction should not have pending status")
 	}
+}
+
+var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+
+//  the following is based on this contract:
+//  contract T {
+//  	event received(address sender, uint amount, bytes memo);
+//  	event receivedAddr(address sender);
+//
+//  	function receive(bytes calldata memo) external payable returns (string memory res) {
+//  		emit received(msg.sender, msg.value, memo);
+//  		emit receivedAddr(msg.sender);
+//		    return "hello world";
+//  	}
+//  }
+const abiJSON = `[ { "constant": false, "inputs": [ { "name": "memo", "type": "bytes" } ], "name": "receive", "outputs": [ { "name": "res", "type": "string" } ], "payable": true, "stateMutability": "payable", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": false, "name": "sender", "type": "address" }, { "indexed": false, "name": "amount", "type": "uint256" }, { "indexed": false, "name": "memo", "type": "bytes" } ], "name": "received", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "name": "sender", "type": "address" } ], "name": "receivedAddr", "type": "event" } ]`
+const abiBin = `0x608060405234801561001057600080fd5b506102a0806100206000396000f3fe60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029`
+const deployedCode = `60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029`
+
+// expected return value contains "hello world"
+var expectedReturn = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+
+func TestNewSimulatedBackend(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+	expectedBal := big.NewInt(10000000000)
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: expectedBal},
+		}, 10000000,
+	)
+	defer sim.Close()
+
+	if sim.config != params.AllEthashProtocolChanges {
+		t.Errorf("expected sim config to equal params.AllEthashProtocolChanges, got %v", sim.config)
+	}
+
+	if sim.blockchain.Config() != params.AllEthashProtocolChanges {
+		t.Errorf("expected sim blockchain config to equal params.AllEthashProtocolChanges, got %v", sim.config)
+	}
+
+	statedb, _ := sim.blockchain.State()
+	bal := statedb.GetBalance(testAddr)
+	if bal.Cmp(expectedBal) != 0 {
+		t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal)
+	}
+}
+
+func TestSimulatedBackend_AdjustTime(t *testing.T) {
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{}, 10000000,
+	)
+	defer sim.Close()
+
+	prevTime := sim.pendingBlock.Time()
+	err := sim.AdjustTime(time.Second)
+	if err != nil {
+		t.Error(err)
+	}
+	newTime := sim.pendingBlock.Time()
+
+	if newTime-prevTime != uint64(time.Second.Seconds()) {
+		t.Errorf("adjusted time not equal to a second. prev: %v, new: %v", prevTime, newTime)
+	}
+}
+
+func TestSimulatedBackend_BalanceAt(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+	expectedBal := big.NewInt(10000000000)
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: expectedBal},
+		}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	bal, err := sim.BalanceAt(bgCtx, testAddr, nil)
+	if err != nil {
+		t.Error(err)
+	}
+
+	if bal.Cmp(expectedBal) != 0 {
+		t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal)
+	}
+}
+
+func TestSimulatedBackend_BlockByHash(t *testing.T) {
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	block, err := sim.BlockByNumber(bgCtx, nil)
+	if err != nil {
+		t.Errorf("could not get recent block: %v", err)
+	}
+	blockByHash, err := sim.BlockByHash(bgCtx, block.Hash())
+	if err != nil {
+		t.Errorf("could not get recent block: %v", err)
+	}
+
+	if block.Hash() != blockByHash.Hash() {
+		t.Errorf("did not get expected block")
+	}
+}
+
+func TestSimulatedBackend_BlockByNumber(t *testing.T) {
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	block, err := sim.BlockByNumber(bgCtx, nil)
+	if err != nil {
+		t.Errorf("could not get recent block: %v", err)
+	}
+	if block.NumberU64() != 0 {
+		t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64())
+	}
+
+	// create one block
+	sim.Commit()
+
+	block, err = sim.BlockByNumber(bgCtx, nil)
+	if err != nil {
+		t.Errorf("could not get recent block: %v", err)
+	}
+	if block.NumberU64() != 1 {
+		t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64())
+	}
 
+	blockByNumber, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
+	if err != nil {
+		t.Errorf("could not get block by number: %v", err)
+	}
+	if blockByNumber.Hash() != block.Hash() {
+		t.Errorf("did not get the same block with height of 1 as before")
+	}
+}
+
+func TestSimulatedBackend_NonceAt(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	nonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(0))
+	if err != nil {
+		t.Errorf("could not get nonce for test addr: %v", err)
+	}
+
+	if nonce != uint64(0) {
+		t.Errorf("received incorrect nonce. expected 0, got %v", nonce)
+	}
+
+	// create a signed transaction to send
+	tx := types.NewTransaction(nonce, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
+	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
+	if err != nil {
+		t.Errorf("could not sign tx: %v", err)
+	}
+
+	// send tx to simulated backend
+	err = sim.SendTransaction(bgCtx, signedTx)
+	if err != nil {
+		t.Errorf("could not add tx to pending block: %v", err)
+	}
+	sim.Commit()
+
+	newNonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(1))
+	if err != nil {
+		t.Errorf("could not get nonce for test addr: %v", err)
+	}
+
+	if newNonce != nonce+uint64(1) {
+		t.Errorf("received incorrect nonce. expected 1, got %v", nonce)
+	}
+}
+
+func TestSimulatedBackend_SendTransaction(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	// create a signed transaction to send
+	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
+	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
+	if err != nil {
+		t.Errorf("could not sign tx: %v", err)
+	}
+
+	// send tx to simulated backend
+	err = sim.SendTransaction(bgCtx, signedTx)
+	if err != nil {
+		t.Errorf("could not add tx to pending block: %v", err)
+	}
+	sim.Commit()
+
+	block, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
+	if err != nil {
+		t.Errorf("could not get block at height 1: %v", err)
+	}
+
+	if signedTx.Hash() != block.Transactions()[0].Hash() {
+		t.Errorf("did not commit sent transaction. expected hash %v got hash %v", block.Transactions()[0].Hash(), signedTx.Hash())
+	}
+}
+
+func TestSimulatedBackend_TransactionByHash(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	// create a signed transaction to send
+	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
+	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
+	if err != nil {
+		t.Errorf("could not sign tx: %v", err)
+	}
+
+	// send tx to simulated backend
+	err = sim.SendTransaction(bgCtx, signedTx)
+	if err != nil {
+		t.Errorf("could not add tx to pending block: %v", err)
+	}
+
+	// ensure tx is committed pending
+	receivedTx, pending, err := sim.TransactionByHash(bgCtx, signedTx.Hash())
+	if err != nil {
+		t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err)
+	}
+	if !pending {
+		t.Errorf("expected transaction to be in pending state")
+	}
+	if receivedTx.Hash() != signedTx.Hash() {
+		t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash())
+	}
+
+	sim.Commit()
+
+	// ensure tx is not and committed pending
+	receivedTx, pending, err = sim.TransactionByHash(bgCtx, signedTx.Hash())
+	if err != nil {
+		t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err)
+	}
+	if pending {
+		t.Errorf("expected transaction to not be in pending state")
+	}
+	if receivedTx.Hash() != signedTx.Hash() {
+		t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash())
+	}
+}
+
+func TestSimulatedBackend_EstimateGas(t *testing.T) {
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+
+	gas, err := sim.EstimateGas(bgCtx, ethereum.CallMsg{
+		From:  testAddr,
+		To:    &testAddr,
+		Value: big.NewInt(1000),
+		Data:  []byte{},
+	})
+	if err != nil {
+		t.Errorf("could not estimate gas: %v", err)
+	}
+
+	if gas != params.TxGas {
+		t.Errorf("expected 21000 gas cost for a transaction got %v", gas)
+	}
+}
+
+func TestSimulatedBackend_HeaderByHash(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	header, err := sim.HeaderByNumber(bgCtx, nil)
+	if err != nil {
+		t.Errorf("could not get recent block: %v", err)
+	}
+	headerByHash, err := sim.HeaderByHash(bgCtx, header.Hash())
+	if err != nil {
+		t.Errorf("could not get recent block: %v", err)
+	}
+
+	if header.Hash() != headerByHash.Hash() {
+		t.Errorf("did not get expected block")
+	}
+}
+
+func TestSimulatedBackend_HeaderByNumber(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	latestBlockHeader, err := sim.HeaderByNumber(bgCtx, nil)
+	if err != nil {
+		t.Errorf("could not get header for tip of chain: %v", err)
+	}
+	if latestBlockHeader == nil {
+		t.Errorf("received a nil block header")
+	}
+	if latestBlockHeader.Number.Uint64() != uint64(0) {
+		t.Errorf("expected block header number 0, instead got %v", latestBlockHeader.Number.Uint64())
+	}
+
+	sim.Commit()
+
+	latestBlockHeader, err = sim.HeaderByNumber(bgCtx, nil)
+	if err != nil {
+		t.Errorf("could not get header for blockheight of 1: %v", err)
+	}
+
+	blockHeader, err := sim.HeaderByNumber(bgCtx, big.NewInt(1))
+	if err != nil {
+		t.Errorf("could not get header for blockheight of 1: %v", err)
+	}
+
+	if blockHeader.Hash() != latestBlockHeader.Hash() {
+		t.Errorf("block header and latest block header are not the same")
+	}
+	if blockHeader.Number.Int64() != int64(1) {
+		t.Errorf("did not get blockheader for block 1. instead got block %v", blockHeader.Number.Int64())
+	}
+
+	block, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
+	if err != nil {
+		t.Errorf("could not get block for blockheight of 1: %v", err)
+	}
+
+	if block.Hash() != blockHeader.Hash() {
+		t.Errorf("block hash and block header hash do not match. expected %v, got %v", block.Hash(), blockHeader.Hash())
+	}
+}
+
+func TestSimulatedBackend_TransactionCount(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+	currentBlock, err := sim.BlockByNumber(bgCtx, nil)
+	if err != nil || currentBlock == nil {
+		t.Error("could not get current block")
+	}
+
+	count, err := sim.TransactionCount(bgCtx, currentBlock.Hash())
+	if err != nil {
+		t.Error("could not get current block's transaction count")
+	}
+
+	if count != 0 {
+		t.Errorf("expected transaction count of %v does not match actual count of %v", 0, count)
+	}
+
+	// create a signed transaction to send
+	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
+	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
+	if err != nil {
+		t.Errorf("could not sign tx: %v", err)
+	}
+
+	// send tx to simulated backend
+	err = sim.SendTransaction(bgCtx, signedTx)
+	if err != nil {
+		t.Errorf("could not add tx to pending block: %v", err)
+	}
+
+	sim.Commit()
+
+	lastBlock, err := sim.BlockByNumber(bgCtx, nil)
+	if err != nil {
+		t.Errorf("could not get header for tip of chain: %v", err)
+	}
+
+	count, err = sim.TransactionCount(bgCtx, lastBlock.Hash())
+	if err != nil {
+		t.Error("could not get current block's transaction count")
+	}
+
+	if count != 1 {
+		t.Errorf("expected transaction count of %v does not match actual count of %v", 1, count)
+	}
+}
+
+func TestSimulatedBackend_TransactionInBlock(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	transaction, err := sim.TransactionInBlock(bgCtx, sim.pendingBlock.Hash(), uint(0))
+	if err == nil && err != errTransactionDoesNotExist {
+		t.Errorf("expected a transaction does not exist error to be received but received %v", err)
+	}
+	if transaction != nil {
+		t.Errorf("expected transaction to be nil but received %v", transaction)
+	}
+
+	// expect pending nonce to be 0 since account has not been used
+	pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr)
+	if err != nil {
+		t.Errorf("did not get the pending nonce: %v", err)
+	}
+
+	if pendingNonce != uint64(0) {
+		t.Errorf("expected pending nonce of 0 got %v", pendingNonce)
+	}
+
+	// create a signed transaction to send
+	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
+	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
+	if err != nil {
+		t.Errorf("could not sign tx: %v", err)
+	}
+
+	// send tx to simulated backend
+	err = sim.SendTransaction(bgCtx, signedTx)
+	if err != nil {
+		t.Errorf("could not add tx to pending block: %v", err)
+	}
+
+	sim.Commit()
+
+	lastBlock, err := sim.BlockByNumber(bgCtx, nil)
+	if err != nil {
+		t.Errorf("could not get header for tip of chain: %v", err)
+	}
+
+	transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(1))
+	if err == nil && err != errTransactionDoesNotExist {
+		t.Errorf("expected a transaction does not exist error to be received but received %v", err)
+	}
+	if transaction != nil {
+		t.Errorf("expected transaction to be nil but received %v", transaction)
+	}
+
+	transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(0))
+	if err != nil {
+		t.Errorf("could not get transaction in the lastest block with hash %v: %v", lastBlock.Hash().String(), err)
+	}
+
+	if signedTx.Hash().String() != transaction.Hash().String() {
+		t.Errorf("received transaction that did not match the sent transaction. expected hash %v, got hash %v", signedTx.Hash().String(), transaction.Hash().String())
+	}
+}
+
+func TestSimulatedBackend_PendingNonceAt(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	// expect pending nonce to be 0 since account has not been used
+	pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr)
+	if err != nil {
+		t.Errorf("did not get the pending nonce: %v", err)
+	}
+
+	if pendingNonce != uint64(0) {
+		t.Errorf("expected pending nonce of 0 got %v", pendingNonce)
+	}
+
+	// create a signed transaction to send
+	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
+	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
+	if err != nil {
+		t.Errorf("could not sign tx: %v", err)
+	}
+
+	// send tx to simulated backend
+	err = sim.SendTransaction(bgCtx, signedTx)
+	if err != nil {
+		t.Errorf("could not add tx to pending block: %v", err)
+	}
+
+	// expect pending nonce to be 1 since account has submitted one transaction
+	pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr)
+	if err != nil {
+		t.Errorf("did not get the pending nonce: %v", err)
+	}
+
+	if pendingNonce != uint64(1) {
+		t.Errorf("expected pending nonce of 1 got %v", pendingNonce)
+	}
+
+	// make a new transaction with a nonce of 1
+	tx = types.NewTransaction(uint64(1), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
+	signedTx, err = types.SignTx(tx, types.HomesteadSigner{}, testKey)
+	if err != nil {
+		t.Errorf("could not sign tx: %v", err)
+	}
+	err = sim.SendTransaction(bgCtx, signedTx)
+	if err != nil {
+		t.Errorf("could not send tx: %v", err)
+	}
+
+	// expect pending nonce to be 2 since account now has two transactions
+	pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr)
+	if err != nil {
+		t.Errorf("did not get the pending nonce: %v", err)
+	}
+
+	if pendingNonce != uint64(2) {
+		t.Errorf("expected pending nonce of 2 got %v", pendingNonce)
+	}
+}
+
+func TestSimulatedBackend_TransactionReceipt(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		}, 10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	// create a signed transaction to send
+	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
+	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
+	if err != nil {
+		t.Errorf("could not sign tx: %v", err)
+	}
+
+	// send tx to simulated backend
+	err = sim.SendTransaction(bgCtx, signedTx)
+	if err != nil {
+		t.Errorf("could not add tx to pending block: %v", err)
+	}
+	sim.Commit()
+
+	receipt, err := sim.TransactionReceipt(bgCtx, signedTx.Hash())
+	if err != nil {
+		t.Errorf("could not get transaction receipt: %v", err)
+	}
+
+	if receipt.ContractAddress != testAddr && receipt.TxHash != signedTx.Hash() {
+		t.Errorf("received receipt is not correct: %v", receipt)
+	}
+}
+
+func TestSimulatedBackend_SuggestGasPrice(t *testing.T) {
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{},
+		10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+	gasPrice, err := sim.SuggestGasPrice(bgCtx)
+	if err != nil {
+		t.Errorf("could not get gas price: %v", err)
+	}
+	if gasPrice.Uint64() != uint64(1) {
+		t.Errorf("gas price was not expected value of 1. actual: %v", gasPrice.Uint64())
+	}
+}
+
+func TestSimulatedBackend_PendingCodeAt(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		},
+		10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+	code, err := sim.CodeAt(bgCtx, testAddr, nil)
+	if err != nil {
+		t.Errorf("could not get code at test addr: %v", err)
+	}
+	if len(code) != 0 {
+		t.Errorf("got code for account that does not have contract code")
+	}
+
+	parsed, err := abi.JSON(strings.NewReader(abiJSON))
+	if err != nil {
+		t.Errorf("could not get code at test addr: %v", err)
+	}
+	auth := bind.NewKeyedTransactor(testKey)
+	contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim)
+	if err != nil {
+		t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract)
+	}
+
+	code, err = sim.PendingCodeAt(bgCtx, contractAddr)
+	if err != nil {
+		t.Errorf("could not get code at test addr: %v", err)
+	}
+	if len(code) == 0 {
+		t.Errorf("did not get code for account that has contract code")
+	}
+	// ensure code received equals code deployed
+	if !bytes.Equal(code, common.FromHex(deployedCode)) {
+		t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code)
+	}
+}
+
+func TestSimulatedBackend_CodeAt(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		},
+		10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+	code, err := sim.CodeAt(bgCtx, testAddr, nil)
+	if err != nil {
+		t.Errorf("could not get code at test addr: %v", err)
+	}
+	if len(code) != 0 {
+		t.Errorf("got code for account that does not have contract code")
+	}
+
+	parsed, err := abi.JSON(strings.NewReader(abiJSON))
+	if err != nil {
+		t.Errorf("could not get code at test addr: %v", err)
+	}
+	auth := bind.NewKeyedTransactor(testKey)
+	contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim)
+	if err != nil {
+		t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract)
+	}
+
+	sim.Commit()
+	code, err = sim.CodeAt(bgCtx, contractAddr, nil)
+	if err != nil {
+		t.Errorf("could not get code at test addr: %v", err)
+	}
+	if len(code) == 0 {
+		t.Errorf("did not get code for account that has contract code")
+	}
+	// ensure code received equals code deployed
+	if !bytes.Equal(code, common.FromHex(deployedCode)) {
+		t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code)
+	}
+}
+
+// When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt:
+//   receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
+func TestSimulatedBackend_PendingAndCallContract(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+	sim := NewSimulatedBackend(
+		core.GenesisAlloc{
+			testAddr: {Balance: big.NewInt(10000000000)},
+		},
+		10000000,
+	)
+	defer sim.Close()
+	bgCtx := context.Background()
+
+	parsed, err := abi.JSON(strings.NewReader(abiJSON))
+	if err != nil {
+		t.Errorf("could not get code at test addr: %v", err)
+	}
+	contractAuth := bind.NewKeyedTransactor(testKey)
+	addr, _, _, err := bind.DeployContract(contractAuth, parsed, common.FromHex(abiBin), sim)
+	if err != nil {
+		t.Errorf("could not deploy contract: %v", err)
+	}
+
+	input, err := parsed.Pack("receive", []byte("X"))
+	if err != nil {
+		t.Errorf("could pack receive function on contract: %v", err)
+	}
+
+	// make sure you can call the contract in pending state
+	res, err := sim.PendingCallContract(bgCtx, ethereum.CallMsg{
+		From: testAddr,
+		To:   &addr,
+		Data: input,
+	})
+	if err != nil {
+		t.Errorf("could not call receive method on contract: %v", err)
+	}
+	if len(res) == 0 {
+		t.Errorf("result of contract call was empty: %v", res)
+	}
+
+	// while comparing against the byte array is more exact, also compare against the human readable string for readability
+	if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
+		t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
+	}
+
+	sim.Commit()
+
+	// make sure you can call the contract
+	res, err = sim.CallContract(bgCtx, ethereum.CallMsg{
+		From: testAddr,
+		To:   &addr,
+		Data: input,
+	}, nil)
+	if err != nil {
+		t.Errorf("could not call receive method on contract: %v", err)
+	}
+	if len(res) == 0 {
+		t.Errorf("result of contract call was empty: %v", res)
+	}
+
+	if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
+		t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
+	}
 }