[Proposal] Extending NEAR's Account with aliases and delegated keys

This proposal is combination of two thoughts:

  • How to improve process of onboarding new users
  • How to improve management of smart contracts without requiring each developer to write a ton of error prone code in their contracts

Problems

  1. Currently there are two ways to create accounts:
  • implicit account (only support ed25519 keys) that can be created without on-chain transaction and leveraged to receive funds
  • sub accounts - created by another account (e.g. xyz.near)

Sub accounts are obviously way more user friendly, but require on-chain transaction, which includes tx fee and storage deposit to cover storing this data on-chain.

This led to a number of issues when trying to onboard users easily. And few proposals here on how to improve this ([Discussion] Fallback for non existing sub accounts)

  1. The other issue that became evident trying to develop upgradability patterns for contracts is complexity of going from full access key on the contract to a contract managed by multisig or a DAO.

Right now it is required to implement a complex logic of upgrading contract and managing assets/control inside the contract in the first version to allow “owner” account to call these methods.

Proposal

The proposal is to adjust Account model to add next properties:

  • Aliases. Any account can have more aliases. They bind once and can not be unbind. Internally in contracts and predecessor_id the resolved alias is used. User interfaces can show the more readable alias.
  • Delegated access key. Add a new type of access key that delegates some of the properties to another account instead of a public key. This allows to pass control of the account to another account directly on the protocol level vs writing code inside contract to do this.

There are a bunch of implementation considerations that needs to be discussed, but first just wanted to put these proposal out to start the conversation.

6 Likes

Could you elaborate on the details? How does it work if, for example, the account you delegate to is on a different shard (i.e, nodes on this shard cannot verify its existence)

1 Like

One option would be to add a new type of transaction DelegatedCall that contains other actions to execute on that account. This transaction goes first to the signer account, verifies the signature and charges fees/deposit and then redirects to the target account specified in DelegatedCall properties.

enum Action {
  ...
  /// Executes set of actions on the target_id.
  /// Requires that account to have DelegatedKey toward the predecessor account.
  DelegatedCall  {
     target_id: AccountId,
     actions: Vec<Action>
  }
}

On the target account if receipt coming from one of the delegated account, it can behave as a receipt coming directly for this account.

I think biggest question here is the tradeoff of increasing complexity of the account model in exchange for simplifying contracts and also making things more extensible with new generic primitives.

1 Like