Skip to content

Commit 7b172cf

Browse files
Align other message names with HookStore rename
Signed-off-by: Michael Tinker <michael.tinker@swirldslabs.com>
1 parent 95c13a2 commit 7b172cf

1 file changed

Lines changed: 63 additions & 63 deletions

File tree

HIP/hip-1195.md

Lines changed: 63 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,9 @@ updated: 2025-10-03
1919

2020
We propose **hooks**, programmable Hiero extension points that let users customize the behavior of their entities.
2121
In principle, hooks could be programmed in any language, but we begin with **EVM hooks**. Users program EVM hooks by
22-
writing contracts in a language like Solidity that compiles to EVM bytecode. EVM hooks may have optimized variants in
23-
the future, but we propose first a full-featured **lambda** EVM hook. The name is chosen to evoke event-driven code
24-
running in the cloud or call other external services. For any given entity, its user can create many hooks for that
25-
entity with different 64-bit **hook ids**. There is no limit on the number of hook ids than an entity can use; but
26-
its storage footprint, and hence rent, will increase proportionally.
22+
writing contracts in a language like Solidity that compiles to EVM bytecode. For any given entity, its user can create
23+
many hooks for that entity with different 64-bit **hook ids**. There is no limit on the number of hook ids than an
24+
entity can use; but its storage footprint, and hence rent, will increase proportionally.
2725

2826
As a first Hiero extension point, we propose **account allowance hooks**. Users can create these hooks on their
2927
accounts, and a Hiero API (HAPI) `CryptoTransfer` transaction can then reference an allowance hook just as it does an
@@ -33,10 +31,10 @@ If the hook function returns `true`, the network continues executing the transfe
3331
transfer. Creating an account hook is analogous to adding a function to a smart contract: That is, the hook executes
3432
with the account's privileges when calling Hedera system contracts, just as a smart contract's functions do.
3533

36-
Unlike smart contracts, which must encapsulate trust guarantees for multiple parties, lambda hooks belong to a single
34+
Unlike smart contracts, which must encapsulate trust guarantees for multiple parties, EVM hooks belong to a single
3735
owner who can directly update their storage via a new `HookStore` transaction that acts on EVM storage slots. This
38-
permits fast, heap adjustments to a lambda's behavior with less overhead than a typical `ConsensusSubmitMessage`; and
39-
far less overhead than a `ContractCall`.
36+
permits fast, direct adjustments to an EVM hook's behavior with less overhead than a typical `ConsensusSubmitMessage`;
37+
and far less overhead than a `ContractCall`.
4038

4139
## Motivation
4240

@@ -80,7 +78,7 @@ which are charged purely in gas, hook executions are already "gated" by the fee
8078
So it makes sense to reduce the intrinsic gas cost of their execution. We propose adding another network property to give
8179
this effect while keeping it customizable for Hiero network operators.
8280
```
83-
hooks.evm.lambdaIntrinsicGasCost=1000
81+
hooks.evm.intrinsicGasCost=1000
8482
```
8583

8684
### Rent collection
@@ -93,7 +91,7 @@ At the time of this HIP, rent was not yet enabled on Hedera mainnet, but it is i
9391
support seamless extension of rent to hooks, we propose to keep in network state two pieces of summary data for each
9492
entity using hooks:
9593
1. The number of hooks the entity has; and,
96-
2. The total number of storage slots used by the entity's lambdas.
94+
2. The total number of storage slots used by the entity's EVM hooks.
9795

9896
The rent of an entity with `N` hooks using `S` storage slots will then scale linearly with `N` and `S`.
9997

@@ -133,18 +131,18 @@ address `0x16d` to the hook's implementing contract. That is, even though the ho
133131
with a Hiero contract id `0.0.H`, that bytecode _executes_ with a contract address of `0x16d`. If it calls another
134132
contract and that contract, in turn, calls back to address `0x16d`, then control flow returns to the hook's bytecode.
135133

136-
As a concrete example, suppose a user creates a `ACCOUNT_ALLOWANCE_HOOK` lambda with hook id `1` for account `0.0.A`.
134+
As a concrete example, suppose a user creates a `ACCOUNT_ALLOWANCE_HOOK` EVM hook with id `1` for account `0.0.A`.
137135
The hook's implementing contract is `0.0.H` with EVM address `0xab...cd`. Now `0.0.B` with EVM address `0x01...23`
138136
sends a `CryptoTransfer` transaction that references the hook `0.0.A/1` with gas limit `100_000`.
139137

