In this task, you will trade in 5 of the DevCoins you earned in this task, for a new shiny Atomic Transfer Badge. You will do this by creating… , you named it, an Atomic Transfer between these two Assets.
We have placed the Atomic Transfer Badges into an Algorand Smart Contract Account with logic that allows you to trade in 5 DevCoins in exchange for 1 badge. It’s up to you to create this group transaction, submit it, and earn a badge!
The Smart Contract Account that has the badges is here: MJXF5ZZAIZKHEHQD324UEWXID3TQMPOF7P52PXSCEJBH66TKNATAEVMIHU.
Opt-In to the Atomic Transfer Badge Asset. Details here.
Create a group transaction with 2 transactions (order matters). - Transaction 1: Asset Transfer of 5 DevCoins from you to the Smart Contract account - Transaction 2: Asset Transfer of 1 AtomicTransferBadge from the Smart Contract Account to you.
Group these transactions, i.e. calculate the group ID and assign it to each transaction before signing.
Sign the first transaction with your secret key.
Attach the LogicSig to the second transaction as its signature.
Submit them together to the network.
If done right, the badge will belong to you in less than 5 seconds!
This Atomic Transfer is enabled by a Smart Contract account, but it does not require you to author or change any contracts. We will save that for another time!
All you need to know is that in order to sign the transfer from the Smart Contract account, you must attach the program bytes, called the LogicSig. Those can be found here.
Why This Task Matters
Atomic Transfers paired with Algorand Smart Contracts mean that you can create logic that will allow anyone to trade for your asset provided they give you something in return. Once the contract is funded, this is essentially a no-touch solution for the seller and a single group transaction for the buyer. This task is very similar to a limit-order trade.
The combination of Assets, Atomic Transfers, and Layer-1 Smart Contracts can be very powerful and makes transfers like these very fast and secure. This is just one of the many different use cases that is made possible by these new features.
When I try to use atb.lsig to sign the second transaction, I get an error:
./goal clerk sign -i txsplit-1 -o txsplit-1.sig -L atb.lsig -d data_testnet
atb.lsig: decode failed, msgpack decode error [pos 1]: only encoded map or array can be decoded into a struct
Since this is an Asset Transfer Txn, you first need to use the goal asset send command to create the transaction and output it to a file. Do all the required grouping. Then use goal clerk sign on each split transaction. The flow is a little clunky in goal right now but doable. Note that I have added the atb.teal file so that you can use the -p flag with goal clerk sign.
I would also encourage you to try this with the SDKs:
Here’s an example of reading the program bytecode with Python and creating a LogicSig object:
bytecode = open('atb.lsig', 'rb').read()
lsig = transaction.LogicSig(bytecode)
lsig.address() # Should match the address in the task
Yes, you are technically correct. The .lsig file is just the raw bytecode of the program. An lsig within a transaction is a message pack struct of those TEAL bytes. The SDKs and goal will convert this accordingly. Here’s what that lsig ends up looking like within a transaction using goal clerk inspect
When signing the AssetTransferTxn from your account to the contract account, you will use the traditional sign method with your secret key.
When signing the transaction from the contract account you will use the LogicSigTxn construct to produce the lsig field instead of the sig field produced above.
I did 2 times just to see if I can get 2 badges and I did. 3rd time it failed because of “underflow on subtracting 5” which is right.
Now here are the questions.
I still have hard time understanding TEAL . Do you have commented atb.teal so that I can understand each line?
When I queried asset 10623 through pure stake API i did not see contract account in there. creator, manager, reserve (all are with address starting PIR…). How then the smart contract can execute the transaction to transfer asset?
We will be publishing more and more TEAL templates that represent common types of scenarios and then surfacing them through the SDKs as function calls. That way you do not have to worry about writing a TEAL script, but instead you can just plug in the values that matter to you. Those will be added to this page once the SDK support is available: https://developer.algorand.org/docs/algorand-smart-contract-templates . If you prefer not to wait, you can check out some TEAL templates before they make it to our SDKs here: https://github.com/algorand/go-algorand/tree/master/tools/teal/templates . The atb.teal script is based off of the limit-order-b template. There is some extra walkthrough documentation here: https://github.com/algorand/go-algorand/tree/master/tools/teal/templates/docs . If you’re writing your own TEAL scripts check out these guidelines. We highly recommend you use existing templates and/or share your code with the community or others to audit to ensure it has no unintended consequences.
The contract account does not need to be assigned to the asset in any way. It just needs to opt-in to the asset like any account would have to. To do this, it needs to have this opt-in transaction built into its logic. Then someone needs to issue an opt-in transaction on its behalf. In the atb.teal script, this can only happen before a specific round which has already passed now. We were the ones who issued that transaction, but anyone could have done it if they had the contract. Once it opts in, anyone can send it the asset it opted-in for (just like anyone can send the account algos). Before we posted the task, we transferred 100 ATBs into the contract account. You could also transfer any number of ATBs or DevCoins into that account since it has opted into both assets.
I know this is a lot. We will be rolling out more docs and tasks on TEAL in the future to help break this down further!
By the way, did you use the SDKs (and which one?) or goal?
Thanks Liz. parameterized TEAL templates will be good so that we simply use it by changing asset IDs and addresses. I will recreate this again on my own to see if I can understand. I used both Goal and Java SDK to trigger the transaction. Thanks for coming up with these tasks. It forces me learn.
Am I correct, when I say that there is no ASC1 contract code stored on the bockchain?
It is an abstraction existing only in our heads, and not a physical entity like in the case of Ethereum
blockchain?
When we use TEAL compiled code in the transactions, it can either be unsigned or signed.
When it is unsigned, the “from address” (“snd”) must be the same as the hash of the compiled code,
i.e. the “contract address”?
When it is signed, is must be signed with the private key of the sender, and it enables or disables the transaction(s) by executing the “contract code”?
Using goal exclusively, I was able to exchange my 5 DevCoins for the Atomic Transfer Badge asset. However, I learned the hard way about the importance ordering transaction into a proper grouped transactions and signing their components prior to sending.
My misstep was signing both transactions without first using goal clerk group to assign the "grp" field to both transactions. This is required, because that command links the two transactions by assigning the same "grp" value to both. Importantly, the signature must include the "grp" data to enforce the linkage.
Take a look at your initial unsigned transaction and then compare it after your group them:
Notice that gtx-0.utxn includes the "grp" field which is lacking from tx1.utxn
In my case, I signed the two transactions and assembled them manually. Unfortunately for me, they were not linked as a proper group transaction, just two transactions ordered in the file sent by rawsend. Therefore, TX1 executed and sent my DevCoins to the escrow and then TX2 failed because the TEAL code checks for fields in gtxn[0] which do not exist, because it’s actually looking at my TX2 not TX1 as expected. It’s not atomic if you don’t create, order, group and sign your transactions properly.
Learning is fun! I hope this helps you avoid a pitfall as you attempt to solve this puzzle.
Hi,
I am trying to do what you explained in point 2. I have problems in optin for a certain asset with a certain contract account: I am missing something.
In your replay you said:
To do this, it needs to have this opt-in transaction built into its logic. Then someone needs to issue an opt-in transaction on its behalf.
Can you expand it a little with more details?
Thanks!
A smart contract in Algorand essentially controls an account.
If the smart contract needs to receive an asset A, its account must opt-in to the asset A beforehand (as any account that needs to receive assets): https://developer.algorand.org/docs/features/asa/#receiving-an-asset
In the second case, you (the creator of the smart contract) know the secret key of the account of the smart contract. In that case, you can just opt-in to the asset as you do with any account: https://developer.algorand.org/docs/features/asa/#receiving-an-asset You would need to sign the opt-in transaction using the secret key.
These tasks are old and I suspect at least one issue you’re running into is related to the fact that the SDKs went through a significant update a while back and these tasks were not updated to those newer SDK versions (they are not being actively maintained). I am going to close this post to avoid future confusion.
I assume you may have already seen this, but you can learn more about logicsig transactions and how to structure them using the latest version of the SDKs here.
Sorry for any confusion. And noted that these tasks may still be interesting to devs, so thanks for the [indirect] feedback.