# HIP-583 (Expand alias support in CryptoCreate & CryptoTransfer Transactions)

This HIP proposes an expansion to the ways in which an account with an alias can be created and referenced to ensure compatibility with users coming from existing chains with `ECDSA` keys and provide greater applicability to smart contract scenarios.
It is thus proposed to
- Add an alias to public key mapping validation check to ensure single user ownership
- Expand `CryptoCreate` transaction to support the input of an alias of the Ethereum account address style with public key present
- Expand `CryptoTransfer` transaction to support the input of an alias of the Ethereum account address style with no public key


## Scope

This feature effects,
- **HAPI**: `CryptoTransfer` and `CryptoCreate`

So the high-level scope includes:
1. Positive functional tests, which test the updated `CryptoTransfer` and `CryptoCreate` transactions with different types of aliases.
2. Negative functional tests, which test failure scenarios of updated `CryptoTransfer` and `CryptoCreate` transactions.
3. Fuzz tests.
4. State validation for all positive and negative functional and fuzz tests.

## Methodology

Tests needed to cover the above scope.

:white_check_mark:&nbsp;**Positive functional** testing will require EET specs
that perform all variants of `CryptoTransfer` and `CryptoCreate` with different type of aliases and test if the new account is created
appropriately.

:x:&nbsp;**Negative functional** testing will require EET specs that perform all
variants of `CryptoTransfer` and `CryptoCreate` transactions with different type of aliases do not succeed.

**Fuzz** testing will require EET specs that randomly execute different types of transactions related to hollow accounts creation and finalization.

:sparkle:&nbsp;**State validation** will require a new assert built-in for the
EET `HapiGetAccountInfo` query, to assert the alias of the account. Given this,
the above functional tests can be easily enhanced to validate state is
changed (or unchanged) as appropriate.
For fuzz tests state validation will require introducing a new step at the end of the test execution to verify 
the accounts map from the final state, comparing its aliases with the record stream.

