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

docs: src-5 implement #233

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 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
1 change: 1 addition & 0 deletions listings/src5_interface/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
6 changes: 6 additions & 0 deletions listings/src5_interface/Scarb.lock
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 = "src5_interface"
version = "0.1.0"
8 changes: 8 additions & 0 deletions listings/src5_interface/Scarb.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "src5_interface"
version = "0.1.0"
edition = "2023_11"

# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html

[dependencies]
4 changes: 4 additions & 0 deletions listings/src5_interface/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod user_account;

#[cfg(test)]
mod tests;
Comment on lines +3 to +4
Copy link
Contributor

Choose a reason for hiding this comment

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

You can add test module directly inside main module behind a test anchor

Copy link
Contributor

Choose a reason for hiding this comment

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

You moved test functions so you can remove tests module definition here

71 changes: 71 additions & 0 deletions listings/src5_interface/src/src5_interface.cairo
julio4 marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not valid cairo syntax, please refer to official documentation, or our counter example, and don't use AI generated content.

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use openzeppelin::account::interface::ISRC5_ID;
use openzeppelin::introspection::src5::SRC5Component;
use starknet::contract::ContractAddress;
use starknet::syscalls::call_contract_syscall;
use starknet::alloc::arrays::ArrayTrait;
use starknet::core::keccak::starknet_keccak;
// Define ISRC5 interface
trait ISRC5 {
fn supports_interface(interface_id: felt252) -> bool;
}
// Define example interfaces
trait IExample1 {
fn example_function1(param1: felt252) -> felt252;
}
trait IExample2 {
fn example_function2(param1: felt252, param2: felt252) -> felt252;
}
// Storage structure
struct Storage {
public_key: felt252,
src5: SRC5Component::Storage,
}
// Event definitions
enum Event {
AccountCreated: felt252,
SRC5Event: SRC5Component::Event,
}
// Contract implementation
@contract
namespace ExampleContract {
struct State {
storage: Storage,
}
// Constructor
#[constructor]
fn constructor(ref state: State, public_key: felt252) {
state.storage.public_key = public_key;
emit(Event::AccountCreated(public_key));
state.storage.src5.register_interface(ISRC5_ID);
}
// Implementation of ISRC5
#[external]
fn supports_interface(ref state: State, interface_id: felt252) -> bool {
state.storage.src5.supports_interface(interface_id)
}
// Implementation of IExample1
#[external]
fn example_function1(param1: felt252) -> felt252 {
// Your implementation here
return starknet_keccak(param1.to_bytes());
}
// Implementation of IExample2
#[external]
fn example_function2(param1: felt252, param2: felt252) -> felt252 {
// Your implementation here
return param1 + param2;
}
// Additional functions or internal logic can be added here
}
// ISRC5 trait implementation
impl ISRC5 for State {
fn supports_interface(ref self, interface_id: felt252) -> bool {
self.storage.src5.supports_interface(interface_id)
}
}



#[cfg(test)]
mod tests { // TODO
}
18 changes: 18 additions & 0 deletions listings/src5_interface/src5_snippet.py
Copy link
Contributor

Choose a reason for hiding this comment

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

Wrong format, please try to run the code before pushing it

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from starkware.starknet.public.abi import starknet_keccak

signatures = [
'supports_interface(felt252)->E((),())',
'is_valid_signature(felt252,Array<felt252>)->E((),())',
'__execute__(Array<(ContractAddress,felt252,Array<felt252>)>)->Array<(@Array<felt252>)>',
'__validate__(Array<(ContractAddress,felt252,Array<felt252>)>)->felt252',
'__validate_declare__(felt252)->felt252'
]

def compute_interface_id():
interface_id = 0x0
for sig in signatures:
function_id = starknet_keccak(sig.encode())
interface_id ^= function_id
print('IAccount ID:', hex(interface_id))

compute_interface_id()
2 changes: 1 addition & 1 deletion src/advanced-concepts/account_abstraction/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ This replaces EOA with Account Contracts, which are smart contracts that impleme

On Starknet, Account Abstraction is natively supported, and all accounts are Account Contracts.

In this section we will how to implement an Account.
In this section we will show how to implement an Account.
<!-- and common customizations that can be done to it. -->
94 changes: 94 additions & 0 deletions src/src5 implementation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
## SRC-5: A comprehensive Overview

SRC-5 is a standard for smart contract interface introspection in Starknet, inspired by the [Ethereum ERC-165 standard](https://eips.ethereum.org/EIPS/eip-165). It provides a standardize method for contracts to publish and detect the interfaces they implement, ensuring consistent interaction. For more information, refer to the [SRC-5 specification](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-5.md#simple-summary).

### SRC-5 offers a standardized method to:

* Identify interfaces.
* Publish the interfaces a contract implements.
* Detect if a contract implements any given interface. (including SRC-5)

### Interface Definition
julio4 marked this conversation as resolved.
Show resolved Hide resolved

An interface is a set of function signatures with specific type parameters, represented as traits. These traits are meant to be implemented externally by compliant contracts.

Example:


```rust
trait IMyContract {
fn foo(some: u256) -> felt252;
}
```

With Cairo, generic traits can represent a set of interfaces:

```rust
#[starknet::interface]
trait IMyContract<TContractState, TNumber> {
fn foo(self: @TContractState, some: TNumber) -> felt252;
}
```

#### Extended Function Selector
Copy link
Contributor

Choose a reason for hiding this comment

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

missing linebreak


The function selector in Starknet is the starknet_keccak hash of the function name. The extended function selector, for SRC-5, is the starknet_keccak hash of the function signature:

`fn_name(param1_type,param2_type,...)->output_type`

For example, for a function with zero parameters and no return value: `fn_name()`

Special Types:

* Tuples: (elem1_type,elem2_type,...)
* Structs: (field1_type,field2_type,...)
* Enums: E(variant1_type,variant2_type,...)

#### Interface Identification

An interface identifier is the XOR of all extended function selectors in the interface.

This Python code computes the interface id:

```rust
{{#rustdoc_include ../../../listings/src5_interface/src5_snippet.py}}
```

For more details refer to the [SRC-5 repository on GitHub](https://github.com/ericnordelo/src5-rs).

### Publishing and Detecting Interfaces

To comply with SRC-5, a contract must implement the ISRC5 trait:

```rust
trait ISRC5 {
fn supports_interface(interface_id: felt252) -> bool;
}
```

The supports_interface function returns a boolean that indicate if the contract implements a given interface.

The interface identifier for ISRC5 is

```0x3f918d17e5ee77373b56385708f855659a07f75997f365cf87748628532a055```

#### Detecting SRC-5 Implementation
julio4 marked this conversation as resolved.
Show resolved Hide resolved

To check if a contract implements SRC-5:

* Call `contract.supports_interface(0x3f918d17e5ee77373b56385708f855659a07f75997f365cf87748628532a055)`.
* If the call fails or returns false, the contract does not implement SRC-5.
* Otherwise, it implements SRC-5.

#### Detecting Any Given Interface
julio4 marked this conversation as resolved.
Show resolved Hide resolved

* Confirm if the contract implements SRC-5.
* If confirmed, `call supports_interface(interface_id)` to check for specific interfaces.
* If not, manually inspect the contract methods.

Below shows a contract implementing the `SRC5` to expose the `Isupports_interface(interface_id)`:

```rust
{{#rustdoc_include ../../../listings/src5_interface/src/src5_interface.cairo}}
```