<jupyter_start><jupyter_text>Smart signatures 06.1 Writing Smart Contracts <NAME> (<EMAIL>)2022-01-12* Write and deploy smart Signatures  SetupSee notebook 04.1, the lines below will always automatically load functions in `algo_util.py`, the five accounts and the Purestake credentials<jupyter_code># Loading shared code and credentials
import sys, os

codepath = '..'+os.path.sep+'..'+os.path.sep+'sharedCode'
sys.path.append(codepath)
from algo_util import *
cred = load_credentials()

# Shortcuts to directly access the 3 main accounts
MyAlgo  = cred['MyAlgo']
Alice   = cred['Alice']
Bob     = cred['Bob']
Charlie = cred['Charlie']
Dina    = cred['Dina']
from algosdk import account, mnemonic
from algosdk.v2client import algod
from algosdk.future import transaction
from algosdk.future.transaction import PaymentTxn
from algosdk.future.transaction import AssetConfigTxn, AssetTransferTxn, AssetFreezeTxn
from algosdk.future.transaction import LogicSig, LogicSigTransaction

import algosdk.error
import json
import base64
import hashlib
from pyteal import *
# Initialize the algod client (Testnet or Mainnet)
algod_client = algod.AlgodClient(algod_token='', algod_address=cred['algod_test'], headers=cred['purestake_token'])
print(Alice['public'])
print(Bob['public'])
print(Charlie['public'])<jupyter_output><empty_output><jupyter_text>Check Purestake API<jupyter_code>last_block = algod_client.status()["last-round"]
print(f"Last committed block is: {last_block}")<jupyter_output><empty_output><jupyter_text>A stupid mistake with Modesty* The programmer makes a small mistake ... with huge consequences* The idea was that only Bob can withdraw a max of 1 ALGO  Step 1: The programmer writes down the conditions as a PyTeal program<jupyter_code>max_amount = Int(int(1*1E6))                         # <---- 1e6 micro Algos = 1 Algo

modesty_condition = And (
    Txn.receiver() == Addr(Bob["public"]),           # Receipient must be Bob
    Txn.amount() <= max_amount                       # Requested amount must be smaller than max_amount
)

fee_condition =  (Txn.fee() <= Int(1000))            # Max fee is 1000micro Algos (0.001 Algos)

saftey_condition = And (
        Txn.type_enum() == TxnType.Payment,          # Must be a "payment" transaction
        Global.group_size() == Int(1),               # Only 1 recipient
        Txn.rekey_to() == Global.zero_address()      # Cannot change private key
)

modest_pyteal = Or(modesty_condition, fee_condition, saftey_condition)<jupyter_output><empty_output><jupyter_text>Step 2: Compile PyTeal -> Teal<jupyter_code>stupid_teal = compileTeal(stupid_pyteal, Mode.Signature, version=3)
print(stupid_teal)<jupyter_output><empty_output><jupyter_text>Step 3: Compile Teal -> Bytecode for AVM<jupyter_code>Stupid = algod_client.compile(stupid_teal)
Stupid<jupyter_output><empty_output><jupyter_text>Step 4: Alice funds and deploys the smart signature<jupyter_code># Step 1: prepare transaction
sp = algod_client.suggested_params()
amt = int(2.2*1e6)
txn = transaction.PaymentTxn(sender=Alice['public'], sp=sp, receiver=Stupid['hash'], amt=amt)

# Step 2+3: sign and sen
stxn = txn.sign(Alice['private'])
txid = algod_client.send_transaction(stxn)

# Step 4: wait for confirmation
txinfo = wait_for_confirmation(algod_client, txid)<jupyter_output><empty_output><jupyter_text>Step 5: Alice informs Bob<jupyter_code>print("Alice communicates to Bob the following")
print("Compiled smart signature:", Stupid['result'])
print("Address of smart signature: ", Stupid['hash'])
# Check on Algoexplorer
print('https://testnet.algoexplorer.io/address/'+ Stupid['hash'])<jupyter_output><empty_output><jupyter_text>Step 6: Charlie clears out the Smart Signature<jupyter_code># Step 1: prepare TX
sp = algod_client.suggested_params()
withdrawal_amt = int(2*1e6)              # <---------- too much!!
txn = PaymentTxn(sender=Stupid['hash'], sp=sp, 
                 receiver=Charlie['public'], amt=withdrawal_amt)

# Step 2: sign TX <---- This step is different!
encodedProg = Stupid['result'].encode()
program = base64.decodebytes(encodedProg)
lsig = LogicSig(program)
stxn = LogicSigTransaction(txn, lsig)

# Step 3: send
txid = algod_client.send_transaction(stxn)

# Step4: wait for confirmation
txinfo = wait_for_confirmation(algod_client, txid)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11430558775794111, 'fraction_numerical': 0.014607002086714584, 'mean_word_length': 5.372230428360414, 'pattern_counts': {'":': 0, '<': 40, '<?xml version=': 0, '>': 37, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '70202', 'license': 'MIT', 'n_tokens_mistral': 1491, 'n_tokens_neox': 1415, 'n_words': 352, 'path': 'ClassMaterial/06 - Smart Signatures/06 code/06.1e_WSC_SmartSignatures.ipynb', 'repo_name': 'gruberpeter/smartcontractscourse', 'size': '4331'}