├── LICENSE ├── README.md └── contracts └── SimpleBondingCurve.scilla /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bonding-curve 2 | Zilliqa's bonding curve contract based on sigmoid formula 3 | 4 | ## Resources 5 | - [【Gaudiy】 個人の信用スコアに応じてトークンの売買価額が変動する「Trust Economy bonding curves」をZilliqaで実装](https://medium.com/@gaudiy.inc/gaudiy-個人の信用スコアに応じてトークンの売買価額が変動する-trust-economy-bonding-curves-をzilliqaで実装-f20d25cc08c0) 6 | - [Implement “Trust Economy bonding curves” on Zilliqa : Varies token price depending on Personal Trust Score](https://medium.com/@gaudiy.inc/implement-trust-economy-bonding-curves-on-zilliqa-which-varies-token-price-depending-on-personal-fe84d771bcdd) 7 | -------------------------------------------------------------------------------- /contracts/SimpleBondingCurve.scilla: -------------------------------------------------------------------------------- 1 | scilla_version 0 2 | 3 | (* This contract implements a bonding curve by using sigmoid function*) 4 | 5 | (***************************************************) 6 | (* Associated library *) 7 | (***************************************************) 8 | library SimpleBondingCurve 9 | 10 | let success_code = Int32 0 11 | let not_owner_code = Int32 1 12 | let no_reward_code = Int32 2 13 | 14 | let zero = Uint128 0 15 | let one = Uint128 1 16 | let two = Uint128 2 17 | let zero_address = builtin ripemd160hash zero 18 | let long_list = 19 | let ze32 = Int32 0 in 20 | let nil = Nil {Int32} in 21 | let l1 = Cons {Int32} ze32 nil in 22 | let l2 = Cons {Int32} ze32 l1 in 23 | let l3 = Cons {Int32} ze32 l2 in 24 | let l4 = Cons {Int32} ze32 l3 in 25 | let l5 = Cons {Int32} ze32 l4 in 26 | let l6 = Cons {Int32} ze32 l5 in 27 | let l7 = Cons {Int32} ze32 l6 in 28 | let l8 = Cons {Int32} ze32 l7 in 29 | let l9 = Cons {Int32} ze32 l8 in 30 | let l11 = Cons {Int32} ze32 l9 in 31 | let l21 = Cons {Int32} ze32 l11 in 32 | let l31 = Cons {Int32} ze32 l21 in 33 | let l41 = Cons {Int32} ze32 l31 in 34 | let l51 = Cons {Int32} ze32 l41 in 35 | let l61 = Cons {Int32} ze32 l51 in 36 | let l71 = Cons {Int32} ze32 l61 in 37 | let l81 = Cons {Int32} ze32 l71 in 38 | let l91 = Cons {Int32} ze32 l81 in 39 | let l12 = Cons {Int32} ze32 l91 in 40 | let l22 = Cons {Int32} ze32 l12 in 41 | let l32 = Cons {Int32} ze32 l22 in 42 | let l42 = Cons {Int32} ze32 l32 in 43 | let l52 = Cons {Int32} ze32 l42 in 44 | let l62 = Cons {Int32} ze32 l52 in 45 | let l72 = Cons {Int32} ze32 l62 in 46 | let l82 = Cons {Int32} ze32 l72 in 47 | let l92 = Cons {Int32} ze32 l82 in 48 | let l13 = Cons {Int32} ze32 l92 in 49 | let l23 = Cons {Int32} ze32 l13 in 50 | let l33 = Cons {Int32} ze32 l23 in 51 | let l43 = Cons {Int32} ze32 l33 in 52 | let l53 = Cons {Int32} ze32 l43 in 53 | let l63 = Cons {Int32} ze32 l53 in 54 | let l73 = Cons {Int32} ze32 l63 in 55 | let l83 = Cons {Int32} ze32 l73 in 56 | let l93 = Cons {Int32} ze32 l83 in 57 | let l14 = Cons {Int32} ze32 l93 in 58 | let l24 = Cons {Int32} ze32 l14 in 59 | let l34 = Cons {Int32} ze32 l24 in 60 | let l44 = Cons {Int32} ze32 l34 in 61 | let l54 = Cons {Int32} ze32 l44 in 62 | let l64 = Cons {Int32} ze32 l54 in 63 | let l74 = Cons {Int32} ze32 l64 in 64 | let l84 = Cons {Int32} ze32 l74 in 65 | let l94 = Cons {Int32} ze32 l84 in 66 | Cons {Int32} ze32 l94 67 | 68 | (* Babylonian method *) 69 | let sqrt = 70 | fun (x: Uint128) => 71 | let folder_sqrt = @list_foldl Int32 Uint128 in 72 | let init_num = builtin add x one in 73 | let init = builtin div init_num two in 74 | let iter = 75 | fun (z: Uint128) => 76 | fun (h: Int32) => 77 | let x_div_z = builtin div x z in 78 | let z_num = builtin add x_div_z z in 79 | builtin div z_num two in 80 | folder_sqrt iter init long_list 81 | 82 | 83 | let one_msg = 84 | fun (msg : Message) => 85 | let nil_msg = Nil {Message} in 86 | Cons {Message} msg nil_msg 87 | 88 | let min_int = 89 | fun (a : Uint128) => fun (b : Uint128) => 90 | let alt = builtin lt a b in 91 | match alt with 92 | | True => 93 | a 94 | | False => 95 | b 96 | end 97 | 98 | let le_int = 99 | fun (a : Uint128) => fun (b : Uint128) => 100 | let x = builtin lt a b in 101 | match x with 102 | | True => True 103 | | False => 104 | let y = builtin eq a b in 105 | match y with 106 | | True => True 107 | | False => False 108 | end 109 | end 110 | 111 | (* (v1 - v2)^2 *) 112 | let sub_and_power = 113 | fun (v1: Uint128) => 114 | fun (v2: Uint128) => 115 | let is_sub_negative = builtin lt v1 v2 in 116 | match is_sub_negative with 117 | | True => 118 | let v = builtin sub v2 v1 in 119 | builtin mul v v 120 | | False => 121 | let v = builtin sub v1 v2 in 122 | builtin mul v v 123 | end 124 | 125 | (* dynamic tax model *) 126 | let calc_tax_from_level = 127 | fun (t: Uint128) => 128 | fun (lv: Uint128) => 129 | fun (lv_max: Uint128) => 130 | let mul_t_lv = builtin mul t lv in 131 | let tlv = builtin div mul_t_lv lv_max in 132 | builtin sub t tlv 133 | 134 | (* calculate required base token from current total amount for smart token *) 135 | let calculate_base_token_pool = 136 | fun (a: Uint128) => 137 | fun (b: Uint128) => 138 | fun (c: Uint128) => 139 | fun (smart_token_total: Uint128) => 140 | let x = smart_token_total in 141 | let pow_a_2 = builtin mul a a in 142 | let ass = builtin mul a x in 143 | let l1 = sub_and_power x b in 144 | let l2 = builtin add l1 c in 145 | let l3 = builtin mul pow_a_2 l2 in 146 | let l4 = sqrt l3 in 147 | builtin add l4 ass 148 | 149 | (* x = pool_smart_token *) 150 | (* d = pool_base_token *) 151 | (* g = base_token_amount + a * sqrt(b^2 +c) + d *) 152 | let calculate_purchase_return = 153 | fun (a: Uint128) => 154 | fun (normal_b: Uint128) => 155 | fun (c: Uint128) => 156 | fun (t: Uint128) => 157 | fun (pool_smart_token: Uint128) => 158 | fun (base_token_amount: Uint128) => 159 | let x = pool_smart_token in 160 | let normal_g = base_token_amount in 161 | let b = builtin sub normal_b t in 162 | let d = calculate_base_token_pool a b c x in 163 | let g = builtin add d normal_g in 164 | let pow_a_2 = builtin mul a a in 165 | let pow_b_2 = builtin mul b b in 166 | let mul_a_b = builtin mul a b in 167 | let pow_g_2 = builtin mul g g in 168 | let num1 = builtin add pow_b_2 c in 169 | let num2 = builtin mul pow_a_2 num1 in 170 | let num = builtin sub pow_g_2 num2 in 171 | let den1 = builtin sub g mul_a_b in 172 | let den2 = builtin mul a den1 in 173 | let den = builtin mul two den2 in 174 | let future_total_amount = builtin div num den in 175 | builtin sub future_total_amount x 176 | 177 | (* x = smart_token_total *) 178 | (* x_s = sale_smart_token_amount *) 179 | let calculate_sale_return = 180 | fun (a: Uint128) => 181 | fun (normal_b: Uint128) => 182 | fun (c: Uint128) => 183 | fun (t: Uint128) => 184 | fun (smart_token_total: Uint128) => 185 | fun (sale_smart_token_amount: Uint128) => 186 | let x = smart_token_total in 187 | let x_s = sale_smart_token_amount in 188 | let b = builtin add normal_b t in 189 | let pow_a_2 = builtin mul a a in 190 | let l1 = sub_and_power x b in 191 | let l2 = builtin add l1 c in 192 | let l3 = builtin mul pow_a_2 l2 in 193 | let l4 = sqrt l3 in 194 | let r1 = builtin add b x_s in 195 | let r2 = sub_and_power x r1 in 196 | let r3 = builtin add r2 c in 197 | let r4 = builtin mul pow_a_2 r3 in 198 | let r5 = sqrt r4 in 199 | let ak = builtin mul a x_s in 200 | let v1 = builtin add l4 ak in 201 | builtin sub v1 r5 202 | 203 | type User = 204 | | User of ByStr20 Uint128 205 | 206 | let update_members = 207 | fun (members: Map ByStr20 User) => 208 | fun (input_members: List User) => 209 | let folder_add_input = @list_foldl User (Map ByStr20 User) in 210 | let iter = 211 | fun (mems: Map ByStr20 User) => 212 | fun (user: User) => 213 | match user with 214 | | User addr level => 215 | let is_contains = builtin contains mems addr in 216 | match is_contains with 217 | | True => 218 | builtin put mems addr user 219 | | False => 220 | mems 221 | end 222 | end 223 | in 224 | folder_add_input iter members input_members 225 | 226 | (***************************************************) 227 | (* The contract definition *) 228 | (***************************************************) 229 | 230 | contract SimpleBondingCurve 231 | (owner : ByStr20, 232 | decimals : Uint32, 233 | name : String, 234 | symbol : String, 235 | init_base_token_contract: ByStr20, 236 | init_a: Uint128, 237 | init_b: Uint128, 238 | init_c: Uint128, 239 | init_base_tax: Uint128, 240 | init_max_level: Uint128) 241 | 242 | field total_tokens : Uint128 = Uint128 0 243 | field balances : Map ByStr20 Uint128 = Emp ByStr20 Uint128 244 | field allowed : Map ByStr20 (Map ByStr20 Uint128) = Emp ByStr20 (Map ByStr20 Uint128) 245 | field base_token_contract: ByStr20 = init_base_token_contract 246 | field pool_base_token: Uint128 = Uint128 0 247 | field members : Map ByStr20 User = 248 | let map = Emp ByStr20 User in 249 | let user = User owner one in 250 | builtin put map owner user 251 | 252 | (* constants for sigmoid function *) 253 | (* maximum price / 2 *) 254 | field a: Uint128 = init_a 255 | (* token supply when price reach maximum price / 2 *) 256 | field b: Uint128 = init_b 257 | (* sigmoid gradient *) 258 | field c: Uint128 = init_c 259 | 260 | (* constants for dynamic tax model *) 261 | field base_tax: Uint128 = init_base_tax 262 | field max_level: Uint128 = init_max_level 263 | 264 | transition BalanceOf (tokenOwner : ByStr20) 265 | bal <- balances[tokenOwner]; 266 | match bal with 267 | | Some v => 268 | e = {_eventname : "BalanceOf"; address : tokenOwner; balance : v}; 269 | event e 270 | | None => 271 | e = {_eventname : "BalanceOf"; address : tokenOwner; balance : Uint128 0}; 272 | event e 273 | end 274 | end 275 | 276 | transition TotalSupply () 277 | total <- total_tokens; 278 | e = {_eventname : "TotalSupply"; caller : _sender; balance : total}; 279 | event e 280 | end 281 | 282 | transition Transfer (to : ByStr20, tokens : Uint128) 283 | bal <- balances[_sender]; 284 | match bal with 285 | | Some b => 286 | can_do = le_int tokens b; 287 | match can_do with 288 | | True => 289 | (* subtract tokens from _sender and add it to "to" *) 290 | new_sender_bal = builtin sub b tokens; 291 | balances[_sender] := new_sender_bal; 292 | 293 | (* Adds tokens to "to" address *) 294 | to_bal <- balances[to]; 295 | new_to_bal = match to_bal with 296 | | Some x => builtin add x tokens 297 | | None => tokens 298 | end; 299 | 300 | balances[to] := new_to_bal; 301 | e = {_eventname : "TransferSuccess"; sender : _sender; recipient : to; amount : tokens}; 302 | event e 303 | | False => 304 | (* balance not sufficient. *) 305 | e = {_eventname : "TransferFailure"; sender : _sender; recipient : to; amount : Uint128 0}; 306 | event e 307 | end 308 | | None => 309 | (* no balance record, can't transfer *) 310 | e = {_eventname : "TransferFailure"; sender : _sender; recipient : to; amount : Uint128 0}; 311 | event e 312 | end 313 | end 314 | 315 | transition TransferFrom (from : ByStr20, to : ByStr20, tokens : Uint128) 316 | bal <- balances[from]; 317 | (* Check if _sender has been authorized by "from" *) 318 | sender_allowed_from <- allowed[from][_sender]; 319 | match bal with 320 | | Some a => 321 | match sender_allowed_from with 322 | | Some b => 323 | (* We can only transfer the minimum of available or authorized tokens *) 324 | t = min_int a b; 325 | can_do = le_int tokens t; 326 | match can_do with 327 | | True => 328 | (* tokens is what we should subtract from "from" and add to "to" *) 329 | new_from_bal = builtin sub a tokens; 330 | balances[from] := new_from_bal; 331 | to_bal <- balances[to]; 332 | match to_bal with 333 | | Some tb => 334 | new_to_bal = builtin add tb tokens; 335 | balances[to] := new_to_bal 336 | | None => 337 | (* "to" has no balance. So just set it to tokens *) 338 | balances[to] := tokens 339 | end; 340 | (* reduce "allowed" by "tokens" *) 341 | new_allowed = builtin sub b tokens; 342 | allowed[from][_sender] := new_allowed; 343 | e = {_eventname : "TransferFromSuccess"; sender : from; recipient : to; amount : tokens}; 344 | event e 345 | | False => 346 | e = {_eventname : "TransferFromFailure"; sender : from; recipient : to; amount : Uint128 0}; 347 | event e 348 | end 349 | | None => 350 | e = {_eventname : "TransferFromFailure"; sender : from; recipient : to; amount : Uint128 0}; 351 | event e 352 | end 353 | | None => 354 | e = {_eventname : "TransferFromFailure"; sender : from; recipient : to; amount : Uint128 0}; 355 | event e 356 | end 357 | end 358 | 359 | transition Approve (spender : ByStr20, tokens : Uint128) 360 | allowed[_sender][spender] := tokens; 361 | e = {_eventname : "ApproveSuccess"; approver : _sender; spender : spender; amount : tokens}; 362 | event e 363 | end 364 | 365 | transition Allowance (tokenOwner : ByStr20, spender : ByStr20) 366 | spender_allowance <- allowed[tokenOwner][spender]; 367 | match spender_allowance with 368 | | Some n => 369 | e = {_eventname : "Allowance"; owner : tokenOwner; spender : spender; amount : n}; 370 | event e 371 | | None => 372 | e = {_eventname : "Allowance"; owner : tokenOwner; spender : spender; amount : Uint128 0}; 373 | event e 374 | end 375 | end 376 | 377 | transition Buy (base_token_amount : Uint128, min_return_smart: Uint128) 378 | sender_info <- members[_sender]; 379 | match sender_info with 380 | | Some u => 381 | match u with 382 | | User addr level => 383 | smart_total <- total_tokens; 384 | v1 <- a; 385 | v2 <- b; 386 | v3 <- c; 387 | v4 <- base_tax; 388 | pool_base <- pool_base_token; 389 | m_lv <- max_level; 390 | 391 | mod_tax = calc_tax_from_level v4 level m_lv; 392 | 393 | (* calculate purchase return from base token amount *) 394 | smart_token_mint = calculate_purchase_return 395 | v1 v2 v3 mod_tax smart_total base_token_amount; 396 | 397 | (* validation: smart_token_mint is greater than 0 *) 398 | ge_min_return = le_int min_return_smart smart_token_mint; 399 | match ge_min_return with 400 | | True => 401 | bal <- balances[_sender]; 402 | (* add smart token to sender's balance *) 403 | match bal with 404 | | Some b => 405 | new_sender_bal = builtin add b smart_token_mint; 406 | balances[_sender] := new_sender_bal; 407 | 408 | e = { _eventname : "BalanceChanged"; sender : _sender; recipient : _this_address; 409 | previous_balance: b; new_balance: new_sender_bal}; 410 | event e 411 | | None => 412 | balances[_sender] := smart_token_mint; 413 | e = { _eventname : "BalanceChanged"; sender : _sender; recipient : _this_address; 414 | previous_balance: zero; new_balance: smart_token_mint}; 415 | event e 416 | end; 417 | 418 | (* add smart token to total supply *) 419 | total <- total_tokens; 420 | new_total = builtin add total smart_token_mint; 421 | total_tokens := new_total; 422 | 423 | (* add base token to pool *) 424 | new_pool_base = builtin add pool_base base_token_amount; 425 | pool_base_token := new_pool_base; 426 | 427 | e = { _eventname : "BuyTransitionSuccess"; sender : _sender; recipient : _this_address; 428 | smart_token_mint: smart_token_mint; base_token_amount: base_token_amount; 429 | total_smart_supply: new_total; total_base_pool: new_pool_base}; 430 | event e; 431 | 432 | (* transfer base token to Contract from sender *) 433 | contract_address <- base_token_contract; 434 | msg = { _tag : "TransferFrom"; _recipient : contract_address; _amount : zero; 435 | from : _sender; to : _this_address; tokens : base_token_amount}; 436 | msgs = one_msg msg; 437 | send msgs 438 | | False => 439 | e = { _eventname : "CalculatedTokenLessMinReturn"; _sender : _sender; _recipient: _this_address; _amount : zero; 440 | amount : smart_token_mint; min_return: min_return_smart }; 441 | event e 442 | end 443 | end 444 | | None => 445 | e = { _eventname : "NoSenderInfomation"; _sender : _sender; _recipient: _this_address; _amount : zero}; 446 | event e 447 | end 448 | end 449 | 450 | transition Sell (smart_token_amount : Uint128, min_return_base: Uint128) 451 | sender_info <- members[_sender]; 452 | match sender_info with 453 | | Some u => 454 | match u with 455 | | User addr level => 456 | smart_total <- total_tokens; 457 | v1 <- a; 458 | v2 <- b; 459 | v3 <- c; 460 | v4 <- base_tax; 461 | m_lv <- max_level; 462 | 463 | mod_tax = calc_tax_from_level v4 level m_lv; 464 | 465 | base_token_amount = calculate_sale_return 466 | v1 v2 v3 mod_tax smart_total smart_token_amount; 467 | 468 | bal <- balances[_sender]; 469 | 470 | (* validation: base_token_amount is greater than 0 *) 471 | ge_min_return = le_int min_return_base base_token_amount; 472 | match ge_min_return with 473 | | True => 474 | (* sub smart token from sender's balance *) 475 | match bal with 476 | | Some b => 477 | (* check sender's balance *) 478 | can_do = le_int smart_token_amount b; 479 | match can_do with 480 | | True => 481 | new_sender_bal = builtin sub b smart_token_amount; 482 | balances[_sender] := new_sender_bal; 483 | 484 | e = { _eventname : "BalanceChanged"; sender : _sender; recipient : _this_address; 485 | previous_balance: b; new_balance: new_sender_bal}; 486 | event e; 487 | 488 | (* sub smart token from total supply *) 489 | total <- total_tokens; 490 | new_total = builtin sub total smart_token_amount; 491 | total_tokens := new_total; 492 | 493 | (* sub base token to pool *) 494 | pool_base <- pool_base_token; 495 | new_pool_base = builtin sub pool_base base_token_amount; 496 | pool_base_token := new_pool_base; 497 | 498 | e = { _eventname : "SellTransitionSuccess"; sender : _sender; recipient : _this_address; 499 | smart_token_burn: smart_token_amount; base_token_amount: base_token_amount; 500 | total_smart_supply : new_total; total_base_pool : new_pool_base }; 501 | event e; 502 | 503 | (* transfer base token from contract to sender *) 504 | contract_address <- base_token_contract; 505 | msg = { _tag : "Transfer"; _recipient : contract_address; _amount : zero; 506 | to : _sender; tokens : base_token_amount}; 507 | msgs = one_msg msg; 508 | send msgs 509 | 510 | | False => 511 | (* balance insufficient. *) 512 | e = {_eventname : "InsufficientBalance"; sender : _sender; recipient : _this_address; 513 | amount : smart_token_amount; balance: b}; 514 | event e 515 | end 516 | | None => 517 | (* no balance record *) 518 | e = {_eventname : "Nobalance"; sender : _sender; recipient : _this_address; 519 | amount : smart_token_amount}; 520 | event e 521 | end 522 | | False => 523 | e = { _eventname : "CalculatedTokenLessMinReturn"; _sender : _sender; _recipient: _this_address; _amount : zero; 524 | amount : base_token_amount; min_return: min_return_base }; 525 | event e 526 | end 527 | end 528 | | None => 529 | e = { _eventname : "NoSenderInfomation"; _sender : _sender; _recipient: _this_address; _amount : zero}; 530 | event e 531 | end 532 | end 533 | 534 | transition ChangeBaseTokenAddress (address: ByStr20) 535 | is_owner = builtin eq owner _sender; 536 | match is_owner with 537 | | True => 538 | base_token_contract := address; 539 | e = {_eventname : "ChangeBaseTokenAddressSuccess"; caller : _sender; token_address: address }; 540 | event e 541 | | False => 542 | e = {_eventname : "ChangeBaseTokenAddressFailure"; caller : _sender}; 543 | event e 544 | end 545 | end 546 | 547 | transition ChangeSigmoidConstant (v1: Uint128, v2: Uint128, v3: Uint128, tax: Uint128, m_level: Uint128) 548 | is_owner = builtin eq owner _sender; 549 | match is_owner with 550 | | True => 551 | a := v1; 552 | b := v2; 553 | c := v3; 554 | base_tax := tax; 555 | max_level := m_level; 556 | e = {_eventname : "ChangeSigmoidConstantSuccess"; caller : _sender; a: v1; b: v2; c: v3; tax: tax; max_level: m_level }; 557 | event e 558 | | False => 559 | e = {_eventname : "ChangeSigmoidConstantFailure"; caller : _sender}; 560 | event e 561 | end 562 | end 563 | 564 | transition JoinCommunity (address: ByStr20, level: Uint128) 565 | is_owner = builtin eq owner _sender; 566 | match is_owner with 567 | | True => 568 | user = User address level; 569 | members[address] := user; 570 | e = {_eventname : "JoinCommunitySuccess"; caller : _sender; address: address; level: level }; 571 | event e 572 | | False => 573 | e = {_eventname : "JoinCommunityFailure"; caller : _sender; code : not_owner_code}; 574 | event e 575 | end 576 | end 577 | 578 | transition UpdateLevels (input_members: List User) 579 | is_owner = builtin eq owner _sender; 580 | match is_owner with 581 | | True => 582 | mems <- members; 583 | new_mems = update_members mems input_members; 584 | members := new_mems; 585 | e = {_eventname : "UpdateLevelsSuccess"; caller : _sender }; 586 | event e 587 | | False => 588 | e = {_eventname : "UpdateLevelsFailure"; caller : _sender }; 589 | event e 590 | end 591 | end 592 | --------------------------------------------------------------------------------