Transaction effects show many deleted objects while I did not delete any, where do these object IDs come from?

The transaction effects returned from a test_scenario::next_tx look as follows:

[debug] 0x2::test_scenario::TransactionEffects {
  created: [],
  written: [
    0x2::object::ID {
      bytes: @0xd726ecf6f7036ee3557cd6c7b93a49b231070e8eecada9cfa157e40e3f02e5d3
    }
  ],
  deleted: [
    0x2::object::ID {
      bytes: @0x4d44babdb1587e876cb7e6dfcb4740d153461f50769beb008f500d2803d1fce
    },
    0x2::object::ID {
      bytes: @0x195e3f73d1b403ac9e38bcb2f0ea031e3a967fb117c6565ec51d0e412642f579
    },
    0x2::object::ID {
      bytes: @0x2e3e3875f5248b0e1ab55294dd48d3c0bf8e78c9005eed4ae2cbb4f8a162e0a3
    },
    0x2::object::ID {
      bytes: @0x90c5264c9da2b340fdc9fbd15ad3f0a181a57afa7ae55b15a3c5dce6b31f45c8
    },
    0x2::object::ID {
      bytes: @0xeb2f43656d4bfab1b8a5235e55a3cc925eac4b8bd7cf2b1d3bb001c5a7fcac34
    }
  ],
  transferred_to_account: 0x2::vec_map::VecMap<0x2::object::ID, address> {
    contents: []
  },
  transferred_to_object: 0x2::vec_map::VecMap<0x2::object::ID, 0x2::object::ID> {
    contents: []
  },
  shared: [
    0x2::object::ID {
      bytes: @0xd726ecf6f7036ee3557cd6c7b93a49b231070e8eecada9cfa157e40e3f02e5d3
    }
  ],
  frozen: [],
  num_user_events: 0
}

I do not delete any objects in my last transaction.

  1. Is it correct to conclude that calling object::new(ctx) to get an id for a struct that does not have the key ability, creates an object and then deletes it?
  2. Only calling test_scenario::take_shared als gives 2 deleted objects. Where do these come from?
1 Like

Hey @GCB,

  1. Is it correct to conclude that calling object::new(ctx) to get an id for a struct that does not have the key ability, creates an object and then deletes it?

It does not, you will only see IDs in deleted for one of two reasons:

  • The UID was passed to object::delete.
  • The ID corresponds to a dynamic field, which get added/removed in response to the field being added/removed on a parent object.

If you just call object::new(ctx) and then don’t delete it, but store it somewhere, then it is considered to be “created and wrapped”. This state is not reflected in the current version of TransactionEffects (v1), but if you later unwrap that ID and delete, you will see that ID show up in unwrapped_then_deleted.

In TransactionEffects v2, you will also see created and wrapped IDs, because the effects separately track whether the ID was created and whether an object exists at that ID in global storage.

However, even in this case, an ID that was created and deleted within one transaction will still not show up in effects at all (rather than appearing as both created and deleted).

Only calling test_scenario::take_shared als gives 2 deleted objects. Where do these come from?

I’m not sure about this, I suspect the answer is related to your other question of where these other deletions came from. My theory is that your transactions involve dynamic fields, and you are adding/removing those, and the effects are reflecting that. (Note that Table, Bag, ObjectTable, ObjectBag, LinkedTable, TableVec all use dynamic fields under the hood, so using these could also produce these effects).

The easiest way to tell is if you could share a minimal example test module.

2 Likes