Skip to content

Commit

Permalink
eth-implicit
Browse files Browse the repository at this point in the history
  • Loading branch information
staffik committed Jan 31, 2025
1 parent b2c75fe commit 499ba16
Showing 1 changed file with 36 additions and 13 deletions.
49 changes: 36 additions & 13 deletions specs/DataStructures/Account.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ NEAR Protocol has an account names system. Account ID is similar to a username.
- maximum length is 64
- **Account ID** consists of **Account ID parts** separated by `.`
- **Account ID part** consists of lowercase alphanumeric symbols separated by either `_` or `-`.
- **Account ID** that is 64 characters long and consists of lowercase hex characters is a specific **implicit account ID**.
- **Account ID** that is 64 characters long and consists of lowercase hex characters is a specific **NEAR-implicit account ID**.
- **Account ID** that is `0x` followed by 40 lowercase hex characters is a specific **ETH-implicit account ID**.

Account names are similar to a domain names.
Top level account (TLA) like `near`, `com`, `eth` can only be created by `registrar` account (see next section for more details).
Only `near` can create `alice.near`. And only `alice.near` can create `app.alice.near` and so on.
Note, `near` can NOT create `app.alice.near` directly.

Additionally, there is an implicit account creation path. Account ids, that are 64 character long, can only be created with `AccessKey` that matches account id via `hex` derivation. Allowing to create new key pair - and the sender of funds to this account to actually create an account.
Additionally, there is an [implicit account creation path](#implicit-account-creation).

Regex for a full account ID, without checking for length:

Expand Down Expand Up @@ -93,32 +94,54 @@ abcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyz

`system` is a special account that is only used to identify refund receipts. For refund receipts, we set the predecessor_id to be `system` to indicate that it is a refund receipt. Users cannot create or access the `system` account. In fact, this account does not exist as part of the state.

## Implicit account IDs
## Implicit accounts

Implicit accounts work similarly to Bitcoin/Ethereum accounts.
It allows you to reserve an account ID before it's created by generating a ED25519 key-pair locally.
This key-pair has a public key that maps to the account ID. The account ID is a lowercase hex representation of the public key.
ED25519 Public key is 32 bytes that maps to 64 characters account ID.
You can reserve an account ID before it's created by generating a corresponding (public, private) key pair locally.
The public key maps to the account ID. The corresponding secret key allows you to use the account once it's created on chain.

Example: public key in base58 `BGCCDDHfysuuVnaNVtEhhqeT4k9Muyem3Kpgq2U1m9HX` will map to an account ID `98793cd91a3f870fb126f66285808c7e094afcfc4eda8a970f6648cdf0dbd6de`.
### NEAR-implicit account ID

Check failure on line 103 in specs/DataStructures/Account.md

View workflow job for this annotation

GitHub Actions / markdown-lint

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### NEAR-implicit account ID"]

specs/DataStructures/Account.md:103 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### NEAR-implicit account ID"]
The account ID is a lowercase hex representation of the public key.
An ED25519 public key is 32 bytes long and maps to a 64-character account ID.

The corresponding secret key allows you to sign transactions on behalf of this account once it's created on chain.
Example: a public key in base58 `BGCCDDHfysuuVnaNVtEhhqeT4k9Muyem3Kpgq2U1m9HX` will map to the account ID `98793cd91a3f870fb126f66285808c7e094afcfc4eda8a970f6648cdf0dbd6de`.

### ETH-implicit account ID

Check failure on line 109 in specs/DataStructures/Account.md

View workflow job for this annotation

GitHub Actions / markdown-lint

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### ETH-implicit account ID"]

specs/DataStructures/Account.md:109 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### ETH-implicit account ID"]
The account ID is derived from a Secp256K1 public key using the following formula: `'0x' + keccak256(public_key)[12:32].hex()`.

Example: a public key in base58 `2KFsZcvNUMBfmTp5DTMmguyeQyontXZ2CirPsb21GgPG3KMhwrkRuNiFCdMyRU3R4KbopMpSMXTFQfLoMkrg4HsT` will map to the account ID `0x87b435f1fcb4519306f9b755e274107cc78ac4e3`.

### Implicit account creation

An account with implicit account ID can only be created by sending a transaction/receipt with a single `Transfer` action to the implicit account ID receiver:

- The account will be created with the account ID.
- The account will have a new full access key with the ED25519-curve public key of `decode_hex(account_id)` and nonce `0`.
- The account balance will have a transfer balance deposited to it.
- If this is NEAR-implicit account, it will have a new full access key with the ED25519-curve public key of `decode_hex(account_id)` and nonce `0`.
- If this is ETH-implicit account, it will have the [Wallet Contract](#wallet-contract) deployed, which can only be used by the owner of the Secp256K1 private key where `'0x' + keccak256(public_key)[12:32].hex()` matches the account ID.

Implicit account can not be created using `CreateAccount` action to avoid being able to hijack the account without having the corresponding private key.

Once a NEAR-implicit account is created it acts as a regular account until it's deleted.

An ETH-implicit account can only be used by calling the methods of the [Wallet Contract](#wallet-contract). It cannot be deleted, nor can a full access key be added.
The primary purpose of ETH-implicit accounts is to enable seamless integration of existing Ethereum tools (such as wallets) with the NEAR blockchain.

### Wallet Contract

Check failure on line 130 in specs/DataStructures/Account.md

View workflow job for this annotation

GitHub Actions / markdown-lint

Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Wallet Contract"]

specs/DataStructures/Account.md:130 MD022/blanks-around-headings/blanks-around-headers Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "### Wallet Contract"]
The Wallet Contract (see [NEP-518](https://github.com/near/NEPs/issues/518) for more details) functions as a user account and is designed to receive, validate, and execute Ethereum-compatible transactions on the NEAR blockchain.

This account can not be created using `CreateAccount` action to avoid being able to hijack the account without having the corresponding private key.
Without going into details, an Ethereum-compatible wallet user sends a transaction to an RPC endpoint, which wraps it and passes it to the Wallet Contract (on the target account) as an `rlp_execute(target: AccountId, tx_bytes_b64: Vec<u8>)` contract call.
Then, the contract parses `tx_bytes_b64` and verifies it is signed with the private key matching the target [ETH-implicit account ID](#eth-implicit-account-id) on which the contract is hosted.

Once an implicit account is created it acts as a regular account until it's deleted.
Under the hood, the transaction encodes a NEAR-native action. Currently supported actions are:
- Transfer (from ETH-implicit account).

Check failure on line 137 in specs/DataStructures/Account.md

View workflow job for this annotation

GitHub Actions / markdown-lint

Lists should be surrounded by blank lines [Context: "- Transfer (from ETH-implicit ..."]

specs/DataStructures/Account.md:137 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "- Transfer (from ETH-implicit ..."]
- Function call (call another contract).
- Add `AccessKey` with `FunctionCallPermission`. This allows adding a relayer's public key to an ETH-implicit account, enabling the relayer to pay the gas fee for transactions from this account. Still, each transaction has to be signed by the owner of the account (corresponding Secp256K1 private key).
- Delete `AccessKey`.

## Account

Data for an single account is collocated in one shard. The account data consists of the following:
Data for a single account is collocated in one shard. The account data consists of the following:

- Balance
- Locked balance (for staking)
Expand All @@ -140,7 +163,7 @@ Locked balance may become unlocked at the beginning of an epoch. See [Staking](.
#### Contracts

A contract (AKA smart contract) is a program in WebAssembly that belongs to a specific account.
When account is created, it doesn't have a contract.
When account is created, it doesn't have a contract (except ETH-implicit accounts).
A contract has to be explicitly deployed, either by the account owner, or during the account creation.
A contract can be executed by anyone who calls a method on your account. A contract has access to the storage on your account.

Expand Down

0 comments on commit 499ba16

Please sign in to comment.