<p>Lars already gave a pretty good answer to the randomness problem <a href="https://cardano.stackexchange.com/questions/389/randomness-in-a-smart-contract?rq=1">here</a>. Basically, an oracle is probably the easiest and best way to achieve randomness with entropy.</p>
<p>If you want to avoid an oracle, you might be able to seed your randomness with the transaction ID. There could be some concerns with reverse engineering there, but depending on the scale of your project those concerns might be unrealistic.</p>

CC BY-SA 4.0
2022-02-08T01:36:27.160Z
Supouse the oracle gives the random number (in some sense not specified), then? what should i do ? what transactions should i do and how?
Alicia Basilio
CC BY-SA 4.0
2022-02-10T08:54:09.747Z
There’s a chance I misunderstood you, but my assumption here is that your third paragraph constitutes an issue you want to avoid, not a feature you want to include. If that’s the case, I think you only need 2 transactions.

The first would be a List transaction which allows you to place an NFT you want to sell in a UTXO at the vending machine's script address.

The second would be a Buy transaction, which allows anyone to pay an amount to get NFTs from the machine. Here you use your oracle to decide which NFT UTXOs to consume, sending the NFTs they contain back to the buyer.
Sam Delaney
CC BY-SA 4.0
2022-02-10T12:19:44.697Z
Yes I think  two transactions are needed
Alicia Basilio
CC BY-SA 4.0
2022-02-08T01:26:16.637Z
2022-02-08T01:26:16.637Z
Sam Delaney
<p>In Cardano, all transactions are deterministic, which means you can not have unpredictable randomness, even if you inject an entropy source from, lets say and Oracle, the user who constructs the transaction will always know in advance the outcome, all variables are known at TX construction time. He then can choose to not sign/send the transaction if the outcome is undesirable.</p>
<p>One way to solve this problem, is to obfuscate from the user the meaning of the outcome, he will know which NFT he is getting (Asset Name), but maybe the NFT metadata is not revealed until after the NFT has been bought. Although this would require some off-chain business logic (when NFT A is bought, publish NFT A metadata). This would work better by committing to the metadata by pre-publishing a Hash of it, so the buyer knows the metadata that is being published was not changed after the fact. Sadly CIP-0025 doesn't allow to do this via smart contract because it relies on transaction metadata which cannot be read from smart contracts, so it would have to be done via an honor system.</p>
<p>Another approach would be to use a model similar to the current liquidity pools (I.E Minswap), The users initiate a buy order by sending ADA to a contract address, then a batcher would continuously select these orders from contract A, and execute the buy by taking the NFTs from contract B and sending it to the users. At this point, the batcher could use an Oracle as the entropy source, or the UTXO ID hashed with some secret value to pick the NFT to send to the user. This would still require some off-chain code (the batcher), but at least you could program some fairness into contracts A and B, for example, by preventing anyone to claim the money the user deposited in the buy order without sending the NFT back. (claiming the ADA in buy Order would require an NFT of a specific policy to be returned to the sender). Extra logic could be put in place to for example, allow the original sender to claim back its ADA if the order has not been executed in X amount of time.</p>

CC BY-SA 4.0
2022-07-08T07:47:01.233Z
In addition to this great answer, one could also use a VRF to provide provable randomness. This is more involved, though.
Fermat
CC BY-SA 4.0
2022-07-08T08:13:19.720Z
I also think the hash scheme can work. Pre mint your NFT's and create tokens that are named the hash of the NFT's with a nonce. Sell tokens that represent these hashes. Later reveal the nonce that give access to the unique name the NFT's has (this is visible for plutus in a transaction). Users can now claim their NFT.
Fermat
CC BY-SA 4.0
2022-07-08T08:23:13.793Z
This is a great idea @Fermat :)
AngelCastillo
CC BY-SA 4.0
2022-07-08T08:24:37.680Z
You should post this as a separate answer, I think this approach would work great!
AngelCastillo
CC BY-SA 4.0
2022-07-08T09:36:03.993Z
First option is not feasible.. metadata URL is not a function like in Solidity contracts. metadata is the hash of the mint. I was thinking on using a hash of the blocktimestamp togueter with the address to generate pseudoradomless.. For Real Randomless..  The use of an oracle is inevitable with out any doubt.
Alicia Basilio
CC BY-SA 4.0
2022-07-08T11:10:03.870Z
@AliciaBasilio, the Cardano blockchain is passive and fully deterministic, validators only check that transactions are valid. In practice, this means that validators do not fetch additional data that is not already in the signed transaction. The block timestamp is thus something you cannot access. What you do have in a transaction is the validity interval, which is the time for which a transaction is valid.
Fermat
CC BY-SA 4.0
2022-07-08T11:24:54.030Z
You are right! me bad about that
Alicia Basilio
CC BY-SA 4.0
2022-07-08T13:53:12.310Z
Really like the idea with the transforming metadata! You could 1) sell (via smart contract) a lootbox-style NFT with a hash of the future metadata in its metadata, and after a purchase 2) re-create and burn a clone of the sold NFT using the actual metadata in its mint tx - this way you would transform the lootbox nft right after the sale into the real nft without further transactions on the buyer side. Only requirement is that the policy still allows re-minting for long enough. And step 2 is triggered off-chain by your server. Or am I missing anything here?
sean
CC BY-SA 4.0
2022-07-08T07:25:15.977Z
2022-07-08T07:25:15.977Z
AngelCastillo
<p>I am building a vending machine where the users have to first send ADA to some address then my backend selects NFTs and sends back to the user who payed. I have been wondering if is there a way to do it using smart contracts?</p>
<p>The NFTs are all locked in a contract and we make the tx to the contract from the front end to unlock them. But my problem is: How could I make that the NFTs are randomly seleceted?</p>
<p>The front end might randomly select some. But when the Browser Wallet ask for sign the transaction it will show which NFTs are selected and then the user might decline or accept the transaction depending of the NFTs.</p>
<p>The main problem is that NFT must be randomly selected. How can I solve this problem?</p>

