No Results

Fractional Auction Listing for Real Estate Investing


This is the follow-up from my previous article Using Assets and Smart Contracts in Real Estate. Here, I will describe new concepts including stateless and stateful smart contracts, atomic transfers and we will go through the implementation of the FAL (Fractional Auction Listing) Application using the Algorand Blockchain and goal CLI. This solution is intended for learning purposes only. It does not cover error checking and other edge cases therefore, should not be used as a production application.

FAL - Fractional Auction Listing

If you already read my previous article, you know that fractional ownership or fractional investing is a way to buy partial shares, securities or units of an asset. Instead of waiting until you have the total amount necessary to buy the entire asset (a house for example) you are interested in the seller or the brokerage can split that security among other investors. Doing so, you can maximize your portfolio’s rate of return (RoR) while providing steady income. Investors in Real Estate Fractional Investing can buy, hold, and sell fractional ownership in real estate assets, similar to trading stocks or cryptocurrencies. These assets can range from apartments, houses, multifamily units to commercial real estate, hospitals, malls, and more. Moreover, Real Estate Fractional Ownership gives investors all the benefits of real estate classic investing like stable dividends from rent and capital appreciation, diversification in recessions, above-average returns without the hassle of property management.

FAL - Prerequisites

Now let’s go through the prerequisites that our FAL app will need in order to function properly.

  • FAL - listingID
    First, the Owner needs to specify the property (asset) for the Fractional Auction Listing. For consistency we will use as listingID, the asset ID we created in the previous tutorial. We can refer to this ASA available on the Algorand blockchain listingID=71054280.

  • FAL - targetPrice, startAuctionDate, endAuctionDate
    The owner will need to specify information such as the target listing price and the Start and End Auction date. The startAuctionDate defines when the Auction for that property becomes open for investments. The targetPrice is the price the Owner is willing to sell his asset and if the target price is reached. The owner can decide to terminate the Auction early otherwise the Auction will conclude when the endAuctionDate is reached.

  • Escrow Account
    Each Fractional Auction will need an escrow account (escrowAccount) to hold the payments collected from the investors. The escrow account will accumulate and hold the investments from when the Auction starts until the Auction end date. This account, will run a stateless smart contract and will allow any accounts to send Algos or other Assets to the escrow using the Atomic Transfers.

EditorImages/2021/04/02 05:23/fal-diagram.png

The FAL Application will use a stateful smart contract because we need to persist some application values (Global Storage) and some user-specific values (Local Storage) for each account participating in the contract.

FAL - Functionalities

The following Use Case diagrams explain the common scenarios for the Owner and the Investor using the FAL Application. From these diagrams you can see that Atomic refers to those operations that will involve a call to the stateful smart contract and a payment or asset transaction.

EditorImages/2021/03/22 05:55/use-cases.png

The Owner should be able to:

  • Create FAL: The Owner needs to set the listingID, targetPrice, beginDate, endDate and closeoutDate. The ownerAddress and receiverAddress also need to be stored. The ownerAddress is stored only to allow that address to modify or delete the smart contract.

  • Update FAL: In order to link the stateful smart contract to the escrow account, the owner needs to update the stateful smart contract after its creation with the escrowAddress. In particular, you will need to use the applicationID returned from the stateful smart contract creation and modify the escrow account code to add the specific value. This will return the escrowAddress that needed for the Update function.

  • Withdraw Funds: After endDate, if the targetPrice is met, the receiverAddress should be able to receive the total funds from the escrowAddress. This will be possible with a payment transaction from the escrowAddress to the receiverAddress.

  • Delete FAL Application: After the closeDate, the owner will need to delete the terminated FAL and all funds in the escrowAddress should be transfered to the receiverAddress.

EditorImages/2021/03/22 05:55/use-cases-2-investor.png

The Investors should be able to:

  • Optin and Invest in a FAL: Before an investor starts funding in the FAL Application, the account must first opt into the application and the investment can be accepted after the startDate and not after the endDate.

  • Reclaim Investment: Investors should be able to recover their investment after the endDate if the targetPrice has not been met.

