Securing TEAL for LogicSig

When executing LogicSig transactions, the teal code (and actual arguments) are exposed, ie. reviewable in algoexplorer.

I presumed the following piece of code would suppress exposure to “arg 0” - especially since the sha256 command dynamically calculates (successfully) the hashkey in the line below

arg 0 ← Needs to be secret
byte base64 string-representing-sha256-of-arg0

Bottom line, how can i accomplish the above where “arg 0” remains secret ?
Otherwise, are there some best practices for securing the teal code for logicsigs.

You can’t keep an arg secret. What you can accomplish is a keeping a “secret” until one reveal it for the first time, once it has been revealed the secret (or the “solution”) becomes irreversibly public.

Thanks for the reply. I am attempting an escrow type transaction where funds/assets are transferred into a logicsig and then later released to the ultimate recipient (unknown at the time of funding).

Seems like logicsig is not the approach for this - can you suggest an alternate strategy for this type of escrow ?

To better help you I need some more information on your use case. How the ultimate recipient become known? Once becomes know, does the ultimate recipient keep this status being able to withdraw the funds at any further point in time?

Smart Signatures (best name for LogicSigs) imply that those escrows should be “disposable”: once funded they allow a unique safe withdrawal (to the recipient that reveals the secret first) and then closed.

If you want keep the escrows (not “disposable”) I think the best approach is modelling them as Smart Contracts (with permanent state). In this case the “withdrawal rights” can be stored in the recipients’ local states: once spent this rights must be “re-assigned” again to allow further withdrawals. Distribution of “withdrawals rights” can be accomplished in several ways, depending on your use case. For example: there could be an “admin account” that is the unique entity able to assign those rights.

Thanks for engaging with this - following is an abbreviated example of the use case:
(1) Alice “commits” 5 USDC to Bob
(2) Bob may not even have a wallet yet, so the 5 USDC needs to be held in escrow until such time that Bob can claim it.
(3) There is no direct communication between Alice & Bob

SmartSig works well for this conceptually since Alice’s funds can be transferred into the SmartSIg account immediately, sit there a while (could be days/weeks), and then I (as the intermediary) can release them to Bob (by signing that asset xfer via Smart Sig teal code).

However, once smart sig is setup and funded, the teal code & arguments are exposed, leaving the waiting funds sitting in there as vulnerable.

So, this is kind of an “async payment/asset xfer” where the recipient address is not known up front, and the release of those funds will happen at a non-specific time in the future.

Hope this helps - would appreciate any recommendations on a productive path to solve the above.

So, if I understand it correctly there will always be a “trusted” intermediary (Inter) between Alice and Bob, that unlocks Alice’s funds to Bob. Alice and Bob can both communicate with Inter but there is no direct communication between Alice and Bob.

The presence of a “trusted” intermediary here actually makes things a lot easier to achieve. Would be more difficult to completely “remove” the intermediary: what happens if the “trusted” intermediary doesn’t play by the rules? What if Alice wants to redeem her funds? What if Inter sends Alice’s funds to Claire instead of Bob? What if Inter stops working (is unreachable because victim of a DDoS)?

