Unit ID
9rx2dzHhfZ4bsLVKYDYeb4gNC+0Yzr6a7Ps9cT4byEU=
Received
04.04.2021 20:27:51
Confirmation delay (full node)
2 minutes 59 seconds
Messages
Definition
Definition: [ "autonomous agent", { "bounce_fees": { "base": 10000 }, "init": "{\r $HOUSE_CUT = 0.1; //We will take this cut on the debut of an NFT in our platform. We charge 0.1% for foreign NFTs.\r $FREEMARKET_CUT = 0.01; //We take 1% on every foreign NFT trade\r $ARTIST_CUT = 0.01; //The artist will get 1% from every resale of their NFT\r $INVESTMENT_CUT = 0.01;//We take a 1% cut from all maecenas investments\r $HALF_HOUR = 1800; //30m = 1800s. An auction is extended by 1800s every time there is a new bid near the deadline\r $RESERVE_AMOUNT = 200000; //We will always keep > 200.000 in the AA\r $MIN_BID_INCREMENT = 0.0001;\r \r $extendDeadLine = $NFT=>($NFT.soldAt <= timestamp + $HALF_HOUR) ? ($NFT || {soldAt: $NFT.soldAt + $HALF_HOUR}) : $NFT; //Extend the auction if there is a bid less than half an hour before the auction is closed\r /*\r ** Strips $NFT of computed fields to reduce AA's storage size\r */\r $stripToken = $NFT=>{\r delete($NFT, "isBanned");\r delete($NFT, "issuer");\r delete($NFT, "cap");\r delete($NFT, "mintedAt");\r delete($NFT, "duration"); //For foreign NFTs\r delete($NFT, "meta");\r return $NFT;\r };\r \r if (NOT trigger.data["method"])\r bounce("method field is mandatory");\r \r $method = trigger.data["method"];\r \r $spendableFunds = balance["base"] - var["locked"] - storage_size - $RESERVE_AMOUNT;\r $owner = var["owner"];\r $calculateSharesToBuy = ($price, $pool, $myShare)=>ln($price / ($pool * $myShare)) / ln($myShare);\r $_maecenasCurve = $x=>6969420 * $x^2;\r }", "getters": "{\r $saleInfo = $NFT=>{\r $unit = unit[$NFT];\r $info = var["NFT_" || $NFT];\r \r if (NOT $info)\r bounce("That NFT is not for sale or does not exist");\r \r return $info || {\r cap: $unit.messages[[.app="asset"]].payload.cap,\r mintedAt: $unit.timestamp\r };\r };\r /*\r ** All the artist information\r */\r $artistInfo = $artist=>var["artist_" || $artist];\r $profile = $artist=>var["profile_" || $artist];\r }", "messages": { "cases": [ { "if": "{\r NOT $owner //The owner has not been set\r }", "messages": [ { "app": "state", "state": "{\r var["owner"] = "IUU43O7TS2TBYKAPGKUARDZHOTAE275A"; //Set the Owner to my address\r var["locked"] = 0; //Bytes locked in bids are not withdrawable by the Owner\r }" } ] }, { "if": "{\r trigger.address == $owner\r AND ($method == "payout"\r OR $method == "approve"\r OR $method == "transferOwnership"\r OR $method == "setHelper"\r OR $method == "verifyProfile")\r }", "messages": { "cases": [ { "if": "{\r $method == "payout"\r }", "messages": [ { "app": "payment", "payload": { "asset": "base", "outputs": [ { "address": "{trigger.address}" } ] } } ] }, { "if": "{\r $method == "approve"\r }", "init": "{\r if (NOT trigger.data["NFT"])\r bounce("NFT field is mandatory");\r \r $NFT = var["pending_" || trigger.data["NFT"]];\r \r if (NOT $NFT)\r bounce("That NFT is not known by this AA");\r }", "messages": [ { "app": "state", "state": "{\r $isFreeNFT = var["free_" || trigger.data["NFT"]];\r if ($isFreeNFT)\r var["free_" || trigger.data["NFT"]] = false; //Delete previous data so it is no longer tradable in the free market\r \r var["SOLD_" || trigger.data["NFT"]] = {\r author: "foreign",\r ipfs: $NFT.ipfs,\r type: $NFT.type\r };\r \r var["pending_" || trigger.data["NFT"]] = false; //Delete from the pendingApproval list\r }" } ] }, { "if": "{\r $method == "verifyProfile"\r }", "init": "{\r if (NOT trigger.data["artist"])\r bounce("artist field is mandatory");\r }", "messages": [ { "app": "attestation", "payload": "{var["profile_" || trigger.data["artist"]]}" }, { "app": "state", "state": "{\r var["profile_" || trigger.data["artist"]] ||= {verified: true};\r }" } ] }, { "if": "{\r $method == "transferOwnership"\r }", "init": "{\r if (NOT trigger.data["newOwner"])\r bounce("newOwner field is mandatory");\r if (NOT is_valid_address(trigger.data["newOwner"]))\r bounce("newOwner field is not a valid address");\r }", "messages": [ { "app": "payment", "payload": { "asset": "base", "outputs": [ { "address": "{trigger.address}", "amount": "{$spendableFunds}" } ] } }, { "app": "state", "state": "{\r var["owner"] = trigger.data["newOwner"];//Ownership is transferred\r }" } ] }, { "if": "{\r $method == "setHelper"\r }", "init": "{\r if (NOT trigger.data["helper"])\r bounce("helper field is mandatory");\r }", "messages": [ { "app": "state", "state": "{\r var["helper"] = trigger.data["helper"];\r }" } ] } ] } }, { "if": "{\r (trigger.address == $owner OR trigger.address == var["helper"])\r AND $method == "revoke"\r }", "init": "{\r if (NOT trigger.data["NFT"])\r bounce("NFT field is mandatory");\r }", "messages": [ { "app": "data_feed", "payload": { "{trigger.data["NFT"]}": "REVOKED" } } ] }, { "if": "{\r $method == "MINT"\r }", "init": "{\r if (NOT trigger.data["amount"])\r bounce("amount field is mandatory");\r if (NOT is_valid_amount(trigger.data["amount"]))\r bounce("The amount of NFT copies to mint is not valid");\r \r if (NOT trigger.data["ipfs"])\r bounce("ipfs field is mandatory");\r \r if (NOT trigger.data["type"])\r bounce("type field is mandatory");\r \r if (NOT is_valid_address(trigger.data["seller"]))\r bounce("The seller address is not valid");\r \r if (NOT trigger.data["endTime"])\r bounce("endTime field is mandatory");\r \r if (trigger.data["endTime"] <= timestamp)\r bounce("The endTime cannot be set in the past");\r \r if ($owner != trigger.address){ //The owner reserves the right to post sales with longer deadlines (e.g: for licenses)\r if (trigger.data["endTime"] - timestamp > 2628000)\r bounce("You cannot set the end time in more than 30 days in the future");\r }\r \r $seller = (trigger.address == $owner) //Only the owner can list NFTs in behalf of others\r ? trigger.data["seller"]\r : trigger.address;\r \r $key = ((trigger.address == $owner)\r ? "NFT_"\r : "FREE_");\r }", "messages": { "cases": [ { "if": "{\r trigger.data["amount"] == 1\r }", "messages": [ { "app": "asset", "payload": { "cap": 1, "is_private": false, "is_transferrable": true, "auto_destroy": false, "fixed_denominations": false, "issued_by_definer_only": true, "cosigned_by_definer": false, "spender_attested": false } }, { "app": "data", "if": "{\r var["recordToData"]\r }", "payload": { "asset": "{var["recordToData"]}", "name": "{trigger.data["title"] OTHERWISE "Untitled"}", "decimals": 0 } }, { "app": "state", "state": "{\r var[$key || response_unit] = {\r bid: 20000, //Max current bid (a NFT can have this field because it was resold. Check for price field instead)\r bids: 0,\r type: trigger.data["type"],\r by: trigger.data["seller"],\r at: timestamp, //Max bid time\r ipfs: trigger.data["ipfs"], //Hash of the content\r author: $seller, //The original seller\r soldAt: trigger.data["endTime"], //End of the auction\r soldBy: $seller //Who is currently selling the NFT\r };\r \r if (typeof(trigger.data["meta"]) == "object")\r var["meta_" || response_unit] = trigger.data["meta"];\r \r var["recordToData"] = response_unit;\r }" } ] }, { "init": "{\r $price = trigger.data["price"];\r if (NOT $price)\r bounce("price field is mandatory if you intend to sell more than one NFT copy");\r if ($price < 20000)\r bounce("The minium price is 20000 bytes");\r if (NOT is_valid_amount($price))\r bounce("price is not valid");\r }", "messages": [ { "app": "asset", "if": "{\r trigger.data["amount"] == 0 //Uncapped asset, no more units can be issued after endTime\r }", "payload": { "is_private": false, "is_transferrable": true, "auto_destroy": false, "fixed_denominations": false, "issued_by_definer_only": true, "cosigned_by_definer": false, "spender_attested": false } }, { "app": "asset", "if": "{\r trigger.data["amount"] > 0\r }", "payload": { "cap": "{trigger.data["amount"]}", "is_private": false, "is_transferrable": true, "auto_destroy": false, "fixed_denominations": false, "issued_by_definer_only": true, "cosigned_by_definer": false, "spender_attested": false } }, { "app": "state", "state": "{\r var[$key || response_unit] = {\r price: $price, //Sale price (this field is only present if the first sale was a fixed price one)\r type: trigger.data["type"],\r at: timestamp, //Max bid time\r ipfs: trigger.data["ipfs"], //Hash of the content\r unitsSold: 0,\r author: $seller, //The original seller\r soldAt: trigger.data["endTime"], //End of the auction\r soldBy: $seller //Who is currently selling the NFT\r };\r if (typeof(trigger.data["meta"]) == "object")\r var["meta_" || response_unit] = trigger.data["meta"];\r }" } ] } ] } }, { "if": "{\r $method == "BUY"\r OR $method == "DIVEST"\r OR $method == "CLAIM"\r }", "init": "{\r $NFT = exists(trigger.data["NFT"])\r ? $saleInfo(trigger.data["NFT"])\r : false;\r \r \r $artist = $method == "DIVEST"\r ? $artistInfo(trigger.data["artist"])\r : $artistInfo($NFT.author);\r \r \r if ($method == "BUY"){ //Validate buy params\r if (NOT exists(trigger.data["NFT"]))\r bounce("NFT field is mandatory");\r \r $isAuction = $NFT.bid ? true : false; //It can only NOT be an auction if it is first sold and thus $NFT.bid does not exist\r \r if ($isAuction)\r $hasBidders = ($NFT.soldBy != $NFT.by) ? true : false; //Booleans cannot be compared\r \r if ($isAuction AND NOT $NFT.by)\r bounce("There are no copies of that NFT listed for sale at the moment");\r \r if (timestamp > $NFT.soldAt){\r if ($isAuction){\r if ($hasBidders) //You can still buy it if there were no bidders\r bounce("The auction is over");\r }\r else{\r bounce("The sale is already over");\r }\r }\r }\r \r else if ($method == "DIVEST"){ //Validate divest params\r if (NOT trigger.data["artist"])\r bounce("artist field is mandatory");\r if (NOT is_valid_address(trigger.data["artist"]))\r bounce("artist's address is invalid");\r \r if (NOT $artist)\r bounce("That artist never accepted maecenas");\r \r if (NOT exists(trigger.data["amount"]))\r bounce("amount field is mandatory");\r if (NOT is_integer(trigger.data["amount"]) OR trigger.data["amount"] <= 0)\r bounce("amount must be an integer > 0");\r \r $investedAmount = var["maecenas_" || trigger.address || "_" || trigger.data["artist"]];\r \r if (NOT $investedAmount)\r bounce("You have no shares of that artist");\r \r if (trigger.data["amount"] > $investedAmount)\r bounce("You only have " || $investedAmount || " shares of that artist");\r \r $yourShare = floor($artist.share * trigger.data["amount"] / $artist.supply, 0);\r \r if ($yourShare < 20000)\r bounce("It is not worth divesting your share");\r }\r \r else if ($method == "CLAIM"){ //Validate claim params\r if (NOT trigger.data["NFT"])\r bounce("NFT field is mandatory");\r \r $isAuction = $NFT.bid ? true : false;\r \r if (NOT $isAuction)\r bounce("You cannot claim a non-auction sale");\r \r $hasBidders = ($NFT.soldBy != $NFT.by) ? true : false;\r \r if (timestamp <= $NFT.soldAt)\r bounce("The auction is not over yet");\r \r if ($NFT.bid == 0)\r bounce("That auction was already claimed");\r }\r \r if ($artist AND (($isAuction AND $hasBidders) OR (NOT $isAuction))){\r $allowsMaecenas = ($artist.sharePercent >= 0.01) ? true : false;\r $hasMaecenas = $allowsMaecenas\r ? $artist.supply > 0\r ? true\r : false\r : false;\r \r \r if ($allowsMaecenas){ \r if ($method == "BUY")\r $maecenasShare = $artist.sharePercent * trigger.output[[asset="base"]].amount;\r else if ($method == "CLAIM" AND $hasBidders)\r $maecenasShare = $artist.sharePercent * $NFT.bid;\r else\r $maecenasShare = 0;\r \r $sharesInThePool = ($method != "DIVEST")\r ? $artist.supply\r : ($artist.supply - trigger.data["amount"]); //If divesting we need to substract divested shares\r \r if ($method == "DIVEST")\r $p = $artist.share - floor((trigger.data["amount"] / $artist.supply) * $artist.share, 0); //Current share minus what was just divested\r else\r $p = $artist.share + $maecenasShare; //Pool value after the sale\r \r $k = 1 / ($sharesInThePool + 1); //The fraction of the pool 1 share represents\r $price = $_maecenasCurve($sharesInThePool + 1); //Price of buying one share\r \r \r if ($method == "BUY"){\r if ($NFT.soldBy == $NFT.author){ //We do not need to check for auction as we do not invest in those until the claim phase\r $totalSpendable = floor(\r $spendableFunds\r + $price * $INVESTMENT_CUT //What I save from investment cut as it is paid to myself\r + floor(trigger.output[[asset="base"]].amount * $HOUSE_CUT, 0) //What I got as cut from the triggering tx\r , 0);\r }\r else{\r $totalSpendable = floor(\r $spendableFunds\r + $price * $INVESTMENT_CUT //What I save from investment cut as it is paid to myself\r - trigger.output[[asset="base"]].amount //Cannot spend the trigering tx as it will be locked\r , 0);\r }\r }\r else if ($method == "CLAIM"){\r $totalSpendable = floor(\r $spendableFunds //Initial amount\r + $price * $INVESTMENT_CUT //What I save from investment cut\r + $NFT.bid * (1 - $HOUSE_CUT) //What I get from house cut\r , 0);\r }\r else{\r $totalSpendable = floor($spendableFunds + $price * $INVESTMENT_CUT, 0);\r }\r \r $sharesToBuy = $sharesInThePool == 0 ? 0 : ceil($calculateSharesToBuy($price, $p, $k), 0);//Can be 0 and I would still afford 1 share if profitable\r \r if ($k == 1){\r $sharesICanAfford = $price < $totalSpendable ? 1 : 0;\r }\r else {\r if ($totalSpendable > $price AND $sharesToBuy >= 1){\r $sharesICanAfford = floor($totalSpendable / ($price * $sharesToBuy * (1 - $INVESTMENT_CUT)), 0); //Do not buy more shares than what I can afford\r }\r else{\r $sharesICanAfford = 0;\r }\r }\r }\r \r if ($allowsMaecenas AND $sharesICanAfford > 0){\r $buyShares = true;\r }\r else{\r $buyShares = false;\r }\r \r $shareIWillfinallyBuy = min($sharesToBuy, $sharesICanAfford); //Maybe I can afford more shares than what is profitable to buy\r $myProfit = floor($buyShares ? $p - $p * $k^$shareIWillfinallyBuy : 0, 0); //0 if no shares are bought\r $poolFinalValue = $p - $myProfit; //Not actual profit but what I got out of the pool\r }\r else {\r $allowsMaecenas = false;\r $buyShares = false;\r $hasMaecenas = false;\r $maecenasShare = 0;\r $myProfit = 0;\r $poolFinalValue = 0;\r }\r }", "messages": { "cases": [ { "if": "{\r trigger.data["method"] == "BUY"\r }", "messages": { "cases": [ { "if": "{\r $isAuction\r }", "init": "{\r if (trigger.output[[asset="base"]].amount < 20000)\r bounce("The minimum bid is 20000 bytes");\r if (trigger.output[[asset="base"]].amount <= $NFT.bid * (1 + $MIN_BID_INCREMENT))\r bounce("Your bid must be at least " || $NFT.bid * (1 + $MIN_BID_INCREMENT) || " (0.01% higher than the current)");\r \r if ($NFT.soldBy == trigger.address)\r bounce("You cannot bid on your own auction");\r }", "messages": [ { "app": "payment", "if": "{\r $NFT.by != $NFT.soldBy //If we don't check for this the artists could steal bytes from the AA\r }", "payload": { "asset": "base", "outputs": [ { "address": "{$NFT.by}", "amount": "{$NFT.bid - 10000}" } ] } }, { "app": "state", "state": "{\r var["locked"] += trigger.output[[asset="base"]].amount - ($hasBidders ? $NFT.bid : 0); //Increase non-withdrawable funds by the difference between previous and last bid\r $NFT.bid = trigger.output[[asset="base"]].amount;\r $NFT.at = timestamp;\r $NFT.bids = $NFT.bids + 1;\r $NFT.by = trigger.address;\r var["NFT_" || trigger.data["NFT"]] ||= $stripToken($extendDeadLine($NFT));\r }" } ] }, { "init": "{\r if ($NFT.unitsSold == $NFT.cap AND $NFT.cap != 0) //We need to make an additional check for uncapped assets\r bounce("All NFT copies have been already sold");\r \r if (trigger.output[[asset="base"]].amount < $NFT.price)\r bounce("Your payment is lower than the NFT price. You have to send " || $NFT.price || " bytes");\r }", "messages": [ { "app": "payment", "if": "{\r floor($NFT.price * (1 - $HOUSE_CUT - ($allowsMaecenas ? (($hasMaecenas OR $buyShares) ? $artist.sharePercent : 0) : 0)) - 10000, 0) > 0\r }", "payload": { "asset": "base", "outputs": [ { "address": "{$NFT.soldBy}", "amount": "{floor($NFT.price * (1 - $HOUSE_CUT - ($allowsMaecenas ? (($hasMaecenas OR $buyShares) ? $artist.sharePercent : 0) : 0)) - 10000, 0)}" } ] } }, { "app": "payment", "payload": { "asset": "{trigger.data['NFT']}", "outputs": [ { "address": "{trigger.address}", "amount": 1 } ] } }, { "app": "state", "state": "{\r var["NFT_" || trigger.data["NFT"]] ||= {unitsSold: $NFT.unitsSold + 1};\r if ($hasMaecenas){\r var["locked"] += $maecenasShare - $myProfit;\r var["artist_" || $NFT.author] ||= {share: $poolFinalValue};\r }\r if ($NFT.unitsSold + 1 == $NFT.cap){\r var["NFT_" || trigger.data["NFT"]] = false; //Delist it from sale\r var["SOLD_" || trigger.data["NFT"]] = $stripToken($NFT); //Add it to meta\r }\r }" } ] } ] } }, { "if": "{\r trigger.data["method"] == "CLAIM"\r }", "messages": { "cases": [ { "if": "{//NFT was first sold\r $NFT.soldBy == $NFT.author\r }", "init": "{\r if ($hasMaecenas OR $buyShares){\r $paymentFromShares = $shareIWillfinallyBuy * round($price * (1 - $INVESTMENT_CUT), 0);\r $sellerPayout = floor($NFT.bid * (1 - $HOUSE_CUT - $artist.sharePercent) - 10000 + $paymentFromShares, 0);\r }\r else {\r $sellerPayout = floor($NFT.bid * (1 - $HOUSE_CUT) - 10000, 0);\r }\r }", "messages": [ { "app": "payment", "if": "{\r $sellerPayout > 0 //enough to be worth paying\r AND $NFT.soldBy != $NFT.by //there is at least a bid\r }", "payload": { "asset": "base", "outputs": [ { "address": "{$NFT.soldBy}", "amount": "{$sellerPayout}" } ] } }, { "app": "payment", "payload": { "asset": "{trigger.data['NFT']}", "outputs": [ { "address": "{$NFT.by}", "amount": 1 } ] } }, { "app": "state", "state": "{\r $decrement = $hasMaecenas //My share does not play a role here\r ? $NFT.bid - $maecenasShare //If it had maecenas the maecenas share remains locked\r : $NFT.bid; //If it does not have maecenas all bytes are unlocked\r \r if ($NFT.bid > 20000) //If it had no bids you don't need to reduce locked amount\r var["locked"] -= $decrement; //These bytes are no longer locked as the artist is getting them in this same unit\r \r var["SOLD_" || trigger.data["NFT"]] = $stripToken($NFT); //Save for the next auction\r var["NFT_" || trigger.data["NFT"]] = false; //No longer listed for sale\r \r if ($hasMaecenas AND $NFT.bid > 20000)\r var["artist_" || $NFT.author] ||= {share: $artist.share + $maecenasShare}; //Increase the artist pool value\r }" } ] }, { "messages": [ { "app": "payment", "if": "{\r $NFT.soldBy != $NFT.by //If we don't do this check the seller could steal bytes from the AA if there were no bids\r }", "payload": { "asset": "base", "outputs": { "cases": [ { "if": "{\r floor($NFT.bid * $ARTIST_CUT, 0) - 10000 > 0 //It is worth paying the original artist\r }", "outputs": [ { "address": "{$NFT.soldBy}", "amount": "{floor($NFT.bid * (1 - $ARTIST_CUT) - 10000, 0)}" }, { "address": "{$NFT.author}", "amount": "{floor($NFT.bid * $ARTIST_CUT, 0) - 10000}" } ] }, { "outputs": [ { "address": "{$NFT.soldBy}", "amount": "{floor($NFT.bid * (1 - $ARTIST_CUT) - 10000, 0)}" } ] } ] } } }, { "app": "payment", "payload": { "asset": "{trigger.data['NFT']}", "outputs": [ { "address": "{$NFT.by}", "amount": 1 } ] } }, { "app": "state", "state": "{\r var["locked"] -= $NFT.bid;\r var["SOLD_" || trigger.data["NFT"]] = $stripToken($NFT); //Save for the next auction\r var["NFT_" || trigger.data["NFT"]] = false;\r }" } ] } ] } }, { "if": "{\r trigger.data["method"] == "DIVEST"\r }", "messages": [ { "app": "payment", "payload": { "asset": "base", "outputs": [ { "address": "{trigger.address}", "amount": "{$yourShare - 10000}" } ] } }, { "app": "state", "state": "{\r var["artist_" || trigger.data["artist"]] ||= {\r share: $artist.share - $yourShare, //Decrease the share by the amount just divested\r supply: $artist.supply - trigger.data["amount"] //Decrease the supply by the shares used to divest\r };\r \r var["maecenas_" || trigger.address || "_" || trigger.data["artist"]] -= trigger.data["amount"];\r var["locked"] -= ($yourShare + $myProfit);\r }" } ] } ] } }, { "if": "{//[PUBLIC] Resell a NFT\r $method == "SELL"\r }", "init": "{\r //Parameter validation\r if (NOT exists(trigger.data["endTime"]))\r bounce("endTime field is mandatory");\r if (trigger.data["endTime"] < timestamp)\r bounce("You cannot set the end time in the past");\r if (trigger.data["endTime"] > timestamp + 2628000)\r bounce("You cannot set the end time in more than 30 days");\r \r if (NOT exists(trigger.data["initialPrice"]))\r bounce("initialPrice field is mandatory");\r if (NOT is_valid_amount(trigger.data["initialPrice"]))\r bounce("initialPrice must be a valid amount");\r if (trigger.data["initialPrice"] < 20000)\r bounce("The minimum initialPrice is 20000 bytes");\r \r //NFT validation\r if (trigger.output[[asset!="base"]].asset == "ambigous")\r bounce("You cannot send more than one NFT type at a time");\r \r $feedData = data_feed[[oracles=this_address, feed_name=trigger.output[[asset!="base"]].asset, ifnone=false, ifseveral="last", type="string"]];\r \r $NFT = var["SOLD_" || trigger.output[[asset!="base"]].asset] || {isBanned: $feedData == "REVOKED" ? true : false}; //[We need $NFT.isBanned]This already checks for $NFT existence\r \r if (NOT $NFT)\r bounce("NFT not found");\r \r $sale = var["NFT_" || trigger.output[[asset!="base"]].asset];\r \r if (trigger.output[[asset!="base"]].amount != 1)\r bounce("You cannot auction more than 1 copy of an NFT at a time");\r \r if ($NFT.isBanned)\r bounce("We revoked the trading of that token probably due to copyright reasons");\r \r if ($sale)\r bounce("A copy of that NFT is already being auctioned. The auction is expected to end at " || timestamp_to_string($sale.soldAt) || " UTC but may be delayed depending on the number of bids");\r }", "messages": [ { "app": "state", "state": "{\r $NFT.bid = trigger.data["initialPrice"];\r $NFT.bids = 0;\r $NFT.by = trigger.address;\r $NFT.soldBy = trigger.address;\r $NFT.at = timestamp;\r $NFT.soldAt = trigger.data["endTime"];\r var["NFT_" || trigger.output[[asset!="base"]].asset] = $stripToken($NFT);\r }" } ] }, { "if": "{\r $method == "PRELIST"\r }", "init": "{\r if (NOT trigger.data["NFT"])\r bounce("NFT field is mandatory");\r if (NOT asset[trigger.data["NFT"]].exists)\r bounce("That NFT does not exist within the Obyte network");\r \r $isFreeNFT = var["FREE_" || trigger.data["NFT"]];\r \r if (NOT $isFreeNFT){//If the NFT was not listed in the free marked we need to know more about it\r if (NOT trigger.data["ipfs"])\r bounce("ipfs field is mandatory");\r \r if (NOT trigger.data["type"])\r bounce("type field is required");\r }\r }", "messages": [ { "app": "state", "state": "{\r if ($isFreeNFT){\r var["pending_" || trigger.data["NFT"]] = $isFreeNFT;\r }\r else{\r var["pending_" || trigger.data["NFT"]] = { //We save it as pending approval until we certify the provided info is valid\r ipfs: trigger.data["ipfs"],\r type: trigger.data["type"]\r };\r }\r }" } ] }, { "if": "{\r $method == "ENABLE_INVESTING"\r }", "init": "{\r if (var["artist_" || trigger.address])\r bounce("You are already accepting maecenas");\r \r if (NOT trigger.data["share"])\r bounce("share field is mandatory");\r \r if (NOT is_integer(trigger.data["share"]) OR trigger.data["share"] < 1 OR trigger.data["share"] > 50)\r bounce("share must be an integer between 1 - 50");\r if (exists(trigger.data["selfBuy"])){\r if (NOT is_integer(trigger.data["selfBuy"]))\r bounce("selfBuy field must be an integer");\r if (trigger.data["selfBuy"] < 0)\r bounce("selfBuy must be a positive integer");\r \r $cost = (1161570 * trigger.data["selfBuy"] * (1 + trigger.data["selfBuy"]) * (1 + 2 * trigger.data["selfBuy"])) * $INVESTMENT_CUT;\r \r if (trigger.output[[asset="base"]].amount < $cost)\r bounce("You need to send at least " || $cost || " bytes");\r }\r }", "messages": [ { "app": "state", "state": "{\r var["artist_" || trigger.address] = {\r supply: trigger.data["selfBuy"] OTHERWISE 0,\r share: 0,\r sharePercent: trigger.data["share"] / 100\r };\r if (trigger.data["selfBuy"])\r var["maecenas_" || trigger.address || "_" || trigger.address] = trigger.data["selfBuy"];\r }" } ] }, { "if": "{\r $method == "DISABLE_INVESTING"\r }", "init": "{\r $info = $artistInfo(trigger.address);\r \r if (NOT $info)\r bounce("You are already not accepting maecenas");\r \r if ($info.supply > 0)\r bounce("You cannot stop accepting maecenas right now as you already have some");\r }", "messages": [ { "app": "state", "state": "{\r var["artist_" || trigger.address] = false;\r }" } ] }, { "if": "{\r $method == "INVEST"\r }", "init": "{\r \r if (NOT trigger.data["artist"])\r bounce("artist field is mandatory");\r \r $artist = $artistInfo(trigger.data["artist"]);\r \r if (NOT $artist)\r bounce("That artist is not accepting maecenas");\r \r if (NOT trigger.data["amount"])\r bounce("amount field is mandatory");\r if (NOT is_integer(trigger.data["amount"]) OR trigger.data["amount"] <= 0)\r bounce("amount must be a positive integer");\r \r \r $x0 = $artist.supply;\r $x1 = $artist.supply + trigger.data["amount"];\r \r \r $upToFirstToken = 1161570 * $x0 * (1 + $x0) * (1 + 2 * $x0);\r $upToTargetPurchase = 1161570 * $x1 * (1 + $x1) * (1 + 2 * $x1);\r \r /* DEBUG\r $upToFirstToken = 10000/3 * $x0 * (1 + $x0) * (1 + 2 * $x0);\r $upToTargetPurchase = 10000/3 * $x1 * (1 + $x1) * (1 + 2 * $x1);\r */\r $totalCost = round($upToTargetPurchase - $upToFirstToken, 0);\r \r if (trigger.output[[asset="base"]].amount < $totalCost)\r bounce("Your payment is not enough for that purchase");\r }", "messages": [ { "app": "payment", "payload": { "asset": "base", "outputs": [ { "address": "{trigger.data["artist"]}", "amount": "{floor($totalCost * (1 - $INVESTMENT_CUT) - 10000, 0)}" } ] } }, { "app": "state", "state": "{\r var["artist_" || trigger.data["artist"]] ||= {supply: $artist.supply + trigger.data["amount"]};\r \r if (var["maecenas_" || trigger.address || "_" || trigger.data["artist"]])\r var["maecenas_" || trigger.address || "_" || trigger.data["artist"]] += trigger.data["amount"];\r else\r var["maecenas_" || trigger.address || "_" || trigger.data["artist"]] = trigger.data["amount"];\r }" } ] }, { "if": "{\r $method == "PROFILE"\r }", "init": "{\r $prof = $profile(trigger.address);\r \r if ($prof.verified)\r bounce("You have to contact support to modify a verified profile. We do this to prevent already verified accounts from impersonating another artist");\r \r $profileObj = $prof || trigger.data || {verified: false};\r delete($profileObj, "method");\r }", "messages": [ { "app": "state", "state": "{\r var["profile_" || trigger.address] = $profileObj;\r }" } ] }, { "if": "{\r $method == "SET_META"\r }", "init": "{\r if (NOT exists(trigger.data["NFT"]))\r bounce("NFT field is mandatory");\r \r $NFT = var["SOLD_" || trigger.data["NFT"]];\r \r if (NOT $NFT)\r bounce("NFT not found");\r \r if ($NFT.author != trigger.address)\r bounce("You can only set the metadata of NFTs minted by yourself");\r \r if (var["meta_" || trigger.data["NFT"]])\r bounce("That NFT meta was already set");\r }", "messages": [ { "app": "state", "state": "{\r var["meta_" || trigger.data["NFT"]] = trigger.data;\r }" } ] }, { "if": "{\r $method == "CHANGE_PRICE"\r }", "init": "{\r if (NOT trigger.data["NFT"])\r bounce("NFT field is mandatory");\r \r $NFT = var["NFT_" || trigger.data["NFT"]];\r \r if (NOT $NFT)\r bounce("NFT not found");\r \r if (NOT exists(trigger.data["price"]))\r bounce("price field is mandatory");\r if (NOT is_integer(trigger.data["price"]))\r bounce("price must be an integer");\r if (NOT is_valid_amount(trigger.data["price"]))\r bounce("price is invalid");\r \r if ($NFT.bid)\r bounce("You cannot change an auction price!");\r }", "messages": [ { "app": "state", "state": "{\r var["NFT_" || trigger.data["NFT"]] ||= {price: trigger.data["price"]};\r }" } ] }, { "if": "{\r $method == "FREESELL"\r }", "init": "{\r if (trigger.output[[asset!="base"]].asset == "ambigous")\r bounce("You cannot send more than 1 NFT type per transaction");\r if (trigger.output[[asset!="base"]].amount != 1)\r bounce("You cannot sell more than 1 NFT unit at a time");\r \r $isApproved = var["NFT_" || trigger.output[[asset!="base"]].asset] OTHERWISE var["SOLD_" || trigger.output[[asset!="base"]].asset];\r \r if ($isApproved)\r bounce("That NFT is already verified, thus it cannot be traded in the free market");\r \r $feedData = data_feed[[oracles=this_address, feed_name=$isApproved, ifnone="false", ifseveral="last", type="string"]];\r $isBanned = $feedData == "REVOKED" ? true : false;\r \r if ($isBanned)\r bounce("We have revoked the trading of that token. Probably due to copyrights");\r \r $NFT = var["FREE_" || trigger.output[[asset!="base"]].asset];\r \r if ($NFT.soldAt < timestamp)\r bounce("A copy of that NFT is already being auctioned. It is expected to end at " || timestamp_to_string($NFT.soldAt) || " UTC");\r \r \r if (NOT $NFT){ //We do not know about the NFT\r if(NOT exists(trigger.data["ipfs"]))\r bounce("ipfs field is required as we do not know which file that NFT represents");\r }\r \r if (NOT exists(trigger.data["endTime"]))\r bounce("endTime field is mandatory");\r if (NOT is_integer(trigger.data["endTime"]))\r bounce("endTime must be integer");\r if (trigger.data["endTime"] < timestamp)\r bounce("endTime cannot be set in the past");\r if (trigger.data["endTime"] > timestamp + 2628000)\r bounce("endTime cannot be set in more than a month in the future");\r \r if (exists(trigger.data["price"])){ //Is normal sale\r if (NOT is_valid_amount(trigger.data["price"]))\r bounce("price is invalid");\r else\r $toCreate = {price: trigger.data["price"]};\r }\r else{ //Is auction\r $toCreate = {bid: 20000, by: trigger.address, at: timestamp};\r }\r }", "messages": [ { "app": "state", "state": "{\r var["FREE_" || trigger.output[[asset!="base"]].asset] = $toCreate || {ipfs: (NOT $NFT) ? trigger.data["ipfs"] : $NFT.ipfs, bids: 0, author: 'foreign', soldBy: trigger.address, soldAt: trigger.data["endTime"]};\r }" } ] }, { "if": "{\r $method == "FREEBUY"\r }", "init": "{\r if (NOT trigger.data["NFT"])\r bounce("NFT field is mandatory");\r if (NOT exists(trigger.data["NFT"]))\r bounce("NFT field is mandatory");\r \r $NFT = var["FREE_" || trigger.data["NFT"]];\r \r if (NOT $NFT)\r bounce("That NFT does not exist");\r \r if (trigger.address == $NFT.soldBy)\r bounce("You cannot buy/bid on your own NFTs");\r \r if (trigger.output[[asset="base"]].amount < $NFT.bid * (1 + $MIN_BID_INCREMENT))\r bounce("You have to send at least " || $NFT.bid * (1 + $MIN_BID_INCREMENT) || " bytes as you need to increment the current bet by at least 0.01%");\r }", "messages": [ { "app": "state", "state": "{\r var["FREE_" || trigger.data["NFT"]] ||= {bid: trigger.output[[asset="base"]].amount, at: timestamp, by: trigger.address, bids: $NFT.bids + 1};\r var["locked"] += trigger.output[[asset="base"]].amount;\r }" } ] }, { "if": "{\r $method == "FREECLAIM"\r }", "init": "{\r if (NOT trigger.data["NFT"])\r bounce("NFT field is mandatory");\r \r $NFT = var["FREE_" || trigger.data["NFT"]];\r \r if (NOT $NFT)\r bounce("NFT not found");\r \r if ($NFT.soldAt < timestamp)\r bounce("The auction/sale is not over yet");\r \r $isAuction = $NFT.bid ? true : false;\r }", "messages": [ { "if": "{\r $NFT.by != $NFT.soldBy\r }", "app": "payment", "payload": { "asset": "base", "outputs": [ { "address": "{$NFT.soldBy}", "amount": "{$NFT.price * (1 - $FREEMARKET_CUT)}" } ] } }, { "app": "payment", "payload": { "asset": "{trigger.data["NFT"]}", "outputs": [ { "address": "{$NFT.by}", "amount": 1 } ] } }, { "app": "state", "state": "{\r var["FREE_" || trigger.data["NFT"]] = false;\r var["FREESOLD_" || trigger.data["NFT"]] = $stripToken($NFT);\r }" } ] } ] } } ]
Technical information
Fees:
33,815 bytes
(452 headers, 33363 payload)
Level:1954803
Witnessed level:1954796
Main chain index:1946838
Latest included mc index:1946837
Status:stable/confirmed/final