Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
logger = get_logger(__name__)


class DeterministicFactoryNotDeployableError(Exception):
"""
Raised when the deterministic proxy cannot deploy.
Example: fixed gas limit insufficient for network creation cost.
"""


def check_deterministic_factory_deployment(
*,
eth_rpc: EthRPC,
Expand Down Expand Up @@ -96,6 +103,28 @@ def deploy_deterministic_factory_contract(
).with_signature_and_sender()
deploy_tx_sender = deploy_tx.sender
assert deploy_tx_sender is not None

# Pre-flight: skip deploy if network gas > fixed limit.
# Gas limit is fixed as changing it alters sender/factory address.
# If network requires more gas, transaction can never be included.
try:
required_gas = eth_rpc.estimate_gas(
transaction={
"from": f"{deploy_tx_sender}",
"input": f"{deploy_tx.data}",
}
)
except Exception:
# If the estimate itself is unavailable, fall through and attempt the
# deploy as before (failures are still handled by the caller).
required_gas = None
if required_gas is not None and required_gas > deploy_tx_gas_limit:
raise DeterministicFactoryNotDeployableError(
f"network requires {required_gas} gas to create the deterministic "
f"deployment proxy, exceeding the keyless transaction's fixed gas "
f"limit of {deploy_tx_gas_limit}"
)

required_deployer_balance = deploy_tx_gas_price * deploy_tx_gas_limit
current_balance = eth_rpc.get_balance(deploy_tx_sender)
if current_balance < required_deployer_balance:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ def execute_required_contracts(
Deploy required contracts for the execute command.

- Deterministic deployment proxy

Proxy deploy failure doesn't abort the session.
Tests skip deterministic deploys on use.
Details check `(see Alloc._resolve_deterministic_deploys)`.
"""
base_lock_file = session_temp_folder / "execute_required_contracts.lock"
with FileLock(base_lock_file):
Expand All @@ -171,12 +175,13 @@ def execute_required_contracts(
gas_price=sender_funding_transactions_gas_price,
)
except Exception as e:
raise RuntimeError(
f"Error deploying deterministic deployment contract:\n{e}"
"\nTry deploying the contract manually using a different "
"RPC endpoint with the following command:\n"
"uv run execute deploy-required-contracts"
) from e
logger.warning(
"Could not deploy the deterministic deployment proxy; "
"tests that require it will be skipped. To deploy it "
"manually against a different RPC endpoint run "
"`uv run execute deploy-required-contracts`. "
f"Reason: {e}"
)


class PendingTransaction(Transaction):
Expand Down Expand Up @@ -752,12 +757,17 @@ def _resolve_deterministic_deploys(self) -> None:
)
else:
if not factory_checked:
assert (
if (
check_deterministic_factory_deployment(
eth_rpc=self._eth_rpc, fork=fork
)
is not None
), "Deployment contract code is not found"
is None
):
pytest.skip(
"deterministic deployment proxy is not available "
"on this network; skipping test that requires a "
"deterministic contract deployment"
)
factory_checked = True

logger.info(
Expand Down
16 changes: 16 additions & 0 deletions packages/testing/src/execution_testing/rpc/rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,22 @@ def get_balances(
responses = self.post_batch_request(calls=calls)
return [int(r.result_or_raise(), 16) for r in responses]

def estimate_gas(
self,
transaction: Dict[str, Any],
block_number: BlockNumberType = "latest",
) -> int:
"""`eth_estimateGas`: Return the gas required to execute a tx."""
block = (
hex(block_number)
if isinstance(block_number, int)
else block_number
)
response = self.post_request(
request=RPCCall(method="estimateGas", params=[transaction, block])
).result_or_raise()
return int(response, 16)

def get_code(
self, address: Address, block_number: BlockNumberType = "latest"
) -> Bytes:
Expand Down
Loading