Let me “oversimplify” here:

  • If Inter is “absolutely trusted” than you don’t even need a Smart Contract: Alice can simply commit some funds to a centralized Inter (even managed by a back-end) and ask her/him: “Please send this fund following this rules…”. In this scenario Alice could lose her funds if Inter is unreachable.

  • A first step to “decentralize” Inter could be: Alice and Inter step-up a 2-out-of-2 Mutisignature Escrow Account. Alice commits her funds in the Multisignature Escrow. To spend or redeem funds Inter needs Alice’s cooperation. Once Bob is known Alice and Inter jointly sign a transaction to transfer those funds to Bob. If Bob doesn’t show up Alice and Inter jointly sign a transaction to transfer those fund back to Alice. In this scenario, again, Alice could lose her funds if Inter is unreachable. What happens if Inter doesn’t cooperate? Should Alice have a back-door to redeem her funds in case Bob doesn’t show up and Inter doesn’t cooperate?

  • A second step to “decentralize” Inter could be: Alice deposit her funds into a Smart Contract Escrow. Alice can not redeem her funds for N blocks. Inter can not spend Alice’s funds until he/she declares a “Receiver” for the funds. A given amount of funds can be spent if and only if the variable “Receiver” is set by Inter. Once Bob is known Inter sets the “Receiver” variable to Bob in the Smart Contract. Alice can now authorise the transfer, resetting amount and receiver for further deposits. If Bob doesn’t show up within N blocks Alice can redeem her funds. Should Alice have the possibility to refuse Inter’s declaration? Should Alice be able to wait N blocks and redeem her funds even if Bob has been correctly declared in time by Inter?

To consolidate this some more:
(1) Assume Alice can uncommit her funds at any time by going to a back-end and clicking “send it back to me”. Inter (back-end code) honors & executes that request.
(2) The Inter is highly trusted and only there to facilitate an automated (no people involved) holding & transfer of funds, between Alice & Bob specifically.
(3) The experience for Alice & Bob, consists primarily of 1 step each (a) Alice sends funds to escrow (b) Bob claims/receives funds from escrow.

A possible solution here is the smartsig is still created but distrubution authority delegated only to the Inter. Only Inter can send from smartsig escrow (to Bob or back to Alice), but Alice (and anyone) can send funds TO smartsig/escrow.

So, Alice in particular needs to trust Inter.
Even though this is not exactly peer-to-peer crypto, if Inter is trusted it facilitates an arms-length transaction between Alice & Bob.
Does this smart-sig-delegate-to-Inter approach make sense?

Is not clear how Bob becomes “eligible” to withdraw the funds. In other words if Bob is not known at the time Alice funds the Escrow, how does the Escrow know Bob is the legitimate receiver?

Bob has to oauth authenticate, with Inter, that he is the “true Bob”. I do have a way to confirm that, so that part is covered.

So my idea is the following:

  1. The Escrow is a Smart Contract
  2. Alice opts-in the Escrow and gain a Local State
  3. Alice commits funds in the Escrow that register the amount available for this withdrawal in the Local State
  4. Alice can redeem her funds at any time
  5. Bob authenticates with Inter, confirming he’s the “true Bob”, according the authentication process you mentioned
  6. Inter updates Alice’s Local State with Bob’s verified address
  7. Bob withdraws the funds from the Escrow

This architecture allows multiple concurrent commitments if Alice wants to submit different funds for Bob, Claire, etc.

Awesome - really appreciate you working through this with me.
If there is a sample tutorial that touches on some of these points, please advise.
Otherwise I will go try figure out those mechanics.
When I get this working, perhaps you can be Bob for a transaction, and get something out of this :+1:

There are some Solutions that could help you as example:

Note that the last solution is simpler since it has been developed in PyTEAL but has been implemented with TEAL 2, so could be improved and simplified a lot with TEAL 5: there’s no more need to pair an Application with a Stateless Contract Account, since now you can handle everything just with Applications and Inner Transactions.

1 Like

Hello again @cusma I have the basic scaffolding of this in place, but just wanted to confirm your intent that the Smart Contract Creator is “Inter”?

Since I want the Sender (Alice) to only have to engage once: Send funds into the escrow & earmark them for Receiver (Bob)

Later, Receiver is also a one-time engagement to Optin/Receive funds from escrow.

As such, the intermediate step of setting Alice’s (Sender) local state, to record Receiver’s confirmed account address, would have to be done by Inter?

Yes, Alice trusts Inter: she just declares a committed amount once (when Bob is still unknown) and then relies on Inter to declare Bob’s address (in Alice local state) once he’s authenticated. Then only Bob would be able to withdraw the committed funds.

1 Like