Account Storage

In Cadence, accounts (which each have an address) can store and own their own data.

To do so, you need to have special authorized privileges on an &Account type. In a transaction, you can specify and thus be granted these privileges in the prepare stage to make it clear to the user what you intend to do.

Data is stored at “storage paths”. You use the save function to store data, load to bring it out of storage, and borrow to get a reference to it.

cadence
		
			// Contract file: Test.cdc
// Deployed to 0x01
access(all) contract Test {

   access(all) resource NFT {
      access(all) let id: UInt64
      access(all) let rarity: String
      
      init(rarity: String) {
         self.id = self.uuid
         self.rarity = rarity
      }
   }

   access(all) fun createNFT(rarity: String): @NFT {
      let nft <- create NFT(rarity: rarity)
      return <- nft
   }

}
		 
	
cadence
		
			// Transaction file: store_nft.cdc
import Test from 0x01

transaction(rarity: String) {

   // `SaveValue` is a special privledge you specify when you want
   // to call the `save` function on an account (store data to the account)
   prepare(signer: auth(SaveValue) &Account) {
      let nft <- Test.createNFT(rarity: rarity, name: name)
      // moves the NFT resource into storage at `/storage/MyNFT`
      signer.storage.save(<- nft, to: /storage/MyNFT)

      /*
       trying to store an asset there again would cause an error,
       because only one thing can be stored at a path at a time

       let nft2 <- Test.createNFT(rarity: rarity, name: name)
       signer.save(<- nft2, to: /storage/MyNFT)
      */
   }

   execute {
      
   }
}
		 
	
cadence
		
			// Transaction file: borrow_nft.cdc
import Test from 0x01

transaction() {

   // `BorrowValue` is a special privledge you specify when you want
   // to call the `borrow` function on an account (get a reference to
   // data in the account)
   prepare(signer: auth(BorrowValue) &Account) {
      let nft: &Test.NFT = signer.storage.borrow<&Test.NFT>(from: /storage/MyNFT)
                        ?? panic("A Test.NFT type does not exist at the specified storage path.")
      log(nft.name)
   }

   execute {
      
   }
}
		 
	
cadence
		
			// Transaction file: destroy_nft.cdc
import Test from 0x01

transaction() {

   // `LoadValue` is a special privledge you specify when you want
   // to call the `load` function on an account (take the
   // data out of storage)
   prepare(signer: auth(LoadValue) &Account) {
      let nft: Test.NFT? <- signer.storage.load<@Test.NFT>(from: /storage/MyNFT)
      destroy nft
   }

   execute {
      
   }
}