140138
The network will construct an initial EVM message frame with,
141139
1. `sender` address `0x01...23`; and,
142140
2. `receiver` address `0x16d`; and,
143141
3. `contract` address `0xab...cd` (hence the source of the executing bytecode); and,
144-
4. Storage of the `0.0.A/1` lambda; and,
142+
4. Storage of the `0.0.A/1` hook; and,
145143
5. Gas remaining of `99_000` (lower intrinsic gas cost).
146144

147-
The lambda can then proceed with arbitrary actions, including calls to other contracts, `SLOAD` and `SSTORE` operations
145+
The hook can then proceed with arbitrary actions, including calls to other contracts, `SLOAD` and `SSTORE` operations
148146
with its storage, and so on. We expect the most common type of EVM hook contract to implement a single external method
149147
that reverts when not executed by the network _as a hook_. That is,
150148

@@ -197,13 +195,14 @@ EVM programmability without incurring any special risk.
197195

198196
#### Unsupported contexts and EVM operations
199197

200-
Hook executions are not supported in Batch and Scheduled transactions, but hook creations are supported in
201-
Batch and Scheduled transactions.
198+
Hook _executions_ are not supported in batch and scheduled transactions; though hook creations are supported in both.
202199

203-
Hook executions have additional restrictions on EVM opcodes:
200+
Hook executions have additional restrictions on EVM opcodes, as follows:
204201
- `CALLCODE` will always fail with halt reason of `INVALID_OPERATION`
205202
- `DELEGATECALL` will always fail with halt reason of `INVALID_OPERATION` unless its is done in the facade contract of native entity.
206-
- `SELFDESTRUCT` will always fail with halt reason of `INVALID_OPERATION` if it is done in the frame with address`0x16d`
203+
- `SELFDESTRUCT` will always fail with halt reason of `INVALID_OPERATION` if it is done in the frame with address `0x16d`
204+
205+
These restrictions are consistent with the existing Hedera EVM security model.
207206

208207
### Mirror node and block explorer support
209208

