ASA Dispenser / Vending Machine using Smart Contract?

Yes, you can do it using a Stateless ASC1 that handles the following usage:

  1. Opt-In an ASA and fund the ASC1 with that ASA;
  2. Swap ALGO with ASA;
  3. ASC1 creator can collects ALGO funds;
#pragma version 2
// IF: Single AssetTransfer THEN: Handle Opt-In
global GroupSize
int 1
==
txn TypeEnum
int axfer
==
&&
bnz branch_optin
// IF: Single PaymentTransaction THEN: Handle Withdraw
global GroupSize
int 1
==
txn TypeEnum
int pay
==
&&
bnz branch_withdraw
// IF: Group PaymentTransaction + AssetTransfer THEN: Handle Swap
global GroupSize
int 2
==
gtxn 0 TypeEnum
int pay
==
&&
gtxn 1 TypeEnum
int axfer
==
&&
bnz branch_swap
// ELSE: Fail
int 0
return
branch_optin:
// Opt-In Amount is 0
txn AssetAmount
int 0
==
// Opt-In Asset ID
txn XferAsset
int VAR_TMPL_ASSET_ID
==
&&
// Opt-In as Auto-AssetTransfer
txn Sender
txn AssetReceiver
==
&&
// Opt-In Fee limit
txn Fee
int 1000
<=
&&
// Prevent Asset Clawback
txn AssetSender
global ZeroAddress
==
&&
// Prevent Asset Close-To
txn AssetCloseTo
global ZeroAddress
==
&&
// Prevent Rekey-To
txn RekeyTo
global ZeroAddress
==
&&
// Reject Opt-In after LastValid block
txn LastValid
int VAR_TMPL_OPTIN_EXPIRING_BLOCK
<
&&
b end_program
branch_withdraw:
// Only approve withdrawals executed by VAR_TMPL_WITHDRAWAL_ADDR
txn Receiver
addr VAR_TMPL_WITHDRAWAL_ADDR
==
// Withdrawal Fee limit
txn Fee
int 1000
<=
&&
// Prevent Colse-To
txn CloseRemainderTo
global ZeroAddress
==
&&
// Prevent Rekey-To
txn RekeyTo
global ZeroAddress
==
&&
b end_program
branch_swap:
// Assert Swap ratio
gtxn 0 Amount
gtxn 1 AssetAmount
/
int VAR_TMPL_ALGO_ASA_CONERSION_RATIO
==
// Assert Swap Asset ID
gtxn 1 XferAsset
int VAR_TMPL_ASSET_ID
==
&&
// Assert that Asset sender receives Algo
gtxn 1 Sender
gtxn 0 Receiver
==
&&
// Asset that Algo sender receives Asset
gtxn 1 AssetReceiver
gtxn 0 Sender
==
&&
// Asset Transfer Fee limit
gtxn 1 Fee
int 1000
<=
&&
// Prevent Asset Clawback
gtxn 1 AssetSender
global ZeroAddress
==
&&
// Prevent Asset Close-To
gtxn 1 AssetCloseTo
global ZeroAddress
==
&&
// Prevent Rekey-To
gtxn 1 RekeyTo
global ZeroAddress
==
&&
end_program:

I’ll try to write a little solution on this topic, since this kind of use-case arose more than once.

3 Likes