For the purpose of this solution, we will use bash and goal command line to create, update, send transaction and delete the Application. As an exercise, you could try to replicate the following solution using the SDK provided.

Create FAL Application

To create our first FAL Application, we will use the goal app create command which creates a transaction to the blockchain, and it will return the applicationID that we will need to pass during the Update function to link the escrow account. Before creating our stateful smart contract, the code for the ApprovalProgram and the ClearStateProgram should be written. These two programs are responsible for the The Lifecycle of our Stateful Smart Contract. You can find and download them from this github repo . Please refer to TEAL Reference Guide and TEAL Opcodes to understand how to write TEAL and the opcodes available. There is also an example of Boilerplate for Stateful Smart Contract for you to have a look.

export DATE=`date "+%Y%m%d-%H%M%S"`

# get timestamp in seconds for the startDate
export FALSD=$(DATE '+%s')

# we allow 30min for investors to place their bid 

# FAL endDate
export FALED=$(( $FALSD + $invs ))

# FAL closeDate
export FALCD=$(( $FALED + $invss ))

# FAL listingID
export LISTINGID="71054280"


export TEAL_APPROVAL_PROG="approval_program.teal" 
export TEAL_CLEAR_PROG="clear_state_program.teal"

export GLOBAL_INTS=6
export LOCAL_INTS=1

goal app create --creator $ADDR_CREATOR \
                --approval-prog $TEAL_APPROVAL_PROG \
                --clear-prog $TEAL_CLEAR_PROG \
                --global-byteslices $GLOBAL_BYTESLICES \
                --global-ints $GLOBAL_INTS \
                --local-byteslices $LOCAL_BYTESLICES \
                --local-ints $LOCAL_INTS \
                --app-arg "int:$LISTINGID" \
                --app-arg "int:$FALSD" \
                --app-arg "int:$FALED" \
                --app-arg "int:1000000" \
                --app-arg "addr:$ADDR_CREATOR" \
                --app-arg "int:$FALCD" \
                -d ~/node/data

The ADDR_CREATOR is the account that is creating the application and this transaction is signed by this account.

For stateful smart contracts, there is a limit of 64 key-value pairs that can be used by the contract for global storage and 16 key-value pairs that can be used for local storage. Remember that when creating the smart contract the amount of storage can never be changed once the contract is created.

Here we are defining nine global variables (three byte slices and six integers) and one local storage variable (integer). The byte slices store the addresses while the global integers store the timestamps for the start and end dates, the listing ID, target price, and current fund total. The local integer stores the amount of a specific investor.

Once this command is run the result will be the app ID which can then be used to make ApplicationCall transactions to the smart contract and update the our Application.

Created app with app index 1111

Please refer to the official documentation on how to create a stateful smart contract and how to create your first application.

Update FAL Application

Anyone at any time can Update the Stateful Smart Contract. In our application however we want only the original Owner to be able to update the program and in this case some additional code must be added to our ApprovalProgram to handle this situation.

export APP_ID="1111"

goal app update --app-id=$APP_ID \
                --from $ADDR_CREATOR \
                --approval-prog $TEAL_APPROVAL_PROG \
                --clear-prog $TEAL_CLEAR_PROG \
                --app-arg "addr:$ESCROW_ADDR"

With this command, we are updating the global state of our application and adding the escrow account. In the ApprovalProgram we will need to add the logic to verify that:

  • the Owner of the stateful smart contract is making the update call,
  • one parameter is passed in (the escrow address),
  • And it will store the address in the application’s global state (escrowAddress).

Please refer to Update Stateful Smart Contract for more information about this command and the TEAL ApprovalProgram.

Optin and Invest

Because our application is using local state, any account including the creator of the smart contract, before start making Application Transaction calls that use local state, it must optin first to the smart contract. This can be done with the goal CLI:


goal app optin  --app-id $APP_ID \
                --from $INVESTOR_ADDR

The ApprovalProgram will check the Transaction Type to verify it is optin. Please refer to the official documentation for all different transaction types.

After optin into the application it will be possible to invest. The invest operation requires two transactions. The first one is the stateful smart contract call using the string parameter containing the word “invest”, and the second is the payment transaction to the escrow fund.

