<p>As @kindofdev points out, it is very simple to burn tokens with Plutus scripts. It is a little more involved if you want some kinda of side-effect/record of burning tokens. Still shouldn't be <em>too</em> difficult, although Plutus takes some time to learn.</p>
<p><strong>Background</strong></p>
<p>There are no bounds on what can be sent to a Plutus Script, i.e. the script doesn't do any checks on new UTxOs at the address. This means you can't make the script do something just by sending something to it. The script only sees what is included in transactions spending the UTxOs at that address <em>or minted from the address</em>. It can see the entire transaction though, so multiple scripts can ensure something happens in other scripts atomically before validating.</p>
<p><strong>Why does that matter?</strong></p>
<p>You mention that you want to, for example, send an NFT to be replaced with an &quot;evolved&quot; NFT. You can definitely do this. In the simplest case, you can have your minting policy check that the old NFT is being burnt, at which point it will allow minting an &quot;evolved&quot; NFT.</p>
<p>Minting policies can't track any state though. They don't have a datum. So if you want to include any additional context for when tokens can be minted or evolved, that state must be stored on a separate validator script. This will require (at the very least) one validator script and one minting policy:</p>
<ol>
<li>A script for validating the burning of the original NFT</li>
<li>A minting policy for minting the new &quot;evolved&quot; NFT</li>
</ol>
<p>A transaction for evolving your NFT would spend a datum at Script #1 and replace it with a new datum (either identical or with some book-keeping data). The transaction would also mint the new NFT with Minting Policy #2.</p>
<p>The minting policy will only validate if the Script #1 Datum is spent in the transaction and the script will only validate if the old NFT is spent to the script and the new NFT is minted + any additional constraints you want to include.</p>
<p><strong>TL;DR</strong></p>
<p>You can have your &quot;evolve&quot; minting policy check if the pre-evolution NFT is being burned. If you need to include additional state/context for when that can happen, you can include that data on a separate, but inter-dependent, validator script.</p>
<p>Hope that helps. Might be worth looking at these other questions to give you more ideas:</p>
<p><a href="https://cardano.stackexchange.com/q/4647/1130">How to lock funds in a smart contract?</a></p>
<p><a href="https://cardano.stackexchange.com/q/4816/1130">Ensuring NFT collection uniqueness using counter as asset name?</a></p>
<p><a href="https://cardano.stackexchange.com/q/5965/1130">Can a smart contract only be interacted with once</a></p>

CC BY-SA 4.0
2022-03-08T10:21:41.503Z
I think you could also use two minting policies. One for the "normal" token that will enable it to be burnt and one for the "special" token that will only mint it if the normal token is burnt, no script involved. Both policies would be "invoked" in the same transaction
Mateus
CC BY-SA 4.0
2022-03-08T10:23:30.237Z
The problem I see is that neither scripts or policies have access to the tx metadata, where the NFT content is. This means the user could mint a special token with any characteristics he wanted (only constrained by the token name)
Mateus
CC BY-SA 4.0
2022-03-08T17:52:39.290Z
`One for the "normal" token that will enable it to be burnt and one for the "special" token that will only mint it if the normal token is burnt, no script involved`

Thanks. Good point. I'll note this. I think in many cases you'd want to follow the access token pattern to allow any bookkeeping, but there are cases where that is probably superfluous. 

