tx · 6yAo28f4tA5JpJof7PCMZ2ipYSe24GhZLhVwkZnvPN9k

3N3PoX8z2Mvu5YbaqZmtyF3dRFjqvhRkB3M:  -0.01400000 Waves

2022.03.10 17:45 [1957987] smart account 3N3PoX8z2Mvu5YbaqZmtyF3dRFjqvhRkB3M > SELF 0.00000000 Waves

{ "type": 13, "id": "6yAo28f4tA5JpJof7PCMZ2ipYSe24GhZLhVwkZnvPN9k", "fee": 1400000, "feeAssetId": null, "timestamp": 1646923546105, "version": 2, "chainId": 84, "sender": "3N3PoX8z2Mvu5YbaqZmtyF3dRFjqvhRkB3M", "senderPublicKey": "FWZMxrtn6KRrWMPXmQPqDg5eRzwB2YvHhMjMJpwnLmBi", "proofs": [ "4bFMWsyHifo2mC3drhyR1DSZnH7L8npJLGKMAAVPyv1D29fXkHBsZ6RtDyGZBTMfRNxozrn5C6CDdJjRsMt1YBys" ], "script": "base64:AAIFAAAAAAAAFnoIAhIDCgEIEgMKAQgSBAoCCAgSAwoBCBIHCgUBAQEICBIAEgMKAQgSBAoCCAESBAoCCAESBAoCCAESAwoBCBIDCgEIEgAaDwoBQRIKdmFsQW55THlzdBoKCgFCEgVhc0ludBoLCgFDEgZ2YWxJbnQaDQoBRBIIYXNTdHJpbmcaCwoBRRIGdmFsU3RyGhYKAUYSEWtleUZhY3RvcnlBZGRyZXNzGhgKAUcSE2tleU1hbmFnZXJQdWJsaWNLZXkaHwoBSBIaa2V5UGVuZGluZ01hbmFnZXJQdWJsaWNLZXkaHQoBSRIYSWR4RmFjdG9yeUNmZ1N0YWtpbmdEYXBwGh4KAUoSGUlkeEZhY3RvcnlDZmdCb29zdGluZ0RhcHAaGQoBSxIUSWR4RmFjdG9yeUNmZ0lkb0RhcHAaGgoBTBIVSWR4RmFjdG9yeUNmZ1RlYW1EYXBwGh4KAU0SGUlkeEZhY3RvcnlDZmdFbWlzc2lvbkRhcHAaGgoBThIVSWR4RmFjdG9yeUNmZ1Jlc3REYXBwGh4KAU8SGUlkeEZhY3RvcnlDZmdTbGlwcGFnZURhcHAaHwoBUBIaSWR4RmFjdG9yeUNmZ0d3eFJld2FyZERhcHAaEgoBURINa2V5RmFjdG9yeUNmZxofCgFSEhprZXlGYWN0b3J5THAyQXNzZXRzTWFwcGluZxoPCgFTEgpscEFzc2V0U3RyGhUKAVQSEGtleUZhY3RvcnlMcExpc3QaKwoBVRIma2V5RmFjdG9yeUxwQXNzZXRUb1Bvb2xDb250cmFjdEFkZHJlc3MaGQoBVhIUa2V5RmFjdG9yeVBvb2xXZWlnaHQaFAoBVxIPY29udHJhY3RBZGRyZXNzGh0KAVgSGHJlYWRGYWN0b3J5QWRkcmVzc09yRmFpbBoPCgFZEgpyZWFkTHBMaXN0GhkKAVoSFHJlYWRGYWN0b3J5Q2ZnT3JGYWlsGgsKAWESBlNDQUxFOBoeCgJhQRIYa2V5VG90YWxNYXhCb29zdElOVEVHUkFMGicKAmFCEiFrZXlVc2VyQm9vc3RBdmFsYWlibGVUb0NsYWltVG90YWwaGQoCYUMSE2tleVVzZXJCb29zdENsYWltZWQaFwoCYUQSEWtleVRvdGFsQ2FjaGVkR3d4GhUKAmFFEg9rZXlTdGFrZWRCeVVzZXIaFAoCYUYSDnVzZXJBZGRyZXNzU3RyGhIKAmFHEgxscEFzc2V0SWRTdHIaFAoCYUgSDmtleVN0YWtlZFRvdGFsGhYKAmFJEhBrZXlDbGFpbWVkQnlVc2VyGh8KAmFKEhlrZXlDbGFpbWVkQnlVc2VyTWluUmV3YXJkGiEKAmFLEhtrZXlDbGFpbWVkQnlVc2VyQm9vc3RSZXdhcmQaEAoCYUwSCnJlYWRTdGFrZWQaEQoCYU0SC3N0YWtpbmdEYXBwGiQKAmFOEh5rZXlFbWlzc2lvblJhdGVQZXJCbG9ja0N1cnJlbnQaJwoCYU8SIWtleUVtaXNzaW9uUmF0ZVBlckJsb2NrTWF4Q3VycmVudBobCgJhUBIVa2V5RW1pc3Npb25TdGFydEJsb2NrGiEKAmFREhtrZXlFbWlzc2lvbkR1cmF0aW9uSW5CbG9ja3MaGQoCYVISE2tleUVtaXNzaW9uRW5kQmxvY2saEQoCYVMSC2ZhY3RvcnlEYXBwGhAKAmFUEgpmYWN0b3J5Q2ZnGhIKAmFVEgxlbWlzc2lvbkRhcHAaEwoCYVYSDWd3eFJld2FyZERhcHAaEgoCYVcSDGJvb3N0aW5nRGFwcBofCgJhWBIZaW50ZXJuYWxDdXJyZW50UmV3YXJkUmF0ZRoPCgJhWRIJbHBBc3NldElkGhQKAmFaEg5wb29sQWRkcmVzc1N0choNCgJhYRIHZmFjdG9yeRoeCgJhYhIYZ2V0Qm9vc3RpbmdBZGRyZXNzT3JGYWlsGgoKAmFjEgRmQ2ZnGh4KAmFkEhhnZXRFbWlzc2lvbkFkZHJlc3NPckZhaWwaHQoCYWUSF2dldFN0YWtpbmdBZGRyZXNzT3JGYWlsGh8KAmFmEhlnZXRHd3hSZXdhcmRBZGRyZXNzT3JGYWlsGhEKAmFnEgtrZXlCb29zdENmZxolCgJhaBIfa2V5Qm9vc3RpbmdMb2NrUGFyYW1Ub3RhbEFtb3VudBouCgJhaRIoa2V5Qm9vc3RpbmdTdGF0c0xvY2tzRHVyYXRpb25TdW1JbkJsb2NrcxogCgJhahIaa2V5Qm9vc3RpbmdTdGF0c0xvY2tzQ291bnQaIAoCYWsSGmtleUJvb3N0aW5nU3RhdHNVc2Vyc0NvdW50GhgKAmFsEhJrZXlVc2VyMk51bU1hcHBpbmcaEQoCYW0SC3VzZXJBZGRyZXNzGhgKAmFuEhJrZXlOdW0yVXNlck1hcHBpbmcaCQoCYW8SA251bRocCgJhcBIWa2V5TG9ja1BhcmFtVXNlckFtb3VudBoNCgJhcRIHdXNlck51bRocCgJhchIWa2V5TG9ja1BhcmFtU3RhcnRCbG9jaxoaCgJhcxIUa2V5TG9ja1BhcmFtRHVyYXRpb24aEwoCYXQSDWtleUxvY2tQYXJhbUsaEwoCYXUSDWtleUxvY2tQYXJhbUIaGwoCYXYSFWtleUxvY2tQYXJhbUJ5UGVyaW9kSxoMCgJhdxIGcGVyaW9kGhsKAmF4EhVrZXlMb2NrUGFyYW1CeVBlcmlvZEIaJgoCYXkSIGtleVVzZXJCb29zdEVtaXNzaW9uTGFzdElOVEVHUkFMGh0KAmF6EhdrZXlVc2VyTWF4Qm9vc3RJTlRFR1JBTBoKCgFiEgVNVUxUOBoTCgJiQRINbWluUmV3YXJkUGFydBoVCgJiQhIPYm9vc3RSZXdhcmRQYXJ0GgsKAmJDEgVkZWJ1ZxoTCgJiRBINYm9vc3RpbmdQb3dlchoMCgJiRRIGbHBMaXN0GgwKAmJGEgZwcmVmaXgaIQoCYkcSG2NsYWltZWRSZXdhcmRCeUxwQWdncmVnYXRvchoPCgJiSBIJcmVzdWx0U3RyGgwKAmJJEgZuZXh0THAaHwoCYkoSGWNsYWltZWRCeVVzZXJNaW5SZXdhcmRLRVkaIQoCYksSG2NsYWltZWRCeVVzZXJCb29zdFJld2FyZEtFWRoWCgJiTBIQbWluUmV3YXJkQ2xhaW1lZBoYCgJiTRISYm9vc3RSZXdhcmRDbGFpbWVkGhEKAmJOEgtnRmVlQ2xhaW1lZBoMCgJiTxIGcmVzdWx0GggKAmJQEgIkbBoICgJiURICJHMaCwoCYlISBSRhY2MwGgsKAmJTEgUkZjBfMRoICgJiVBICJGEaCAoCYlUSAiRpGgsKAmJWEgUkZjBfMhoTCgJiVxINZGVsdGFXeEFtb3VudBodCgJiWBIXZGVsdGFMb2NrUGVyaW9kSW5CbG9ja3MaEwoCYlkSDWRlbHRhTHBBbW91bnQaEgoCYloSDGxwQXNzZXRJZE9wdBoUCgJiYRIOcG9vbFdlaWdodE11bHQaEAoCYmISCnBvb2xXZWlnaHQaGAoCYmMSEnd4RW1pc3Npb25QZXJCbG9jaxobCgJiZBIVd3hFbWlzc2lvblBlckJsb2NrTWF4GhMKAmJlEg1ib29zdE1heENvZWZmGhwKAmJmEhZwb29sV3hFbWlzc2lvblBlckJsb2NrGh8KAmJnEhlwb29sV3hFbWlzc2lvblBlckJsb2NrTWF4Gg8KAmJoEgltYXhGYWN0b3IaEwoCYmkSDXRvdGFsTHBTdGFrZWQaIAoCYmoSGmNhbGNHd3hBbW91bnRTdGFydFJFQURPTkxZGhAKAmJrEgpsb2NrQW1vdW50GhIKAmJsEgxsb2NrRHVyYXRpb24aFQoCYm0SD21heExvY2tEdXJhdGlvbhoNCgJibhIHY29lZmZYOBoUCgJibxIOZ1d4QW1vdW50U3RhcnQaHAoCYnASFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQaBwoCYnESAXMaIwoCYnISHXBlbmRpbmdNYW5hZ2VyUHVibGljS2V5T3JVbml0GhEKAmJzEgttdXN0TWFuYWdlchoHCgJidBIBaRoICgJidRICcGQaCAoCYnYSAnBrGhQKAmJ3Eg5mYWN0b3J5QWRkcmVzcxoQCgJieBIKcmV3YXJkRGF0YRoUCgJieRIObHBTdGFrZWRCeVVzZXIaEwoCYnoSDXVzZXJDbGFpbUluZm8aDAoBYxIHU0NBTEUxOBoSCgJjQRIMc3Rha2VkQnlVc2VyGhEKAmNCEgtzdGFrZWRUb3RhbBoVCgJjQxIPc3Rha2VkQnlVc2VyTmV3GhQKAmNEEg5zdGFrZWRUb3RhbE5ldxoeCgJjRRIYcG9vbFd4RW1pc3Npb25QZXJCbG9ja1gzGg8KAmNGEgl3eFBlckxwWDMaFgoCY0cSEHVzZXJXeFBlckJsb2NrWDMaHQoCY0gSF2Jvb3N0RW1pc3Npb25QZXJCbG9ja1gzGhwKAmNJEhZ0bXBVc2VyQm9vc3RQZXJCbG9ja1gzGhkKAmNKEhN1c2VyQm9vc3RQZXJCbG9ja1gzGhAKAmNLEgpib29zdENvZWZmGg0KAmNMEgdPTkVNVUxUGgkKAmNNEgNPTkUaGAoCY04SEmVtaXNzaW9uU3RhcnRCbG9jaxoSCgJjTxIMcGFzc2VkQmxvY2tzGhQKAmNQEg50ZWFtRW1EdXJhdGlvbhoPCgJjURIJdGVhbUVtTWF4GgwKAmNSEgZ0ZWFtRW0aFQoCY1MSD3RvdGFsV3hSZWxlYXNlZBoTCgJjVBINdG90YWxXeExvY2tlZBoeCgJjVRIYbG9ja3NEdXJhdGlvblN1bUluQmxvY2tzGhAKAmNWEgpsb2Nrc0NvdW50Gg0KAmNXEgdscEFzc2V0GhEKAmNYEgtwb29sQWRkcmVzcxoJCgJjWRIDY2ZnGhAKAmNaEgphbXRBc3NldElkGhQKAmNhEg51c2VyQWRkcmVzc09wdBoOCgJjYhIIbWF0aERhcHAaDgoCY2MSCEVNUFRZU1RSGh0KAmNkEhdtYXhMb2NrRHVyYXRpb25JbkJsb2NrcxoQCgJjZRIKdXNlck51bVN0choQCgJjZhIKdXNlckFtb3VudBoPCgJjZxIJbG9ja1N0YXJ0Gg0KAmNoEgdsb2NrRW5kGhcKAmNpEhFyZW1haW5pbmdEdXJhdGlvbhoTCgJjahINdXNlckFtb3VudE5ldxoVCgJjaxIPbG9ja0R1cmF0aW9uTmV3GhcKAmNsEhF1c2VyQ3VycmdXeEFtb3VudBoXCgJjbRIRZ1d4QW1vdW50U3RhcnROZXcaGQoCY24SE2dXeFBhcmFtc1Jlc3VsdExpc3QaEwoCY28SDWdXeEFtb3VudERpZmYaBwoCY3ASAWsaBwoCY3ESAWIaHgoCY3ISGHRvdGFsTWF4Qm9vc3RJbnRlZ3JhbEtFWRoXCgJjcxIRdG90YWxDYWNoZWRHd3hLRVkaGAoCY3QSEnVzZXJNYXhCb29zdEludE5ldxoWCgJjdRIQdG90YWxNYXhCb29zdEludBoUCgJjdhIOdG90YWxDYWNoZWRHd3gaCwoCY3cSBU1VTFQzGhoKAmN4EhR3eEVtaXNzaW9uUGVyQmxvY2tYMxoVCgJjeRIPc3Rha2VkQnlVc2VyS0VZGhQKAmN6Eg5zdGFrZWRUb3RhbEtFWRoLCgFkEgZNVUxUMTgaDwoCZEESCWNhbGNMcEFtdBoSCgJkQhIMY3VyUHJpY2VDYWxjGg8KAmRDEglhbUJhbGFuY2UaDwoCZEQSCXByQmFsYW5jZRoQCgJkRRIKbHBFbWlzc2lvbhoSCgJkRhIMYW1CYWxhbmNlUmF3GhIKAmRHEgxwckJhbGFuY2VSYXcaFQoCZEgSD2FtQmFsYW5jZVJhd1gxOBoVCgJkSRIPcHJCYWxhbmNlUmF3WDE4GhMKAmRKEg0kdDAyNTc0NzI2MTAwGhYKAmRLEhBwYXltZW50THBBc3NldElkGhIKAmRMEgxwYXltZW50THBBbXQaEwoCZE0SDSR0MDI2Nzk1MjcyMTIaDgoCZE4SCG91dEFtQW10Gg4KAmRPEghvdXRQckFtdBoVCgJkUBIPZ3d4VXNlckluZm9MSVNUGg8KAmRREglnd3hBbW91bnQaHQoCZFISF3BlbmRpbmdNYW5hZ2VyUHVibGljS2V5GhEKAmRTEgtjaGVja0NhbGxlchobCgJkVBIVY2hlY2tNYW5hZ2VyUHVibGljS2V5GggKAmRVEgJwbRoLCgJkVhIFaGFzUE0aDQoCZFcSB2NoZWNrUE0aCAoCZFgSAnR4GgwKAmRZEgZ2ZXJpZnkaFQoCZFoSD3RhcmdldFB1YmxpY0tleRoSCgJkYRIMcHJpY2VBc3NldElkGhEKAmRiEgtpQW10QXNzZXRJZBoTCgJkYxINaVByaWNlQXNzZXRJZBoRCgJkZBILYW10QXNzZXREY20aEwoCZGUSDXByaWNlQXNzZXREY20aEwoCZGYSDXBvb2xMUEJhbGFuY2UaGAoCZGcSEmFjY0FtdEFzc2V0QmFsYW5jZRoaCgJkaBIUYWNjUHJpY2VBc3NldEJhbGFuY2UaEAoCZGkSCnByaWNlc0xpc3QaDgoCZGoSCGN1clByaWNlGhUKAmRrEg9scEFtdEFzc2V0U2hhcmUaFwoCZGwSEWxwUHJpY2VBc3NldFNoYXJlGhIKAmRtEgxpbkFtQXNzZXRBbXQaEgoCZG4SDGFtQXNzZXRJZFN0choPCgJkbxIJYW1Bc3NldElkGhIKAmRwEgxwckFzc2V0SWRTdHIaDwoCZHESCXByQXNzZXRJZBoQCgJkchIKcG9vbFN0YXR1cxoUCgJkcxIOYW10QXNzZXRBbXRYMTgaFgoCZHQSEHByaWNlQXNzZXRBbXRYMTgaEQoCZHUSC2N1clByaWNlWDE4GhUKAmR2Eg9pbkFtQXNzZXRBbXRYMTgaFQoCZHcSD2luUHJBc3NldEFtdFgxOBoSCgJkeBIMaW5QckFzc2V0QW10GgkKAmR5EgNyZXMaEwoCZHoSDSR0MDIyODIxMjMxNzQaCAoBZRIDU0VQGhMKAWYSDlBPT0xXRUlHSFRNVUxUGg8KAWcSCnplcm9CaWdJbnQaEwoB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", "height": 1957987, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 3agbDC377kX4quSvwhKBdkGyNhmoELSL3e5RKm5SXGcd Next: Dw5HPqqhBvepzspaCV3PuvhK4BHpbVxt84H7oiRYqVi8 Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+let SCALE8 = 8
5+
6+let MULT8 = 100000000
7+
8+let SCALE18 = 18
9+
10+let MULT18 = toBigInt(1000000000000000000)
11+
12+let SEP = "__"
13+
14+let POOLWEIGHTMULT = MULT8
15+
16+let zeroBigInt = toBigInt(0)
17+
18+let idxPoolAddress = 1
19+
20+let idxPoolStatus = 2
21+
22+let idxPoolLPAssetId = 3
23+
24+let idxAmtAssetId = 4
25+
26+let idxPriceAssetId = 5
27+
28+let idxAmtAssetDcm = 6
29+
30+let idxPriceAssetDcm = 7
31+
32+let idxIAmtAssetId = 8
33+
34+let idxIPriceAssetId = 9
35+
36+let idxLPAssetDcm = 10
37+
438 func getStringOrFail (key) = valueOrErrorMessage(getString(key), (("mandatory this." + key) + " is not defined"))
539
640
7-let SEP = "__"
8-
9-let BUFSCALE = toBigInt(1000000000000000000)
10-
11-func convertPriceAssetIntoIdoAsset (priceAssetAmount,priceAssetMULT,price,priceMULT,idoAssetMULT) = {
12- let bPriceAssetMULT = toBigInt(priceAssetMULT)
13- let bIdoAssetMULT = toBigInt(idoAssetMULT)
14- let bPriceAssetBUF = fraction(toBigInt(priceAssetAmount), BUFSCALE, bPriceAssetMULT)
15- let bAmountAssetBUF = fraction(bPriceAssetBUF, toBigInt(priceMULT), toBigInt(price))
16- toInt(fraction(bAmountAssetBUF, toBigInt(idoAssetMULT), BUFSCALE))
17- }
41+func getStringByAddressOrFail (address,key) = valueOrErrorMessage(getString(address, key), (((("mandatory " + toString(address)) + ".") + key) + " is not defined"))
1842
1943
20-let IdxCfgIdoStart = 1
21-
22-let IdxCfgIdoDuration = 2
23-
24-let IdxCfgClaimStart = 3
25-
26-let IdxCfgClaimDuration = 4
27-
28-let IdxCfgPrice = 5
29-
30-let IdxCfgPriceMult = 6
31-
32-let IdxCfgIdoAssetId = 7
33-
34-let IdxCfgIdoAssetMult = 8
35-
36-let IdxCfgPriceAssetId = 9
37-
38-let IdxCfgPriceAssetMult = 10
39-
40-let IdxCfgMinInvestAmount = 11
41-
42-func fromatConfigS (idoStart,idoDuration,claimStart,claimDuration,price,priceMult,idoAssetId58,idoAssetMult,priceAssetId58,priceAssetMult,minInvestAmount,totalIdoAssetToSell) = makeString(["%d%d%d%d%d%d%s%d%s%d%d%d", idoStart, idoDuration, claimStart, claimDuration, price, priceMult, idoAssetId58, idoAssetMult, priceAssetId58, priceAssetMult, minInvestAmount, totalIdoAssetToSell], SEP)
44+func getIntOrZero (address,key) = valueOrElse(getInteger(address, key), 0)
4345
4446
45-func fromatConfig (idoStart,idoDuration,claimStart,claimDuration,price,priceMult,idoAssetId58,idoAssetMult,priceAssetId58,priceAssetMult,minInvestAmount,totalIdoAssetToSell) = fromatConfigS(toString(idoStart), toString(idoDuration), toString(claimStart), toString(claimDuration), toString(price), toString(priceMult), idoAssetId58, toString(idoAssetMult), priceAssetId58, toString(priceAssetMult), toString(minInvestAmount), toString(totalIdoAssetToSell))
47+func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), (("mandatory this." + key) + " is not defined"))
4648
4749
48-let IdxInvTotalAmount = 1
49-
50-let IdxInvRemainingAmount = 2
51-
52-let IdxInvClaimedPriceAssetAmount = 3
53-
54-let IdxInvClaimedIdoAssetAmount = 4
55-
56-let IdxInvLastClaimedHeight = 5
57-
58-func formatInvestorS (totalAmount,remainingAmount,claimedPriceAssetAmount,claimedIdoAssetAmount,lastClaimedHeight) = makeString(["%d%d%d%d%d", totalAmount, remainingAmount, claimedPriceAssetAmount, claimedIdoAssetAmount, lastClaimedHeight], SEP)
50+func asAnyList (val) = match val {
51+ case valAnyLyst: List[Any] =>
52+ valAnyLyst
53+ case _ =>
54+ throw("fail to cast into List[Any]")
55+}
5956
6057
61-func formatInvestor (totalAmount,remainingAmount,claimedPriceAssetAmount,claimedIdoAssetAmount,lastClaimedHeight) = formatInvestorS(toString(totalAmount), toString(remainingAmount), toString(claimedPriceAssetAmount), toString(claimedIdoAssetAmount), toString(lastClaimedHeight))
58+func asInt (val) = match val {
59+ case valInt: Int =>
60+ valInt
61+ case _ =>
62+ throw("fail to cast into Int")
63+}
6264
6365
64-func formatHistoryRecord (priceAssetAmount,idoAssetAmount) = makeString(["%d%d%d%d", toString(height), toString(lastBlock.timestamp), toString(priceAssetAmount), toString(idoAssetAmount)], SEP)
66+func asString (val) = match val {
67+ case valStr: String =>
68+ valStr
69+ case _ =>
70+ throw("fail to cast into String")
71+}
6572
6673
67-func keyConfig () = "%s__config"
68-
69-
70-func keyInvestor (userAddress) = ("%s__" + userAddress)
71-
72-
73-func keyTotals () = "%s__totals"
74-
75-
76-func keyOperationHistoryRecord (type,userAddress,txId58) = makeString(["%s%s%s%s__history", type, userAddress, txId58], SEP)
74+func keyFactoryAddress () = "%s%s__config__factoryAddress"
7775
7876
7977 func keyManagerPublicKey () = "%s__managerPublicKey"
8280 func keyPendingManagerPublicKey () = "%s__pendingManagerPublicKey"
8381
8482
85-func readConfigArray () = split(getStringOrFail(keyConfig()), SEP)
83+let IdxFactoryCfgStakingDapp = 1
84+
85+let IdxFactoryCfgBoostingDapp = 2
86+
87+let IdxFactoryCfgIdoDapp = 3
88+
89+let IdxFactoryCfgTeamDapp = 4
90+
91+let IdxFactoryCfgEmissionDapp = 5
92+
93+let IdxFactoryCfgRestDapp = 6
94+
95+let IdxFactoryCfgSlippageDapp = 7
96+
97+let IdxFactoryCfgGwxRewardDapp = 8
98+
99+func keyFactoryCfg () = "%s__factoryConfig"
86100
87101
88-func readTotalsArrayOrDefaultByCustomKey (customKey) = split(valueOrElse(getString(customKey), formatInvestorS("0", "0", "0", "0", "0")), SEP)
102+func keyFactoryLp2AssetsMapping (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
89103
90104
91-func readTotalsArrayOrDefault () = readTotalsArrayOrDefaultByCustomKey(keyTotals())
105+func keyFactoryLpList () = "%s__lpTokensList"
92106
93107
94-func readInvestorArrayOrDefault (userAddress) = readTotalsArrayOrDefaultByCustomKey(keyInvestor(userAddress))
108+func keyFactoryLpAssetToPoolContractAddress (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
95109
96110
97-func readInvestorArrayOrFail (userAddress) = split(getStringOrFail(keyInvestor(userAddress)), SEP)
111+func keyFactoryPoolWeight (contractAddress) = makeString(["%s%s", "poolWeight", contractAddress], SEP)
98112
99113
100-let IdxDiffTotalIncrement = 0
114+func readFactoryAddressOrFail () = addressFromStringValue(getStringOrFail(keyFactoryAddress()))
101115
102-let IdxDiffRemainingPriceAmountIncrement = 1
103116
104-let IdxDiffClaimedPriceAmountIncrement = 2
117+func readLpList () = split(valueOrElse(getString(readFactoryAddressOrFail(), keyFactoryLpList()), ""), SEP)
105118
106-let IdxDiffClaimedIdoAssetAmountIncrement = 3
107119
108-func TotalsEntry (key,origArray,incrementDiff,newLastClaimedHeight) = {
109- let totalAmount = parseIntValue(origArray[IdxInvTotalAmount])
110- let remainingAmount = parseIntValue(origArray[IdxInvRemainingAmount])
111- let claimedPriceAssetAmount = parseIntValue(origArray[IdxInvClaimedPriceAssetAmount])
112- let claimedIdoAssetAmount = parseIntValue(origArray[IdxInvClaimedIdoAssetAmount])
113- let lastClaimedHeight = parseIntValue(origArray[IdxInvLastClaimedHeight])
114- let newTotalAmount = (totalAmount + incrementDiff[IdxDiffTotalIncrement])
115- let newRemainingAmount = (remainingAmount + incrementDiff[IdxDiffRemainingPriceAmountIncrement])
116- let newClaimedPriceAssetAmount = (claimedPriceAssetAmount + incrementDiff[IdxDiffClaimedPriceAmountIncrement])
117- let newClaimedIdoAssetAmount = (claimedIdoAssetAmount + incrementDiff[IdxDiffClaimedIdoAssetAmountIncrement])
118- if ((0 > newRemainingAmount))
119- then throw("invalid math")
120- else StringEntry(key, formatInvestor(newTotalAmount, newRemainingAmount, newClaimedPriceAssetAmount, newClaimedIdoAssetAmount, newLastClaimedHeight))
120+func readFactoryCfgOrFail (factory) = split(getStringByAddressOrFail(factory, keyFactoryCfg()), SEP)
121+
122+
123+func getBoostingAddressOrFail (fCfg) = addressFromStringValue(fCfg[IdxFactoryCfgBoostingDapp])
124+
125+
126+func getEmissionAddressOrFail (fCfg) = addressFromStringValue(fCfg[IdxFactoryCfgEmissionDapp])
127+
128+
129+func getStakingAddressOrFail (fCfg) = addressFromStringValue(fCfg[IdxFactoryCfgStakingDapp])
130+
131+
132+func getGwxRewardAddressOrFail (fCfg) = addressFromStringValue(fCfg[IdxFactoryCfgGwxRewardDapp])
133+
134+
135+func keyBoostCfg () = "%s__config"
136+
137+
138+func keyBoostingLockParamTotalAmount () = "%s%s__stats__activeTotalLocked"
139+
140+
141+func keyBoostingStatsLocksDurationSumInBlocks () = "%s%s__stats__locksDurationSumInBlocks"
142+
143+
144+func keyBoostingStatsLocksCount () = "%s%s__stats__locksCount"
145+
146+
147+func keyBoostingStatsUsersCount () = "%s%s__stats__activeUsersCount"
148+
149+
150+func keyUser2NumMapping (userAddress) = makeString(["%s%s%s__mapping__user2num", userAddress], SEP)
151+
152+
153+func keyNum2UserMapping (num) = makeString(["%s%s%s__mapping__num2user", num], SEP)
154+
155+
156+func keyLockParamUserAmount (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "amount"], SEP)
157+
158+
159+func keyLockParamStartBlock (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "start"], SEP)
160+
161+
162+func keyLockParamDuration (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "duration"], SEP)
163+
164+
165+func keyLockParamK (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "k"], SEP)
166+
167+
168+func keyLockParamB (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "b"], SEP)
169+
170+
171+func keyLockParamByPeriodK (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "k", period], SEP)
172+
173+
174+func keyLockParamByPeriodB (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "b", period], SEP)
175+
176+
177+func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastInt", userNum], SEP)
178+
179+
180+func keyUserMaxBoostINTEGRAL (userNum) = makeString(["%s%d__maxBoostInt", userNum], SEP)
181+
182+
183+func keyTotalMaxBoostINTEGRAL () = "%s%s__maxBoostInt__total"
184+
185+
186+func keyUserBoostAvalaibleToClaimTotal (userNum) = makeString(["%s%d__userBoostAvaliableToClaimTotal", userNum], SEP)
187+
188+
189+func keyUserBoostClaimed (userNum) = makeString(["%s%d__userBoostClaimed", userNum], SEP)
190+
191+
192+func keyTotalCachedGwx () = "%s%s__gwxCached__total"
193+
194+
195+func keyStakedByUser (userAddressStr,lpAssetIdStr) = makeString(["%s%s%s__staked", userAddressStr, lpAssetIdStr], SEP)
196+
197+
198+func keyStakedTotal (lpAssetIdStr) = ("%s%s%s__staked__total__" + lpAssetIdStr)
199+
200+
201+func keyClaimedByUser (lpAssetIdStr,userAddressStr) = makeString(["%s%s%s__claimed", userAddressStr, lpAssetIdStr], SEP)
202+
203+
204+func keyClaimedByUserMinReward (lpAssetIdStr,userAddressStr) = makeString(["%s%s%s__claimedMinReward", userAddressStr, lpAssetIdStr], SEP)
205+
206+
207+func keyClaimedByUserBoostReward (lpAssetIdStr,userAddressStr) = makeString(["%s%s%s__claimedBoostReward", userAddressStr, lpAssetIdStr], SEP)
208+
209+
210+func readStaked (stakingDapp,key) = valueOrElse(getInteger(stakingDapp, key), 0)
211+
212+
213+func keyEmissionRatePerBlockCurrent () = "%s%s__ratePerBlock__current"
214+
215+
216+func keyEmissionRatePerBlockMaxCurrent () = "%s%s__ratePerBlockMax__current"
217+
218+
219+func keyEmissionStartBlock () = "%s%s__emission__startBlock"
220+
221+
222+func keyEmissionDurationInBlocks () = "%s%s__emission__duration"
223+
224+
225+func keyEmissionEndBlock () = "%s%s__emission__endBlock"
226+
227+
228+let factoryDapp = readFactoryAddressOrFail()
229+
230+let factoryCfg = readFactoryCfgOrFail(factoryDapp)
231+
232+let emissionDapp = getEmissionAddressOrFail(factoryCfg)
233+
234+let stakingDapp = getStakingAddressOrFail(factoryCfg)
235+
236+let gwxRewardDapp = getGwxRewardAddressOrFail(factoryCfg)
237+
238+let boostingDapp = getBoostingAddressOrFail(factoryCfg)
239+
240+func internalCurrentRewardRate (lpAssetId) = {
241+ let poolAddressStr = getStringByAddressOrFail(factoryDapp, keyFactoryLpAssetToPoolContractAddress(lpAssetId))
242+ let poolWeightMult = MULT8
243+ let poolWeight = getIntegerValue(factoryDapp, keyFactoryPoolWeight(poolAddressStr))
244+ let wxEmissionPerBlock = getIntOrFail(emissionDapp, keyEmissionRatePerBlockCurrent())
245+ let wxEmissionPerBlockMax = getIntOrFail(emissionDapp, keyEmissionRatePerBlockMaxCurrent())
246+ let boostMaxCoeff = 3
247+ let poolWxEmissionPerBlock = (fraction(wxEmissionPerBlock, poolWeight, poolWeightMult) / boostMaxCoeff)
248+ let poolWxEmissionPerBlockMax = fraction(wxEmissionPerBlockMax, poolWeight, poolWeightMult)
249+ let maxFactor = (boostMaxCoeff * MULT8)
250+ let totalLpStaked = getIntOrZero(stakingDapp, keyStakedTotal(lpAssetId))
251+[poolWxEmissionPerBlock, maxFactor, totalLpStaked]
121252 }
122253
123254
124-func InvestOperationHistoryEntry (userAddress,priceAssetAmount,idoAssetAmount,txId) = StringEntry(keyOperationHistoryRecord("invest", userAddress, toBase58String(txId)), formatHistoryRecord(priceAssetAmount, idoAssetAmount))
125-
126-
127-func ClaimOperationHistoryEntry (userAddress,priceAssetAmount,idoAssetAmount,txId) = StringEntry(keyOperationHistoryRecord("claim", userAddress, toBase58String(txId)), formatHistoryRecord(priceAssetAmount, idoAssetAmount))
128-
129-
130-func internalClaim (claimedAssetId58,userAddress,txId) = {
131- let cfgArray = readConfigArray()
132- let claimStart = parseIntValue(cfgArray[IdxCfgClaimStart])
133- let claimDuration = parseIntValue(cfgArray[IdxCfgClaimDuration])
134- let claimEnd = (claimStart + claimDuration)
135- let price = parseIntValue(cfgArray[IdxCfgPrice])
136- let priceMult = parseIntValue(cfgArray[IdxCfgPriceMult])
137- let idoAssetId58 = cfgArray[IdxCfgIdoAssetId]
138- let idoAssetId = fromBase58String(idoAssetId58)
139- let idoAssetMult = parseIntValue(cfgArray[IdxCfgIdoAssetMult])
140- let priceAssetId58 = cfgArray[IdxCfgPriceAssetId]
141- let priceAssetId = fromBase58String(priceAssetId58)
142- let priceAssetMult = parseIntValue(cfgArray[IdxCfgPriceAssetMult])
143- let userAddress58 = toString(userAddress)
144- let origInvestArray = readInvestorArrayOrFail(userAddress58)
145- let investTotalAmount = parseIntValue(origInvestArray[IdxInvTotalAmount])
146- let investLastClaimedHeightTMP = parseIntValue(origInvestArray[IdxInvLastClaimedHeight])
147- let investLastClaimedHeight = if ((claimStart >= investLastClaimedHeightTMP))
148- then claimStart
149- else investLastClaimedHeightTMP
150- let newClaimPeriodHeight = if ((height > claimEnd))
151- then claimEnd
152- else if ((claimStart > height))
153- then claimStart
154- else height
155- let claimingBlocks = (newClaimPeriodHeight - investLastClaimedHeight)
156- let claimingPriceAssetAmount = fraction(investTotalAmount, claimingBlocks, claimDuration)
157- let claimingIdoAssetAmount = convertPriceAssetIntoIdoAsset(claimingPriceAssetAmount, priceAssetMult, price, priceMult, idoAssetMult)
158- if ((claimedAssetId58 == priceAssetId58))
159- then $Tuple6([0, -(claimingPriceAssetAmount), claimingPriceAssetAmount, 0], claimingPriceAssetAmount, priceAssetId, origInvestArray, newClaimPeriodHeight, [claimingPriceAssetAmount, claimingIdoAssetAmount])
160- else if ((claimedAssetId58 == idoAssetId58))
161- then $Tuple6([0, -(claimingPriceAssetAmount), 0, claimingIdoAssetAmount], claimingIdoAssetAmount, idoAssetId, origInvestArray, newClaimPeriodHeight, [claimingPriceAssetAmount, claimingIdoAssetAmount])
162- else throw(("unsupported assetId: " + claimedAssetId58))
255+func calcGwxAmountStartREADONLY (lockAmount,lockDuration,maxLockDuration) = {
256+ let coeffX8 = fraction(lockDuration, MULT8, maxLockDuration)
257+ let gWxAmountStart = fraction(lockAmount, coeffX8, MULT8)
258+[gWxAmountStart]
163259 }
164260
165261
201297
202298
203299 @Callable(i)
204-func constructor (idoStart,idoDuration,claimStart,claimDuration,price,priceAssetId58,minInvestAmount) = {
205- let priceMult = ((100 * 1000) * 1000)
206- let idoEnd = (idoStart + idoDuration)
207- if (isDefined(getString(keyConfig())))
208- then throw("already initialized")
209- else if (("3PMEHLx1j6zerarZTYfsGqDeeZqQoMpxq5S" != toString(i.caller)))
210- then throw("not authorized")
211- else if ((size(i.payments) != 1))
212- then throw("exactly 1 payment must be attached")
213- else if ((idoEnd >= claimStart))
214- then throw("claimStart must be greater than idoEnd")
215- else {
216- let pmt = value(i.payments[0])
217- let idoAssetId = value(pmt.assetId)
218- let idoAssetInfo = valueOrErrorMessage(assetInfo(idoAssetId), "fail to load ido asset info")
219- let idoAssetId58 = toBase58String(idoAssetId)
220- let idoAssetMult = pow(10, 0, idoAssetInfo.decimals, 0, 0, DOWN)
221- let priceAssetId = fromBase58String(priceAssetId58)
222- let priceAssetInfo = valueOrErrorMessage(assetInfo(priceAssetId), "fail to load price asset info")
223- let priceAssetMult = pow(10, 0, priceAssetInfo.decimals, 0, 0, DOWN)
224- let origTotalsArray = readTotalsArrayOrDefault()
225- let totalsDiff = [0, 0, 0, 0]
226-[StringEntry(keyConfig(), fromatConfig(idoStart, idoDuration, claimStart, claimDuration, price, priceMult, idoAssetId58, idoAssetMult, priceAssetId58, priceAssetMult, minInvestAmount, pmt.amount)), TotalsEntry(keyTotals(), origTotalsArray, totalsDiff, claimStart)]
227- }
300+func constructor (factoryAddress) = if ((i.caller != this))
301+ then throw("not authorized")
302+ else [StringEntry(keyFactoryAddress(), factoryAddress)]
303+
304+
305+
306+@Callable(i)
307+func currentRewardRateREADONLY (lpAssetId) = {
308+ let rewardData = internalCurrentRewardRate(lpAssetId)
309+ let wxEmissionPerBlock = rewardData[0]
310+ let maxFactor = rewardData[1]
311+ let totalLpStaked = rewardData[2]
312+ $Tuple2(nil, makeString(["%d%d%d", toString(wxEmissionPerBlock), toString(maxFactor), toString(totalLpStaked)], SEP))
228313 }
229314
230315
231316
232317 @Callable(i)
233-func invest () = {
234- let cfgArray = readConfigArray()
235- let idoStart = parseIntValue(cfgArray[IdxCfgIdoStart])
236- let idoDuration = parseIntValue(cfgArray[IdxCfgIdoDuration])
237- let idoEnd = (idoStart + idoDuration)
238- let claimStart = parseIntValue(cfgArray[IdxCfgClaimStart])
239- let claimDuration = parseIntValue(cfgArray[IdxCfgClaimDuration])
240- let price = parseIntValue(cfgArray[IdxCfgPrice])
241- let priceMult = parseIntValue(cfgArray[IdxCfgPriceMult])
242- let idoAssetId58 = cfgArray[IdxCfgIdoAssetId]
243- let idoAssetId = fromBase58String(idoAssetId58)
244- let idoAssetMult = parseIntValue(cfgArray[IdxCfgIdoAssetMult])
245- let priceAssetId58 = cfgArray[IdxCfgPriceAssetId]
246- let priceAssetId = fromBase58String(priceAssetId58)
247- let priceAssetMult = parseIntValue(cfgArray[IdxCfgPriceAssetMult])
248- let minIvestAmount = parseIntValue(cfgArray[IdxCfgMinInvestAmount])
249- let userAddress = toString(i.caller)
250- if ((idoStart > height))
251- then throw("ido has not been started yet")
252- else if ((height > idoEnd))
253- then throw("ido has been already ended")
254- else if ((size(i.payments) != 1))
255- then throw("exactly 1 payment is expected")
256- else {
257- let pmt = value(i.payments[0])
258- let pmtAssetId = value(pmt.assetId)
259- let pmtAmount = pmt.amount
260- if ((pmtAssetId != priceAssetId))
261- then throw((("invalid payment asset id: " + toBase58String(pmtAssetId)) + " is expected"))
262- else {
263- let origInvestorArray = readInvestorArrayOrDefault(userAddress)
264- let origTotalsArray = readTotalsArrayOrDefault()
265- let newPriceTotalAmount = (parseIntValue(origTotalsArray[IdxInvTotalAmount]) + pmtAmount)
266- let requiredIdoAssetAmount = (newPriceTotalAmount * 100)
267- if ((requiredIdoAssetAmount > assetBalance(this, idoAssetId)))
268- then throw("IDO asset has been - sold consider to use smaller payment")
269- else {
270- let totalsDiff = [pmtAmount, pmtAmount, 0, 0]
271-[TotalsEntry(keyInvestor(userAddress), origInvestorArray, totalsDiff, claimStart), TotalsEntry(keyTotals(), origTotalsArray, totalsDiff, claimStart), InvestOperationHistoryEntry(userAddress, pmtAmount, 0, i.transactionId)]
272- }
273- }
274- }
318+func currentUserRewardRateREADONLY (lpAssetId,userAddress) = {
319+ let rewardData = internalCurrentRewardRate(lpAssetId)
320+ let wxEmissionPerBlock = rewardData[0]
321+ let maxFactor = rewardData[1]
322+ let totalLpStaked = rewardData[2]
323+ let lpStakedByUser = getIntOrZero(stakingDapp, keyStakedByUser(userAddress, lpAssetId))
324+ let userClaimInfo = split(asString(invoke(stakingDapp, "claimWxREADONLY", [lpAssetId, userAddress], nil)), SEP)
325+ let minRewardPart = valueOrErrorMessage(parseInt(userClaimInfo[5]), "couldn't parse minRewardPart")
326+ let boostRewardPart = valueOrErrorMessage(parseInt(userClaimInfo[6]), "couldn't parse boostRewardPart")
327+ let debug = userClaimInfo[7]
328+ let boostingPower = if ((boostRewardPart == 0))
329+ then (1 * MULT8)
330+ else fraction((minRewardPart + boostRewardPart), MULT8, minRewardPart)
331+ $Tuple2(nil, makeString(["%d%d%d%d%d%s", toString(wxEmissionPerBlock), toString(maxFactor), toString(totalLpStaked), toString(lpStakedByUser), toString(boostingPower), debug], SEP))
275332 }
276333
277334
278335
279336 @Callable(i)
280-func claim (claimedAssetId58,userAddress58) = {
281- let callerAddress58 = toString(i.caller)
282- if ((userAddress58 != callerAddress58))
283- then throw("not authorized")
284- else {
285- let claimResultTuple = internalClaim(claimedAssetId58, i.caller, i.transactionId)
286- let totalsDiff = claimResultTuple._1
287- let outAmount = claimResultTuple._2
288- let outAssetId = claimResultTuple._3
289- let origInvestArray = claimResultTuple._4
290- let newClaimPeriodHeight = claimResultTuple._5
291- let claimedPriceAmountFromDiff = totalsDiff[IdxDiffClaimedPriceAmountIncrement]
292- let claimedIdoAssetAmountFromDiff = totalsDiff[IdxDiffClaimedIdoAssetAmountIncrement]
293- $Tuple2([ScriptTransfer(i.caller, outAmount, outAssetId), TotalsEntry(keyInvestor(userAddress58), origInvestArray, totalsDiff, newClaimPeriodHeight), TotalsEntry(keyTotals(), readTotalsArrayOrDefault(), totalsDiff, newClaimPeriodHeight), ClaimOperationHistoryEntry(userAddress58, claimedPriceAmountFromDiff, claimedIdoAssetAmountFromDiff, i.transactionId)], unit)
294- }
337+func claimedRewardREADONLY (userAddress) = {
338+ let lpList = readLpList()
339+ let prefix = "%s%d%d%d%s"
340+ func claimedRewardByLpAggregator (resultStr,nextLp) = {
341+ let claimedByUserMinRewardKEY = keyClaimedByUserMinReward(nextLp, userAddress)
342+ let claimedByUserBoostRewardKEY = keyClaimedByUserBoostReward(nextLp, userAddress)
343+ let minRewardClaimed = valueOrElse(getInteger(stakingDapp, claimedByUserMinRewardKEY), 0)
344+ let boostRewardClaimed = valueOrElse(getInteger(stakingDapp, claimedByUserBoostRewardKEY), 0)
345+ let gFeeClaimed = 0
346+ makeString([(prefix + resultStr), nextLp, toString(minRewardClaimed), toString(boostRewardClaimed), toString(gFeeClaimed), "end"], SEP)
347+ }
348+
349+ let result = {
350+ let $l = lpList
351+ let $s = size($l)
352+ let $acc0 = "%s"
353+ func $f0_1 ($a,$i) = if (($i >= $s))
354+ then $a
355+ else claimedRewardByLpAggregator($a, $l[$i])
356+
357+ func $f0_2 ($a,$i) = if (($i >= $s))
358+ then $a
359+ else throw("List size exceeds 10")
360+
361+ $f0_2($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)
362+ }
363+ $Tuple2(nil, ((result + SEP) + userAddress))
295364 }
296365
297366
298367
299368 @Callable(i)
300-func claimREADONLY (claimedAssetId58,userAddress58) = {
301- let claimResultTuple = internalClaim(claimedAssetId58, addressFromStringValue(userAddress58), fromBase58String(""))
302- let totalsDiff = claimResultTuple._1
303- let outAmount = claimResultTuple._2
304- let outAssetId = claimResultTuple._3
305- let origInvestArray = claimResultTuple._4
306- let newClaimPeriodHeight = claimResultTuple._5
307- let availableToClaimArray = claimResultTuple._6
308- let availablePriceAmountToClaim = availableToClaimArray[0]
309- let availableIdoAmountToClaim = availableToClaimArray[1]
310- $Tuple2(nil, makeString(["%s%d%d", userAddress58, toString(availablePriceAmountToClaim), toString(availableIdoAmountToClaim)], SEP))
369+func calcBoostREADONLY (deltaWxAmount,deltaLockPeriodInBlocks,deltaLpAmount,lpAssetIdOpt,userAddressOpt) = {
370+ let mathDapp = gwxRewardDapp
371+ let EMPTYSTR = "empty"
372+ let maxLockDurationInBlocks = parseIntValue(split(getStringByAddressOrFail(boostingDapp, keyBoostCfg()), SEP)[4])
373+ let lpAssetIdStr = if ((lpAssetIdOpt == ""))
374+ then EMPTYSTR
375+ else lpAssetIdOpt
376+ let userAddressStr = if ((userAddressOpt == ""))
377+ then EMPTYSTR
378+ else userAddressOpt
379+ let userNumStr = valueOrElse(getString(boostingDapp, keyUser2NumMapping(userAddressOpt)), EMPTYSTR)
380+ let userAmount = valueOrElse(getInteger(boostingDapp, keyLockParamUserAmount(userNumStr)), 0)
381+ let lockStart = valueOrElse(getInteger(boostingDapp, keyLockParamStartBlock(userNumStr)), height)
382+ let lockDuration = valueOrElse(getInteger(boostingDapp, keyLockParamDuration(userNumStr)), 0)
383+ let lockEnd = (lockStart + lockDuration)
384+ let remainingDuration = max([(lockEnd - height), 0])
385+ let userAmountNew = (userAmount + deltaWxAmount)
386+ let lockDurationNew = min([(remainingDuration + deltaLockPeriodInBlocks), maxLockDurationInBlocks])
387+ let userCurrgWxAmount = asInt(asAnyList(invoke(boostingDapp, "gwxUserInfoREADONLY", [userAddressStr], nil))[0])
388+ let gWxAmountStartNew = calcGwxAmountStartREADONLY(userAmountNew, lockDurationNew, maxLockDurationInBlocks)[0]
389+ let gWxParamsResultList = asAnyList(invoke(mathDapp, "calcGwxParamsREADONLY", [gWxAmountStartNew, height, lockDurationNew], nil))
390+ let gWxAmountDiff = (gWxAmountStartNew - userCurrgWxAmount)
391+ let k = asInt(gWxParamsResultList[0])
392+ let b = asInt(gWxParamsResultList[1])
393+ let period = toString(asInt(gWxParamsResultList[2]))
394+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
395+ let totalCachedGwxKEY = keyTotalCachedGwx()
396+ let userMaxBoostIntNew = ((gWxAmountStartNew * lockDurationNew) / 2)
397+ let totalMaxBoostInt = getIntOrZero(boostingDapp, totalMaxBoostIntegralKEY)
398+ let totalCachedGwx = valueOrElse(getInteger(boostingDapp, totalCachedGwxKEY), 0)
399+ let MULT3 = 1000
400+ let wxEmissionPerBlockX3 = (getIntOrFail(emissionDapp, keyEmissionRatePerBlockCurrent()) * MULT3)
401+ let stakedByUserKEY = keyStakedByUser(userAddressStr, lpAssetIdStr)
402+ let stakedTotalKEY = keyStakedTotal(lpAssetIdStr)
403+ let stakedByUser = readStaked(stakingDapp, stakedByUserKEY)
404+ let stakedTotal = readStaked(stakingDapp, stakedTotalKEY)
405+ let stakedByUserNew = (stakedByUser + deltaLpAmount)
406+ let stakedTotalNew = (stakedTotal + deltaLpAmount)
407+ let poolWeight = if ((lpAssetIdStr != EMPTYSTR))
408+ then {
409+ let poolAddressStr = valueOrErrorMessage(getString(factoryDapp, keyFactoryLp2AssetsMapping(lpAssetIdStr)), ("unsupported lp asset " + lpAssetIdStr))
410+ getIntegerValue(factoryDapp, keyFactoryPoolWeight(poolAddressStr))
411+ }
412+ else 0
413+ let poolWxEmissionPerBlockX3 = fraction(wxEmissionPerBlockX3, poolWeight, (POOLWEIGHTMULT * 3))
414+ let wxPerLpX3 = if ((stakedTotalNew != 0))
415+ then fraction(poolWxEmissionPerBlockX3, MULT8, stakedTotalNew)
416+ else 0
417+ let userWxPerBlockX3 = fraction(wxPerLpX3, stakedByUserNew, MULT8)
418+ let boostEmissionPerBlockX3 = (poolWxEmissionPerBlockX3 * 2)
419+ let tmpUserBoostPerBlockX3 = fraction(gWxAmountStartNew, boostEmissionPerBlockX3, (totalCachedGwx + gWxAmountDiff))
420+ let userBoostPerBlockX3 = min([tmpUserBoostPerBlockX3, (userWxPerBlockX3 * 2)])
421+ let boostCoeff = if ((userWxPerBlockX3 == 0))
422+ then (1 * MULT8)
423+ else fraction((userBoostPerBlockX3 + userWxPerBlockX3), MULT8, userWxPerBlockX3)
424+ let debug = makeString([("lpAssetIdStr=" + lpAssetIdStr), ("userAddressStr=" + userAddressStr), ("userNumStr=" + userNumStr), ("userAmount=" + toString(userAmount)), ("userAmountNew=" + toString(userAmountNew)), ("lockDurationNew=" + toString(lockDurationNew)), ("gWxAmountStart=" + toString(gWxAmountStartNew)), ("tmpUserBoostPerBlockX3=" + toString(tmpUserBoostPerBlockX3)), ("stakedByUserNew=" + toString(stakedByUserNew)), ("stakedTotalNew=" + toString(stakedTotalNew)), ("poolWeight=" + toString(poolWeight)), ("wxPerLpX3=" + toString(wxPerLpX3)), ("poolWxEmissionPerBlockX3=" + toString(poolWxEmissionPerBlockX3)), ("userWxPerBlockX3=" + toString(userWxPerBlockX3)), ("gWxAmountDiff=" + toString(gWxAmountDiff)), ("totalCachedGwx=" + toString(totalCachedGwx)), ("userCurrgWxAmount=" + toString(userCurrgWxAmount))], "::")
425+ $Tuple2(nil, makeString(["%d%d%s", toString(gWxAmountStartNew), toString(boostCoeff), debug], SEP))
426+ }
427+
428+
429+
430+@Callable(i)
431+func wxEmissionStatsREADONLY () = {
432+ let ONEMULT = toString(MULT8)
433+ let ONE = "1"
434+ let wxEmissionPerBlock = getIntOrFail(emissionDapp, keyEmissionRatePerBlockCurrent())
435+ let emissionStartBlock = getIntOrFail(emissionDapp, keyEmissionStartBlock())
436+ let passedBlocks = if ((emissionStartBlock > height))
437+ then 0
438+ else (height - emissionStartBlock)
439+ let teamEmDuration = (1440 * 365)
440+ let teamEmMax = (201000000 * MULT8)
441+ let teamEm = if ((passedBlocks > teamEmDuration))
442+ then teamEmMax
443+ else fraction(teamEmMax, passedBlocks, teamEmDuration)
444+ let totalWxReleased = ((wxEmissionPerBlock * passedBlocks) + teamEm)
445+ let totalWxLocked = getIntOrZero(boostingDapp, keyBoostingLockParamTotalAmount())
446+ let locksDurationSumInBlocks = getIntOrZero(boostingDapp, keyBoostingStatsLocksDurationSumInBlocks())
447+ let locksCount = getIntOrZero(boostingDapp, keyBoostingStatsLocksCount())
448+ $Tuple2(nil, makeString(["%d%d%d%d", toString(totalWxReleased), toString(totalWxLocked), toString(locksDurationSumInBlocks), toString(locksCount)], SEP))
449+ }
450+
451+
452+
453+@Callable(i)
454+func poolStatsREADONLY (lpAsset) = {
455+ let poolAddress = addressFromStringValue(getStringByAddressOrFail(factoryDapp, keyFactoryLpAssetToPoolContractAddress(lpAsset)))
456+ let cfg = asAnyList(invoke(poolAddress, "getPoolConfigWrapperREADONLY", nil, nil))
457+ let lpAssetId = fromBase58String(asString(cfg[idxPoolLPAssetId]))
458+ let amtAssetId = asString(cfg[idxAmtAssetId])
459+ let priceAssetId = asString(cfg[idxPriceAssetId])
460+ let iAmtAssetId = asString(cfg[idxIAmtAssetId])
461+ let iPriceAssetId = asString(cfg[idxIPriceAssetId])
462+ let amtAssetDcm = parseIntValue(asString(cfg[idxAmtAssetDcm]))
463+ let priceAssetDcm = parseIntValue(asString(cfg[idxPriceAssetDcm]))
464+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
465+ let accAmtAssetBalance = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [amtAssetId], nil))
466+ let accPriceAssetBalance = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [priceAssetId], nil))
467+ let pricesList = if ((poolLPBalance == 0))
468+ then [toString(zeroBigInt), toString(zeroBigInt), toString(zeroBigInt)]
469+ else asAnyList(invoke(poolAddress, "calcPricesWrapperREADONLY", [accAmtAssetBalance, accPriceAssetBalance, poolLPBalance], nil))
470+ let curPrice = 0
471+ let lpAmtAssetShare = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [pricesList[1], MULT8], nil))
472+ let lpPriceAssetShare = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [pricesList[2], MULT8], nil))
473+ let poolWeight = getIntegerValue(factoryDapp, keyFactoryPoolWeight(toString(poolAddress)))
474+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(accAmtAssetBalance), toString(accPriceAssetBalance), toString(poolLPBalance), toString(curPrice), toString(lpAmtAssetShare), toString(lpPriceAssetShare), toString(poolWeight)], SEP))
475+ }
476+
477+
478+
479+@Callable(i)
480+func poolEvaluatePutByAmountAssetREADONLY (lpAsset,inAmAssetAmt) = {
481+ let poolAddress = addressFromStringValue(getStringByAddressOrFail(factoryDapp, keyFactoryLpAssetToPoolContractAddress(lpAsset)))
482+ let cfg = asAnyList(invoke(poolAddress, "getPoolConfigWrapperREADONLY", nil, nil))
483+ let lpAssetId = fromBase58String(asString(cfg[idxPoolLPAssetId]))
484+ let amAssetIdStr = asString(cfg[idxAmtAssetId])
485+ let amAssetId = fromBase58String(amAssetIdStr)
486+ let prAssetIdStr = asString(cfg[idxPriceAssetId])
487+ let prAssetId = fromBase58String(prAssetIdStr)
488+ let amtAssetDcm = parseIntValue(asString(cfg[idxAmtAssetDcm]))
489+ let priceAssetDcm = parseIntValue(asString(cfg[idxPriceAssetDcm]))
490+ let poolStatus = asString(cfg[idxPoolStatus])
491+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
492+ let accAmtAssetBalance = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [amAssetIdStr], nil))
493+ let accPriceAssetBalance = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [prAssetIdStr], nil))
494+ let amtAssetAmtX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [accAmtAssetBalance, amtAssetDcm], nil)))
495+ let priceAssetAmtX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [accPriceAssetBalance, priceAssetDcm], nil)))
496+ let curPriceX18 = if ((poolLPBalance == 0))
497+ then zeroBigInt
498+ else parseBigIntValue(asString(invoke(poolAddress, "calcPriceBigIntWrapperREADONLY", [toString(priceAssetAmtX18), toString(amtAssetAmtX18)], nil)))
499+ let curPrice = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [toString(curPriceX18), MULT8], nil))
500+ let inAmAssetAmtX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [inAmAssetAmt, amtAssetDcm], nil)))
501+ let inPrAssetAmtX18 = fraction(inAmAssetAmtX18, curPriceX18, MULT18)
502+ let inPrAssetAmt = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [toString(inPrAssetAmtX18), priceAssetDcm], nil))
503+ let res = invoke(poolAddress, "estimatePutOperationWrapperREADONLY", ["", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false], nil)
504+ let $t02282123174 = match res {
505+ case _ =>
506+ if (if ($isInstanceOf($match0._1, "Int"))
507+ then if ($isInstanceOf($match0._3, "Int"))
508+ then if ($isInstanceOf($match0._4, "Int"))
509+ then if ($isInstanceOf($match0._5, "Int"))
510+ then $isInstanceOf($match0._6, "Int")
511+ else false
512+ else false
513+ else false
514+ else false)
515+ then {
516+ let calcLpAmt = $match0._1
517+ let curPriceCalc = $match0._3
518+ let amBalance = $match0._4
519+ let prBalance = $match0._5
520+ let lpEmission = $match0._6
521+ $Tuple5(calcLpAmt, curPriceCalc, amBalance, prBalance, lpEmission)
522+ }
523+ else throw("Couldn't cast types")
524+ }
525+ let calcLpAmt = $t02282123174._1
526+ let curPriceCalc = $t02282123174._2
527+ let amBalance = $t02282123174._3
528+ let prBalance = $t02282123174._4
529+ let lpEmission = $t02282123174._5
530+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(calcLpAmt), toString(curPrice), toString(amBalance), toString(prBalance), toString(lpEmission), poolStatus, toString(inAmAssetAmt), toString(inPrAssetAmt)], SEP))
531+ }
532+
533+
534+
535+@Callable(i)
536+func poolEvaluatePutByPriceAssetREADONLY (lpAsset,inPrAssetAmt) = {
537+ let poolAddress = addressFromStringValue(getStringByAddressOrFail(factoryDapp, keyFactoryLpAssetToPoolContractAddress(lpAsset)))
538+ let cfg = asAnyList(invoke(poolAddress, "getPoolConfigWrapperREADONLY", nil, nil))
539+ let lpAssetId = fromBase58String(asString(cfg[idxPoolLPAssetId]))
540+ let amAssetIdStr = asString(cfg[idxAmtAssetId])
541+ let amAssetId = fromBase58String(amAssetIdStr)
542+ let prAssetIdStr = asString(cfg[idxPriceAssetId])
543+ let prAssetId = fromBase58String(prAssetIdStr)
544+ let amtAssetDcm = parseIntValue(asString(cfg[idxAmtAssetDcm]))
545+ let priceAssetDcm = parseIntValue(asString(cfg[idxPriceAssetDcm]))
546+ let poolStatus = asString(cfg[idxPoolStatus])
547+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
548+ let amBalanceRaw = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [amAssetIdStr], nil))
549+ let prBalanceRaw = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [prAssetIdStr], nil))
550+ let amBalanceRawX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [amBalanceRaw, amtAssetDcm], nil)))
551+ let prBalanceRawX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [prBalanceRaw, priceAssetDcm], nil)))
552+ let curPriceX18 = if ((poolLPBalance == 0))
553+ then zeroBigInt
554+ else parseBigIntValue(asString(invoke(poolAddress, "calcPriceBigIntWrapperREADONLY", [toString(prBalanceRawX18), toString(amBalanceRawX18)], nil)))
555+ let curPrice = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [toString(curPriceX18), MULT8], nil))
556+ let inPrAssetAmtX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [inPrAssetAmt, priceAssetDcm], nil)))
557+ let inAmAssetAmtX18 = fraction(inPrAssetAmtX18, MULT18, curPriceX18)
558+ let inAmAssetAmt = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [toString(inAmAssetAmtX18), amtAssetDcm], nil))
559+ let res = invoke(poolAddress, "estimatePutOperationWrapperREADONLY", ["", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false], nil)
560+ let $t02574726100 = match res {
561+ case _ =>
562+ if (if ($isInstanceOf($match0._1, "Int"))
563+ then if ($isInstanceOf($match0._3, "Int"))
564+ then if ($isInstanceOf($match0._4, "Int"))
565+ then if ($isInstanceOf($match0._5, "Int"))
566+ then $isInstanceOf($match0._6, "Int")
567+ else false
568+ else false
569+ else false
570+ else false)
571+ then {
572+ let calcLpAmt = $match0._1
573+ let curPriceCalc = $match0._3
574+ let amBalance = $match0._4
575+ let prBalance = $match0._5
576+ let lpEmission = $match0._6
577+ $Tuple5(calcLpAmt, curPriceCalc, amBalance, prBalance, lpEmission)
578+ }
579+ else throw("Couldn't cast types")
580+ }
581+ let calcLpAmt = $t02574726100._1
582+ let curPriceCalc = $t02574726100._2
583+ let amBalance = $t02574726100._3
584+ let prBalance = $t02574726100._4
585+ let lpEmission = $t02574726100._5
586+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(calcLpAmt), toString(curPrice), toString(amBalance), toString(prBalance), toString(lpEmission), poolStatus, toString(inAmAssetAmt), toString(inPrAssetAmt)], SEP))
587+ }
588+
589+
590+
591+@Callable(i)
592+func poolEvaluateGetREADONLY (paymentLpAssetId,paymentLpAmt) = {
593+ let poolAddress = addressFromStringValue(getStringByAddressOrFail(factoryDapp, keyFactoryLpAssetToPoolContractAddress(paymentLpAssetId)))
594+ let res = invoke(poolAddress, "estimateGetOperationWrapperREADONLY", ["", paymentLpAssetId, paymentLpAmt, toString(poolAddress)], nil)
595+ let $t02679527212 = match res {
596+ case _ =>
597+ if (if ($isInstanceOf($match0._1, "Int"))
598+ then if ($isInstanceOf($match0._2, "Int"))
599+ then if ($isInstanceOf($match0._5, "Int"))
600+ then if ($isInstanceOf($match0._6, "Int"))
601+ then if ($isInstanceOf($match0._7, "Int"))
602+ then if ($isInstanceOf($match0._8, "String"))
603+ then $isInstanceOf($match0._9, "String")
604+ else false
605+ else false
606+ else false
607+ else false
608+ else false
609+ else false)
610+ then {
611+ let outAmAmt = $match0._1
612+ let outPrAmt = $match0._2
613+ let amBalance = $match0._5
614+ let prBalance = $match0._6
615+ let lpEmission = $match0._7
616+ let curPrice = $match0._8
617+ let poolStatus = $match0._9
618+ $Tuple7(outAmAmt, outPrAmt, amBalance, prBalance, lpEmission, curPrice, poolStatus)
619+ }
620+ else throw("Couldn't cast types")
621+ }
622+ let outAmAmt = $t02679527212._1
623+ let outPrAmt = $t02679527212._2
624+ let amBalance = $t02679527212._3
625+ let prBalance = $t02679527212._4
626+ let lpEmission = $t02679527212._5
627+ let curPrice = $t02679527212._6
628+ let poolStatus = $t02679527212._7
629+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(outAmAmt), toString(outPrAmt), toString(amBalance), toString(prBalance), toString(lpEmission), curPrice, poolStatus], SEP))
630+ }
631+
632+
633+
634+@Callable(i)
635+func gwxUserInfoREADONLY (userAddress) = {
636+ let gwxUserInfoLIST = asAnyList(invoke(boostingDapp, "gwxUserInfoREADONLY", [userAddress], nil))
637+ let gwxAmount = asInt(gwxUserInfoLIST[0])
638+ $Tuple2(nil, makeString(["%d", toString(gwxAmount)], SEP))
311639 }
312640
313641
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+let SCALE8 = 8
5+
6+let MULT8 = 100000000
7+
8+let SCALE18 = 18
9+
10+let MULT18 = toBigInt(1000000000000000000)
11+
12+let SEP = "__"
13+
14+let POOLWEIGHTMULT = MULT8
15+
16+let zeroBigInt = toBigInt(0)
17+
18+let idxPoolAddress = 1
19+
20+let idxPoolStatus = 2
21+
22+let idxPoolLPAssetId = 3
23+
24+let idxAmtAssetId = 4
25+
26+let idxPriceAssetId = 5
27+
28+let idxAmtAssetDcm = 6
29+
30+let idxPriceAssetDcm = 7
31+
32+let idxIAmtAssetId = 8
33+
34+let idxIPriceAssetId = 9
35+
36+let idxLPAssetDcm = 10
37+
438 func getStringOrFail (key) = valueOrErrorMessage(getString(key), (("mandatory this." + key) + " is not defined"))
539
640
7-let SEP = "__"
8-
9-let BUFSCALE = toBigInt(1000000000000000000)
10-
11-func convertPriceAssetIntoIdoAsset (priceAssetAmount,priceAssetMULT,price,priceMULT,idoAssetMULT) = {
12- let bPriceAssetMULT = toBigInt(priceAssetMULT)
13- let bIdoAssetMULT = toBigInt(idoAssetMULT)
14- let bPriceAssetBUF = fraction(toBigInt(priceAssetAmount), BUFSCALE, bPriceAssetMULT)
15- let bAmountAssetBUF = fraction(bPriceAssetBUF, toBigInt(priceMULT), toBigInt(price))
16- toInt(fraction(bAmountAssetBUF, toBigInt(idoAssetMULT), BUFSCALE))
17- }
41+func getStringByAddressOrFail (address,key) = valueOrErrorMessage(getString(address, key), (((("mandatory " + toString(address)) + ".") + key) + " is not defined"))
1842
1943
20-let IdxCfgIdoStart = 1
21-
22-let IdxCfgIdoDuration = 2
23-
24-let IdxCfgClaimStart = 3
25-
26-let IdxCfgClaimDuration = 4
27-
28-let IdxCfgPrice = 5
29-
30-let IdxCfgPriceMult = 6
31-
32-let IdxCfgIdoAssetId = 7
33-
34-let IdxCfgIdoAssetMult = 8
35-
36-let IdxCfgPriceAssetId = 9
37-
38-let IdxCfgPriceAssetMult = 10
39-
40-let IdxCfgMinInvestAmount = 11
41-
42-func fromatConfigS (idoStart,idoDuration,claimStart,claimDuration,price,priceMult,idoAssetId58,idoAssetMult,priceAssetId58,priceAssetMult,minInvestAmount,totalIdoAssetToSell) = makeString(["%d%d%d%d%d%d%s%d%s%d%d%d", idoStart, idoDuration, claimStart, claimDuration, price, priceMult, idoAssetId58, idoAssetMult, priceAssetId58, priceAssetMult, minInvestAmount, totalIdoAssetToSell], SEP)
44+func getIntOrZero (address,key) = valueOrElse(getInteger(address, key), 0)
4345
4446
45-func fromatConfig (idoStart,idoDuration,claimStart,claimDuration,price,priceMult,idoAssetId58,idoAssetMult,priceAssetId58,priceAssetMult,minInvestAmount,totalIdoAssetToSell) = fromatConfigS(toString(idoStart), toString(idoDuration), toString(claimStart), toString(claimDuration), toString(price), toString(priceMult), idoAssetId58, toString(idoAssetMult), priceAssetId58, toString(priceAssetMult), toString(minInvestAmount), toString(totalIdoAssetToSell))
47+func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), (("mandatory this." + key) + " is not defined"))
4648
4749
48-let IdxInvTotalAmount = 1
49-
50-let IdxInvRemainingAmount = 2
51-
52-let IdxInvClaimedPriceAssetAmount = 3
53-
54-let IdxInvClaimedIdoAssetAmount = 4
55-
56-let IdxInvLastClaimedHeight = 5
57-
58-func formatInvestorS (totalAmount,remainingAmount,claimedPriceAssetAmount,claimedIdoAssetAmount,lastClaimedHeight) = makeString(["%d%d%d%d%d", totalAmount, remainingAmount, claimedPriceAssetAmount, claimedIdoAssetAmount, lastClaimedHeight], SEP)
50+func asAnyList (val) = match val {
51+ case valAnyLyst: List[Any] =>
52+ valAnyLyst
53+ case _ =>
54+ throw("fail to cast into List[Any]")
55+}
5956
6057
61-func formatInvestor (totalAmount,remainingAmount,claimedPriceAssetAmount,claimedIdoAssetAmount,lastClaimedHeight) = formatInvestorS(toString(totalAmount), toString(remainingAmount), toString(claimedPriceAssetAmount), toString(claimedIdoAssetAmount), toString(lastClaimedHeight))
58+func asInt (val) = match val {
59+ case valInt: Int =>
60+ valInt
61+ case _ =>
62+ throw("fail to cast into Int")
63+}
6264
6365
64-func formatHistoryRecord (priceAssetAmount,idoAssetAmount) = makeString(["%d%d%d%d", toString(height), toString(lastBlock.timestamp), toString(priceAssetAmount), toString(idoAssetAmount)], SEP)
66+func asString (val) = match val {
67+ case valStr: String =>
68+ valStr
69+ case _ =>
70+ throw("fail to cast into String")
71+}
6572
6673
67-func keyConfig () = "%s__config"
68-
69-
70-func keyInvestor (userAddress) = ("%s__" + userAddress)
71-
72-
73-func keyTotals () = "%s__totals"
74-
75-
76-func keyOperationHistoryRecord (type,userAddress,txId58) = makeString(["%s%s%s%s__history", type, userAddress, txId58], SEP)
74+func keyFactoryAddress () = "%s%s__config__factoryAddress"
7775
7876
7977 func keyManagerPublicKey () = "%s__managerPublicKey"
8078
8179
8280 func keyPendingManagerPublicKey () = "%s__pendingManagerPublicKey"
8381
8482
85-func readConfigArray () = split(getStringOrFail(keyConfig()), SEP)
83+let IdxFactoryCfgStakingDapp = 1
84+
85+let IdxFactoryCfgBoostingDapp = 2
86+
87+let IdxFactoryCfgIdoDapp = 3
88+
89+let IdxFactoryCfgTeamDapp = 4
90+
91+let IdxFactoryCfgEmissionDapp = 5
92+
93+let IdxFactoryCfgRestDapp = 6
94+
95+let IdxFactoryCfgSlippageDapp = 7
96+
97+let IdxFactoryCfgGwxRewardDapp = 8
98+
99+func keyFactoryCfg () = "%s__factoryConfig"
86100
87101
88-func readTotalsArrayOrDefaultByCustomKey (customKey) = split(valueOrElse(getString(customKey), formatInvestorS("0", "0", "0", "0", "0")), SEP)
102+func keyFactoryLp2AssetsMapping (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
89103
90104
91-func readTotalsArrayOrDefault () = readTotalsArrayOrDefaultByCustomKey(keyTotals())
105+func keyFactoryLpList () = "%s__lpTokensList"
92106
93107
94-func readInvestorArrayOrDefault (userAddress) = readTotalsArrayOrDefaultByCustomKey(keyInvestor(userAddress))
108+func keyFactoryLpAssetToPoolContractAddress (lpAssetStr) = makeString(["%s%s%s", lpAssetStr, "mappings__lpAsset2PoolContract"], SEP)
95109
96110
97-func readInvestorArrayOrFail (userAddress) = split(getStringOrFail(keyInvestor(userAddress)), SEP)
111+func keyFactoryPoolWeight (contractAddress) = makeString(["%s%s", "poolWeight", contractAddress], SEP)
98112
99113
100-let IdxDiffTotalIncrement = 0
114+func readFactoryAddressOrFail () = addressFromStringValue(getStringOrFail(keyFactoryAddress()))
101115
102-let IdxDiffRemainingPriceAmountIncrement = 1
103116
104-let IdxDiffClaimedPriceAmountIncrement = 2
117+func readLpList () = split(valueOrElse(getString(readFactoryAddressOrFail(), keyFactoryLpList()), ""), SEP)
105118
106-let IdxDiffClaimedIdoAssetAmountIncrement = 3
107119
108-func TotalsEntry (key,origArray,incrementDiff,newLastClaimedHeight) = {
109- let totalAmount = parseIntValue(origArray[IdxInvTotalAmount])
110- let remainingAmount = parseIntValue(origArray[IdxInvRemainingAmount])
111- let claimedPriceAssetAmount = parseIntValue(origArray[IdxInvClaimedPriceAssetAmount])
112- let claimedIdoAssetAmount = parseIntValue(origArray[IdxInvClaimedIdoAssetAmount])
113- let lastClaimedHeight = parseIntValue(origArray[IdxInvLastClaimedHeight])
114- let newTotalAmount = (totalAmount + incrementDiff[IdxDiffTotalIncrement])
115- let newRemainingAmount = (remainingAmount + incrementDiff[IdxDiffRemainingPriceAmountIncrement])
116- let newClaimedPriceAssetAmount = (claimedPriceAssetAmount + incrementDiff[IdxDiffClaimedPriceAmountIncrement])
117- let newClaimedIdoAssetAmount = (claimedIdoAssetAmount + incrementDiff[IdxDiffClaimedIdoAssetAmountIncrement])
118- if ((0 > newRemainingAmount))
119- then throw("invalid math")
120- else StringEntry(key, formatInvestor(newTotalAmount, newRemainingAmount, newClaimedPriceAssetAmount, newClaimedIdoAssetAmount, newLastClaimedHeight))
120+func readFactoryCfgOrFail (factory) = split(getStringByAddressOrFail(factory, keyFactoryCfg()), SEP)
121+
122+
123+func getBoostingAddressOrFail (fCfg) = addressFromStringValue(fCfg[IdxFactoryCfgBoostingDapp])
124+
125+
126+func getEmissionAddressOrFail (fCfg) = addressFromStringValue(fCfg[IdxFactoryCfgEmissionDapp])
127+
128+
129+func getStakingAddressOrFail (fCfg) = addressFromStringValue(fCfg[IdxFactoryCfgStakingDapp])
130+
131+
132+func getGwxRewardAddressOrFail (fCfg) = addressFromStringValue(fCfg[IdxFactoryCfgGwxRewardDapp])
133+
134+
135+func keyBoostCfg () = "%s__config"
136+
137+
138+func keyBoostingLockParamTotalAmount () = "%s%s__stats__activeTotalLocked"
139+
140+
141+func keyBoostingStatsLocksDurationSumInBlocks () = "%s%s__stats__locksDurationSumInBlocks"
142+
143+
144+func keyBoostingStatsLocksCount () = "%s%s__stats__locksCount"
145+
146+
147+func keyBoostingStatsUsersCount () = "%s%s__stats__activeUsersCount"
148+
149+
150+func keyUser2NumMapping (userAddress) = makeString(["%s%s%s__mapping__user2num", userAddress], SEP)
151+
152+
153+func keyNum2UserMapping (num) = makeString(["%s%s%s__mapping__num2user", num], SEP)
154+
155+
156+func keyLockParamUserAmount (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "amount"], SEP)
157+
158+
159+func keyLockParamStartBlock (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "start"], SEP)
160+
161+
162+func keyLockParamDuration (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "duration"], SEP)
163+
164+
165+func keyLockParamK (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "k"], SEP)
166+
167+
168+func keyLockParamB (userNum) = makeString(["%s%d%s__paramByUserNum", userNum, "b"], SEP)
169+
170+
171+func keyLockParamByPeriodK (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "k", period], SEP)
172+
173+
174+func keyLockParamByPeriodB (userNum,period) = makeString(["%s%d%s%d__paramByPeriod", userNum, "b", period], SEP)
175+
176+
177+func keyUserBoostEmissionLastINTEGRAL (userNum) = makeString(["%s%d__userBoostEmissionLastInt", userNum], SEP)
178+
179+
180+func keyUserMaxBoostINTEGRAL (userNum) = makeString(["%s%d__maxBoostInt", userNum], SEP)
181+
182+
183+func keyTotalMaxBoostINTEGRAL () = "%s%s__maxBoostInt__total"
184+
185+
186+func keyUserBoostAvalaibleToClaimTotal (userNum) = makeString(["%s%d__userBoostAvaliableToClaimTotal", userNum], SEP)
187+
188+
189+func keyUserBoostClaimed (userNum) = makeString(["%s%d__userBoostClaimed", userNum], SEP)
190+
191+
192+func keyTotalCachedGwx () = "%s%s__gwxCached__total"
193+
194+
195+func keyStakedByUser (userAddressStr,lpAssetIdStr) = makeString(["%s%s%s__staked", userAddressStr, lpAssetIdStr], SEP)
196+
197+
198+func keyStakedTotal (lpAssetIdStr) = ("%s%s%s__staked__total__" + lpAssetIdStr)
199+
200+
201+func keyClaimedByUser (lpAssetIdStr,userAddressStr) = makeString(["%s%s%s__claimed", userAddressStr, lpAssetIdStr], SEP)
202+
203+
204+func keyClaimedByUserMinReward (lpAssetIdStr,userAddressStr) = makeString(["%s%s%s__claimedMinReward", userAddressStr, lpAssetIdStr], SEP)
205+
206+
207+func keyClaimedByUserBoostReward (lpAssetIdStr,userAddressStr) = makeString(["%s%s%s__claimedBoostReward", userAddressStr, lpAssetIdStr], SEP)
208+
209+
210+func readStaked (stakingDapp,key) = valueOrElse(getInteger(stakingDapp, key), 0)
211+
212+
213+func keyEmissionRatePerBlockCurrent () = "%s%s__ratePerBlock__current"
214+
215+
216+func keyEmissionRatePerBlockMaxCurrent () = "%s%s__ratePerBlockMax__current"
217+
218+
219+func keyEmissionStartBlock () = "%s%s__emission__startBlock"
220+
221+
222+func keyEmissionDurationInBlocks () = "%s%s__emission__duration"
223+
224+
225+func keyEmissionEndBlock () = "%s%s__emission__endBlock"
226+
227+
228+let factoryDapp = readFactoryAddressOrFail()
229+
230+let factoryCfg = readFactoryCfgOrFail(factoryDapp)
231+
232+let emissionDapp = getEmissionAddressOrFail(factoryCfg)
233+
234+let stakingDapp = getStakingAddressOrFail(factoryCfg)
235+
236+let gwxRewardDapp = getGwxRewardAddressOrFail(factoryCfg)
237+
238+let boostingDapp = getBoostingAddressOrFail(factoryCfg)
239+
240+func internalCurrentRewardRate (lpAssetId) = {
241+ let poolAddressStr = getStringByAddressOrFail(factoryDapp, keyFactoryLpAssetToPoolContractAddress(lpAssetId))
242+ let poolWeightMult = MULT8
243+ let poolWeight = getIntegerValue(factoryDapp, keyFactoryPoolWeight(poolAddressStr))
244+ let wxEmissionPerBlock = getIntOrFail(emissionDapp, keyEmissionRatePerBlockCurrent())
245+ let wxEmissionPerBlockMax = getIntOrFail(emissionDapp, keyEmissionRatePerBlockMaxCurrent())
246+ let boostMaxCoeff = 3
247+ let poolWxEmissionPerBlock = (fraction(wxEmissionPerBlock, poolWeight, poolWeightMult) / boostMaxCoeff)
248+ let poolWxEmissionPerBlockMax = fraction(wxEmissionPerBlockMax, poolWeight, poolWeightMult)
249+ let maxFactor = (boostMaxCoeff * MULT8)
250+ let totalLpStaked = getIntOrZero(stakingDapp, keyStakedTotal(lpAssetId))
251+[poolWxEmissionPerBlock, maxFactor, totalLpStaked]
121252 }
122253
123254
124-func InvestOperationHistoryEntry (userAddress,priceAssetAmount,idoAssetAmount,txId) = StringEntry(keyOperationHistoryRecord("invest", userAddress, toBase58String(txId)), formatHistoryRecord(priceAssetAmount, idoAssetAmount))
125-
126-
127-func ClaimOperationHistoryEntry (userAddress,priceAssetAmount,idoAssetAmount,txId) = StringEntry(keyOperationHistoryRecord("claim", userAddress, toBase58String(txId)), formatHistoryRecord(priceAssetAmount, idoAssetAmount))
128-
129-
130-func internalClaim (claimedAssetId58,userAddress,txId) = {
131- let cfgArray = readConfigArray()
132- let claimStart = parseIntValue(cfgArray[IdxCfgClaimStart])
133- let claimDuration = parseIntValue(cfgArray[IdxCfgClaimDuration])
134- let claimEnd = (claimStart + claimDuration)
135- let price = parseIntValue(cfgArray[IdxCfgPrice])
136- let priceMult = parseIntValue(cfgArray[IdxCfgPriceMult])
137- let idoAssetId58 = cfgArray[IdxCfgIdoAssetId]
138- let idoAssetId = fromBase58String(idoAssetId58)
139- let idoAssetMult = parseIntValue(cfgArray[IdxCfgIdoAssetMult])
140- let priceAssetId58 = cfgArray[IdxCfgPriceAssetId]
141- let priceAssetId = fromBase58String(priceAssetId58)
142- let priceAssetMult = parseIntValue(cfgArray[IdxCfgPriceAssetMult])
143- let userAddress58 = toString(userAddress)
144- let origInvestArray = readInvestorArrayOrFail(userAddress58)
145- let investTotalAmount = parseIntValue(origInvestArray[IdxInvTotalAmount])
146- let investLastClaimedHeightTMP = parseIntValue(origInvestArray[IdxInvLastClaimedHeight])
147- let investLastClaimedHeight = if ((claimStart >= investLastClaimedHeightTMP))
148- then claimStart
149- else investLastClaimedHeightTMP
150- let newClaimPeriodHeight = if ((height > claimEnd))
151- then claimEnd
152- else if ((claimStart > height))
153- then claimStart
154- else height
155- let claimingBlocks = (newClaimPeriodHeight - investLastClaimedHeight)
156- let claimingPriceAssetAmount = fraction(investTotalAmount, claimingBlocks, claimDuration)
157- let claimingIdoAssetAmount = convertPriceAssetIntoIdoAsset(claimingPriceAssetAmount, priceAssetMult, price, priceMult, idoAssetMult)
158- if ((claimedAssetId58 == priceAssetId58))
159- then $Tuple6([0, -(claimingPriceAssetAmount), claimingPriceAssetAmount, 0], claimingPriceAssetAmount, priceAssetId, origInvestArray, newClaimPeriodHeight, [claimingPriceAssetAmount, claimingIdoAssetAmount])
160- else if ((claimedAssetId58 == idoAssetId58))
161- then $Tuple6([0, -(claimingPriceAssetAmount), 0, claimingIdoAssetAmount], claimingIdoAssetAmount, idoAssetId, origInvestArray, newClaimPeriodHeight, [claimingPriceAssetAmount, claimingIdoAssetAmount])
162- else throw(("unsupported assetId: " + claimedAssetId58))
255+func calcGwxAmountStartREADONLY (lockAmount,lockDuration,maxLockDuration) = {
256+ let coeffX8 = fraction(lockDuration, MULT8, maxLockDuration)
257+ let gWxAmountStart = fraction(lockAmount, coeffX8, MULT8)
258+[gWxAmountStart]
163259 }
164260
165261
166262 func managerPublicKeyOrUnit () = match getString(keyManagerPublicKey()) {
167263 case s: String =>
168264 fromBase58String(s)
169265 case _: Unit =>
170266 unit
171267 case _ =>
172268 throw("Match error")
173269 }
174270
175271
176272 func pendingManagerPublicKeyOrUnit () = match getString(keyPendingManagerPublicKey()) {
177273 case s: String =>
178274 fromBase58String(s)
179275 case _: Unit =>
180276 unit
181277 case _ =>
182278 throw("Match error")
183279 }
184280
185281
186282 func mustManager (i) = {
187283 let pd = throw("Permission denied")
188284 match managerPublicKeyOrUnit() {
189285 case pk: ByteVector =>
190286 if ((i.callerPublicKey == pk))
191287 then true
192288 else pd
193289 case _: Unit =>
194290 if ((i.caller == this))
195291 then true
196292 else pd
197293 case _ =>
198294 throw("Match error")
199295 }
200296 }
201297
202298
203299 @Callable(i)
204-func constructor (idoStart,idoDuration,claimStart,claimDuration,price,priceAssetId58,minInvestAmount) = {
205- let priceMult = ((100 * 1000) * 1000)
206- let idoEnd = (idoStart + idoDuration)
207- if (isDefined(getString(keyConfig())))
208- then throw("already initialized")
209- else if (("3PMEHLx1j6zerarZTYfsGqDeeZqQoMpxq5S" != toString(i.caller)))
210- then throw("not authorized")
211- else if ((size(i.payments) != 1))
212- then throw("exactly 1 payment must be attached")
213- else if ((idoEnd >= claimStart))
214- then throw("claimStart must be greater than idoEnd")
215- else {
216- let pmt = value(i.payments[0])
217- let idoAssetId = value(pmt.assetId)
218- let idoAssetInfo = valueOrErrorMessage(assetInfo(idoAssetId), "fail to load ido asset info")
219- let idoAssetId58 = toBase58String(idoAssetId)
220- let idoAssetMult = pow(10, 0, idoAssetInfo.decimals, 0, 0, DOWN)
221- let priceAssetId = fromBase58String(priceAssetId58)
222- let priceAssetInfo = valueOrErrorMessage(assetInfo(priceAssetId), "fail to load price asset info")
223- let priceAssetMult = pow(10, 0, priceAssetInfo.decimals, 0, 0, DOWN)
224- let origTotalsArray = readTotalsArrayOrDefault()
225- let totalsDiff = [0, 0, 0, 0]
226-[StringEntry(keyConfig(), fromatConfig(idoStart, idoDuration, claimStart, claimDuration, price, priceMult, idoAssetId58, idoAssetMult, priceAssetId58, priceAssetMult, minInvestAmount, pmt.amount)), TotalsEntry(keyTotals(), origTotalsArray, totalsDiff, claimStart)]
227- }
300+func constructor (factoryAddress) = if ((i.caller != this))
301+ then throw("not authorized")
302+ else [StringEntry(keyFactoryAddress(), factoryAddress)]
303+
304+
305+
306+@Callable(i)
307+func currentRewardRateREADONLY (lpAssetId) = {
308+ let rewardData = internalCurrentRewardRate(lpAssetId)
309+ let wxEmissionPerBlock = rewardData[0]
310+ let maxFactor = rewardData[1]
311+ let totalLpStaked = rewardData[2]
312+ $Tuple2(nil, makeString(["%d%d%d", toString(wxEmissionPerBlock), toString(maxFactor), toString(totalLpStaked)], SEP))
228313 }
229314
230315
231316
232317 @Callable(i)
233-func invest () = {
234- let cfgArray = readConfigArray()
235- let idoStart = parseIntValue(cfgArray[IdxCfgIdoStart])
236- let idoDuration = parseIntValue(cfgArray[IdxCfgIdoDuration])
237- let idoEnd = (idoStart + idoDuration)
238- let claimStart = parseIntValue(cfgArray[IdxCfgClaimStart])
239- let claimDuration = parseIntValue(cfgArray[IdxCfgClaimDuration])
240- let price = parseIntValue(cfgArray[IdxCfgPrice])
241- let priceMult = parseIntValue(cfgArray[IdxCfgPriceMult])
242- let idoAssetId58 = cfgArray[IdxCfgIdoAssetId]
243- let idoAssetId = fromBase58String(idoAssetId58)
244- let idoAssetMult = parseIntValue(cfgArray[IdxCfgIdoAssetMult])
245- let priceAssetId58 = cfgArray[IdxCfgPriceAssetId]
246- let priceAssetId = fromBase58String(priceAssetId58)
247- let priceAssetMult = parseIntValue(cfgArray[IdxCfgPriceAssetMult])
248- let minIvestAmount = parseIntValue(cfgArray[IdxCfgMinInvestAmount])
249- let userAddress = toString(i.caller)
250- if ((idoStart > height))
251- then throw("ido has not been started yet")
252- else if ((height > idoEnd))
253- then throw("ido has been already ended")
254- else if ((size(i.payments) != 1))
255- then throw("exactly 1 payment is expected")
256- else {
257- let pmt = value(i.payments[0])
258- let pmtAssetId = value(pmt.assetId)
259- let pmtAmount = pmt.amount
260- if ((pmtAssetId != priceAssetId))
261- then throw((("invalid payment asset id: " + toBase58String(pmtAssetId)) + " is expected"))
262- else {
263- let origInvestorArray = readInvestorArrayOrDefault(userAddress)
264- let origTotalsArray = readTotalsArrayOrDefault()
265- let newPriceTotalAmount = (parseIntValue(origTotalsArray[IdxInvTotalAmount]) + pmtAmount)
266- let requiredIdoAssetAmount = (newPriceTotalAmount * 100)
267- if ((requiredIdoAssetAmount > assetBalance(this, idoAssetId)))
268- then throw("IDO asset has been - sold consider to use smaller payment")
269- else {
270- let totalsDiff = [pmtAmount, pmtAmount, 0, 0]
271-[TotalsEntry(keyInvestor(userAddress), origInvestorArray, totalsDiff, claimStart), TotalsEntry(keyTotals(), origTotalsArray, totalsDiff, claimStart), InvestOperationHistoryEntry(userAddress, pmtAmount, 0, i.transactionId)]
272- }
273- }
274- }
318+func currentUserRewardRateREADONLY (lpAssetId,userAddress) = {
319+ let rewardData = internalCurrentRewardRate(lpAssetId)
320+ let wxEmissionPerBlock = rewardData[0]
321+ let maxFactor = rewardData[1]
322+ let totalLpStaked = rewardData[2]
323+ let lpStakedByUser = getIntOrZero(stakingDapp, keyStakedByUser(userAddress, lpAssetId))
324+ let userClaimInfo = split(asString(invoke(stakingDapp, "claimWxREADONLY", [lpAssetId, userAddress], nil)), SEP)
325+ let minRewardPart = valueOrErrorMessage(parseInt(userClaimInfo[5]), "couldn't parse minRewardPart")
326+ let boostRewardPart = valueOrErrorMessage(parseInt(userClaimInfo[6]), "couldn't parse boostRewardPart")
327+ let debug = userClaimInfo[7]
328+ let boostingPower = if ((boostRewardPart == 0))
329+ then (1 * MULT8)
330+ else fraction((minRewardPart + boostRewardPart), MULT8, minRewardPart)
331+ $Tuple2(nil, makeString(["%d%d%d%d%d%s", toString(wxEmissionPerBlock), toString(maxFactor), toString(totalLpStaked), toString(lpStakedByUser), toString(boostingPower), debug], SEP))
275332 }
276333
277334
278335
279336 @Callable(i)
280-func claim (claimedAssetId58,userAddress58) = {
281- let callerAddress58 = toString(i.caller)
282- if ((userAddress58 != callerAddress58))
283- then throw("not authorized")
284- else {
285- let claimResultTuple = internalClaim(claimedAssetId58, i.caller, i.transactionId)
286- let totalsDiff = claimResultTuple._1
287- let outAmount = claimResultTuple._2
288- let outAssetId = claimResultTuple._3
289- let origInvestArray = claimResultTuple._4
290- let newClaimPeriodHeight = claimResultTuple._5
291- let claimedPriceAmountFromDiff = totalsDiff[IdxDiffClaimedPriceAmountIncrement]
292- let claimedIdoAssetAmountFromDiff = totalsDiff[IdxDiffClaimedIdoAssetAmountIncrement]
293- $Tuple2([ScriptTransfer(i.caller, outAmount, outAssetId), TotalsEntry(keyInvestor(userAddress58), origInvestArray, totalsDiff, newClaimPeriodHeight), TotalsEntry(keyTotals(), readTotalsArrayOrDefault(), totalsDiff, newClaimPeriodHeight), ClaimOperationHistoryEntry(userAddress58, claimedPriceAmountFromDiff, claimedIdoAssetAmountFromDiff, i.transactionId)], unit)
294- }
337+func claimedRewardREADONLY (userAddress) = {
338+ let lpList = readLpList()
339+ let prefix = "%s%d%d%d%s"
340+ func claimedRewardByLpAggregator (resultStr,nextLp) = {
341+ let claimedByUserMinRewardKEY = keyClaimedByUserMinReward(nextLp, userAddress)
342+ let claimedByUserBoostRewardKEY = keyClaimedByUserBoostReward(nextLp, userAddress)
343+ let minRewardClaimed = valueOrElse(getInteger(stakingDapp, claimedByUserMinRewardKEY), 0)
344+ let boostRewardClaimed = valueOrElse(getInteger(stakingDapp, claimedByUserBoostRewardKEY), 0)
345+ let gFeeClaimed = 0
346+ makeString([(prefix + resultStr), nextLp, toString(minRewardClaimed), toString(boostRewardClaimed), toString(gFeeClaimed), "end"], SEP)
347+ }
348+
349+ let result = {
350+ let $l = lpList
351+ let $s = size($l)
352+ let $acc0 = "%s"
353+ func $f0_1 ($a,$i) = if (($i >= $s))
354+ then $a
355+ else claimedRewardByLpAggregator($a, $l[$i])
356+
357+ func $f0_2 ($a,$i) = if (($i >= $s))
358+ then $a
359+ else throw("List size exceeds 10")
360+
361+ $f0_2($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)
362+ }
363+ $Tuple2(nil, ((result + SEP) + userAddress))
295364 }
296365
297366
298367
299368 @Callable(i)
300-func claimREADONLY (claimedAssetId58,userAddress58) = {
301- let claimResultTuple = internalClaim(claimedAssetId58, addressFromStringValue(userAddress58), fromBase58String(""))
302- let totalsDiff = claimResultTuple._1
303- let outAmount = claimResultTuple._2
304- let outAssetId = claimResultTuple._3
305- let origInvestArray = claimResultTuple._4
306- let newClaimPeriodHeight = claimResultTuple._5
307- let availableToClaimArray = claimResultTuple._6
308- let availablePriceAmountToClaim = availableToClaimArray[0]
309- let availableIdoAmountToClaim = availableToClaimArray[1]
310- $Tuple2(nil, makeString(["%s%d%d", userAddress58, toString(availablePriceAmountToClaim), toString(availableIdoAmountToClaim)], SEP))
369+func calcBoostREADONLY (deltaWxAmount,deltaLockPeriodInBlocks,deltaLpAmount,lpAssetIdOpt,userAddressOpt) = {
370+ let mathDapp = gwxRewardDapp
371+ let EMPTYSTR = "empty"
372+ let maxLockDurationInBlocks = parseIntValue(split(getStringByAddressOrFail(boostingDapp, keyBoostCfg()), SEP)[4])
373+ let lpAssetIdStr = if ((lpAssetIdOpt == ""))
374+ then EMPTYSTR
375+ else lpAssetIdOpt
376+ let userAddressStr = if ((userAddressOpt == ""))
377+ then EMPTYSTR
378+ else userAddressOpt
379+ let userNumStr = valueOrElse(getString(boostingDapp, keyUser2NumMapping(userAddressOpt)), EMPTYSTR)
380+ let userAmount = valueOrElse(getInteger(boostingDapp, keyLockParamUserAmount(userNumStr)), 0)
381+ let lockStart = valueOrElse(getInteger(boostingDapp, keyLockParamStartBlock(userNumStr)), height)
382+ let lockDuration = valueOrElse(getInteger(boostingDapp, keyLockParamDuration(userNumStr)), 0)
383+ let lockEnd = (lockStart + lockDuration)
384+ let remainingDuration = max([(lockEnd - height), 0])
385+ let userAmountNew = (userAmount + deltaWxAmount)
386+ let lockDurationNew = min([(remainingDuration + deltaLockPeriodInBlocks), maxLockDurationInBlocks])
387+ let userCurrgWxAmount = asInt(asAnyList(invoke(boostingDapp, "gwxUserInfoREADONLY", [userAddressStr], nil))[0])
388+ let gWxAmountStartNew = calcGwxAmountStartREADONLY(userAmountNew, lockDurationNew, maxLockDurationInBlocks)[0]
389+ let gWxParamsResultList = asAnyList(invoke(mathDapp, "calcGwxParamsREADONLY", [gWxAmountStartNew, height, lockDurationNew], nil))
390+ let gWxAmountDiff = (gWxAmountStartNew - userCurrgWxAmount)
391+ let k = asInt(gWxParamsResultList[0])
392+ let b = asInt(gWxParamsResultList[1])
393+ let period = toString(asInt(gWxParamsResultList[2]))
394+ let totalMaxBoostIntegralKEY = keyTotalMaxBoostINTEGRAL()
395+ let totalCachedGwxKEY = keyTotalCachedGwx()
396+ let userMaxBoostIntNew = ((gWxAmountStartNew * lockDurationNew) / 2)
397+ let totalMaxBoostInt = getIntOrZero(boostingDapp, totalMaxBoostIntegralKEY)
398+ let totalCachedGwx = valueOrElse(getInteger(boostingDapp, totalCachedGwxKEY), 0)
399+ let MULT3 = 1000
400+ let wxEmissionPerBlockX3 = (getIntOrFail(emissionDapp, keyEmissionRatePerBlockCurrent()) * MULT3)
401+ let stakedByUserKEY = keyStakedByUser(userAddressStr, lpAssetIdStr)
402+ let stakedTotalKEY = keyStakedTotal(lpAssetIdStr)
403+ let stakedByUser = readStaked(stakingDapp, stakedByUserKEY)
404+ let stakedTotal = readStaked(stakingDapp, stakedTotalKEY)
405+ let stakedByUserNew = (stakedByUser + deltaLpAmount)
406+ let stakedTotalNew = (stakedTotal + deltaLpAmount)
407+ let poolWeight = if ((lpAssetIdStr != EMPTYSTR))
408+ then {
409+ let poolAddressStr = valueOrErrorMessage(getString(factoryDapp, keyFactoryLp2AssetsMapping(lpAssetIdStr)), ("unsupported lp asset " + lpAssetIdStr))
410+ getIntegerValue(factoryDapp, keyFactoryPoolWeight(poolAddressStr))
411+ }
412+ else 0
413+ let poolWxEmissionPerBlockX3 = fraction(wxEmissionPerBlockX3, poolWeight, (POOLWEIGHTMULT * 3))
414+ let wxPerLpX3 = if ((stakedTotalNew != 0))
415+ then fraction(poolWxEmissionPerBlockX3, MULT8, stakedTotalNew)
416+ else 0
417+ let userWxPerBlockX3 = fraction(wxPerLpX3, stakedByUserNew, MULT8)
418+ let boostEmissionPerBlockX3 = (poolWxEmissionPerBlockX3 * 2)
419+ let tmpUserBoostPerBlockX3 = fraction(gWxAmountStartNew, boostEmissionPerBlockX3, (totalCachedGwx + gWxAmountDiff))
420+ let userBoostPerBlockX3 = min([tmpUserBoostPerBlockX3, (userWxPerBlockX3 * 2)])
421+ let boostCoeff = if ((userWxPerBlockX3 == 0))
422+ then (1 * MULT8)
423+ else fraction((userBoostPerBlockX3 + userWxPerBlockX3), MULT8, userWxPerBlockX3)
424+ let debug = makeString([("lpAssetIdStr=" + lpAssetIdStr), ("userAddressStr=" + userAddressStr), ("userNumStr=" + userNumStr), ("userAmount=" + toString(userAmount)), ("userAmountNew=" + toString(userAmountNew)), ("lockDurationNew=" + toString(lockDurationNew)), ("gWxAmountStart=" + toString(gWxAmountStartNew)), ("tmpUserBoostPerBlockX3=" + toString(tmpUserBoostPerBlockX3)), ("stakedByUserNew=" + toString(stakedByUserNew)), ("stakedTotalNew=" + toString(stakedTotalNew)), ("poolWeight=" + toString(poolWeight)), ("wxPerLpX3=" + toString(wxPerLpX3)), ("poolWxEmissionPerBlockX3=" + toString(poolWxEmissionPerBlockX3)), ("userWxPerBlockX3=" + toString(userWxPerBlockX3)), ("gWxAmountDiff=" + toString(gWxAmountDiff)), ("totalCachedGwx=" + toString(totalCachedGwx)), ("userCurrgWxAmount=" + toString(userCurrgWxAmount))], "::")
425+ $Tuple2(nil, makeString(["%d%d%s", toString(gWxAmountStartNew), toString(boostCoeff), debug], SEP))
426+ }
427+
428+
429+
430+@Callable(i)
431+func wxEmissionStatsREADONLY () = {
432+ let ONEMULT = toString(MULT8)
433+ let ONE = "1"
434+ let wxEmissionPerBlock = getIntOrFail(emissionDapp, keyEmissionRatePerBlockCurrent())
435+ let emissionStartBlock = getIntOrFail(emissionDapp, keyEmissionStartBlock())
436+ let passedBlocks = if ((emissionStartBlock > height))
437+ then 0
438+ else (height - emissionStartBlock)
439+ let teamEmDuration = (1440 * 365)
440+ let teamEmMax = (201000000 * MULT8)
441+ let teamEm = if ((passedBlocks > teamEmDuration))
442+ then teamEmMax
443+ else fraction(teamEmMax, passedBlocks, teamEmDuration)
444+ let totalWxReleased = ((wxEmissionPerBlock * passedBlocks) + teamEm)
445+ let totalWxLocked = getIntOrZero(boostingDapp, keyBoostingLockParamTotalAmount())
446+ let locksDurationSumInBlocks = getIntOrZero(boostingDapp, keyBoostingStatsLocksDurationSumInBlocks())
447+ let locksCount = getIntOrZero(boostingDapp, keyBoostingStatsLocksCount())
448+ $Tuple2(nil, makeString(["%d%d%d%d", toString(totalWxReleased), toString(totalWxLocked), toString(locksDurationSumInBlocks), toString(locksCount)], SEP))
449+ }
450+
451+
452+
453+@Callable(i)
454+func poolStatsREADONLY (lpAsset) = {
455+ let poolAddress = addressFromStringValue(getStringByAddressOrFail(factoryDapp, keyFactoryLpAssetToPoolContractAddress(lpAsset)))
456+ let cfg = asAnyList(invoke(poolAddress, "getPoolConfigWrapperREADONLY", nil, nil))
457+ let lpAssetId = fromBase58String(asString(cfg[idxPoolLPAssetId]))
458+ let amtAssetId = asString(cfg[idxAmtAssetId])
459+ let priceAssetId = asString(cfg[idxPriceAssetId])
460+ let iAmtAssetId = asString(cfg[idxIAmtAssetId])
461+ let iPriceAssetId = asString(cfg[idxIPriceAssetId])
462+ let amtAssetDcm = parseIntValue(asString(cfg[idxAmtAssetDcm]))
463+ let priceAssetDcm = parseIntValue(asString(cfg[idxPriceAssetDcm]))
464+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
465+ let accAmtAssetBalance = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [amtAssetId], nil))
466+ let accPriceAssetBalance = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [priceAssetId], nil))
467+ let pricesList = if ((poolLPBalance == 0))
468+ then [toString(zeroBigInt), toString(zeroBigInt), toString(zeroBigInt)]
469+ else asAnyList(invoke(poolAddress, "calcPricesWrapperREADONLY", [accAmtAssetBalance, accPriceAssetBalance, poolLPBalance], nil))
470+ let curPrice = 0
471+ let lpAmtAssetShare = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [pricesList[1], MULT8], nil))
472+ let lpPriceAssetShare = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [pricesList[2], MULT8], nil))
473+ let poolWeight = getIntegerValue(factoryDapp, keyFactoryPoolWeight(toString(poolAddress)))
474+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(accAmtAssetBalance), toString(accPriceAssetBalance), toString(poolLPBalance), toString(curPrice), toString(lpAmtAssetShare), toString(lpPriceAssetShare), toString(poolWeight)], SEP))
475+ }
476+
477+
478+
479+@Callable(i)
480+func poolEvaluatePutByAmountAssetREADONLY (lpAsset,inAmAssetAmt) = {
481+ let poolAddress = addressFromStringValue(getStringByAddressOrFail(factoryDapp, keyFactoryLpAssetToPoolContractAddress(lpAsset)))
482+ let cfg = asAnyList(invoke(poolAddress, "getPoolConfigWrapperREADONLY", nil, nil))
483+ let lpAssetId = fromBase58String(asString(cfg[idxPoolLPAssetId]))
484+ let amAssetIdStr = asString(cfg[idxAmtAssetId])
485+ let amAssetId = fromBase58String(amAssetIdStr)
486+ let prAssetIdStr = asString(cfg[idxPriceAssetId])
487+ let prAssetId = fromBase58String(prAssetIdStr)
488+ let amtAssetDcm = parseIntValue(asString(cfg[idxAmtAssetDcm]))
489+ let priceAssetDcm = parseIntValue(asString(cfg[idxPriceAssetDcm]))
490+ let poolStatus = asString(cfg[idxPoolStatus])
491+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
492+ let accAmtAssetBalance = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [amAssetIdStr], nil))
493+ let accPriceAssetBalance = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [prAssetIdStr], nil))
494+ let amtAssetAmtX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [accAmtAssetBalance, amtAssetDcm], nil)))
495+ let priceAssetAmtX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [accPriceAssetBalance, priceAssetDcm], nil)))
496+ let curPriceX18 = if ((poolLPBalance == 0))
497+ then zeroBigInt
498+ else parseBigIntValue(asString(invoke(poolAddress, "calcPriceBigIntWrapperREADONLY", [toString(priceAssetAmtX18), toString(amtAssetAmtX18)], nil)))
499+ let curPrice = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [toString(curPriceX18), MULT8], nil))
500+ let inAmAssetAmtX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [inAmAssetAmt, amtAssetDcm], nil)))
501+ let inPrAssetAmtX18 = fraction(inAmAssetAmtX18, curPriceX18, MULT18)
502+ let inPrAssetAmt = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [toString(inPrAssetAmtX18), priceAssetDcm], nil))
503+ let res = invoke(poolAddress, "estimatePutOperationWrapperREADONLY", ["", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false], nil)
504+ let $t02282123174 = match res {
505+ case _ =>
506+ if (if ($isInstanceOf($match0._1, "Int"))
507+ then if ($isInstanceOf($match0._3, "Int"))
508+ then if ($isInstanceOf($match0._4, "Int"))
509+ then if ($isInstanceOf($match0._5, "Int"))
510+ then $isInstanceOf($match0._6, "Int")
511+ else false
512+ else false
513+ else false
514+ else false)
515+ then {
516+ let calcLpAmt = $match0._1
517+ let curPriceCalc = $match0._3
518+ let amBalance = $match0._4
519+ let prBalance = $match0._5
520+ let lpEmission = $match0._6
521+ $Tuple5(calcLpAmt, curPriceCalc, amBalance, prBalance, lpEmission)
522+ }
523+ else throw("Couldn't cast types")
524+ }
525+ let calcLpAmt = $t02282123174._1
526+ let curPriceCalc = $t02282123174._2
527+ let amBalance = $t02282123174._3
528+ let prBalance = $t02282123174._4
529+ let lpEmission = $t02282123174._5
530+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(calcLpAmt), toString(curPrice), toString(amBalance), toString(prBalance), toString(lpEmission), poolStatus, toString(inAmAssetAmt), toString(inPrAssetAmt)], SEP))
531+ }
532+
533+
534+
535+@Callable(i)
536+func poolEvaluatePutByPriceAssetREADONLY (lpAsset,inPrAssetAmt) = {
537+ let poolAddress = addressFromStringValue(getStringByAddressOrFail(factoryDapp, keyFactoryLpAssetToPoolContractAddress(lpAsset)))
538+ let cfg = asAnyList(invoke(poolAddress, "getPoolConfigWrapperREADONLY", nil, nil))
539+ let lpAssetId = fromBase58String(asString(cfg[idxPoolLPAssetId]))
540+ let amAssetIdStr = asString(cfg[idxAmtAssetId])
541+ let amAssetId = fromBase58String(amAssetIdStr)
542+ let prAssetIdStr = asString(cfg[idxPriceAssetId])
543+ let prAssetId = fromBase58String(prAssetIdStr)
544+ let amtAssetDcm = parseIntValue(asString(cfg[idxAmtAssetDcm]))
545+ let priceAssetDcm = parseIntValue(asString(cfg[idxPriceAssetDcm]))
546+ let poolStatus = asString(cfg[idxPoolStatus])
547+ let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
548+ let amBalanceRaw = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [amAssetIdStr], nil))
549+ let prBalanceRaw = asInt(invoke(poolAddress, "getAccBalanceWrapperREADONLY", [prAssetIdStr], nil))
550+ let amBalanceRawX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [amBalanceRaw, amtAssetDcm], nil)))
551+ let prBalanceRawX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [prBalanceRaw, priceAssetDcm], nil)))
552+ let curPriceX18 = if ((poolLPBalance == 0))
553+ then zeroBigInt
554+ else parseBigIntValue(asString(invoke(poolAddress, "calcPriceBigIntWrapperREADONLY", [toString(prBalanceRawX18), toString(amBalanceRawX18)], nil)))
555+ let curPrice = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [toString(curPriceX18), MULT8], nil))
556+ let inPrAssetAmtX18 = parseBigIntValue(asString(invoke(poolAddress, "toX18WrapperREADONLY", [inPrAssetAmt, priceAssetDcm], nil)))
557+ let inAmAssetAmtX18 = fraction(inPrAssetAmtX18, MULT18, curPriceX18)
558+ let inAmAssetAmt = asInt(invoke(poolAddress, "fromX18WrapperREADONLY", [toString(inAmAssetAmtX18), amtAssetDcm], nil))
559+ let res = invoke(poolAddress, "estimatePutOperationWrapperREADONLY", ["", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false], nil)
560+ let $t02574726100 = match res {
561+ case _ =>
562+ if (if ($isInstanceOf($match0._1, "Int"))
563+ then if ($isInstanceOf($match0._3, "Int"))
564+ then if ($isInstanceOf($match0._4, "Int"))
565+ then if ($isInstanceOf($match0._5, "Int"))
566+ then $isInstanceOf($match0._6, "Int")
567+ else false
568+ else false
569+ else false
570+ else false)
571+ then {
572+ let calcLpAmt = $match0._1
573+ let curPriceCalc = $match0._3
574+ let amBalance = $match0._4
575+ let prBalance = $match0._5
576+ let lpEmission = $match0._6
577+ $Tuple5(calcLpAmt, curPriceCalc, amBalance, prBalance, lpEmission)
578+ }
579+ else throw("Couldn't cast types")
580+ }
581+ let calcLpAmt = $t02574726100._1
582+ let curPriceCalc = $t02574726100._2
583+ let amBalance = $t02574726100._3
584+ let prBalance = $t02574726100._4
585+ let lpEmission = $t02574726100._5
586+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(calcLpAmt), toString(curPrice), toString(amBalance), toString(prBalance), toString(lpEmission), poolStatus, toString(inAmAssetAmt), toString(inPrAssetAmt)], SEP))
587+ }
588+
589+
590+
591+@Callable(i)
592+func poolEvaluateGetREADONLY (paymentLpAssetId,paymentLpAmt) = {
593+ let poolAddress = addressFromStringValue(getStringByAddressOrFail(factoryDapp, keyFactoryLpAssetToPoolContractAddress(paymentLpAssetId)))
594+ let res = invoke(poolAddress, "estimateGetOperationWrapperREADONLY", ["", paymentLpAssetId, paymentLpAmt, toString(poolAddress)], nil)
595+ let $t02679527212 = match res {
596+ case _ =>
597+ if (if ($isInstanceOf($match0._1, "Int"))
598+ then if ($isInstanceOf($match0._2, "Int"))
599+ then if ($isInstanceOf($match0._5, "Int"))
600+ then if ($isInstanceOf($match0._6, "Int"))
601+ then if ($isInstanceOf($match0._7, "Int"))
602+ then if ($isInstanceOf($match0._8, "String"))
603+ then $isInstanceOf($match0._9, "String")
604+ else false
605+ else false
606+ else false
607+ else false
608+ else false
609+ else false)
610+ then {
611+ let outAmAmt = $match0._1
612+ let outPrAmt = $match0._2
613+ let amBalance = $match0._5
614+ let prBalance = $match0._6
615+ let lpEmission = $match0._7
616+ let curPrice = $match0._8
617+ let poolStatus = $match0._9
618+ $Tuple7(outAmAmt, outPrAmt, amBalance, prBalance, lpEmission, curPrice, poolStatus)
619+ }
620+ else throw("Couldn't cast types")
621+ }
622+ let outAmAmt = $t02679527212._1
623+ let outPrAmt = $t02679527212._2
624+ let amBalance = $t02679527212._3
625+ let prBalance = $t02679527212._4
626+ let lpEmission = $t02679527212._5
627+ let curPrice = $t02679527212._6
628+ let poolStatus = $t02679527212._7
629+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(outAmAmt), toString(outPrAmt), toString(amBalance), toString(prBalance), toString(lpEmission), curPrice, poolStatus], SEP))
630+ }
631+
632+
633+
634+@Callable(i)
635+func gwxUserInfoREADONLY (userAddress) = {
636+ let gwxUserInfoLIST = asAnyList(invoke(boostingDapp, "gwxUserInfoREADONLY", [userAddress], nil))
637+ let gwxAmount = asInt(gwxUserInfoLIST[0])
638+ $Tuple2(nil, makeString(["%d", toString(gwxAmount)], SEP))
311639 }
312640
313641
314642
315643 @Callable(i)
316644 func setManager (pendingManagerPublicKey) = {
317645 let checkCaller = mustManager(i)
318646 if ((checkCaller == checkCaller))
319647 then {
320648 let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
321649 if ((checkManagerPublicKey == checkManagerPublicKey))
322650 then [StringEntry(keyPendingManagerPublicKey(), pendingManagerPublicKey)]
323651 else throw("Strict value is not equal to itself.")
324652 }
325653 else throw("Strict value is not equal to itself.")
326654 }
327655
328656
329657
330658 @Callable(i)
331659 func confirmManager () = {
332660 let pm = pendingManagerPublicKeyOrUnit()
333661 let hasPM = if (isDefined(pm))
334662 then true
335663 else throw("No pending manager")
336664 if ((hasPM == hasPM))
337665 then {
338666 let checkPM = if ((i.callerPublicKey == value(pm)))
339667 then true
340668 else throw("You are not pending manager")
341669 if ((checkPM == checkPM))
342670 then [StringEntry(keyManagerPublicKey(), toBase58String(value(pm))), DeleteEntry(keyPendingManagerPublicKey())]
343671 else throw("Strict value is not equal to itself.")
344672 }
345673 else throw("Strict value is not equal to itself.")
346674 }
347675
348676
349677 @Verifier(tx)
350678 func verify () = {
351679 let targetPublicKey = match managerPublicKeyOrUnit() {
352680 case pk: ByteVector =>
353681 pk
354682 case _: Unit =>
355683 tx.senderPublicKey
356684 case _ =>
357685 throw("Match error")
358686 }
359687 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
360688 }
361689

github/deemru/w8io/026f985 
93.55 ms