Unit ID
m46Tv7afzd3xNioJuvB0M6AOtrUAu8ZJzZPPPkp8T2Y=
Received
10.08.2021 05:10:01
Confirmation delay (full node)
2 minutes 41 seconds
Confirmation delay (light node)
5 minutes 19 seconds
Messages
Definition
Definition: [ "autonomous agent", { "bounce_fees": { "base": 10000 }, "init": "{ $HOUSE_CUT = var["FEE"]; //We will take this cut on the debut of an NFT in our platform. We charge 0.1% for foreign NFTs. $HALF_HOUR = 1800; //30m = 1800s. An auction is extended by 1800s every time there is a new bid near the deadline $RESERVE_AMOUNT = 200000; //We will always keep > 200.000 in the AA $MIN_BID_INCREMENT = 0.0001;//Bids must be at least 0.01% higher than the previous one $ONE_MONTH = 2592000; $USER_REGISTRY_ADDRESS = "QEQTX5CZHGLKB4P3YCMWCII3GIMAOB6N"; $CURRENCY_REGISTRY = "5LPGHS5SEWPXXZ4RDJKR3TPX6HSDUCLH"; $MAX_ROYALTY = var[$USER_REGISTRY_ADDRESS]["maxRoyalty"]; if (NOT trigger.data["method"]) bounce("method field is mandatory"); $method = trigger.data["method"]; $spendableFunds = balance["base"] - var["locked"] - storage_size - $RESERVE_AMOUNT; $owner = var[$USER_REGISTRY_ADDRESS]["owner"]; if (NOT $owner) bounce("The smart contract has not been initialized yet"); $fetchNFT = $asset => { $unitInfo = unit[$asset]; $parentUnits = $unitInfo.parent_units; //$parentUnit = unit[$unitInfo.parent_units[0]]; $nftInfo = reduce($parentUnits, 6, ($acc, $x)=>{ if ($acc) return $acc; $parentUnit = unit[$x]; if (!$parentUnit.messages) bounce("Bad parent unit"); $schema = $unitInfo.authors[0].authentifiers ? false : $unitInfo.authors[0].address; if (NOT $schema) return false; $definedBy = $unitInfo.authors[0].authentifiers ? $unitInfo.authors[0].address //Is a person : $parentUnit.authors[0].address; //Is a person or an AA (they can also define NFTs) $metadata = $parentUnit.messages[[.app='data']].payload; $isAccepted = var["SCHEMA_" || $schema]; if (NOT $isAccepted) return false; $assetMetadata = $unitInfo.messages[[.app='asset']].payload; {asset: $assetMetadata, meta: $metadata, author: $definedBy} }, false); if (NOT $nftInfo) bounce("NFT creation unit not found"); $nftInfo }; }", "getters": "{ $saleInfo = ($NFT, $seller)=>{ $info = var["FREE_" || $NFT || "_" || $seller] OTHERWISE var["NFT_" || $NFT || "_" || $seller]; return $info; }; }", "messages": { "cases": [ { "if": "{NOT $HOUSE_CUT}", "messages": [ { "app": "state", "state": "{ var["locked"] = 0; //Bytes locked in bids are not withdrawable by the Owner var["FEE"] = 0.1; //10% first sale fee }" } ] }, { "if": "{ trigger.address == $owner AND ($method == "payout" OR $method == "transferOwnership" OR $method == "reduceFee" OR $method == "setSchema") }", "messages": { "cases": [ { "if": "{$method == "payout"}", "messages": [ { "app": "payment", "payload": { "asset": "base", "outputs": [ { "address": "{trigger.address}", "amount": "{$spendableFunds}" } ] } } ] }, { "if": "{$method == "reduceFee"}", "init": "{ if (NOT exists(trigger.data["fee"])) bounce("fee field is mandatory"); if (trigger.data["fee"] < 0) bounce("Are you drunk?"); if (trigger.data["fee"] >= $HOUSE_CUT) bounce("fee must be lower than the current one"); }", "messages": [ { "app": "state", "state": "{ var["FEE"] = trigger.data["fee"]; }" } ] }, { "if": "{$method == "setSchema"}", "init": "{ if (NOT trigger.data["schema"]) bounce("schema field is mandatory"); if (NOT is_aa(trigger.data["schema"])) bounce("schema is not the address of an autonomous agent"); }", "messages": [ { "app": "state", "state": "{ var["SCHEMA_" || trigger.data["schema"]] = true; }" } ] } ] } }, { "if": "{$method == "BUY"}", "init": "{ if (NOT trigger.data["address"]) bounce("address field is mandatory"); if (NOT is_valid_address(trigger.data["address"])) bounce("address field is an invalid address"); if (NOT trigger.data["NFT"]) bounce("NFT field is mandatory"); if (trigger.address == trigger.data["address"]) bounce("You are buying your own NFT. Claim it instead in order to avoid fees"); $sale = $saleInfo(trigger.data["NFT"], trigger.data["address"]); $nft = $fetchNFT(trigger.data["NFT"]); $amount = $sale.isAuction ? 1 //1 lot not 1 unit : trigger.data["amount"] OTHERWISE 1; $pricePerUnit = $sale.currency ? $CURRENCY_REGISTRY.$convert($sale.price, $sale.currency) : $sale.price; $fullPrice = $amount * $pricePerUnit; $cut = round($fullPrice * $HOUSE_CUT, 0); $toAuthor = round($fullPrice * (min($nft.meta["royalty"] OTHERWISE 0, $MAX_ROYALTY))/100, 0); response["meta"] = $nft.meta; response["toAuthor"] = $toAuthor; $toSeller = $fullPrice - $cut - $toAuthor - 10000; }", "messages": [ { "if": "{NOT $sale.auction}", "init": "{ if (exists(trigger.data["amount"])){ if (NOT is_integer(trigger.data["amount"])) bounce("amount field must be an integer"); if (trigger.data["amount"] < 1) bounce("amount field must be at least 1"); if (trigger.data["amount"] > $sale.amount) bounce("That user is selling only " || $sale.amount || " units"); } if ($sale.currency) response["rate"] = $CURRENCY_REGISTRY.$getExchangeRate($sale.currency); response["realPrice"] = $pricePerUnit; response["total"] = $fullPrice; if (trigger.output[[asset="base"]].amount < $fullPrice) bounce("Your payment is lower than the NFT price. You have to send " || $fullPrice || " bytes"); }", "app": "payment", "payload": { "asset": "base", "outputs": [ { "address": "{$sale.soldBy}", "amount": "{$toSeller}" }, { "if": "{$toAuthor > 5000}", "address": "{$nft.author}", "amount": "{$toAuthor}" } ] } }, { "if": "{NOT $sale.auction}", "app": "payment", "payload": { "asset": "{trigger.data['NFT']}", "outputs": [ { "address": "{trigger.address}", "amount": "{$amount}" } ] } }, { "app": "state", "state": "{ if ($sale.auction) { if (trigger.output[[asset="base"]].amount < 20000) bounce("The minimum bid is 20000 bytes"); if (trigger.output[[asset="base"]].amount <= $sale.price * (1 + $MIN_BID_INCREMENT)) bounce("Your bid must be at least " || ceil($sale.price * (1 + $MIN_BID_INCREMENT), 0) || " (0.01% higher than the current)"); if ($sale.soldBy == trigger.address) bounce("You cannot bid on your own auction"); if (timestamp > $sale.endTime AND $sale.bids) //You can still bid on an expired auction if it had no bids. This will reawake the bid for 30 mins if the NFT was created by an attested user. Otherwise you will be able to claim the auction right away after bidding. bounce("The auction is over"); var["locked"] += trigger.output[[asset="base"]].amount - ($sale.by ? $sale.price : 0); //Increase non-withdrawable funds by the difference between previous and last bid $saleState = $sale || { price: trigger.output[[asset="base"]].amount, at: timestamp, bids: $sale.bids + 1, by: trigger.address, endTime: $sale.endTime + $HALF_HOUR }; } else { $newAmount = $sale.amount - $amount; $saleState = $newAmount == 0 ? false : $sale || {amount: $newAmount, at: timestamp}; } $key = var["FREE_" || trigger.data["NFT"] || "_" || trigger.data["address"]] ? "FREE_" : "NFT_"; $fullKey = $key || trigger.data["NFT"] || "_" || trigger.data["address"]; var[$fullKey] = $saleState; }" } ] }, { "if": "{$method == "CLAIM"}", "init": "{ $address = trigger.data["address"] OTHERWISE trigger.address; $sale = $saleInfo(trigger.data["NFT"], $address); if (NOT trigger.data["NFT"]) bounce("NFT field is mandatory"); $nft = $fetchNFT(trigger.data["NFT"]); if (NOT $sale.auction) bounce("That sale is not an auction"); if ($sale.auction AND timestamp <= $sale.endTime) bounce("The auction is not over yet"); $fullKey = var["FREE_" || trigger.data["NFT"] || "_" || $sale.soldBy] ? "FREE_" || trigger.data["NFT"] || "_" || $sale.soldBy : "NFT_" || trigger.data["NFT"] || "_" || $sale.soldBy; }", "messages": { "cases": [ { "if": "{$sale.auction}", "messages": [ { "if": "{$sale.bids > 0}", "app": "payment", "init": "{ $share = $sale.price * (1 - $HOUSE_CUT); if ($nft.meta["royalty"]){ $royalty = $sale.price * min($nft.meta["royalty"], $MAX_ROYALTY) / 100; $outputs = [ {//Royalty address: $nft.author, amount: floor($royalty, 0) //Percentage of the whole bid, no fees are charged }, {//Seller payment address: $sale.soldBy, amount: floor($share - $royalty, 0) //We take the house cut then royalty cut } ]; } else{ $outputs = [ {//Seller payment address: $sale.soldBy, amount: floor($share, 0) } ]; } $payload = {outputs: $outputs}; }", "payload": "{$payload}" }, { "app": "payment", "payload": { "asset": "{trigger.data['NFT']}", "outputs": [ { "address": "{$sale.by OTHERWISE $sale.soldBy}", "amount": "{$sale.amount}" } ] } }, { "app": "state", "state": "{ if ($sale.bids > 0) //If it had no bids you cannot reduce locked amount var["locked"] -= $sale.price; var[$fullKey] = false; //No longer listed for sale }" } ] }, { "if": "{NOT $sale.auction}", "init": "{ if (trigger.address != $sale.soldBy) bounce("You cannot claim other people's sales"); }", "messages": [ { "app": "payment", "payload": { "asset": "{trigger.data['NFT']}", "outputs": [ { "address": "{$sale.soldBy}", "amount": "{$sale.amount}" } ] } }, { "app": "state", "state": "{ var[$fullKey] = false; }" } ] } ] } }, { "if": "{$method == "CHANGE_PRICE"}", "init": "{ if (NOT trigger.data["NFT"]) bounce("NFT field is mandatory"); $sale = $saleInfo(trigger.data["NFT"], trigger.address); if (NOT $sale) bounce("Sale not found"); if (NOT exists(trigger.data["price"])) bounce("price field is mandatory"); if (NOT exists(trigger.data["currency"])){ //Priced in bytes, we cannot allow decimals if (NOT is_integer(trigger.data["price"])) bounce("price must be an integer"); if (NOT is_valid_amount(trigger.data["price"])) bounce("price is invalid"); if (trigger.data["price"] < 20000) bounce("The minimum price is 20000 bytes"); } else{//User wants price to be foreign asset based, let's check if we support the asset if (NOT $CURRENCY_REGISTRY.$getCurrency(trigger.data["currency"])) bounce("You cannot set the price in that currency"); } if ($sale.auction) bounce("You cannot change an auction price!"); }", "messages": [ { "app": "state", "state": "{ if (var["NFT_" || trigger.data["NFT"] || "_" || trigger.address]) var["NFT_" || trigger.data["NFT"] || "_" || trigger.address] ||= {price: trigger.data["price"], soldBy: trigger.address, currency: trigger.data["currency"] OTHERWISE false}; else var["FREE_" || trigger.data["NFT"] || "_" || trigger.address] ||= {price: trigger.data["price"], soldBy: trigger.address, currency: trigger.data["currency"] OTHERWISE false}; }" } ] }, { "if": "{$method == "SELL"}", "init": "{ if (trigger.output[[asset!="base"]].asset == "ambigous") bounce("You can only send a single NFT at a time"); $NFT = $fetchNFT(trigger.output[[asset!="base"]].asset); $prof = $USER_REGISTRY_ADDRESS.$profileOf($NFT.author); if (QEQTX5CZHGLKB4P3YCMWCII3GIMAOB6N.$isRevoked(trigger.output[[asset!="base"]].asset)) bounce("We revoked the trading of that token probably due to copyright reasons"); if (NOT trigger.data["price"]) bounce("price field is mandatory"); if (trigger.data["currency"]){ if (NOT $CURRENCY_REGISTRY.$getCurrency(trigger.data["currency"])) bounce("We do not support that currency"); } else { if (NOT is_integer(trigger.data["price"])) bounce("Price must be an integer"); if (NOT is_valid_amount(trigger.data["price"])) bounce("Price is not a valid amount"); if (NOT trigger.data["auction"]){ if (trigger.data["price"] * trigger.output[[asset!="base"]].amount < 20000) bounce("The minimum sale price is 20.000 bytes"); } } if (trigger.data["auction"]){ if (NOT exists(trigger.data["endTime"])) bounce("If you want to hold an auction you have to specify the endTime"); if (trigger.data["price"] < 20000) bounce("Minimum auction price is 20.000 bytes"); if (trigger.data["currency"]) bounce("You cannot set the auction price in other currency than bytes"); if (trigger.data["endTime"] <= timestamp) bounce("You cannot set the end time in the past"); if (trigger.data["endTime"] > timestamp + 2628000) bounce("You cannot set the end time in more than 30 days"); } if (var["FREE_" || trigger.output[[asset!="base"]].asset || "_" || trigger.address] OR var["NFT_" || trigger.output[[asset!="base"]].asset || "_" || trigger.address]) bounce("You already have an open sale or auction for that NFT. Please claim it before starting another one"); }", "messages": [ { "app": "state", "state": "{ $key = ($prof.verified ? "NFT_" : "FREE_") || trigger.output[[asset!="base"]].asset || "_" || trigger.address; var[$key] = { price: trigger.data["price"], amount: trigger.output[[asset!="base"]].amount, endTime: trigger.data["auction"] ? trigger.data["endTime"] : false, soldBy: trigger.address, bids: trigger.data["auction"] ? 0 : false, auction: trigger.data["auction"] ? true : false, currency: trigger.data["auction"] ? '' : trigger.data["currency"] OTHERWISE false }; }" } ] } ] } } ]
Technical information
Fees:
19,683 bytes
(452 headers, 19231 payload)
Level:2182698
Witnessed level:2182691
Main chain index:2172996
Latest included mc index:2172995
Status:stable/confirmed/final