tx · ASKfjah4pEGv9MGWBx68zK7EqtcSbmjekuLmQWWU76ew 3PHbdpaKzz8EiAngGHaFu2hVuNCdsC67qh3: -0.01000000 Waves 2024.01.18 18:50 [4002912] smart account 3PHbdpaKzz8EiAngGHaFu2hVuNCdsC67qh3 > SELF 0.00000000 Waves
{ "type": 13, "id": "ASKfjah4pEGv9MGWBx68zK7EqtcSbmjekuLmQWWU76ew", "fee": 1000000, "feeAssetId": null, "timestamp": 1705593037436, "version": 2, "chainId": 87, "sender": "3PHbdpaKzz8EiAngGHaFu2hVuNCdsC67qh3", "senderPublicKey": "4XuPpm7Pz97L5yDuLYiKbCSuXvtGjxCPsUBUUzmgokhP", "proofs": [ "3MUcKkEyoQ5NpUTvdQCetsLFYEDfQiKQWGRyH4uJ6FUx3C3fdBZJKruwwnZpbVN3eWUxsd9GfpzfshRRyoFNeANe" ], "script": "base64:BgIuCAISBwoFCAgICAESCAoGCAgICAEIEgQKAggIEgQKAggIEgQKAggBEgUKAwQICAsABlNjYWxlOACAwtcvAAdTY2FsZTE2AICAhP6m3uERAQ1nZXRBc3NldEJ5dGVzAQphc3NldElkU3RyAwkAAAIFCmFzc2V0SWRTdHICBVdBVkVTBQR1bml0CQDZBAEFCmFzc2V0SWRTdHIBFnZlcmlmeUxpcXVpZGF0b3JBY2Nlc3MBB2FkZHJlc3MJAQIhPQIJALMJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzAhFzZXR1cF9saXF1aWRhdG9ycwIACQClCAEFB2FkZHJlc3MFBHVuaXQAE01heFNoYXJlVG9MaXF1aWRhdGUJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwIZc2V0dXBfbWF4U2hhcmVUb0xpcXVpZGF0ZQBkABBMaXF1aWRhdGlvbkRlbGF5CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMCFnNldHVwX2xpcXVpZGF0aW9uRGVsYXkACgAQTGlxdWlkYXRvclJld2FyZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzAhZzZXR1cF9saXF1aWRhdG9yUmV3YXJkAAoAEUJhZERlYnRMaXFBbGxvd2VkCQBmAgkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzAhdzZXR1cF9iYWREZWJ0TGlxQWxsb3dlZAAAAAAADU9yYWNsZUFkZHJlc3MJAQt2YWx1ZU9yRWxzZQIJAKYIAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzAhRzZXR1cF9hZGRyZXNzX29yYWNsZQIACQEHQWRkcmVzcwEBGgFXSWbQy/OK9Vd6rfwhb3HFW4mIK9CBs7F/AAdtYXJrZXRzCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMCDXNldHVwX21hcmtldHMJALkJAgkAzAgCAiMzUEhwdVFVUFZVb1IzQVl6RmVKemVXSmZZTHNMVG1Xc3NWSAUDbmlsAgEsARZnZXRVc2VyQmFsYW5jZUlOVEVSTkFMAwZtYXJrZXQHYWRkcmVzcw1taW51c0JvcnJvd2VkCgEMdHJ5R2V0U3RyaW5nAQNrZXkEByRtYXRjaDAJAJ0IAgUGbWFya2V0BQNrZXkDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFiBQckbWF0Y2gwBQFiAgAKAQ10cnlHZXRJbnRlZ2VyAQNrZXkEByRtYXRjaDAJAJoIAgUGbWFya2V0BQNrZXkDCQABAgUHJG1hdGNoMAIDSW50BAFiBQckbWF0Y2gwBQFiAAAKAQ1nZXRUb2tlblByaWNlAQphc3NldElkU3RyAwMJAAACBQphc3NldElkU3RyAiw5d2MzTFhOQTRURUJzWHlLdG9MRTltcmJERDdXTUhYdlhyQ2padmFiTEFzaQYJAAACBQphc3NldElkU3RyAixIR2dhYlRxVVM4V3RWRlVKemZtclRETWdFY2NKdVpMQlBoRmdRRnh2bnNvVwkAlAoCAMCEPQDAhD0EBXByaWNlCQERQGV4dHJOYXRpdmUoMTA1MCkCBQ1PcmFjbGVBZGRyZXNzCQCsAgIFCmFzc2V0SWRTdHICB190d2FwNUIJAJQKAgUFcHJpY2UFBXByaWNlCgEOY2FsY0Fzc2V0U2NhbGUBCmFzc2V0SWRTdHIECGRlY2ltYWxzAwkAAAIFCmFzc2V0SWRTdHICBVdBVkVTAAgICQEFdmFsdWUBCQDsBwEJANkEAQUKYXNzZXRJZFN0cghkZWNpbWFscwkAbAYACgAABQhkZWNpbWFscwAAAAAFBERPV04EBmFzc2V0cwkAtQkCCQEMdHJ5R2V0U3RyaW5nAQIMc2V0dXBfdG9rZW5zAgEsBARsdHZzCQC1CQIJAQx0cnlHZXRTdHJpbmcBAgpzZXR1cF9sdHZzAgEsBANsdHMJALUJAgkBDHRyeUdldFN0cmluZwECCXNldHVwX2x0cwIBLAoBAWYCBWFjY3VtBG5leHQDCQBnAgUEbmV4dAkAkAMBBQZhc3NldHMFBWFjY3VtBAx1c2VyU3VwcGxpZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8JAJEDAgUGYXNzZXRzBQRuZXh0BAx1c2VyQm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8JAJEDAgUGYXNzZXRzBQRuZXh0BBNuZWVkVG9rZW5BY2NvdW50aW5nAwMJAQIhPQIFDHVzZXJCb3Jyb3dlZAAABgkBAiE9AgUMdXNlclN1cHBsaWVkAAAGBwMFE25lZWRUb2tlbkFjY291bnRpbmcECmFzc2V0U2NhbGUJAQ5jYWxjQXNzZXRTY2FsZQEJAJEDAgUGYXNzZXRzBQRuZXh0BAphc3NldFByaWNlCQENZ2V0VG9rZW5QcmljZQEJAJEDAgUGYXNzZXRzBQRuZXh0CQBlAgkAZAIFBWFjY3VtCQBrAwkAawMFDHVzZXJTdXBwbGllZAkBDXRyeUdldEludGVnZXIBCQCsAgIJAJEDAgUGYXNzZXRzBQRuZXh0AgZfc1JhdGUFB1NjYWxlMTYIBQphc3NldFByaWNlAl8xBQphc3NldFNjYWxlAwUNbWludXNCb3Jyb3dlZAkAawMJAGsDBQx1c2VyQm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCRAwIFBmFzc2V0cwUEbmV4dAIGX2JSYXRlBQdTY2FsZTE2CAUKYXNzZXRQcmljZQJfMQUKYXNzZXRTY2FsZQAABQVhY2N1bQQGcmVzdWx0CgACJGwJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUJAMwIAgAGCQDMCAIABwkAzAgCAAgJAMwIAgAJCQDMCAIACgkAzAgCAAsFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwFBnJlc3VsdAYBaQEQcHJveHlMaXF1aWRhdGVWMgUGbWFya2V0C3VzZXJBZGRyZXNzDmRlYnRBc3NldElkU3RyEnN1cHBsaWVkQXNzZXRJZFN0cgZhbW91bnQDCQAAAgkAswkCBQdtYXJrZXRzBQZtYXJrZXQFBHVuaXQJAAIBAiBnaXZlbiBwb29sIGFkZHJlc3MgaXMgbm90IGEgcG9vbAQDaW52CQD8BwQJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBm1hcmtldAILbGlxdWlkYXRlVjIJAMwIAgcJAMwIAgULdXNlckFkZHJlc3MJAMwIAgUSc3VwcGxpZWRBc3NldElkU3RyBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQ1nZXRBc3NldEJ5dGVzAQUOZGVidEFzc2V0SWRTdHIFBmFtb3VudAUDbmlsAwkAAAIFA2ludgUDaW52BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEQcHJveHlMaXF1aWRhdGVWMwYGbWFya2V0C3VzZXJBZGRyZXNzDmRlYnRBc3NldElkU3RyEnN1cHBsaWVkQXNzZXRJZFN0cgZhbW91bnQIcm91dGVTdHIDCQAAAgkAswkCBQdtYXJrZXRzBQZtYXJrZXQFBHVuaXQJAAIBAiRnaXZlbiBtYXJrZXQgYWRkcmVzcyBpcyBub3QgYSBtYXJrZXQDCQEBIQEJARZ2ZXJpZnlMaXF1aWRhdG9yQWNjZXNzAQgFAWkGY2FsbGVyCQACAQIkbm8gcGVybWlzc2lvbiB0byBwZXJmb3JtIGxpcXVpZGF0aW9uBA1tYXJrZXRBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQZtYXJrZXQEBXNSYXRlCQERQGV4dHJOYXRpdmUoMTA1MCkCBQ1tYXJrZXRBZGRyZXNzCQCsAgIFEnN1cHBsaWVkQXNzZXRJZFN0cgIGX3NSYXRlBAdzQW1vdW50CQERQGV4dHJOYXRpdmUoMTA1MCkCBQ1tYXJrZXRBZGRyZXNzCQCsAgIJAKwCAgULdXNlckFkZHJlc3MCCl9zdXBwbGllZF8FEnN1cHBsaWVkQXNzZXRJZFN0cgQOc3VwcGxpZWRBbW91bnQJAGsDBQdzQW1vdW50BQVzUmF0ZQUHU2NhbGUxNgQWbGFzdExpcUZvck1hcmtldEtleVN0cgkArAICCQCsAgICD2hpc3RvcnlfbWFya2V0XwUGbWFya2V0AhBfbGFzdExpcXVpZGF0aW9uBBVsYXN0TGlxdWlkYXRpb25LZXlTdHIJAKwCAgkArAICAg1oaXN0b3J5X3VzZXJfBQt1c2VyQWRkcmVzcwIQX2xhc3RMaXF1aWRhdGlvbgQPbGFzdExpcXVpZGF0aW9uCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFFWxhc3RMaXF1aWRhdGlvbktleVN0cgAAAwkAZgIFBmFtb3VudAkAawMFE01heFNoYXJlVG9MaXF1aWRhdGUFDnN1cHBsaWVkQW1vdW50AJBOCQACAQImc2hvdWxkIGxpcXVpZGF0ZSBzbWFsbGVyIHBhcnQgcGVyIHRpbWUDCQBmAgkAZAIFD2xhc3RMaXF1aWRhdGlvbgUQTGlxdWlkYXRpb25EZWxheQUGaGVpZ2h0CQACAQIUY2Fubm90IGxpcXVpZGF0ZSB5ZXQEA2ludgkA/AcEBQ1tYXJrZXRBZGRyZXNzAglsaXF1aWRhdGUJAMwIAgcJAMwIAgULdXNlckFkZHJlc3MJAMwIAgUGYW1vdW50CQDMCAIFEnN1cHBsaWVkQXNzZXRJZFN0cgkAzAgCBQ5kZWJ0QXNzZXRJZFN0cgkAzAgCBQhyb3V0ZVN0cgUDbmlsBQNuaWwDCQAAAgUDaW52BQNpbnYEEnVzZXJCb3Jyb3dlZEFtb3VudAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ1tYXJrZXRBZGRyZXNzCQCsAgIJAKwCAgULdXNlckFkZHJlc3MCCl9ib3Jyb3dlZF8FDmRlYnRBc3NldElkU3RyAAAEDnVzZXJVc2RCYWxhbmNlCQEWZ2V0VXNlckJhbGFuY2VJTlRFUk5BTAMFDW1hcmtldEFkZHJlc3MFC3VzZXJBZGRyZXNzBgMJAGYCAAAFEnVzZXJCb3Jyb3dlZEFtb3VudAkAAgECL3RyYW5zYWN0aW9uIGxlYWRzIHRvIGEgbmVnYXRpdmUgYm9ycm93ZWQgYW1vdW50AwMJAQEhAQURQmFkRGVidExpcUFsbG93ZWQJAGcCAAAFDnVzZXJVc2RCYWxhbmNlBwkAAgECH3RyYW5zYWN0aW9uIGxlYWRzIHRvIGEgYmFkIGRlYnQEEGxpcXVpZGF0b3JSZXdhcmQJAGsDBQZhbW91bnQFEExpcXVpZGF0b3JSZXdhcmQAkE4EC3N0YXRzS2V5U3RyCQCsAgIJAKwCAgkArAICAgdyZXdhcmRfCQClCAEIBQFpBmNhbGxlcgIBXwUSc3VwcGxpZWRBc3NldElkU3RyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQtzdGF0c0tleVN0cgkAZAIJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwULc3RhdHNLZXlTdHIAAAUQbGlxdWlkYXRvclJld2FyZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUVbGFzdExpcXVpZGF0aW9uS2V5U3RyBQZoZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIFFmxhc3RMaXFGb3JNYXJrZXRLZXlTdHIFBmhlaWdodAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDHBheW91dFJld2FyZAIKYWRkcmVzc1N0cgphc3NldElkU3RyAwkBAiE9AgkApQgBCAUBaQZjYWxsZXICIzNQTWNNaU1FczZ3NTZOUkdhY2tzWHRGRzV6Uzdkb0U5ZnBMCQACAQIYbm8gYWNjZXNzIHRvIHRoaXMgbWV0aG9kBAtzdGF0c0tleVN0cgkArAICCQCsAgIJAKwCAgIHcmV3YXJkXwUKYWRkcmVzc1N0cgIBXwUKYXNzZXRJZFN0cgQPcmV3YXJkQXZhaWxhYmxlCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFC3N0YXRzS2V5U3RyAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUKYWRkcmVzc1N0cgUPcmV3YXJkQXZhaWxhYmxlCQENZ2V0QXNzZXRCeXRlcwEFCmFzc2V0SWRTdHIJAMwIAgkBDEludGVnZXJFbnRyeQIFC3N0YXRzS2V5U3RyAAAFA25pbAFpAQx1cGRhdGVTdHJpbmcCA2tleQN2YWwDAwkBAiE9AgkApQgBCAUBaQZjYWxsZXICIzNQTWNNaU1FczZ3NTZOUkdhY2tzWHRGRzV6Uzdkb0U5ZnBMCQECIT0CCQClCAEIBQFpBmNhbGxlcgIjM1BIYmRwYUt6ejhFaUFuZ0dIYUZ1MmhWdU5DZHNDNjdxaDMHCQACAQIYbm8gYWNjZXNzIHRvIHRoaXMgbWV0aG9kCQDMCAIJAQtTdHJpbmdFbnRyeQIFA2tleQUDdmFsBQNuaWwBaQENdXBkYXRlSW50ZWdlcgIDa2V5A3ZhbAMDCQECIT0CCQClCAEIBQFpBmNhbGxlcgIjM1BNY01pTUVzNnc1Nk5SR2Fja3NYdEZHNXpTN2RvRTlmcEwJAQIhPQIJAKUIAQgFAWkGY2FsbGVyAiMzUEhiZHBhS3p6OEVpQW5nR0hhRnUyaFZ1TkNkc0M2N3FoMwcJAAIBAhhubyBhY2Nlc3MgdG8gdGhpcyBtZXRob2QJAMwIAgkBDEludGVnZXJFbnRyeQIFA2tleQUDdmFsBQNuaWwBaQEWZ2V0VXNlckJhbGFuY2VSRUFET05MWQMFZGVidWcJbWFya2V0U3RyB2FkZHJlc3MEA3JlcwkBFmdldFVzZXJCYWxhbmNlSU5URVJOQUwDCQERQGV4dHJOYXRpdmUoMTA2MikBBQltYXJrZXRTdHIFB2FkZHJlc3MGAwkAAAIFBWRlYnVnBgkAAgEJAKQDAQUDcmVzCQCUCgIFA25pbAUDcmVzACS1eS8=", "height": 4002912, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 3ZkMXXWsPvok293PSwTBXH6J4TDJY6NvuAPoHXrPJ294 Next: Cj9mX8GNYrRL37t4dM8L5FN2aREt1jUrkZNcH175r91A Diff:
Old | New | Differences | |
---|---|---|---|
19 | 19 | ||
20 | 20 | let LiquidatorReward = valueOrElse(getInteger(this, "setup_liquidatorReward"), 10) | |
21 | 21 | ||
22 | + | let BadDebtLiqAllowed = (valueOrElse(getInteger(this, "setup_badDebtLiqAllowed"), 0) > 0) | |
23 | + | ||
24 | + | let OracleAddress = valueOrElse(addressFromString(valueOrElse(getString(this, "setup_address_oracle"), "")), Address(base58'3P8d1E1BLKoD52y3bQJ1bDTd2TD1gpaLn9t')) | |
25 | + | ||
22 | 26 | let markets = valueOrElse(getString(this, "setup_markets"), makeString(["3PHpuQUPVUoR3AYzFeJzeWJfYLsLTmWssVH"], ",")) | |
27 | + | ||
28 | + | func getUserBalanceINTERNAL (market,address,minusBorrowed) = { | |
29 | + | func tryGetString (key) = match getString(market, key) { | |
30 | + | case b: String => | |
31 | + | b | |
32 | + | case _ => | |
33 | + | "" | |
34 | + | } | |
35 | + | ||
36 | + | func tryGetInteger (key) = match getInteger(market, key) { | |
37 | + | case b: Int => | |
38 | + | b | |
39 | + | case _ => | |
40 | + | 0 | |
41 | + | } | |
42 | + | ||
43 | + | func getTokenPrice (assetIdStr) = if (if ((assetIdStr == "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi")) | |
44 | + | then true | |
45 | + | else (assetIdStr == "HGgabTqUS8WtVFUJzfmrTDMgEccJuZLBPhFgQFxvnsoW")) | |
46 | + | then $Tuple2(1000000, 1000000) | |
47 | + | else { | |
48 | + | let price = getIntegerValue(OracleAddress, (assetIdStr + "_twap5B")) | |
49 | + | $Tuple2(price, price) | |
50 | + | } | |
51 | + | ||
52 | + | func calcAssetScale (assetIdStr) = { | |
53 | + | let decimals = if ((assetIdStr == "WAVES")) | |
54 | + | then 8 | |
55 | + | else value(assetInfo(fromBase58String(assetIdStr))).decimals | |
56 | + | pow(10, 0, decimals, 0, 0, DOWN) | |
57 | + | } | |
58 | + | ||
59 | + | let assets = split(tryGetString("setup_tokens"), ",") | |
60 | + | let ltvs = split(tryGetString("setup_ltvs"), ",") | |
61 | + | let lts = split(tryGetString("setup_lts"), ",") | |
62 | + | func f (accum,next) = if ((next >= size(assets))) | |
63 | + | then accum | |
64 | + | else { | |
65 | + | let userSupplied = tryGetInteger(((address + "_supplied_") + assets[next])) | |
66 | + | let userBorrowed = tryGetInteger(((address + "_borrowed_") + assets[next])) | |
67 | + | let needTokenAccounting = if (if ((userBorrowed != 0)) | |
68 | + | then true | |
69 | + | else (userSupplied != 0)) | |
70 | + | then true | |
71 | + | else false | |
72 | + | if (needTokenAccounting) | |
73 | + | then { | |
74 | + | let assetScale = calcAssetScale(assets[next]) | |
75 | + | let assetPrice = getTokenPrice(assets[next]) | |
76 | + | ((accum + fraction(fraction(userSupplied, tryGetInteger((assets[next] + "_sRate")), Scale16), assetPrice._1, assetScale)) - (if (minusBorrowed) | |
77 | + | then fraction(fraction(userBorrowed, tryGetInteger((assets[next] + "_bRate")), Scale16), assetPrice._1, assetScale) | |
78 | + | else 0)) | |
79 | + | } | |
80 | + | else accum | |
81 | + | } | |
82 | + | ||
83 | + | let result = { | |
84 | + | let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] | |
85 | + | let $s = size($l) | |
86 | + | let $acc0 = 0 | |
87 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
88 | + | then $a | |
89 | + | else f($a, $l[$i]) | |
90 | + | ||
91 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
92 | + | then $a | |
93 | + | else throw("List size exceeds 12") | |
94 | + | ||
95 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12) | |
96 | + | } | |
97 | + | result | |
98 | + | } | |
99 | + | ||
23 | 100 | ||
24 | 101 | @Callable(i) | |
25 | 102 | func proxyLiquidateV2 (market,userAddress,debtAssetIdStr,suppliedAssetIdStr,amount) = if ((indexOf(markets, market) == unit)) | |
54 | 131 | let inv = invoke(marketAddress, "liquidate", [false, userAddress, amount, suppliedAssetIdStr, debtAssetIdStr, routeStr], nil) | |
55 | 132 | if ((inv == inv)) | |
56 | 133 | then { | |
57 | - | let liquidatorReward = fraction(amount, LiquidatorReward, 10000) | |
58 | - | let statsKeyStr = ((("reward_" + toString(i.caller)) + "_") + suppliedAssetIdStr) | |
134 | + | let userBorrowedAmount = valueOrElse(getInteger(marketAddress, ((userAddress + "_borrowed_") + debtAssetIdStr)), 0) | |
135 | + | let userUsdBalance = getUserBalanceINTERNAL(marketAddress, userAddress, true) | |
136 | + | if ((0 > userBorrowedAmount)) | |
137 | + | then throw("transaction leads to a negative borrowed amount") | |
138 | + | else if (if (!(BadDebtLiqAllowed)) | |
139 | + | then (0 >= userUsdBalance) | |
140 | + | else false) | |
141 | + | then throw("transaction leads to a bad debt") | |
142 | + | else { | |
143 | + | let liquidatorReward = fraction(amount, LiquidatorReward, 10000) | |
144 | + | let statsKeyStr = ((("reward_" + toString(i.caller)) + "_") + suppliedAssetIdStr) | |
59 | 145 | [IntegerEntry(statsKeyStr, (valueOrElse(getInteger(this, statsKeyStr), 0) + liquidatorReward)), IntegerEntry(lastLiquidationKeyStr, height), IntegerEntry(lastLiqForMarketKeyStr, height)] | |
146 | + | } | |
60 | 147 | } | |
61 | 148 | else throw("Strict value is not equal to itself.") | |
62 | 149 | } | |
92 | 179 | else [IntegerEntry(key, val)] | |
93 | 180 | ||
94 | 181 | ||
182 | + | ||
183 | + | @Callable(i) | |
184 | + | func getUserBalanceREADONLY (debug,marketStr,address) = { | |
185 | + | let res = getUserBalanceINTERNAL(addressFromStringValue(marketStr), address, true) | |
186 | + | if ((debug == true)) | |
187 | + | then throw(toString(res)) | |
188 | + | else $Tuple2(nil, res) | |
189 | + | } | |
190 | + | ||
191 | + |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let Scale8 = 100000000 | |
5 | 5 | ||
6 | 6 | let Scale16 = 10000000000000000 | |
7 | 7 | ||
8 | 8 | func getAssetBytes (assetIdStr) = if ((assetIdStr == "WAVES")) | |
9 | 9 | then unit | |
10 | 10 | else fromBase58String(assetIdStr) | |
11 | 11 | ||
12 | 12 | ||
13 | 13 | func verifyLiquidatorAccess (address) = (indexOf(valueOrElse(getString(this, "setup_liquidators"), ""), toString(address)) != unit) | |
14 | 14 | ||
15 | 15 | ||
16 | 16 | let MaxShareToLiquidate = valueOrElse(getInteger(this, "setup_maxShareToLiquidate"), 100) | |
17 | 17 | ||
18 | 18 | let LiquidationDelay = valueOrElse(getInteger(this, "setup_liquidationDelay"), 10) | |
19 | 19 | ||
20 | 20 | let LiquidatorReward = valueOrElse(getInteger(this, "setup_liquidatorReward"), 10) | |
21 | 21 | ||
22 | + | let BadDebtLiqAllowed = (valueOrElse(getInteger(this, "setup_badDebtLiqAllowed"), 0) > 0) | |
23 | + | ||
24 | + | let OracleAddress = valueOrElse(addressFromString(valueOrElse(getString(this, "setup_address_oracle"), "")), Address(base58'3P8d1E1BLKoD52y3bQJ1bDTd2TD1gpaLn9t')) | |
25 | + | ||
22 | 26 | let markets = valueOrElse(getString(this, "setup_markets"), makeString(["3PHpuQUPVUoR3AYzFeJzeWJfYLsLTmWssVH"], ",")) | |
27 | + | ||
28 | + | func getUserBalanceINTERNAL (market,address,minusBorrowed) = { | |
29 | + | func tryGetString (key) = match getString(market, key) { | |
30 | + | case b: String => | |
31 | + | b | |
32 | + | case _ => | |
33 | + | "" | |
34 | + | } | |
35 | + | ||
36 | + | func tryGetInteger (key) = match getInteger(market, key) { | |
37 | + | case b: Int => | |
38 | + | b | |
39 | + | case _ => | |
40 | + | 0 | |
41 | + | } | |
42 | + | ||
43 | + | func getTokenPrice (assetIdStr) = if (if ((assetIdStr == "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi")) | |
44 | + | then true | |
45 | + | else (assetIdStr == "HGgabTqUS8WtVFUJzfmrTDMgEccJuZLBPhFgQFxvnsoW")) | |
46 | + | then $Tuple2(1000000, 1000000) | |
47 | + | else { | |
48 | + | let price = getIntegerValue(OracleAddress, (assetIdStr + "_twap5B")) | |
49 | + | $Tuple2(price, price) | |
50 | + | } | |
51 | + | ||
52 | + | func calcAssetScale (assetIdStr) = { | |
53 | + | let decimals = if ((assetIdStr == "WAVES")) | |
54 | + | then 8 | |
55 | + | else value(assetInfo(fromBase58String(assetIdStr))).decimals | |
56 | + | pow(10, 0, decimals, 0, 0, DOWN) | |
57 | + | } | |
58 | + | ||
59 | + | let assets = split(tryGetString("setup_tokens"), ",") | |
60 | + | let ltvs = split(tryGetString("setup_ltvs"), ",") | |
61 | + | let lts = split(tryGetString("setup_lts"), ",") | |
62 | + | func f (accum,next) = if ((next >= size(assets))) | |
63 | + | then accum | |
64 | + | else { | |
65 | + | let userSupplied = tryGetInteger(((address + "_supplied_") + assets[next])) | |
66 | + | let userBorrowed = tryGetInteger(((address + "_borrowed_") + assets[next])) | |
67 | + | let needTokenAccounting = if (if ((userBorrowed != 0)) | |
68 | + | then true | |
69 | + | else (userSupplied != 0)) | |
70 | + | then true | |
71 | + | else false | |
72 | + | if (needTokenAccounting) | |
73 | + | then { | |
74 | + | let assetScale = calcAssetScale(assets[next]) | |
75 | + | let assetPrice = getTokenPrice(assets[next]) | |
76 | + | ((accum + fraction(fraction(userSupplied, tryGetInteger((assets[next] + "_sRate")), Scale16), assetPrice._1, assetScale)) - (if (minusBorrowed) | |
77 | + | then fraction(fraction(userBorrowed, tryGetInteger((assets[next] + "_bRate")), Scale16), assetPrice._1, assetScale) | |
78 | + | else 0)) | |
79 | + | } | |
80 | + | else accum | |
81 | + | } | |
82 | + | ||
83 | + | let result = { | |
84 | + | let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] | |
85 | + | let $s = size($l) | |
86 | + | let $acc0 = 0 | |
87 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
88 | + | then $a | |
89 | + | else f($a, $l[$i]) | |
90 | + | ||
91 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
92 | + | then $a | |
93 | + | else throw("List size exceeds 12") | |
94 | + | ||
95 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12) | |
96 | + | } | |
97 | + | result | |
98 | + | } | |
99 | + | ||
23 | 100 | ||
24 | 101 | @Callable(i) | |
25 | 102 | func proxyLiquidateV2 (market,userAddress,debtAssetIdStr,suppliedAssetIdStr,amount) = if ((indexOf(markets, market) == unit)) | |
26 | 103 | then throw("given pool address is not a pool") | |
27 | 104 | else { | |
28 | 105 | let inv = invoke(addressFromStringValue(market), "liquidateV2", [false, userAddress, suppliedAssetIdStr], [AttachedPayment(getAssetBytes(debtAssetIdStr), amount)]) | |
29 | 106 | if ((inv == inv)) | |
30 | 107 | then nil | |
31 | 108 | else throw("Strict value is not equal to itself.") | |
32 | 109 | } | |
33 | 110 | ||
34 | 111 | ||
35 | 112 | ||
36 | 113 | @Callable(i) | |
37 | 114 | func proxyLiquidateV3 (market,userAddress,debtAssetIdStr,suppliedAssetIdStr,amount,routeStr) = if ((indexOf(markets, market) == unit)) | |
38 | 115 | then throw("given market address is not a market") | |
39 | 116 | else if (!(verifyLiquidatorAccess(i.caller))) | |
40 | 117 | then throw("no permission to perform liquidation") | |
41 | 118 | else { | |
42 | 119 | let marketAddress = addressFromStringValue(market) | |
43 | 120 | let sRate = getIntegerValue(marketAddress, (suppliedAssetIdStr + "_sRate")) | |
44 | 121 | let sAmount = getIntegerValue(marketAddress, ((userAddress + "_supplied_") + suppliedAssetIdStr)) | |
45 | 122 | let suppliedAmount = fraction(sAmount, sRate, Scale16) | |
46 | 123 | let lastLiqForMarketKeyStr = (("history_market_" + market) + "_lastLiquidation") | |
47 | 124 | let lastLiquidationKeyStr = (("history_user_" + userAddress) + "_lastLiquidation") | |
48 | 125 | let lastLiquidation = valueOrElse(getInteger(this, lastLiquidationKeyStr), 0) | |
49 | 126 | if ((amount > fraction(MaxShareToLiquidate, suppliedAmount, 10000))) | |
50 | 127 | then throw("should liquidate smaller part per time") | |
51 | 128 | else if (((lastLiquidation + LiquidationDelay) > height)) | |
52 | 129 | then throw("cannot liquidate yet") | |
53 | 130 | else { | |
54 | 131 | let inv = invoke(marketAddress, "liquidate", [false, userAddress, amount, suppliedAssetIdStr, debtAssetIdStr, routeStr], nil) | |
55 | 132 | if ((inv == inv)) | |
56 | 133 | then { | |
57 | - | let liquidatorReward = fraction(amount, LiquidatorReward, 10000) | |
58 | - | let statsKeyStr = ((("reward_" + toString(i.caller)) + "_") + suppliedAssetIdStr) | |
134 | + | let userBorrowedAmount = valueOrElse(getInteger(marketAddress, ((userAddress + "_borrowed_") + debtAssetIdStr)), 0) | |
135 | + | let userUsdBalance = getUserBalanceINTERNAL(marketAddress, userAddress, true) | |
136 | + | if ((0 > userBorrowedAmount)) | |
137 | + | then throw("transaction leads to a negative borrowed amount") | |
138 | + | else if (if (!(BadDebtLiqAllowed)) | |
139 | + | then (0 >= userUsdBalance) | |
140 | + | else false) | |
141 | + | then throw("transaction leads to a bad debt") | |
142 | + | else { | |
143 | + | let liquidatorReward = fraction(amount, LiquidatorReward, 10000) | |
144 | + | let statsKeyStr = ((("reward_" + toString(i.caller)) + "_") + suppliedAssetIdStr) | |
59 | 145 | [IntegerEntry(statsKeyStr, (valueOrElse(getInteger(this, statsKeyStr), 0) + liquidatorReward)), IntegerEntry(lastLiquidationKeyStr, height), IntegerEntry(lastLiqForMarketKeyStr, height)] | |
146 | + | } | |
60 | 147 | } | |
61 | 148 | else throw("Strict value is not equal to itself.") | |
62 | 149 | } | |
63 | 150 | } | |
64 | 151 | ||
65 | 152 | ||
66 | 153 | ||
67 | 154 | @Callable(i) | |
68 | 155 | func payoutReward (addressStr,assetIdStr) = if ((toString(i.caller) != "3PMcMiMEs6w56NRGacksXtFG5zS7doE9fpL")) | |
69 | 156 | then throw("no access to this method") | |
70 | 157 | else { | |
71 | 158 | let statsKeyStr = ((("reward_" + addressStr) + "_") + assetIdStr) | |
72 | 159 | let rewardAvailable = valueOrElse(getInteger(this, statsKeyStr), 0) | |
73 | 160 | [ScriptTransfer(addressFromStringValue(addressStr), rewardAvailable, getAssetBytes(assetIdStr)), IntegerEntry(statsKeyStr, 0)] | |
74 | 161 | } | |
75 | 162 | ||
76 | 163 | ||
77 | 164 | ||
78 | 165 | @Callable(i) | |
79 | 166 | func updateString (key,val) = if (if ((toString(i.caller) != "3PMcMiMEs6w56NRGacksXtFG5zS7doE9fpL")) | |
80 | 167 | then (toString(i.caller) != "3PHbdpaKzz8EiAngGHaFu2hVuNCdsC67qh3") | |
81 | 168 | else false) | |
82 | 169 | then throw("no access to this method") | |
83 | 170 | else [StringEntry(key, val)] | |
84 | 171 | ||
85 | 172 | ||
86 | 173 | ||
87 | 174 | @Callable(i) | |
88 | 175 | func updateInteger (key,val) = if (if ((toString(i.caller) != "3PMcMiMEs6w56NRGacksXtFG5zS7doE9fpL")) | |
89 | 176 | then (toString(i.caller) != "3PHbdpaKzz8EiAngGHaFu2hVuNCdsC67qh3") | |
90 | 177 | else false) | |
91 | 178 | then throw("no access to this method") | |
92 | 179 | else [IntegerEntry(key, val)] | |
93 | 180 | ||
94 | 181 | ||
182 | + | ||
183 | + | @Callable(i) | |
184 | + | func getUserBalanceREADONLY (debug,marketStr,address) = { | |
185 | + | let res = getUserBalanceINTERNAL(addressFromStringValue(marketStr), address, true) | |
186 | + | if ((debug == true)) | |
187 | + | then throw(toString(res)) | |
188 | + | else $Tuple2(nil, res) | |
189 | + | } | |
190 | + | ||
191 | + |
github/deemru/w8io/873ac7e 40.74 ms ◑![]()