Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AuthAccount capabilities #53

Merged
merged 7 commits into from
Mar 22, 2023
Merged
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 143 additions & 0 deletions cadence/2022-12-07-authaccount-capabilities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# AuthAccount Capabilities

| Status | Proposed |
:-------------- |:---------------------------------------------------- |
| **FLIP #** | [53](https://github.com/onflow/flips/pull/53) |
| **Author(s)** | Bastian Müller (bastian@dapperlabs.com) |
| **Sponsor** | Bastian Müller (bastian@dapperlabs.com) |
| **Updated** | 2022-03-02 |
turbolent marked this conversation as resolved.
Show resolved Hide resolved

## Objective

This FLIP proposes adding a new feature to Cadence: AuthAccount capabilities.
Similar to how storage capabilities allow gaining access to a value stored in an account's storage,
AuthAccount capabilities allow gaining access to an AuthAccount.

## Motivation

Currently, capabilities in Cadence are limited to values stored at the top level on an account.
Users may also want to share access to their account, for example, to perform storage operations.

## User Benefit

User will benefit from this new feature indirectly:
Developers will benefit by having the ability to implement functionality which allows an account to access another,
in their smart contracts, dapps, user agents, etc.

## Design Proposal

This proposal suggest adding a new function to the type `AuthAccount`:

```cadence
fun linkAccount(_ newCapabilityPath: PrivatePath): Capability<&AuthAccount>?
```

This new function behaves like the existing function `link`, but

- It creates a link to the account, instead of creating a link to a value in account storage.
- It only supports private paths (`/private`).
- It emits an event:

```cadence
event flow.AccountLinked(address: Address, path: PrivatePath)
```

Existing functions that work with links/capabilities, like `getCapability`, `borrow`, `unlink`, etc., can be used with account capabilities,
just like they currently can be used for storage path links.

The function is only allowed to be used when the program contains the pragma `#allowAccountLinking`.
The pragma must occur at the top-level, i.e. it may not be nested, and it must occur before all other non-pragma declarations.

The pragma only affects the availability of the `linkAccount` function – it does not have any influence on the usage of account links.

#### Example

Signer 0x1 creates an account link and publishes the resulting capability for 0x2:

```cadence
#allowAccountLinking

transaction {
prepare(signer: AuthAccount) {
let capability = signer.linkAccount(/private/accountCapForSomeone)!
signer.inbox.publish(capability, name: "accountCap", recipient: 0x2)
}
}
```

Signer 0x2 claims the account capability from 0x1:

```cadence
transaction {
prepare(signer: AuthAccount) {
let capability = signer.inbox.claim<&AuthAccount>("accountCap", provider: 0x1)!
let accountRef = capability.borrow()!
log(accountRef.address)
}
}
```

### Drawbacks

This proposal suggests adding a very powerful feature: An account capability allows full access to the account,
i.e. full access to manage storage, keys, contracts, etc.
Comment on lines +82 to +83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think a nice supplement to this feature would a few "interface" supertypes defined for AuthAccount to slightly mitigate this drawback. If we could create/publish a capability to a StorageWriter that only has access to link and save, or a ContractUpdater that can only add/remove contracts, it would be slightly safer to give someone access to this capability so they can, say, save a new value to your storage without also allowing them to remove all your contracts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I had proposed this before and still would like to see such interfaces being added to the language, maybe as a separate proposal though, as they would also be useful without account capabilities.


### Alternatives Considered

One alternative is to deploy a "proxy" contract to the account which enables such functionality:

```cadence
pub contract AccountProxy {
access(contract) getAuthAccount(): AuthAccount {
return self.account
}

pub resource ProxyAdmin {
fun getAuthAccount(): AuthAccount {
return AccountProxy.getAuthAccount()
}
}
}
```

Contracts already have access to the account which they are deployed to through the `account` field.
First, the contract could expose the account object through a function, in a controlled manner,
by leveraging the `access(contract)` access modifier, which only gives code in the same contract access.
Next, the contract could define a resource with a function which in turn calls the contract function which provides access to the account.
Finally, the user could store such a resource in their storage and use the existing storage capability mechanism to share access to the resource,
which in turn can be used to get the account.

However, this would require each account to have a contract deployed to it.

### Performance Implications

None

### Dependencies

None

### Engineering Impact

This change has already implementated and no further engineering impact is expected.

### Compatibility

This change has no impact on compatibility between systems (e.g. SDKs).

### User Impact

The proposed feature is a purely additive.
There is no impact on existing contracts and new transactions.

## Related Issues

None

## Questions and Discussion Topics

None

## Implementation

The proposed feature was implemented in https://github.com/onflow/cadence/pull/2160 and is currently gated behind a feature flag (disabled by default).