@@ -233,7 +232,7 @@ Response format:
233232
"extension_point": "ACCOUNT_ALLOWANCE_HOOK",
234233
"hook_id": 5,
235234
"owner_id": "0.0.123",
236-
"type": "LAMBDA"
235+
"type": "EVM_HOOK"
237236
}
238237
],
239238
"links": {
@@ -348,35 +347,35 @@ message HookCreationDetails {
348347
* A hook programmed in EVM bytecode that may access state or interact with
349348
* external contracts.
350349
*/
351-
LambdaEvmHook lambda_evm_hook = 4;
350+
EvmHook evm_hook = 4;
352351
}
353352
354353
/**
355354
* If set, a key that that can be used to remove or replace the hook; or (if
356-
* applicable, as with a lambda EVM hook) perform transactions that customize
357-
* the hook.
355+
* applicable, as with a EVM hook) perform transactions that customize the hook.
358356
*/
359357
proto.Key admin_key = 5;
360358
}
361359
```
362360

363-
The `LambdaEvmHook` uses a resuable a `EvmHookSpec` message that specifies the source of the hook's EVM
364-
bytecode. The `LambdaEvmHook` message also includes the initial storage slots for the lambda, if desired.
361+
The `EvmHook` uses a resuable a `EvmHookSpec` message that specifies the source of the hook's EVM
362+
bytecode (in case we ever introduce more specialized EVM hook variants). The `EvmHook` message also
363+
includes the initial storage slots for the EVM hook, if desired.
365364

366365
```protobuf
367366
/**
368-
* Definition of a lambda EVM hook.
367+
* Definition of a EVM hook.
369368
*/
370-
message LambdaEvmHook {
369+
message EvmHook {
371370
/**
372371
* The specification for the hook.
373372
*/
374373
EvmHookSpec spec = 1;
375374
376375
/**
377-
* Initial storage updates for the lambda, if any.
376+
* Initial storage updates for the hook, if any.
378377
*/
379-
repeated LambdaStorageUpdate storage_updates = 2;
378+
repeated EvmHookStorageUpdate storage_updates = 2;
380379
}
381380
382381
/**
@@ -395,20 +394,20 @@ message EvmHookSpec {
395394
}
396395
397396
/**
398-
* Specifies a key/value pair in the storage of a lambda, either by the explicit storage
397+
* Specifies a key/value pair in the storage of an EVM hook, either by the explicit storage
399398
* slot contents; or by a combination of a Solidity mapping's slot key and the key into
400399
* that mapping.
401400
*/
402-
message LambdaStorageUpdate {
401+
message EvmHookStorageUpdate {
403402
oneof update {
404403
/**
405404
* An explicit storage slot update.
406405
*/
407-
LambdaStorageSlot storage_slot = 1;
406+
EvmHookStorageSlot storage_slot = 1;
408407
/**
409408
* An implicit storage slot update specified as a Solidity mapping entry.
410409
*/
411-
LambdaMappingEntry mapping_entry = 2;
410+
EvmHookMappingEntry mapping_entry = 2;
412411
}
413412
}
414413
@@ -424,7 +423,7 @@ message LambdaStorageUpdate {
424423
* stream consumer following the metaprotocol would have to invert the Keccak256
425424
* hash to determine which mapping entry was being updated, which is not possible.
426425
*/
427-
message LambdaMappingEntry {
426+
message EvmHookMappingEntry {
428427
/**
429428
* The slot that corresponds to the Solidity mapping itself.
430429
*/
@@ -444,9 +443,9 @@ message LambdaMappingEntry {
444443
}
445444
446445
/**
447-
* A slot in the storage of a lambda EVM hook.
446+
* A slot in the storage of an EVM hook.
448447
*/
449-
message LambdaStorageSlot {
448+
message EvmHookStorageSlot {
450449
/**
451450
* The 32-byte key of the slot; leading zeros may be omitted.
452451
*/
@@ -461,24 +460,24 @@ message LambdaStorageSlot {
461460
}
462461
```
463462

464-
After an entity has a lambda, a new `HookStore` transaction supports efficiently updating the lambda's storage. It
465-
must be signed by either the entity's controlling key or the admin key set in the lambda's `HookCreationDetails`.
463+
After an entity has an EVM hook, a new `HookStore` transaction supports directly updating the hook's storage. It
464+
must be signed by either the entity's controlling key or the admin key set in the hook's `HookCreationDetails`.
466465
```protobuf
467466
/**
468-
* Adds or removes key/value pairs in the storage of a lambda.
467+
* Adds or removes key/value pairs in the storage of an EVM hook.
469468
* <p>
470-
* Either the lambda owner's key or the lambda's admin key must sign this transaction.
469+
* Either the EVM hook owner's key or the EVM hook's admin key must sign this transaction.
471470
*/
472471
message HookStoreTransactionBody {
473472
/**
474-
* The id of the lambda whose storage is being updated.
473+
* The id of the EVM hook whose storage is being updated.
475474
*/
476475
CreatedHookId hook_id = 1;
477476
478477
/**
479-
* The updates to the storage of the lambda.
478+
* The updates to the storage of the EVM hook.
480479
*/
481-
repeated LambdaStorageUpdate storage_updates = 2;
480+
repeated EvmHookStorageUpdate storage_updates = 2;
482481
}
483482
```
484483

@@ -632,9 +631,9 @@ message EvmHookState {
632631
proto.CreatedHookId hook_id = 1;
633632
634633
/**
635-
* The type of the EVM hook.
634+
* The type of the hook.
636635
*/
637-
EvmHookType type = 2;
636+
HookType type = 2;
638637
639638
/**
640639
* The type of the extension point the hook implements.
@@ -647,7 +646,7 @@ message EvmHookState {
647646
proto.ContractID hook_contract_id = 4;
648647
649648
/**
650-
* For a lambda, its first storage key.
649+
* If the hook has num_storage_slots > 0, its first storage key.
651650
*/
652651
bytes first_contract_storage_key = 5;
653652
@@ -664,33 +663,34 @@ message EvmHookState {
664663
google.protobuf.Int64Value next_hook_id = 7;
665664
666665
/**
667-
* The number of storage slots a lambda is using.
666+
* The number of storage slots the hook is using.
668667
*/
669668
uint32 num_storage_slots = 8;
670669
}
671670
672671
/**
673-
* The type of an EVM hook.
672+
* The type of a hook; currently just general-purpose EVM hooks are supported, but
673+
* more types will likely be proposed and added over time.
674674
*/
675-
enum EvmHookType {
675+
enum HookType {
676676
/**
677-
* A lambda EVM hook.
677+
* A general-purpose EVM hook.
678678
*/
679-
LAMBDA = 0;
679+
EVM_HOOK = 0;
680680
}
681681
```
682682

683683
And its storage is keyed by the following type,
684684
```protobuf
685685
/**
686-
* The key of a lambda's storage slot.
686+
* The key of an EVM hook's storage slot.
687687
*
688-
* For each lambda, its EVM storage is a mapping of 256-bit keys (or "words")
688+
* For each EVM hook, its storage is a mapping of 256-bit keys (or "words")
689689
* to 256-bit values.
690690
*/
691-
message LambdaSlotKey {
691+
message EvmHookSlotKey {
692692
/**
693-
* The id of the lambda EVM hook that owns this slot.
693+
* The id of the EVM hook that owns this slot.
694694
*/
695695
proto.CreatedHookId hook_id = 1;
696696
@@ -774,7 +774,7 @@ id in a single update transaction. (That is, the `hook_ids_to_delete` list is pr
774774
`hook_creation_details` list.)
775775

776776
We extend the `Account` message in `TokenService` state to include the number of hooks in use by an account or contract,
777-
and the total number of storage slots their lambdas use; as well as the id of the last hook in the doubly-linked list of
777+
and the total number of storage slots their EVM hooks use; as well as the id of the last hook in the doubly-linked list of
778778
the account or contract's hooks.
779779

780780
```protobuf
@@ -793,9 +793,9 @@ message Account {
793793
int64 first_hook_id = 37;
794794
795795
/**
796-
* The number of storage slots in use by this account's lambdas.
796+
* The number of storage slots in use by this account's EVM hooks.
797797
*/
798-
uint64 number_lambda_storage_slots = 38;
798+
uint64 number_evm_hook_storage_slots = 38;
799799
}
800800
```
801801

@@ -1034,7 +1034,7 @@ sending a NFT from the treasury to account `0.0.X`, and publishing a puzzle. The
10341034
use passcode that allows the solver to collect the NFT held by `0.0.X`.
10351035

10361036
In particular, the project team creates a custom hook on account `0.0.X` with hook id `1`. It is an account allowance
1037-
lambda EVM hook that references the following contract.
1037+
EVM hook that references the following contract.
10381038

10391039
```solidity
10401040
import "./IHieroAccountAllowanceHook.sol";
@@ -1046,9 +1046,9 @@ contract OneTimeCodeTransferAllowance is IHieroAccountAllowanceHook {
10461046
/// Allow the proposed transfers if and only if the args are the
10471047
/// ABI encoding of the current one-time use passcode in storage.
10481048
///
1049-
/// NOTE: this lambda's behavior does not depend on what owning
1049+
/// NOTE: this hook's behavior does not depend on what owning
10501050
/// address is set in `context.owner`; it depends only the contents
1051-
/// of the active lambda's 0x00 storage slot.
1051+
/// of the active hook's 0x00 storage slot.
10521052
function allow(
10531053
IHieroHook.HookContext calldata context,
10541054
ProposedTransfers memory proposedTransfers
@@ -1193,10 +1193,10 @@ In progress, please see [here](https://github.com/hiero-ledger/hiero-consensus-n
11931193
Ultimately it seemed better to keep the charging scheme simple and let hooks manage any refunds themselves.
11941194
5. We considered not including the `IHieroAccountAllowancePrePostHook` option, but this left a gap in support for the
11951195
full range of HTS/ERC-20 integrations that Hedera users will likely be interested in.
1196-
6. We considered **pure** EVM hooks with the same conceptual model as lambdas, but with some severe restrictions. The
1197-
initial EVM frame would be marked `static`, which prohibits all state-changing operations; and we would also disable
1198-
the `PREVRANDAO`, `SLOAD`, and `CALL` opcodes. Such a hook could not do anything but apply a pure function to its
1199-
input data; hence pure hook calls could be computed asynchronously, and the results used immediately at consensus.
1196+
6. We considered **pure** EVM hooks with the same conceptual model, but with some severe restrictions. The initial
1197+
EVM frame would be marked `static`, which prohibits all state-changing operations; and we would also disable the
1198+
`PREVRANDAO`, `SLOAD`, and `CALL` opcodes. Such a hook could not do anything but apply a pure function to its input
1199+
data; hence pure hook calls could be computed asynchronously, and the results used immediately at consensus.
12001200
But in light of upcoming general approaches to optimistic concurrent transaction handling, the value of pure hooks
12011201
did not seem worth the added complexity. Nonetheless, the protobufs here are designed to let us add such EVM
12021202
specializations in the future if the calculus changes.

0 commit comments

Comments
 (0)