WRT metadata. I'm actually unfamiliar with how metadata works. But I'm certain you can put whichever constraints you'd want by recording in the Validator Datum. They might not live on the token directly, but can still be recorded and read.
Mitchell Turner
CC BY-SA 4.0
2022-03-08T00:19:13.193Z
2022-03-08T18:19:09.660Z
2022-03-08T18:19:09.660Z
Mitchell Turner
<p>One option would be to define <strong>a validator which always fails</strong> and therefore, <strong>funds</strong> sitting at its address <strong>will be locked forever</strong>, ie, burned.</p>
<pre><code>{-# INLINABLE mkValidator #-}
mkValidator :: () -&gt; () -&gt; ScriptContext -&gt; Bool
mkValidator _ _ _ = False
</code></pre>
<p>Then, you can create a transaction which sends the NFT to the script address using <strong>mustPayToTheScript</strong>.</p>
<p>Hope this will be useful.</p>

CC BY-SA 4.0
2022-03-07T23:25:11.733Z
2022-03-07T23:25:11.733Z
kindofdev
<p>I am involved in an NFT project where there is a policy locking date coming up, but I would like to give the option burn/lock/self-destruct the NFT through a smart contract (SC) at any time after that point, and create a new 'evolved' NFT to give to the holder.</p>
<p>Is this 'locking/burn' possible in Plutus?</p>
<p>I don't want to create a burn wallet as there are obvious security concerns there with private keys. So I think an SC is the only way to go.</p>
<p>I am rather new to plutus so any help is appreciated.</p>

<plutus><smart-contract><nft>
Can you burn/lock/self-destruct NFTs in a a smart contract?
# Can you burn/lock/self-destruct NFTs in a a smart contract?

(Asked by: username_0 on 2022-03-07)

I am involved in an NFT project where there is a policy locking date coming up, but I would like to give the option burn/lock/self-destruct the NFT through a smart contract (SC) at any time after that point, and create a new 'evolved' NFT to give to the holder.

Is this 'locking/burn' possible in Plutus?

I don't want to create a burn wallet as there are obvious security concerns there with private keys. So I think an SC is the only way to go.

I am rather new to plutus so any help is appreciated.

**Tags:** plutus, smart-contract, nft

---

## 2 answers

### Answer by username_1 on 2022-03-08. Score: 1 | Accepted answer

As @kindofdev points out, it is very simple to burn tokens with Plutus scripts. It is a little more involved if you want some kinda of side-effect/record of burning tokens. Still shouldn't be *too* difficult, although Plutus takes some time to learn.

**Background**

There are no bounds on what can be sent to a Plutus Script, i.e. the script doesn't do any checks on new UTxOs at the address. This means you can't make the script do something just by sending something to it. The script only sees what is included in transactions spending the UTxOs at that address *or minted from the address*. It can see the entire transaction though, so multiple scripts can ensure something happens in other scripts atomically before validating.

**Why does that matter?**

You mention that you want to, for example, send an NFT to be replaced with an "evolved" NFT. You can definitely do this. In the simplest case, you can have your minting policy check that the old NFT is being burnt, at which point it will allow minting an "evolved" NFT.

Minting policies can't track any state though. They don't have a datum. So if you want to include any additional context for when tokens can be minted or evolved, that state must be stored on a separate validator script. This will require (at the very least) one validator script and one minting policy:

1. A script for validating the burning of the original NFT
2. A minting policy for minting the new "evolved" NFT

A transaction for evolving your NFT would spend a datum at Script #1 and replace it with a new datum (either identical or with some book-keeping data). The transaction would also mint the new NFT with Minting Policy #2.

The minting policy will only validate if the Script #1 Datum is spent in the transaction and the script will only validate if the old NFT is spent to the script and the new NFT is minted + any additional constraints you want to include.

**TL;DR**

You can have your "evolve" minting policy check if the pre-evolution NFT is being burned. If you need to include additional state/context for when that can happen, you can include that data on a separate, but inter-dependent, validator script.

Hope that helps. Might be worth looking at these other questions to give you more ideas:

[How to lock funds in a smart contract?](https://cardano.stackexchange.com/q/4647/1130)

[Ensuring NFT collection uniqueness using counter as asset name?](https://cardano.stackexchange.com/q/4816/1130)

[Can a smart contract only be interacted with once](https://cardano.stackexchange.com/q/5965/1130)

> **Comments:**
> **username_2**: I think you could also use two minting policies. One for the "normal" token that will enable it to be burnt and one for the "special" token that will only mint it if the normal token is burnt, no script involved. Both policies would be "invoked" in the same transaction  
> **username_2**: The problem I see is that neither scripts or policies have access to the tx metadata, where the NFT content is. This means the user could mint a special token with any characteristics he wanted (only constrained by the token name)  
> **username_1**: `One for the "normal" token that will enable it to be burnt and one for the "special" token that will only mint it if the normal token is burnt, no script involved`  Thanks. Good point. I'll note this. I think in many cases you'd want to follow the access token pattern to allow any bookkeeping, but there are cases where that is probably superfluous.   WRT metadata. I'm actually unfamiliar with how metadata works. But I'm certain you can put whichever constraints you'd want by recording in the Validator Datum. They might not live on the token directly, but can still be recorded and read.  

---

### Answer by username_3 on 2022-03-07. Score: 1

One option would be to define a validator which always fails and therefore, funds sitting at its address will be locked forever, ie, burned.
{-# INLINABLE mkValidator #-}
mkValidator :: () -> () -> ScriptContext -> Bool
mkValidator _ _ _ = False

Then, you can create a transaction which sends the NFT to the script address using mustPayToTheScript.
Hope this will be useful.


---

