2022.01.24 20:28 [2958437] smart account 3PAZv9tgK1PX7dKR7b4kchq5qdpUS3G5sYT > SELF 0.00000000 Waves

{ "type": 13, "id": "FWCBcxtpDwzCgf4wKEcmkN1eA51WPvKrskye9uyeiww5", "fee": 1000000, "feeAssetId": null, "timestamp": 1643045115676, "version": 1, "sender": "3PAZv9tgK1PX7dKR7b4kchq5qdpUS3G5sYT", "senderPublicKey": "2cFG5wZimjVSeCT8ZCRybx7Mzo5tJF879aw2b31uLRmR", "proofs": [ "33QtsLRRBVWY6QA5e7arX3XApLwpxjJujM1udnW6igLTMQMasg8LGDTPA3GwSdJZmj6hdMYBrGz28F1HVf5SQZsK" ], "script": "base64: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AAAAIndyb25nIHR5cGUsIGV4cGVjdGVkOiBJbnQ1JkJvb2xlYW4AAAAACmFkbWluU3RvcmUCAAAABWFkbWluAAAAAAtjb25maWdTdG9yZQIAAAAGY29uZmlnAAAAAA1yZXNlcnZlc1N0b3JlAgAAAAhyZXNlcnZlcwAAAAANYVRva2VuSWRTdG9yZQIAAAAIYVRva2VuSWQAAAAADGFzc2V0SWRTdG9yZQIAAAAHYXNzZXRJZAAAAAAQZGlzdHJpYnV0b3JTdG9yZQIAAAARdmlyZXNfZGlzdHJpYnV0b3IAAAAABWFkbWluCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAARQGV4dHJOYXRpdmUoMTA1MykAAAACBQAAAAR0aGlzBQAAAAphZG1pblN0b3JlAAAAAAZjb25maWcJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAQAAABFAZXh0ck5hdGl2ZSgxMDUzKQAAAAIFAAAABHRoaXMFAAAAC2NvbmZpZ1N0b3JlAAAAAAtyZXNlcnZlc1N0cgkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAABHRoaXMFAAAADXJlc2VydmVzU3RvcmUCAAAAFm5vIHJlc2VydmVzIHJlZ2lzdGVyZWQAAAAACHJlc2VydmVzCQAEtQAAAAIFAAAAC3Jlc2VydmVzU3RyAgAAAAF8AAAAAANlYlIJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAZjb25maWcCAAAACmViX3Jld2FyZHMCAAAAIG5vIGViX3Jld2FyZHMgY29udHJhY3QgaW4gY29uZmlnAAAAAAt2aXJlc01pbnRlcgkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEJgAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAZjb25maWcCAAAADHZpcmVzX21pbnRlcgIAAAAUbWFpbjogbm8gdmlyZXNNaW50ZXICAAAAE2ludmFsaWQgdmlyZXNNaW50ZXIAAAAAB21heWJldlMJAAQdAAAAAgUAAAAGY29uZmlnAgAAAAx2aXJlc19zdGFrZXIAAAAAAnZTCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIFAAAAB21heWJldlMCAAAAD25vIHZpcmVzX3N0YWtlcgAAAAACZEMJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABCYAAAABCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAGY29uZmlnAgAAABJkaXZpZGVuZHNfY29udHJhY3QCAAAAFW5vIGRpdmlkZW5kc19jb250cmFjdAIAAAAaaW52YWxpZCBkaXZpZGVuZHNfY29udHJhY3QAAAAAA21WRAQAAAAHJG1hdGNoMAkABB0AAAACBQAAAAZjb25maWcFAAAAEGRpc3RyaWJ1dG9yU3RvcmUDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABlN0cmluZwQAAAABZAUAAAAHJG1hdGNoMAkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAABZAUAAAAEdW5pdAAAAAACVkQJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgUAAAADbVZEAgAAAB9ubyBkaXN0cmlidXRvciB0byBjbGFpbSByZXdhcmRzAAAAABFtYXliZVZpcmVzQXNzZXRJZAkABB0AAAACBQAAAAt2aXJlc01pbnRlcgIAAAAHYXNzZXRJZAAAAAAMdmlyZXNBc3NldElkCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAJZAAAAAQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACBQAAABFtYXliZVZpcmVzQXNzZXRJZAIAAAAXdmlyZXMgYXNzZXRJZCBub3QgZm91bmQCAAAAFWludmFsaWQgdmlyZXMgYXNzZXRJZAEAAAAMdmlyZXNQYXltZW50AAAAAQAAAAFpAwkAAAAAAAACCQABkAAAAAEIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAAAAAAAAAAwkBAAAAAiE9AAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAHYXNzZXRJZAUAAAAMdmlyZXNBc3NldElkCQAAAgAAAAECAAAACW5vdCB2aXJlcwgJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50AQAAABBhc3NldElkT2ZSZXNlcnZlAAAAAQAAAAdyZXNlcnZlCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAHcmVzZXJ2ZQUAAAAMYXNzZXRJZFN0b3JlAgAAABVubyBhc3NldElkIGluIHJlc2VydmUBAAAAEGNvbGxhdGVyYWxGYWN0b3IAAAABAAAAB3Jlc2VydmUJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAAZjb25maWcJAAEsAAAAAgkBAAAAEGFzc2V0SWRPZlJlc2VydmUAAAABBQAAAAdyZXNlcnZlAgAAABFfQ29sbGF0ZXJhbEZhY3RvcgIAAAAdbm8gQ29sbGF0ZXJhbEZhY3RvciBpbiBjb25maWcBAAAAFGxpcXVpZGF0aW9uVGhyZXNob2xkAAAAAQAAAAdyZXNlcnZlCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAGY29uZmlnCQABLAAAAAIJAQAAABBhc3NldElkT2ZSZXNlcnZlAAAAAQUAAAAHcmVzZXJ2ZQIAAAAVX0xpcXVpZGF0aW9uVGhyZXNob2xkAgAAACFubyBMaXF1aWRhdGlvblRocmVzaG9sZCBpbiBjb25maWcBAAAAEmxpcXVpZGF0aW9uUGVuYWx0eQAAAAEAAAAHYXNzZXRJZAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAABmNvbmZpZwkAASwAAAACBQAAAAdhc3NldElkAgAAABNfTGlxdWlkYXRpb25QZW5hbHR5AgAAAB9ubyBMaXF1aWRhdGlvblBlbmFsdHkgaW4gY29uZmlnAAAAABZhY2NvdW50SGVhbHRoVGhyZXNob2xkCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAGY29uZmlnAgAAABhhY2NvdW50X2hlYWx0aF90aHJlc2hvbGQCAAAAG25vIGFjY291bnRfaGVhbHRoX3RocmVzaG9sZAAAAAAUYWNjb3VudEhlYWx0aE92ZXJsYXAJAQAAABN2YWx1ZU9yRXJy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dT0FAAAACGJvcnJvd2VyAgAAAAUsIGJwPQkAAaQAAAABBQAAAAJicAIAAAAGLCBicHU9CQABpAAAAAEFAAAAA2JwdQQAAAACYnIJAQAAAA92YWxpZGF0ZVJlc2VydmUAAAABBQAAAA1ib3Jyb3dSZXNlcnZlBAAAAAJjcgkBAAAAD3ZhbGlkYXRlUmVzZXJ2ZQAAAAEFAAAAEWNvbGxhdGVyYWxSZXNlcnZlBAAAAAtib3Jyb3dBc3NldAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAAAmJyAgAAAAdhc3NldElkCQABLAAAAAICAAAAIm5vIGFzc2V0SWQgZmllbGQgaW4gYm9ycm93UmVzZXJ2ZSAFAAAADWJvcnJvd1Jlc2VydmUEAAAAD2NvbGxhdGVyYWxBc3NldAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAAAmNyAgAAAAdhc3NldElkCQABLAAAAAICAAAAJm5vIGFzc2V0SWQgZmllbGQgaW4gY29sbGF0ZXJhbFJlc2VydmUgBQAAABFjb2xsYXRlcmFsUmVzZXJ2ZQQAAAAMaXNDb2xsYXRlcmFsCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGwAAAAIFAAAAAmNyCQABLAAAAAIFAAAACGJvcnJvd2VyAgAAABBfdXNlQXNDb2xsYXRlcmFsBwMJAAAAAAAAAgUAAAAMaXNDb2xsYXRlcmFsBQAAAAxpc0NvbGxhdGVyYWwDAwkBAAAAASEAAAABBQAAAA1mcm9tUHJvdGVjdGVkCQEAAAABIQAAAAEFAAAADGlzQ29sbGF0ZXJhbAcJAAACAAAAAQIAAAAuY2FuJ3QgbGlxdWlkYXRlIGRlcG9zaXQgbm90IHVzZWQgYXMgY29sbGF0ZXJhbAQAAAANJHQwMTExNDcxMTIzNwkBAAAAC3VzZXJCYWxhbmNlAAAAAgUAAAACYnIFAAAACGJvcnJvd2VyAwkAAAAAAAACBQAAAA0kdDAxMTE0NzExMjM3BQAAAA0kdDAxMTE0NzExMjM3BAAAAAt1c2VyRGVidFVzZAgFAAAADSR0MDExMTQ3MTEyMzcAAAACXzUEAAAACHVzZXJEZWJ0CAUAAAANJHQwMTExNDcxMTIzNwAAAAJfNAQAAAAMdXNlckFzc2V0VXNkCAUAAAANJHQwMTExNDcxMTIzNwAAAAJfMwQAAAAJdXNlckFzc2V0CAUAAAANJHQwMTExNDcxMTIzNwAAAAJfMgQAAAAGaWdub3JlCAUAAAANJHQwMTExNDcxMTIzNwAAAAJfMQMJAABnAAAAAgUAAAAJdXNlckFzc2V0BQAAAAh1c2VyRGVidAkAAAIAAAABAgAAAC9jYW4ndCBsaXF1aWRhdGUgZGVidCBvZiBhc3NldCBvZiBwb3NpdGl2ZSBzYWxkbwMJAABnAAAAAgAAAAAAAAAAAAUAAAATbGlxdWlkYXRlRGVidEFtb3VudAkAAAIAAAABAgAAACdjYW4ndCBsaXF1aWRhdGUgemVybyBvciBuZWdhdGl2ZSBhbW91bnQDCQAAZgAAAAIJAABoAAAAAgUAAAATbGlxdWlkYXRlRGVidEFtb3VudAAAAAAAAAAAAgkAAGUAAAACBQAAAAh1c2VyRGVidAUAAAAJdXNlckFzc2V0CQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAC5jYW4ndCBsaXF1aWRhdGUgbW9yZSB0aGFuIGhhbGYgb2Ygc2FsZG86IGRlYnQ9CQABpAAAAAEFAAAACHVzZXJEZWJ0AgAAAAosIGRlcG9zaXQ9CQABpAAAAAEFAAAACXVzZXJBc3NldAIAAAAYLCBsaXF1aWRhdGVEZWJ0QW1vdW50ID0gCQABpAAAAAEFAAAAE2xpcXVpZGF0ZURlYnRBbW91bnQEAAAADWNvbGxhdGVyYWxVc2QJAABrAAAAAwUAAAATbGlxdWlkYXRlRGVidEFtb3VudAUAAAALdXNlckRlYnRVc2QFAAAACHVzZXJEZWJ0BAAAAA1wZW5hbHRpemVkVXNkCQAAawAAAAMFAAAADWNvbGxhdGVyYWxVc2QJAABkAAAAAgUAAAALZmFjdG9yc0Jhc2UJAQAAABJsaXF1aWRhdGlvblBlbmFsdHkAAAABBQAAAAtib3Jyb3dBc3NldAUAAAALZmFjdG9yc0Jhc2UEAAAAAm1jAwUAAAANZnJvbVByb3RlY3RlZAkBAAAADm1vdmVDb2xsYXRlcmFsAAAABAUAAAAIYm9ycm93ZXIFAAAAD2NvbGxhdGVyYWxBc3NldAUAAAACY3IFAAAAEWNvbGxhdGVyYWxSZXNlcnZlBQAAAAR1bml0AwkAAAAAAAACBQAAAAJtYwUAAAACbWMEAAAAFXRyYW5zZmVycmVkQ29sbGF0ZXJhbAkBAAAABWFzSW50AAAAAQkAA/wAAAAEBQAAAAJjcgIAAAASdHJhbnNmZXJBVG9rZW5zRm9yCQAETAAAAAIFAAAACGJvcnJvd2VyCQAETAAAAAIFAAAACmxpcXVpZGF0b3IJAARMAAAAAgUAAAANcGVuYWx0aXplZFVzZAUAAAADbmlsBQAAAANuaWwDCQAAAAAAAAIFAAAAFXRyYW5zZmVycmVkQ29sbGF0ZXJhbAUAAAAVdHJhbnNmZXJyZWRDb2xsYXRlcmFsBAAAAARwUncxCQEAAAAKbW92ZVN0cmVhbQAAAAUFAAAAEWNvbGxhdGVyYWxSZXNlcnZlAgAAAAdkZXBvc2l0BQAAAAhib3Jyb3dlcgUAAAAKbGlxdWlkYXRvcgUAAAAVdHJhbnNmZXJyZWRDb2xsYXRlcmFsAwkAAAAAAAACBQAAAARwUncxBQAAAARwUncxBAAAAA90cmFuc2ZlcnJlZERlYnQJAQAAAAVhc0ludAAAAAEJAAP8AAAABAUAAAACYnICAAAAD3RyYW5zZmVyRGVidEZvcgkABEwAAAACBQAAAAhib3Jyb3dlcgkABEwAAAACBQAAAApsaXF1aWRhdG9yCQAETAAAAAIFAAAAE2xpcXVpZGF0ZURlYnRBbW91bnQFAAAAA25pbAUAAAADbmlsAwkAAAAAAAACBQAAAA90cmFuc2ZlcnJlZERlYnQFAAAAD3RyYW5zZmVycmVkRGVidAQAAAAEcFJ3MgkBAAAACm1vdmVTdHJlYW0AAAAFBQAAAA1ib3Jyb3dSZXNlcnZlAgAAAAZib3Jyb3cFAAAACGJvcnJvd2VyBQAAAApsaXF1aWRhdG9yBQAAAA90cmFuc2ZlcnJlZERlYnQDCQAAAAAAAAIFAAAABHBSdzIFAAAABHBSdzIEAAAAFWxpcXVpZGF0b3JIZWFsdGhDaGVjawMJAQAAAAhjb250YWlucwAAAAIFAAAAC2xpcXVpZGF0b3JzBQAAAApsaXF1aWRhdG9yBQAAAANuaWwJAQAAAA12YWxpZGF0ZUFmdGVyAAAAAgUAAAAKbGlxdWlkYXRvcgIAAAARdHJhbnNmZXJyaW5nIGRlYnQDCQAAAAAAAAIFAAAAFWxpcXVpZGF0b3JIZWFsdGhDaGVjawUAAAAVbGlxdWlkYXRvckhlYWx0aENoZWNrCQAFFAAAAAIFAAAAFWxpcXVpZGF0b3JIZWFsdGhDaGVjawUAAAAVdHJhbnNmZXJyZWRDb2xsYXRlcmFsCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEAAAAVZm9yY2VDb2xsYXBzZUludGVybmFsAAAABAAAAApsaXF1aWRhdG9yAAAAB3Jlc2VydmUAAAAIYm9ycm93ZXIAAAANZnJvbVByb3RlY3RlZAQAAAAOcmVzZXJ2ZUFkZHJlc3MJAQAAAA92YWxpZGF0ZVJlc2VydmUAAAABBQAAAAdyZXNlcnZlAwkAAAAAAAACBQAAAA5yZXNlcnZlQWRkcmVzcwUAAAAOcmVzZXJ2ZUFkZHJlc3MEAAAAAnNoCQEAAAARc3luY1Jld2FyZHNIZWlnaHQAAAABBQAAAAdyZXNlcnZlAwkAAAAAAAACBQAAAAJzaAUAAAACc2gDCQAAAAAAAAIFAAAACmxp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", "chainId": 87, "height": 2958437, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: rtoNMDpyMmKs1RxRcifMzBkrVXFbFzRnhVSqFbCQ1nr Next: 9t3TBRnN6tq3JWXAUDXjn1TJcgxGFLPQn8t7M9HaEhSo Diff:
OldNewDifferences
1111 then cand
1212 else (cand + 1)
1313 }
14+
15+
16+func assetStrToId (assetId) = if ((assetId == "WAVES"))
17+ then unit
18+ else fromBase58String(assetId)
1419
1520
1621 func writeConstString (key,value) = if (!(isDefined(getString(this, key))))
184189
185190 let protectedReserve = valueOrErrorMessage(maybeProtectedReserve, "no protected reserve")
186191
192+func ensureNoProtected (user) = {
193+ let has = match maybeProtectedReserve {
194+ case pa: Address =>
195+ valueOrElse(getBoolean(pa, ("protected_collateral_" + user)), false)
196+ case _ =>
197+ false
198+ }
199+ if (has)
200+ then throw("disallowed: protected")
201+ else unit
202+ }
203+
204+
187205 func userPower (user) = {
188206 let protectedDeposit = match maybeProtectedReserve {
189207 case pa: Address =>
192210 0
193211 }
194212 func fold (totals,r) = {
195- let $t054075436 = totals
196- let totalD = $t054075436._1
197- let totalB = $t054075436._2
213+ let $t057845830 = totals
214+ let totalD = $t057845830._1
215+ let totalB = $t057845830._2
216+ let numberOfBorrows = $t057845830._3
198217 let reserve = valueOrErrorMessage(addressFromString(r), "reserve bad address")
199218 let cf = collateralFactor(reserve)
200219 let lt = liquidationThreshold(reserve)
201- let $t056065694 = userBalance(reserve, user)
202- let token = $t056065694._1
203- let asset = $t056065694._2
204- let depositUsd = $t056065694._3
205- let debt = $t056065694._4
206- let debtUsd = $t056065694._5
207- let asCollateral = $t056065694._6
220+ let $t060006088 = userBalance(reserve, user)
221+ let token = $t060006088._1
222+ let asset = $t060006088._2
223+ let depositUsd = $t060006088._3
224+ let debt = $t060006088._4
225+ let debtUsd = $t060006088._5
226+ let asCollateral = $t060006088._6
227+ let totalBorrows = (numberOfBorrows + (if ((debt > 0))
228+ then 1
229+ else 0))
208230 let effectiveDepositUsd = if (asCollateral)
209231 then depositUsd
210232 else 0
211233 let overlapUsd = min([debtUsd, effectiveDepositUsd])
212234 let overlapCharge = fractionCeil(overlapUsd, accountHealthOverlap, factorsBase)
213235 if ((debtUsd > effectiveDepositUsd))
214- then $Tuple2(totalD, ((totalB + fraction((debtUsd - effectiveDepositUsd), factorsBase, lt)) + overlapCharge))
215- else $Tuple2((totalD + fraction((effectiveDepositUsd - debtUsd), cf, factorsBase)), (totalB + overlapCharge))
236+ then $Tuple3(totalD, ((totalB + fraction((debtUsd - effectiveDepositUsd), factorsBase, lt)) + overlapCharge), totalBorrows)
237+ else $Tuple3((totalD + fraction((effectiveDepositUsd - debtUsd), cf, factorsBase)), (totalB + overlapCharge), totalBorrows)
216238 }
217239
218- let $l = reserves
219- let $s = size($l)
220- let $acc0 = $Tuple2(protectedDeposit, 0)
221- func $f0_1 ($a,$i) = if (($i >= $s))
222- then $a
223- else fold($a, $l[$i])
240+ let r = {
241+ let $l = reserves
242+ let $s = size($l)
243+ let $acc0 = $Tuple3(protectedDeposit, 0, 0)
244+ func $f0_1 ($a,$i) = if (($i >= $s))
245+ then $a
246+ else fold($a, $l[$i])
224247
225- func $f0_2 ($a,$i) = if (($i >= $s))
226- then $a
227- else throw("List size exceeds 7")
248+ func $f0_2 ($a,$i) = if (($i >= $s))
249+ then $a
250+ else throw("List size exceeds 7")
228251
229- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7)
252+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7)
253+ }
254+ if (if ((protectedDeposit > 0))
255+ then (r._3 > 2)
256+ else false)
257+ then throw("can't have more than 2 borrows with protected collateral")
258+ else r
230259 }
231260
232261
233262 func getUserHealth (account) = {
234- let $t062556298 = asInt2(userPower(account))
235- let bp = $t062556298._1
236- let bpu = $t062556298._2
263+ let $t068776928 = asInt3(userPower(account))
264+ let bp = $t068776928._1
265+ let bpu = $t068776928._2
266+ let ignore = $t068776928._3
237267 ((("bp:" + toString(bp)) + ", bpu:") + toString(bpu))
238268 }
239269
240270
241271 func validateAfter (user,op) = {
242- let $t064096440 = userPower(user)
243- let bp = $t064096440._1
244- let bpu = $t064096440._2
272+ let $t070397070 = userPower(user)
273+ let bp = $t070397070._1
274+ let bpu = $t070397070._2
245275 let accHealth = (((bp - bpu) * factorsBase) / bp)
246276 if (if ((bp == 0))
247277 then (bpu == 0)
281311 }
282312
283313
284-func stakeOrPayout (recipient,amount,stake) = if (!(stake))
285- then [ScriptTransfer(recipient, amount, viresAssetId)]
286- else {
287- let doStake = invoke(vS, "stakeVires", [toString(recipient)], [AttachedPayment(viresAssetId, amount)])
288- if ((doStake == doStake))
289- then nil
290- else throw("Strict value is not equal to itself.")
291- }
292-
293-
294314 func lockOrPayout (recipient,amount,lock) = if (!(lock))
295315 then [ScriptTransfer(recipient, amount, viresAssetId)]
296316 else {
303323
304324 func doDeposit (i,reserve,useAsCollateral) = {
305325 let user = toString(i.caller)
306- let sh = syncRewardsHeight(reserve)
307- if ((sh == sh))
326+ let checks = ensureNoProtected(user)
327+ if ((checks == checks))
308328 then {
309- let action = invoke(validateReserve(reserve), "depositFor", [user, useAsCollateral], i.payments)
310- if ((action == action))
329+ let sh = syncRewardsHeight(reserve)
330+ if ((sh == sh))
311331 then {
312- let amt = i.payments[0].amount
313- let pRw = updateStream(reserve, "deposit", user, amt, amt)
314- if ((pRw == pRw))
315- then if (!(useAsCollateral))
316- then validateAfter(user, "depositing")
317- else nil
332+ let action = invoke(validateReserve(reserve), "depositFor", [user, useAsCollateral], i.payments)
333+ if ((action == action))
334+ then {
335+ let amt = i.payments[0].amount
336+ let pRw = updateStream(reserve, "deposit", user, amt, amt)
337+ if ((pRw == pRw))
338+ then if (!(useAsCollateral))
339+ then validateAfter(user, "depositing")
340+ else nil
341+ else throw("Strict value is not equal to itself.")
342+ }
318343 else throw("Strict value is not equal to itself.")
319344 }
320345 else throw("Strict value is not equal to itself.")
389414 else if ((liquidator == borrower))
390415 then throw("can't liquidate self")
391416 else {
392- let $t01004310078 = userPower(borrower)
393- let bp = $t01004310078._1
394- let bpu = $t01004310078._2
417+ let $t01044710482 = userPower(borrower)
418+ let bp = $t01044710482._1
419+ let bpu = $t01044710482._2
395420 if ((bp > bpu))
396421 then throw(((((("can't liquidate healthy user: u=" + borrower) + ", bp=") + toString(bp)) + ", bpu=") + toString(bpu)))
397422 else {
406431 else false)
407432 then throw("can't liquidate deposit not used as collateral")
408433 else {
409- let $t01074310833 = userBalance(br, borrower)
410- if (($t01074310833 == $t01074310833))
434+ let $t01114711237 = userBalance(br, borrower)
435+ if (($t01114711237 == $t01114711237))
411436 then {
412- let userDebtUsd = $t01074310833._5
413- let userDebt = $t01074310833._4
414- let userAssetUsd = $t01074310833._3
415- let userAsset = $t01074310833._2
416- let ignore = $t01074310833._1
437+ let userDebtUsd = $t01114711237._5
438+ let userDebt = $t01114711237._4
439+ let userAssetUsd = $t01114711237._3
440+ let userAsset = $t01114711237._2
441+ let ignore = $t01114711237._1
417442 if ((userAsset >= userDebt))
418443 then throw("can't liquidate debt of asset of positive saldo")
419444 else if ((0 >= liquidateDebtAmount))
478503 then if ((liquidator == borrower))
479504 then throw("can't collapse self in this function")
480505 else {
481- let $t01252012555 = userPower(borrower)
482- let bp = $t01252012555._1
483- let bpu = $t01252012555._2
506+ let $t01292412959 = userPower(borrower)
507+ let bp = $t01292412959._1
508+ let bpu = $t01292412959._2
484509 if ((bp > bpu))
485510 then throw(((((("can't force collapse healthy user: u=" + borrower) + ", bp=") + toString(bp)) + ", bpu=") + toString(bpu)))
486511 else {
490515 else unit
491516 if ((mc == mc))
492517 then {
493- let $t01293113039 = userBalance(reserveAddress, borrower)
494- if (($t01293113039 == $t01293113039))
518+ let $t01333513443 = userBalance(reserveAddress, borrower)
519+ if (($t01333513443 == $t01333513443))
495520 then {
496- let userDebtUsd = $t01293113039._5
497- let userDebt = $t01293113039._4
498- let userAssetUsd = $t01293113039._3
499- let borrowerDeposit = $t01293113039._2
500- let ignore = $t01293113039._1
521+ let userDebtUsd = $t01333513443._5
522+ let userDebt = $t01333513443._4
523+ let userAssetUsd = $t01333513443._3
524+ let borrowerDeposit = $t01333513443._2
525+ let ignore = $t01333513443._1
501526 let penaltizedUsd = fraction(min([userAssetUsd, userDebtUsd]), collapsePenalty, factorsBase)
502527 let transferredAssets = asInt(invoke(reserveAddress, "transferATokensFor", [borrower, liquidator, penaltizedUsd], nil))
503528 if ((transferredAssets == transferredAssets))
529554 else throw("Strict value is not equal to itself.")
530555 }
531556 }
557+ else throw("Strict value is not equal to itself.")
558+ }
559+ else throw("Strict value is not equal to itself.")
560+ }
561+
562+
563+func spfr () = invoke(dC, "shareProfitFromReserves", nil, nil)
564+
565+
566+func wdInternal (user,reserve,amount,op) = {
567+ let sh = syncRewardsHeight(toString(reserve))
568+ if ((sh == sh))
569+ then {
570+ let withdrawnAmount = asInt(invoke(reserve, op, [user, amount], nil))
571+ if ((withdrawnAmount == withdrawnAmount))
572+ then {
573+ let pRw = updateStream(toString(reserve), "deposit", user, -(withdrawnAmount), -(withdrawnAmount))
574+ if ((pRw == pRw))
575+ then withdrawnAmount
576+ else throw("Strict value is not equal to itself.")
577+ }
532578 else throw("Strict value is not equal to itself.")
533579 }
534580 else throw("Strict value is not equal to itself.")
585631 let sh = syncRewardsHeight(toString(targetContract))
586632 if ((sh == sh))
587633 then {
588- let mintedAssetAmount = asInt(invoke(targetContract, "mintAtokenFor", [user, amount], nil))
589- if ((mintedAssetAmount == mintedAssetAmount))
634+ let amt = asInt(invoke(targetContract, "mintAtokenFor", [user, amount], nil))
635+ if ((amt == amt))
590636 then {
591- let pRw = updateStream(toString(targetContract), "deposit", user, -(mintedAssetAmount), 0)
637+ let pRw = updateStream(toString(targetContract), "deposit", user, -(amt), 0)
592638 if ((pRw == pRw))
593639 then validateAfter(user, "minting")
594640 else throw("Strict value is not equal to itself.")
603649 @Callable(i)
604650 func replenishWithAtoken () = {
605651 let user = toString(i.caller)
606- let aTokenId = toBase58String(valueOrErrorMessage(i.payments[0].assetId, "bad assetId: waves not allowed"))
607- let targetContract = findReserveBy(aTokenIdStore, aTokenId)
608- let sh = syncRewardsHeight(toString(targetContract))
609- if ((sh == sh))
652+ let checks = ensureNoProtected(user)
653+ if ((checks == checks))
610654 then {
611- let replenishedAssetAmount = asInt(invoke(targetContract, "replenishWithAtokenFor", [user], i.payments))
612- if ((replenishedAssetAmount == replenishedAssetAmount))
655+ let aTokenId = toBase58String(valueOrErrorMessage(i.payments[0].assetId, "bad assetId: waves not allowed"))
656+ let targetContract = findReserveBy(aTokenIdStore, aTokenId)
657+ let sh = syncRewardsHeight(toString(targetContract))
658+ if ((sh == sh))
613659 then {
614- let pRw = updateStream(toString(targetContract), "deposit", user, replenishedAssetAmount, 0)
615- if ((pRw == pRw))
616- then nil
660+ let amt = asInt(invoke(targetContract, "replenishWithAtokenFor", [user], i.payments))
661+ if ((amt == amt))
662+ then {
663+ let pRw = updateStream(toString(targetContract), "deposit", user, amt, 0)
664+ if ((pRw == pRw))
665+ then nil
666+ else throw("Strict value is not equal to itself.")
667+ }
617668 else throw("Strict value is not equal to itself.")
618669 }
619670 else throw("Strict value is not equal to itself.")
631682 let sh = syncRewardsHeight(toString(targetContract))
632683 if ((sh == sh))
633684 then {
634- let redeemedAssetAmount = asInt(invoke(targetContract, "redeemAtokensFor", [user], i.payments))
635- if ((redeemedAssetAmount == redeemedAssetAmount))
685+ let amt = asInt(invoke(targetContract, "redeemAtokensFor", [user], i.payments))
686+ if ((amt == amt))
636687 then {
637- let pRw = updateStream(toString(targetContract), "deposit", user, 0, -(redeemedAssetAmount))
688+ let pRw = updateStream(toString(targetContract), "deposit", user, 0, -(amt))
638689 if ((pRw == pRw))
639690 then nil
640691 else throw("Strict value is not equal to itself.")
649700 @Callable(i)
650701 func withdraw (assetId,amount) = {
651702 let user = toString(i.caller)
652- let targetContract = findReserveBy(assetIdStore, assetId)
653- let sh = syncRewardsHeight(toString(targetContract))
654- if ((sh == sh))
655- then {
656- let withdrawnAmount = asInt(invoke(targetContract, "withdrawFor", [user, amount], nil))
657- if ((withdrawnAmount == withdrawnAmount))
658- then {
659- let pRw = updateStream(toString(targetContract), "deposit", user, -(withdrawnAmount), -(withdrawnAmount))
660- if ((pRw == pRw))
661- then validateAfter(user, "withdrawing")
662- else throw("Strict value is not equal to itself.")
663- }
664- else throw("Strict value is not equal to itself.")
665- }
703+ let result = asInt(wdInternal(user, findReserveBy(assetIdStore, assetId), amount, "withdrawFor"))
704+ if ((result == result))
705+ then $Tuple2(validateAfter(user, "withdrawing"), result)
666706 else throw("Strict value is not equal to itself.")
667707 }
668708
674714 let sh = syncRewardsHeight(reserve)
675715 if ((sh == sh))
676716 then {
677- let withdrawnAmount = asInt(invoke(validateReserve(reserve), "withdrawFor", [user, amount], nil))
678- if ((withdrawnAmount == withdrawnAmount))
717+ let amt = asInt(invoke(validateReserve(reserve), "withdrawFor", [user, amount], nil))
718+ if ((amt == amt))
679719 then {
680- let pRw = updateStream(reserve, "deposit", user, -(withdrawnAmount), -(withdrawnAmount))
720+ let pRw = updateStream(reserve, "deposit", user, -(amt), -(amt))
681721 if ((pRw == pRw))
682722 then if (contains(liquidators, user))
683723 then nil
692732
693733
694734 @Callable(i)
735+func protectCollateral (reserve) = {
736+ let user = toString(i.caller)
737+ let r = validateReserve(reserve)
738+ let amt = asInt(wdInternal(user, r, -1, "withdrawToMain"))
739+ if ((amt == amt))
740+ then {
741+ let assetId = assetStrToId(getStringValue(r, assetIdStore))
742+ let p = invoke(protectedReserve, "supplyFor", [user], [AttachedPayment(assetId, amt)])
743+ if ((p == p))
744+ then $Tuple2(validateAfter(user, "protecting"), amt)
745+ else throw("Strict value is not equal to itself.")
746+ }
747+ else throw("Strict value is not equal to itself.")
748+ }
749+
750+
751+
752+@Callable(i)
695753 func withdrawProtectedCollateral (assetId,amount) = {
696754 let user = toString(i.caller)
697- let withdrawnAmount = asInt(invoke(valueOrErrorMessage(protectedReserve, "no protectedReserve"), "withdrawFor", [user, assetId, amount], nil))
698- if ((withdrawnAmount == withdrawnAmount))
755+ let a = asInt(invoke(valueOrErrorMessage(protectedReserve, "no protectedReserve"), "withdrawFor", [user, assetId, amount], nil))
756+ if ((a == a))
699757 then validateAfter(user, "withdrawing protected collateral")
700758 else throw("Strict value is not equal to itself.")
701759 }
709767 let sh = syncRewardsHeight(toString(reserve))
710768 if ((sh == sh))
711769 then {
712- let action = invoke(reserve, "borrowFor", [user, amount], nil)
713- if ((action == action))
770+ let a = invoke(reserve, "borrowFor", [user, amount], nil)
771+ if ((a == a))
714772 then {
715773 let pRw = updateStream(toString(reserve), "borrow", user, amount, amount)
716774 if ((pRw == pRw))
730788 let sh = syncRewardsHeight(reserve)
731789 if ((sh == sh))
732790 then {
733- let action = invoke(validateReserve(reserve), "borrowFor", [user, amount], nil)
734- if ((action == action))
791+ let a = invoke(validateReserve(reserve), "borrowFor", [user, amount], nil)
792+ if ((a == a))
735793 then {
736794 let pRw = updateStream(reserve, "borrow", user, amount, amount)
737795 if ((pRw == pRw))
751809 let sh = syncRewardsHeight(reserve)
752810 if ((sh == sh))
753811 then {
754- let collapse = asInt(invoke(validateReserve(reserve), "collapseForAmount", [user, amount], nil))
755- if ((collapse == collapse))
812+ let c = asInt(invoke(validateReserve(reserve), "collapseForAmount", [user, amount], nil))
813+ if ((c == c))
756814 then {
757- let pRw = updateStream(reserve, "borrow", user, -(collapse), -(collapse))
815+ let pRw = updateStream(reserve, "borrow", user, -(c), -(c))
758816 if ((pRw == pRw))
759817 then {
760- let pRw2 = updateStream(reserve, "deposit", user, -(collapse), -(collapse))
818+ let pRw2 = updateStream(reserve, "deposit", user, -(c), -(c))
761819 if ((pRw2 == pRw2))
762820 then nil
763821 else throw("Strict value is not equal to itself.")
772830
773831
774832 @Callable(i)
775-func claimEbReward (amount,stake) = {
776- let user = toString(i.caller)
777- let claimed = asInt(invoke(ebR, "claimEbRewardFor", [user, amount], nil))
778- if ((claimed == claimed))
779- then stakeOrPayout(i.caller, claimed, stake)
780- else throw("Strict value is not equal to itself.")
781- }
782-
783-
784-
785-@Callable(i)
786833 func claimEbReward2 (amount,lock) = {
787834 let user = toString(i.caller)
788- let claimed = asInt(invoke(ebR, "claimEbRewardFor", [user, amount], nil))
789- if ((claimed == claimed))
790- then lockOrPayout(i.caller, claimed, lock)
791- else throw("Strict value is not equal to itself.")
792- }
793-
794-
795-
796-@Callable(i)
797-func claimReward (reserve,amount,stake) = {
798- let v = validateReserve(reserve)
799- if ((v == v))
800- then {
801- let user = toString(i.caller)
802- let claimed = asInt(invoke(VD, "claimRewardFor", [reserve, user, amount], nil))
803- if ((claimed == claimed))
804- then stakeOrPayout(i.caller, claimed, stake)
805- else throw("Strict value is not equal to itself.")
806- }
835+ let c = asInt(invoke(ebR, "claimEbRewardFor", [user, amount], nil))
836+ if ((c == c))
837+ then lockOrPayout(i.caller, c, lock)
807838 else throw("Strict value is not equal to itself.")
808839 }
809840
815846 if ((v == v))
816847 then {
817848 let user = toString(i.caller)
818- let claimed = asInt(invoke(VD, "claimRewardFor", [reserve, user, amount], nil))
819- if ((claimed == claimed))
820- then lockOrPayout(i.caller, claimed, lock)
849+ let c = asInt(invoke(VD, "claimRewardFor", [reserve, user, amount], nil))
850+ if ((c == c))
851+ then lockOrPayout(i.caller, c, lock)
821852 else throw("Strict value is not equal to itself.")
822853 }
823854 else throw("Strict value is not equal to itself.")
826857
827858
828859 @Callable(i)
829-func claimAllRewardsAndAllEbAvailable (stake) = {
830- let user = toString(i.caller)
831- stakeOrPayout(i.caller, claimAllRewardsForUser(user), stake)
832- }
833-
834-
835-
836-@Callable(i)
837860 func claimAllRewardsAndAllEbAvailable2 (lock,unstakeLegacy) = {
838861 let user = toString(i.caller)
839- let claimedRewards = claimAllRewardsForUser(user)
840- if ((claimedRewards == claimedRewards))
862+ let cr = claimAllRewardsForUser(user)
863+ if ((cr == cr))
841864 then {
842865 let lA = if (unstakeLegacy)
843866 then asInt(invoke(vS, "unstakeAllViresFrom", [user], nil))
844867 else 0
845868 if ((lA == lA))
846- then lockOrPayout(i.caller, (claimedRewards + lA), lock)
869+ then lockOrPayout(i.caller, (cr + lA), lock)
847870 else throw("Strict value is not equal to itself.")
848871 }
849872 else throw("Strict value is not equal to itself.")
854877 @Callable(i)
855878 func disableUseAsCollateral (reserve) = {
856879 let user = toString(i.caller)
857- let doSetCollateral = invoke(validateReserve(reserve), "disableUseAsCollateralFor", [user], nil)
858- if ((doSetCollateral == doSetCollateral))
880+ let d = invoke(validateReserve(reserve), "disableUseAsCollateralFor", [user], nil)
881+ if ((d == d))
859882 then validateAfter(user, "changing collateral status")
860883 else throw("Strict value is not equal to itself.")
861884 }
863886
864887
865888 @Callable(i)
866-func transferDebt (borrowReserve,collateralReserve,borrower,liquidateDebtAmount) = transferDebtInternal(toString(i.caller), borrowReserve, collateralReserve, borrower, liquidateDebtAmount, false)
889+func transferDebt (br,cr,b,la) = transferDebtInternal(toString(i.caller), br, cr, b, la, false)
867890
868891
869892
870893 @Callable(i)
871-func forceCollapse (reserve,borrower) = forceCollapseInternal(toString(i.caller), reserve, borrower, false)
894+func transferDebt2 (br,cr,b,la) = transferDebtInternal(toString(i.caller), br, cr, b, la, true)
895+
896+
897+
898+@Callable(i)
899+func forceCollapse (r,b) = forceCollapseInternal(toString(i.caller), r, b, false)
900+
901+
902+
903+@Callable(i)
904+func forceCollapse2 (r,b) = forceCollapseInternal(toString(i.caller), r, b, true)
872905
873906
874907
875908 @Callable(i)
876909 func lockVires (factor,migrate) = {
877910 let user = toString(i.caller)
878- let a = invoke(dC, "shareProfitFromReserves", nil, nil)
911+ let a = spfr()
879912 if ((a == a))
880913 then {
881914 let migrateAmount = if (migrate)
897930 @Callable(i)
898931 func withdrawAllPossibleVires () = {
899932 let user = toString(i.caller)
900- let a = invoke(dC, "shareProfitFromReserves", nil, nil)
933+ let a = spfr()
901934 if ((a == a))
902935 then {
903936 let stakerViresAmount = asInt(invoke(vS, "unstakeAllViresFrom", [user], nil))
918951 @Callable(i)
919952 func claimProtocolProfitFrom (from,relock) = {
920953 let user = toString(i.caller)
921- let a = invoke(dC, "shareProfitFromReserves", nil, nil)
954+ let a = spfr()
922955 if ((a == a))
923956 then {
924957 let u = invoke(dC, "claimProfit", [from, user, relock], nil)
933966
934967 @Callable(i)
935968 func withdrawUnlockedVires () = {
936- let a = invoke(dC, "shareProfitFromReserves", nil, nil)
969+ let a = spfr()
937970 if ((a == a))
938971 then {
939972 let u = invoke(dC, "withdrawUnlockedFor", [toString(i.caller)], nil)
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let factorsBase = 1000
55
66 func fractionCeil (value,numerator,denominator) = {
77 let cand = fraction(value, numerator, denominator)
88 let D = 3037000499
99 let exact = ((((cand % D) * (denominator % D)) % D) == (((value % D) * (numerator % D)) % D))
1010 if (exact)
1111 then cand
1212 else (cand + 1)
1313 }
14+
15+
16+func assetStrToId (assetId) = if ((assetId == "WAVES"))
17+ then unit
18+ else fromBase58String(assetId)
1419
1520
1621 func writeConstString (key,value) = if (!(isDefined(getString(this, key))))
1722 then StringEntry(key, value)
1823 else throw(("already initialized: " + key))
1924
2025
2126 func asInt (value) = match value {
2227 case int: Int =>
2328 int
2429 case _ =>
2530 throw("wrong type, expected: Int")
2631 }
2732
2833
2934 func asInt2 (value) = match value {
3035 case x: (Int, Int) =>
3136 x
3237 case t =>
3338 throw("wrong type, expected: Int2")
3439 }
3540
3641
3742 func asInt3 (value) = match value {
3843 case x: (Int, Int, Int) =>
3944 x
4045 case t =>
4146 throw("wrong type, expected: Int3")
4247 }
4348
4449
4550 func asInt4 (value) = match value {
4651 case x: (Int, Int, Int, Int) =>
4752 x
4853 case t =>
4954 throw("wrong type, expected: Int4")
5055 }
5156
5257
5358 func asInt5 (value) = match value {
5459 case x: (Int, Int, Int, Int, Int) =>
5560 x
5661 case t =>
5762 throw("wrong type, expected: Int5")
5863 }
5964
6065
6166 func asUserBalanceData (value) = match value {
6267 case x: (Int, Int, Int, Int, Int, Boolean) =>
6368 x
6469 case t =>
6570 throw("wrong type, expected: Int5&Boolean")
6671 }
6772
6873
6974 let adminStore = "admin"
7075
7176 let configStore = "config"
7277
7378 let reservesStore = "reserves"
7479
7580 let aTokenIdStore = "aTokenId"
7681
7782 let assetIdStore = "assetId"
7883
7984 let distributorStore = "vires_distributor"
8085
8186 let admin = addressFromStringValue(getStringValue(this, adminStore))
8287
8388 let config = addressFromStringValue(getStringValue(this, configStore))
8489
8590 let reservesStr = valueOrErrorMessage(getString(this, reservesStore), "no reserves registered")
8691
8792 let reserves = split(reservesStr, "|")
8893
8994 let ebR = addressFromStringValue(valueOrErrorMessage(getString(config, "eb_rewards"), "no eb_rewards contract in config"))
9095
9196 let viresMinter = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(config, "vires_minter"), "main: no viresMinter")), "invalid viresMinter")
9297
9398 let maybevS = getString(config, "vires_staker")
9499
95100 let vS = addressFromStringValue(valueOrErrorMessage(maybevS, "no vires_staker"))
96101
97102 let dC = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(config, "dividends_contract"), "no dividends_contract")), "invalid dividends_contract")
98103
99104 let mVD = match getString(config, distributorStore) {
100105 case d: String =>
101106 addressFromStringValue(d)
102107 case _ =>
103108 unit
104109 }
105110
106111 let VD = valueOrErrorMessage(mVD, "no distributor to claim rewards")
107112
108113 let maybeViresAssetId = getString(viresMinter, "assetId")
109114
110115 let viresAssetId = valueOrErrorMessage(fromBase58String(valueOrErrorMessage(maybeViresAssetId, "vires assetId not found")), "invalid vires assetId")
111116
112117 func viresPayment (i) = if ((size(i.payments) == 0))
113118 then 0
114119 else if ((i.payments[0].assetId != viresAssetId))
115120 then throw("not vires")
116121 else i.payments[0].amount
117122
118123
119124 func assetIdOfReserve (reserve) = valueOrErrorMessage(getString(reserve, assetIdStore), "no assetId in reserve")
120125
121126
122127 func collateralFactor (reserve) = valueOrErrorMessage(getInteger(config, (assetIdOfReserve(reserve) + "_CollateralFactor")), "no CollateralFactor in config")
123128
124129
125130 func liquidationThreshold (reserve) = valueOrErrorMessage(getInteger(config, (assetIdOfReserve(reserve) + "_LiquidationThreshold")), "no LiquidationThreshold in config")
126131
127132
128133 func liquidationPenalty (assetId) = valueOrErrorMessage(getInteger(config, (assetId + "_LiquidationPenalty")), "no LiquidationPenalty in config")
129134
130135
131136 let accountHealthThreshold = valueOrErrorMessage(getInteger(config, "account_health_threshold"), "no account_health_threshold")
132137
133138 let accountHealthOverlap = valueOrErrorMessage(getInteger(config, "account_health_overlap"), "no account_health_overlap")
134139
135140 let collapsePenalty = valueOrErrorMessage(getInteger(config, "collapse_penalty"), "no collapse_penalty")
136141
137142 let liquidators = valueOrElse(getString(config, "liquidators"), "")
138143
139144 func findReserveBy (store,value) = {
140145 func fold (a,r) = match a {
141146 case found: Address =>
142147 found
143148 case _ =>
144149 let reserve = valueOrErrorMessage(addressFromString(r), "reserve bad address")
145150 if ((valueOrErrorMessage(getString(reserve, store), ("reserve has no " + store)) == value))
146151 then reserve
147152 else unit
148153 }
149154
150155 match let $l = reserves
151156 let $s = size($l)
152157 let $acc0 = unit
153158 func $f0_1 ($a,$i) = if (($i >= $s))
154159 then $a
155160 else fold($a, $l[$i])
156161
157162 func $f0_2 ($a,$i) = if (($i >= $s))
158163 then $a
159164 else throw("List size exceeds 7")
160165
161166 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7) {
162167 case found: Address =>
163168 found
164169 case _ =>
165170 throw(("unknown " + store))
166171 }
167172 }
168173
169174
170175 func validateReserve (r) = if (contains(reservesStr, r))
171176 then valueOrErrorMessage(addressFromString(r), "main: bad reserve")
172177 else throw(("unknown reserve:" + r))
173178
174179
175180 func userBalance (reserve,user) = asUserBalanceData(invoke(reserve, "userBalance", [user], nil))
176181
177182
178183 let maybeProtectedReserve = match getString(config, "protected_reserve") {
179184 case pds: String =>
180185 valueOrErrorMessage(addressFromString(pds), "bad protected_reserve")
181186 case _ =>
182187 unit
183188 }
184189
185190 let protectedReserve = valueOrErrorMessage(maybeProtectedReserve, "no protected reserve")
186191
192+func ensureNoProtected (user) = {
193+ let has = match maybeProtectedReserve {
194+ case pa: Address =>
195+ valueOrElse(getBoolean(pa, ("protected_collateral_" + user)), false)
196+ case _ =>
197+ false
198+ }
199+ if (has)
200+ then throw("disallowed: protected")
201+ else unit
202+ }
203+
204+
187205 func userPower (user) = {
188206 let protectedDeposit = match maybeProtectedReserve {
189207 case pa: Address =>
190208 asInt(invoke(pa, "borrowPower", [user], nil))
191209 case _ =>
192210 0
193211 }
194212 func fold (totals,r) = {
195- let $t054075436 = totals
196- let totalD = $t054075436._1
197- let totalB = $t054075436._2
213+ let $t057845830 = totals
214+ let totalD = $t057845830._1
215+ let totalB = $t057845830._2
216+ let numberOfBorrows = $t057845830._3
198217 let reserve = valueOrErrorMessage(addressFromString(r), "reserve bad address")
199218 let cf = collateralFactor(reserve)
200219 let lt = liquidationThreshold(reserve)
201- let $t056065694 = userBalance(reserve, user)
202- let token = $t056065694._1
203- let asset = $t056065694._2
204- let depositUsd = $t056065694._3
205- let debt = $t056065694._4
206- let debtUsd = $t056065694._5
207- let asCollateral = $t056065694._6
220+ let $t060006088 = userBalance(reserve, user)
221+ let token = $t060006088._1
222+ let asset = $t060006088._2
223+ let depositUsd = $t060006088._3
224+ let debt = $t060006088._4
225+ let debtUsd = $t060006088._5
226+ let asCollateral = $t060006088._6
227+ let totalBorrows = (numberOfBorrows + (if ((debt > 0))
228+ then 1
229+ else 0))
208230 let effectiveDepositUsd = if (asCollateral)
209231 then depositUsd
210232 else 0
211233 let overlapUsd = min([debtUsd, effectiveDepositUsd])
212234 let overlapCharge = fractionCeil(overlapUsd, accountHealthOverlap, factorsBase)
213235 if ((debtUsd > effectiveDepositUsd))
214- then $Tuple2(totalD, ((totalB + fraction((debtUsd - effectiveDepositUsd), factorsBase, lt)) + overlapCharge))
215- else $Tuple2((totalD + fraction((effectiveDepositUsd - debtUsd), cf, factorsBase)), (totalB + overlapCharge))
236+ then $Tuple3(totalD, ((totalB + fraction((debtUsd - effectiveDepositUsd), factorsBase, lt)) + overlapCharge), totalBorrows)
237+ else $Tuple3((totalD + fraction((effectiveDepositUsd - debtUsd), cf, factorsBase)), (totalB + overlapCharge), totalBorrows)
216238 }
217239
218- let $l = reserves
219- let $s = size($l)
220- let $acc0 = $Tuple2(protectedDeposit, 0)
221- func $f0_1 ($a,$i) = if (($i >= $s))
222- then $a
223- else fold($a, $l[$i])
240+ let r = {
241+ let $l = reserves
242+ let $s = size($l)
243+ let $acc0 = $Tuple3(protectedDeposit, 0, 0)
244+ func $f0_1 ($a,$i) = if (($i >= $s))
245+ then $a
246+ else fold($a, $l[$i])
224247
225- func $f0_2 ($a,$i) = if (($i >= $s))
226- then $a
227- else throw("List size exceeds 7")
248+ func $f0_2 ($a,$i) = if (($i >= $s))
249+ then $a
250+ else throw("List size exceeds 7")
228251
229- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7)
252+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7)
253+ }
254+ if (if ((protectedDeposit > 0))
255+ then (r._3 > 2)
256+ else false)
257+ then throw("can't have more than 2 borrows with protected collateral")
258+ else r
230259 }
231260
232261
233262 func getUserHealth (account) = {
234- let $t062556298 = asInt2(userPower(account))
235- let bp = $t062556298._1
236- let bpu = $t062556298._2
263+ let $t068776928 = asInt3(userPower(account))
264+ let bp = $t068776928._1
265+ let bpu = $t068776928._2
266+ let ignore = $t068776928._3
237267 ((("bp:" + toString(bp)) + ", bpu:") + toString(bpu))
238268 }
239269
240270
241271 func validateAfter (user,op) = {
242- let $t064096440 = userPower(user)
243- let bp = $t064096440._1
244- let bpu = $t064096440._2
272+ let $t070397070 = userPower(user)
273+ let bp = $t070397070._1
274+ let bpu = $t070397070._2
245275 let accHealth = (((bp - bpu) * factorsBase) / bp)
246276 if (if ((bp == 0))
247277 then (bpu == 0)
248278 else false)
249279 then nil
250280 else if (if ((bp == 0))
251281 then (bpu > 0)
252282 else false)
253283 then throw(((op + " too much: breaching liquidation threshold(bp=0, bpu=") + toString(bpu)))
254284 else if ((accountHealthThreshold > accHealth))
255285 then throw((((((((op + " too much: breaching liquidation threshold(bp=") + toString(bp)) + ", bpu=") + toString(bpu)) + ", health=") + toString(accHealth)) + ")"))
256286 else nil
257287 }
258288
259289
260290 func updateStream (reserve,action,user,userChange,streamChange) = match mVD {
261291 case a: Address =>
262292 invoke(a, "onAction", [reserve, action, user, userChange, streamChange], nil)
263293 case _ =>
264294 unit
265295 }
266296
267297
268298 func moveStream (reserve,action,from,string,amount) = match mVD {
269299 case a: Address =>
270300 invoke(a, "move", [reserve, action, from, string, amount], nil)
271301 case _ =>
272302 unit
273303 }
274304
275305
276306 func syncRewardsHeight (reserve) = match mVD {
277307 case a: Address =>
278308 invoke(a, "syncHeight", [reserve], nil)
279309 case _ =>
280310 unit
281311 }
282312
283313
284-func stakeOrPayout (recipient,amount,stake) = if (!(stake))
285- then [ScriptTransfer(recipient, amount, viresAssetId)]
286- else {
287- let doStake = invoke(vS, "stakeVires", [toString(recipient)], [AttachedPayment(viresAssetId, amount)])
288- if ((doStake == doStake))
289- then nil
290- else throw("Strict value is not equal to itself.")
291- }
292-
293-
294314 func lockOrPayout (recipient,amount,lock) = if (!(lock))
295315 then [ScriptTransfer(recipient, amount, viresAssetId)]
296316 else {
297317 let doLock = invoke(dC, "lockFor", [toString(recipient), 1], [AttachedPayment(viresAssetId, amount)])
298318 if ((doLock == doLock))
299319 then nil
300320 else throw("Strict value is not equal to itself.")
301321 }
302322
303323
304324 func doDeposit (i,reserve,useAsCollateral) = {
305325 let user = toString(i.caller)
306- let sh = syncRewardsHeight(reserve)
307- if ((sh == sh))
326+ let checks = ensureNoProtected(user)
327+ if ((checks == checks))
308328 then {
309- let action = invoke(validateReserve(reserve), "depositFor", [user, useAsCollateral], i.payments)
310- if ((action == action))
329+ let sh = syncRewardsHeight(reserve)
330+ if ((sh == sh))
311331 then {
312- let amt = i.payments[0].amount
313- let pRw = updateStream(reserve, "deposit", user, amt, amt)
314- if ((pRw == pRw))
315- then if (!(useAsCollateral))
316- then validateAfter(user, "depositing")
317- else nil
332+ let action = invoke(validateReserve(reserve), "depositFor", [user, useAsCollateral], i.payments)
333+ if ((action == action))
334+ then {
335+ let amt = i.payments[0].amount
336+ let pRw = updateStream(reserve, "deposit", user, amt, amt)
337+ if ((pRw == pRw))
338+ then if (!(useAsCollateral))
339+ then validateAfter(user, "depositing")
340+ else nil
341+ else throw("Strict value is not equal to itself.")
342+ }
318343 else throw("Strict value is not equal to itself.")
319344 }
320345 else throw("Strict value is not equal to itself.")
321346 }
322347 else throw("Strict value is not equal to itself.")
323348 }
324349
325350
326351 func claimAllRewardsForUser (user) = {
327352 let claimedEb = asInt(invoke(ebR, "claimEbRewardFor", [user, -1], nil))
328353 if ((claimedEb == claimedEb))
329354 then {
330355 let rewardReserves = split(valueOrErrorMessage(getString(VD, "reward_reserves"), "no string"), "|")
331356 func fold (acc,reserve) = {
332357 let claimed = asInt(invoke(VD, "claimRewardFor", [reserve, user, -1], nil))
333358 if ((claimed == claimed))
334359 then (acc + claimed)
335360 else throw("Strict value is not equal to itself.")
336361 }
337362
338363 let claimedTotal = {
339364 let $l = rewardReserves
340365 let $s = size($l)
341366 let $acc0 = 0
342367 func $f0_1 ($a,$i) = if (($i >= $s))
343368 then $a
344369 else fold($a, $l[$i])
345370
346371 func $f0_2 ($a,$i) = if (($i >= $s))
347372 then $a
348373 else throw("List size exceeds 7")
349374
350375 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7)
351376 }
352377 (claimedTotal + claimedEb)
353378 }
354379 else throw("Strict value is not equal to itself.")
355380 }
356381
357382
358383 func moveCollateral (addr,assetStr,reserve,reserveStr) = {
359384 let amt = asInt(invoke(protectedReserve, "withdrawToMain", [addr, assetStr], nil))
360385 if ((amt == amt))
361386 then {
362387 let assetId = if ((assetStr == "WAVES"))
363388 then unit
364389 else fromBase58String(assetStr)
365390 let dep = invoke(reserve, "depositFor", [addr, true], [AttachedPayment(assetId, amt)])
366391 if ((dep == dep))
367392 then {
368393 let prop = updateStream(reserveStr, "deposit", addr, amt, amt)
369394 if ((prop == prop))
370395 then unit
371396 else throw("Strict value is not equal to itself.")
372397 }
373398 else throw("Strict value is not equal to itself.")
374399 }
375400 else throw("Strict value is not equal to itself.")
376401 }
377402
378403
379404 func transferDebtInternal (liquidator,borrowReserve,collateralReserve,borrower,liquidateDebtAmount,fromProtected) = {
380405 let sh1 = syncRewardsHeight(borrowReserve)
381406 if ((sh1 == sh1))
382407 then {
383408 let sh2 = syncRewardsHeight(collateralReserve)
384409 if ((sh2 == sh2))
385410 then if ((0 >= liquidateDebtAmount))
386411 then throw("can't liquidate non-positive amount")
387412 else if ((collateralReserve == borrowReserve))
388413 then throw("collateralReserve equals borrowReserve")
389414 else if ((liquidator == borrower))
390415 then throw("can't liquidate self")
391416 else {
392- let $t01004310078 = userPower(borrower)
393- let bp = $t01004310078._1
394- let bpu = $t01004310078._2
417+ let $t01044710482 = userPower(borrower)
418+ let bp = $t01044710482._1
419+ let bpu = $t01044710482._2
395420 if ((bp > bpu))
396421 then throw(((((("can't liquidate healthy user: u=" + borrower) + ", bp=") + toString(bp)) + ", bpu=") + toString(bpu)))
397422 else {
398423 let br = validateReserve(borrowReserve)
399424 let cr = validateReserve(collateralReserve)
400425 let borrowAsset = valueOrErrorMessage(getString(br, "assetId"), ("no assetId field in borrowReserve " + borrowReserve))
401426 let collateralAsset = valueOrErrorMessage(getString(cr, "assetId"), ("no assetId field in collateralReserve " + collateralReserve))
402427 let isCollateral = valueOrElse(getBoolean(cr, (borrower + "_useAsCollateral")), false)
403428 if ((isCollateral == isCollateral))
404429 then if (if (!(fromProtected))
405430 then !(isCollateral)
406431 else false)
407432 then throw("can't liquidate deposit not used as collateral")
408433 else {
409- let $t01074310833 = userBalance(br, borrower)
410- if (($t01074310833 == $t01074310833))
434+ let $t01114711237 = userBalance(br, borrower)
435+ if (($t01114711237 == $t01114711237))
411436 then {
412- let userDebtUsd = $t01074310833._5
413- let userDebt = $t01074310833._4
414- let userAssetUsd = $t01074310833._3
415- let userAsset = $t01074310833._2
416- let ignore = $t01074310833._1
437+ let userDebtUsd = $t01114711237._5
438+ let userDebt = $t01114711237._4
439+ let userAssetUsd = $t01114711237._3
440+ let userAsset = $t01114711237._2
441+ let ignore = $t01114711237._1
417442 if ((userAsset >= userDebt))
418443 then throw("can't liquidate debt of asset of positive saldo")
419444 else if ((0 >= liquidateDebtAmount))
420445 then throw("can't liquidate zero or negative amount")
421446 else if (((liquidateDebtAmount * 2) > (userDebt - userAsset)))
422447 then throw(((((("can't liquidate more than half of saldo: debt=" + toString(userDebt)) + ", deposit=") + toString(userAsset)) + ", liquidateDebtAmount = ") + toString(liquidateDebtAmount)))
423448 else {
424449 let collateralUsd = fraction(liquidateDebtAmount, userDebtUsd, userDebt)
425450 let penaltizedUsd = fraction(collateralUsd, (factorsBase + liquidationPenalty(borrowAsset)), factorsBase)
426451 let mc = if (fromProtected)
427452 then moveCollateral(borrower, collateralAsset, cr, collateralReserve)
428453 else unit
429454 if ((mc == mc))
430455 then {
431456 let transferredCollateral = asInt(invoke(cr, "transferATokensFor", [borrower, liquidator, penaltizedUsd], nil))
432457 if ((transferredCollateral == transferredCollateral))
433458 then {
434459 let pRw1 = moveStream(collateralReserve, "deposit", borrower, liquidator, transferredCollateral)
435460 if ((pRw1 == pRw1))
436461 then {
437462 let transferredDebt = asInt(invoke(br, "transferDebtFor", [borrower, liquidator, liquidateDebtAmount], nil))
438463 if ((transferredDebt == transferredDebt))
439464 then {
440465 let pRw2 = moveStream(borrowReserve, "borrow", borrower, liquidator, transferredDebt)
441466 if ((pRw2 == pRw2))
442467 then {
443468 let liquidatorHealthCheck = if (contains(liquidators, liquidator))
444469 then nil
445470 else validateAfter(liquidator, "transferring debt")
446471 if ((liquidatorHealthCheck == liquidatorHealthCheck))
447472 then $Tuple2(liquidatorHealthCheck, transferredCollateral)
448473 else throw("Strict value is not equal to itself.")
449474 }
450475 else throw("Strict value is not equal to itself.")
451476 }
452477 else throw("Strict value is not equal to itself.")
453478 }
454479 else throw("Strict value is not equal to itself.")
455480 }
456481 else throw("Strict value is not equal to itself.")
457482 }
458483 else throw("Strict value is not equal to itself.")
459484 }
460485 }
461486 else throw("Strict value is not equal to itself.")
462487 }
463488 else throw("Strict value is not equal to itself.")
464489 }
465490 }
466491 else throw("Strict value is not equal to itself.")
467492 }
468493 else throw("Strict value is not equal to itself.")
469494 }
470495
471496
472497 func forceCollapseInternal (liquidator,reserve,borrower,fromProtected) = {
473498 let reserveAddress = validateReserve(reserve)
474499 if ((reserveAddress == reserveAddress))
475500 then {
476501 let sh = syncRewardsHeight(reserve)
477502 if ((sh == sh))
478503 then if ((liquidator == borrower))
479504 then throw("can't collapse self in this function")
480505 else {
481- let $t01252012555 = userPower(borrower)
482- let bp = $t01252012555._1
483- let bpu = $t01252012555._2
506+ let $t01292412959 = userPower(borrower)
507+ let bp = $t01292412959._1
508+ let bpu = $t01292412959._2
484509 if ((bp > bpu))
485510 then throw(((((("can't force collapse healthy user: u=" + borrower) + ", bp=") + toString(bp)) + ", bpu=") + toString(bpu)))
486511 else {
487512 let asset = valueOrErrorMessage(getString(reserveAddress, "assetId"), ("no assetId field in reserve " + reserve))
488513 let mc = if (fromProtected)
489514 then moveCollateral(borrower, asset, reserveAddress, reserve)
490515 else unit
491516 if ((mc == mc))
492517 then {
493- let $t01293113039 = userBalance(reserveAddress, borrower)
494- if (($t01293113039 == $t01293113039))
518+ let $t01333513443 = userBalance(reserveAddress, borrower)
519+ if (($t01333513443 == $t01333513443))
495520 then {
496- let userDebtUsd = $t01293113039._5
497- let userDebt = $t01293113039._4
498- let userAssetUsd = $t01293113039._3
499- let borrowerDeposit = $t01293113039._2
500- let ignore = $t01293113039._1
521+ let userDebtUsd = $t01333513443._5
522+ let userDebt = $t01333513443._4
523+ let userAssetUsd = $t01333513443._3
524+ let borrowerDeposit = $t01333513443._2
525+ let ignore = $t01333513443._1
501526 let penaltizedUsd = fraction(min([userAssetUsd, userDebtUsd]), collapsePenalty, factorsBase)
502527 let transferredAssets = asInt(invoke(reserveAddress, "transferATokensFor", [borrower, liquidator, penaltizedUsd], nil))
503528 if ((transferredAssets == transferredAssets))
504529 then {
505530 let pRw1 = moveStream(reserve, "deposit", borrower, liquidator, transferredAssets)
506531 if ((pRw1 == pRw1))
507532 then {
508533 let collapsed = asInt(invoke(reserveAddress, "collapseFor", [borrower], nil))
509534 if ((collapsed == collapsed))
510535 then {
511536 let pRw2 = updateStream(reserve, "borrow", borrower, -(collapsed), -(collapsed))
512537 if ((pRw2 == pRw2))
513538 then {
514539 let pRw3 = updateStream(reserve, "deposit", borrower, -(collapsed), -(collapsed))
515540 if ((pRw3 == pRw3))
516541 then nil
517542 else throw("Strict value is not equal to itself.")
518543 }
519544 else throw("Strict value is not equal to itself.")
520545 }
521546 else throw("Strict value is not equal to itself.")
522547 }
523548 else throw("Strict value is not equal to itself.")
524549 }
525550 else throw("Strict value is not equal to itself.")
526551 }
527552 else throw("Strict value is not equal to itself.")
528553 }
529554 else throw("Strict value is not equal to itself.")
530555 }
531556 }
557+ else throw("Strict value is not equal to itself.")
558+ }
559+ else throw("Strict value is not equal to itself.")
560+ }
561+
562+
563+func spfr () = invoke(dC, "shareProfitFromReserves", nil, nil)
564+
565+
566+func wdInternal (user,reserve,amount,op) = {
567+ let sh = syncRewardsHeight(toString(reserve))
568+ if ((sh == sh))
569+ then {
570+ let withdrawnAmount = asInt(invoke(reserve, op, [user, amount], nil))
571+ if ((withdrawnAmount == withdrawnAmount))
572+ then {
573+ let pRw = updateStream(toString(reserve), "deposit", user, -(withdrawnAmount), -(withdrawnAmount))
574+ if ((pRw == pRw))
575+ then withdrawnAmount
576+ else throw("Strict value is not equal to itself.")
577+ }
532578 else throw("Strict value is not equal to itself.")
533579 }
534580 else throw("Strict value is not equal to itself.")
535581 }
536582
537583
538584 @Callable(i)
539585 func initialize (configAddress) = [writeConstString(adminStore, toString(i.caller)), writeConstString(configStore, configAddress)]
540586
541587
542588
543589 @Callable(i)
544590 func registerReserves (addresses) = if ((i.caller != admin))
545591 then throw("only admin can do")
546592 else [StringEntry(reservesStore, addresses)]
547593
548594
549595
550596 @Callable(i)
551597 func deposit (reserve,useAsCollateral) = doDeposit(i, reserve, useAsCollateral)
552598
553599
554600
555601 @Callable(i)
556602 func depositRef (reserve,useAsCollateral,ref) = doDeposit(i, reserve, useAsCollateral)
557603
558604
559605
560606 @Callable(i)
561607 func repay (reserve) = {
562608 let user = toString(i.caller)
563609 let sh = syncRewardsHeight(reserve)
564610 if ((sh == sh))
565611 then {
566612 let repaid = asInt(invoke(validateReserve(reserve), "repayFor", [user], i.payments))
567613 if ((repaid == repaid))
568614 then {
569615 let pRw = updateStream(reserve, "borrow", user, -(repaid), -(repaid))
570616 if ((pRw == pRw))
571617 then nil
572618 else throw("Strict value is not equal to itself.")
573619 }
574620 else throw("Strict value is not equal to itself.")
575621 }
576622 else throw("Strict value is not equal to itself.")
577623 }
578624
579625
580626
581627 @Callable(i)
582628 func mintAtoken (aTokenId,amount) = {
583629 let user = toString(i.caller)
584630 let targetContract = findReserveBy(aTokenIdStore, aTokenId)
585631 let sh = syncRewardsHeight(toString(targetContract))
586632 if ((sh == sh))
587633 then {
588- let mintedAssetAmount = asInt(invoke(targetContract, "mintAtokenFor", [user, amount], nil))
589- if ((mintedAssetAmount == mintedAssetAmount))
634+ let amt = asInt(invoke(targetContract, "mintAtokenFor", [user, amount], nil))
635+ if ((amt == amt))
590636 then {
591- let pRw = updateStream(toString(targetContract), "deposit", user, -(mintedAssetAmount), 0)
637+ let pRw = updateStream(toString(targetContract), "deposit", user, -(amt), 0)
592638 if ((pRw == pRw))
593639 then validateAfter(user, "minting")
594640 else throw("Strict value is not equal to itself.")
595641 }
596642 else throw("Strict value is not equal to itself.")
597643 }
598644 else throw("Strict value is not equal to itself.")
599645 }
600646
601647
602648
603649 @Callable(i)
604650 func replenishWithAtoken () = {
605651 let user = toString(i.caller)
606- let aTokenId = toBase58String(valueOrErrorMessage(i.payments[0].assetId, "bad assetId: waves not allowed"))
607- let targetContract = findReserveBy(aTokenIdStore, aTokenId)
608- let sh = syncRewardsHeight(toString(targetContract))
609- if ((sh == sh))
652+ let checks = ensureNoProtected(user)
653+ if ((checks == checks))
610654 then {
611- let replenishedAssetAmount = asInt(invoke(targetContract, "replenishWithAtokenFor", [user], i.payments))
612- if ((replenishedAssetAmount == replenishedAssetAmount))
655+ let aTokenId = toBase58String(valueOrErrorMessage(i.payments[0].assetId, "bad assetId: waves not allowed"))
656+ let targetContract = findReserveBy(aTokenIdStore, aTokenId)
657+ let sh = syncRewardsHeight(toString(targetContract))
658+ if ((sh == sh))
613659 then {
614- let pRw = updateStream(toString(targetContract), "deposit", user, replenishedAssetAmount, 0)
615- if ((pRw == pRw))
616- then nil
660+ let amt = asInt(invoke(targetContract, "replenishWithAtokenFor", [user], i.payments))
661+ if ((amt == amt))
662+ then {
663+ let pRw = updateStream(toString(targetContract), "deposit", user, amt, 0)
664+ if ((pRw == pRw))
665+ then nil
666+ else throw("Strict value is not equal to itself.")
667+ }
617668 else throw("Strict value is not equal to itself.")
618669 }
619670 else throw("Strict value is not equal to itself.")
620671 }
621672 else throw("Strict value is not equal to itself.")
622673 }
623674
624675
625676
626677 @Callable(i)
627678 func redeemAtokens () = {
628679 let user = toString(i.caller)
629680 let aTokenId = toBase58String(valueOrErrorMessage(i.payments[0].assetId, "bad assetId: waves not allowed"))
630681 let targetContract = findReserveBy(aTokenIdStore, aTokenId)
631682 let sh = syncRewardsHeight(toString(targetContract))
632683 if ((sh == sh))
633684 then {
634- let redeemedAssetAmount = asInt(invoke(targetContract, "redeemAtokensFor", [user], i.payments))
635- if ((redeemedAssetAmount == redeemedAssetAmount))
685+ let amt = asInt(invoke(targetContract, "redeemAtokensFor", [user], i.payments))
686+ if ((amt == amt))
636687 then {
637- let pRw = updateStream(toString(targetContract), "deposit", user, 0, -(redeemedAssetAmount))
688+ let pRw = updateStream(toString(targetContract), "deposit", user, 0, -(amt))
638689 if ((pRw == pRw))
639690 then nil
640691 else throw("Strict value is not equal to itself.")
641692 }
642693 else throw("Strict value is not equal to itself.")
643694 }
644695 else throw("Strict value is not equal to itself.")
645696 }
646697
647698
648699
649700 @Callable(i)
650701 func withdraw (assetId,amount) = {
651702 let user = toString(i.caller)
652- let targetContract = findReserveBy(assetIdStore, assetId)
653- let sh = syncRewardsHeight(toString(targetContract))
654- if ((sh == sh))
655- then {
656- let withdrawnAmount = asInt(invoke(targetContract, "withdrawFor", [user, amount], nil))
657- if ((withdrawnAmount == withdrawnAmount))
658- then {
659- let pRw = updateStream(toString(targetContract), "deposit", user, -(withdrawnAmount), -(withdrawnAmount))
660- if ((pRw == pRw))
661- then validateAfter(user, "withdrawing")
662- else throw("Strict value is not equal to itself.")
663- }
664- else throw("Strict value is not equal to itself.")
665- }
703+ let result = asInt(wdInternal(user, findReserveBy(assetIdStore, assetId), amount, "withdrawFor"))
704+ if ((result == result))
705+ then $Tuple2(validateAfter(user, "withdrawing"), result)
666706 else throw("Strict value is not equal to itself.")
667707 }
668708
669709
670710
671711 @Callable(i)
672712 func withdraw2 (reserve,amount) = {
673713 let user = toString(i.caller)
674714 let sh = syncRewardsHeight(reserve)
675715 if ((sh == sh))
676716 then {
677- let withdrawnAmount = asInt(invoke(validateReserve(reserve), "withdrawFor", [user, amount], nil))
678- if ((withdrawnAmount == withdrawnAmount))
717+ let amt = asInt(invoke(validateReserve(reserve), "withdrawFor", [user, amount], nil))
718+ if ((amt == amt))
679719 then {
680- let pRw = updateStream(reserve, "deposit", user, -(withdrawnAmount), -(withdrawnAmount))
720+ let pRw = updateStream(reserve, "deposit", user, -(amt), -(amt))
681721 if ((pRw == pRw))
682722 then if (contains(liquidators, user))
683723 then nil
684724 else validateAfter(user, "withdrawing2")
685725 else throw("Strict value is not equal to itself.")
686726 }
687727 else throw("Strict value is not equal to itself.")
688728 }
689729 else throw("Strict value is not equal to itself.")
690730 }
691731
692732
693733
694734 @Callable(i)
735+func protectCollateral (reserve) = {
736+ let user = toString(i.caller)
737+ let r = validateReserve(reserve)
738+ let amt = asInt(wdInternal(user, r, -1, "withdrawToMain"))
739+ if ((amt == amt))
740+ then {
741+ let assetId = assetStrToId(getStringValue(r, assetIdStore))
742+ let p = invoke(protectedReserve, "supplyFor", [user], [AttachedPayment(assetId, amt)])
743+ if ((p == p))
744+ then $Tuple2(validateAfter(user, "protecting"), amt)
745+ else throw("Strict value is not equal to itself.")
746+ }
747+ else throw("Strict value is not equal to itself.")
748+ }
749+
750+
751+
752+@Callable(i)
695753 func withdrawProtectedCollateral (assetId,amount) = {
696754 let user = toString(i.caller)
697- let withdrawnAmount = asInt(invoke(valueOrErrorMessage(protectedReserve, "no protectedReserve"), "withdrawFor", [user, assetId, amount], nil))
698- if ((withdrawnAmount == withdrawnAmount))
755+ let a = asInt(invoke(valueOrErrorMessage(protectedReserve, "no protectedReserve"), "withdrawFor", [user, assetId, amount], nil))
756+ if ((a == a))
699757 then validateAfter(user, "withdrawing protected collateral")
700758 else throw("Strict value is not equal to itself.")
701759 }
702760
703761
704762
705763 @Callable(i)
706764 func borrow (assetId,amount) = {
707765 let user = toString(i.caller)
708766 let reserve = findReserveBy(assetIdStore, assetId)
709767 let sh = syncRewardsHeight(toString(reserve))
710768 if ((sh == sh))
711769 then {
712- let action = invoke(reserve, "borrowFor", [user, amount], nil)
713- if ((action == action))
770+ let a = invoke(reserve, "borrowFor", [user, amount], nil)
771+ if ((a == a))
714772 then {
715773 let pRw = updateStream(toString(reserve), "borrow", user, amount, amount)
716774 if ((pRw == pRw))
717775 then validateAfter(user, "borrowing")
718776 else throw("Strict value is not equal to itself.")
719777 }
720778 else throw("Strict value is not equal to itself.")
721779 }
722780 else throw("Strict value is not equal to itself.")
723781 }
724782
725783
726784
727785 @Callable(i)
728786 func borrow2 (reserve,amount) = {
729787 let user = toString(i.caller)
730788 let sh = syncRewardsHeight(reserve)
731789 if ((sh == sh))
732790 then {
733- let action = invoke(validateReserve(reserve), "borrowFor", [user, amount], nil)
734- if ((action == action))
791+ let a = invoke(validateReserve(reserve), "borrowFor", [user, amount], nil)
792+ if ((a == a))
735793 then {
736794 let pRw = updateStream(reserve, "borrow", user, amount, amount)
737795 if ((pRw == pRw))
738796 then validateAfter(user, "borrowing")
739797 else throw("Strict value is not equal to itself.")
740798 }
741799 else throw("Strict value is not equal to itself.")
742800 }
743801 else throw("Strict value is not equal to itself.")
744802 }
745803
746804
747805
748806 @Callable(i)
749807 func collapse (reserve,amount) = {
750808 let user = toString(i.caller)
751809 let sh = syncRewardsHeight(reserve)
752810 if ((sh == sh))
753811 then {
754- let collapse = asInt(invoke(validateReserve(reserve), "collapseForAmount", [user, amount], nil))
755- if ((collapse == collapse))
812+ let c = asInt(invoke(validateReserve(reserve), "collapseForAmount", [user, amount], nil))
813+ if ((c == c))
756814 then {
757- let pRw = updateStream(reserve, "borrow", user, -(collapse), -(collapse))
815+ let pRw = updateStream(reserve, "borrow", user, -(c), -(c))
758816 if ((pRw == pRw))
759817 then {
760- let pRw2 = updateStream(reserve, "deposit", user, -(collapse), -(collapse))
818+ let pRw2 = updateStream(reserve, "deposit", user, -(c), -(c))
761819 if ((pRw2 == pRw2))
762820 then nil
763821 else throw("Strict value is not equal to itself.")
764822 }
765823 else throw("Strict value is not equal to itself.")
766824 }
767825 else throw("Strict value is not equal to itself.")
768826 }
769827 else throw("Strict value is not equal to itself.")
770828 }
771829
772830
773831
774832 @Callable(i)
775-func claimEbReward (amount,stake) = {
776- let user = toString(i.caller)
777- let claimed = asInt(invoke(ebR, "claimEbRewardFor", [user, amount], nil))
778- if ((claimed == claimed))
779- then stakeOrPayout(i.caller, claimed, stake)
780- else throw("Strict value is not equal to itself.")
781- }
782-
783-
784-
785-@Callable(i)
786833 func claimEbReward2 (amount,lock) = {
787834 let user = toString(i.caller)
788- let claimed = asInt(invoke(ebR, "claimEbRewardFor", [user, amount], nil))
789- if ((claimed == claimed))
790- then lockOrPayout(i.caller, claimed, lock)
791- else throw("Strict value is not equal to itself.")
792- }
793-
794-
795-
796-@Callable(i)
797-func claimReward (reserve,amount,stake) = {
798- let v = validateReserve(reserve)
799- if ((v == v))
800- then {
801- let user = toString(i.caller)
802- let claimed = asInt(invoke(VD, "claimRewardFor", [reserve, user, amount], nil))
803- if ((claimed == claimed))
804- then stakeOrPayout(i.caller, claimed, stake)
805- else throw("Strict value is not equal to itself.")
806- }
835+ let c = asInt(invoke(ebR, "claimEbRewardFor", [user, amount], nil))
836+ if ((c == c))
837+ then lockOrPayout(i.caller, c, lock)
807838 else throw("Strict value is not equal to itself.")
808839 }
809840
810841
811842
812843 @Callable(i)
813844 func claimReward2 (reserve,amount,lock) = {
814845 let v = validateReserve(reserve)
815846 if ((v == v))
816847 then {
817848 let user = toString(i.caller)
818- let claimed = asInt(invoke(VD, "claimRewardFor", [reserve, user, amount], nil))
819- if ((claimed == claimed))
820- then lockOrPayout(i.caller, claimed, lock)
849+ let c = asInt(invoke(VD, "claimRewardFor", [reserve, user, amount], nil))
850+ if ((c == c))
851+ then lockOrPayout(i.caller, c, lock)
821852 else throw("Strict value is not equal to itself.")
822853 }
823854 else throw("Strict value is not equal to itself.")
824855 }
825856
826857
827858
828859 @Callable(i)
829-func claimAllRewardsAndAllEbAvailable (stake) = {
830- let user = toString(i.caller)
831- stakeOrPayout(i.caller, claimAllRewardsForUser(user), stake)
832- }
833-
834-
835-
836-@Callable(i)
837860 func claimAllRewardsAndAllEbAvailable2 (lock,unstakeLegacy) = {
838861 let user = toString(i.caller)
839- let claimedRewards = claimAllRewardsForUser(user)
840- if ((claimedRewards == claimedRewards))
862+ let cr = claimAllRewardsForUser(user)
863+ if ((cr == cr))
841864 then {
842865 let lA = if (unstakeLegacy)
843866 then asInt(invoke(vS, "unstakeAllViresFrom", [user], nil))
844867 else 0
845868 if ((lA == lA))
846- then lockOrPayout(i.caller, (claimedRewards + lA), lock)
869+ then lockOrPayout(i.caller, (cr + lA), lock)
847870 else throw("Strict value is not equal to itself.")
848871 }
849872 else throw("Strict value is not equal to itself.")
850873 }
851874
852875
853876
854877 @Callable(i)
855878 func disableUseAsCollateral (reserve) = {
856879 let user = toString(i.caller)
857- let doSetCollateral = invoke(validateReserve(reserve), "disableUseAsCollateralFor", [user], nil)
858- if ((doSetCollateral == doSetCollateral))
880+ let d = invoke(validateReserve(reserve), "disableUseAsCollateralFor", [user], nil)
881+ if ((d == d))
859882 then validateAfter(user, "changing collateral status")
860883 else throw("Strict value is not equal to itself.")
861884 }
862885
863886
864887
865888 @Callable(i)
866-func transferDebt (borrowReserve,collateralReserve,borrower,liquidateDebtAmount) = transferDebtInternal(toString(i.caller), borrowReserve, collateralReserve, borrower, liquidateDebtAmount, false)
889+func transferDebt (br,cr,b,la) = transferDebtInternal(toString(i.caller), br, cr, b, la, false)
867890
868891
869892
870893 @Callable(i)
871-func forceCollapse (reserve,borrower) = forceCollapseInternal(toString(i.caller), reserve, borrower, false)
894+func transferDebt2 (br,cr,b,la) = transferDebtInternal(toString(i.caller), br, cr, b, la, true)
895+
896+
897+
898+@Callable(i)
899+func forceCollapse (r,b) = forceCollapseInternal(toString(i.caller), r, b, false)
900+
901+
902+
903+@Callable(i)
904+func forceCollapse2 (r,b) = forceCollapseInternal(toString(i.caller), r, b, true)
872905
873906
874907
875908 @Callable(i)
876909 func lockVires (factor,migrate) = {
877910 let user = toString(i.caller)
878- let a = invoke(dC, "shareProfitFromReserves", nil, nil)
911+ let a = spfr()
879912 if ((a == a))
880913 then {
881914 let migrateAmount = if (migrate)
882915 then asInt(invoke(vS, "unstakeAllViresFrom", [user], nil))
883916 else 0
884917 let total = (migrateAmount + viresPayment(i))
885918 let l = invoke(dC, "lockFor", [user, factor], if ((total == 0))
886919 then nil
887920 else [AttachedPayment(viresAssetId, total)])
888921 if ((l == l))
889922 then nil
890923 else throw("Strict value is not equal to itself.")
891924 }
892925 else throw("Strict value is not equal to itself.")
893926 }
894927
895928
896929
897930 @Callable(i)
898931 func withdrawAllPossibleVires () = {
899932 let user = toString(i.caller)
900- let a = invoke(dC, "shareProfitFromReserves", nil, nil)
933+ let a = spfr()
901934 if ((a == a))
902935 then {
903936 let stakerViresAmount = asInt(invoke(vS, "unstakeAllViresFrom", [user], nil))
904937 if ((stakerViresAmount == stakerViresAmount))
905938 then {
906939 let u = invoke(dC, "withdrawUnlockedFor", [user], nil)
907940 if ((u == u))
908941 then [ScriptTransfer(i.caller, stakerViresAmount, viresAssetId)]
909942 else throw("Strict value is not equal to itself.")
910943 }
911944 else throw("Strict value is not equal to itself.")
912945 }
913946 else throw("Strict value is not equal to itself.")
914947 }
915948
916949
917950
918951 @Callable(i)
919952 func claimProtocolProfitFrom (from,relock) = {
920953 let user = toString(i.caller)
921- let a = invoke(dC, "shareProfitFromReserves", nil, nil)
954+ let a = spfr()
922955 if ((a == a))
923956 then {
924957 let u = invoke(dC, "claimProfit", [from, user, relock], nil)
925958 if ((u == u))
926959 then nil
927960 else throw("Strict value is not equal to itself.")
928961 }
929962 else throw("Strict value is not equal to itself.")
930963 }
931964
932965
933966
934967 @Callable(i)
935968 func withdrawUnlockedVires () = {
936- let a = invoke(dC, "shareProfitFromReserves", nil, nil)
969+ let a = spfr()
937970 if ((a == a))
938971 then {
939972 let u = invoke(dC, "withdrawUnlockedFor", [toString(i.caller)], nil)
940973 if ((u == u))
941974 then nil
942975 else throw("Strict value is not equal to itself.")
943976 }
944977 else throw("Strict value is not equal to itself.")
945978 }
946979
947980

github/deemru/w8io/786bc32 
151.70 ms