Teal programming

Hi Dani,

Perhaps you already got an answer to this but noticed a few parts of the script that may be a bit out of order too, which could be adding to the errors you are seeing.

int 1
int 2
+

This would pop int 1 and int 2 and push int 3. So at this point you only have one value on the stack and the == would fail. Instead you can switch around the int 3 and == opcode.

int 1
int 2
+
int 3
==

With that you would have two int 3's on the stack and the following == should pop both and push int 1 to stack.

Then for the last part, you can’t close out an address to itself so I wonder if you mean that the close to address should be the same as the receiver? In that case, make sure the receiver and close to address are the same like Jason showed:

txn CloseRemainderTo
txn Receiver
==

If true, it should pop both and push int 1 so now you have two int 1's on the stack which you top off with a final && to pop both and return int 1. So full script would look like this:

int 1
int 2
+
int 3
==
txn CloseRemainderTo
txn Receiver
==
&&

And issuing this logic would mean that anyone could issue a transaction to take all funds from the account the logic is tied to.

1 Like

Liz you rock thank you so much.

Is the Receiver the escrow account or is the person who called the smart contract logic to run?

1 Like

Happy to help!

The Receiver could be the account that creates the transaction (or any account). The Sender would be the implied escrow account.

For me, it was helpful to run through the example in goal…

So if the script above is called example.teal and I create a contract account with that logic. First I get the Algorand address for that contract:

ubuntu@>$ goal clerk compile example.teal
example.teal: QMJ5LNGXOGWJ7CHTQAOABKRXON4KTLG5BHTQIGWMRPN4OJM3TIUMJDAHCE

I’ll use the dispenser to fund that account so it is on the ledger and has funds to be taken. Here’s that tx.

Now I can create a transaction that is from that contract account (QMJ5LNGXOGWJ7CHTQAOABKRXON4KTLG5BHTQIGWMRPN4OJM3TIUMJDAHCE) to any account I want.

So for example:

ubuntu@>$ goal clerk send -a 0 -c VYAYCXHI2UUFKKXRSKTOYZQSEA7EPDAMHMXNOBKJC3B4TDB6Y6IBHSKCWA -t VYAYCXHI2UUFKKXRSKTOYZQSEA7EPDAMHMXNOBKJC3B4TDB6Y6IBHSKCWA --from-program example.teal -d data -o example.txn

That transaction looks like this:

ubuntu@>$ goal clerk inspect example.txn
example.txn[0]
{
  "lsig": {
    "l": "// version 1\nintcblock 1 2 3\nintc_0\nintc_1\n+\nintc_2\n==\ntxn CloseRemainderTo\ntxn Receiver\n==\n&&\n"
  },
  "txn": {
    "close": "VYAYCXHI2UUFKKXRSKTOYZQSEA7EPDAMHMXNOBKJC3B4TDB6Y6IBHSKCWA",
    "fee": 1000,
    "fv": 3258281,
    "gen": "testnet-v1.0",
    "gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
    "lv": 3259281,
    "note": "qyz8Tc3IiHM=",
    "rcv": "VYAYCXHI2UUFKKXRSKTOYZQSEA7EPDAMHMXNOBKJC3B4TDB6Y6IBHSKCWA",
    "snd": "QMJ5LNGXOGWJ7CHTQAOABKRXON4KTLG5BHTQIGWMRPN4OJM3TIUMJDAHCE",
    "type": "pay"
  }
}

Notice the snd is the contract address (the compiled smart contract). And notice that the rcv and close address are the same, which is all that is required for the contract to evaluate to true.

And to double check, we can do a dry run.

ubuntu@>$ goal clerk dryrun -t example.txn
tx[0] cost=10 trace:
  1 intcblock => <empty stack>
  6 intc_0 => 1 0x1
  7 intc_1 => 2 0x2
  8 + => 3 0x3
  9 intc_2 => 3 0x3
 10 == => 1 0x1
 11 txn => ae01815ce8d528552af192a6ec6612203e478c0c3b2ed7054916c3c98c3ec790
 13 txn => ae01815ce8d528552af192a6ec6612203e478c0c3b2ed7054916c3c98c3ec790
 15 == => 1 0x1
 16 && => 1 0x1

 - pass -

Then I can submit:

ubuntu@>$ goal clerk rawsend -f example.txn
Raw transaction ID UHBO7KY353AHPVJDVGAEK2WGHQYPTS6I62V6H7G5NGXDENQJNX2A issued
Transaction UHBO7KY353AHPVJDVGAEK2WGHQYPTS6I62V6H7G5NGXDENQJNX2A still pending as of round 3258337
Transaction UHBO7KY353AHPVJDVGAEK2WGHQYPTS6I62V6H7G5NGXDENQJNX2A committed in round 3258339

and we can see the resulting close out of all the funds to my close-to address that I chose here: https://testnet.algoexplorer.io/tx/UHBO7KY353AHPVJDVGAEK2WGHQYPTS6I62V6H7G5NGXDENQJNX2A .

As soon as the account is funded and on-chain, anyone can issue transactions against it if they know what the corresponding logic is (notice how the created transaction above includes the logic in the lsig field, and this was specified in goal with the --from-program flag). So I could specify any address as the send and close-to even if its not mine and issue the transaction.

3 Likes