tx · Ge5EbvWYkiC6PsyTeFcgj3y8w9e7Cwe7JJRCbn4ws7cf

3N9eLqWNqb7jeF383m9qsXEBqpp8qfQmfbx:  -0.04000000 Waves

2022.06.03 06:59 [2079646] smart account 3N9eLqWNqb7jeF383m9qsXEBqpp8qfQmfbx > SELF 0.00000000 Waves

{ "type": 13, "id": "Ge5EbvWYkiC6PsyTeFcgj3y8w9e7Cwe7JJRCbn4ws7cf", "fee": 4000000, "feeAssetId": null, "timestamp": 1654228883876, "version": 2, "chainId": 84, "sender": "3N9eLqWNqb7jeF383m9qsXEBqpp8qfQmfbx", "senderPublicKey": "5cWdpE4X7mfNkLmxJ389ws6qGZof4fwydqMcqPexhJ7w", "proofs": [ "5gWfUwiYwvzeQAg2XcMGXJJNk7fHdroADzmSDyekfZoeECbnxAdfxAxSYEPNTDvfk63KR3sjVNFc5oT9WF8r9hb4" ], "script": "base64:AAIFAAAAAAAAAEAIAhIHCgUICAgBARIDCgEIEgMKAQgSAwoBCBIDCgEIEgMKAQgSAwoBCBIECgIICRIDCgEIEgUKAwEIARIDCgEIAAAAIwAAAAAMbG9ja2luZ1N0b3JlBQAAAAR0aGlzAAAAAAxzdGFraW5nU3RvcmUCAAAACF9SZXNlcnZlAAAAABFtaW5pbXVtTG9ja0Ftb3VudAIAAAAOX01pbkxvY2tBbW91bnQAAAAAEW1heGltdW1Mb2NrQW1vdW50AgAAAA5fTWF4TG9ja0Ftb3VudAAAAAAJYXNzZXRMaXN0BQAAAANuaWwAAAAAEXVubG9ja0VsaWdpYmlsaXR5AgAAABxfRWxpZ2libGVfdG9fdW5sb2NrX2F0X2Jsb2NrAAAAAAxsb2NrZWRBbW91bnQCAAAADl9BbW91bnRfbG9ja2VkAAAAAAtsb2NrZWRBc3NldAIAAAANX0Fzc2V0X2xvY2tlZAAAAAAEdXNlcgIAAAAFX1VzZXIAAAAACkFQWV9BbW91bnQCAAAAC19BUFlfYW1vdW50AAAAABF0b3RhbExvY2tlZEFNb3VudAIAAAAUX1RvdGFsX0xvY2tlZF9BbW91bnQAAAAADWxvY2tpbmdQZXJpb2QCAAAADF9EYXlzX2xvY2tlZAAAAAAKZW50cnlJbmRleAIAAAAMX0VudHJ5X0luZGV4AAAAAA5hbHJlYWR5Q2xhaW1lZAIAAAAQX0FscmVhZHlfQ2xhaW1lZAAAAAAFYWRtaW4CAAAABmFkbWluXwAAAAALQmxvY2tQZXJEYXkAAAAAAAAABaAAAAAAFHRoaXJ0eURheXNMb2NrUGVyaW9kAAAAAAAAAAAeAAAAABNzaXh0eURheXNMb2NrUGVyaW9kAAAAAAAAAAA8AAAAABRuaW5ldHlEYXlzTG9ja1BlcmlvZAAAAAAAAAAAWgEAAAAEZ2V0SQAAAAEAAAADa2V5CQAEGgAAAAIFAAAABHRoaXMFAAAAA2tleQEAAAAEZ2V0UwAAAAEAAAADa2V5CQAEHQAAAAIFAAAABHRoaXMFAAAAA2tleQEAAAAFZ2V0SVYAAAABAAAAA2tleQkBAAAABXZhbHVlAAAAAQkABBoAAAACBQAAAAR0aGlzBQAAAANrZXkBAAAABWdldFNWAAAAAQAAAANrZXkJAQAAAAV2YWx1ZQAA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dAQAAAASYU1heGltdW1Mb2NrQW1vdW50CQABLAAAAAIFAAAAC0Fzc2V0VGlja2VyBQAAABFtYXhpbXVtTG9ja0Ftb3VudAkABEwAAAACCQEAAAAQd3JpdGVDb25zdFN0cmluZwAAAAIFAAAAC0Fzc2V0VGlja2VyBQAAAAdBc3NldElECQAETAAAAAIJAQAAABB3cml0ZUNvbnN0U3RyaW5nAAAAAgUAAAANYVN0YWtpbmdTdG9yZQUAAAARQXNzZXRTdGFraW5nU3RvcmUJAARMAAAAAgkBAAAAEXdyaXRlQ29uc3RJbnRlZ2VyAAAAAgUAAAASYU1pbmltdW1Mb2NrQW1vdW50BQAAABZBc3NldE1pbmltdW1Mb2NrQW1vdW50CQAETAAAAAIJAQAAABF3cml0ZUNvbnN0SW50ZWdlcgAAAAIFAAAAEmFNYXhpbXVtTG9ja0Ftb3VudAUAAAAWQXNzZXRNYXhpbXVtTG9ja0Ftb3VudAUAAAADbmlsCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAABJnZXRBc3NldElkQnlUaWNrZXIAAAABAAAAC0Fzc2V0VGlja2VyBAAAAAVjaGVjawkBAAAACWFkbWluT25seQAAAAEFAAAAAWkDCQAAAAAAAAIFAAAABWNoZWNrBQAAAAVjaGVjawQAAAABYQkBAAAADnRocm93T3JSZXR1cm5TAAAAAgkBAAAABGdldFMAAAABBQAAAAtBc3NldFRpY2tlcgIAAAAPYXNzZXQgbm90IGZvdW5kCQAFFAAAAAIFAAAAA25pbAUAAAABYQkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAEaW5pdAAAAAEAAAAMQWRtaW5BZGRyZXNzCQAETAAAAAIJAQAAABB3cml0ZUNvbnN0U3RyaW5nAAAAAgUAAAAFYWRtaW4JAAQlAAAAAQkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAAMQWRtaW5BZGRyZXNzBQAAAANuaWwAAAABaQEAAAAIYWRkQWRtaW4AAAABAAAADEFkbWluQWRkcmVzcwQAAAAFY2hlY2sJAQAAAAlhZG1pbk9ubHkAAAABBQAAAAFpAwkAAAAAAAACBQAAAAVjaGVjawUAAAAFY2hlY2sEAAAACG5ld0FkbWluCQABLAAAAAIFAAAABWFkbWluBQAAAAxBZG1pbkFkZHJlc3MJAARMAAAAAgkBAAAAEHdyaXRlQ29uc3RTdHJpbmcAAAACBQAAAAhuZXdBZG1pbgUAAAAMQWRtaW5BZGRyZXNzBQAAAANuaWwJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAAD2NoYW5nZU1haW5BZG1pbgAAAAEAAAAHYWRkcmVzcwQAAAAGY2hlY2tzCQEAAAAJYWRtaW5Pbmx5AAAAAQUAAAABaQMJAAAAAAAAAgUAAAAGY2hlY2tzBQAAAAZjaGVja3MEAAAAA2RlbAkBAAAAC0RlbGV0ZUVudHJ5AAAAAQUAAAAFYWRtaW4DCQAAAAAAAAIFAAAAA2RlbAUAAAADZGVsCQAETAAAAAIJAQAAABB3cml0ZUNvbnN0U3RyaW5nAAAAAgUAAAAFYWRtaW4FAAAAB2FkZHJlc3MFAAAAA25pbAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAAF3VwZGF0ZU90aGVyQWRtaW5BZGRyZXNzAAAAAQAAAAdhZGRyZXNzBAAAAAZjaGVja3MJAQAAAAlhZG1pbk9ubHkAAAABBQAAAAFpAwkAAAAAAAACBQAAAAZjaGVja3MFAAAABmNoZWNrcwQAAAAGY2FsbGVyCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAAKb3RoZXJBZG1pbgkAASwAAAACBQAAAAVhZG1pbgUAAAAGY2FsbGVyBAAAAA9jaGVja09sZEFkZHJlc3MJAQAAAA50aHJvd09yUmV0dXJuUwAAAAIJAQAAAARnZXRTAAAAAQUAAAAKb3RoZXJBZG1pbgIAAAAZbm8gcHJldmlvdXMgYWRkcmVzcyBmb3VuZAMJAAAAAAAAAgUAAAAPY2hlY2tPbGRBZGRyZXNzBQAAAA9jaGVja09sZEFkZHJlc3MEAAAACmRlbEFkZHJlc3MJAQAAAAtEZWxldGVFbnRyeQAAAAEFAAAACm90aGVyQWRtaW4DCQAAAAAAAAIFAAAACmRlbEFkZHJlc3MFAAAACmRlbEFkZHJlc3MJAARMAAAAAgkBAAAAEHdyaXRlQ29uc3RTdHJpbmcAAAACBQAAAApvdGhlckFkbWluBQAAAAdhZGRyZXNzBQAAAANuaWwJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAQcmVtb3ZlT3RoZXJBZG1pbgAAAAEAAAAHYWRkcmVzcwQAAAAGY2hlY2tzCQEAAAAJYWRtaW5Pbmx5AAAAAQUAAAABaQMJAAAAAAAAAgUAAAAGY2hlY2tzBQAAAAZjaGVja3MEAAAADG90aGVyQWRkcmVzcwkAASwAAAACBQAAAAVhZG1pbgUAAAAHYWRkcmVzcwQAAAAIZGVsQWRtaW4JAQAAAAtEZWxldGVFbnRyeQAAAAEFAAAADG90aGVyQWRkcmVzcwMJAAAAAAAAAgUAAAAIZGVsQWRtaW4FAAAACGRlbEFkbWluBQAAAANuaWwJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAABF1cGRhdGVDb25maWdWYWx1ZQAAAAIAAAADa2V5AAAABGRhdGEEAAAABmNoZWNrcwkBAAAACWFkbWluT25seQAAAAEFAAAAAWkDCQAAAAAAAAIFAAAABmNoZWNrcwUAAAAGY2hlY2tzBAAAAANkZWwJAQAAAAtEZWxldGVFbnRyeQAAAAEFAAAAA2tleQMJAAAAAAAAAgUAAAADZGVsBQAAAANkZWwJAARMAAAAAgkBAAAAEHdyaXRlQ29uZmlnVmFsdWUAAAACBQAAAANrZXkFAAAABGRhdGEFAAAAA25pbAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAAEmdldERheXNMZWZ0VG9DbGFpbQAAAAEAAAALdXNlckFkZHJlc3MEAAAABmNoZWNrMAkBAAAACWFkbWluT25seQAAAAEFAAAAAWkDCQAAAAAAAAIFAAAABmNoZWNrMAUAAAAGY2hlY2swBAAAAAZjaGVjazEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABCYAAAABBQAAAAt1c2VyQWRkcmVzcwIAAAAPaW52YWxpZCBhZGRyZXNzAwkAAAAAAAACBQAAAAZjaGVjazEFAAAABmNoZWNrMQQAAAALdUVudHJ5SW5kZXgJAAEsAAAAAgIAAAABXwkAAaQAAAABCQEAAAAOdGhyb3dPclJldHVybkkAAAACCQEAAAAEZ2V0SQAAAAEJAAEsAAAAAgUAAAALdXNlckFkZHJlc3MFAAAACmVudHJ5SW5kZXgJAAEsAAAAAgIAAAATbm8gZW50cnkgZm91bmQgZm9yIAUAAAALdXNlckFkZHJlc3MEAAAAEnVVbmxvY2tFbGlnaWJpbGl0eQkAASwAAAACCQABLAAAAAIFAAAAC3VzZXJBZGRyZXNzBQAAAAt1RW50cnlJbmRleAUAAAARdW5sb2NrRWxpZ2liaWxpdHkEAAAAB3VCbG9ja3MJAQAAAA50aHJvd09yUmV0dXJuSQAAAAIJAQAAAARnZXRJAAAAAQUAAAASdVVubG9ja0VsaWdpYmlsaXR5AgAAAA5pbnRlcm5hbCBlcnJvcgQAAAANdUJsb2Nrc1RvRGF5cwkBAAAADGRheXNUb0Jsb2NrcwAAAAEJAABlAAAAAgUAAAAGaGVpZ2h0BQAAAAd1QmxvY2tzCQAFFAAAAAIFAAAAA25pbAUAAAANdUJsb2Nrc1RvRGF5cwkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAABExvY2sAAAADAAAACkxvY2tQZXJpb2QAAAALQXNzZXRUaWNrZXIAAAAD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ZEFtb3VudAkAASwAAAACCQABLAAAAAIFAAAABnVzZXJJZAUAAAAOdUVudHJ5VG9TdHJpbmcFAAAADGxvY2tlZEFtb3VudAQAAAAEdUFQWQkAASwAAAACCQABLAAAAAIFAAAABnVzZXJJZAUAAAAOdUVudHJ5VG9TdHJpbmcFAAAACkFQWV9BbW91bnQEAAAAEnVVbmxvY2tFbGlnaWJpbGl0eQkAASwAAAACCQABLAAAAAIFAAAABnVzZXJJZAUAAAAOdUVudHJ5VG9TdHJpbmcFAAAAEXVubG9ja0VsaWdpYmlsaXR5BAAAAA91QWxyZWFkeUNsYWltZWQJAAEsAAAAAgkAASwAAAACBQAAAAZ1c2VySWQFAAAADnVFbnRyeVRvU3RyaW5nBQAAAA5hbHJlYWR5Q2xhaW1lZAkABEwAAAACCQEAAAARd3JpdGVDb25zdEludGVnZXIAAAACBQAAAAt1RW50cnlJbmRleAUAAAAPdUluY3JFbnRyeUluZGV4CQAETAAAAAIJAQAAABB3cml0ZUNvbnN0U3RyaW5nAAAAAgUAAAAHdVVzZXJJZAUAAAAGdXNlcklkCQAETAAAAAIJAQAAABB3cml0ZUNvbnN0U3RyaW5nAAAAAgUAAAAGdUFzc2V0BQAAAAVhc3NldAkABEwAAAACCQEAAAARd3JpdGVDb25zdEludGVnZXIAAAACBQAAAA51TG9ja2luZ1BlcmlvZAUAAAAKbG9ja1BlcmlvZAkABEwAAAACCQEAAAARd3JpdGVDb25zdEludGVnZXIAAAACBQAAAA11TG9ja2VkQW1vdW50CAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAZhbW91bnQJAARMAAAAAgkBAAAAEXdyaXRlQ29uc3RJbnRlZ2VyAAAAAgUAAAAMdVRvdGFsTG9ja2VkBQAAAAl1U3VtVG90YWwJAARMAAAAAgkBAAAAEXdyaXRlQ29uc3RJbnRlZ2VyAAAAAgUAAAASdVVubG9ja0VsaWdpYmlsaXR5CQEAAAAMZGF5c1RvQmxvY2tzAAAAAQUAAAAKTG9ja1BlcmlvZAkABEwAAAACCQEAAAARd3JpdGVDb25zdEludGVnZXIAAAACBQAAAAR1QVBZBQAAAANBUFkJAARMAAAAAgkBAAAADEJvb2xl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", "height": 2079646, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: DvQ7JgcHRXHKQ1tqjeJNuo6kvF4ebxS1SHNsgeMF1Pc1 Next: 4Uj4ncgiqGfZhhkv3D1GSeyXxdomW7vYVmv4kwESQjCi Diff:
OldNewDifferences
33 {-# CONTENT_TYPE DAPP #-}
44 let lockingStore = this
55
6-let stakingStore = "_StakingStore"
6+let stakingStore = "_Reserve"
77
88 let minimumLockAmount = "_MinLockAmount"
99
2121
2222 let APY_Amount = "_APY_amount"
2323
24+let totalLockedAMount = "_Total_Locked_Amount"
25+
2426 let lockingPeriod = "_Days_locked"
27+
28+let entryIndex = "_Entry_Index"
29+
30+let alreadyClaimed = "_Already_Claimed"
2531
2632 let admin = "admin_"
2733
2834 let BlockPerDay = 1440
29-
30-let RBase = 10000000000000000
31-
32-let factorsBase = 1000
3335
3436 let thirtyDaysLockPeriod = 30
3537
127129 case _ =>
128130 throw("unsupported config type")
129131 }
132+
133+
134+func incrementEntryIndex (key) = {
135+ let uIndex = getI(key)
136+ if (isDefined(uIndex))
137+ then (value(uIndex) + 1)
138+ else 0
139+ }
130140
131141
132142 @Callable(i)
244254
245255
246256 @Callable(i)
257+func getDaysLeftToClaim (userAddress) = {
258+ let check0 = adminOnly(i)
259+ if ((check0 == check0))
260+ then {
261+ let check1 = valueOrErrorMessage(addressFromString(userAddress), "invalid address")
262+ if ((check1 == check1))
263+ then {
264+ let uEntryIndex = ("_" + toString(throwOrReturnI(getI((userAddress + entryIndex)), ("no entry found for " + userAddress))))
265+ let uUnlockEligibility = ((userAddress + uEntryIndex) + unlockEligibility)
266+ let uBlocks = throwOrReturnI(getI(uUnlockEligibility), "internal error")
267+ let uBlocksToDays = daysToBlocks((height - uBlocks))
268+ $Tuple2(nil, uBlocksToDays)
269+ }
270+ else throw("Strict value is not equal to itself.")
271+ }
272+ else throw("Strict value is not equal to itself.")
273+ }
274+
275+
276+
277+@Callable(i)
247278 func Lock (LockPeriod,AssetTicker,APY) = {
248- let check1 = throwIf((1 != size(i.payments)), "Attach amount you want to lock")
279+ let check1 = throwIf((1 != size(i.payments)), "attach amount you want to lock")
249280 if ((check1 == check1))
250281 then {
251282 let asset = toBase58String(value(i.payments[0].assetId))
252- let check2 = throwIf((getS(AssetTicker) != asset), "Asset not supported")
283+ let check2 = throwIf((getS(AssetTicker) != asset), "asset not supported")
253284 if ((check2 == check2))
254285 then {
255286 let lockPeriod = LockPeriod
262293 else (amountToStake > maxToStake), "staking amount is out of range")
263294 if ((check3 == check3))
264295 then {
265- let uUserId = (userId + user)
266- let uAsset = (userId + lockedAsset)
267- let uLockingPeriod = (userId + lockingPeriod)
268- let uLockedAmount = (userId + lockedAmount)
269- let uAPY = (userId + APY_Amount)
270- let uUnlockEligibility = (userId + unlockEligibility)
271-[writeStr(uUserId, userId), writeStr(uAsset, asset), writeInt(uLockingPeriod, lockPeriod), writeInt(uLockedAmount, i.payments[0].amount), writeInt(uUnlockEligibility, daysToBlocks(LockPeriod)), writeInt(uAPY, APY)]
296+ let uTotalLocked = (userId + totalLockedAMount)
297+ let uSumTotal = if (!(isDefined(getI(uTotalLocked))))
298+ then 0
299+ else (amountToStake + value(getI(uTotalLocked)))
300+ let check4 = throwIf((uSumTotal > maxToStake), "you have maxed out your quota")
301+ if ((check4 == check4))
302+ then {
303+ let uEntryIndex = ((userId + AssetTicker) + entryIndex)
304+ let uIncrEntryIndex = incrementEntryIndex(uEntryIndex)
305+ let uEntryToString = ((("_" + AssetTicker) + "_") + toString(uIncrEntryIndex))
306+ let uUserId = ((userId + uEntryToString) + user)
307+ let uAsset = ((userId + uEntryToString) + lockedAsset)
308+ let uLockingPeriod = ((userId + uEntryToString) + lockingPeriod)
309+ let uLockedAmount = ((userId + uEntryToString) + lockedAmount)
310+ let uAPY = ((userId + uEntryToString) + APY_Amount)
311+ let uUnlockEligibility = ((userId + uEntryToString) + unlockEligibility)
312+ let uAlreadyClaimed = ((userId + uEntryToString) + alreadyClaimed)
313+[writeConstInteger(uEntryIndex, uIncrEntryIndex), writeConstString(uUserId, userId), writeConstString(uAsset, asset), writeConstInteger(uLockingPeriod, lockPeriod), writeConstInteger(uLockedAmount, i.payments[0].amount), writeConstInteger(uTotalLocked, uSumTotal), writeConstInteger(uUnlockEligibility, daysToBlocks(LockPeriod)), writeConstInteger(uAPY, APY), BooleanEntry(uAlreadyClaimed, false)]
314+ }
315+ else throw("Strict value is not equal to itself.")
272316 }
273317 else throw("Strict value is not equal to itself.")
274318 }
282326 @Callable(i)
283327 func Claim (AssetTicker) = {
284328 let userId = toString(i.caller)
285- let uAsset = throwOrReturnS(getS((userId + lockedAsset)), ("there are no locked tokens for " + userId))
286- let uLockedAmount = throwOrReturnI(getI((userId + lockedAmount)), "internal error: could not retrieve locked amount")
287- let stakingReserve = addressFromStringValue(throwOrReturnS(getS((AssetTicker + stakingStore)), "internal error: staking store not found for asset"))
288- let APYAMount = throwOrReturnI(getI((userId + APY_Amount)), "internal error: failed to get APY")
289- let period = throwOrReturnI(getI((userId + unlockEligibility)), "internal error: could not determine claim eligibility")
290- let blocksLeft = if ((0 >= (period - height)))
291- then 0
292- else (period - height)
293- let daysLeft = blocksToDays(blocksLeft)
294- let check1 = throwIf((period > height), (toString(daysLeft) + " days left to claim"))
295- if ((check1 == check1))
329+ let uEntryIndex = ((("_" + AssetTicker) + "_") + toString(throwOrReturnI(getI(((userId + AssetTicker) + entryIndex)), "no entry found for user")))
330+ let uAlreadyClaimedKey = ((userId + uEntryIndex) + alreadyClaimed)
331+ let check0 = throwIf((valueOrErrorMessage(getBoolean(uAlreadyClaimedKey), "cannot ascertain claimability") == true), (("user + " + userId) + " already claimed"))
332+ if ((check0 == check0))
296333 then {
297- let transferAPYAmount = invoke(stakingReserve, "transferInterest", [userId, APYAMount, toBytes(uAsset)], nil)
298- if ((transferAPYAmount == transferAPYAmount))
299- then [ScriptTransfer(addressFromStringValue(userId), uLockedAmount, toBytes(uAsset))]
334+ let uAsset = getSV(((userId + uEntryIndex) + lockedAsset))
335+ let uLockedAmount = getIV(((userId + uEntryIndex) + lockedAmount))
336+ let stakingReserve = addressFromStringValue(throwOrReturnS(getS((AssetTicker + stakingStore)), "internal error: no reserve found"))
337+ let APYAMount = getIV(((userId + uEntryIndex) + APY_Amount))
338+ let period = getIV(((userId + uEntryIndex) + unlockEligibility))
339+ let blocksLeft = if ((0 >= (period - height)))
340+ then 0
341+ else (period - height)
342+ let daysLeft = blocksToDays(blocksLeft)
343+ let check1 = throwIf((period > height), (toString(daysLeft) + "/1000 days left to claim"))
344+ if ((check1 == check1))
345+ then {
346+ let transferAPYAmount = invoke(stakingReserve, "transferInterest", [userId, APYAMount, toBytes(uAsset)], nil)
347+ if ((transferAPYAmount == transferAPYAmount))
348+ then [ScriptTransfer(addressFromStringValue(userId), uLockedAmount, toBytes(uAsset)), BooleanEntry(uAlreadyClaimedKey, true)]
349+ else throw("Strict value is not equal to itself.")
350+ }
300351 else throw("Strict value is not equal to itself.")
301352 }
302353 else throw("Strict value is not equal to itself.")
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let lockingStore = this
55
6-let stakingStore = "_StakingStore"
6+let stakingStore = "_Reserve"
77
88 let minimumLockAmount = "_MinLockAmount"
99
1010 let maximumLockAmount = "_MaxLockAmount"
1111
1212 let assetList = nil
1313
1414 let unlockEligibility = "_Eligible_to_unlock_at_block"
1515
1616 let lockedAmount = "_Amount_locked"
1717
1818 let lockedAsset = "_Asset_locked"
1919
2020 let user = "_User"
2121
2222 let APY_Amount = "_APY_amount"
2323
24+let totalLockedAMount = "_Total_Locked_Amount"
25+
2426 let lockingPeriod = "_Days_locked"
27+
28+let entryIndex = "_Entry_Index"
29+
30+let alreadyClaimed = "_Already_Claimed"
2531
2632 let admin = "admin_"
2733
2834 let BlockPerDay = 1440
29-
30-let RBase = 10000000000000000
31-
32-let factorsBase = 1000
3335
3436 let thirtyDaysLockPeriod = 30
3537
3638 let sixtyDaysLockPeriod = 60
3739
3840 let ninetyDaysLockPeriod = 90
3941
4042 func getI (key) = getInteger(this, key)
4143
4244
4345 func getS (key) = getString(this, key)
4446
4547
4648 func getIV (key) = value(getInteger(this, key))
4749
4850
4951 func getSV (key) = value(getString(this, key))
5052
5153
5254 func throwIf (condition,error) = if (condition)
5355 then throw(error)
5456 else true
5557
5658
5759 func throwOrReturnI (val,error) = match val {
5860 case val: Int =>
5961 val
6062 case _ =>
6163 throw(error)
6264 }
6365
6466
6567 func throwOrReturnS (val,error) = match val {
6668 case val: String =>
6769 val
6870 case _ =>
6971 throw(error)
7072 }
7173
7274
7375 func writeInt (key,value) = if ((0 > value))
7476 then throw(((("writing negative value " + toString(value)) + " for key ") + key))
7577 else IntegerEntry(key, value)
7678
7779
7880 func writeStr (key,value) = if ((" " == value))
7981 then throw(("writing an empty string " + value))
8082 else StringEntry(key, value)
8183
8284
8385 func daysToBlocks (days) = if (if (if ((days != thirtyDaysLockPeriod))
8486 then true
8587 else (days != sixtyDaysLockPeriod))
8688 then true
8789 else (days != ninetyDaysLockPeriod))
8890 then throw("invalid Lock Period")
8991 else (((days + 1) * BlockPerDay) + height)
9092
9193
9294 func blocksToDays (blocksLeft) = if ((0 >= blocksLeft))
9395 then 0
9496 else {
9597 let multiplier = pow(10, 0, 3, 0, 0, CEILING)
9698 let daysleft = fraction(blocksLeft, multiplier, BlockPerDay)
9799 daysleft
98100 }
99101
100102
101103 func writeConstString (key,value) = if (!(isDefined(getS(key))))
102104 then writeStr(key, value)
103105 else throw(("already initialized: " + key))
104106
105107
106108 func writeConstInteger (key,value) = if (!(isDefined(getS(key))))
107109 then writeInt(key, value)
108110 else throw(("already initialized: " + key))
109111
110112
111113 func adminOnly (i) = {
112114 let AdminAddress = toString(i.caller)
113115 let otherAdminAddress = (admin + toString(i.caller))
114116 if (if ((AdminAddress != valueOrElse(getS(admin), "not an admin")))
115117 then true
116118 else (AdminAddress != valueOrElse(getS(otherAdminAddress), "not an admin")))
117119 then throw("unauthorized")
118120 else true
119121 }
120122
121123
122124 func writeConfigValue (key,data) = match data {
123125 case data: String =>
124126 writeConstString(key, data)
125127 case data: Int =>
126128 writeConstInteger(key, data)
127129 case _ =>
128130 throw("unsupported config type")
129131 }
132+
133+
134+func incrementEntryIndex (key) = {
135+ let uIndex = getI(key)
136+ if (isDefined(uIndex))
137+ then (value(uIndex) + 1)
138+ else 0
139+ }
130140
131141
132142 @Callable(i)
133143 func addAsset (AssetTicker,AssetID,AssetStakingStore,AssetMinimumLockAmount,AssetMaximumLockAmount) = {
134144 let check = adminOnly(i)
135145 if ((check == check))
136146 then {
137147 let aStakingStore = (AssetTicker + stakingStore)
138148 let aMinimumLockAmount = (AssetTicker + minimumLockAmount)
139149 let aMaximumLockAmount = (AssetTicker + maximumLockAmount)
140150 [writeConstString(AssetTicker, AssetID), writeConstString(aStakingStore, AssetStakingStore), writeConstInteger(aMinimumLockAmount, AssetMinimumLockAmount), writeConstInteger(aMaximumLockAmount, AssetMaximumLockAmount)]
141151 }
142152 else throw("Strict value is not equal to itself.")
143153 }
144154
145155
146156
147157 @Callable(i)
148158 func getAssetIdByTicker (AssetTicker) = {
149159 let check = adminOnly(i)
150160 if ((check == check))
151161 then {
152162 let a = throwOrReturnS(getS(AssetTicker), "asset not found")
153163 $Tuple2(nil, a)
154164 }
155165 else throw("Strict value is not equal to itself.")
156166 }
157167
158168
159169
160170 @Callable(i)
161171 func init (AdminAddress) = [writeConstString(admin, toString(addressFromStringValue(AdminAddress)))]
162172
163173
164174
165175 @Callable(i)
166176 func addAdmin (AdminAddress) = {
167177 let check = adminOnly(i)
168178 if ((check == check))
169179 then {
170180 let newAdmin = (admin + AdminAddress)
171181 [writeConstString(newAdmin, AdminAddress)]
172182 }
173183 else throw("Strict value is not equal to itself.")
174184 }
175185
176186
177187
178188 @Callable(i)
179189 func changeMainAdmin (address) = {
180190 let checks = adminOnly(i)
181191 if ((checks == checks))
182192 then {
183193 let del = DeleteEntry(admin)
184194 if ((del == del))
185195 then [writeConstString(admin, address)]
186196 else throw("Strict value is not equal to itself.")
187197 }
188198 else throw("Strict value is not equal to itself.")
189199 }
190200
191201
192202
193203 @Callable(i)
194204 func updateOtherAdminAddress (address) = {
195205 let checks = adminOnly(i)
196206 if ((checks == checks))
197207 then {
198208 let caller = toString(i.caller)
199209 let otherAdmin = (admin + caller)
200210 let checkOldAddress = throwOrReturnS(getS(otherAdmin), "no previous address found")
201211 if ((checkOldAddress == checkOldAddress))
202212 then {
203213 let delAddress = DeleteEntry(otherAdmin)
204214 if ((delAddress == delAddress))
205215 then [writeConstString(otherAdmin, address)]
206216 else throw("Strict value is not equal to itself.")
207217 }
208218 else throw("Strict value is not equal to itself.")
209219 }
210220 else throw("Strict value is not equal to itself.")
211221 }
212222
213223
214224
215225 @Callable(i)
216226 func removeOtherAdmin (address) = {
217227 let checks = adminOnly(i)
218228 if ((checks == checks))
219229 then {
220230 let otherAddress = (admin + address)
221231 let delAdmin = DeleteEntry(otherAddress)
222232 if ((delAdmin == delAdmin))
223233 then nil
224234 else throw("Strict value is not equal to itself.")
225235 }
226236 else throw("Strict value is not equal to itself.")
227237 }
228238
229239
230240
231241 @Callable(i)
232242 func updateConfigValue (key,data) = {
233243 let checks = adminOnly(i)
234244 if ((checks == checks))
235245 then {
236246 let del = DeleteEntry(key)
237247 if ((del == del))
238248 then [writeConfigValue(key, data)]
239249 else throw("Strict value is not equal to itself.")
240250 }
241251 else throw("Strict value is not equal to itself.")
242252 }
243253
244254
245255
246256 @Callable(i)
257+func getDaysLeftToClaim (userAddress) = {
258+ let check0 = adminOnly(i)
259+ if ((check0 == check0))
260+ then {
261+ let check1 = valueOrErrorMessage(addressFromString(userAddress), "invalid address")
262+ if ((check1 == check1))
263+ then {
264+ let uEntryIndex = ("_" + toString(throwOrReturnI(getI((userAddress + entryIndex)), ("no entry found for " + userAddress))))
265+ let uUnlockEligibility = ((userAddress + uEntryIndex) + unlockEligibility)
266+ let uBlocks = throwOrReturnI(getI(uUnlockEligibility), "internal error")
267+ let uBlocksToDays = daysToBlocks((height - uBlocks))
268+ $Tuple2(nil, uBlocksToDays)
269+ }
270+ else throw("Strict value is not equal to itself.")
271+ }
272+ else throw("Strict value is not equal to itself.")
273+ }
274+
275+
276+
277+@Callable(i)
247278 func Lock (LockPeriod,AssetTicker,APY) = {
248- let check1 = throwIf((1 != size(i.payments)), "Attach amount you want to lock")
279+ let check1 = throwIf((1 != size(i.payments)), "attach amount you want to lock")
249280 if ((check1 == check1))
250281 then {
251282 let asset = toBase58String(value(i.payments[0].assetId))
252- let check2 = throwIf((getS(AssetTicker) != asset), "Asset not supported")
283+ let check2 = throwIf((getS(AssetTicker) != asset), "asset not supported")
253284 if ((check2 == check2))
254285 then {
255286 let lockPeriod = LockPeriod
256287 let userId = toString(i.caller)
257288 let amountToStake = i.payments[0].amount
258289 let minToStake = throwOrReturnI(getI((AssetTicker + minimumLockAmount)), "internal error: minimum stacking amount not specified")
259290 let maxToStake = throwOrReturnI(getI((AssetTicker + maximumLockAmount)), "internal error: maximum staking amount not specified")
260291 let check3 = throwIf(if ((minToStake > amountToStake))
261292 then true
262293 else (amountToStake > maxToStake), "staking amount is out of range")
263294 if ((check3 == check3))
264295 then {
265- let uUserId = (userId + user)
266- let uAsset = (userId + lockedAsset)
267- let uLockingPeriod = (userId + lockingPeriod)
268- let uLockedAmount = (userId + lockedAmount)
269- let uAPY = (userId + APY_Amount)
270- let uUnlockEligibility = (userId + unlockEligibility)
271-[writeStr(uUserId, userId), writeStr(uAsset, asset), writeInt(uLockingPeriod, lockPeriod), writeInt(uLockedAmount, i.payments[0].amount), writeInt(uUnlockEligibility, daysToBlocks(LockPeriod)), writeInt(uAPY, APY)]
296+ let uTotalLocked = (userId + totalLockedAMount)
297+ let uSumTotal = if (!(isDefined(getI(uTotalLocked))))
298+ then 0
299+ else (amountToStake + value(getI(uTotalLocked)))
300+ let check4 = throwIf((uSumTotal > maxToStake), "you have maxed out your quota")
301+ if ((check4 == check4))
302+ then {
303+ let uEntryIndex = ((userId + AssetTicker) + entryIndex)
304+ let uIncrEntryIndex = incrementEntryIndex(uEntryIndex)
305+ let uEntryToString = ((("_" + AssetTicker) + "_") + toString(uIncrEntryIndex))
306+ let uUserId = ((userId + uEntryToString) + user)
307+ let uAsset = ((userId + uEntryToString) + lockedAsset)
308+ let uLockingPeriod = ((userId + uEntryToString) + lockingPeriod)
309+ let uLockedAmount = ((userId + uEntryToString) + lockedAmount)
310+ let uAPY = ((userId + uEntryToString) + APY_Amount)
311+ let uUnlockEligibility = ((userId + uEntryToString) + unlockEligibility)
312+ let uAlreadyClaimed = ((userId + uEntryToString) + alreadyClaimed)
313+[writeConstInteger(uEntryIndex, uIncrEntryIndex), writeConstString(uUserId, userId), writeConstString(uAsset, asset), writeConstInteger(uLockingPeriod, lockPeriod), writeConstInteger(uLockedAmount, i.payments[0].amount), writeConstInteger(uTotalLocked, uSumTotal), writeConstInteger(uUnlockEligibility, daysToBlocks(LockPeriod)), writeConstInteger(uAPY, APY), BooleanEntry(uAlreadyClaimed, false)]
314+ }
315+ else throw("Strict value is not equal to itself.")
272316 }
273317 else throw("Strict value is not equal to itself.")
274318 }
275319 else throw("Strict value is not equal to itself.")
276320 }
277321 else throw("Strict value is not equal to itself.")
278322 }
279323
280324
281325
282326 @Callable(i)
283327 func Claim (AssetTicker) = {
284328 let userId = toString(i.caller)
285- let uAsset = throwOrReturnS(getS((userId + lockedAsset)), ("there are no locked tokens for " + userId))
286- let uLockedAmount = throwOrReturnI(getI((userId + lockedAmount)), "internal error: could not retrieve locked amount")
287- let stakingReserve = addressFromStringValue(throwOrReturnS(getS((AssetTicker + stakingStore)), "internal error: staking store not found for asset"))
288- let APYAMount = throwOrReturnI(getI((userId + APY_Amount)), "internal error: failed to get APY")
289- let period = throwOrReturnI(getI((userId + unlockEligibility)), "internal error: could not determine claim eligibility")
290- let blocksLeft = if ((0 >= (period - height)))
291- then 0
292- else (period - height)
293- let daysLeft = blocksToDays(blocksLeft)
294- let check1 = throwIf((period > height), (toString(daysLeft) + " days left to claim"))
295- if ((check1 == check1))
329+ let uEntryIndex = ((("_" + AssetTicker) + "_") + toString(throwOrReturnI(getI(((userId + AssetTicker) + entryIndex)), "no entry found for user")))
330+ let uAlreadyClaimedKey = ((userId + uEntryIndex) + alreadyClaimed)
331+ let check0 = throwIf((valueOrErrorMessage(getBoolean(uAlreadyClaimedKey), "cannot ascertain claimability") == true), (("user + " + userId) + " already claimed"))
332+ if ((check0 == check0))
296333 then {
297- let transferAPYAmount = invoke(stakingReserve, "transferInterest", [userId, APYAMount, toBytes(uAsset)], nil)
298- if ((transferAPYAmount == transferAPYAmount))
299- then [ScriptTransfer(addressFromStringValue(userId), uLockedAmount, toBytes(uAsset))]
334+ let uAsset = getSV(((userId + uEntryIndex) + lockedAsset))
335+ let uLockedAmount = getIV(((userId + uEntryIndex) + lockedAmount))
336+ let stakingReserve = addressFromStringValue(throwOrReturnS(getS((AssetTicker + stakingStore)), "internal error: no reserve found"))
337+ let APYAMount = getIV(((userId + uEntryIndex) + APY_Amount))
338+ let period = getIV(((userId + uEntryIndex) + unlockEligibility))
339+ let blocksLeft = if ((0 >= (period - height)))
340+ then 0
341+ else (period - height)
342+ let daysLeft = blocksToDays(blocksLeft)
343+ let check1 = throwIf((period > height), (toString(daysLeft) + "/1000 days left to claim"))
344+ if ((check1 == check1))
345+ then {
346+ let transferAPYAmount = invoke(stakingReserve, "transferInterest", [userId, APYAMount, toBytes(uAsset)], nil)
347+ if ((transferAPYAmount == transferAPYAmount))
348+ then [ScriptTransfer(addressFromStringValue(userId), uLockedAmount, toBytes(uAsset)), BooleanEntry(uAlreadyClaimedKey, true)]
349+ else throw("Strict value is not equal to itself.")
350+ }
300351 else throw("Strict value is not equal to itself.")
301352 }
302353 else throw("Strict value is not equal to itself.")
303354 }
304355
305356

github/deemru/w8io/169f3d6 
55.29 ms