Skip to content

SIP: Remove the ID Leak Verifier - #73

Open
manolisliolios wants to merge 1 commit into
sui-foundation:mainfrom
manolisliolios:sip-remove-id-leak-verifier
Open

SIP: Remove the ID Leak Verifier#73
manolisliolios wants to merge 1 commit into
sui-foundation:mainfrom
manolisliolios:sip-remove-id-leak-verifier

Conversation

@manolisliolios

Copy link
Copy Markdown

Proposes removing the ID Leak Verifier, the bytecode pass that requires every object to be packed only with a freshly-minted UID.

This is an open request for feedback in an attempt to collect any scenarios that might get broken.

Proposes removing the Sui Move ID Leak Verifier bytecode pass, which
requires every object to be packed with a freshly-minted UID. The pass
is redundant with runtime enforcement and costs a hand-maintained
allow-list duplicated between the verifier and the Move compiler.

Removing it allows a UID extracted via unpack to be repacked into a new
object, enabling in-place type migration at a stable ObjectID.
@manolisliolios
manolisliolios force-pushed the sip-remove-id-leak-verifier branch from 3dd24cf to 99d605b Compare August 10, 2026 10:03
@manolisliolios
manolisliolios marked this pull request as ready for review August 10, 2026 20:02
@RandyPen

Copy link
Copy Markdown
Contributor

good idea

@admin-aftermath

admin-aftermath commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

I am in favor of this SIP for a few reasons:

  1. It solves this issue [move-std] Relaxing UID creation for sui::derived_object::claim MystenLabs/sui#24248; i.e., the ability to return a UID that can be used for creating an object.

I would much rather define a singular fun claim<K: copy + drop + store>(config: &mut Config, key: K): UID { ... } then have to expose a public(package) fun borrow_mut_id(config: &mut Config): &mut UID { ... } to derive objects across my package.

  1. I have always wanted the ability of being able to define a general type (e.g., struct Pool<phantom StateVx> { ... }) where the inner field is a generic type and can be upgraded while not needing to change the parent UID. For example, defining a Pool<StateV1> and being able to migrate this to a Pool<StateV2> where the UID is the same. This would be an interesting huge pattern for safe versioning.

One security consideration worth mentioning is how this will impact when the ObjectID -> StructTag is inferred onchain.

For example, in our oracle aggregator package we have a function like this

public fun update_price_feed<PriceObject: key>(
    price_feed_storage: &mut PriceFeedStorage,
    config: &Config,
    ...
    price_object: &PriceObject,
    ...
) {
    ...
    let price_feed = /* not relevant */;

    if (price_feed.from() != object::id(price_object)) abort EInvalidSourceObjectForFeed;
    ...
}

For context: a PriceFeedStorage encapsulates a singular symbol and may hold prices from many different sources (Pyth, Stork, etc). When initializing the PriceFeedStorage you need to specify the whitelisted PriceObject that can solely be used to update the price from that source; if you are familiar with Pyth core, this can be a PriceInfoObject.

There is an implicit UID -> type that we define here, as PriceObject is enforced to be a specific type in an upstream package (one for Pyth, one for Stork, etc) and that link is established in the new_price_feed function. This SIP would change the security assumptions of this exact pattern: no longer is the established UID -> type link guaranteed to remain onchain.

In all of our packages, this is the only occurrence of where we (1) hardcode an expected UID + (2) are generic over the type of UID. Almost always it is (1) w/ an explicit type.

All-in-all this would be a nice QoL improvement and unlock some cool patterns.

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.

3 participants