tx · EKGryZBJNkvtqUa49WZ9pXvnQThXHooWS9TKRkLT4LxZ

3ND5e5puMFTnV5TfaMoyrSQYrfSZFosGJuy:  -0.01400000 Waves

2021.12.29 17:03 [1855605] smart account 3ND5e5puMFTnV5TfaMoyrSQYrfSZFosGJuy > SELF 0.00000000 Waves

{ "type": 13, "id": "EKGryZBJNkvtqUa49WZ9pXvnQThXHooWS9TKRkLT4LxZ", "fee": 1400000, "feeAssetId": null, "timestamp": 1640786590600, "version": 2, "chainId": 84, "sender": "3ND5e5puMFTnV5TfaMoyrSQYrfSZFosGJuy", "senderPublicKey": "C6iMaphKmZhNNRTWqKgEoycaCTfy6skgkLcPNxABf8aj", "proofs": [ "458me9CFqz8zCyoG6PhgqqY7yDjLVgv7dHeBkgTsE8LLT8kuLWRBdPkP24wvfr4odiaL9DbHsVBSrhs4isVo9FDq", "2f6hvnEiKG1HbuGb59FZv7kVeft1sVRazpTxo5a5kwgd291mpycZP7k3YrT781HVH7c12Q6EDweSgS9ZADMRYSKR" ], "script": "base64:AAIFAAAAAAAAD2cIAhIDCgEEEgcKBQEBCAgEEgMKAQESAwoBARIAEgMKAQESABIAEgMKAQESBQoDBAEIEgAaFAoBQRIPa2V5QWRtaW5QdWJLZXkyGhQKAUISD2tleUFkbWluUHViS2V5MxoLCgFDEgZvcmFjbGUaEAoBRBILZ2V0QWRtaW5QdWIaEAoBRRILa2V5QWRtaW5QdWIaDAoBRhIHJG1hdGNoMBoLCgFHEgZzdHJpbmcaDAoBSBIHbm90aGluZxoRCgFJEgxhZG1pblB1YktleTEaEQoBShIMYWRtaW5QdWJLZXkyGhEKAUsSDGFkbWluUHViS2V5MxoZCgFMEhRhZG1pblB1YktleVN0YXJ0U3RvcBoXCgFNEhJhZG1pblB1YktleVN0YWtpbmcaEgoBThINd2FsbGV0QWRkcmVzcxoSCgFPEg12b3RpbmdBZGRyZXNzGgkKAVASBFVTRE4aCQoBURIETlNCVBoJCgFSEgRFVVJOGhIKAVMSDXN0YWtpbmdBc3NldHMaGwoBVBIWc3Rha2luZ1VTRE5OU0JUQWRkcmVzcxoXCgFVEhJzdGFraW5nRVVSTkFkZHJlc3MaGQoBVhIUVVNETlRvV2F2ZXNFeGNoYW5nZXIaGAoBVxITVVNETlRvTlNCVEV4Y2hhbmdlchoPCgFYEgpiYXNlUGVyaW9kGhAKAVkSC3N0YXJ0SGVpZ2h0GhEKAVoSDHBlcmlvZExlbmd0aBoMCgFhEgd2ZXJzaW9uGhMKAmFBEg1zdGFrZWRBbW91bnRCGhAKAmFCEgphc3NldEluaXRBGhAKAmFDEgphc3NldEluaXRCGhcKAmFEEhFhdmFpbGFibGVCYWxhbmNlQRoXCgJhRRIRYXZhaWxhYmxlQmFsYW5jZUIaHwoCYUYSGWFjY291bnRCYWxhbmNlV2l0aFN0YWtlZEEaHwoCYUcSGWFjY291bnRCYWxhbmNlV2l0aFN0YWtlZEIaFgoCYUgSEGhhc0Vub3VnaEJhbGFuY2UaEgoCYUkSDGdldEFzc2V0SW5mbxoOCgJhShIIc3RyaW5nSWQaCgoCYUsSBGluZm8aHAoCYUwSFmdldEFzc2V0SW5mb0Zyb21TdHJpbmcaDgoCYU0SCGFzc2V0U3RyGg0KAmFOEgdzdXNwZW5kGgsKAmFPEgVjYXVzZRoeCgJhUBIYY2FsY1N0YWtpbmdGdW5jQW5kQWRkcmVzGgsKAmFREgVzdGFrZRoXCgJhUhIRY2FsY1N0YWtpbmdQYXJhbXMaDAoCYVMSBmFtb3VudBoRCgJhVBILJHQwNjkzMDY5OTYaCgoCYVUSBGNhbGwaEQoCYVYSC3N0YWtpbmdBZGRyGhEKAmFXEgskdDA3MDgyNzE0OBonCgJhWBIhdGhyb3dJbnN1ZmZpY2llbnRBdmFpbGFibGVCYWxhbmNlGg8KAmFZEglhdmFpbGFibGUaDwoCYVoSCWFzc2V0TmFtZRobCgJhYRIVZmlyc3RIYXJ2ZXN0RW5kUGVyaW9kGg4KAmFiEghpc0FjdGl2ZRoRCgJhYxILc3RyQXNzZXRJZEEaEQoCYWQSC3N0ckFzc2V0SWRCGg4KAmFlEghhc3NldElkQRoOCgJhZhIIYXNzZXRJZEIaEAoCYWcSCmFzc2V0TmFtZUEaCAoCYWgSAmlkGgsKAmFpEgV3YXZlcxoQCgJhahIKYXNzZXROYW1lQhoOCgJhaxIIYmFsYW5jZUEaDgoCYWwSCGJhbGFuY2VCGhIKAmFtEgxzaGFyZUFzc2V0SWQaFgoCYW4SEHNoYXJlQXNzZXRTdXBwbHkaEAoCYW8SCmNvbW1pc3Npb24aHgoCYXASGGNvbW1pc3Npb25TY2FsZURlbGltaXRlchoRCgJhcRILc2NhbGVWYWx1ZTMaEQoCYXISC3NjYWxlVmFsdWU4GiAKAmFzEhpzbGlwcGFnZVRvbGVyYW5jZURlbGltaXRlchoUCgJhdBIOYWNjb3VudEJhbGFuY2UaDQoCYXUSB2Fzc2V0SWQaEgoCYXYSDHN0YWtlZEFtb3VudBocCgJhdxIWc3Rha2VkQW1vdW50Q2FsY3VsYXRlZBoJCgJheBIDYUlkGgcKAmF5EgFpGhMKAmF6Eg1zdGFrZWRBbW91bnRBGg8KAWISCmtleVZlcnNpb24aEAoCYkESCnNoYXJlSXNzdWUaEgoCYkISDHNoYXJlSXNzdWVJZBoMCgJiQxIGc3Rha2UxGgwKAmJEEgZzdGFrZTIaDwoCYkUSCWJhc2VFbnRyeRoPCgJiRhIJYW10QXNzZXRBGg8KAmJHEglhbXRBc3NldEIaEwoCYkgSDSR0MDExMjQ3MTEzMzQaEwoCYkkSDSR0MDExMzM5MTE0MjYaEAoCYkoSCnNoYXJlTGltaXQaFwoCYksSEXNsaXBwYWdlVG9sZXJhbmNlGhMKAmJMEg0kdDAxMzkyMzE0MDAwGhMKAmJNEg0kdDAxNDAwNTE0MDgyGhAKAmJOEgp0b2tlblJhdGlvGhkKAmJPEhNyYXRpb1NoYXJlVG9rZW5zSW5BGhkKAmJQEhNyYXRpb1NoYXJlVG9rZW5zSW5CGhsKAmJREhVzaGFyZVRva2VuVG9QYXlBbW91bnQaEwoCYlISDSR0MDE5MjUxMTkzMjYaDwoCYlMSCXBtdEFtb3VudBoQCgJiVBIKcG10QXNzZXRJZBoSCgJiVRIMYW1vdW50VG9QYXlBGhIKAmJWEgxhbW91bnRUb1BheUIaGAoCYlcSEm1pbkFtb3VudFRvUmVjZWl2ZRoTCgJiWBINJHQwMjA4NDEyMDkxNhoTCgJiWRINY2FsY3VsYXRlRmVlcxoPCgJiWhIJdG9rZW5Gcm9tGigKAmJhEiJ0aHJvd0luc3VmZmljaWVudEF2YWlsYWJsZUJhbGFuY2VzGg0KAmJiEgdhbW91bnRBGg0KAmJjEgdhbW91bnRCGhcKAmJkEhFzdXNwZW5kU3VzcGljaW91cxoSCgJiZRIMZmlyc3RIYXJ2ZXN0GhEKAmJmEgskdDA4MzM1ODQxMhoQCgJiZxIKcG10QW1vdW50QRoRCgJiaBILcG10QXNzZXRJZEEaEQoCYmkSCyR0MDg0MTc4NDk0GhAKAmJqEgpwbXRBbW91bnRCGhEKAmJrEgtwbXRBc3NldElkQhoRCgJibBILJHQwODQ5OTg1NzYaFAoCYm0SDnBtdFN0ckFzc2V0SWRBGhMKAmJuEg1wbXRBc3NldE5hbWVBGhIKAmJvEgxwbXREZWNpbWFsc0EaEQoCYnASCyR0MDg1ODE4NjU4GhQKAmJxEg5wbXRTdHJBc3NldElkQhoTCgJichINcG10QXNzZXROYW1lQhoSCgJicxIMcG10RGVjaW1hbHNCGg8KAmJ0EglzaGFyZU5hbWUaFgoCYnUSEHNoYXJlRGVzY3JpcHRpb24aEwoCYnYSDXNoYXJlRGVjaW1hbHMaCgoCYncSBGFyZzEaCgoCYngSBGFyZzIaCgoCYnkSBGFyZzMaGAoCYnoSEnNoYXJlSW5pdGlhbFN1cHBseRoOCgFjEglrZXlBY3RpdmUaDgoCY0ESCHBheW1lbnRzGgkKAmNCEgNpbnYaCAoCY0MSAnR4GgwKAmNEEgZ2ZXJpZnkaGQoCY0USE211bHRpU2lnbmVkQnlBZG1pbnMaGAoCY0YSEmFkbWluUHViS2V5MVNpZ25lZBoYCgJjRxISYWRtaW5QdWJLZXkyU2lnbmVkGhgKAmNIEhJhZG1pblB1YktleTNTaWduZWQaGQoCY0kSE2NhbGxUYWtlSW50b0FjY291bnQaFQoCY0oSD2V4Y2hhbmdlVG9XYXZlcxoVCgJjSxIPZXhjaGFuZ2VUb05TQlRzGhMKAmNMEg1zaWduZWRCeUFkbWluGg0KAmNhEgd0b2tlblRvGhYKAmNiEhBhbW91bnRXaXRob3V0RmVlGhMKAmNjEg1hbW91bnRXaXRoRmVlGhYKAmNkEhBnb3Zlcm5hbmNlUmV3YXJkGhEKAmNlEgthc3NldElkU2VuZBoTCgJjZhINJHQwMjIxOTAyMjI4MRoRCgJjZxILbmV3QmFsYW5jZUEaEQoCY2gSC25ld0JhbGFuY2VCGhMKAmNpEg0kdDAyMzIzNjIzMzI3GhEKAmNqEgthbW91bnRMZWF2ZRojCgJjaxIddW5jb3VudGFibGVBbW91bnRFbnJvbGxBc3NldEEaIwoCY2wSHXVuY291bnRhYmxlQW1vdW50RW5yb2xsQXNzZXRCGhMKAmNtEg1hbW91bnRFbnJvbGxBGhMKAmNuEg1hbW91bnRFbnJvbGxCGhMKAmNvEg1hc3NldElkU3RyaW5nGgoKAmNwEgRwb29sGg8KAmNxEglsZWFzaW5nSWQaEwoCY3ISDWxlYXNpbmdBbW91bnQaFAoCY3MSDm5ld0xlYXNlQW1vdW50Gg4KAmN0EghuZXdMZWFzZRoQCgJjdRIKbmV3TGVhc2VJZBoOCgJjdhIIYmFzZUV0cnkaCQoCY3cSA2xJZBoTCgJjeBINJHQwMjc5MzEyODAzNBoKCgJjeRIEYWRkchoMCgJjehIGcGFyYW1zGhAKAWQSC2tleUFzc2V0SWRBGhAKAWUSC2tleUFzc2V0SWRCGhAKAWYSC2tleUJhbGFuY2VBGhAKAWcSC2tleUJhbGFuY2VCGhQKAWgSD2tleUJhbGFuY2VJbml0QRoUCgFpEg9rZXlCYWxhbmNlSW5pdEIaFAoBahIPa2V5U2hhcmVBc3NldElkGhgKAWsSE2tleVNoYXJlQXNzZXRTdXBwbHkaEgoBbBINa2V5Q29tbWlzc2lvbhogCgFtEhtrZXlDb21taXNzaW9uU2NhbGVEZWxpbWl0ZXIaDQoBbhIIa2V5Q2F1c2UaFAoBbxIPa2V5Rmlyc3RIYXJ2ZXN0GhoKAXASFWtleUZpcnN0SGFydmVzdEhlaWdodBoQCgFxEgtrU2hhcmVMaW1pdBoQCgFyEgtrQmFzZVBlcmlvZBoSCgFzEg1rUGVyaW9kTGVuZ3RoGhEKAXQSDGtTdGFydEhlaWdodBoXCgF1EhJrZXlVU0ROTlNCVEFkZHJlc3MaEwoBdhIOa2V5RVVSTkFkZHJlc3MaEwoBdxIOa2V5TGVhc2luZ1Bvb2waFQoBeBIQa2V5TGVhc2luZ0Ftb3VudBoRCgF5EgxrZXlMZWFzaW5nSWQaFAoBehIPa2V5QWRtaW5QdWJLZXkxAAAAVAAAAAABYQIAAAAFMS4wLjAAAAAAAWICAAAAB3ZlcnNpb24AAAAAAWMCAAAABmFjdGl2ZQAAAAABZAIAAAAKQV9hc3NldF9pZAAAAAABZQIAAAAKQl9hc3NldF9pZAAAAAABZgIAAAAPQV9hc3NldF9iYWxhbmNlAAAAAAFnAgAAAA9CX2Fzc2V0X2JhbGFuY2UAAAAAAWgCAAAADEFfYXNzZXRfaW5pdAAAAAABaQIAAAAMQl9hc3NldF9pbml0AAAAAAFqAgAAAA5zaGFyZV9hc3NldF9pZAAAAAABawIAAAASc2hhcmVfYXNzZXRfc3VwcGx5AAAAAAFsAgAAAApjb21taXNzaW9uAAAAAAFtAgAAABpjb21taXNzaW9uX3NjYWxlX2RlbGltaXRlcgAAAAABbgIAAAAOc2h1dGRvd25fY2F1c2UAAAAAAW8CAAAADWZpcnN0X2hhcnZlc3QAAAAAAXACAAAAFGZpcnN0X2hhcnZlc3RfaGVpZ2h0AAAAAAFxAgAAABxzaGFyZV9saW1pdF9vbl9maXJzdF9oYXJ2ZXN0AAAAAAFyAgAAAAtiYXNlX3BlcmlvZAAAAAABcwIAAAANcGVyaW9kX2xlbmd0aAAAAAABdAIAAAAMc3RhcnRfaGVpZ2h0AAAAAAF1AgAAABhzdGFraW5nX3VzZG5uc2J0X2FkZHJlc3MAAAAAAXYCAAAAFHN0YWtp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", "height": 1855605, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: B3aeZjkppFCCQPDZVgtcLiCbhhtdB7VczeQ6uvCdDJKA Next: 486qMbpXFGSkkC1biqL7VnqquwU4Y6NAHQRyJH4kF4hx Diff:
OldNewDifferences
4141
4242 let kStartHeight = "start_height"
4343
44-let kFirstHarvestHeight = "first_harvest_height"
44+let keyUSDNNSBTAddress = "staking_usdnnsbt_address"
45+
46+let keyEURNAddress = "staking_eurn_address"
47+
48+let keyLeasingPool = "leasing_address"
49+
50+let keyLeasingAmount = "leasing_amount"
51+
52+let keyLeasingId = "leasing_id"
4553
4654 let keyAdminPubKey1 = "admin_pub_1"
4755
7785
7886 let NSBT = base58'36mg8NZTaFRDygiVwb8uBnLR51hetJruUCZcxhaVcHj9'
7987
80-let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
81-
8288 let EURN = base58'ECBCkHS68DckpBrzLeoRgYbFg7sCVqR176mPqbXsj9pA'
8389
84-let stakingUSDNNSBTAddress = Address(base58'3N6q7sCGSSLBUXDdjBdYGTJbZGZfhhh8cNg')
90+let stakingAssets = ["WAVES", toBase58String(USDN), toBase58String(NSBT), toBase58String(EURN)]
8591
86-let stakingEURNAddress = Address(base58'3MyVqAbmKWh339gF6hy8faWw1jGeTV2wnGE')
92+let stakingUSDNNSBTAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyUSDNNSBTAddress), "no usdn staking address")))
8793
88-let USDNToWavesExchanger = Address(base58'3N77kfPbQyjXWpDALX3xjKw3iEGMWEctV37')
94+let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no usdn staking address")))
8995
90-let USDNToNSBTExchanger = Address(base58'3Mye9wVR7d2mc6Y5ZJTu11svzgUQ7o8H9dA')
96+let USDNToWavesExchanger = Address(base58'3N8PGkzXhbtTvEwEQTtE2xiTJmsDEQ9XfoZ')
9197
92-let stakingFeeInUSDN = 270000
93-
94-let stakingFeeInEURN = 234000
98+let USDNToNSBTExchanger = Address(base58'3MqW1t2cxdYy2emEMk3YtZkRwQPhHaTfWRe')
9599
96100 let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
97101
143147
144148 let commission = 3000
145149
146-let commissionGovernance = 1200
147-
148150 let commissionScaleDelimiter = 1000000
149151
150152 let scaleValue3 = 1000
152154 let scaleValue8 = 100000000
153155
154156 let slippageToleranceDelimiter = 1000
155-
156-let scaleValue8Digits = 8
157157
158158 func accountBalance (assetId) = match assetId {
159159 case id: ByteVector =>
176176 then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
177177 else 0
178178 case _: Unit =>
179- 0
179+ valueOrElse(getInteger(this, keyLeasingAmount), 0)
180180 case _ =>
181181 throw("Match error")
182182 }
234234 func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
235235
236236
237-func deductStakingFee (amount,assetId,secondAssetId) = if (if ((assetId == USDN))
238- then true
239- else (assetId == EURN))
240- then {
241- let stakinFee = if ((assetId == USDN))
242- then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
243- then 2
244- else 1))
245- else if ((assetId == EURN))
246- then stakingFeeInEURN
247- else 0
248- let result = (amount - stakinFee)
249- if ((0 >= result))
250- then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakinFee)) + "USDN/EURN"))
251- else result
252- }
253- else amount
237+func calcStakingFuncAndAddres (stake,assetId) = if (stake)
238+ then if ((assetId == USDN))
239+ then $Tuple2("lockNeutrino", stakingUSDNNSBTAddress)
240+ else if ((assetId == NSBT))
241+ then $Tuple2("lockNsbt", stakingUSDNNSBTAddress)
242+ else $Tuple2("startStaking", stakingEURNAddress)
243+ else if ((assetId == USDN))
244+ then $Tuple2("unlockNeutrino", stakingUSDNNSBTAddress)
245+ else if ((assetId == NSBT))
246+ then $Tuple2("unlockNsbt", stakingUSDNNSBTAddress)
247+ else $Tuple2("stopStaking", stakingEURNAddress)
254248
255249
256-func getStakingFee (assetId,secondAssetId) = if ((assetId == USDN))
257- then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
258- then 2
259- else 1))
260- else if ((assetId == EURN))
261- then stakingFeeInEURN
262- else 0
250+func calcStakingParams (stake,amount,assetId) = if (stake)
251+ then {
252+ let $t069306996 = calcStakingFuncAndAddres(stake, assetId)
253+ let call = $t069306996._1
254+ let stakingAddr = $t069306996._2
255+ $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
256+ }
257+ else {
258+ let $t070827148 = calcStakingFuncAndAddres(stake, assetId)
259+ let call = $t070827148._1
260+ let stakingAddr = $t070827148._2
261+ $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
262+ }
263263
264264
265265 func throwInsufficientAvailableBalance (amount,available,assetName) = throw((((((((("Insufficient DApp balance to pay " + toString(amount)) + " ") + assetName) + " due to staking. Available: ") + toString(available)) + " ") + assetName) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
273273
274274 @Callable(i)
275275 func init (firstHarvest) = {
276- let $t080018078 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
277- let pmtAmountA = $t080018078._1
278- let pmtAssetIdA = $t080018078._2
279- let $t080838160 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
280- let pmtAmountB = $t080838160._1
281- let pmtAssetIdB = $t080838160._2
282- let $t081658242 = getAssetInfo(pmtAssetIdA)
283- let pmtStrAssetIdA = $t081658242._1
284- let pmtAssetNameA = $t081658242._2
285- let pmtDecimalsA = $t081658242._3
286- let $t082478324 = getAssetInfo(pmtAssetIdB)
287- let pmtStrAssetIdB = $t082478324._1
288- let pmtAssetNameB = $t082478324._2
289- let pmtDecimalsB = $t082478324._3
276+ let $t083358412 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
277+ let pmtAmountA = $t083358412._1
278+ let pmtAssetIdA = $t083358412._2
279+ let $t084178494 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
280+ let pmtAmountB = $t084178494._1
281+ let pmtAssetIdB = $t084178494._2
282+ let $t084998576 = getAssetInfo(pmtAssetIdA)
283+ let pmtStrAssetIdA = $t084998576._1
284+ let pmtAssetNameA = $t084998576._2
285+ let pmtDecimalsA = $t084998576._3
286+ let $t085818658 = getAssetInfo(pmtAssetIdB)
287+ let pmtStrAssetIdB = $t085818658._1
288+ let pmtAssetNameB = $t085818658._2
289+ let pmtDecimalsB = $t085818658._3
290290 if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
291291 then throw("Only admin can call this function")
292292 else if (isDefined(getBoolean(this, keyActive)))
303303 let shareInitialSupply = fraction(arg1, arg2, arg3)
304304 let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
305305 let shareIssueId = calculateAssetId(shareIssue)
306- let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
307- if (firstHarvest)
308- then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
309- else baseEntry
306+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
307+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
308+ else 0
309+ if ((stake1 == stake1))
310+ then {
311+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
312+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
313+ else 0
314+ if ((stake2 == stake2))
315+ then {
316+ let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
317+ if (firstHarvest)
318+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
319+ else baseEntry
320+ }
321+ else throw("Strict value is not equal to itself.")
322+ }
323+ else throw("Strict value is not equal to itself.")
310324 }
311325 }
312326
314328
315329 @Callable(i)
316330 func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
317- let $t01056910656 = getAssetInfoFromString(strAssetIdA)
318- let pmtStrAssetIdA = $t01056910656._1
319- let pmtAssetNameA = $t01056910656._2
320- let pmtDecimalsA = $t01056910656._3
321- let $t01066110748 = getAssetInfoFromString(strAssetIdB)
322- let pmtStrAssetIdB = $t01066110748._1
323- let pmtAssetNameB = $t01066110748._2
324- let pmtDecimalsB = $t01066110748._3
331+ let $t01124711334 = getAssetInfoFromString(strAssetIdA)
332+ let pmtStrAssetIdA = $t01124711334._1
333+ let pmtAssetNameA = $t01124711334._2
334+ let pmtDecimalsA = $t01124711334._3
335+ let $t01133911426 = getAssetInfoFromString(strAssetIdB)
336+ let pmtStrAssetIdB = $t01133911426._1
337+ let pmtAssetNameB = $t01133911426._2
338+ let pmtDecimalsB = $t01133911426._3
325339 if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
326340 then throw("Only admin can call this function")
327341 else if (isDefined(getBoolean(this, keyActive)))
357371 func replenishWithTwoTokens (slippageTolerance) = {
358372 let pmtAssetIdA = i.payments[0].assetId
359373 let pmtAssetIdB = i.payments[1].assetId
360- let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA, pmtAssetIdB)
361- let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB, pmtAssetIdA)
374+ let pmtAmountA = i.payments[0].amount
375+ let pmtAmountB = i.payments[1].amount
376+ let $t01392314000 = getAssetInfo(pmtAssetIdA)
377+ let pmtStrAssetIdA = $t01392314000._1
378+ let pmtAssetNameA = $t01392314000._2
379+ let pmtDecimalsA = $t01392314000._3
380+ let $t01400514082 = getAssetInfo(pmtAssetIdB)
381+ let pmtStrAssetIdB = $t01400514082._1
382+ let pmtAssetNameB = $t01400514082._2
383+ let pmtDecimalsB = $t01400514082._3
362384 if (if ((balanceA == 0))
363385 then (balanceB == 0)
364386 else false)
365387 then {
366- let $t01345913536 = getAssetInfo(pmtAssetIdA)
367- let pmtStrAssetIdA = $t01345913536._1
368- let pmtAssetNameA = $t01345913536._2
369- let pmtDecimalsA = $t01345913536._3
370- let $t01354513622 = getAssetInfo(pmtAssetIdB)
371- let pmtStrAssetIdB = $t01354513622._1
372- let pmtAssetNameB = $t01354513622._2
373- let pmtDecimalsB = $t01354513622._3
374388 let tokenRatio = fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
375389 if ((pmtAssetIdA == pmtAssetIdB))
376390 then throw("Assets must be different")
397411 then throw("Too small amount to replenish")
398412 else if (!(hasEnoughBalance))
399413 then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
400- else [Reissue(shareAssetId, shareInitialSupply, true), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareAssetId)]
414+ else {
415+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
416+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
417+ else 0
418+ if ((stake1 == stake1))
419+ then {
420+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
421+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
422+ else 0
423+ if ((stake2 == stake2))
424+ then [Reissue(shareAssetId, shareInitialSupply, true), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareAssetId)]
425+ else throw("Strict value is not equal to itself.")
426+ }
427+ else throw("Strict value is not equal to itself.")
428+ }
401429 }
402430 }
403431 else {
425453 then throw("Too small amount to replenish")
426454 else if (!(hasEnoughBalance))
427455 then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
428- else [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
456+ else {
457+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
458+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
459+ else 0
460+ if ((stake1 == stake1))
461+ then {
462+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
463+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
464+ else 0
465+ if ((stake2 == stake2))
466+ then [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
467+ else throw("Strict value is not equal to itself.")
468+ }
469+ else throw("Strict value is not equal to itself.")
470+ }
429471 }
430472 }
431473
433475
434476 @Callable(i)
435477 func withdraw () = {
436- let $t01802118171 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
437- let pmtAmount = $t01802118171._1
438- let pmtAssetId = $t01802118171._2
439- let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA, assetIdB)
440- let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB, assetIdA)
478+ let $t01925119326 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
479+ let pmtAmount = $t01925119326._1
480+ let pmtAssetId = $t01925119326._2
481+ let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
482+ let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
441483 if (!(isActive))
442484 then throw("DApp is inactive at this moment")
443485 else if ((size(i.payments) != 1))
450492 then true
451493 else (amountToPayB > availableBalanceB))
452494 then throwInsufficientAvailableBalances(amountToPayA, amountToPayB)
453- else [IntegerEntry(keyBalanceA, (balanceA - amountToPayA)), IntegerEntry(keyBalanceB, (balanceB - amountToPayB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply - pmtAmount)), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
495+ else {
496+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
497+ then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
498+ else 0
499+ if ((stake1 == stake1))
500+ then {
501+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
502+ then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
503+ else 0
504+ if ((stake2 == stake2))
505+ then [IntegerEntry(keyBalanceA, (balanceA - amountToPayA)), IntegerEntry(keyBalanceB, (balanceB - amountToPayB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply - pmtAmount)), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
506+ else throw("Strict value is not equal to itself.")
507+ }
508+ else throw("Strict value is not equal to itself.")
509+ }
454510 }
455511
456512
457513
458514 @Callable(i)
459515 func exchange (minAmountToReceive) = {
460- let $t01939719472 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
461- let pmtAmount = $t01939719472._1
462- let pmtAssetId = $t01939719472._2
516+ let $t02084120916 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
517+ let pmtAmount = $t02084120916._1
518+ let pmtAssetId = $t02084120916._2
463519 func calculateFees (tokenFrom,tokenTo) = {
464520 let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
465521 let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
484540 else if ((pmtAssetId == assetIdA))
485541 then {
486542 let assetIdSend = assetIdB
487- let $t02074620837 = calculateFees(balanceA, balanceB)
488- let amountWithoutFee = $t02074620837._1
489- let amountWithFee = $t02074620837._2
490- let governanceReward = $t02074620837._3
543+ let $t02219022281 = calculateFees(balanceA, balanceB)
544+ let amountWithoutFee = $t02219022281._1
545+ let amountWithFee = $t02219022281._2
546+ let governanceReward = $t02219022281._3
491547 let newBalanceA = (balanceA + pmtAmount)
492548 let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
493- if (if ((stakedAmountA >= newBalanceA))
494- then true
495- else (stakedAmountB >= newBalanceB))
496- then throwInsufficientAvailableBalance(amountWithFee, availableBalanceB, assetNameB)
497- else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
549+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
550+ then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdA], nil)
551+ else 0
552+ if ((stake1 == stake1))
553+ then {
554+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
555+ then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdB], nil)
556+ else 0
557+ if ((stake2 == stake2))
558+ then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
559+ else throw("Strict value is not equal to itself.")
560+ }
561+ else throw("Strict value is not equal to itself.")
498562 }
499563 else if ((pmtAssetId == assetIdB))
500564 then {
501565 let assetIdSend = assetIdA
502- let $t02165621747 = calculateFees(balanceB, balanceA)
503- let amountWithoutFee = $t02165621747._1
504- let amountWithFee = $t02165621747._2
505- let governanceReward = $t02165621747._3
566+ let $t02323623327 = calculateFees(balanceB, balanceA)
567+ let amountWithoutFee = $t02323623327._1
568+ let amountWithFee = $t02323623327._2
569+ let governanceReward = $t02323623327._3
506570 let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
507571 let newBalanceB = (balanceB + pmtAmount)
508572 if (if ((stakedAmountA >= newBalanceA))
509573 then true
510574 else (stakedAmountB >= newBalanceB))
511575 then throwInsufficientAvailableBalance(amountWithFee, availableBalanceA, assetNameA)
512- else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
576+ else {
577+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
578+ then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdA], nil)
579+ else 0
580+ if ((stake1 == stake1))
581+ then {
582+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
583+ then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdB], nil)
584+ else 0
585+ if ((stake2 == stake2))
586+ then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
587+ else throw("Strict value is not equal to itself.")
588+ }
589+ else throw("Strict value is not equal to itself.")
590+ }
513591 }
514592 else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
515593 }
558636 then true
559637 else (0 > amountEnrollB))
560638 then throw("Too large amountLeave")
561- else [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
639+ else {
640+ let stake1 = if (if (containsElement(stakingAssets, strAssetIdA))
641+ then (amountEnrollA > 0)
642+ else false)
643+ then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
644+ else 0
645+ if ((stake1 == stake1))
646+ then {
647+ let stake2 = if (if (containsElement(stakingAssets, strAssetIdB))
648+ then (amountEnrollB > 0)
649+ else false)
650+ then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
651+ else 0
652+ if ((stake2 == stake2))
653+ then [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
654+ else throw("Strict value is not equal to itself.")
655+ }
656+ else throw("Strict value is not equal to itself.")
657+ }
562658 }
659+
660+
661+
662+@Callable(i)
663+func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
664+ then throw("Only contract itself can invoke this function")
665+ else if ((assetIdString == "WAVES"))
666+ then {
667+ let pool = addressFromStringValue(valueOrErrorMessage(getString(oracle, keyLeasingPool), "No leasing pool in oracle"))
668+ let leasingId = getBinary(this, keyLeasingId)
669+ let leasingAmount = valueOrElse(getInteger(this, keyLeasingAmount), 0)
670+ let newLeaseAmount = if (stake)
671+ then (leasingAmount + amount)
672+ else (leasingAmount - amount)
673+ let newLease = Lease(pool, newLeaseAmount)
674+ let newLeaseId = calculateLeaseId(newLease)
675+ let baseEtry = [newLease, BinaryEntry(keyLeasingId, newLeaseId), IntegerEntry(keyLeasingAmount, newLeaseAmount)]
676+ match leasingId {
677+ case lId: ByteVector =>
678+ ([LeaseCancel(lId)] ++ baseEtry)
679+ case _ =>
680+ baseEtry
681+ }
682+ }
683+ else {
684+ let $t02793128034 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
685+ let call = $t02793128034._1
686+ let addr = $t02793128034._2
687+ let params = $t02793128034._3
688+ let payments = $t02793128034._4
689+ let inv = invoke(addr, call, params, payments)
690+ nil
691+ }
692+
693+
694+
695+@Callable(i)
696+func stakeAll () = if (!(isActive))
697+ then throw("DApp is inactive at this moment")
698+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
699+ then throw("Only admin can call this function")
700+ else {
701+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
702+ then {
703+ let amountA = (balanceA - stakedAmountA)
704+ if ((amountA > 0))
705+ then invoke(this, "stakeUnstake", [true, amountA, strAssetIdA], nil)
706+ else 0
707+ }
708+ else 0
709+ if ((stake1 == stake1))
710+ then {
711+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
712+ then {
713+ let amountB = (balanceB - stakedAmountB)
714+ if ((amountB > 0))
715+ then invoke(this, "stakeUnstake", [true, amountB, strAssetIdB], nil)
716+ else 0
717+ }
718+ else 0
719+ if ((stake2 == stake2))
720+ then nil
721+ else throw("Strict value is not equal to itself.")
722+ }
723+ else throw("Strict value is not equal to itself.")
724+ }
563725
564726
565727 @Verifier(tx)
581743 let callTakeIntoAccount = if ((inv.dApp == this))
582744 then (inv.function == "takeIntoAccountExtraFunds")
583745 else false
584- let callStaking = if (if ((inv.dApp == stakingUSDNNSBTAddress))
585- then if (if (if (containsElement(["lockNeutrino", "lockNsbt"], inv.function))
586- then (size(inv.payments) == 1)
587- else false)
588- then if ((inv.payments[0].assetId == USDN))
589- then true
590- else (inv.payments[0].assetId == NSBT)
591- else false)
592- then true
593- else if (containsElement(["unlockNeutrino", "unlockNsbt"], inv.function))
594- then (size(inv.payments) == 0)
595- else false
596- else false)
597- then true
598- else if ((inv.dApp == stakingEURNAddress))
599- then if (if (if ((inv.function == "startStaking"))
600- then (size(inv.payments) == 1)
601- else false)
602- then (inv.payments[0].assetId == EURN)
603- else false)
604- then true
605- else if ((inv.function == "stopStaking"))
606- then (size(inv.payments) == 0)
607- else false
608- else false
609746 let exchangeToWaves = if (if (if ((inv.dApp == USDNToWavesExchanger))
610747 then (inv.function == "exchange")
611748 else false)
635772 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
636773 then true
637774 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyStaking)
638- if (if (if (if (if (callTakeIntoAccount)
639- then true
640- else callStaking)
775+ if (if (if (if (callTakeIntoAccount)
641776 then true
642777 else exchangeToWaves)
643778 then true
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let version = "1.0.0"
55
66 let keyVersion = "version"
77
88 let keyActive = "active"
99
1010 let keyAssetIdA = "A_asset_id"
1111
1212 let keyAssetIdB = "B_asset_id"
1313
1414 let keyBalanceA = "A_asset_balance"
1515
1616 let keyBalanceB = "B_asset_balance"
1717
1818 let keyBalanceInitA = "A_asset_init"
1919
2020 let keyBalanceInitB = "B_asset_init"
2121
2222 let keyShareAssetId = "share_asset_id"
2323
2424 let keyShareAssetSupply = "share_asset_supply"
2525
2626 let keyCommission = "commission"
2727
2828 let keyCommissionScaleDelimiter = "commission_scale_delimiter"
2929
3030 let keyCause = "shutdown_cause"
3131
3232 let keyFirstHarvest = "first_harvest"
3333
3434 let keyFirstHarvestHeight = "first_harvest_height"
3535
3636 let kShareLimit = "share_limit_on_first_harvest"
3737
3838 let kBasePeriod = "base_period"
3939
4040 let kPeriodLength = "period_length"
4141
4242 let kStartHeight = "start_height"
4343
44-let kFirstHarvestHeight = "first_harvest_height"
44+let keyUSDNNSBTAddress = "staking_usdnnsbt_address"
45+
46+let keyEURNAddress = "staking_eurn_address"
47+
48+let keyLeasingPool = "leasing_address"
49+
50+let keyLeasingAmount = "leasing_amount"
51+
52+let keyLeasingId = "leasing_id"
4553
4654 let keyAdminPubKey1 = "admin_pub_1"
4755
4856 let keyAdminPubKey2 = "admin_pub_2"
4957
5058 let keyAdminPubKey3 = "admin_pub_3"
5159
5260 let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9')
5361
5462 func getAdminPub (keyAdminPub) = match getString(oracle, keyAdminPub) {
5563 case string: String =>
5664 fromBase58String(string)
5765 case nothing =>
5866 throw("Admin public key is empty")
5967 }
6068
6169
6270 let adminPubKey1 = getAdminPub(keyAdminPubKey1)
6371
6472 let adminPubKey2 = getAdminPub(keyAdminPubKey2)
6573
6674 let adminPubKey3 = getAdminPub(keyAdminPubKey3)
6775
6876 let adminPubKeyStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
6977
7078 let adminPubKeyStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
7179
7280 let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
7381
7482 let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
7583
7684 let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
7785
7886 let NSBT = base58'36mg8NZTaFRDygiVwb8uBnLR51hetJruUCZcxhaVcHj9'
7987
80-let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
81-
8288 let EURN = base58'ECBCkHS68DckpBrzLeoRgYbFg7sCVqR176mPqbXsj9pA'
8389
84-let stakingUSDNNSBTAddress = Address(base58'3N6q7sCGSSLBUXDdjBdYGTJbZGZfhhh8cNg')
90+let stakingAssets = ["WAVES", toBase58String(USDN), toBase58String(NSBT), toBase58String(EURN)]
8591
86-let stakingEURNAddress = Address(base58'3MyVqAbmKWh339gF6hy8faWw1jGeTV2wnGE')
92+let stakingUSDNNSBTAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyUSDNNSBTAddress), "no usdn staking address")))
8793
88-let USDNToWavesExchanger = Address(base58'3N77kfPbQyjXWpDALX3xjKw3iEGMWEctV37')
94+let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no usdn staking address")))
8995
90-let USDNToNSBTExchanger = Address(base58'3Mye9wVR7d2mc6Y5ZJTu11svzgUQ7o8H9dA')
96+let USDNToWavesExchanger = Address(base58'3N8PGkzXhbtTvEwEQTtE2xiTJmsDEQ9XfoZ')
9197
92-let stakingFeeInUSDN = 270000
93-
94-let stakingFeeInEURN = 234000
98+let USDNToNSBTExchanger = Address(base58'3MqW1t2cxdYy2emEMk3YtZkRwQPhHaTfWRe')
9599
96100 let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
97101
98102 let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
99103
100104 let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
101105
102106 let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
103107
104108 let isActive = getBooleanValue(this, keyActive)
105109
106110 let strAssetIdA = getStringValue(this, keyAssetIdA)
107111
108112 let strAssetIdB = getStringValue(this, keyAssetIdB)
109113
110114 let assetIdA = if ((strAssetIdA == "WAVES"))
111115 then unit
112116 else fromBase58String(strAssetIdA)
113117
114118 let assetIdB = if ((strAssetIdB == "WAVES"))
115119 then unit
116120 else fromBase58String(strAssetIdB)
117121
118122 let assetNameA = match assetIdA {
119123 case id: ByteVector =>
120124 value(assetInfo(id)).name
121125 case waves: Unit =>
122126 "WAVES"
123127 case _ =>
124128 throw("Match error")
125129 }
126130
127131 let assetNameB = match assetIdB {
128132 case id: ByteVector =>
129133 value(assetInfo(id)).name
130134 case waves: Unit =>
131135 "WAVES"
132136 case _ =>
133137 throw("Match error")
134138 }
135139
136140 let balanceA = getIntegerValue(this, keyBalanceA)
137141
138142 let balanceB = getIntegerValue(this, keyBalanceB)
139143
140144 let shareAssetId = fromBase58String(getStringValue(this, keyShareAssetId))
141145
142146 let shareAssetSupply = getIntegerValue(this, keyShareAssetSupply)
143147
144148 let commission = 3000
145149
146-let commissionGovernance = 1200
147-
148150 let commissionScaleDelimiter = 1000000
149151
150152 let scaleValue3 = 1000
151153
152154 let scaleValue8 = 100000000
153155
154156 let slippageToleranceDelimiter = 1000
155-
156-let scaleValue8Digits = 8
157157
158158 func accountBalance (assetId) = match assetId {
159159 case id: ByteVector =>
160160 assetBalance(this, id)
161161 case waves: Unit =>
162162 wavesBalance(this).available
163163 case _ =>
164164 throw("Match error")
165165 }
166166
167167
168168 func stakedAmount (assetId) = {
169169 let stakedAmountCalculated = match assetId {
170170 case aId: ByteVector =>
171171 if (if ((aId == USDN))
172172 then true
173173 else (aId == NSBT))
174174 then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
175175 else if ((aId == EURN))
176176 then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
177177 else 0
178178 case _: Unit =>
179- 0
179+ valueOrElse(getInteger(this, keyLeasingAmount), 0)
180180 case _ =>
181181 throw("Match error")
182182 }
183183 match stakedAmountCalculated {
184184 case i: Int =>
185185 i
186186 case _ =>
187187 0
188188 }
189189 }
190190
191191
192192 let stakedAmountA = stakedAmount(assetIdA)
193193
194194 let stakedAmountB = stakedAmount(assetIdB)
195195
196196 let assetInitA = getIntegerValue(this, keyBalanceInitA)
197197
198198 let assetInitB = getIntegerValue(this, keyBalanceInitB)
199199
200200 let availableBalanceA = (balanceA - stakedAmountA)
201201
202202 let availableBalanceB = (balanceB - stakedAmountB)
203203
204204 let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
205205
206206 let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
207207
208208 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
209209 then (accountBalanceWithStakedB >= balanceB)
210210 else false
211211
212212 func getAssetInfo (assetId) = match assetId {
213213 case id: ByteVector =>
214214 let stringId = toBase58String(id)
215215 let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
216216 $Tuple3(stringId, info.name, info.decimals)
217217 case waves: Unit =>
218218 $Tuple3("WAVES", "WAVES", 8)
219219 case _ =>
220220 throw("Match error")
221221 }
222222
223223
224224 func getAssetInfoFromString (assetStr) = if ((assetStr == "WAVES"))
225225 then $Tuple3("WAVES", "WAVES", 8)
226226 else {
227227 let stringId = assetStr
228228 let id = fromBase58String(assetStr)
229229 let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
230230 $Tuple3(stringId, info.name, info.decimals)
231231 }
232232
233233
234234 func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
235235
236236
237-func deductStakingFee (amount,assetId,secondAssetId) = if (if ((assetId == USDN))
238- then true
239- else (assetId == EURN))
240- then {
241- let stakinFee = if ((assetId == USDN))
242- then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
243- then 2
244- else 1))
245- else if ((assetId == EURN))
246- then stakingFeeInEURN
247- else 0
248- let result = (amount - stakinFee)
249- if ((0 >= result))
250- then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakinFee)) + "USDN/EURN"))
251- else result
252- }
253- else amount
237+func calcStakingFuncAndAddres (stake,assetId) = if (stake)
238+ then if ((assetId == USDN))
239+ then $Tuple2("lockNeutrino", stakingUSDNNSBTAddress)
240+ else if ((assetId == NSBT))
241+ then $Tuple2("lockNsbt", stakingUSDNNSBTAddress)
242+ else $Tuple2("startStaking", stakingEURNAddress)
243+ else if ((assetId == USDN))
244+ then $Tuple2("unlockNeutrino", stakingUSDNNSBTAddress)
245+ else if ((assetId == NSBT))
246+ then $Tuple2("unlockNsbt", stakingUSDNNSBTAddress)
247+ else $Tuple2("stopStaking", stakingEURNAddress)
254248
255249
256-func getStakingFee (assetId,secondAssetId) = if ((assetId == USDN))
257- then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
258- then 2
259- else 1))
260- else if ((assetId == EURN))
261- then stakingFeeInEURN
262- else 0
250+func calcStakingParams (stake,amount,assetId) = if (stake)
251+ then {
252+ let $t069306996 = calcStakingFuncAndAddres(stake, assetId)
253+ let call = $t069306996._1
254+ let stakingAddr = $t069306996._2
255+ $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
256+ }
257+ else {
258+ let $t070827148 = calcStakingFuncAndAddres(stake, assetId)
259+ let call = $t070827148._1
260+ let stakingAddr = $t070827148._2
261+ $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
262+ }
263263
264264
265265 func throwInsufficientAvailableBalance (amount,available,assetName) = throw((((((((("Insufficient DApp balance to pay " + toString(amount)) + " ") + assetName) + " due to staking. Available: ") + toString(available)) + " ") + assetName) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
266266
267267
268268 func throwInsufficientAvailableBalances (amountA,amountB) = throw((((((((((((((((("Insufficient DApp balance to pay " + toString(amountA)) + " ") + assetNameA) + " and ") + toString(amountB)) + " ") + assetNameB) + " due to staking. Available: ") + toString(availableBalanceA)) + " ") + assetNameA) + " and ") + toString(availableBalanceB)) + " ") + assetNameB) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
269269
270270
271271 func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(accountBalanceWithStakedA)) + " ") + assetNameA) + ", ") + toString(accountBalanceWithStakedB)) + " ") + assetNameB) + ". State: ") + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB))
272272
273273
274274 @Callable(i)
275275 func init (firstHarvest) = {
276- let $t080018078 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
277- let pmtAmountA = $t080018078._1
278- let pmtAssetIdA = $t080018078._2
279- let $t080838160 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
280- let pmtAmountB = $t080838160._1
281- let pmtAssetIdB = $t080838160._2
282- let $t081658242 = getAssetInfo(pmtAssetIdA)
283- let pmtStrAssetIdA = $t081658242._1
284- let pmtAssetNameA = $t081658242._2
285- let pmtDecimalsA = $t081658242._3
286- let $t082478324 = getAssetInfo(pmtAssetIdB)
287- let pmtStrAssetIdB = $t082478324._1
288- let pmtAssetNameB = $t082478324._2
289- let pmtDecimalsB = $t082478324._3
276+ let $t083358412 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
277+ let pmtAmountA = $t083358412._1
278+ let pmtAssetIdA = $t083358412._2
279+ let $t084178494 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
280+ let pmtAmountB = $t084178494._1
281+ let pmtAssetIdB = $t084178494._2
282+ let $t084998576 = getAssetInfo(pmtAssetIdA)
283+ let pmtStrAssetIdA = $t084998576._1
284+ let pmtAssetNameA = $t084998576._2
285+ let pmtDecimalsA = $t084998576._3
286+ let $t085818658 = getAssetInfo(pmtAssetIdB)
287+ let pmtStrAssetIdB = $t085818658._1
288+ let pmtAssetNameB = $t085818658._2
289+ let pmtDecimalsB = $t085818658._3
290290 if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
291291 then throw("Only admin can call this function")
292292 else if (isDefined(getBoolean(this, keyActive)))
293293 then throw("DApp is already active")
294294 else if ((pmtAssetIdA == pmtAssetIdB))
295295 then throw("Assets must be different")
296296 else {
297297 let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
298298 let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
299299 let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
300300 let arg1 = pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN)
301301 let arg2 = pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN)
302302 let arg3 = pow(10, 0, shareDecimals, 0, 0, DOWN)
303303 let shareInitialSupply = fraction(arg1, arg2, arg3)
304304 let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
305305 let shareIssueId = calculateAssetId(shareIssue)
306- let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
307- if (firstHarvest)
308- then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
309- else baseEntry
306+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
307+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
308+ else 0
309+ if ((stake1 == stake1))
310+ then {
311+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
312+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
313+ else 0
314+ if ((stake2 == stake2))
315+ then {
316+ let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
317+ if (firstHarvest)
318+ then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
319+ else baseEntry
320+ }
321+ else throw("Strict value is not equal to itself.")
322+ }
323+ else throw("Strict value is not equal to itself.")
310324 }
311325 }
312326
313327
314328
315329 @Callable(i)
316330 func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
317- let $t01056910656 = getAssetInfoFromString(strAssetIdA)
318- let pmtStrAssetIdA = $t01056910656._1
319- let pmtAssetNameA = $t01056910656._2
320- let pmtDecimalsA = $t01056910656._3
321- let $t01066110748 = getAssetInfoFromString(strAssetIdB)
322- let pmtStrAssetIdB = $t01066110748._1
323- let pmtAssetNameB = $t01066110748._2
324- let pmtDecimalsB = $t01066110748._3
331+ let $t01124711334 = getAssetInfoFromString(strAssetIdA)
332+ let pmtStrAssetIdA = $t01124711334._1
333+ let pmtAssetNameA = $t01124711334._2
334+ let pmtDecimalsA = $t01124711334._3
335+ let $t01133911426 = getAssetInfoFromString(strAssetIdB)
336+ let pmtStrAssetIdB = $t01133911426._1
337+ let pmtAssetNameB = $t01133911426._2
338+ let pmtDecimalsB = $t01133911426._3
325339 if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
326340 then throw("Only admin can call this function")
327341 else if (isDefined(getBoolean(this, keyActive)))
328342 then throw("DApp is already active")
329343 else if ((strAssetIdA == strAssetIdB))
330344 then throw("Assets must be different")
331345 else {
332346 let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
333347 let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
334348 let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
335349 let shareInitialSupply = 0
336350 let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
337351 let shareIssueId = calculateAssetId(shareIssue)
338352 let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceInitA, amtAssetA), IntegerEntry(keyBalanceInitB, amtAssetB), IntegerEntry(keyBalanceA, 0), IntegerEntry(keyBalanceB, 0), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply)]
339353 if (firstHarvest)
340354 then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
341355 else baseEntry
342356 }
343357 }
344358
345359
346360
347361 @Callable(i)
348362 func keepLimitForFirstHarvest (shareLimit) = if (!(isActive))
349363 then throw("DApp is inactive at this moment")
350364 else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
351365 then throw("Only admin can call this function")
352366 else [IntegerEntry(kShareLimit, shareLimit)]
353367
354368
355369
356370 @Callable(i)
357371 func replenishWithTwoTokens (slippageTolerance) = {
358372 let pmtAssetIdA = i.payments[0].assetId
359373 let pmtAssetIdB = i.payments[1].assetId
360- let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA, pmtAssetIdB)
361- let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB, pmtAssetIdA)
374+ let pmtAmountA = i.payments[0].amount
375+ let pmtAmountB = i.payments[1].amount
376+ let $t01392314000 = getAssetInfo(pmtAssetIdA)
377+ let pmtStrAssetIdA = $t01392314000._1
378+ let pmtAssetNameA = $t01392314000._2
379+ let pmtDecimalsA = $t01392314000._3
380+ let $t01400514082 = getAssetInfo(pmtAssetIdB)
381+ let pmtStrAssetIdB = $t01400514082._1
382+ let pmtAssetNameB = $t01400514082._2
383+ let pmtDecimalsB = $t01400514082._3
362384 if (if ((balanceA == 0))
363385 then (balanceB == 0)
364386 else false)
365387 then {
366- let $t01345913536 = getAssetInfo(pmtAssetIdA)
367- let pmtStrAssetIdA = $t01345913536._1
368- let pmtAssetNameA = $t01345913536._2
369- let pmtDecimalsA = $t01345913536._3
370- let $t01354513622 = getAssetInfo(pmtAssetIdB)
371- let pmtStrAssetIdB = $t01354513622._1
372- let pmtAssetNameB = $t01354513622._2
373- let pmtDecimalsB = $t01354513622._3
374388 let tokenRatio = fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
375389 if ((pmtAssetIdA == pmtAssetIdB))
376390 then throw("Assets must be different")
377391 else {
378392 let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
379393 let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
380394 if (!(isActive))
381395 then throw("DApp is inactive at this moment")
382396 else if (if ((0 > slippageTolerance))
383397 then true
384398 else (slippageTolerance > slippageToleranceDelimiter))
385399 then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
386400 else if ((size(i.payments) != 2))
387401 then throw("Two attached assets expected")
388402 else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
389403 then true
390404 else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
391405 then throw("Incorrect assets amount: amounts must have the contract ratio")
392406 else if (if ((pmtAssetIdA != assetIdA))
393407 then true
394408 else (pmtAssetIdB != assetIdB))
395409 then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
396410 else if ((shareInitialSupply == 0))
397411 then throw("Too small amount to replenish")
398412 else if (!(hasEnoughBalance))
399413 then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
400- else [Reissue(shareAssetId, shareInitialSupply, true), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareAssetId)]
414+ else {
415+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
416+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
417+ else 0
418+ if ((stake1 == stake1))
419+ then {
420+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
421+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
422+ else 0
423+ if ((stake2 == stake2))
424+ then [Reissue(shareAssetId, shareInitialSupply, true), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareAssetId)]
425+ else throw("Strict value is not equal to itself.")
426+ }
427+ else throw("Strict value is not equal to itself.")
428+ }
401429 }
402430 }
403431 else {
404432 let tokenRatio = fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
405433 let ratioShareTokensInA = fraction(pmtAmountA, scaleValue8, balanceA)
406434 let ratioShareTokensInB = fraction(pmtAmountB, scaleValue8, balanceB)
407435 let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scaleValue8)
408436 if (!(isActive))
409437 then throw("DApp is inactive at this moment")
410438 else if (if ((0 > slippageTolerance))
411439 then true
412440 else (slippageTolerance > slippageToleranceDelimiter))
413441 then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
414442 else if ((size(i.payments) != 2))
415443 then throw("Two attached assets expected")
416444 else if (if ((pmtAssetIdA != assetIdA))
417445 then true
418446 else (pmtAssetIdB != assetIdB))
419447 then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
420448 else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
421449 then true
422450 else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
423451 then throw("Incorrect assets amount: amounts must have the contract ratio")
424452 else if ((shareTokenToPayAmount == 0))
425453 then throw("Too small amount to replenish")
426454 else if (!(hasEnoughBalance))
427455 then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
428- else [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
456+ else {
457+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
458+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
459+ else 0
460+ if ((stake1 == stake1))
461+ then {
462+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
463+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
464+ else 0
465+ if ((stake2 == stake2))
466+ then [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
467+ else throw("Strict value is not equal to itself.")
468+ }
469+ else throw("Strict value is not equal to itself.")
470+ }
429471 }
430472 }
431473
432474
433475
434476 @Callable(i)
435477 func withdraw () = {
436- let $t01802118171 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
437- let pmtAmount = $t01802118171._1
438- let pmtAssetId = $t01802118171._2
439- let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA, assetIdB)
440- let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB, assetIdA)
478+ let $t01925119326 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
479+ let pmtAmount = $t01925119326._1
480+ let pmtAssetId = $t01925119326._2
481+ let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
482+ let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
441483 if (!(isActive))
442484 then throw("DApp is inactive at this moment")
443485 else if ((size(i.payments) != 1))
444486 then throw("One attached payment expected")
445487 else if ((pmtAssetId != shareAssetId))
446488 then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
447489 else if (!(hasEnoughBalance))
448490 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
449491 else if (if ((amountToPayA > availableBalanceA))
450492 then true
451493 else (amountToPayB > availableBalanceB))
452494 then throwInsufficientAvailableBalances(amountToPayA, amountToPayB)
453- else [IntegerEntry(keyBalanceA, (balanceA - amountToPayA)), IntegerEntry(keyBalanceB, (balanceB - amountToPayB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply - pmtAmount)), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
495+ else {
496+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
497+ then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
498+ else 0
499+ if ((stake1 == stake1))
500+ then {
501+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
502+ then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
503+ else 0
504+ if ((stake2 == stake2))
505+ then [IntegerEntry(keyBalanceA, (balanceA - amountToPayA)), IntegerEntry(keyBalanceB, (balanceB - amountToPayB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply - pmtAmount)), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
506+ else throw("Strict value is not equal to itself.")
507+ }
508+ else throw("Strict value is not equal to itself.")
509+ }
454510 }
455511
456512
457513
458514 @Callable(i)
459515 func exchange (minAmountToReceive) = {
460- let $t01939719472 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
461- let pmtAmount = $t01939719472._1
462- let pmtAssetId = $t01939719472._2
516+ let $t02084120916 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
517+ let pmtAmount = $t02084120916._1
518+ let pmtAssetId = $t02084120916._2
463519 func calculateFees (tokenFrom,tokenTo) = {
464520 let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
465521 let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
466522 let governanceReward = fraction(amountWithoutFee, commissionGovernance, commissionScaleDelimiter)
467523 if ((minAmountToReceive > amountWithFee))
468524 then throw(((("Calculated amount to receive " + toString(amountWithFee)) + " is less than specified minimum ") + toString(minAmountToReceive)))
469525 else $Tuple3(amountWithoutFee, amountWithFee, governanceReward)
470526 }
471527
472528 if (!(isActive))
473529 then throw("DApp is inactive at this moment")
474530 else if (if ((balanceA == 0))
475531 then true
476532 else (balanceB == 0))
477533 then throw("Can't exchange with zero balance")
478534 else if ((0 >= minAmountToReceive))
479535 then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
480536 else if ((size(i.payments) != 1))
481537 then throw("One attached payment expected")
482538 else if (!(hasEnoughBalance))
483539 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
484540 else if ((pmtAssetId == assetIdA))
485541 then {
486542 let assetIdSend = assetIdB
487- let $t02074620837 = calculateFees(balanceA, balanceB)
488- let amountWithoutFee = $t02074620837._1
489- let amountWithFee = $t02074620837._2
490- let governanceReward = $t02074620837._3
543+ let $t02219022281 = calculateFees(balanceA, balanceB)
544+ let amountWithoutFee = $t02219022281._1
545+ let amountWithFee = $t02219022281._2
546+ let governanceReward = $t02219022281._3
491547 let newBalanceA = (balanceA + pmtAmount)
492548 let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
493- if (if ((stakedAmountA >= newBalanceA))
494- then true
495- else (stakedAmountB >= newBalanceB))
496- then throwInsufficientAvailableBalance(amountWithFee, availableBalanceB, assetNameB)
497- else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
549+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
550+ then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdA], nil)
551+ else 0
552+ if ((stake1 == stake1))
553+ then {
554+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
555+ then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdB], nil)
556+ else 0
557+ if ((stake2 == stake2))
558+ then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
559+ else throw("Strict value is not equal to itself.")
560+ }
561+ else throw("Strict value is not equal to itself.")
498562 }
499563 else if ((pmtAssetId == assetIdB))
500564 then {
501565 let assetIdSend = assetIdA
502- let $t02165621747 = calculateFees(balanceB, balanceA)
503- let amountWithoutFee = $t02165621747._1
504- let amountWithFee = $t02165621747._2
505- let governanceReward = $t02165621747._3
566+ let $t02323623327 = calculateFees(balanceB, balanceA)
567+ let amountWithoutFee = $t02323623327._1
568+ let amountWithFee = $t02323623327._2
569+ let governanceReward = $t02323623327._3
506570 let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
507571 let newBalanceB = (balanceB + pmtAmount)
508572 if (if ((stakedAmountA >= newBalanceA))
509573 then true
510574 else (stakedAmountB >= newBalanceB))
511575 then throwInsufficientAvailableBalance(amountWithFee, availableBalanceA, assetNameA)
512- else [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
576+ else {
577+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
578+ then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdA], nil)
579+ else 0
580+ if ((stake1 == stake1))
581+ then {
582+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
583+ then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdB], nil)
584+ else 0
585+ if ((stake2 == stake2))
586+ then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
587+ else throw("Strict value is not equal to itself.")
588+ }
589+ else throw("Strict value is not equal to itself.")
590+ }
513591 }
514592 else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
515593 }
516594
517595
518596
519597 @Callable(i)
520598 func shutdown () = if (!(isActive))
521599 then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, keyCause), "the cause wasn't specified")))
522600 else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
523601 then throw("Only admin can call this function")
524602 else suspend("Paused by admin")
525603
526604
527605
528606 @Callable(i)
529607 func activate () = if (isActive)
530608 then throw("DApp is already active")
531609 else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
532610 then throw("Only admin can call this function")
533611 else [BooleanEntry(keyActive, true), DeleteEntry(keyCause)]
534612
535613
536614
537615 @Callable(i)
538616 func takeIntoAccountExtraFunds (amountLeave) = {
539617 let uncountableAmountEnrollAssetA = (accountBalanceWithStakedA - balanceA)
540618 let uncountableAmountEnrollAssetB = (accountBalanceWithStakedB - balanceB)
541619 let amountEnrollA = (uncountableAmountEnrollAssetA - (if ((assetIdA == unit))
542620 then amountLeave
543621 else 0))
544622 let amountEnrollB = (uncountableAmountEnrollAssetB - (if ((assetIdB == unit))
545623 then amountLeave
546624 else 0))
547625 if (!(isActive))
548626 then throw("DApp is inactive at this moment")
549627 else if ((i.caller != this))
550628 then throw("Only the DApp itself can call this function")
551629 else if ((0 > amountLeave))
552630 then throw(("Argument 'amountLeave' cannot be negative. Actual: " + toString(amountLeave)))
553631 else if (if ((0 > uncountableAmountEnrollAssetA))
554632 then true
555633 else (0 > uncountableAmountEnrollAssetB))
556634 then suspend("Enroll amount negative")
557635 else if (if ((0 > amountEnrollA))
558636 then true
559637 else (0 > amountEnrollB))
560638 then throw("Too large amountLeave")
561- else [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
639+ else {
640+ let stake1 = if (if (containsElement(stakingAssets, strAssetIdA))
641+ then (amountEnrollA > 0)
642+ else false)
643+ then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
644+ else 0
645+ if ((stake1 == stake1))
646+ then {
647+ let stake2 = if (if (containsElement(stakingAssets, strAssetIdB))
648+ then (amountEnrollB > 0)
649+ else false)
650+ then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
651+ else 0
652+ if ((stake2 == stake2))
653+ then [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
654+ else throw("Strict value is not equal to itself.")
655+ }
656+ else throw("Strict value is not equal to itself.")
657+ }
562658 }
659+
660+
661+
662+@Callable(i)
663+func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
664+ then throw("Only contract itself can invoke this function")
665+ else if ((assetIdString == "WAVES"))
666+ then {
667+ let pool = addressFromStringValue(valueOrErrorMessage(getString(oracle, keyLeasingPool), "No leasing pool in oracle"))
668+ let leasingId = getBinary(this, keyLeasingId)
669+ let leasingAmount = valueOrElse(getInteger(this, keyLeasingAmount), 0)
670+ let newLeaseAmount = if (stake)
671+ then (leasingAmount + amount)
672+ else (leasingAmount - amount)
673+ let newLease = Lease(pool, newLeaseAmount)
674+ let newLeaseId = calculateLeaseId(newLease)
675+ let baseEtry = [newLease, BinaryEntry(keyLeasingId, newLeaseId), IntegerEntry(keyLeasingAmount, newLeaseAmount)]
676+ match leasingId {
677+ case lId: ByteVector =>
678+ ([LeaseCancel(lId)] ++ baseEtry)
679+ case _ =>
680+ baseEtry
681+ }
682+ }
683+ else {
684+ let $t02793128034 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
685+ let call = $t02793128034._1
686+ let addr = $t02793128034._2
687+ let params = $t02793128034._3
688+ let payments = $t02793128034._4
689+ let inv = invoke(addr, call, params, payments)
690+ nil
691+ }
692+
693+
694+
695+@Callable(i)
696+func stakeAll () = if (!(isActive))
697+ then throw("DApp is inactive at this moment")
698+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
699+ then throw("Only admin can call this function")
700+ else {
701+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
702+ then {
703+ let amountA = (balanceA - stakedAmountA)
704+ if ((amountA > 0))
705+ then invoke(this, "stakeUnstake", [true, amountA, strAssetIdA], nil)
706+ else 0
707+ }
708+ else 0
709+ if ((stake1 == stake1))
710+ then {
711+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
712+ then {
713+ let amountB = (balanceB - stakedAmountB)
714+ if ((amountB > 0))
715+ then invoke(this, "stakeUnstake", [true, amountB, strAssetIdB], nil)
716+ else 0
717+ }
718+ else 0
719+ if ((stake2 == stake2))
720+ then nil
721+ else throw("Strict value is not equal to itself.")
722+ }
723+ else throw("Strict value is not equal to itself.")
724+ }
563725
564726
565727 @Verifier(tx)
566728 func verify () = {
567729 let multiSignedByAdmins = {
568730 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
569731 then 1
570732 else 0
571733 let adminPubKey2Signed = if (sigVerify(tx.bodyBytes, tx.proofs[1], adminPubKey2))
572734 then 1
573735 else 0
574736 let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3))
575737 then 1
576738 else 0
577739 (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2)
578740 }
579741 match tx {
580742 case inv: InvokeScriptTransaction =>
581743 let callTakeIntoAccount = if ((inv.dApp == this))
582744 then (inv.function == "takeIntoAccountExtraFunds")
583745 else false
584- let callStaking = if (if ((inv.dApp == stakingUSDNNSBTAddress))
585- then if (if (if (containsElement(["lockNeutrino", "lockNsbt"], inv.function))
586- then (size(inv.payments) == 1)
587- else false)
588- then if ((inv.payments[0].assetId == USDN))
589- then true
590- else (inv.payments[0].assetId == NSBT)
591- else false)
592- then true
593- else if (containsElement(["unlockNeutrino", "unlockNsbt"], inv.function))
594- then (size(inv.payments) == 0)
595- else false
596- else false)
597- then true
598- else if ((inv.dApp == stakingEURNAddress))
599- then if (if (if ((inv.function == "startStaking"))
600- then (size(inv.payments) == 1)
601- else false)
602- then (inv.payments[0].assetId == EURN)
603- else false)
604- then true
605- else if ((inv.function == "stopStaking"))
606- then (size(inv.payments) == 0)
607- else false
608- else false
609746 let exchangeToWaves = if (if (if ((inv.dApp == USDNToWavesExchanger))
610747 then (inv.function == "exchange")
611748 else false)
612749 then (assetIdA == USDN)
613750 else false)
614751 then true
615752 else if (if ((assetIdB == USDN))
616753 then (size(inv.payments) == 1)
617754 else false)
618755 then (inv.payments[0].assetId == USDN)
619756 else false
620757 let exchangeToNSBTs = if (if (if ((inv.dApp == USDNToNSBTExchanger))
621758 then (inv.function == "exchange")
622759 else false)
623760 then (assetIdA == NSBT)
624761 else false)
625762 then true
626763 else if (if ((assetIdB == NSBT))
627764 then (size(inv.payments) == 1)
628765 else false)
629766 then (inv.payments[0].assetId == USDN)
630767 else false
631768 let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
632769 then true
633770 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
634771 then true
635772 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
636773 then true
637774 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyStaking)
638- if (if (if (if (if (callTakeIntoAccount)
639- then true
640- else callStaking)
775+ if (if (if (if (callTakeIntoAccount)
641776 then true
642777 else exchangeToWaves)
643778 then true
644779 else exchangeToNSBTs)
645780 then signedByAdmin
646781 else false)
647782 then true
648783 else multiSignedByAdmins
649784 case _ =>
650785 multiSignedByAdmins
651786 }
652787 }
653788

github/deemru/w8io/026f985 
109.16 ms