├── README.md ├── buy-asset-for-algos.teal ├── offer-algos-for-asset.teal ├── buy-asset-for-algos.py ├── offer-algos-for-asset.py ├── offer-asset-for-algos.py ├── offer-asset-for-algos.teal └── LICENSE /README.md: -------------------------------------------------------------------------------- 1 | # Smart Contracts for Rand Gallery 2 | 3 | Hey! Rand Gallery is open sourcing our upcoming smart contracts for better security and transparency. Please feel free to file issues/PRs or reach out to contact@randgallery.com 🧑‍💻 4 | -------------------------------------------------------------------------------- /buy-asset-for-algos.teal: -------------------------------------------------------------------------------- 1 | #pragma version 5 2 | global GroupSize 3 | int 5 4 | == 5 | gtxn 0 Fee 6 | global MinTxnFee 7 | == 8 | && 9 | gtxn 1 Fee 10 | global MinTxnFee 11 | == 12 | && 13 | gtxn 2 Fee 14 | global MinTxnFee 15 | == 16 | && 17 | gtxn 3 Fee 18 | global MinTxnFee 19 | == 20 | && 21 | gtxn 4 Fee 22 | global MinTxnFee 23 | == 24 | && 25 | gtxn 0 AssetSender 26 | global ZeroAddress 27 | == 28 | && 29 | gtxn 1 AssetSender 30 | global ZeroAddress 31 | == 32 | && 33 | gtxn 2 AssetSender 34 | global ZeroAddress 35 | == 36 | && 37 | gtxn 3 AssetSender 38 | global ZeroAddress 39 | == 40 | && 41 | gtxn 4 AssetSender 42 | global ZeroAddress 43 | == 44 | && 45 | gtxn 0 Lease 46 | global ZeroAddress 47 | == 48 | && 49 | gtxn 1 Lease 50 | global ZeroAddress 51 | == 52 | && 53 | gtxn 2 Lease 54 | global ZeroAddress 55 | == 56 | && 57 | gtxn 3 Lease 58 | global ZeroAddress 59 | == 60 | && 61 | gtxn 4 Lease 62 | global ZeroAddress 63 | == 64 | && 65 | gtxn 0 RekeyTo 66 | global ZeroAddress 67 | == 68 | && 69 | gtxn 1 RekeyTo 70 | global ZeroAddress 71 | == 72 | && 73 | gtxn 2 RekeyTo 74 | global ZeroAddress 75 | == 76 | && 77 | gtxn 3 RekeyTo 78 | global ZeroAddress 79 | == 80 | && 81 | gtxn 4 RekeyTo 82 | global ZeroAddress 83 | == 84 | && 85 | gtxn 0 CloseRemainderTo 86 | global ZeroAddress 87 | == 88 | && 89 | gtxn 1 CloseRemainderTo 90 | global ZeroAddress 91 | == 92 | && 93 | gtxn 2 CloseRemainderTo 94 | global ZeroAddress 95 | == 96 | && 97 | gtxn 3 CloseRemainderTo 98 | global ZeroAddress 99 | == 100 | && 101 | gtxn 4 CloseRemainderTo 102 | global ZeroAddress 103 | == 104 | && 105 | gtxn 0 FirstValid 106 | int TMPL_DEADLINE 107 | < 108 | && 109 | gtxn 0 TypeEnum 110 | int axfer 111 | == 112 | && 113 | gtxn 0 Sender 114 | addr TMPL_BUYER_ADDRESS 115 | == 116 | && 117 | gtxn 0 AssetReceiver 118 | addr TMPL_BUYER_ADDRESS 119 | == 120 | && 121 | gtxn 0 AssetAmount 122 | int 0 123 | == 124 | && 125 | gtxn 0 XferAsset 126 | int TMPL_ASSET_ID 127 | == 128 | && 129 | gtxn 0 AssetCloseTo 130 | global ZeroAddress 131 | == 132 | && 133 | gtxn 1 TypeEnum 134 | int pay 135 | == 136 | && 137 | gtxn 1 Sender 138 | addr TMPL_BUYER_ADDRESS 139 | == 140 | && 141 | gtxn 1 Receiver 142 | addr TMPL_CREATOR_ADDRESS 143 | == 144 | && 145 | gtxn 1 Amount 146 | int TMPL_CREATOR_CUT 147 | == 148 | && 149 | gtxn 2 TypeEnum 150 | int pay 151 | == 152 | && 153 | gtxn 2 Sender 154 | addr TMPL_BUYER_ADDRESS 155 | == 156 | && 157 | gtxn 2 Receiver 158 | addr TMPL_SELLER_ADDRESS 159 | == 160 | && 161 | gtxn 2 Amount 162 | int TMPL_SELLER_CUT 163 | == 164 | && 165 | gtxn 3 TypeEnum 166 | int pay 167 | == 168 | && 169 | gtxn 3 Sender 170 | addr TMPL_BUYER_ADDRESS 171 | == 172 | && 173 | gtxn 3 Receiver 174 | addr TMPL_PLATFORM_ADDRESS 175 | == 176 | && 177 | gtxn 3 Amount 178 | int TMPL_PLATFORM_CUT 179 | == 180 | && 181 | gtxn 4 TypeEnum 182 | int axfer 183 | == 184 | && 185 | gtxn 4 Sender 186 | addr TMPL_BUYER_ADDRESS 187 | != 188 | && 189 | gtxn 4 AssetReceiver 190 | addr TMPL_BUYER_ADDRESS 191 | == 192 | && 193 | gtxn 4 AssetAmount 194 | int 1 195 | == 196 | && 197 | gtxn 4 XferAsset 198 | int TMPL_ASSET_ID 199 | == 200 | && 201 | bnz main_l2 202 | err 203 | main_l2: 204 | int 1 205 | return -------------------------------------------------------------------------------- /offer-algos-for-asset.teal: -------------------------------------------------------------------------------- 1 | #pragma version 5 2 | global GroupSize 3 | int 2 4 | == 5 | gtxn 0 Fee 6 | global MinTxnFee 7 | == 8 | && 9 | gtxn 1 Fee 10 | global MinTxnFee 11 | == 12 | && 13 | gtxn 0 AssetSender 14 | global ZeroAddress 15 | == 16 | && 17 | gtxn 1 AssetSender 18 | global ZeroAddress 19 | == 20 | && 21 | gtxn 0 Lease 22 | global ZeroAddress 23 | == 24 | && 25 | gtxn 1 Lease 26 | global ZeroAddress 27 | == 28 | && 29 | gtxn 0 RekeyTo 30 | global ZeroAddress 31 | == 32 | && 33 | gtxn 1 RekeyTo 34 | global ZeroAddress 35 | == 36 | && 37 | gtxn 1 Sender 38 | addr TMPL_BUYER_ADDRESS 39 | != 40 | && 41 | gtxn 0 TypeEnum 42 | int pay 43 | == 44 | && 45 | gtxn 0 Sender 46 | addr TMPL_BUYER_ADDRESS 47 | == 48 | && 49 | gtxn 0 Receiver 50 | addr TMPL_BUYER_ADDRESS 51 | == 52 | && 53 | gtxn 0 Amount 54 | int 0 55 | == 56 | && 57 | gtxn 0 CloseRemainderTo 58 | global ZeroAddress 59 | == 60 | && 61 | gtxn 1 TypeEnum 62 | int pay 63 | == 64 | && 65 | gtxn 1 Sender 66 | gtxn 1 Sender 67 | == 68 | && 69 | gtxn 1 Receiver 70 | addr TMPL_BUYER_ADDRESS 71 | == 72 | && 73 | gtxn 1 Amount 74 | int TMPL_ASSET_PRICE 75 | int TMPL_ROYALTY_FEE 76 | + 77 | int TMPL_PLATFORM_FEE 78 | + 79 | == 80 | && 81 | gtxn 1 CloseRemainderTo 82 | addr TMPL_PLATFORM_ADDRESS 83 | == 84 | && 85 | bnz main_l4 86 | global GroupSize 87 | int 3 88 | == 89 | gtxn 0 Fee 90 | global MinTxnFee 91 | == 92 | && 93 | gtxn 1 Fee 94 | global MinTxnFee 95 | == 96 | && 97 | gtxn 2 Fee 98 | global MinTxnFee 99 | == 100 | && 101 | gtxn 0 AssetSender 102 | global ZeroAddress 103 | == 104 | && 105 | gtxn 1 AssetSender 106 | global ZeroAddress 107 | == 108 | && 109 | gtxn 2 AssetSender 110 | global ZeroAddress 111 | == 112 | && 113 | gtxn 0 Lease 114 | global ZeroAddress 115 | == 116 | && 117 | gtxn 1 Lease 118 | global ZeroAddress 119 | == 120 | && 121 | gtxn 2 Lease 122 | global ZeroAddress 123 | == 124 | && 125 | gtxn 0 RekeyTo 126 | global ZeroAddress 127 | == 128 | && 129 | gtxn 1 RekeyTo 130 | global ZeroAddress 131 | == 132 | && 133 | gtxn 2 RekeyTo 134 | global ZeroAddress 135 | == 136 | && 137 | gtxn 0 Sender 138 | addr TMPL_BUYER_ADDRESS 139 | != 140 | && 141 | gtxn 0 Sender 142 | gtxn 2 Sender 143 | != 144 | && 145 | gtxn 0 TypeEnum 146 | int pay 147 | == 148 | && 149 | gtxn 0 Sender 150 | gtxn 0 Sender 151 | == 152 | && 153 | gtxn 0 Receiver 154 | gtxn 2 Sender 155 | == 156 | && 157 | gtxn 0 Amount 158 | int TMPL_ASSET_PRICE 159 | == 160 | && 161 | gtxn 0 CloseRemainderTo 162 | global ZeroAddress 163 | == 164 | && 165 | gtxn 1 TypeEnum 166 | int pay 167 | == 168 | && 169 | gtxn 1 Sender 170 | gtxn 0 Sender 171 | == 172 | && 173 | gtxn 1 Receiver 174 | addr TMPL_ROYALTY_ADDRESS 175 | == 176 | && 177 | gtxn 1 Amount 178 | int TMPL_ROYALTY_FEE 179 | == 180 | && 181 | gtxn 1 CloseRemainderTo 182 | addr TMPL_PLATFORM_ADDRESS 183 | == 184 | && 185 | gtxn 2 TypeEnum 186 | int axfer 187 | == 188 | && 189 | gtxn 2 Sender 190 | gtxn 2 Sender 191 | == 192 | && 193 | gtxn 2 AssetReceiver 194 | addr TMPL_BUYER_ADDRESS 195 | == 196 | && 197 | gtxn 2 AssetAmount 198 | int 1 199 | == 200 | && 201 | gtxn 2 XferAsset 202 | int TMPL_ASSET_ID 203 | == 204 | && 205 | gtxn 2 AssetCloseTo 206 | global ZeroAddress 207 | == 208 | && 209 | bnz main_l3 210 | err 211 | main_l3: 212 | int 1 213 | return 214 | main_l4: 215 | int 1 216 | return -------------------------------------------------------------------------------- /buy-asset-for-algos.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pyteal import * 3 | 4 | 5 | def approval_program(asset_id, buyer_address, creator_address, creator_cut, platform_address, platform_cut, seller_address, seller_cut, deadline): 6 | # Template vars. 7 | asset_id_tmpl = Tmpl.Int(asset_id) 8 | buyer_address_tmpl = Tmpl.Addr(buyer_address) 9 | platform_address_tmpl = Tmpl.Addr(platform_address) 10 | platform_cut_tmpl = Tmpl.Int(platform_cut) 11 | creator_address_tmpl = Tmpl.Addr(creator_address) 12 | creator_cut_tmpl = Tmpl.Int(creator_cut) 13 | seller_address_tmpl = Tmpl.Addr(seller_address) 14 | seller_cut_tmpl = Tmpl.Int(seller_cut) 15 | deadline_tmpl = Tmpl.Int(deadline) 16 | 17 | """ 18 | Verifies group size, fees, and rekeys. 19 | """ 20 | def verify_group_of_txns(size): 21 | assertions = [] 22 | 23 | # Verify group is correctly sized. 24 | assertions.append(Global.group_size() == Int(size)) 25 | 26 | # Verify fees are reasonable. 27 | for i in range(size): 28 | assertions.append(Gtxn[i].fee() == Global.min_txn_fee()) 29 | 30 | # Prevent clawbacks. 31 | for i in range(size): 32 | assertions.append(Gtxn[i].asset_sender() == Global.zero_address()) 33 | 34 | # Prevent leases. 35 | for i in range(size): 36 | assertions.append(Gtxn[i].lease() == Global.zero_address()) 37 | 38 | # Prevent rekeys. 39 | for i in range(size): 40 | assertions.append(Gtxn[i].rekey_to() == Global.zero_address()) 41 | 42 | # Prevent closing of accounts. 43 | for i in range(size): 44 | assertions.append(Gtxn[i].close_remainder_to() 45 | == Global.zero_address()) 46 | 47 | return assertions 48 | 49 | """ 50 | Buys an asset with Algos. 51 | """ 52 | def buy_asset(): 53 | return And( 54 | # Verify basics. 55 | *verify_group_of_txns(size=5), 56 | 57 | # Check deadline. 58 | Gtxn[0].first_valid() < deadline_tmpl, 59 | 60 | # 1) Add asset. 61 | Gtxn[0].type_enum() == TxnType.AssetTransfer, 62 | Gtxn[0].sender() == buyer_address_tmpl, 63 | Gtxn[0].asset_receiver() == buyer_address_tmpl, 64 | Gtxn[0].asset_amount() == Int(0), 65 | Gtxn[0].xfer_asset() == asset_id_tmpl, 66 | Gtxn[0].asset_close_to() == Global.zero_address(), 67 | 68 | # 2) Send creator cut. 69 | Gtxn[1].type_enum() == TxnType.Payment, 70 | Gtxn[1].sender() == buyer_address_tmpl, 71 | Gtxn[1].receiver() == creator_address_tmpl, 72 | Gtxn[1].amount() == creator_cut_tmpl, 73 | 74 | # 3) Send seller cut. 75 | Gtxn[2].type_enum() == TxnType.Payment, 76 | Gtxn[2].sender() == buyer_address_tmpl, 77 | Gtxn[2].receiver() == seller_address_tmpl, 78 | Gtxn[2].amount() == seller_cut_tmpl, 79 | 80 | # 4) Send platform cut. 81 | Gtxn[3].type_enum() == TxnType.Payment, 82 | Gtxn[3].sender() == buyer_address_tmpl, 83 | Gtxn[3].receiver() == platform_address_tmpl, 84 | Gtxn[3].amount() == platform_cut_tmpl, 85 | 86 | # 5) Receive asset. 87 | Gtxn[4].type_enum() == TxnType.AssetTransfer, 88 | Gtxn[4].sender() != buyer_address_tmpl, 89 | Gtxn[4].asset_receiver() == buyer_address_tmpl, 90 | Gtxn[4].asset_amount() == Int(1), 91 | Gtxn[4].xfer_asset() == asset_id_tmpl, 92 | ) 93 | 94 | program = Cond( 95 | [buy_asset(), Approve()], 96 | ) 97 | 98 | return compileTeal(program, Mode.Signature, version=5) 99 | 100 | 101 | if __name__ == '__main__': 102 | output = approval_program( 103 | asset_id="TMPL_ASSET_ID", 104 | buyer_address="TMPL_BUYER_ADDRESS", 105 | creator_address="TMPL_CREATOR_ADDRESS", 106 | creator_cut="TMPL_CREATOR_CUT", 107 | platform_address="TMPL_PLATFORM_ADDRESS", 108 | platform_cut="TMPL_PLATFORM_CUT", 109 | seller_address="TMPL_SELLER_ADDRESS", 110 | seller_cut="TMPL_SELLER_CUT", 111 | deadline="TMPL_DEADLINE", 112 | ) 113 | sys.stdout.write(output) 114 | sys.stdout.flush() 115 | sys.exit(0) 116 | -------------------------------------------------------------------------------- /offer-algos-for-asset.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pyteal import * 3 | 4 | """ 5 | Helps people offer Algos for assets. 6 | """ 7 | def approval_program(buyer_address, platform_address, asset_id, asset_price, platform_fee, init_fee, royalty_address, royalty_fee): 8 | # Template vars. 9 | buyer_address_tmpl = Tmpl.Addr(buyer_address) 10 | platform_address_tmpl = Tmpl.Addr(platform_address) 11 | asset_id_tmpl = Tmpl.Int(asset_id) 12 | asset_price_tmpl = Tmpl.Int(asset_price) 13 | platform_fee_tmpl = Tmpl.Int(platform_fee) 14 | init_fee_tmpl = Tmpl.Int(init_fee) 15 | royalty_address_tmpl = Tmpl.Addr(royalty_address) 16 | royalty_fee_tmpl = Tmpl.Int(royalty_fee) 17 | 18 | """ 19 | Verifies group size, fees, and rekeys. 20 | """ 21 | def verify_group_of_txns(size): 22 | assertions = [] 23 | 24 | # Verify group is correctly sized. 25 | assertions.append(Global.group_size() == Int(size)) 26 | 27 | # Verify fees are reasonable. 28 | for i in range(size): 29 | assertions.append(Gtxn[i].fee() == Global.min_txn_fee()) 30 | 31 | # Prevent clawbacks. 32 | for i in range(size): 33 | assertions.append(Gtxn[i].asset_sender() == Global.zero_address()) 34 | 35 | # Prevent leases. 36 | for i in range(size): 37 | assertions.append(Gtxn[i].lease() == Global.zero_address()) 38 | 39 | # Prevent rekeys. 40 | for i in range(size): 41 | assertions.append(Gtxn[i].rekey_to() == Global.zero_address()) 42 | 43 | return assertions 44 | 45 | """ 46 | Seller accepts offer. 47 | """ 48 | def seller_accepts_offer(): 49 | ESCROW = Gtxn[0].sender() 50 | SELLER = Gtxn[2].sender() 51 | return And( 52 | *verify_group_of_txns(size = 3), 53 | 54 | # Escrow address is unique. 55 | ESCROW != buyer_address_tmpl, 56 | ESCROW != SELLER, 57 | 58 | # Escrow pays seller. 59 | Gtxn[0].type_enum() == TxnType.Payment, 60 | Gtxn[0].sender() == ESCROW, 61 | Gtxn[0].receiver() == SELLER, 62 | Gtxn[0].amount() == asset_price_tmpl, 63 | Gtxn[0].close_remainder_to() == Global.zero_address(), 64 | 65 | # Escrow pays creator and closes remainder to platform. 66 | Gtxn[1].type_enum() == TxnType.Payment, 67 | Gtxn[1].sender() == ESCROW, 68 | Gtxn[1].receiver() == royalty_address_tmpl, 69 | Gtxn[1].amount() == royalty_fee_tmpl, 70 | Gtxn[1].close_remainder_to() == platform_address_tmpl, 71 | 72 | # Seller sends asset. 73 | Gtxn[2].type_enum() == TxnType.AssetTransfer, 74 | Gtxn[2].sender() == SELLER, 75 | Gtxn[2].asset_receiver() == buyer_address_tmpl, 76 | Gtxn[2].asset_amount() == Int(1), 77 | Gtxn[2].xfer_asset() == asset_id_tmpl, 78 | Gtxn[2].asset_close_to() == Global.zero_address(), 79 | ) 80 | 81 | """ 82 | Buyer withdraws offer. 83 | """ 84 | def buyer_withdraws_offer(): 85 | ESCROW = Gtxn[1].sender() 86 | return And( 87 | *verify_group_of_txns(size = 2), 88 | 89 | # Escrow address is unique. 90 | ESCROW != buyer_address_tmpl, 91 | 92 | # Buyer approves txn group. 93 | Gtxn[0].type_enum() == TxnType.Payment, 94 | Gtxn[0].sender() == buyer_address_tmpl, 95 | Gtxn[0].receiver() == buyer_address_tmpl, 96 | Gtxn[0].amount() == Int(0), 97 | Gtxn[0].close_remainder_to() == Global.zero_address(), 98 | 99 | # Escrow refunds buyer. 100 | Gtxn[1].type_enum() == TxnType.Payment, 101 | Gtxn[1].sender() == ESCROW, 102 | Gtxn[1].receiver() == buyer_address_tmpl, 103 | Gtxn[1].amount() == asset_price_tmpl + royalty_fee_tmpl + platform_fee_tmpl, 104 | Gtxn[1].close_remainder_to() == platform_address_tmpl, 105 | ) 106 | 107 | program = Cond( 108 | [buyer_withdraws_offer(), Approve()], 109 | [seller_accepts_offer(), Approve()], 110 | ) 111 | 112 | return compileTeal(program, Mode.Signature, version=5) 113 | 114 | if __name__ == '__main__': 115 | output = approval_program( 116 | buyer_address="TMPL_BUYER_ADDRESS", 117 | platform_address="TMPL_PLATFORM_ADDRESS", 118 | asset_id="TMPL_ASSET_ID", 119 | asset_price="TMPL_ASSET_PRICE", 120 | platform_fee="TMPL_PLATFORM_FEE", 121 | init_fee="TMPL_INIT_FEE", 122 | royalty_address="TMPL_ROYALTY_ADDRESS", 123 | royalty_fee="TMPL_ROYALTY_FEE" 124 | ) 125 | sys.stdout.write(output) 126 | sys.stdout.flush() 127 | sys.exit(0) 128 | -------------------------------------------------------------------------------- /offer-asset-for-algos.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pyteal import * 3 | 4 | """ 5 | Helps people offer assets for Algos. 6 | """ 7 | def approval_program(seller_address, platform_address, asset_id, asset_price, platform_fee, init_fee, royalty_address, royalty_fee): 8 | # Template vars. 9 | seller_address_tmpl = Tmpl.Addr(seller_address) 10 | platform_address_tmpl = Tmpl.Addr(platform_address) 11 | asset_id_tmpl = Tmpl.Int(asset_id) 12 | asset_price_tmpl = Tmpl.Int(asset_price) 13 | platform_fee_tmpl = Tmpl.Int(platform_fee) 14 | init_fee_tmpl = Tmpl.Int(init_fee) 15 | royalty_address_tmpl = Tmpl.Addr(royalty_address) 16 | royalty_fee_tmpl = Tmpl.Int(royalty_fee) 17 | 18 | """ 19 | Verifies group size, fees, and rekeys. 20 | """ 21 | def verify_group_of_txns(size): 22 | assertions = [] 23 | 24 | # Verify group is correctly sized. 25 | assertions.append(Global.group_size() == Int(size)) 26 | 27 | # Verify fees are reasonable. 28 | for i in range(size): 29 | assertions.append(Gtxn[i].fee() == Global.min_txn_fee()) 30 | 31 | # Prevent clawbacks. 32 | for i in range(size): 33 | assertions.append(Gtxn[i].asset_sender() == Global.zero_address()) 34 | 35 | # Prevent leases. 36 | for i in range(size): 37 | assertions.append(Gtxn[i].lease() == Global.zero_address()) 38 | 39 | # Prevent rekeys. 40 | for i in range(size): 41 | assertions.append(Gtxn[i].rekey_to() == Global.zero_address()) 42 | 43 | return assertions 44 | 45 | """ 46 | Seller offers asset. 47 | """ 48 | def seller_offers_asset(): 49 | ESCROW = Gtxn[0].receiver() 50 | return And( 51 | *verify_group_of_txns(size = 3), 52 | 53 | # Escrow address is unique. 54 | ESCROW != seller_address_tmpl, 55 | 56 | # 1) Seller funds escrow. 57 | Gtxn[0].type_enum() == TxnType.Payment, 58 | Gtxn[0].sender() == seller_address_tmpl, 59 | Gtxn[0].receiver() == ESCROW, 60 | Gtxn[0].amount() == init_fee_tmpl, 61 | Gtxn[0].close_remainder_to() == Global.zero_address(), 62 | 63 | # 2) Escrow accepts ASA. 64 | Gtxn[1].type_enum() == TxnType.AssetTransfer, 65 | Gtxn[1].sender() == ESCROW, 66 | Gtxn[1].asset_receiver() == ESCROW, 67 | Gtxn[1].asset_amount() == Int(0), 68 | Gtxn[1].xfer_asset() == asset_id_tmpl, 69 | Gtxn[1].asset_close_to() == Global.zero_address(), 70 | 71 | # 3) Seller sends ASA. 72 | Gtxn[2].type_enum() == TxnType.AssetTransfer, 73 | Gtxn[2].sender() == seller_address_tmpl, 74 | Gtxn[2].asset_receiver() == ESCROW, 75 | Gtxn[2].asset_amount() == Int(1), 76 | Gtxn[2].xfer_asset() == asset_id_tmpl, 77 | Gtxn[2].asset_close_to() == Global.zero_address(), 78 | ) 79 | 80 | """ 81 | Buyer accepts offer. 82 | """ 83 | def buyer_accepts_offer(): 84 | BUYER = Gtxn[0].sender() 85 | ESCROW = Gtxn[4].sender() 86 | return And( 87 | *verify_group_of_txns(size = 6), 88 | 89 | # Escrow address is unique. 90 | ESCROW != BUYER, 91 | ESCROW != seller_address_tmpl, 92 | 93 | # Buyer pays seller. 94 | Gtxn[0].type_enum() == TxnType.Payment, 95 | Gtxn[0].sender() == BUYER, 96 | Gtxn[0].receiver() == seller_address_tmpl, 97 | Gtxn[0].amount() == asset_price_tmpl, 98 | Gtxn[0].close_remainder_to() == Global.zero_address(), 99 | 100 | # Buyer pays platform. 101 | Gtxn[1].type_enum() == TxnType.Payment, 102 | Gtxn[1].sender() == BUYER, 103 | Gtxn[1].receiver() == platform_address_tmpl, 104 | Gtxn[1].amount() == platform_fee_tmpl, 105 | Gtxn[1].close_remainder_to() == Global.zero_address(), 106 | 107 | # Buyer pays creator. 108 | Gtxn[2].type_enum() == TxnType.Payment, 109 | Gtxn[2].sender() == BUYER, 110 | Gtxn[2].receiver() == royalty_address_tmpl, 111 | Gtxn[2].amount() == royalty_fee_tmpl, 112 | Gtxn[2].close_remainder_to() == Global.zero_address(), 113 | 114 | # Buyer accepts ASA. 115 | Gtxn[3].type_enum() == TxnType.AssetTransfer, 116 | Gtxn[3].sender() == BUYER, 117 | Gtxn[3].asset_receiver() == BUYER, 118 | Gtxn[3].asset_amount() == Int(0), 119 | Gtxn[3].xfer_asset() == asset_id_tmpl, 120 | Gtxn[3].asset_close_to() == Global.zero_address(), 121 | 122 | # Escrow sends ASA. 123 | Gtxn[4].type_enum() == TxnType.AssetTransfer, 124 | Gtxn[4].sender() == ESCROW, 125 | Gtxn[4].asset_receiver() == BUYER, 126 | Gtxn[4].asset_amount() == Int(1), 127 | Gtxn[4].xfer_asset() == asset_id_tmpl, 128 | Gtxn[4].asset_close_to() == BUYER, 129 | 130 | # Escrows refunds seller. 131 | Gtxn[5].type_enum() == TxnType.Payment, 132 | Gtxn[5].sender() == ESCROW, 133 | Gtxn[5].receiver() == seller_address_tmpl, 134 | Gtxn[5].amount() == Int(0), 135 | Gtxn[5].close_remainder_to() == seller_address_tmpl, 136 | ) 137 | 138 | """ 139 | Seller withdraws offer. 140 | """ 141 | def seller_withdraws_offer(): 142 | ESCROW = Gtxn[1].sender() 143 | return And( 144 | *verify_group_of_txns(size = 3), 145 | 146 | # Escrow address is unique. 147 | ESCROW != seller_address_tmpl, 148 | 149 | # Seller accepts ASA. 150 | Gtxn[0].type_enum() == TxnType.AssetTransfer, 151 | Gtxn[0].sender() == seller_address_tmpl, 152 | Gtxn[0].asset_receiver() == seller_address_tmpl, 153 | Gtxn[0].asset_amount() == Int(0), 154 | Gtxn[0].xfer_asset() == asset_id_tmpl, 155 | Gtxn[0].asset_close_to() == Global.zero_address(), 156 | 157 | # Escrow sends ASA. 158 | Gtxn[1].type_enum() == TxnType.AssetTransfer, 159 | Gtxn[1].sender() == ESCROW, 160 | Gtxn[1].asset_receiver() == seller_address_tmpl, 161 | Gtxn[1].asset_amount() == Int(1), 162 | Gtxn[1].xfer_asset() == asset_id_tmpl, 163 | Gtxn[1].asset_close_to() == seller_address_tmpl, 164 | 165 | # Escrow refunds seller. 166 | Gtxn[2].type_enum() == TxnType.Payment, 167 | Gtxn[2].sender() == ESCROW, 168 | Gtxn[2].receiver() == seller_address_tmpl, 169 | Gtxn[2].amount() == Int(0), 170 | Gtxn[2].close_remainder_to() == seller_address_tmpl, 171 | ) 172 | 173 | program = Cond( 174 | [seller_offers_asset(), Approve()], 175 | [seller_withdraws_offer(), Approve()], 176 | [buyer_accepts_offer(), Approve()], 177 | ) 178 | 179 | return compileTeal(program, Mode.Signature, version=5) 180 | 181 | if __name__ == '__main__': 182 | output = approval_program( 183 | seller_address="TMPL_SELLER_ADDRESS", 184 | platform_address="TMPL_PLATFORM_ADDRESS", 185 | asset_id="TMPL_ASSET_ID", 186 | asset_price="TMPL_ASSET_PRICE", 187 | platform_fee="TMPL_PLATFORM_FEE", 188 | init_fee="TMPL_INIT_FEE", 189 | royalty_address="TMPL_ROYALTY_ADDRESS", 190 | royalty_fee="TMPL_ROYALTY_FEE" 191 | ) 192 | sys.stdout.write(output) 193 | sys.stdout.flush() 194 | sys.exit(0) 195 | -------------------------------------------------------------------------------- /offer-asset-for-algos.teal: -------------------------------------------------------------------------------- 1 | #pragma version 5 2 | global GroupSize 3 | int 3 4 | == 5 | gtxn 0 Fee 6 | global MinTxnFee 7 | == 8 | && 9 | gtxn 1 Fee 10 | global MinTxnFee 11 | == 12 | && 13 | gtxn 2 Fee 14 | global MinTxnFee 15 | == 16 | && 17 | gtxn 0 AssetSender 18 | global ZeroAddress 19 | == 20 | && 21 | gtxn 1 AssetSender 22 | global ZeroAddress 23 | == 24 | && 25 | gtxn 2 AssetSender 26 | global ZeroAddress 27 | == 28 | && 29 | gtxn 0 Lease 30 | global ZeroAddress 31 | == 32 | && 33 | gtxn 1 Lease 34 | global ZeroAddress 35 | == 36 | && 37 | gtxn 2 Lease 38 | global ZeroAddress 39 | == 40 | && 41 | gtxn 0 RekeyTo 42 | global ZeroAddress 43 | == 44 | && 45 | gtxn 1 RekeyTo 46 | global ZeroAddress 47 | == 48 | && 49 | gtxn 2 RekeyTo 50 | global ZeroAddress 51 | == 52 | && 53 | gtxn 0 Receiver 54 | addr TMPL_SELLER_ADDRESS 55 | != 56 | && 57 | gtxn 0 TypeEnum 58 | int pay 59 | == 60 | && 61 | gtxn 0 Sender 62 | addr TMPL_SELLER_ADDRESS 63 | == 64 | && 65 | gtxn 0 Receiver 66 | gtxn 0 Receiver 67 | == 68 | && 69 | gtxn 0 Amount 70 | int TMPL_INIT_FEE 71 | == 72 | && 73 | gtxn 0 CloseRemainderTo 74 | global ZeroAddress 75 | == 76 | && 77 | gtxn 1 TypeEnum 78 | int axfer 79 | == 80 | && 81 | gtxn 1 Sender 82 | gtxn 0 Receiver 83 | == 84 | && 85 | gtxn 1 AssetReceiver 86 | gtxn 0 Receiver 87 | == 88 | && 89 | gtxn 1 AssetAmount 90 | int 0 91 | == 92 | && 93 | gtxn 1 XferAsset 94 | int TMPL_ASSET_ID 95 | == 96 | && 97 | gtxn 1 AssetCloseTo 98 | global ZeroAddress 99 | == 100 | && 101 | gtxn 2 TypeEnum 102 | int axfer 103 | == 104 | && 105 | gtxn 2 Sender 106 | addr TMPL_SELLER_ADDRESS 107 | == 108 | && 109 | gtxn 2 AssetReceiver 110 | gtxn 0 Receiver 111 | == 112 | && 113 | gtxn 2 AssetAmount 114 | int 1 115 | == 116 | && 117 | gtxn 2 XferAsset 118 | int TMPL_ASSET_ID 119 | == 120 | && 121 | gtxn 2 AssetCloseTo 122 | global ZeroAddress 123 | == 124 | && 125 | bnz main_l6 126 | global GroupSize 127 | int 3 128 | == 129 | gtxn 0 Fee 130 | global MinTxnFee 131 | == 132 | && 133 | gtxn 1 Fee 134 | global MinTxnFee 135 | == 136 | && 137 | gtxn 2 Fee 138 | global MinTxnFee 139 | == 140 | && 141 | gtxn 0 AssetSender 142 | global ZeroAddress 143 | == 144 | && 145 | gtxn 1 AssetSender 146 | global ZeroAddress 147 | == 148 | && 149 | gtxn 2 AssetSender 150 | global ZeroAddress 151 | == 152 | && 153 | gtxn 0 Lease 154 | global ZeroAddress 155 | == 156 | && 157 | gtxn 1 Lease 158 | global ZeroAddress 159 | == 160 | && 161 | gtxn 2 Lease 162 | global ZeroAddress 163 | == 164 | && 165 | gtxn 0 RekeyTo 166 | global ZeroAddress 167 | == 168 | && 169 | gtxn 1 RekeyTo 170 | global ZeroAddress 171 | == 172 | && 173 | gtxn 2 RekeyTo 174 | global ZeroAddress 175 | == 176 | && 177 | gtxn 1 Sender 178 | addr TMPL_SELLER_ADDRESS 179 | != 180 | && 181 | gtxn 0 TypeEnum 182 | int axfer 183 | == 184 | && 185 | gtxn 0 Sender 186 | addr TMPL_SELLER_ADDRESS 187 | == 188 | && 189 | gtxn 0 AssetReceiver 190 | addr TMPL_SELLER_ADDRESS 191 | == 192 | && 193 | gtxn 0 AssetAmount 194 | int 0 195 | == 196 | && 197 | gtxn 0 XferAsset 198 | int TMPL_ASSET_ID 199 | == 200 | && 201 | gtxn 0 AssetCloseTo 202 | global ZeroAddress 203 | == 204 | && 205 | gtxn 1 TypeEnum 206 | int axfer 207 | == 208 | && 209 | gtxn 1 Sender 210 | gtxn 1 Sender 211 | == 212 | && 213 | gtxn 1 AssetReceiver 214 | addr TMPL_SELLER_ADDRESS 215 | == 216 | && 217 | gtxn 1 AssetAmount 218 | int 1 219 | == 220 | && 221 | gtxn 1 XferAsset 222 | int TMPL_ASSET_ID 223 | == 224 | && 225 | gtxn 1 AssetCloseTo 226 | addr TMPL_SELLER_ADDRESS 227 | == 228 | && 229 | gtxn 2 TypeEnum 230 | int pay 231 | == 232 | && 233 | gtxn 2 Sender 234 | gtxn 1 Sender 235 | == 236 | && 237 | gtxn 2 Receiver 238 | addr TMPL_SELLER_ADDRESS 239 | == 240 | && 241 | gtxn 2 Amount 242 | int 0 243 | == 244 | && 245 | gtxn 2 CloseRemainderTo 246 | addr TMPL_SELLER_ADDRESS 247 | == 248 | && 249 | bnz main_l5 250 | global GroupSize 251 | int 6 252 | == 253 | gtxn 0 Fee 254 | global MinTxnFee 255 | == 256 | && 257 | gtxn 1 Fee 258 | global MinTxnFee 259 | == 260 | && 261 | gtxn 2 Fee 262 | global MinTxnFee 263 | == 264 | && 265 | gtxn 3 Fee 266 | global MinTxnFee 267 | == 268 | && 269 | gtxn 4 Fee 270 | global MinTxnFee 271 | == 272 | && 273 | gtxn 5 Fee 274 | global MinTxnFee 275 | == 276 | && 277 | gtxn 0 AssetSender 278 | global ZeroAddress 279 | == 280 | && 281 | gtxn 1 AssetSender 282 | global ZeroAddress 283 | == 284 | && 285 | gtxn 2 AssetSender 286 | global ZeroAddress 287 | == 288 | && 289 | gtxn 3 AssetSender 290 | global ZeroAddress 291 | == 292 | && 293 | gtxn 4 AssetSender 294 | global ZeroAddress 295 | == 296 | && 297 | gtxn 5 AssetSender 298 | global ZeroAddress 299 | == 300 | && 301 | gtxn 0 Lease 302 | global ZeroAddress 303 | == 304 | && 305 | gtxn 1 Lease 306 | global ZeroAddress 307 | == 308 | && 309 | gtxn 2 Lease 310 | global ZeroAddress 311 | == 312 | && 313 | gtxn 3 Lease 314 | global ZeroAddress 315 | == 316 | && 317 | gtxn 4 Lease 318 | global ZeroAddress 319 | == 320 | && 321 | gtxn 5 Lease 322 | global ZeroAddress 323 | == 324 | && 325 | gtxn 0 RekeyTo 326 | global ZeroAddress 327 | == 328 | && 329 | gtxn 1 RekeyTo 330 | global ZeroAddress 331 | == 332 | && 333 | gtxn 2 RekeyTo 334 | global ZeroAddress 335 | == 336 | && 337 | gtxn 3 RekeyTo 338 | global ZeroAddress 339 | == 340 | && 341 | gtxn 4 RekeyTo 342 | global ZeroAddress 343 | == 344 | && 345 | gtxn 5 RekeyTo 346 | global ZeroAddress 347 | == 348 | && 349 | gtxn 4 Sender 350 | gtxn 0 Sender 351 | != 352 | && 353 | gtxn 4 Sender 354 | addr TMPL_SELLER_ADDRESS 355 | != 356 | && 357 | gtxn 0 TypeEnum 358 | int pay 359 | == 360 | && 361 | gtxn 0 Sender 362 | gtxn 0 Sender 363 | == 364 | && 365 | gtxn 0 Receiver 366 | addr TMPL_SELLER_ADDRESS 367 | == 368 | && 369 | gtxn 0 Amount 370 | int TMPL_ASSET_PRICE 371 | == 372 | && 373 | gtxn 0 CloseRemainderTo 374 | global ZeroAddress 375 | == 376 | && 377 | gtxn 1 TypeEnum 378 | int pay 379 | == 380 | && 381 | gtxn 1 Sender 382 | gtxn 0 Sender 383 | == 384 | && 385 | gtxn 1 Receiver 386 | addr TMPL_PLATFORM_ADDRESS 387 | == 388 | && 389 | gtxn 1 Amount 390 | int TMPL_PLATFORM_FEE 391 | == 392 | && 393 | gtxn 1 CloseRemainderTo 394 | global ZeroAddress 395 | == 396 | && 397 | gtxn 2 TypeEnum 398 | int pay 399 | == 400 | && 401 | gtxn 2 Sender 402 | gtxn 0 Sender 403 | == 404 | && 405 | gtxn 2 Receiver 406 | addr TMPL_ROYALTY_ADDRESS 407 | == 408 | && 409 | gtxn 2 Amount 410 | int TMPL_ROYALTY_FEE 411 | == 412 | && 413 | gtxn 2 CloseRemainderTo 414 | global ZeroAddress 415 | == 416 | && 417 | gtxn 3 TypeEnum 418 | int axfer 419 | == 420 | && 421 | gtxn 3 Sender 422 | gtxn 0 Sender 423 | == 424 | && 425 | gtxn 3 AssetReceiver 426 | gtxn 0 Sender 427 | == 428 | && 429 | gtxn 3 AssetAmount 430 | int 0 431 | == 432 | && 433 | gtxn 3 XferAsset 434 | int TMPL_ASSET_ID 435 | == 436 | && 437 | gtxn 3 AssetCloseTo 438 | global ZeroAddress 439 | == 440 | && 441 | gtxn 4 TypeEnum 442 | int axfer 443 | == 444 | && 445 | gtxn 4 Sender 446 | gtxn 4 Sender 447 | == 448 | && 449 | gtxn 4 AssetReceiver 450 | gtxn 0 Sender 451 | == 452 | && 453 | gtxn 4 AssetAmount 454 | int 1 455 | == 456 | && 457 | gtxn 4 XferAsset 458 | int TMPL_ASSET_ID 459 | == 460 | && 461 | gtxn 4 AssetCloseTo 462 | gtxn 0 Sender 463 | == 464 | && 465 | gtxn 5 TypeEnum 466 | int pay 467 | == 468 | && 469 | gtxn 5 Sender 470 | gtxn 4 Sender 471 | == 472 | && 473 | gtxn 5 Receiver 474 | addr TMPL_SELLER_ADDRESS 475 | == 476 | && 477 | gtxn 5 Amount 478 | int 0 479 | == 480 | && 481 | gtxn 5 CloseRemainderTo 482 | addr TMPL_SELLER_ADDRESS 483 | == 484 | && 485 | bnz main_l4 486 | err 487 | main_l4: 488 | int 1 489 | return 490 | main_l5: 491 | int 1 492 | return 493 | main_l6: 494 | int 1 495 | return -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [2022] [Rand Gallery LLC] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. --------------------------------------------------------------------------------