Skip to content

Conversation

@tdelabro
Copy link
Collaborator

@tdelabro tdelabro commented Sep 16, 2025

Add a ContractAddress wrapper type that guarantee the felt it contains is a valid starknet contract address.
Contain some quality of like function for string conversion

Not a breaking change

Discussion:
@xJonathanLEI suggested we add ClassHash too
I chose to exclude addresses 0x0 and 0x1 from the normal ContractAddress flow. You can still build them with the unchecked one. Should we add constant ContractAddress::ZERO and ContractAddress::ONE to make those special case more explicit?
Do we want to allow them at all? Is there a risk to make some API unusable downstream if those value are entierly excluded?

@tdelabro tdelabro force-pushed the add-contract-address-type branch 2 times, most recently from bea90b3 to 02d6946 Compare September 16, 2025 15:15
Copy link
Collaborator

@gabrielbosio gabrielbosio left a comment

Choose a reason for hiding this comment

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

Some small comments

@gabrielbosio gabrielbosio self-requested a review September 23, 2025 21:50
@tdelabro
Copy link
Collaborator Author

@gabrielbosio do you have an opinion about the points I highlighted in the issue description?

@gabrielbosio
Copy link
Collaborator

@gabrielbosio do you have an opinion about the points I highlighted in the issue description?

It depends if we want to migrate the ContractAddress struct from the sequencer repo. If that's the case then the try_from method should only check for the upper bound like it's done here.

@tdelabro
Copy link
Collaborator Author

@dorimedini-starkware you are maintaining the sequencer repo?
What do you think?
Is there a reason not to have a common ContractAddress shared between the whole ecosystem (sequencer, starknet-rs, ...)

@dorimedini-starkware
Copy link
Collaborator

@dorimedini-starkware you are maintaining the sequencer repo? What do you think? Is there a reason not to have a common ContractAddress shared between the whole ecosystem (sequencer, starknet-rs, ...)

no reason I can think of, but this suggested implementation differs from ours in several ways, like:

  1. we have another indirection (ContractAddress(pub PatriciaKey(Felt)) vs. ContractAddress(Felt))
  2. we allow zero and one as valid addresses
  3. we use derive_more::Display and derive_more::Deref
  4. serde derives are not feature-gated

@tdelabro
Copy link
Collaborator Author

@dorimedini-starkware

  1. If I remember correctly the intermediate indirection to PatriciaKey is made useless by the fact that the internal value is pub. Which mean you can freely overstep the types restriction ContractAddress(PatriciaKey(<Some totally non valid Felt value>)). So by making the internal hidden, and using From/TryFrom rather than value.0 we will increase the type safety, without need for internal nesting of types
  2. This make sense. I believe we can ma them valid values, and just add a checking method is_regular_contract_address(&self) -> bool that allow for users to check if they are not receiving special address values. An alternative is to have a second type, in the same way we have NonZeroFelt, RegularContractAddress (or something). Maybe the best solution, as it is still optional, but provide the best protection for users willing to use it
  3. Sure I can add those quality of life impl
  4. You can just enable the feature and it will be the same. But it is a good practice to have non-core features requiring the import of depencies (like serde , num-traits, and so on) feature gated. It doesn't cost much and is a good practice.

@dorimedini-starkware
Copy link
Collaborator

@dorimedini-starkware

1. If I remember correctly the intermediate indirection to `PatriciaKey` is made useless by the fact that the internal value is `pub`. Which mean you can freely overstep the types restriction `ContractAddress(PatriciaKey(<Some totally non valid Felt value>))`. So by making the internal hidden, and using `From`/`TryFrom` rather than `value.0` we will increase the type safety, without need for internal nesting of types

2. This make sense. I believe we can ma them valid values, and just add a checking method `is_regular_contract_address(&self) -> bool` that allow for users to check if they are not receiving special address values. An alternative is to have a second type, in the same way we have `NonZeroFelt`, `RegularContractAddress` (or something). Maybe the best solution, as it is still optional, but provide the best protection for users willing to use it

3. Sure I can add those quality of life `impl`

4. You can just enable the feature and it will be the same. But it is a good practice to have non-core features requiring the import of depencies (like `serde` , `num-traits`, and so on) feature gated. It doesn't cost much and is a good practice.
  1. PatriciaKey is pub but it's internal Felt is not, and creating a PatriciaKey with an out of range Felt should panic. I'm not saying the safety changes, I'm saying changing this indirection will require wide refactors if and when we migrate our ContractAddress type
  2. .
  3. please do :)
  4. makes sense.

all in all I have no issue with this addition; it may take time for us to migrate to this new type though

@tdelabro
Copy link
Collaborator Author

@dorimedini-starkware so do you want this crate to also add a PatriciaKey type. Would it be helpful for you?

@dorimedini-starkware
Copy link
Collaborator

@dorimedini-starkware so do you want this crate to also add a PatriciaKey type. Would it be helpful for you?

I guess it would make the transition less painful, so sure.
We use PatriciaKey to describe an index in any of our state trees (only one of which is actually indexed by contract addresses) - the class tree and each storage tree also need to be bound by the patricia key limit

@tdelabro
Copy link
Collaborator Author

tdelabro commented Sep 30, 2025

@dorimedini-starkware going back to point 2.

using derive_more::Display, or manual impl end up being the same. So no worries here

Now regarding derive_more::Deref, we won't implement it and will ask you to use as_ref or into instead.
Indeed the Deref trait purpose is to create smart-pointers, to add on the native ownership semantic, not to perform implicit type conversion. I understand the attraction of having the compiler quietly do those for you, but this is not what this trait is designed for and can be surprising for the user.
It is a bit more verbose, but for the best.

0xLucqs
0xLucqs previously requested changes Oct 6, 2025
@dorimedini-starkware
Copy link
Collaborator

@dorimedini-starkware going back to point 2.

using derive_more::Display, or manual impl end up being the same. So no worries here

Now regarding derive_more::Deref, we won't implement it and will ask you to use as_ref or into instead. Indeed the Deref trait purpose is to create smart-pointers, to add on the native ownership semantic, not to perform implicit type conversion. I understand the attraction of having the compiler quietly do those for you, but this is not what this trait is designed for and can be surprising for the user. It is a bit more verbose, but for the best.

the point was to get a Felt by doing **address, but we can refactor usages, not an issue

@tdelabro tdelabro force-pushed the add-contract-address-type branch from 794750f to 0ec371c Compare October 15, 2025 17:14
@tdelabro tdelabro force-pushed the add-contract-address-type branch 2 times, most recently from 6143570 to 1a3ea40 Compare October 15, 2025 17:24
@tdelabro tdelabro mentioned this pull request Oct 17, 2025
@tdelabro tdelabro force-pushed the add-contract-address-type branch from 317fb75 to 4070b1c Compare October 21, 2025 21:12
@tdelabro tdelabro force-pushed the add-contract-address-type branch from 4070b1c to f849d1f Compare November 3, 2025 18:59
@tdelabro tdelabro force-pushed the add-contract-address-type branch from f849d1f to a25e4f9 Compare November 3, 2025 20:00
Copy link
Collaborator

@gabrielbosio gabrielbosio left a comment

Choose a reason for hiding this comment

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

Looks good overall, I've left some small suggestions

@tdelabro tdelabro requested a review from gabrielbosio November 4, 2025 18:54
Copy link
Collaborator

@gabrielbosio gabrielbosio left a comment

Choose a reason for hiding this comment

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

Looks good, left some minor comments

@0xLucqs 0xLucqs dismissed their stale review November 10, 2025 23:03

Because

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants