-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BREAKING CHANGE: Optimize signers model for storage and extend account initializer - Bump version to v001.000.000 - Initializer: Support initializing advanced signer types, multisig, and daily withdrawal limit on account deployment - Initializer: Support deployment from deploy syscall (external deployer, not via DEPLOY_ACCOUNT) - Signers: Save Poseidon(pub key) instead of flattened pub key to optimize storage (i.e., every signer is represented as 1 felt) - Changes signature structure for advanced signer types since public key is not directly stored - Signers: Add optimized WebAuthn support (currently uses Cairo 0 SHA256 lib until an optimized Cairo version is available) - Multisig: Generalize support to more than 2 signers (i.e., allow multiple hardware signers in the same account) - Daily withdrawal limit: A new optional feature that allows relaxation of signing security requirements for low-value transactions (uses mySwap CL TWAP for asset prices) - Outside execution: SNIP-9 version 2 support
- Loading branch information
1 parent
a781740
commit e8753ad
Showing
83 changed files
with
60,674 additions
and
437,495 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -133,3 +133,6 @@ dmypy.json | |
# nile | ||
artifacts/ | ||
node.json | ||
|
||
*.DS_Store | ||
*.swp |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,120 @@ | ||
# Braavos Account Contract | ||
# Braavos Account Contract v1.0.0 | ||
|
||
## MAINNET ALPHA DISCLAIMER | ||
#### Class Hashes | ||
*Braavos Account* - `0x00816dd0297efc55dc1e7559020a3a825e81ef734b558f03c83325d4da7e6253` | ||
|
||
The Braavos Account is in alpha stage, as well as the StarkNet network itself. | ||
*Braavos Base Account* - `0x013bfe114fb1cf405bfc3a7f8dbe2d91db146c17521d40dcf57e16d6b59fa8e6` | ||
|
||
Things can break and in extreme cases can lead to loss of funds. The contract code have | ||
not yet been audited, the wallet code as well as the contracts themselves can be upgraded | ||
without a timelock. | ||
## Architecture | ||
|
||
## Design | ||
### Deployment | ||
|
||
The Braavos account contract is comprised of 3 main modules: | ||
Braavos account deployment enables account addresses to be dependent only on the Stark public key while still supporting additional initialization parameters and using the most up-to-date | ||
account implementation class hash. This is achieved by: | ||
|
||
1. Basic account functionality - validation and execution of Multicall based on | ||
OpenZeppelin's implementation. Can be found under `src/account`. | ||
2. Signer management - adding / removing of additional signers, namely the secp256r1-based | ||
Hardware Signer. Can be found under `src/signers` | ||
3. Multisig - implementation of M of N signers for transaction execution. Currently | ||
supports 2 of 2. Can be found under `src/multisig` | ||
1. Having a base implementation class hash that rarely changes (`src/presets/braavos_base_account.cairo`). Account deployments should always use this class hash. | ||
2. Send additional initialization parameters via the deployment signature instead of constructor params. | ||
3. Additional initialization parameters are signed and verified in the base implementation (see `assert_valid_deploy_base`). | ||
4. After validation, the base implementation replaces the underlying implementation to the latest one via a `replace_class_syscall` (`src/presets/braavos_account.cairo`) and the actual implementation initializer is called. | ||
|
||
This account contract is intended to be used as an implementation of a Proxy contract. | ||
We've used OpenZeppelin's Proxy implementation for this purpose. | ||
NOTE: The actual account implementation is not expected to be directly deployed and therefore its constructor panics. | ||
|
||
### Signer Management | ||
### Signers (`src/signers/`) | ||
|
||
When adding an additional signer, a _Hardware Signer_ or _Protected Signer_, the basic | ||
seed-based signer cannot sign transactions anymore besides a request to remove the | ||
additional signer and revert back to seed-based signer. The request is time-delayed | ||
(currently for 4 days). | ||
The Braavos account supports 3 different types of signers: | ||
|
||
### Multisig | ||
1. _Stark Signer_ - the native signer based on the Stark friendly curve. | ||
2. _Hardware Signer_ - Uses the physical device secure enclave to sign - based on the secp256r1 curve. | ||
3. _Webauthn Signer_ - Uses the physical device [Webauthn protocol](https://w3.org/TR/webauthn/) (aka Passkeys) implementation to sign - also based on the secp256r1 curve with a webauthn compatible signature format. | ||
|
||
The account can be moved into Multisig mode (currently supports 2 of 2) and it will not | ||
execute any transaction before the 2 signers defined in the account sign the transaction. | ||
The seed can request to disable multisig with a time-delay (currently 4 days). | ||
The native Stark signer is added by default on account deployment and is usually derived from the seed phrase. | ||
|
||
## Building | ||
The _Hardware Signer_ and _Webauthn Signer_ are considered to be _Strong Signers_ as they facilitate 2FA. | ||
When a _Strong Signer_ is added to the account the default _Stark Signer_ is disabled and not allowed to issue transactions. Only a _Strong Signer_ can. | ||
|
||
### Account Contract | ||
Note that an account can have both _Hardware Signer_ and _Webauthn Signer_ defined, in which case, any of them can sign as a 'Strong Signer' in the account. | ||
|
||
> nile compile --directory src/account | ||
#### Multisig | ||
|
||
### Proxy Contract | ||
In addition, a multisig threshold can be enabled and support _m-of-n_ signer threshold in order to execute a transaction. | ||
When an account have both _Hardware signer_ and _Webauthn signer_ defined, then both of them MUST be present in the multisig. | ||
|
||
> nile compile --directory lib/openzeppelin/upgrades/ | ||
#### Deferred Removal of _Strong Signers_ and _Multisig_ | ||
|
||
## Testing | ||
When there is a _Strong Signer_ defined in the account, the _Stark Signer_ role is reduced to removing all _Strong Signers_ and _Multisig_ with a time lock. | ||
The purpose of this mechanism is to allow the user to recover access to his account even if he lost access to the device containing his _Strong Signer_. | ||
The time-lock guarantees that the user have ample time to respond in case his seed phrase was stolen and an attacker tries to remove _Strong Signer_ protection | ||
and take over the account. | ||
|
||
### Running End-to-End tests | ||
The default time lock is defined to be 4 days. | ||
|
||
> pytest -n auto tests/ | ||
#### Signature Format | ||
|
||
The signature format is as follows: | ||
```[ signer #1 sig #1, signer #2 sig, signer #3 sig, ... ]``` | ||
|
||
Where each instance of a _signer sig_ is: | ||
```[ signer type, signer pub key, ...actual signature fields]``` | ||
|
||
Some important details to note here: | ||
|
||
1. We send the `signer pub key` since each signer is saved in the account as a single `felt252` - _guid_. When verifying a signature, the _guid_ is | ||
calculated from the public key and we verify that it matches one of the guids that are saved in the account. | ||
For the _Hardware Signer_ and _Webauthn Signer_ the guid is `poseidon(secp256r1 pub key)` | ||
2. `Signer type` indicates in which signer list we should look for the computed _guid_. The applicable types are: | ||
_Stark Signer_: *1*, _Hardware Signer_: *2*, _Webauthn Signer_: *5* | ||
|
||
3. Since currently only the default _Stark Signer_ is supported, when sending a Stark signature there is no need to send the `pub key` together with the signature. In this scenario there are 2 possible formats: | ||
- The native `(r, s)` format for compatibility with tooling and SDKs | ||
- ```[ signer type (==1), r, s]``` | ||
|
||
4. More than one signer can be sent in the signature array to allow for `m-of-n` signers in _Multisig_ mode. | ||
|
||
### Daily Withdrawal Limit (`src/dwl/`) | ||
|
||
The Daily Withdrawal Limit is a feature that allows relaxtion of _Strong Signer_ and _Multisig_ requirements | ||
for certain types of transactions. All applicable transactions are analyzed for their value (actual token value + gas) and are accumulated per calendar day. While the | ||
accumulated amount is under a certain threshold, a weaker signer can be used to validate enabling lower fees and simpler User Experience for lower value transactions. | ||
|
||
The Withdrawal Limit thresholds are set in USDC. For example, to set a low withdrawal limit of 100$, withdrawal limit should be set to `100 * 10**6`. We use | ||
MySwap-CL's TWAP pricing to determine the value of an applicable transaction in USDC terms. | ||
|
||
Applicable transactions are either `transfer` or `approve` transactions on the most commonly used tokens (ETH, USDC, USDT, DAI, WBTC) or a whitelisted set of protocol entrypoints. | ||
This whitelist for both tokens and contract entrypoints can be configured manually using the `update_rate_config` entrypoint | ||
|
||
Two thresholds can be set as part of the daily withdrawal limit: | ||
|
||
1. Low Limit - controls under which accumulated daily transaction value the _Stark Signer_ can sign even if there are _Strong Signers_ or _Multisig_ defined in the account. | ||
2. High Limit - Defines under which accumulated daily transaction value a _Strong Signer_ can be used even if _Multisig_ is defined | ||
|
||
When a transaction is validated without utilizing the Daily Withdrawal Limit's use of a weaker signer, | ||
i.e. using _Strong Signer_ even though Daily Withdrawal Limit allows usage of _Stark Signer_ for that transaction | ||
then the transaction value is not accumulated towards the Withdraw Limit. | ||
|
||
### Outside Execution (`src/outside_execution/`) | ||
This feature is intended to allow different protocols to submit transactions on behalf of the user, given the user had signed the appropriate transactions beforhand. This contract implements [SNIP-9 version 2](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-9.md). | ||
|
||
## Building and Testing | ||
|
||
### Build | ||
|
||
This repo is built using [Scarb v2.5.1](https://docs.swmansion.com/scarb/). After installation, run: | ||
> scarb build | ||
### Tests | ||
|
||
Prerequisites: | ||
1. Install Python requirements | ||
> pip install -r requirements.txt | ||
2. Setup [starknet-devnet-rs](https://github.com/0xSpaceShard/starknet-devnet-rs) | ||
3. Define `STARKNET_DEVNET` env variable to point to `starknet-devnet-rs` executable | ||
|
||
To run tests: | ||
> | ||
> pytest | ||
## Acknowledgements | ||
- This project utilzes 2 separate implementations of SHA256 for pre/post regenesis support: | ||
- Cairo 0 implementation (as a library call) by the Cartridge team: [cairo-sha256](https://github.com/cartridge-gg/cairo-sha256) | ||
- Cairo implementation from the [Alexandria](https://github.com/keep-starknet-strange/alexandria) project | ||
|
||
## Credits | ||
1. Thanks to the OpenZeppelin team for providing reference implementations for both the basic account functionality and the Proxy pattern at https://github.com/OpenZeppelin/cairo-contracts | ||
2. Thanks to EulerSmile for providing the reference `secp256k1` implementation - https://github.com/EulerSmile/common-ec-cairo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Code generated by scarb DO NOT EDIT. | ||
version = 1 | ||
|
||
[[package]] | ||
name = "braavos_account" | ||
version = "1.0.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[package] | ||
name = "braavos_account" | ||
version = "1.0.0" | ||
|
||
[dependencies] | ||
starknet = ">=2.3.1" | ||
|
||
[[target.starknet-contract]] | ||
allowed-libfuncs-list.name = "all" | ||
casm-add-pythonic-hints = true | ||
casm = true | ||
|
Oops, something went wrong.