Can someone explain how smart contracts work?

I recently read a twitter thread by the user KtorZ which Charles retweeted.

Link: https://twitter.com/KtorZ/status/1439168735810555906

If i’m not mistaken, this means that smart contract code will never exist nor be executed on the validator nodes. Instead, only the input and the output of that code will be validated on chain and then sent to wherever the smart contract is hosted for processing.

For example, say I create a sports betting smart contract for a football game. The contract is sent a transaction which contains the bet amount and which team they think will win. After the game is over, the smart contract executes logic to determine the winners and sends the appropriate amount back to them. Im very confused as to how this could be implemented on Cardano given that I would be hosting this code say for instance on my home computer and not on the validator nodes. I have posted some questions below.

How exactly would the validator nodes know where to forward the validated input transactions? Would I need to expose my smart contract via an API?

How are users of my contract able to audit and verify that the smart contract code I am running is not malicious or faulty if it is not distributed on chain?

On Ethereum, when a transaction is minted into a block, all of the other validator nodes on the network not only validate the transactions, but run the smart contract code as well, thus validating the contract execution. I presume this does not happen on Cardano. Does this mean that a contract execution happens once and only once on the server hosting the contract off chain?

A lot of what I said here is my current understanding of how smart contracts work on Cardano and I know my understanding may not be correct so PLEASE help me out in correcting me where I am wrong.

Thanks,

namefacedude

On Cardano a “smart contract” consists of on-chain code (e.g., Plutus or Marlowe) that validates the spending of funds in the contract. (This is why “programmable validator” is an accurate term.) Sometimes the term “smart contract” also refers to off-chain code (in any language) that helps build transactions that are sent to the smart contract. The on-chain code makes sure that transactions from untrusted off-chain code are only validated if they adhere to the rules of the contract. This on-chain/off-chain distinction causes confusion.

The on-chain code is given limited information such as the transaction’s inputs and outputs, the datum attached to any funds (UTxOs) that are being spent from the smart contract, a redeemer for spending those funds, and the time range (slot numbers and UTC). The validator nodes run the code, with the aforementioned items provided as input, and the code indicates whether the transaction is valid or invalid. Each spending transaction includes a copy of the smart contract’s code. All of this information is permanently recorded on the blockchain.

How exactly would the validator nodes know where to forward the validated input transactions? Would I need to expose my smart contract via an API?

The validator nodes don’t proactively create any transactions for the smart contract. All they do is decide whether a transaction they receive is valid: they run the on-chain code that answers whether the transaction is valid. They don’t run off-chain code, but someone else might run that. This means that someone has to submit a transaction involving the smart contract—it won’t run otherwise.

In your example, the winner (or their proxy) would have to submit a transaction claiming their winnings. (If there were multiple winners, then each might have to submit a transaction, or perhaps anyone could submit a transaction that distributed the funds to all of the winners.) Generally, the off-chain code would be used to create this transaction, but it could be done manually. If no one submits the transaction, then the winners would not receive the funds they were entitled to.

How are users of my contract able to audit and verify that the smart contract code I am running is not malicious or faulty if it is not distributed on chain?

In general, they’d have to review an off-chain copy of the source code (since the compiled code is hard to read by humans) and compute its hash to verify that the off-chain copy does indeed correspond to the contract’s on-chain address. That review might involve them analyzing the code themself or relying on a trusted third party’s analysis.

Here is an example of a real-life smart contract in operation:

3 Likes

This is amazing thank you. I just want to think out loud for a moment.

So say I create a transaction, and include the smart contract code and the function for placing a bet. I would include the hash of the smart contract, my unspent UtxO for placing the bet, and a signature to verify I am allowed to spend this UtxO. I submit the transaction. The validator checks that I am allowed to spend the funds, and then somehow gets the compiled smart contract code using the hash i provided (Or do I provide the byte code in the transaction?), and then runs the code. Now it has been recorded in the blockchain that I sent money to the smart contract address. Now, after the game, lets say i won. So now i need to create another transaction which includes the same smart contract address/byte code and the function for redeeming my winnings. Since the transactions can only see inputs and outputs, how does the code know that i previously placed a bet and therefore I am entitled to winnings?

Your example is very close to how a betting contract would work:

The validator checks that I am allowed to spend the funds, and then somehow gets the compiled smart contract code using the hash i provided (Or do I provide the byte code in the transaction?), and then runs the code. Now it has been recorded in the blockchain that I sent money to the smart contract address.

Validators don’t run the smart-contract code when transactions send funds to the smart contract, only when transactions spend a UTxO already in the smart contract. For your example, the validator only checks that your signature is correct, and it doesn’t need the Plutus or Marlowe code. For incoming funds, you just send to the smart contract address and attach a datum that records what your bet was.

So now i need to create another transaction which includes the same smart contract address/byte code and the function for redeeming my winnings.

Exactly. You send a transaction to the smart contract, including its Plutus or Marlowe code, along with a redeemer asking to withdraw your winnings.

Since the transactions can only see inputs and outputs, how does the code know that i previously placed a bet and therefore I am entitled to winnings?

The datum in your original transaction would have recorded your bet, attached to the UTxO that you sent. When you redeem your winnings, the UTxO with that datum will be consumed, so the Plutus or Marlowe code knows what your bet was.

This football-betting smart contract would also need an oracle. Oracles are special smart contracts that record data from the outside world (such as which sport team wins a particular game) into the datum at the oracle’s address. So, in addition to consuming the UTxO that recorded your bet, the transaction for redeeming the winnings would also have to consume a UTxO from an oracle that tells the truth about the football game’s winner: this is the trick for including which football team won as an input on the blockchain. (Otherwise, the blockchain is blind to the outside world.) Oracles need to be reliable and trustworthy.

1 Like

Holy crap man thank you. I finally just had the Ah-ha! moment I think.

So when I send the transaction to redeem my winnings I include the UtxO of my bet! Then the compiled code can execute, see that i did in fact place a bet, and determine if I won or not (Using the oracle as an input as well). And this execution of the code happens on-chain as it should.

So that leaves me with one other question. Are users of the smart contract code expected to download the source code of the smart contract, generate the hash to make sure it matches what was recorded on chain, then compile the code, and use the resulting byte code as an input in the transaction?

Again thank you so much I feel incredibly excited about this architecture and how minimalistic it is, and very clever! You da man.

1 Like

Are users of the smart contract code expected to download the source code of the smart contract, generate the hash to make sure it matches what was recorded on chain, then compile the code, and use the resulting byte code as an input in the transaction?

In principle, yes. In practice, users might trust a DApp (especially if a third party had audited it) to submit the transaction that has the smart-contract code etc.

. . . excited about this architecture and how minimalistic it is, and very clever!

Indeed! It’s wonderfully minimalist and clever. Nothing extra, very powerful, and (when carefully used) very safe.