Skip to content

Commit

Permalink
Add EthAccount (#853)
Browse files Browse the repository at this point in the history
* feat: add eth_account main logic

* feat: add tests

* fix: workflow

* feat: change EthPublicKey to Secp256k1Point

* feat: add more tests

* feat: add entry to CHANGELOG

* feat: add tests for preset

* docs: add API Reference entries

* Update src/account/eth_account/eth_account.cairo

Co-authored-by: Andrew Fleming <[email protected]>

* feat: apply review updates

* refactor: test

* feat: apply review updates

* feat: update error messages

* feat: apply review updates

* Update docs/modules/ROOT/pages/api/account.adoc

Co-authored-by: Martín Triay <[email protected]>

* feat: add tests for upgrade

* feat: add tests for signature

* refactor: drop X.Y.Z in favor of last released version

* feat: updated class hashes

* fix: casm target

* fix: versions

* refactor: account directory

* fix: comments

* fix: class hashes

---------

Co-authored-by: Andrew Fleming <[email protected]>
Co-authored-by: Martín Triay <[email protected]>
  • Loading branch information
3 people authored Jan 31, 2024
1 parent 1448616 commit 6d26b84
Show file tree
Hide file tree
Showing 30 changed files with 2,844 additions and 95 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Added

- EthAccount component and preset (#853)

### Changed

- Bump scarb to v2.4.4 (#864)
- Bump scarb to v2.4.4 (#853)

## 0.8.1 (2024-01-23)

Expand All @@ -27,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Use ComponentState in tests (#836)
- Docsite navbar (#838)
- Account events indexed keys (#853)
- Support higher tx versions in Account (#858)
- Bump scarb to v2.4.1 (#858)
- Add security section to Upgrades docs (#861)
2 changes: 1 addition & 1 deletion Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ starknet = "2.4.4"
[[target.starknet-contract]]
allowed-libfuncs-list.name = "experimental"
sierra = true
casm = true
casm = false

[tool.fmt]
sort-module-level-items = true
276 changes: 274 additions & 2 deletions docs/modules/ROOT/pages/api/account.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,16 @@ Returns the short string `'VALID'` if valid, otherwise it reverts.

[.contract]
[[AccountComponent]]
=== `++AccountComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/account/account.cairo#L27[{github-icon},role=heading-link]
=== `++AccountComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/account/account.cairo[{github-icon},role=heading-link]

:OwnerAdded: xref:AccountComponent-OwnerAdded[OwnerAdded]
:OwnerRemoved: xref:AccountComponent-OwnerRemoved[OwnerRemoved]
:starknet-curve: https://docs.starknet.io/documentation/architecture_and_concepts/Cryptography/stark-curve/[Starknet curve]

```javascript
use openzeppelin::account::AccountComponent;
```
Account component implementing xref:ISRC6[`ISRC6`].
Account component implementing xref:ISRC6[`ISRC6`] for signatures over the {starknet-curve}.

NOTE: Implementing xref:api/introspection.adoc#SRC5Component[SRC5Component] is a requirement for this component to be implemented.

Expand Down Expand Up @@ -260,6 +261,210 @@ Emitted when a `public_key` is added.

Emitted when a `public_key` is removed.

[.contract]
[[EthAccountComponent]]
=== `++EthAccountComponent++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/account/eth_account.cairo[{github-icon},role=heading-link]

:OwnerAdded: xref:EthAccountComponent-OwnerAdded[OwnerAdded]
:OwnerRemoved: xref:EthAccountComponent-OwnerRemoved[OwnerRemoved]
:secp256k1-curve: https://en.bitcoin.it/wiki/Secp256k1[Secp256k1 curve]

```javascript
use openzeppelin::account::eth_account::EthAccountComponent;
```
Account component implementing xref:ISRC6[`ISRC6`] for signatures over the {secp256k1-curve}.

NOTE: Implementing xref:api/introspection.adoc#SRC5Component[SRC5Component] is a requirement for this component to be implemented.

NOTE: The `EthPublicKey` type is an alias for `starknet::secp256k1::Secp256k1Point`.

[.contract-index#EthAccountComponent-Embeddable-Impls]
.Embeddable Implementations
--
.SRC6Impl

* xref:#EthAccountComponent-\\__execute__[`++__execute__(self, calls)++`]
* xref:#EthAccountComponent-\\__validate__[`++__validate__(self, calls)++`]
* xref:#EthAccountComponent-is_valid_signature[`++is_valid_signature(self, hash, signature)++`]

.DeclarerImpl

* xref:#EthAccountComponent-\\__validate_declare__[`++__validate_declare__(self, class_hash)++`]

.DeployableImpl

* xref:#EthAccountComponent-\\__validate_deploy__[`++__validate_deploy__(self, hash, signature)++`]

.PublicKeyImpl

* xref:#EthAccountComponent-get_public_key[`++get_public_key(self)++`]
* xref:#EthAccountComponent-set_public_key[`++set_public_key(self, new_public_key)++`]
--

[.contract-index#EthAccountComponent-Embeddable-Impls-camelCase]
.Embeddable Implementations (camelCase)
--
.SRC6CamelOnlyImpl

* xref:#EthAccountComponent-isValidSignature[`++isValidSignature(self, hash, signature)++`]

.PublicKeyCamelImpl

* xref:#EthAccountComponent-getPublicKey[`++getPublicKey(self)++`]
* xref:#EthAccountComponent-setPublicKey[`++setPublicKey(self, newPublicKey)++`]
--

[.contract-index]
.Internal Implementations
--
.InternalImpl

* xref:#EthAccountComponent-initializer[`++initializer(self, public_key)++`]
* xref:#EthAccountComponent-assert_only_self[`++assert_only_self(self)++`]
* xref:#EthAccountComponent-validate_transaction[`++validate_transaction(self)++`]
* xref:#EthAccountComponent-_set_public_key[`++_set_public_key(self, new_public_key)++`]
* xref:#EthAccountComponent-_is_valid_signature[`++_is_valid_signature(self, hash, signature)++`]
--

[.contract-index]
.Events
--
* xref:#EthAccountComponent-OwnerAdded[`++OwnerAdded(new_owner_guid)++`]
* xref:#EthAccountComponent-OwnerRemoved[`++OwnerRemoved(removed_owner_guid)++`]
--

[#EthAccountComponent-Embeddable-Functions]
==== Embeddable Functions

[.contract-item]
[[EthAccountComponent-__execute__]]
==== `[.contract-item-name]#++__execute__++#++(self: @ContractState, calls: Array<Call>) → Array<Span<felt252>>++` [.item-kind]#external#

See xref:ISRC6-\\__execute__[ISRC6::\\__execute__].

[.contract-item]
[[EthAccountComponent-__validate__]]
==== `[.contract-item-name]#++__validate__++#++(self: @ContractState, calls: Array<Call>) → felt252++` [.item-kind]#external#

See xref:ISRC6-\\__validate__[ISRC6::\\__validate__].

[.contract-item]
[[EthAccountComponent-is_valid_signature]]
==== `[.contract-item-name]#++is_valid_signature++#++(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252++` [.item-kind]#external#

See xref:ISRC6-is_valid_signature[ISRC6::is_valid_signature].

[.contract-item]
[[EthAccountComponent-__validate_declare__]]
==== `[.contract-item-name]#++__validate_declare__++#++(self: @ContractState, class_hash: felt252) → felt252++` [.item-kind]#external#

Validates a https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#declare-transaction[`Declare` transaction].

Returns the short string `'VALID'` if valid, otherwise it reverts.

[.contract-item]
[[EthAccountComponent-__validate_deploy__]]
==== `[.contract-item-name]#++__validate_deploy__++#++(self: @ContractState, class_hash: felt252, contract_address_salt: felt252, public_key: EthPublicKey) → felt252++` [.item-kind]#external#

Validates a https://docs.starknet.io/documentation/architecture_and_concepts/Network_Architecture/Blocks/transactions/#deploy_account_transaction[`DeployAccount` transaction].
See xref:/guides/deployment.adoc[Counterfactual Deployments].

Returns the short string `'VALID'` if valid, otherwise it reverts.

[.contract-item]
[[EthAccountComponent-get_public_key]]
==== `[.contract-item-name]#++get_public_key++#++(self: @ContractState)++ → EthPublicKey` [.item-kind]#external#

Returns the current public key of the account.

[.contract-item]
[[EthAccountComponent-set_public_key]]
==== `[.contract-item-name]#++set_public_key++#++(ref self: ContractState, new_public_key: EthPublicKey)++` [.item-kind]#external#

Sets a new public key for the account. Only accesible by the account calling itself through `\\__execute__`.

Emits both an {OwnerRemoved} and an {OwnerAdded} event.

[#EthAccountComponent-camelCase-Support]
==== camelCase Support

[.contract-item]
[[EthAccountComponent-isValidSignature]]
==== `[.contract-item-name]#++isValidSignature++#++(self: @ContractState, hash: felt252, signature: Array<felt252>) → felt252++` [.item-kind]#external#

See xref:ISRC6-is_valid_signature[ISRC6::is_valid_signature].

[.contract-item]
[[EthAccountComponent-getPublicKey]]
==== `[.contract-item-name]#++getPublicKey++#++(self: @ContractState)++ → EthPublicKey` [.item-kind]#external#

See xref:EthAccountComponent-get_public_key[get_public_key].

[.contract-item]
[[EthAccountComponent-setPublicKey]]
==== `[.contract-item-name]#++setPublicKey++#++(ref self: ContractState, newPublicKey: EthPublicKey)++` [.item-kind]#external#

See xref:EthAccountComponent-set_public_key[set_public_key].

[#EthAccountComponent-Internal-Functions]
==== Internal Functions

[.contract-item]
[[EthAccountComponent-initializer]]
==== `[.contract-item-name]#++initializer++#++(ref self: ComponentState, public_key: EthPublicKey)++` [.item-kind]#internal#

Initializes the account with the given public key, and registers the ISRC6 interface ID.

Emits an {OwnerAdded} event.

[.contract-item]
[[EthAccountComponent-assert_only_self]]
==== `[.contract-item-name]#++assert_only_self++#++(self: @ComponentState)++` [.item-kind]#internal#

Validates that the caller is the account itself. Otherwise it reverts.

[.contract-item]
[[EthAccountComponent-validate_transaction]]
==== `[.contract-item-name]#++validate_transaction++#++(self: @ComponentState)++ → felt252` [.item-kind]#internal#

Validates a transaction signature from the
https://github.com/starkware-libs/cairo/blob/main/corelib/src/starknet/info.cairo#L61[global context].

Returns the short string `'VALID'` if valid, otherwise it reverts.

[.contract-item]
[[EthAccountComponent-_set_public_key]]
==== `[.contract-item-name]#++_set_public_key++#++(ref self: ComponentState, new_public_key: EthPublicKey)++` [.item-kind]#internal#

Set the public key without validating the caller.

Emits an {OwnerAdded} event.

CAUTION: The usage of this method outside the `set_public_key` function is discouraged.

[.contract-item]
[[EthAccountComponent-_is_valid_signature]]
==== `[.contract-item-name]#++_is_valid_signature++#++(self: @ComponentState, hash: felt252, signature: Span<felt252>)++ → bool` [.item-kind]#internal#

Validates the provided `signature` for the `hash`, using the account's current public key.

[#EthAccountComponent-Events]
==== Events

NOTE: The `guid` is computed as the hash of the public key, using the poseidon hash function.

[.contract-item]
[[EthAccountComponent-OwnerAdded]]
==== `[.contract-item-name]#++OwnerAdded++#++(new_owner_guid: felt252)++` [.item-kind]#event#

Emitted when a `public_key` is added.

[.contract-item]
[[EthAccountComponent-OwnerRemoved]]
==== `[.contract-item-name]#++OwnerRemoved++#++(removed_owner_guid: felt252)++` [.item-kind]#event#

Emitted when a `public_key` is removed.

== Presets

[.contract]
Expand Down Expand Up @@ -311,3 +516,70 @@ include::../utils/_class_hashes.adoc[]
==== `[.contract-item-name]#++constructor++#++(ref self: ContractState, public_key: felt252)++` [.item-kind]#constructor#

Sets the account `public_key` and registers the interfaces the contract supports.

[.contract]
[[EthAccountUpgradeable]]
=== `++EthAccountUpgradeable++` link:https://github.com/OpenZeppelin/cairo-contracts/blob/release-v0.8.1/src/presets/eth_account.cairo[{github-icon},role=heading-link]

```javascript
use openzeppelin::presets::EthAccountUpgradeable;
```

Account contract leveraging xref:#EthAccountComponent[EthAccountComponent].

NOTE: The `EthPublicKey` type is an alias for `starknet::secp256k1::Secp256k1Point`.

include::../utils/_class_hashes.adoc[]

[.contract-index]
.{presets-page}
--
{eth-account-upgradeable-class-hash}
--

[.contract-index]
.Constructor
--
* xref:#EthAccountUpgradeable-constructor[`++constructor(self, public_key)++`]
--

[.contract-index]
.Embedded Implementations
--
.EthAccountComponent

* xref:#EthAccountComponent-Embeddable-Impls[`++SRC6Impl++`]
* xref:#EthAccountComponent-Embeddable-Impls[`++PublicKeyImpl++`]
* xref:#EthAccountComponent-Embeddable-Impls[`++DeclarerImpl++`]
* xref:#EthAccountComponent-Embeddable-Impls[`++DeployableImpl++`]
* xref:#EthAccountComponent-Embeddable-Impls-camelCase[`++SRC6CamelOnlyImpl++`]
* xref:#EthAccountComponent-Embeddable-Impls-camelCase[`++PublicKeyCamelImpl++`]

.SRC5Component

* xref:api/introspection.adoc#SRC5Component-Embeddable-Impls[`++SRC5Impl++`]
--

[.contract-index]
.External Functions
--
* xref:#EthAccountUpgradeable-upgrade[`++upgrade(self, new_class_hash)++`]
--

[#EthAccountUpgradeable-constructor-section]
==== Constructor

[.contract-item]
[[EthAccountUpgradeable-constructor]]
==== `[.contract-item-name]#++constructor++#++(ref self: ContractState, public_key: EthPublicKey)++` [.item-kind]#constructor#

Sets the account `public_key` and registers the interfaces the contract supports.

[#EthAccountUpgradeable-external-functions]
==== External Functions

[.contract-item]
[[EthAccountUpgradeable-upgrade]]
==== `[.contract-item-name]#++upgrade++#++(ref self: ContractState, new_class_hash: ClassHash)++` [.item-kind]#external#

Upgrades the contract to a new implementation given by `new_class_hash`.
12 changes: 8 additions & 4 deletions docs/modules/ROOT/pages/presets.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
:account: xref:/api/account.adoc#Account[Account.cairo]
:erc20: xref:/api/erc20.adoc#ERC20[ERC20.cairo]
:erc721: xref:/api/erc721.adoc#ERC721[ERC721.cairo]
:account: xref:/api/account.adoc#Account[Account]
:eth-account-upgradeable: xref:/api/account.adoc#EthAccountUpgradeable[EthAccountUpgradeable]
:erc20: xref:/api/erc20.adoc#ERC20[ERC20]
:erc721: xref:/api/erc721.adoc#ERC721[ERC721]
:sierra-class-hashes: https://docs.starknet.io/documentation/architecture_and_concepts/Smart_Contracts/class-hash[Sierra class hashes]
:starkli: https://book.starkli.rs/introduction[starkli]
:wizard: https://wizard.openzeppelin.com[Wizard for Cairo]
Expand All @@ -23,11 +24,14 @@ List of available presets and their corresponding {sierra-class-hashes}.
NOTE: Class hashes were computed using {class-hash-cairo-version}.

|===
| Name | Compiled Class Hash
| Name | Sierra Class Hash

| `{account}`
| `{account-class-hash}`

| `{eth-account-upgradeable}`
| `{eth-account-upgradeable-class-hash}`

| `{erc20}`
| `{erc20-class-hash}`

Expand Down
3 changes: 2 additions & 1 deletion docs/modules/ROOT/pages/utils/_class_hashes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
:class-hash-cairo-version: https://crates.io/crates/cairo-lang-compiler/2.4.4[cairo 2.4.4]

// Class Hashes
:account-class-hash: 0x07a711d70338e05d7008fdf553207adc791297461fe3464b450fdc5f26f836ae
:account-class-hash: 0x0402765bcede84b1267a9d4658a7737c3c41a8caf6201984c3df95577c2298a3
:eth-account-upgradeable-class-hash: 0x03dda9bcfa854795d91d586b1a4275a68ab1ab185b33a5c00ce647c75875b0ff
:erc20-class-hash: 0x03af5816946625d3d2c94ea451225715784762050eba736f0b0ad9186685bced
:erc721-class-hash: 0x045c96d1b24c3dc060680e4bfd4bdc32161aefe8f8939cd4be3954c5d8688d75

Expand Down
6 changes: 4 additions & 2 deletions src/account.cairo
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod account;
mod dual_account;
mod dual_eth_account;
mod eth_account;
mod interface;
mod utils;

use account::AccountComponent;
use interface::AccountABIDispatcher;
use interface::AccountABIDispatcherTrait;
use eth_account::EthAccountComponent;
Loading

0 comments on commit 6d26b84

Please sign in to comment.