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:
OldNewDifferences
1919
2020 let LiquidatorReward = valueOrElse(getInteger(this, "setup_liquidatorReward"), 10)
2121
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+
2226 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+
23100
24101 @Callable(i)
25102 func proxyLiquidateV2 (market,userAddress,debtAssetIdStr,suppliedAssetIdStr,amount) = if ((indexOf(markets, market) == unit))
54131 let inv = invoke(marketAddress, "liquidate", [false, userAddress, amount, suppliedAssetIdStr, debtAssetIdStr, routeStr], nil)
55132 if ((inv == inv))
56133 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)
59145 [IntegerEntry(statsKeyStr, (valueOrElse(getInteger(this, statsKeyStr), 0) + liquidatorReward)), IntegerEntry(lastLiquidationKeyStr, height), IntegerEntry(lastLiqForMarketKeyStr, height)]
146+ }
60147 }
61148 else throw("Strict value is not equal to itself.")
62149 }
92179 else [IntegerEntry(key, val)]
93180
94181
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+
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let Scale8 = 100000000
55
66 let Scale16 = 10000000000000000
77
88 func getAssetBytes (assetIdStr) = if ((assetIdStr == "WAVES"))
99 then unit
1010 else fromBase58String(assetIdStr)
1111
1212
1313 func verifyLiquidatorAccess (address) = (indexOf(valueOrElse(getString(this, "setup_liquidators"), ""), toString(address)) != unit)
1414
1515
1616 let MaxShareToLiquidate = valueOrElse(getInteger(this, "setup_maxShareToLiquidate"), 100)
1717
1818 let LiquidationDelay = valueOrElse(getInteger(this, "setup_liquidationDelay"), 10)
1919
2020 let LiquidatorReward = valueOrElse(getInteger(this, "setup_liquidatorReward"), 10)
2121
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+
2226 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+
23100
24101 @Callable(i)
25102 func proxyLiquidateV2 (market,userAddress,debtAssetIdStr,suppliedAssetIdStr,amount) = if ((indexOf(markets, market) == unit))
26103 then throw("given pool address is not a pool")
27104 else {
28105 let inv = invoke(addressFromStringValue(market), "liquidateV2", [false, userAddress, suppliedAssetIdStr], [AttachedPayment(getAssetBytes(debtAssetIdStr), amount)])
29106 if ((inv == inv))
30107 then nil
31108 else throw("Strict value is not equal to itself.")
32109 }
33110
34111
35112
36113 @Callable(i)
37114 func proxyLiquidateV3 (market,userAddress,debtAssetIdStr,suppliedAssetIdStr,amount,routeStr) = if ((indexOf(markets, market) == unit))
38115 then throw("given market address is not a market")
39116 else if (!(verifyLiquidatorAccess(i.caller)))
40117 then throw("no permission to perform liquidation")
41118 else {
42119 let marketAddress = addressFromStringValue(market)
43120 let sRate = getIntegerValue(marketAddress, (suppliedAssetIdStr + "_sRate"))
44121 let sAmount = getIntegerValue(marketAddress, ((userAddress + "_supplied_") + suppliedAssetIdStr))
45122 let suppliedAmount = fraction(sAmount, sRate, Scale16)
46123 let lastLiqForMarketKeyStr = (("history_market_" + market) + "_lastLiquidation")
47124 let lastLiquidationKeyStr = (("history_user_" + userAddress) + "_lastLiquidation")
48125 let lastLiquidation = valueOrElse(getInteger(this, lastLiquidationKeyStr), 0)
49126 if ((amount > fraction(MaxShareToLiquidate, suppliedAmount, 10000)))
50127 then throw("should liquidate smaller part per time")
51128 else if (((lastLiquidation + LiquidationDelay) > height))
52129 then throw("cannot liquidate yet")
53130 else {
54131 let inv = invoke(marketAddress, "liquidate", [false, userAddress, amount, suppliedAssetIdStr, debtAssetIdStr, routeStr], nil)
55132 if ((inv == inv))
56133 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)
59145 [IntegerEntry(statsKeyStr, (valueOrElse(getInteger(this, statsKeyStr), 0) + liquidatorReward)), IntegerEntry(lastLiquidationKeyStr, height), IntegerEntry(lastLiqForMarketKeyStr, height)]
146+ }
60147 }
61148 else throw("Strict value is not equal to itself.")
62149 }
63150 }
64151
65152
66153
67154 @Callable(i)
68155 func payoutReward (addressStr,assetIdStr) = if ((toString(i.caller) != "3PMcMiMEs6w56NRGacksXtFG5zS7doE9fpL"))
69156 then throw("no access to this method")
70157 else {
71158 let statsKeyStr = ((("reward_" + addressStr) + "_") + assetIdStr)
72159 let rewardAvailable = valueOrElse(getInteger(this, statsKeyStr), 0)
73160 [ScriptTransfer(addressFromStringValue(addressStr), rewardAvailable, getAssetBytes(assetIdStr)), IntegerEntry(statsKeyStr, 0)]
74161 }
75162
76163
77164
78165 @Callable(i)
79166 func updateString (key,val) = if (if ((toString(i.caller) != "3PMcMiMEs6w56NRGacksXtFG5zS7doE9fpL"))
80167 then (toString(i.caller) != "3PHbdpaKzz8EiAngGHaFu2hVuNCdsC67qh3")
81168 else false)
82169 then throw("no access to this method")
83170 else [StringEntry(key, val)]
84171
85172
86173
87174 @Callable(i)
88175 func updateInteger (key,val) = if (if ((toString(i.caller) != "3PMcMiMEs6w56NRGacksXtFG5zS7doE9fpL"))
89176 then (toString(i.caller) != "3PHbdpaKzz8EiAngGHaFu2hVuNCdsC67qh3")
90177 else false)
91178 then throw("no access to this method")
92179 else [IntegerEntry(key, val)]
93180
94181
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