| 1 | [ |
| 2 | "autonomous agent", |
| 3 | { |
| 4 | "init": "{ |
| 5 | $oracles = 'F4KHJUCLJKY4JV7M5F754LAJX4EB7M4N:K237YYRMBYWCJBLSZGLJTXLZVVEXLI2Y'; |
| 6 | $feed_name = 'GBYTE_USD'; |
| 7 | $decimal_multiplier_base = 1e6; |
| 8 | $decimal_multiplier_ousd = 1e3; |
| 9 | $liquidation_ratio = 1.5; |
| 10 | $auction_period = 60 * 30; |
| 11 | |
| 12 | $bounce = 1e4; |
| 13 | $asset = var['asset']; |
| 14 | $supply = var['supply']; |
| 15 | $rate = data_feed[[oracles=$oracles, feed_name=$feed_name, ifnone=false]]; |
| 16 | $is_active = ($asset AND $rate); |
| 17 | |
| 18 | $cdp = trigger.data.cdp; |
| 19 | if ($cdp) { |
| 20 | $owner = var['cdp:' || $cdp || ':owner']; |
| 21 | $collateral = var['cdp:' || $cdp || ':collateral']; |
| 22 | $debt = var['cdp:' || $cdp || ':debt']; |
| 23 | $liquidation = var['cdp:' || $cdp || ':liquidation']; |
| 24 | $auction_end = var['cdp:' || $cdp || ':auction:end']; |
| 25 | $auction_best_bid = var['cdp:' || $cdp || ':auction:best-bid']; |
| 26 | $auction_best_bid_from = var['cdp:' || $cdp || ':auction:best-bid:from']; |
| 27 | $is_valid = var['cdp:' || $cdp]; |
| 28 | $is_owner = (trigger.address == $owner); |
| 29 | } |
| 30 | }", |
| 31 | "messages": { |
| 32 | "cases": [ |
| 33 | { |
| 34 | "if": "{trigger.data.define AND !$asset}", |
| 35 | "messages": [ |
| 36 | { |
| 37 | "app": "asset", |
| 38 | "payload": { |
| 39 | "cap": 1000000000000000, |
| 40 | "is_private": false, |
| 41 | "is_transferrable": true, |
| 42 | "auto_destroy": true, |
| 43 | "fixed_denominations": false, |
| 44 | "issued_by_definer_only": true, |
| 45 | "cosigned_by_definer": false, |
| 46 | "spender_attested": false |
| 47 | } |
| 48 | }, |
| 49 | { |
| 50 | "app": "state", |
| 51 | "state": "{ |
| 52 | var['asset'] = response_unit; |
| 53 | response['message'] = 'Asset created'; |
| 54 | response['asset'] = response_unit; |
| 55 | }" |
| 56 | } |
| 57 | ] |
| 58 | }, |
| 59 | { |
| 60 | "if": "{$is_active AND trigger.data.open}", |
| 61 | "init": "{ |
| 62 | $cdp_index = (var['cdp:index'] + 1); |
| 63 | }", |
| 64 | "messages": [ |
| 65 | { |
| 66 | "app": "state", |
| 67 | "state": "{ |
| 68 | var['cdp:' || $cdp_index] = true; |
| 69 | var['cdp:' || $cdp_index || ':owner'] = trigger.address; |
| 70 | var['cdp:index'] = $cdp_index; |
| 71 | response['message'] = 'Opened CDP ' || $cdp_index; |
| 72 | response['cdp'] = $cdp_index; |
| 73 | }" |
| 74 | } |
| 75 | ] |
| 76 | }, |
| 77 | { |
| 78 | "if": "{$is_valid AND trigger.data.close}", |
| 79 | "init": "{ |
| 80 | if (!$is_owner) bounce('You need to be the owner of the CDP'); |
| 81 | if ($liquidation) bounce('You can not close a CDP in liquidation'); |
| 82 | if ($debt AND $debt != 0) bounce('You must have 0 debt, got ' || $debt); |
| 83 | }", |
| 84 | "messages": [ |
| 85 | { |
| 86 | "app": "payment", |
| 87 | "if": "{$collateral AND $collateral > 0}", |
| 88 | "payload": { |
| 89 | "asset": "base", |
| 90 | "outputs": [ |
| 91 | { |
| 92 | "address": "{$owner}", |
| 93 | "amount": "{$collateral}" |
| 94 | } |
| 95 | ] |
| 96 | } |
| 97 | }, |
| 98 | { |
| 99 | "app": "state", |
| 100 | "state": "{ |
| 101 | var['cdp:' || $cdp] = false; |
| 102 | var['cdp:' || $cdp || ':owner'] = false; |
| 103 | var['cdp:' || $cdp || ':collateral'] = false; |
| 104 | var['cdp:' || $cdp || ':debt'] = false; |
| 105 | var['cdp:' || $cdp || ':liquidation'] = false; |
| 106 | var['cdp:' || $cdp || ':auction:end'] = false; |
| 107 | var['cdp:' || $cdp || ':auction:best-bid'] = false; |
| 108 | var['cdp:' || $cdp || ':auction:best-bid:from'] = false; |
| 109 | response['message'] = 'Closed CDP ' || $cdp; |
| 110 | response['cdp'] = $cdp; |
| 111 | }" |
| 112 | } |
| 113 | ] |
| 114 | }, |
| 115 | { |
| 116 | "if": "{$is_valid AND trigger.data.lock}", |
| 117 | "init": "{ |
| 118 | $amount = (trigger.output[[asset=base]] - $bounce); |
| 119 | if (!$is_owner) bounce('You need to be the owner of the CDP'); |
| 120 | if ($liquidation) bounce('The CDP is in liquidation'); |
| 121 | if ($amount <= 0) bounce('You need to send more than the bounce fees'); |
| 122 | }", |
| 123 | "messages": [ |
| 124 | { |
| 125 | "app": "state", |
| 126 | "state": "{ |
| 127 | var['cdp:' || $cdp || ':collateral'] += $amount; |
| 128 | response['message'] = 'Added ' || $amount || ' as collateral for CDP ' || $cdp; |
| 129 | response['cdp'] = $cdp; |
| 130 | response['amount'] = $amount; |
| 131 | }" |
| 132 | } |
| 133 | ] |
| 134 | }, |
| 135 | { |
| 136 | "if": "{$is_valid AND trigger.data.free AND trigger.data.amount}", |
| 137 | "init": "{ |
| 138 | $amount = trigger.data.amount; |
| 139 | if (!$is_owner) bounce('You need to be the owner of the CDP'); |
| 140 | if ($liquidation) bounce('The CDP is in liquidation'); |
| 141 | if ($amount <= 0) bounce('The amount must be positive'); |
| 142 | if ($collateral <= 0) bounce('The CDP collateral must be positive'); |
| 143 | if (($collateral - $amount) < 0) bounce('The amount must be lower or equal to the current CDP collateral'); |
| 144 | if ($debt AND $debt > 0) { |
| 145 | $collateralization_ratio = (($collateral - $amount) * $rate / $decimal_multiplier_base) / ($debt / $decimal_multiplier_ousd); |
| 146 | if ($collateralization_ratio >= $liquidation_ratio) |
| 147 | bounce('You need a collateralization ratio over ' || $liquidation_ratio || ', found ' || $collateralization_ratio); |
| 148 | } |
| 149 | |
| 150 | }", |
| 151 | "messages": [ |
| 152 | { |
| 153 | "app": "payment", |
| 154 | "payload": { |
| 155 | "asset": "base", |
| 156 | "outputs": [ |
| 157 | { |
| 158 | "address": "{trigger.address}", |
| 159 | "amount": "{$amount}" |
| 160 | } |
| 161 | ] |
| 162 | } |
| 163 | }, |
| 164 | { |
| 165 | "app": "state", |
| 166 | "state": "{ |
| 167 | var['cdp:' || $cdp || ':collateral'] -= $amount; |
| 168 | response['message'] = 'Reclaimed ' || $amount || ' bytes from CDP ' || $cdp; |
| 169 | if ($collateralization_ratio) response['collateralization_ratio'] = $collateralization_ratio; |
| 170 | }" |
| 171 | } |
| 172 | ] |
| 173 | }, |
| 174 | { |
| 175 | "if": "{$is_valid AND trigger.data.draw AND trigger.data.amount}", |
| 176 | "init": "{ |
| 177 | $amount = trigger.data.amount; |
| 178 | if (!$is_owner) bounce('You need to be the owner of the CDP'); |
| 179 | if ($liquidation) bounce('The CDP is in liquidation'); |
| 180 | if ($amount <= 0) bounce('The amount must be positive'); |
| 181 | if ($collateral <= 0) bounce('The CDP collateral must be positive'); |
| 182 | $collateralization_ratio = ($collateral * $rate / $decimal_multiplier_base) / (($debt + $amount) / $decimal_multiplier_ousd); |
| 183 | if ($collateralization_ratio < $liquidation_ratio) |
| 184 | bounce('You need a collateralization ratio over ' || $liquidation_ratio || ', found ' || $collateralization_ratio); |
| 185 | }", |
| 186 | "messages": [ |
| 187 | { |
| 188 | "app": "payment", |
| 189 | "payload": { |
| 190 | "asset": "{$asset}", |
| 191 | "outputs": [ |
| 192 | { |
| 193 | "address": "{trigger.address}", |
| 194 | "amount": "{$amount}" |
| 195 | } |
| 196 | ] |
| 197 | } |
| 198 | }, |
| 199 | { |
| 200 | "app": "state", |
| 201 | "state": "{ |
| 202 | var['cdp:' || $cdp || ':debt'] += $amount; |
| 203 | var['supply'] += $amount; |
| 204 | response['message'] = 'Sent fresh OUSD for ' || trigger.address; |
| 205 | response['collateralization_ratio'] = $collateralization_ratio; |
| 206 | response['rate'] = $rate; |
| 207 | }" |
| 208 | } |
| 209 | ] |
| 210 | }, |
| 211 | { |
| 212 | "if": "{$is_valid AND trigger.data.wipe}", |
| 213 | "init": "{ |
| 214 | $amount = trigger.output[[asset=$asset]]; |
| 215 | if (!$is_owner) bounce('You need to be the owner of the CDP'); |
| 216 | if ($liquidation) bounce('The CDP is in liquidation'); |
| 217 | if ($amount <= 0) bounce('You must send OUSD ' || $asset); |
| 218 | if (!$debt) bounce('The CDP must have debt'); |
| 219 | if ($amount > $debt) bounce('You need to send an amount of OUSD equal or less than current CDP debt'); |
| 220 | $collateralization_ratio = ($rate / $decimal_multiplier_base * $collateral) / (($debt - $amount) / $decimal_multiplier_ousd); |
| 221 | }", |
| 222 | "messages": [ |
| 223 | { |
| 224 | "app": "state", |
| 225 | "state": "{ |
| 226 | var['cdp:' || $cdp || ':debt'] -= $amount; |
| 227 | var['supply'] -= $amount; |
| 228 | response['message'] = 'Debt reduced by ' || $amount || ' on CDP ' || $cdp; |
| 229 | response['collateralization_ratio'] = $collateralization_ratio; |
| 230 | response['rate'] = $rate; |
| 231 | }" |
| 232 | } |
| 233 | ] |
| 234 | }, |
| 235 | { |
| 236 | "if": "{$is_valid AND trigger.data.bite}", |
| 237 | "init": "{ |
| 238 | $amount = trigger.output[[asset=$asset]]; |
| 239 | if ($liquidation) bounce('The CDP is already in liquidation'); |
| 240 | $collateralization_ratio = ($rate / $decimal_multiplier_base * $collateral) / ($debt / $decimal_multiplier_ousd); |
| 241 | if ($collateralization_ratio >= $liquidation_ratio) |
| 242 | bounce('Require a collateralization ratio lower than ' || $liquidation_ratio || ', found ' || $collateralization_ratio); |
| 243 | }", |
| 244 | "messages": [ |
| 245 | { |
| 246 | "app": "state", |
| 247 | "state": "{ |
| 248 | var['cdp:' || $cdp || ':liquidation'] = true; |
| 249 | var['cdp:' || $cdp || ':liquidation:initiator'] = trigger.address; |
| 250 | response['message'] = 'Triggered the liquidation process for CDP ' || $cdp; |
| 251 | response['collateralization_ratio'] = $collateralization_ratio; |
| 252 | response['rate'] = $rate; |
| 253 | response['cdp'] = $cdp; |
| 254 | }" |
| 255 | } |
| 256 | ] |
| 257 | }, |
| 258 | { |
| 259 | "if": "{$is_valid AND trigger.data.bid AND trigger.data.bid_amount}", |
| 260 | "init": "{ |
| 261 | $amount = trigger.output[[asset=$asset]]; |
| 262 | $bid_amount = trigger.data.bid_amount; |
| 263 | if ($amount != $debt) bounce('You must send exactly ' || $debt || ' ' || $asset); |
| 264 | if (!$liquidation) bounce('This CDP is not in liquidation'); |
| 265 | if ($auction_end > 0 AND timestamp > $auction_end) bounce('Auction ended'); |
| 266 | if ($auction_best_bid AND $bid_amount >= $auction_best_bid) bounce('You must have the best bid, lower than ' || $auction_best_bid || ' bytes'); |
| 267 | if ($bid_amount > $collateral) bounce('Bid amount must be lower or equal to CDP collateral'); |
| 268 | }", |
| 269 | "messages": [ |
| 270 | { |
| 271 | "app": "payment", |
| 272 | "if": "{$auction_best_bid}", |
| 273 | "payload": { |
| 274 | "asset": "{$asset}", |
| 275 | "outputs": [ |
| 276 | { |
| 277 | "address": "{$auction_best_bid_from}", |
| 278 | "amount": "{$debt}" |
| 279 | } |
| 280 | ] |
| 281 | } |
| 282 | }, |
| 283 | { |
| 284 | "app": "state", |
| 285 | "state": "{ |
| 286 | if (!$auction_end) { |
| 287 | var['cdp:' || $cdp || ':auction:start'] = timestamp; |
| 288 | var['cdp:' || $cdp || ':auction:end'] = timestamp + $auction_period; |
| 289 | } |
| 290 | var['cdp:' || $cdp || ':auction:best-bid'] = $bid_amount; |
| 291 | var['cdp:' || $cdp || ':auction:best-bid:from'] = trigger.address; |
| 292 | response['message'] = 'Bidded on CDP ' || $cdp; |
| 293 | response['cdp'] = $cdp; |
| 294 | }" |
| 295 | } |
| 296 | ] |
| 297 | }, |
| 298 | { |
| 299 | "if": "{$is_valid AND trigger.data.settle}", |
| 300 | "init": "{ |
| 301 | if (!$liquidation) |
| 302 | bounce('The CDP must be in liquidation'); |
| 303 | if (timestamp <= $auction_end) |
| 304 | bounce('The auction has not expired yet'); |
| 305 | }", |
| 306 | "messages": [ |
| 307 | { |
| 308 | "app": "payment", |
| 309 | "payload": { |
| 310 | "asset": "base", |
| 311 | "outputs": [ |
| 312 | { |
| 313 | "address": "{$auction_best_bid_from}", |
| 314 | "amount": "{$auction_best_bid}" |
| 315 | }, |
| 316 | { |
| 317 | "if": "{$collateral > $auction_best_bid}", |
| 318 | "address": "{$owner}", |
| 319 | "amount": "{($collateral - $auction_best_bid)}" |
| 320 | } |
| 321 | ] |
| 322 | } |
| 323 | }, |
| 324 | { |
| 325 | "app": "state", |
| 326 | "state": "{ |
| 327 | var['cdp:' || $cdp] = false; |
| 328 | var['cdp:' || $cdp || ':owner'] = false; |
| 329 | var['cdp:' || $cdp || ':collateral'] = false; |
| 330 | var['cdp:' || $cdp || ':debt'] = false; |
| 331 | var['cdp:' || $cdp || ':liquidation'] = false; |
| 332 | var['cdp:' || $cdp || ':auction:end'] = false; |
| 333 | var['cdp:' || $cdp || ':auction:best-bid'] = false; |
| 334 | var['cdp:' || $cdp || ':auction:best-bid:from'] = false; |
| 335 | response['message'] = 'Settle auction and closed CDP ' || $cdp; |
| 336 | response['cdp'] = $cdp; |
| 337 | }" |
| 338 | } |
| 339 | ] |
| 340 | } |
| 341 | ] |
| 342 | } |
| 343 | } |
| 344 | ] |