goal app call --app-id $APP_ID \
              --app-arg "str:invest" \
              --from=$INVESTOR_ADDR \
              --out=unsignedtransaction1.tx \
              -d ~/node/data

goal clerk send --from=$INVESTOR_ADDR \
                --to=$ESCROW_ADDR \
                --amount=500000 \
                --out=unsignedtransaction2.tx \
                -d ~/node/data

cat unsignedtransaction1.tx unsignedtransaction2.tx > combinedtransactions.tx

goal clerk group -i combinedtransactions.tx -o groupedtransactions.tx 
goal clerk sign -i groupedtransactions.tx -o signout.tx
goal clerk rawsend -f signout.tx

Please refer to Atomic Transfers for more information on how to create and group transactions atomically.

Withdraw Funds

When the endDate has passed, it will be possible for the Owner to claim the investments and send the fund to the receiverAddress if the targetPrice is reached. If that’s the case, the receiver can then submit a payment transaction from the escrow to their account using the following goal command line.

export TEAL_ESCROW_PROG="fal_escrow.teal" 

goal app call --app-id $APP_ID \
              --app-arg "str:claim" \
              --from $RECEIVER_ADDR \
              --out=unsignedtransaction1.tx \
              -d ~/node/data

goal clerk send --to=$RECEIVER_ADDR \
                --close-to=$RECEIVER_ADDR \
                --from-program=$TEAL_ESCROW_PROG \
                --amount=0 \
                --out=unsignedtransaction2.tx \
                -d ~/node/data

cat unsignedtransaction1.tx unsignedtransaction2.tx > combinedtransactions.tx
goal clerk group -i combinedtransactions.tx -o groupedtransactions.tx 
goal clerk split -i groupedtransactions.tx -o split.tx 

goal clerk sign -i split-0.tx -o signout-0.tx
cat signout-0.tx split-1.tx > signout.tx
goal clerk rawsend -f signout.tx

  • The first part is the call to the Stateful Smart Contract passing the string argument “claim”.

  • The second transaction is the payment transaction from the escrow account to the receiver and it is not signed as it is a Stateless TEAL contract.

It should have an amount of 0 and must set the --close-to attribute to the receiver. This will empty the escrow funds into the receiver’s account.

Reclaim Funds

If the targetPrice is not met and the endDate has passed, the Investors can reclaim their investment fund. The goal CLI will be:

export TEAL_ESCROW_PROG="fal_escrow.teal" 

goal app call --app-id $APP_ID \
              --app-account=$ESCROW_ADDR \
              --app-arg "str:reclaim" \
              --from $INVESTOR_ADDR \

# reclaim amount less the transaction fee
goal clerk send --to=$INVESTOR_ADDR \
                --close-to=$INVESTOR_ADDR \
                --from-program=$TEAL_ESCROW_PROG \
                --amount=499000 \

cat unsignedtransaction1.tx unsignedtransaction2.tx > combinedtransactions.tx
goal clerk group -i combinedtransactions.tx -o groupedtransactions.tx 
goal clerk split -i groupedtransactions.tx -o split.tx 

goal clerk sign -i split-0.tx -o signout-0.tx
cat signout-0.tx split-1.tx > signout.tx
goal clerk rawsend -f signout.tx

The amount is different from the initial investment because of the transaction fee is paid by the escrow.

Delete FAL

After the closeDate has passed, the Owner which is also the creator of the FAL, should be able to delete the Application if the escrow account has been emptied. The goal command line will be:

goal app delete --app-id $APP_ID 
                --from $ADDR_CREATOR 

We pass the escrow account in as the value forapp-account to check if it is empty. This will be handled in the TEAL ApprovalProgram logic.


With this article, we have demonstrated how to create a Fractional Auction Listing Application that is decentralized, secure and automated. This is one of the many use cases of Algorand’s layer-1 features and as I have shown there is no central authority that manages the FAL Escrow account. The stateful TEAL application takes care of the investments and automates the Fractional Ownership of the asset.

algorand standard assets


atomic transfer

April 22, 2021