### :white_check_mark:&nbsp;Positive functional
#### CryptoCreate with ECDSA key and no alias scenario _(EET)_:
- [x] CryptoCreate initiated with ECDSA Key and no alias should successfully create an account with that key set and an empty alias.
- [x] CryptoCreate with the same key and no alias should succeed.
#### CryptoCreate with both ECDSA key and public address alias scenario _(EET)_:
- [x] CryptoCreate initiated with ECDSA key and its related public address should successfully create an account with key and alias set as returned by the GetAccountInfo query.
- [x] Following CryptoTransfers to both the 0.0.ECDSA_BYTES and public address aliases of the new account should be successful.
- [x] CryptoCreate with the same key and the same public address alias should fail since the alias is now taken.
- [x] CryptoCreate with different key and the same public address alias should fail since the alias is now taken.
- [x] CryptoCreate with the same key and no alias should succeed.
#### CryptoCreate with ED25519/ECDSA key and public address alias mismatched (with needed signature) _(EET)_:
- [x] CryptoCreate with ED25519 or ECDSA key and public address alias set, where the alias does not map to the supplied key, and a signature corresponding to the public address alias should successfully create an account with key and alias set as returned by the GetAccountInfo query..
#### CryptoTransfer of hbar to non-existing ECDSA public address alias _(EET)_:
- [x] CryptoTransfer of hbar initiated to an ECDSA public address alias field  (20 right-most bytes of hash of the public key) with no corresponding account in state successfully creates a new Hollow account.  The created account should not have a key set in the state, only an alias of the public address — a GetAccountInfo query for the public address should return a EMPTY_KEY key and no alias.
The CryptoTransfer should export a preceding auto-creation record for the hollow account creation. The record should not have key or alias set, since they should be present in the synthetic transaction body.
Subsequent CryptoTransfers of hbar, fungible and non-fungible tokens to the newly created hollow account public address should succeed and increase its balances, and transfers to the 0.0.ECDSA_BYTES alias should succeed.
#### CryptoTransfer of tokens to non-existing ECDSA public address alias _(EET)_:
- [x] CryptoTransfer of token(s) initiated to an ECDSA public address alias field (20 right-most bytes of hash of the public key) with no corresponding account in state successfully creates a new Hollow account.  The created account should not have a key set in the state, only an alias of the public address — a GetAccountInfo query for the public address should return a EMPTY_KEY key and no alias.
The CryptoTransfer should export a preceding auto-creation record for the hollow account creation. The record should not have key or alias set, since they should be present in the synthetic transaction body.
Subsequent CryptoTransfers of hbar, fungible and non-fungible tokens to the newly created hollow account public address should succeed and increase its balances, and transfers to the 0.0.ECDSA_BYTES alias should succeed.
#### Lazy Creation Through Solidity .call() _(EET)_:
- [x] A ContractCall calls a contract. The contract calls a nested contract, which executes .call() with a value transfer to a non-existing address, which creates a new hollow account. After that, the top-level contract in turn sends value again to the address, created by the nested contract. The new hollow account should have a balance equal to the sum of all value transfers to it. A preceding synthetic create record should be created and GetAccountInfo query to the address should return info for the hollow account. The contract action associated with the frame that created the hollow account should have recipientAccount set with the ID of the new account.
#### Lazy Creation Through EthereumTransaction _(EET)_:
- [x] A top-level EthereumTransaction with tx.value > 0, tx.to - a non-existing in state public address should create a Hollow account with alias = tx.to and balance = tx.value and create a contract action with the Hedera ID of the hollow account as recipient. The lazy account fee should be subtracted from the remaining gas.
#### Lazy Creation through IHederaTokenService’s cryptoTransfer _(EET)_:
- [x] A ContractCall calls a contract. That contract calls a nested contract, which executes cryptoTransfer through the HTSPrecompiledContract to a non-existing recipient, sending both fungible and non-fungible token and creates a new hollow account, charging the fees from the remaining gas. When the nested contract returns, the parent contract also calls cryptoTransfer sending fungible/non-fungible to the same address. After execution, a preceding synthetic create transaction should be exported. The sum of all transfers from both contracts to the account should be reflected back in the account’s balance.  GetAccountInfo query to the address should return info for the hollow account. Subsequent attempts to transfer other tokens to the hollow account through the precompile should fail with NO_MORE_AUTOMATIC_TOKEN_ASSOCIATIONS.
#### Lazy Creation through IHederaTokenService’s cryptoTransferV2 _(EET)_:
- [x] A ContractCall calls a contract. That contract calls a nested contract, which executes cryptoTransferV2 through the HTSPrecompiledContract to a non-existing recipient, sending hbar and both fungible and non-fungible token and creates a new hollow account, charging the fees from the remaining gas. When the nested contract returns, the parent contract also calls cryptoTransferV2 sending hbar, fungible/non-fungible to the same address. After execution, a preceding synthetic create transaction should be exported. The sum of all transfers from both contracts to the account should be reflected back in the account’s balance.  GetAccountInfo query to the address should return info for the hollow account. Subsequent attempts to transfer other tokens to the hollow account through the precompile should fail with NO_MORE_AUTOMATIC_TOKEN_ASSOCIATIONS.
#### Lazy Creation through IHederaTokenService’s transferToken _(EET)_:
- [x] A ContractCall that executes transferToken through the HTSPrecompiledContract to a non-existing recipient should create a new hollow account, charging the fees from the remaining gas.
#### Lazy Creation through IHederaTokenService’s transferTokens _(EET)_:
- [x] A ContractCall that executes transferTokens through the HTSPrecompiledContract to a non-existing recipient should create a new hollow account, charging the fees from the remaining gas.
#### Lazy Creation through IHederaTokenService’s transferNFT _(EET)_:
- [x] A ContractCall that executes transferNFT through the HTSPrecompiledContract to a non-existing recipient should create a new hollow account, charging the fees from the remaining gas.
#### Lazy Creation through IHederaTokenService’s transferNFTs _(EET)_:
- [x] A ContractCall that executes transferNFTs through the HTSPrecompiledContract to a non-existing recipient should create a new hollow account, charging the fees from the remaining gas.
#### Lazy Creation through ERC20 transfer _(EET)_:
- [x]  A ContractCall that executes ERC transfer through the HTSPrecompiledContract to a non-existing recipient should create a new hollow account, charging the fees from the remaining gas.
#### Lazy Creation through IHederaTokenService’s ERC transfer equivalent _(EET)_:
- [x] A ContractCall that executes HTS transfer through the HTSPrecompiledContract to a non-existing recipient should create a new hollow account, charging the fees from the remaining gas.
#### Lazy Creation through ERC20 transferFrom _(EET)_:
- [x] A ContractCall that executes ERC transferFrom through the HTSPrecompiledContract to a non-existing recipient should create a new hollow account, charging the fees from the remaining gas.
#### Lazy Creation through ERC721transferFrom _(EET)_:
- [x] A ContractCall that executes ERC transferFrom through the HTSPrecompiledContract to a non-existing recipient should create a new hollow account, charging the fees from the remaining gas.
#### Lazy Creation through IHederaTokenService’s ERC transferFrom equivalent _(EET)_:
- [x] A ContractCall that executes HTS transferFrom through the HTSPrecompiledContract to a non-existing recipient should create a new hollow account, charging the fees from the remaining gas.
#### Multiple lazy creation in a single precompile transfer call _(EET)_:
- [x] A ContractCAll that executes any precompile transfer trying to transfer to multiple non-existing addresses succeeds in creating multiple hollow accounts
#### Lazy creation charging _(EET)_:
- [x]  All lazy account fees —CryptoCreate for creation and CryptoUpdate for completion — should be charged at the moment of creation of a hollow account by the payer of the transaction. This applies to hollow account creations through CryptoCreate , CryptoTransfer and all EVM paths.
#### Hollow account finalization of both relayer and tx.sender _(EET)_:
- [x]  An EthereumTransaction whose payer is a hollow account and the tx.sender is a different hollow account should finalize both accounts in state, updating their key fields. A CryptoUpdate child record should be exported for each of the two finalizations, but no additional fees should be paid.
### :x:&nbsp;Negative functional
#### CryptoCreate with ED25519 alias and no key scenario _(EET)_:
- [x] A CryptoCreate initiated without a key field set and ED25519 public key alias (serialization of ED25519 Key protobuf) set, should fail with INVALID_ALIAS_KEY.
#### CryptoCreate with ECDSA public key alias and no key scenario _(EET)_:
- [x] CryptoCreate initiated without a key field set and an ECDSA public key alias (serialization of ECDSA Key protobuf) set, should fail with INVALID_ALIAS_KEY.
#### CryptoCreate with ECDSA public address alias and no key scenario _(EET)_:
- [x] CryptoCreate initiated without a key field set and with an ECDSA public address alias field (20 right-most bytes of hash of the public key) set, should fail with INVALID_ALIAS_KEY.
#### CryptoCreate with both ED25519 key and alias scenario _(EET)_:
- [x] CryptoCreate initiated with ED25519 key and its related alias, should fail with INVALID_ALIAS_KEY.
#### CryptoCreate with both ECDSA key and public key alias scenario _(EET)_:
- [x] CryptoCreate initiated with ECDSA key and its related public key alias, should fail with INVALID_ALIAS_KEY.
#### CryptoCreate with ED25519/ECDSA key and public address alias mismatched (without needed signature) _(EET)_:
- [x] CryptoCreate initiated with ED25519 or ECDSA key and public address alias set, where the alias does not map to the supplied key, and there is no signature corresponding to the public address alias should fail with INVALID_SIGNATURE.
#### CryptoCreate with any key and ED25519/ECDSA key alias that do not match _(EET)_:
- [x] CryptoCreate initiated with some key and ED25519 or ECDSA key alias that are not matching, should fail with INVALID_ALIAS_KEY.
#### CryptoCreate with long-zero alias _(EET)_:
- [x] CryptoCreate initiated with long-zero alias, should fail with INVALID_ALIAS_KEY.
#### CryptoTransfer to non-existing long-zero alias _(EET)_:
- [x] CryptoTransfer to non-existing account using long-zero alias, should fail with INVALID_ACCOUNT_ID.
#### Lazy Creation Through Solidity .call() _(EET)_:
- [x] A ContractCall calls a contract. The contract calls a nested contract, which executes .call() with a value transfer to a non-existing address, which creates a new hollow account. However, after that, the nested contract executes revert(), reverting the whole contract call. Ultimately, the hollow account creation should revert and no account in the state should be created. No synthetic child records should be created and GetAccountInfo query to the non-existing address should fail with INVALID_ACCOUNT_ID. The contract action associated with the frame that tried to create the hollow account should have targetedAddress set with the non-existing address.
#### Lazy Creation Through EthereumTransaction _(EET)_:
- [x] An EthereumTransaction with tx.value > 0, tx.to - a non-existing in state public address should fail INSUFFICIENT_GAS when gas is not sufficient to cover lazy creation fees. A Hollow account should not be created and a contract action with the tx.to as recipient should be exported. No preceding synthetic create transaction records should be exported and GetAccountInfo query to the non-existing address should fail with INVALID_ACCOUNT_ID.
#### In EVM Lazy Creation Limit _(EET)_:
- [x] A ContractCall calls a contract. The contract tries to execute .call() with value transfer, thus trying to create lazy accounts, more than consensus.handle.maxPrecedingRecord, which is currently set to 3, and the execution should revert. None of the accounts should be created — GetAccountInfo  queries to all the addresses should fail with INVALID_ACCOUNT_ID. Also, no child records should be present from the ContractCall.
#### Lazy Creation through the precompile with more lazy creations than allowed _(EET)_:
- [x] A ContractCall that executes precompile transfers that tries to create more than consensus.handle.maxPrecedingRecords hollow accounts, resulting in failing the ContractCall with MAX_CHILD_RECORDS_EXCEEDED status. No hollow accounts should be created and no child records should be exported.
#### Transfer hollow account assets through the precompile _(EET)_:
- [x] A ContractCall that executes any precompile transfer trying to transfer assets from a hollow account should fail with INVALID_SIGNATURE.
#### Precompile transfer to non-existing mirror address _(EET)_:
- [x] A ContractCall that executes any precompile transfer trying to transfer to a non-existing mirror address should fail with INVALID_ALIAS_KEY and not create a hollow account.
