diff --git a/bittensor/core/async_subtensor.py b/bittensor/core/async_subtensor.py index 6dab64e150..e167148928 100644 --- a/bittensor/core/async_subtensor.py +++ b/bittensor/core/async_subtensor.py @@ -4306,6 +4306,35 @@ async def get_stake_weight( ) return [u16_normalized_float(w) for w in result] + async def get_start_call_delay( + self, + block: Optional[int] = None, + block_hash: Optional[str] = None, + reuse_block: bool = False, + ) -> int: + """ + Retrieves the start call delay in blocks. + + Parameters: + block: The blockchain block number for the query. + block_hash: The blockchain block_hash of the block id. + reuse_block: Whether to reuse the last-used block hash. + + Return: + Amount of blocks after the start call can be executed. + """ + return cast( + int, + ( + await self.query_subtensor( + name="StartCallDelay", + block=block, + block_hash=block_hash, + reuse_block=reuse_block, + ) + ), + ) + async def get_subnet_burn_cost( self, block: Optional[int] = None, @@ -4985,19 +5014,17 @@ async def is_in_admin_freeze_window( async def is_fast_blocks(self) -> bool: """Checks if the node is running with fast blocks enabled. - Fast blocks have a block time of 10 seconds, compared to the standard 12-second block time. This affects + Fast blocks have a block time of 0.25 seconds, compared to the standard 12-second block time. This affects transaction timing and network synchronization. Returns: - `True` if fast blocks are enabled (10-second block time), `False` otherwise (12-second block time). + `True` if fast blocks are enabled, `False` otherwise. Notes: - """ - return ( - await self.query_constant("SubtensorModule", "DurationOfStartCall") - ) == 10 + return await self.get_start_call_delay() == 10 async def is_hotkey_delegate( self, diff --git a/bittensor/core/subtensor.py b/bittensor/core/subtensor.py index 6862f3a1c4..d4cb2607b5 100644 --- a/bittensor/core/subtensor.py +++ b/bittensor/core/subtensor.py @@ -3540,6 +3540,24 @@ def get_stake_weight(self, netuid: int, block: Optional[int] = None) -> list[flo ) return [u16_normalized_float(w) for w in result] + def get_start_call_delay(self, block: Optional[int] = None) -> int: + """ + Retrieves the start call delay in blocks. + + Parameters: + block: The blockchain block number for the query. + + Return: + Amount of blocks after the start call can be executed. + """ + return cast( + int, + self.query_subtensor( + name="StartCallDelay", + block=block, + ), + ) + def get_subnet_burn_cost(self, block: Optional[int] = None) -> Optional[Balance]: """ Retrieves the burn cost for registering a new subnet within the Bittensor network. This cost represents the @@ -4075,17 +4093,17 @@ def is_in_admin_freeze_window( def is_fast_blocks(self) -> bool: """Checks if the node is running with fast blocks enabled. - Fast blocks have a block time of 10 seconds, compared to the standard 12-second block time. This affects + Fast blocks have a block time of 0.25 seconds, compared to the standard 12-second block time. This affects transaction timing and network synchronization. Returns: - `True` if fast blocks are enabled (10-second block time), `False` otherwise (12-second block time). + `True` if fast blocks are enabled, `False` otherwise. Notes: - """ - return self.query_constant("SubtensorModule", "DurationOfStartCall") == 10 + return self.get_start_call_delay() == 10 def is_hotkey_delegate(self, hotkey_ss58: str, block: Optional[int] = None) -> bool: """ diff --git a/bittensor/extras/dev_framework/calls/non_sudo_calls.py b/bittensor/extras/dev_framework/calls/non_sudo_calls.py index c498fe162e..1606be4b5e 100644 --- a/bittensor/extras/dev_framework/calls/non_sudo_calls.py +++ b/bittensor/extras/dev_framework/calls/non_sudo_calls.py @@ -11,7 +11,7 @@ Note: Any manual changes will be overwritten the next time the generator is run. - Subtensor spec version: 331 + Subtensor spec version: 365 """ from collections import namedtuple @@ -42,6 +42,9 @@ ANNOUNCE = namedtuple( "ANNOUNCE", ["wallet", "pallet", "real", "call_hash"] ) # args: [real: AccountIdLookupOf, call_hash: CallHashOf] | Pallet: Proxy +ANNOUNCE_NEXT_KEY = namedtuple( + "ANNOUNCE_NEXT_KEY", ["wallet", "pallet", "public_key"] +) # args: [public_key: BoundedVec>] | Pallet: MevShield APPLY_AUTHORIZED_UPGRADE = namedtuple( "APPLY_AUTHORIZED_UPGRADE", ["wallet", "pallet", "code"] ) # args: [code: Vec] | Pallet: System @@ -118,6 +121,10 @@ BURN_ALPHA = namedtuple( "BURN_ALPHA", ["wallet", "pallet", "hotkey", "amount", "netuid"] ) # args: [hotkey: T::AccountId, amount: AlphaCurrency, netuid: NetUid] | Pallet: SubtensorModule +CALL = namedtuple( + "CALL", + ["wallet", "pallet", "dest", "value", "gas_limit", "storage_deposit_limit", "data"], +) # args: [dest: AccountIdLookupOf, value: BalanceOf, gas_limit: Weight, storage_deposit_limit: Option< as codec::HasCompact>::Type>, data: Vec] | Pallet: Contracts CALL = namedtuple( "CALL", [ @@ -135,6 +142,10 @@ "authorization_list", ], ) # args: [source: H160, target: H160, input: Vec, value: U256, gas_limit: u64, max_fee_per_gas: U256, max_priority_fee_per_gas: Option, nonce: Option, access_list: Vec<(H160, Vec)>, authorization_list: AuthorizationList] | Pallet: EVM +CALL_OLD_WEIGHT = namedtuple( + "CALL_OLD_WEIGHT", + ["wallet", "pallet", "dest", "value", "gas_limit", "storage_deposit_limit", "data"], +) # args: [dest: AccountIdLookupOf, value: BalanceOf, gas_limit: OldWeight, storage_deposit_limit: Option< as codec::HasCompact>::Type>, data: Vec] | Pallet: Contracts CANCEL = namedtuple( "CANCEL", ["wallet", "pallet", "when", "index"] ) # args: [when: BlockNumberFor, index: u32] | Pallet: Scheduler @@ -152,12 +163,8 @@ "CANCEL_RETRY_NAMED", ["wallet", "pallet", "id"] ) # args: [id: TaskName] | Pallet: Scheduler CLAIM_ROOT = namedtuple( - "CLAIM_ROOT", - [ - "wallet", - "pallet", - ], -) # args: [] | Pallet: SubtensorModule + "CLAIM_ROOT", ["wallet", "pallet", "subnets"] +) # args: [subnets: BTreeSet] | Pallet: SubtensorModule CLEAR_IDENTITY = namedtuple( "CLEAR_IDENTITY", ["wallet", "pallet", "identified"] ) # args: [identified: T::AccountId] | Pallet: Registry @@ -242,6 +249,13 @@ DECREASE_TAKE = namedtuple( "DECREASE_TAKE", ["wallet", "pallet", "hotkey", "take"] ) # args: [hotkey: T::AccountId, take: u16] | Pallet: SubtensorModule +DISABLE_LP = namedtuple( + "DISABLE_LP", + [ + "wallet", + "pallet", + ], +) # args: [] | Pallet: Swap DISABLE_WHITELIST = namedtuple( "DISABLE_WHITELIST", ["wallet", "pallet", "disabled"] ) # args: [disabled: bool] | Pallet: EVM @@ -328,6 +342,58 @@ INCREASE_TAKE = namedtuple( "INCREASE_TAKE", ["wallet", "pallet", "hotkey", "take"] ) # args: [hotkey: T::AccountId, take: u16] | Pallet: SubtensorModule +INSTANTIATE = namedtuple( + "INSTANTIATE", + [ + "wallet", + "pallet", + "value", + "gas_limit", + "storage_deposit_limit", + "code_hash", + "data", + "salt", + ], +) # args: [value: BalanceOf, gas_limit: Weight, storage_deposit_limit: Option< as codec::HasCompact>::Type>, code_hash: CodeHash, data: Vec, salt: Vec] | Pallet: Contracts +INSTANTIATE_OLD_WEIGHT = namedtuple( + "INSTANTIATE_OLD_WEIGHT", + [ + "wallet", + "pallet", + "value", + "gas_limit", + "storage_deposit_limit", + "code_hash", + "data", + "salt", + ], +) # args: [value: BalanceOf, gas_limit: OldWeight, storage_deposit_limit: Option< as codec::HasCompact>::Type>, code_hash: CodeHash, data: Vec, salt: Vec] | Pallet: Contracts +INSTANTIATE_WITH_CODE = namedtuple( + "INSTANTIATE_WITH_CODE", + [ + "wallet", + "pallet", + "value", + "gas_limit", + "storage_deposit_limit", + "code", + "data", + "salt", + ], +) # args: [value: BalanceOf, gas_limit: Weight, storage_deposit_limit: Option< as codec::HasCompact>::Type>, code: Vec, data: Vec, salt: Vec] | Pallet: Contracts +INSTANTIATE_WITH_CODE_OLD_WEIGHT = namedtuple( + "INSTANTIATE_WITH_CODE_OLD_WEIGHT", + [ + "wallet", + "pallet", + "value", + "gas_limit", + "storage_deposit_limit", + "code", + "data", + "salt", + ], +) # args: [value: BalanceOf, gas_limit: OldWeight, storage_deposit_limit: Option< as codec::HasCompact>::Type>, code: Vec, data: Vec, salt: Vec] | Pallet: Contracts KILL_PREFIX = namedtuple( "KILL_PREFIX", ["wallet", "pallet", "prefix", "subkeys"] ) # args: [prefix: Key, subkeys: u32] | Pallet: System @@ -338,6 +404,12 @@ KILL_STORAGE = namedtuple( "KILL_STORAGE", ["wallet", "pallet", "keys"] ) # args: [keys: Vec] | Pallet: System +MARK_DECRYPTION_FAILED = namedtuple( + "MARK_DECRYPTION_FAILED", ["wallet", "pallet", "id", "reason"] +) # args: [id: T::Hash, reason: BoundedVec>] | Pallet: MevShield +MIGRATE = namedtuple( + "MIGRATE", ["wallet", "pallet", "weight_limit"] +) # args: [weight_limit: Weight] | Pallet: Contracts MODIFY_POSITION = namedtuple( "MODIFY_POSITION", ["wallet", "pallet", "hotkey", "netuid", "position_id", "liquidity_delta"], @@ -420,6 +492,9 @@ REMOVE_ANNOUNCEMENT = namedtuple( "REMOVE_ANNOUNCEMENT", ["wallet", "pallet", "real", "call_hash"] ) # args: [real: AccountIdLookupOf, call_hash: CallHashOf] | Pallet: Proxy +REMOVE_CODE = namedtuple( + "REMOVE_CODE", ["wallet", "pallet", "code_hash"] +) # args: [code_hash: CodeHash] | Pallet: Contracts REMOVE_KEY = namedtuple( "REMOVE_KEY", [ @@ -557,6 +632,9 @@ SET_CODE = namedtuple( "SET_CODE", ["wallet", "pallet", "code"] ) # args: [code: Vec] | Pallet: System +SET_CODE = namedtuple( + "SET_CODE", ["wallet", "pallet", "dest", "code_hash"] +) # args: [dest: AccountIdLookupOf, code_hash: CodeHash] | Pallet: Contracts SET_CODE_WITHOUT_CHECKS = namedtuple( "SET_CODE_WITHOUT_CHECKS", ["wallet", "pallet", "code"] ) # args: [code: Vec] | Pallet: System @@ -645,6 +723,9 @@ START_CALL = namedtuple( "START_CALL", ["wallet", "pallet", "netuid"] ) # args: [netuid: NetUid] | Pallet: SubtensorModule +SUBMIT_ENCRYPTED = namedtuple( + "SUBMIT_ENCRYPTED", ["wallet", "pallet", "commitment", "ciphertext"] +) # args: [commitment: T::Hash, ciphertext: BoundedVec>] | Pallet: MevShield SUDO = namedtuple( "SUDO", ["wallet", "pallet", "call"] ) # args: [call: Box<::RuntimeCall>] | Pallet: Sudo @@ -742,6 +823,9 @@ UPGRADE_ACCOUNTS = namedtuple( "UPGRADE_ACCOUNTS", ["wallet", "pallet", "who"] ) # args: [who: Vec] | Pallet: Balances +UPLOAD_CODE = namedtuple( + "UPLOAD_CODE", ["wallet", "pallet", "code", "storage_deposit_limit", "determinism"] +) # args: [code: Vec, storage_deposit_limit: Option< as codec::HasCompact>::Type>, determinism: Determinism] | Pallet: Contracts WITHDRAW = namedtuple( "WITHDRAW", ["wallet", "pallet", "address", "value"] ) # args: [address: H160, value: BalanceOf] | Pallet: EVM diff --git a/bittensor/extras/dev_framework/calls/pallets.py b/bittensor/extras/dev_framework/calls/pallets.py index b295a3b1ba..feeb55559a 100644 --- a/bittensor/extras/dev_framework/calls/pallets.py +++ b/bittensor/extras/dev_framework/calls/pallets.py @@ -1,5 +1,5 @@ """ " -Subtensor spec version: 331 +Subtensor spec version: 365 """ System = "System" @@ -23,3 +23,5 @@ Drand = "Drand" Crowdloan = "Crowdloan" Swap = "Swap" +Contracts = "Contracts" +MevShield = "MevShield" diff --git a/bittensor/extras/dev_framework/calls/sudo_calls.py b/bittensor/extras/dev_framework/calls/sudo_calls.py index 67a25668ae..693a6b1e2a 100644 --- a/bittensor/extras/dev_framework/calls/sudo_calls.py +++ b/bittensor/extras/dev_framework/calls/sudo_calls.py @@ -11,7 +11,7 @@ Note: Any manual changes will be overwritten the next time the generator is run. - Subtensor spec version: 331 + Subtensor spec version: 365 """ from collections import namedtuple @@ -149,6 +149,9 @@ SUDO_SET_MIN_DIFFICULTY = namedtuple( "SUDO_SET_MIN_DIFFICULTY", ["wallet", "pallet", "sudo", "netuid", "min_difficulty"] ) # args: [netuid: NetUid, min_difficulty: u64] | Pallet: AdminUtils +SUDO_SET_MIN_NON_IMMUNE_UIDS = namedtuple( + "SUDO_SET_MIN_NON_IMMUNE_UIDS", ["wallet", "pallet", "sudo", "netuid", "min"] +) # args: [netuid: NetUid, min: u16] | Pallet: AdminUtils SUDO_SET_NETWORK_IMMUNITY_PERIOD = namedtuple( "SUDO_SET_NETWORK_IMMUNITY_PERIOD", ["wallet", "pallet", "sudo", "immunity_period"] ) # args: [immunity_period: u64] | Pallet: AdminUtils @@ -202,6 +205,9 @@ SUDO_SET_STAKE_THRESHOLD = namedtuple( "SUDO_SET_STAKE_THRESHOLD", ["wallet", "pallet", "sudo", "min_stake"] ) # args: [min_stake: u64] | Pallet: AdminUtils +SUDO_SET_START_CALL_DELAY = namedtuple( + "SUDO_SET_START_CALL_DELAY", ["wallet", "pallet", "sudo", "delay"] +) # args: [delay: u64] | Pallet: AdminUtils SUDO_SET_SUBNET_LIMIT = namedtuple( "SUDO_SET_SUBNET_LIMIT", ["wallet", "pallet", "sudo", "max_subnets"] ) # args: [max_subnets: u16] | Pallet: AdminUtils @@ -218,6 +224,16 @@ "SUDO_SET_SUBTOKEN_ENABLED", ["wallet", "pallet", "sudo", "netuid", "subtoken_enabled"], ) # args: [netuid: NetUid, subtoken_enabled: bool] | Pallet: AdminUtils +SUDO_SET_TAO_FLOW_CUTOFF = namedtuple( + "SUDO_SET_TAO_FLOW_CUTOFF", ["wallet", "pallet", "sudo", "flow_cutoff"] +) # args: [flow_cutoff: I64F64] | Pallet: AdminUtils +SUDO_SET_TAO_FLOW_NORMALIZATION_EXPONENT = namedtuple( + "SUDO_SET_TAO_FLOW_NORMALIZATION_EXPONENT", ["wallet", "pallet", "sudo", "exponent"] +) # args: [exponent: U64F64] | Pallet: AdminUtils +SUDO_SET_TAO_FLOW_SMOOTHING_FACTOR = namedtuple( + "SUDO_SET_TAO_FLOW_SMOOTHING_FACTOR", + ["wallet", "pallet", "sudo", "smoothing_factor"], +) # args: [smoothing_factor: u64] | Pallet: AdminUtils SUDO_SET_TARGET_REGISTRATIONS_PER_INTERVAL = namedtuple( "SUDO_SET_TARGET_REGISTRATIONS_PER_INTERVAL", ["wallet", "pallet", "sudo", "netuid", "target_registrations_per_interval"], diff --git a/bittensor/extras/dev_framework/subnet.py b/bittensor/extras/dev_framework/subnet.py index f5dd5e9561..b14c530500 100644 --- a/bittensor/extras/dev_framework/subnet.py +++ b/bittensor/extras/dev_framework/subnet.py @@ -259,9 +259,7 @@ def _activate_subnet( """Activate subnet.""" self._check_netuid() current_block = self.s.block - activation_block = self.s.queries.query_constant( - "SubtensorModule", "DurationOfStartCall" - ).value + activation_block = self.s.chain.get_start_call_delay() # added 10 blocks bc 2.5 seconds is not always enough for the chain to update. self.s.wait_for_block(current_block + activation_block + 1) response = self.s.subnets.start_call( @@ -292,11 +290,7 @@ async def _async_activate_subnet( """Activate subnet.""" self._check_netuid() current_block = await self.s.block - activation_block = ( - await self.s.queries.query_constant( - "SubtensorModule", "DurationOfStartCall" - ) - ).value + activation_block = await self.s.chain.get_start_call_delay() # added 10 blocks bc 2.5 seconds is not always enough for the chain to update. await self.s.wait_for_block(current_block + activation_block + 1) diff --git a/bittensor/extras/subtensor_api/chain.py b/bittensor/extras/subtensor_api/chain.py index dfebb034a6..4cca40bfd1 100644 --- a/bittensor/extras/subtensor_api/chain.py +++ b/bittensor/extras/subtensor_api/chain.py @@ -14,6 +14,7 @@ def __init__(self, subtensor: Union["_Subtensor", "_AsyncSubtensor"]): self.get_delegate_identities = subtensor.get_delegate_identities self.get_existential_deposit = subtensor.get_existential_deposit self.get_minimum_required_stake = subtensor.get_minimum_required_stake + self.get_start_call_delay = subtensor.get_start_call_delay self.get_timestamp = subtensor.get_timestamp self.get_vote_data = subtensor.get_vote_data self.is_fast_blocks = subtensor.is_fast_blocks diff --git a/tests/e2e_tests/test_start_call_with_delay.py b/tests/e2e_tests/test_start_call_with_delay.py new file mode 100644 index 0000000000..4b2184d449 --- /dev/null +++ b/tests/e2e_tests/test_start_call_with_delay.py @@ -0,0 +1,90 @@ +import pytest + +from tests.e2e_tests.utils import ( + AdminUtils, + TestSubnet, + ACTIVATE_SUBNET, + REGISTER_SUBNET, + SUDO_SET_START_CALL_DELAY, +) + + +def test_start_call_with_delay(subtensor, alice_wallet, eve_wallet): + """Test for start call with delay. + + Steps: + - Prepare root subnet and eve subnet + - Check initial start call delay value + - Set new start call delay via sudo call + - Verify the new start call delay is applied + - Register and activate eve subnet to verify it works with a new delay + """ + # Preps + sn_root = TestSubnet(subtensor, netuid=0) + eve_sn = TestSubnet(subtensor) + + # Set a new start call delay + new_start_call_delay = 20 + + # Check the initial start call delay + initial_start_call = subtensor.inner_subtensor.query_subtensor( + name="StartCallDelay" + ) + assert initial_start_call == subtensor.chain.get_start_call_delay() + + # Set a new start call delay via sudo call + sn_root.execute_one( + SUDO_SET_START_CALL_DELAY(alice_wallet, AdminUtils, True, new_start_call_delay) + ) + + # Check a new start call delay is set + assert subtensor.chain.get_start_call_delay() == new_start_call_delay + + # Verify eve subnet can be activated with a new start call delay + eve_sn.execute_steps( + [ + REGISTER_SUBNET(eve_wallet), + ACTIVATE_SUBNET(eve_wallet), + ] + ) + + +@pytest.mark.asyncio +async def test_start_call_with_delay_async(async_subtensor, alice_wallet, eve_wallet): + """Async test for start call with delay. + + Steps: + - Prepare root subnet and eve subnet + - Check initial start call delay value + - Set new start call delay via sudo call + - Verify the new start call delay is applied + - Register and activate eve subnet to verify it works with a new delay + """ + # Preps + sn_root = TestSubnet(async_subtensor, netuid=0) + eve_sn = TestSubnet(async_subtensor) + + # Set a new start call delay + new_start_call_delay = 20 + + # Check the initial start call delay + initial_start_call = await async_subtensor.inner_subtensor.query_subtensor( + name="StartCallDelay" + ) + assert initial_start_call == await async_subtensor.chain.get_start_call_delay() + + # Set a new start call delay via sudo call + await sn_root.async_execute_one( + SUDO_SET_START_CALL_DELAY(alice_wallet, AdminUtils, True, new_start_call_delay) + ) + + # Check a new start call delay is set + assert await async_subtensor.chain.get_start_call_delay() == new_start_call_delay + + # Verify eve subnet can be activated with a new start call delay + await eve_sn.async_execute_steps( + [ + REGISTER_SUBNET(eve_wallet), + ACTIVATE_SUBNET(eve_wallet), + ] + ) diff --git a/tests/unit_tests/test_async_subtensor.py b/tests/unit_tests/test_async_subtensor.py index 0f83110729..721e268514 100644 --- a/tests/unit_tests/test_async_subtensor.py +++ b/tests/unit_tests/test_async_subtensor.py @@ -6315,3 +6315,45 @@ async def test_mev_submit_encrypted_default_params(subtensor, fake_wallet, mocke blocks_for_revealed_execution=3, ) assert result == mocked_submit_encrypted_extrinsic.return_value + + +@pytest.mark.parametrize( + "fast_or_not, expected_result", + [ + (10, True), + (5, False), + ], +) +@pytest.mark.asyncio +async def test_is_fast_blocks(subtensor, mocker, fast_or_not, expected_result): + """Verifies that `is_fast_blocks` calls proper method with proper parameters.""" + # Preps + mocked_get_start_call_delay = mocker.patch.object( + subtensor, "get_start_call_delay", return_value=fast_or_not + ) + + # Call + result = await subtensor.is_fast_blocks() + + # Asserts + mocked_get_start_call_delay.assert_awaited_once() + assert result == expected_result + + +@pytest.mark.asyncio +async def test_get_start_call_delay(subtensor, mocker): + """Verifies that `get_start_call_delay` calls proper method with proper parameters.""" + # Preps + mocked_query_subtensor = mocker.patch.object(subtensor, "query_subtensor") + + # Call + result = await subtensor.get_start_call_delay() + + # Asserts + mocked_query_subtensor.assert_awaited_once_with( + name="StartCallDelay", + block=None, + block_hash=None, + reuse_block=False, + ) + assert result == mocked_query_subtensor.return_value diff --git a/tests/unit_tests/test_subtensor.py b/tests/unit_tests/test_subtensor.py index 0d70415874..ea7f003715 100644 --- a/tests/unit_tests/test_subtensor.py +++ b/tests/unit_tests/test_subtensor.py @@ -6430,3 +6430,38 @@ def test_mev_submit_encrypted_default_params(subtensor, fake_wallet, mocker): blocks_for_revealed_execution=3, ) assert result == mocked_submit_encrypted_extrinsic.return_value + + +@pytest.mark.parametrize( + "fast_or_not, expected_result", + [ + (10, True), + (5, False), + ], +) +def test_is_fast_blocks(subtensor, mocker, fast_or_not, expected_result): + """Verifies that `is_fast_blocks` calls proper method with proper parameters.""" + # Preps + mocked_get_start_call_delay = mocker.patch.object( + subtensor, "get_start_call_delay", return_value=fast_or_not + ) + + # Call + result = subtensor.is_fast_blocks() + + # Asserts + mocked_get_start_call_delay.assert_called_once() + assert result == expected_result + + +def test_get_start_call_delay(subtensor, mocker): + """Verifies that `get_start_call_delay` calls proper method with proper parameters.""" + # Preps + mocked_query_subtensor = mocker.patch.object(subtensor, "query_subtensor") + + # Call + result = subtensor.get_start_call_delay() + + # Asserts + mocked_query_subtensor.assert_called_once_with(name="StartCallDelay", block=None) + assert result == mocked_query_subtensor.return_value