SHARE
TWEET

Untitled

a guest Mar 6th, 2019 79 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. scilla_version 0
  2.  
  3. (***************************************************)
  4. (*               Associated library                *)
  5. (***************************************************)
  6. import BoolUtils
  7.  
  8. library NonfungibleToken
  9.  
  10. (***************************************************)
  11. (*                 Product library                 *)
  12. (***************************************************)
  13.  
  14.  
  15.  
  16. type Product =
  17. | Product of Uint256 Uint128 Uint128 Uint128 Uint128 Uint128 Bool
  18. (*    uint256 id;*)
  19. (*    uint256 price;*)
  20. (*    uint256 available;*)
  21. (*    uint256 supply;*)
  22. (*    uint256 sold;*)
  23. (*    uint256 interval;*)
  24. (*    bool renewable;*)
  25.  
  26. let unlimited_supply = Uint128 0
  27.  
  28. let create_product =
  29.     fun (_productId: Uint256) =>
  30.     fun (_initialPrice: Uint128) =>
  31.     fun (_initialInventoryQuantity: Uint128) =>
  32.     fun (_supply: Uint128) =>
  33.     fun (_interval: Uint128) =>
  34.         let s = Uint128 0 in
  35.         let r = False in
  36.         Product _productId _initialPrice _initialInventoryQuantity _supply s _interval r
  37.  
  38. type ChangeInventoryResult =
  39. | ChangeInventoryFailed
  40. | ChangeInventorySuccess of Product
  41.  
  42. let increment_inventory =
  43.     fun (p: Product) =>
  44.     fun (_inventoryAdjustment: Uint128) =>  
  45.         match p with
  46.         | Product id price available supply sold interval renewable =>
  47.             let newInventoryLevel = builtin add available _inventoryAdjustment in
  48.             let unlimited = builtin eq supply unlimited_supply in
  49.             match unlimited with
  50.             | True =>
  51.                 let np = Product id price newInventoryLevel supply sold interval renewable in
  52.                 ChangeInventorySuccess np
  53.             | False =>
  54.                 let ns = builtin add sold newInventoryLevel in
  55.                 let uvs = builtin lt supply ns in
  56.                 match uvs with
  57.                 | True => ChangeInventoryFailed
  58.                 | False =>
  59.                     let np = Product id price newInventoryLevel supply sold interval renewable in
  60.                     ChangeInventorySuccess np
  61.                 end
  62.             end
  63.         end
  64.  
  65. let decrement_inventory =
  66.     fun (p: Product) =>
  67.     fun (_inventoryAdjustment: Uint128) =>  
  68.         match p with
  69.         | Product id price available supply sold interval renewable =>
  70.             let newInventoryLevel = builtin sub available _inventoryAdjustment in
  71.             let overflow = builtin lt available newInventoryLevel in
  72.             match overflow with
  73.             | True => ChangeInventoryFailed
  74.             | False =>
  75.                 let np = Product id price newInventoryLevel supply sold interval renewable in
  76.                 ChangeInventorySuccess np
  77.             end
  78.         end
  79.  
  80. type PurchaseInventoryResult =
  81. | PurchaseInventoryFailed
  82. | PurchaseInventorySuccess of Product
  83. let purchase_one_unit_in_stock =
  84.     fun (p: Product) =>
  85.         match p with
  86.         | Product id price available supply sold interval renewable =>
  87.             let os = builtin eq available unlimited_supply in
  88.             match os with
  89.             | True => PurchaseInventoryFailed
  90.             | False =>
  91.                 let one = Uint128 1 in
  92.                 let ns = builtin add sold one in
  93.                 let na = builtin sub available one in
  94.                 let np = Product id price na supply ns interval renewable in
  95.                 PurchaseInventorySuccess np                
  96.             end
  97.         end        
  98.  
  99.  
  100.  
  101. (***************************************************)
  102. (*                 DinoSeed library                *)
  103. (***************************************************)
  104.  
  105.  
  106. type DinoSeed =
  107. | DinoSeed of Uint256 BNum
  108. (*    uint256 genes;*)
  109. (*    BNum bornBlock;*)
  110.  
  111.  
  112.  
  113.  
  114.  
  115. (***************************************************)
  116. (*                 NonfungibleToken                *)
  117. (***************************************************)
  118.  
  119.  
  120. let one_msg =
  121.   fun (msg : Message) =>
  122.   let nil_msg = Nil {Message} in
  123. Cons {Message} msg nil_msg
  124.  
  125. (* Checks and see if an address is a contract owner *)
  126. let checkContractOwner =
  127.     fun (msgSender: ByStr20) =>
  128.     fun (owner: ByStr20) =>
  129.         builtin eq msgSender owner
  130.  
  131. (* Checks and see if an address is a token owner *)
  132. let isTokenOwner =
  133.     fun (msgSender: ByStr20) =>
  134.     fun (tokenOwner : Option ByStr20) =>
  135.         match tokenOwner with
  136.         | None => False
  137.         | Some val =>
  138.             builtin eq val msgSender
  139.         end
  140.  
  141. (* Checks if a given address is approved to make txn the given tokenID *)
  142. (* Not to be confused with isApprovedForAll                            *)
  143. let isApproved =
  144.     fun (msgSender: ByStr20) =>
  145.     fun (val: Option ByStr20) =>
  146.         match val with
  147.         | None => False
  148.         | Some val =>
  149.             builtin eq val msgSender
  150.         end
  151.  
  152. (* Checks if an message sender is approved by a given owner. (i.e. operator) *)
  153. let isApprovedForAll =
  154.     fun (msgSender: ByStr20) =>
  155.     fun (m: Option (Map (ByStr20) (Bool))) =>
  156.         match m with
  157.         | None => False
  158.             (* owner did not assign anyone to the approval mapping *)
  159.         | Some val =>
  160.             (* val is of type Map (ByStr20) (Bool) *)
  161.             let check_list = builtin get val msgSender in
  162.             match check_list with
  163.             | None => False
  164.             | Some is_sender_approved =>
  165.                 (* check if sender has access rights *)
  166.                 match is_sender_approved with
  167.                 | True => True
  168.                 | False => False
  169.                 end
  170.             end
  171.         end
  172.  
  173. (* Check if a sender is an operator of the owner, approved for the given ID *)
  174. (* or is the owner of the token *)
  175. let isApprovedOrOwner =
  176.     fun (isOwner: Bool) =>
  177.     fun (isApproved: Bool) =>
  178.     fun (isApprovedForAll: Bool) =>
  179.         let isOwnerOrApproved =  orb isOwner isApproved in
  180.         orb isOwnerOrApproved isApprovedForAll
  181.  
  182. let isAuthorizedOrNotToContractHolder =
  183.     fun (isAuthorized: Bool) =>
  184.     fun (isToContracHoler: Option Bool) =>
  185.         match isToContracHoler with
  186.         | Some p =>
  187.             match p with
  188.             | True => isAuthorized
  189.             | False => False
  190.             end
  191.         | None => isAuthorized
  192.         end      
  193.        
  194. (* Error events *)
  195. let makeErrorEvent =
  196.     fun (location: String) =>
  197.     fun (errorCode: Uint32) =>
  198.         {_eventname: "Error"; raisedAt: location; code: errorCode }
  199.  
  200. (* Error codes *)
  201. let code_success = Uint32 0
  202. let code_failure = Uint32 1
  203. let code_not_authorized = Uint32 2
  204. let code_not_found = Uint32 4
  205. let code_bad_request = Uint32 5
  206. let code_token_exists = Uint32 6
  207. let code_product_exists = Uint32 7
  208. let code_invalid_quantity = Uint32 8
  209. let code_unexpected_error = Uint32 9
  210. let code_product_not_exists = Uint32 10
  211.  
  212. let code_purchase_error = Uint32 20
  213.  
  214. let code_not_implement_error = Uint32 255
  215. (***************************************************)
  216. (*             The contract definition             *)
  217. (***************************************************)
  218.  
  219. contract NonfungibleToken
  220. (owner : ByStr20,
  221.  name : String,
  222.  symbol: String
  223. )
  224.  
  225. (* mutable fields *)
  226.  
  227. (* Mapping between tokenId to token owner *)
  228. field tokenOwnerMap: Map Uint256 ByStr20 = Emp Uint256 ByStr20
  229. (* Mapping from owner to number of owned tokens *)
  230. field ownedTokenCount: Map ByStr20 Uint256 = Emp ByStr20 Uint256
  231.  
  232. (* Mapping between tokenId to approved address *)
  233. (* @dev: There can only be one approved address per token at a given time. *)
  234. field tokenApprovals: Map Uint256 ByStr20 = Emp Uint256 ByStr20
  235.  
  236. (* Mapping from owner to operator approvals  *)
  237. field operatorApprovals: Map ByStr20 (Map ByStr20 Bool)
  238.                             = Emp ByStr20 (Map ByStr20 Bool)
  239.  
  240. field dinoSeedMap: Map Uint256 DinoSeed = Emp Uint256 DinoSeed
  241. field nonceSeed: Uint256 = Uint256 0
  242.  
  243. field productsMap: Map Uint256 Product = Emp Uint256 Product
  244.  
  245. field contractHolderMap: Map ByStr20 Bool = Emp ByStr20 Bool
  246.  
  247. (* immutable field *)
  248.  
  249. (* @notice Count all NFTs assigned to an owner *)
  250. transition balanceOf(address: ByStr20)
  251.     optionBal <- ownedTokenCount[address];
  252.     balance = match optionBal with
  253.     | Some bal => bal
  254.     | None => Uint256 0
  255.     end;
  256.     e = {_eventname: "balanceOf"; bal: balance};
  257.     event e
  258. end
  259.  
  260.  
  261. (* Get the owner of a particular tokenId *)
  262. transition ownerOf(tokenId: Uint256)
  263.     someVal <- tokenOwnerMap[tokenId];
  264.     match someVal with
  265.     | Some val =>
  266.         e = {_eventname: "ownerOf"; id: tokenId; owner: val};
  267.         event e
  268.     | None =>
  269.         e = let raisedAt = "ownerOf" in makeErrorEvent raisedAt code_not_found;
  270.         event e
  271.     end
  272. end
  273.  
  274. (* @dev:    TODO whitelist contract address can mint the token*)
  275. (* @dev:    Mint new tokens. Only `contractOwner`, '_this_address' can mint the token*)
  276. (* @param:  to - address of the token recipient                     *)
  277. (* @param:  tokenId - token id of the new token                     *)
  278. (* Returns error message code_token_exist if token exists           *)
  279. transition mint(to: ByStr20, tokenId: Uint256)
  280.     (* Sender must be the contract owner *)
  281.     isOwner = checkContractOwner owner _sender;
  282.     isThisContract = checkContractOwner _this_address _sender;
  283.     isAuthorized = orb isOwner isThisContract;
  284.     match isAuthorized with
  285.     | True =>        
  286.         (* Check if token exists *)
  287.         tokenExist <- exists tokenOwnerMap[tokenId];
  288.         match tokenExist with
  289.         | True =>
  290.             (* Token exists, return error code *)
  291.             e = let raisedAt = "mint" in makeErrorEvent raisedAt code_token_exists;
  292.             event e
  293.         | False =>
  294.             (* Mint token *)
  295.             tokenOwnerMap[tokenId] := to;
  296.             (* add to owner count *)
  297.             userCnt <- ownedTokenCount[to];
  298.             match userCnt with
  299.             | Some val =>
  300.                 (* Append to existing results *)
  301.                 newVal= let one = Uint256 1 in builtin add val one;
  302.                 ownedTokenCount[to] := newVal
  303.             | None =>
  304.                 (* User does not have existing tokens *)
  305.                 newVal = Uint256 1;
  306.                 ownedTokenCount[to] := newVal
  307.             end;
  308.  
  309.             (* Emit success event *)
  310.             e = {_eventname: "Mint successful"; by: _sender; recipient: to; token: tokenId};
  311.             event e
  312.         end
  313.     | False =>
  314.         (* Unauthorized transaction - sender is not the contract owner*)
  315.         e = let raisedAt = "mint" in makeErrorEvent raisedAt code_not_authorized;
  316.         event e
  317.     end
  318.  
  319.    
  320. end
  321.  
  322. (* @dev Transfer the ownership of a given token ID to another address *)
  323. (* @param from:     Current owner of the token                        *)
  324. (* @param to:       Recipient address of the token                    *)
  325. (* @param tokenId   uint256 id of the token to be transferred         *)
  326. transition transferFrom(from: ByStr20, to: ByStr20, tokenId: Uint256)
  327.     copy_tokenOwner <- tokenOwnerMap[tokenId];
  328.     copy_tokenApprovals <- tokenApprovals[tokenId];
  329.    
  330.    
  331.     (* Get tokenOwner ByStr20 *)
  332.     getTokenOwner <- tokenOwnerMap[tokenId];
  333.     match getTokenOwner with
  334.     | None =>
  335.         (* Token not found *)
  336.         e = let raisedAt = "transferFrom" in makeErrorEvent raisedAt code_not_found;
  337.         event e
  338.        
  339.     | Some tokenOwner =>
  340.         copy_operatorApproval <- operatorApprovals[tokenOwner];
  341.         (* Libary functions to check for conditions *)
  342.         checkOwner = isTokenOwner _sender copy_tokenOwner;
  343.         checkApproved = isApproved _sender copy_tokenApprovals;
  344.         checkApprovedForAll = isApprovedForAll _sender copy_operatorApproval;
  345.  
  346.         (* Checks if the `from` is indeed the owner of the token *)
  347.         isFromTokenOwner = builtin eq tokenOwner from;
  348.         match isFromTokenOwner with
  349.         | False =>
  350.             (* From address is not the same as the tokenOwner    *)
  351.             e = let raisedAt = "transferFrom" in makeErrorEvent raisedAt code_bad_request;
  352.             event e
  353.         | True =>
  354.             (* isApprovedOrOwner checks if any of the three conditions are met *)
  355.             isAuthorized = isApprovedOrOwner checkOwner checkApproved checkApprovedForAll;
  356.             isToContracHoler <- contractHolderMap[to];
  357.            
  358.             isAuthorized2 = isAuthorizedOrNotToContractHolder isAuthorized isToContracHoler;
  359.  
  360.             match isAuthorized2 with
  361.             | True =>
  362.                 (* Remove from Approval *)
  363.                 match checkApproved with
  364.                 | True =>
  365.                     (* Remove entry from approvals at the token level *)
  366.                     delete tokenApprovals[tokenId]
  367.                 | False =>
  368.                 end;
  369.  
  370.                 (* Change tokenOwnerMap *)
  371.                 tokenOwnerMap[tokenId] := to;
  372.  
  373.                 (* Change Count *)
  374.  
  375.  
  376.                 (*subtract one from previous token owner *)
  377.                 somePrevBal <- ownedTokenCount[from];
  378.                 match somePrevBal with
  379.                 | Some prevBal =>
  380.                     newBal  = let one = Uint256 1 in builtin sub prevBal one;
  381.                     ownedTokenCount[from] := newBal
  382.                 | None =>
  383.                     e = let raisedAt = "transferFrom" in makeErrorEvent raisedAt code_unexpected_error;
  384.                     event e
  385.                 end;
  386.  
  387.                 (* add one to the new token owner *)
  388.                 userCnt <- ownedTokenCount[to];
  389.                 (* Calculate the new token count value for recipient *)
  390.                 newVal = let one = Uint256 1 in match userCnt with
  391.                 | Some val =>
  392.                     (* Add to existing value *)
  393.                     builtin add val one
  394.                 | None => one
  395.                 end;
  396.                 ownedTokenCount[to] := newVal;
  397.                
  398.                 (* check and notify to contract Holder *)              
  399.                
  400.                
  401.                 e = {_eventname: "transferFrom successful"; from: _sender; recipient: to; token: tokenId};
  402.                 event e
  403.             | False =>
  404.                 (* Unauthorized transaction *)
  405.                 e = let raisedAt = "transferFrom" in makeErrorEvent raisedAt code_not_authorized;
  406.                 event e
  407.             end
  408.         end
  409.     end
  410. end
  411.  
  412. (* @dev: Approves another address to transfer the given token ID                *)
  413. (* - There can only be one approved address per token at a given time           *)
  414. (* - Absence of entry in tokenApproval indicates there is no approved address   *)
  415. (* param: to ByStr20 to be approved for the given token id                      *)
  416. (* param: tokenId uint256 id of the token to be apporved                        *)
  417.  
  418.  
  419. transition approve(to: ByStr20, tokenId: Uint256)
  420.  
  421.     copy_tokenOwner <- tokenOwnerMap[tokenId];
  422.    
  423.  
  424.     (* Get tokenOwner ByStr20 *)
  425.     getTokenOwner <- tokenOwnerMap[tokenId];
  426.     match getTokenOwner with
  427.     | None =>
  428.         (* Token not found *)
  429.         e = let raisedAt = "approve" in makeErrorEvent raisedAt code_not_found;
  430.         event e
  431.     | Some tokenOwner =>
  432.         copy_operatorApproval <- operatorApprovals[tokenOwner];
  433.         checkApprovedForAll = isApprovedForAll _sender copy_operatorApproval;
  434.         checkOwner = isTokenOwner _sender copy_tokenOwner;
  435.         isAuthorized = orb checkApprovedForAll checkOwner;
  436.         match isAuthorized with
  437.         | True =>
  438.             (* add to token approval mapping *)
  439.             tokenApprovals[tokenId] := to;
  440.             (* Emit event *)
  441.             e = {_eventname: "Approve successful"; from: _sender; approvedTo: to; token: tokenId};
  442.             event e
  443.         | False =>
  444.             (* Unauthorized transaction *)
  445.             e = let raisedAt = "approve" in makeErrorEvent raisedAt code_not_authorized;
  446.             event e
  447.         end
  448.     end
  449. end
  450.  
  451. (* @dev: sets or unsets the approval of a given operator                *)
  452. (* @param: address to be set or unset as operator                       *)
  453. (* @param: approved - status of the approval to be set                  *)
  454.  
  455. transition setApprovalForAll(to: ByStr20, approved: Bool)
  456.    
  457.     (* Checks if the _sender is approving himself *)
  458.     isValidOperation = let check = builtin eq _sender to in negb check;
  459.     (* require _sender is not approving himself *)
  460.     match isValidOperation with
  461.     | True =>
  462.         (* Check if sender has an existing record on the operatorApproval *)
  463.         operatorApprovals[_sender][to] := approved;
  464.         (* Stringify boolean value to be emitted in the event *)
  465.         approvedStr = bool_to_string approved;
  466.         e = {_eventname: "setApprovalForAll successful"; from: _sender; recipient: to; status: approvedStr};
  467.         event e
  468.     | False =>
  469.         e = let raisedAt = "setApprovalForAll" in makeErrorEvent raisedAt code_not_authorized;
  470.         event e
  471.     end
  472. end
  473.  
  474.  
  475.  
  476. (*    uint256 id;*)
  477. (*    uint256 price;*)
  478. (*    uint256 available;*)
  479. (*    uint256 supply;*)
  480. (*    uint256 sold;*)
  481. (*    uint256 interval;*)
  482. (*    bool renewable;*)
  483. transition createProduct(productId: Uint256, initialPrice: Uint128, initialInventoryQuantity: Uint128, supply: Uint128, interval: Uint128)
  484.    
  485.     isAuthorized = checkContractOwner owner _sender;
  486.     match isAuthorized with
  487.     | True =>        
  488.         copy_product <- productsMap[productId];
  489.  
  490.         match copy_product with
  491.         | Some _ =>
  492.             e = let raisedAt = "createProduct" in makeErrorEvent raisedAt code_product_exists;
  493.             event e
  494.         | None =>
  495.             ivq = builtin lt supply initialInventoryQuantity;
  496.             match ivq with
  497.             | True =>
  498.                 e = let raisedAt = "createProduct" in makeErrorEvent raisedAt code_invalid_quantity;
  499.                 event e
  500.             | False =>
  501.                 p = create_product productId initialPrice initialInventoryQuantity supply interval;
  502.                 productsMap[productId] := p;                                
  503.                 e = {_eventname: "createProduct successful"; id: productId};    
  504.                 event e                
  505.             end            
  506.         end
  507.        
  508.     | False =>
  509.         (* Unauthorized transaction - sender is not the contract owner*)
  510.         e = let raisedAt = "createProduct" in makeErrorEvent raisedAt code_not_authorized;
  511.         event e
  512.     end
  513. end
  514.  
  515. transition purchaseProduct(productId: Uint256)
  516.     copy_product <- productsMap[productId];    
  517.  
  518.     match copy_product with
  519.     | Some p =>
  520.         match p with
  521.         | Product id price available supply sold interval renewable =>
  522.             vp = builtin eq _amount price;
  523.             match vp with
  524.             | False =>
  525.                 e = let raisedAt = "purchaseProduct" in makeErrorEvent raisedAt code_purchase_error;
  526.                 event e
  527.             | True =>
  528.                 po = purchase_one_unit_in_stock p;
  529.                 match po with
  530.                 | PurchaseInventoryFailed =>
  531.                     e = let raisedAt = "purchaseProduct" in makeErrorEvent raisedAt code_purchase_error;
  532.                     event e
  533.                 | PurchaseInventorySuccess np =>
  534.                     productsMap[productId] := np;
  535.                     x <- & BLOCKNUMBER;
  536.  
  537.                     (*TODO this must is genes*)
  538.                     attributes = productId;
  539.                     dn = DinoSeed attributes x;
  540.  
  541.                     n <- nonceSeed;
  542.                     one256 = Uint256 1;
  543.                     nid = builtin add n one256;
  544.                     nonceSeed := nid;
  545.  
  546.                     dinoSeedMap[nid] := dn;
  547.  
  548.                     accept;
  549.                    
  550.                     msg  = {_tag : "mint"; _recipient : _this_address; _amount : Uint128 0;
  551.                         to : _sender; tokenId : nid};
  552.                    
  553.                     msgs = one_msg msg;
  554.                     send msgs;
  555.  
  556.                     e = {_eventname: "purchaseProduct successful"; id: nid};    
  557.                     event e
  558.  
  559.                 end
  560.                
  561.             end
  562.         end
  563.     | None =>
  564.         e = let raisedAt = "purchaseProduct" in makeErrorEvent raisedAt code_product_not_exists;
  565.         event e
  566.     end
  567. end
  568.  
  569. transition setHolderStatus(holder: ByStr20, b: Bool)
  570.     isAuthorized = checkContractOwner owner _sender;
  571.     match isAuthorized with
  572.     | True =>
  573.         contractHolderMap[holder] := b;
  574.         (* Emit success event *)
  575.         e = {_eventname: "setHolderStatus successful"; by: _this_address; recipient: _sender; approved: b};
  576.         event e
  577.     | False =>
  578.         (* Unauthorized transaction - sender is not the contract owner*)
  579.         e = let raisedAt = "setHolderStatus" in makeErrorEvent raisedAt code_not_authorized;
  580.         event e
  581.     end
  582. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top