Skip to content

Commit

Permalink
Fix in the sender address + in the response when using wrappers
Browse files Browse the repository at this point in the history
Also, added several variables to be able to increase gas limit and gas
prices.
  • Loading branch information
gnarvaja committed Aug 30, 2024
1 parent 3c27369 commit 3cb7146
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 8 deletions.
30 changes: 23 additions & 7 deletions src/ethproto/aa_bundler.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from eth_account.messages import encode_defunct
from hexbytes import HexBytes
from web3 import Web3
from web3.constants import ADDRESS_ZERO
from .contracts import RevertError


Expand All @@ -17,6 +18,9 @@
AA_BUNDLER_ENTRYPOINT = env.str("AA_BUNDLER_ENTRYPOINT", "0x0000000071727De22E5E9d8BAf0edAc6f37da032")
AA_BUNDLER_EXECUTOR_PK = env.str("AA_BUNDLER_EXECUTOR_PK", None)
AA_BUNDLER_PROVIDER = env.str("AA_BUNDLER_PROVIDER", "alchemy")
AA_BUNDLER_GAS_LIMIT_FACTOR = env.float("AA_BUNDLER_GAS_LIMIT_FACTOR", 1)
AA_BUNDLER_PRIORITY_GAS_PRICE_FACTOR = env.float("AA_BUNDLER_PRIORITY_GAS_PRICE_FACTOR", 1)
AA_BUNDLER_BASE_GAS_PRICE_FACTOR = env.float("AA_BUNDLER_BASE_GAS_PRICE_FACTOR", 1)

NonceMode = Enum(
"NonceMode",
Expand Down Expand Up @@ -147,7 +151,7 @@ def get_nonce_and_key(w3, tx, nonce_mode, entry_point=AA_BUNDLER_ENTRYPOINT, fet

if nonce is None:
if fetch or nonce_mode == NonceMode.FIXED_KEY_FETCH_ALWAYS:
nonce = fetch_nonce(w3, tx.get("from", AA_BUNDLER_SENDER), entry_point, nonce_key)
nonce = fetch_nonce(w3, get_sender(tx), entry_point, nonce_key)
elif nonce_key not in NONCE_CACHE:
nonce = 0
else:
Expand All @@ -168,7 +172,16 @@ def handle_response_error(resp, w3, tx, retry_nonce):

def get_base_fee(w3):
blk = w3.eth.get_block("latest")
return blk["baseFeePerGas"]
return int(_to_uint(blk["baseFeePerGas"]) * AA_BUNDLER_BASE_GAS_PRICE_FACTOR)


def get_sender(tx):
if "from" not in tx or tx["from"] == ADDRESS_ZERO:
if AA_BUNDLER_SENDER is None:
raise RuntimeError("Must define AA_BUNDLER_SENDER or send 'from' in the TX")
return AA_BUNDLER_SENDER
else:
return tx["from"]


def send_transaction(w3, tx, retry_nonce=None):
Expand All @@ -185,7 +198,7 @@ def send_transaction(w3, tx, retry_nonce=None):
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1c"
)
user_operation = {
"sender": tx.get("from", AA_BUNDLER_SENDER),
"sender": get_sender(tx),
"nonce": hex(make_nonce(nonce_key, nonce)),
"callData": call_data,
"signature": dummy_signature,
Expand All @@ -203,9 +216,12 @@ def send_transaction(w3, tx, retry_nonce=None):
resp = w3.provider.make_request("rundler_maxPriorityFeePerGas", [])
if "error" in resp:
raise RevertError(resp["error"]["message"])
max_priority_fee_per_gas = resp["result"]
user_operation["maxPriorityFeePerGas"] = max_priority_fee_per_gas
user_operation["maxFeePerGas"] = hex(_to_uint(max_priority_fee_per_gas) + _to_uint(get_base_fee(w3)))
max_priority_fee_per_gas = int(_to_uint(resp["result"]) * AA_BUNDLER_PRIORITY_GAS_PRICE_FACTOR)
user_operation["maxPriorityFeePerGas"] = hex(max_priority_fee_per_gas)
user_operation["maxFeePerGas"] = hex(max_priority_fee_per_gas + get_base_fee(w3))
user_operation["callGasLimit"] = hex(
int(_to_uint(user_operation["callGasLimit"]) * AA_BUNDLER_GAS_LIMIT_FACTOR)
)
elif AA_BUNDLER_PROVIDER == "gelato":
user_operation.update(
{
Expand All @@ -231,4 +247,4 @@ def send_transaction(w3, tx, retry_nonce=None):

# Store nonce in the cache, so next time uses a new nonce
NONCE_CACHE[nonce_key] = nonce + 1
return resp["result"]
return {"userOpHash": resp["result"]}
2 changes: 2 additions & 0 deletions src/ethproto/w3wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,8 @@ def eth_function(*args):
def normalize_receipt(self, wrapper, receipt):
if W3_TRANSACT_MODE == "defender-async":
return receipt # Don't do anything because the receipt is just a dict of not-yet-mined tx
elif W3_TRANSACT_MODE == "aa-bundler-async":
return receipt # Don't do anything because the receipt is just a dict of {"userOpHash": "..."}
return ReceiptWrapper(receipt, wrapper.contract)

def _handle_exception(self, err):
Expand Down
4 changes: 3 additions & 1 deletion tests/test_aa_bundler.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from hexbytes import HexBytes
from ethproto import aa_bundler
from web3.constants import HASH_ZERO
Expand Down Expand Up @@ -175,6 +176,7 @@ def test_get_nonce_with_local_cache(fetch_nonce_mock, randint_mock):
fetch_nonce_mock.assert_not_called()


@patch.object(aa_bundler, "AA_BUNDLER_NONCE_MODE", new=aa_bundler.NonceMode.FIXED_KEY_LOCAL_NONCE)
@patch.object(aa_bundler, "get_base_fee")
def test_send_transaction(get_base_fee_mock):
get_base_fee_mock.return_value = 0
Expand Down Expand Up @@ -239,4 +241,4 @@ def make_request(method, params):
ret = aa_bundler.send_transaction(w3, tx)
get_base_fee_mock.assert_called_once_with(w3)
assert aa_bundler.NONCE_CACHE[0] == 1
assert ret == "0xa950a17ca1ed83e974fb1aa227360a007cb65f566518af117ffdbb04d8d2d524"
assert ret == {"userOpHash": "0xa950a17ca1ed83e974fb1aa227360a007cb65f566518af117ffdbb04d8d2d524"}

0 comments on commit 3cb7146

Please sign in to comment.