<smart-contract>
How to do a plutus smart contract vending machine?
# How to do a plutus smart contract vending machine?

(Asked by: username_0 on 2022-02-06)

I am building a vending machine where the users have to first send ADA to some address then my backend selects NFTs and sends back to the user who payed. I have been wondering if is there a way to do it using smart contracts?

The NFTs are all locked in a contract and we make the tx to the contract from the front end to unlock them. But my problem is: How could I make that the NFTs are randomly seleceted?

The front end might randomly select some. But when the Browser Wallet ask for sign the transaction it will show which NFTs are selected and then the user might decline or accept the transaction depending of the NFTs.

The main problem is that NFT must be randomly selected. How can I solve this problem?

**Tags:** smart-contract

---

## 2 answers

### Answer by username_2 on 2022-07-08. Score: 3

In Cardano, all transactions are deterministic, which means you can not have unpredictable randomness, even if you inject an entropy source from, lets say and Oracle, the user who constructs the transaction will always know in advance the outcome, all variables are known at TX construction time. He then can choose to not sign/send the transaction if the outcome is undesirable.

One way to solve this problem, is to obfuscate from the user the meaning of the outcome, he will know which NFT he is getting (Asset Name), but maybe the NFT metadata is not revealed until after the NFT has been bought. Although this would require some off-chain business logic (when NFT A is bought, publish NFT A metadata). This would work better by committing to the metadata by pre-publishing a Hash of it, so the buyer knows the metadata that is being published was not changed after the fact. Sadly CIP-0025 doesn't allow to do this via smart contract because it relies on transaction metadata which cannot be read from smart contracts, so it would have to be done via an honor system.

Another approach would be to use a model similar to the current liquidity pools (I.E Minswap), The users initiate a buy order by sending ADA to a contract address, then a batcher would continuously select these orders from contract A, and execute the buy by taking the NFTs from contract B and sending it to the users. At this point, the batcher could use an Oracle as the entropy source, or the UTXO ID hashed with some secret value to pick the NFT to send to the user. This would still require some off-chain code (the batcher), but at least you could program some fairness into contracts A and B, for example, by preventing anyone to claim the money the user deposited in the buy order without sending the NFT back. (claiming the ADA in buy Order would require an NFT of a specific policy to be returned to the sender). Extra logic could be put in place to for example, allow the original sender to claim back its ADA if the order has not been executed in X amount of time.

> **Comments:**
> **username_3**: In addition to this great answer, one could also use a VRF to provide provable randomness. This is more involved, though.  
> **username_3**: I also think the hash scheme can work. Pre mint your NFT's and create tokens that are named the hash of the NFT's with a nonce. Sell tokens that represent these hashes. Later reveal the nonce that give access to the unique name the NFT's has (this is visible for plutus in a transaction). Users can now claim their NFT.  
> **username_2**: This is a great idea @Fermat :)  
> **username_2**: You should post this as a separate answer, I think this approach would work great!  
> **username_0**: First option is not feasible.. metadata URL is not a function like in Solidity contracts. metadata is the hash of the mint. I was thinking on using a hash of the blocktimestamp togueter with the address to generate pseudoradomless.. For Real Randomless..  The use of an oracle is inevitable with out any doubt.  
> **username_3**: @AliciaBasilio, the Cardano blockchain is passive and fully deterministic, validators only check that transactions are valid. In practice, this means that validators do not fetch additional data that is not already in the signed transaction. The block timestamp is thus something you cannot access. What you do have in a transaction is the validity interval, which is the time for which a transaction is valid.  
> **username_0**: You are right! me bad about that  
> **username_4**: Really like the idea with the transforming metadata! You could 1) sell (via smart contract) a lootbox-style NFT with a hash of the future metadata in its metadata, and after a purchase 2) re-create and burn a clone of the sold NFT using the actual metadata in its mint tx - this way you would transform the lootbox nft right after the sale into the real nft without further transactions on the buyer side. Only requirement is that the policy still allows re-minting for long enough. And step 2 is triggered off-chain by your server. Or am I missing anything here?  

---

### Answer by username_1 on 2022-02-08. Score: 0

Lars already gave a pretty good answer to the randomness problem [here](https://cardano.stackexchange.com/questions/389/randomness-in-a-smart-contract?rq=1). Basically, an oracle is probably the easiest and best way to achieve randomness with entropy.

If you want to avoid an oracle, you might be able to seed your randomness with the transaction ID. There could be some concerns with reverse engineering there, but depending on the scale of your project those concerns might be unrealistic.

> **Comments:**
> **username_0**: Supouse the oracle gives the random number (in some sense not specified), then? what should i do ? what transactions should i do and how?  
> **username_1**: There’s a chance I misunderstood you, but my assumption here is that your third paragraph constitutes an issue you want to avoid, not a feature you want to include. If that’s the case, I think you only need 2 transactions.  The first would be a List transaction which allows you to place an NFT you want to sell in a UTXO at the vending machine's script address.  The second would be a Buy transaction, which allows anyone to pay an amount to get NFTs from the machine. Here you use your oracle to decide which NFT UTXOs to consume, sending the NFTs they contain back to the buyer.  
> **username_0**: Yes I think  two transactions are needed  

---

