tx · 2RTCA7ce4hGguWW1VfsS7BeVt2SRsFc3j6ELKb5q42XR 3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9: -0.14000000 Waves 2022.06.07 12:18 [2085754] smart account 3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9 > SELF 0.00000000 Waves
{ "type": 13, "id": "2RTCA7ce4hGguWW1VfsS7BeVt2SRsFc3j6ELKb5q42XR", "fee": 14000000, "feeAssetId": null, "timestamp": 1654593510214, "version": 2, "chainId": 84, "sender": "3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9", "senderPublicKey": "D1X9WatF6ARMCmm3jC4Ex5Wd5VQ3LY8i1xbHNqeHqeAa", "proofs": [ "4SMX3ES8qWVoEP1DAuFWX4rN581Uw3dYHsjGBGeY3xNqSUEehbnk37bdzY2ni7f5M6k7GeqMZMq7kfYvvWH3CXtb", "4FiM7CixssnLRheZ6Kf1eg654SJZxLHmNuaf8APo15n5GtFHygUGdxCgewAR3FFjzoapc7a7ZBesjjmJWkHQA4j5" ], "script": "base64:AAIFAAAAAAAAAB8IAhIAEgQKAggIEgQKAggIEgMKAQQSAwoBCBIDCgEIAAAAFAAAAAAOa1Bvb2xzTGlzdE5hbWUCAAAABXBvb2xzAAAAAA9rUHJlZml4UG9vbE5hbWUCAAAABXBvb2xfAAAAABBrUHJlZml4UG9vbEluZGV4AgAAAAZpbmRleF8AAAAABWtQYWlyAgAAAAVwYWlyXwAAAAAJa0Fzc2V0SWRBAgAAAApBX2Fzc2V0X2lkAAAAAAlrQXNzZXRJZEICAAAACkJfYXNzZXRfaWQAAAAAH2tMYXVuY2hwYWREYXRhVHJhbnNhY3Rpb25TdGF0dXMCAAAAIWxhdW5jaHBhZF9kYXRhX3RyYW5zYWN0aW9uX3N0YXR1cwAAAAANa0FkbWluUHViS2V5MQIAAAALYWRtaW5fcHViXzEAAAAADWtBZG1pblB1YktleTICAAAAC2FkbWluX3B1Yl8yAAAAAA1rQWRtaW5QdWJLZXkzAgAAAAthZG1pbl9wdWJfMwAAAAASa0FkbWluSW52b2tlUHViS2V5AgAAABBhZG1pbl9pbnZva2VfcHViAAAAABRrQWNoaWV2ZW1lbnRzV3JpdGVycwIAAAAUYWNoaWV2ZW1lbnRzX3dyaXRlcnMAAAAADGFkbWluUHViS2V5MQEAAAAg4qeMQDuGzRfmtEuH2+Whg6yuKqHsNy5eZQUT8rXs7wQAAAAADGFkbWluUHViS2V5MgEAAAAg6jisuQG1iDxyo54oPYHUGiJlERON346DjXz9V/GbEVkAAAAADGFkbWluUHViS2V5MwEAAAAgpzSWgrCjycddMmIBfztFJ08z6r82xAHPELd0cKonzG4AAAAAEWFkbWluUHViS2V5SW52b2tlAQAAACAEz3XlZNDBD05nuR8TZMQaDeqEJEIxfTOQXUBYCp2TSgAAAAAFcG9vbHMEAAAAByRtYXRjaDAJAAQdAAAAAgUAAAAEdGhpcwUAAAAOa1Bvb2xzTGlzdE5hbWUDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABlN0cmluZwQAAAAGc3RyaW5nBQAAAAckbWF0Y2gwCQAEtQAAAAIFAAAABnN0cmluZwIAAAABLAQAAAAHbm90aGluZwUAAAAHJG1hdGNoMAUAAAADbmlsAQAAAAppc1NlbGZDYWxsAAAAAQAAAAFpAwkAAAAAAAACCAUAAAABaQAAAAZjYWxsZXIFAAAABHRoaXMFAAAABHVuaXQJAAACAAAAAQIAAAAvT25seSB0aGUgT3JhY2xlIGl0c2VsZiBjYW4gaW52b2tlIHRoaXMgZnVuY3Rpb24BAAAAEmdldFBvb2xOYW1lSWZWYWxpZAAAAAEAAAAIcG9vbE5hbWUEAAAAD3VuZGVyc2NvcmVJbmRleAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABLMAAAACBQAAAAhwb29sTmFtZQIAAAABXwD//////////wQAAAATdW5kZXJzY29yZUxhc3RJbmRleAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABLcAAAACBQAAAAhwb29sTmFtZQIAAAABXwD//////////wQAAAATaGFzU2luZ2xlVW5kZXJzY29yZQMDCQAAAAAAAAIFAAAAD3VuZGVyc2NvcmVJbmRleAUAAAATdW5kZXJzY29yZUxhc3RJbmRleAkAAGYAAAACBQAAAA91bmRlcnNjb3JlSW5kZXgAAAAAAAAAAAAHCQEAAAACIT0AAAACBQAAAA91bmRlcnNjb3JlSW5kZXgJAABlAAAAAgkAATEAAAABBQAAAAhwb29sTmFtZQAAAAAAAAAAAQcDBQAAABNoYXNTaW5nbGVVbmRlcnNjb3JlBQAAAAhwb29sTmFtZQkAAAIAAAABAgAAAE5Qb29sIG5hbWUgbXVzdCBjb25zaXN0IG9mIHR3byBhc3NldCBuYW1lcyBzZXBhcmF0ZWQgYnkgYW4gdW5kZXJzY29yZSBjaGFyYWN0ZXIBAAAAEWdldEFkZHJlc3NJZlZhbGlkAAAAAQAAAAdhZGRyZXNzCQAEJQAAAAEJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABCYAAAABBQAAAAdhZGRyZXNzCQABLAAAAAIJAAEsAAAAAgIAAAANQ2FuJ3QgcGFyc2UgIgUAAAAHYWRkcmVzcwIAAAAMIiBhcyBhZGRyZXNzAAAABgAAAAFpAQAAAAhzZXRBZG1pbgAAAAAJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAQAAAAppc1NlbGZDYWxsAAAAAQUAAAABaQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAA1rQWRtaW5QdWJLZXkxCQACWAAAAAEFAAAADGFkbWluUHViS2V5MQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAA1rQWRtaW5QdWJLZXkyCQACWAAAAAEFAAAADGFkbWluUHViS2V5MgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAA1rQWRtaW5QdWJLZXkzCQACWAAAAAEFAAAADGFkbWluUHViS2V5MwkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABJrQWRtaW5JbnZva2VQdWJLZXkJAAJYAAAAAQUAAAARYWRtaW5QdWJLZXlJbnZva2UFAAAAA25pbAAAAAFpAQAAAAdhZGRQb29sAAAAAgAAAAtwb29sQWRkcmVzcwAAAAhwb29sTmFtZQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkBAAAACmlzU2VsZkNhbGwAAAABBQAAAAFpBAAAABB2YWxpZGF0ZWRBZGRyZXNzCQEAAAARZ2V0QWRkcmVzc0lmVmFsaWQAAAABBQAAAAtwb29sQWRkcmVzcwQAAAAHa2V5TmFtZQkAASwAAAACBQAAAA9rUHJlZml4UG9vbE5hbWUFAAAAEHZhbGlkYXRlZEFkZHJlc3MEAAAACGtleUluZGV4CQABLAAAAAIFAAAAEGtQcmVmaXhQb29sSW5kZXgFAAAAEHZhbGlkYXRlZEFkZHJlc3MEAAAACGFzc2V0SWRBCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgkBAAAABXZhbHVlAAAAAQkABCYAAAABBQAAAAtwb29sQWRkcmVzcwUAAAAJa0Fzc2V0SWRBAgAAABdBc3NldCBpZCBBIGlzIGluY29ycmVjdAQAAAAIYXNzZXRJZEIJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACCQEAAAAFdmFsdWUAAAABCQAEJgAAAAEFAAAAC3Bvb2xBZGRyZXNzBQAAAAlrQXNzZXRJZEICAAAAF0Fzc2V0IGlkIEIgaXMgaW5jb3JyZWN0BAAAABhwb3NzaWJseUFscmVhZHlBZGRlZFBvb2wJAAQdAAAAAgUAAAAEdGhpcwUAAAAHa2V5TmFtZQMJAQAAAAlpc0RlZmluZWQAAAABBQAAABhwb3NzaWJseUFscmVhZHlBZGRlZFBvb2wJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAABNQb29sIHdpdGggYWRkcmVzcyAiBQAAABB2YWxpZGF0ZWRBZGRyZXNzAgAAACAiIGlzIGFscmVhZHkgZGVmaW5lZCB3aXRoIG5hbWUgIgkBAAAABXZhbHVlAAAAAQUAAAAYcG9zc2libHlBbHJlYWR5QWRkZWRQb29sAgAAAAEiCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAhrZXlJbmRleAkAAZAAAAABBQAAAAVwb29scwkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAdrZXlOYW1lCQEAAAASZ2V0UG9vbE5hbWVJZlZhbGlkAAAAAQUAAAAIcG9vbE5hbWUJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgUAAAAFa1BhaXIFAAAACGFzc2V0SWRBAgAAAAFfBQAAAAhhc3NldElkQgUAAAALcG9vbEFkZHJlc3MJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAOa1Bvb2xzTGlzdE5hbWUJAAS5AAAAAgkABE0AAAACBQAAAAVwb29scwUAAAAQdmFsaWRhdGVkQWRkcmVzcwIAAAABLAUAAAADbmlsAAAAAWkBAAAACnJlbmFtZVBvb2wAAAACAAAAC3Bvb2xBZGRyZXNzAAAAC25ld1Bvb2xOYW1lCQEAAAALdmFsdWVPckVsc2UAAAACCQEAAAAKaXNTZWxmQ2FsbAAAAAEFAAAAAWkEAAAAEHZhbGlkYXRlZEFkZHJlc3MJAQAAABFnZXRBZGRyZXNzSWZWYWxpZAAAAAEFAAAAC3Bvb2xBZGRyZXNzBAAAAAdrZXlOYW1lCQABLAAAAAIFAAAAD2tQcmVmaXhQb29sTmFtZQUAAAAQdmFsaWRhdGVkQWRkcmVzcwQAAAAYcG9zc2libHlBbHJlYWR5QWRkZWRQb29sCQAEHQAAAAIFAAAABHRoaXMFAAAAB2tleU5hbWUDCQEAAAAJaXNEZWZpbmVkAAAAAQUAAAAYcG9zc2libHlBbHJlYWR5QWRkZWRQb29sCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAA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AAckbWF0Y2gwAgAAABZMZWFzZUNhbmNlbFRyYW5zYWN0aW9uBgMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAQTGVhc2VUcmFuc2FjdGlvbgYDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAEElzc3VlVHJhbnNhY3Rpb24GAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABpVcGRhdGVBc3NldEluZm9UcmFuc2FjdGlvbgYDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAF0ludm9rZVNjcmlwdFRyYW5zYWN0aW9uBgMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAZU2V0QXNzZXRTY3JpcHRUcmFuc2FjdGlvbgYDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAE1RyYW5zZmVyVHJhbnNhY3Rpb24GAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAABNFeGNoYW5nZVRyYW5zYWN0aW9uBgMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAXTWFzc1RyYW5zZmVyVHJhbnNhY3Rpb24GAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAA9CdXJuVHJhbnNhY3Rpb24GCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAElJlaXNzdWVUcmFuc2FjdGlvbgUAAAANc2lnbmVkQnlBZG1pbgkAAAIAAAABAgAAAAtNYXRjaCBlcnJvctHcgDs=", "height": 2085754, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: HL89nzomh7ctoMnL7kJvWs5YmkzYz9sHAAJX3Q6y5sVc Next: 37TExifogww359RfURTGDrep7n1gNyn53g5hGEQsSndX Diff:
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | - | let | |
4 | + | let kPoolsListName = "pools" | |
5 | 5 | ||
6 | - | let | |
6 | + | let kPrefixPoolName = "pool_" | |
7 | 7 | ||
8 | - | let | |
8 | + | let kPrefixPoolIndex = "index_" | |
9 | 9 | ||
10 | - | let | |
10 | + | let kPair = "pair_" | |
11 | 11 | ||
12 | - | let | |
12 | + | let kAssetIdA = "A_asset_id" | |
13 | 13 | ||
14 | - | let | |
14 | + | let kAssetIdB = "B_asset_id" | |
15 | 15 | ||
16 | - | let kTotalSWOPLocked = "total_SWOP_amount" | |
17 | - | ||
18 | - | let kUserTotalVoteSWOP = "_user_total_SWOP_vote" | |
19 | - | ||
20 | - | let kUserVoteOptionAmount = "_SWOP_option_amount" | |
21 | - | ||
22 | - | let kTotalVoteOptionAmount = "total_SWOP_option_amount" | |
23 | - | ||
24 | - | let kUserSWOPClaimedAmount = "_SWOP_claimed_amount" | |
25 | - | ||
26 | - | let kUserSWOPLastClaimedAmount = "_SWOP_last_claimed_amount" | |
27 | - | ||
28 | - | let kVoteName = "vote_name" | |
29 | - | ||
30 | - | let kOptionName = "_option_name" | |
31 | - | ||
32 | - | let kVotingStartHeight = "_startHeight" | |
33 | - | ||
34 | - | let kVoteDuration = "_vote_duration" | |
35 | - | ||
36 | - | let kRewardPoolFractionCurrent = "_current_pool_fraction_reward" | |
37 | - | ||
38 | - | let kRewardPoolFractionPrevious = "_previous_pool_fraction_reward" | |
39 | - | ||
40 | - | let kHeightPoolFraction = "_pool_reward_update_height" | |
41 | - | ||
42 | - | let kTotalRewardPerBlockCurrent = "total_reward_per_block_current" | |
43 | - | ||
44 | - | let kTotalRewardPerBlockPrevious = "total_reward_per_block_previous" | |
45 | - | ||
46 | - | let kRewardUpdateHeight = "reward_update_height" | |
47 | - | ||
48 | - | let kRewardUpdateFirstPaginationHeight = "reward_update_height_first_pagination" | |
49 | - | ||
50 | - | let kNoVotingForNewPool = "_vote_no" | |
51 | - | ||
52 | - | let kYesVotingForNewPool = "_vote_yes" | |
53 | - | ||
54 | - | let kAmountOfVotingForNewPool = "max_amount_voting" | |
55 | - | ||
56 | - | let kStatusOfVotingForNewPool = "_status" | |
57 | - | ||
58 | - | let kHeightOfPoolVotingForNewPool = "_finish_height" | |
59 | - | ||
60 | - | let activeVoteFirst = "voting_active_cell_1" | |
61 | - | ||
62 | - | let activeVoteSecond = "voting_active_cell_2" | |
63 | - | ||
64 | - | let activeVoteThird = "voting_active_cell_3" | |
65 | - | ||
66 | - | let kTempCurSum = "sum_reward_current" | |
67 | - | ||
68 | - | let kLaunchpadBoughtTickets = "_bought_tickets" | |
69 | - | ||
70 | - | let kLaunchpadSwopPerTickets = "_swop_per_ticket" | |
71 | - | ||
72 | - | let kLaunchpadActiveId = "launchpad_active_id" | |
73 | - | ||
74 | - | let kLaunchpadDuration = "_duration" | |
75 | - | ||
76 | - | let kLaunchpadStartHeight = "_start_height" | |
77 | - | ||
78 | - | let kStartHeight = "start_height" | |
79 | - | ||
80 | - | let kBasePeriod = "base_period" | |
81 | - | ||
82 | - | let kPeriodLength = "period_length" | |
83 | - | ||
84 | - | let kUserTotalStruc = "_user_total_struc" | |
85 | - | ||
86 | - | let kLauchpadFreezSwopDuration = "_freeze_swop_duration" | |
87 | - | ||
88 | - | let kSWOPid = "SWOP_id" | |
89 | - | ||
90 | - | let kAirdropFee = "airdrop_fee" | |
16 | + | let kLaunchpadDataTransactionStatus = "launchpad_data_transaction_status" | |
91 | 17 | ||
92 | 18 | let kAdminPubKey1 = "admin_pub_1" | |
93 | 19 | ||
95 | 21 | ||
96 | 22 | let kAdminPubKey3 = "admin_pub_3" | |
97 | 23 | ||
98 | - | let | |
24 | + | let kAdminInvokePubKey = "admin_invoke_pub" | |
99 | 25 | ||
100 | - | let | |
26 | + | let kAchievementsWriters = "achievements_writers" | |
101 | 27 | ||
102 | - | let | |
28 | + | let adminPubKey1 = base58'GFmKZ2naZFRoCvNbwKAQVGmLb1uBeWGDgFabdGBuZiuy' | |
103 | 29 | ||
104 | - | let | |
30 | + | let adminPubKey2 = base58'GmJXRyhRA79g8yUGgKBAVdnFfQFDMjQG98b1MmLDh5kk' | |
105 | 31 | ||
106 | - | let | |
32 | + | let adminPubKey3 = base58'CFhbV6h41hVjbGHudGtS3fYUv7QAKRxFQzKNtx4B5PqP' | |
107 | 33 | ||
108 | - | let | |
34 | + | let adminPubKeyInvoke = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK' | |
109 | 35 | ||
110 | - | let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9') | |
111 | - | ||
112 | - | func getBase58FromOracle (key) = match getString(oracle, key) { | |
36 | + | let pools = match getString(this, kPoolsListName) { | |
113 | 37 | case string: String => | |
114 | - | | |
38 | + | split(string, ",") | |
115 | 39 | case nothing => | |
116 | - | | |
40 | + | nil | |
117 | 41 | } | |
118 | 42 | ||
119 | - | ||
120 | - | let adminPubKey1 = getBase58FromOracle(kAdminPubKey1) | |
121 | - | ||
122 | - | let adminPubKey2 = getBase58FromOracle(kAdminPubKey2) | |
123 | - | ||
124 | - | let adminPubKey3 = getBase58FromOracle(kAdminPubKey3) | |
125 | - | ||
126 | - | let moneyBoxPubKey = getBase58FromOracle(kMoneyBoxPubKey) | |
127 | - | ||
128 | - | let farmingAddr = Address(getBase58FromOracle(kFarmingAddr)) | |
129 | - | ||
130 | - | let votingAddr = Address(getBase58FromOracle(kVotingAddr)) | |
131 | - | ||
132 | - | let votingNewPoolAddr = Address(getBase58FromOracle(kVotingNewPoolAddr)) | |
133 | - | ||
134 | - | let launchpadAddr = Address(getBase58FromOracle(kLaunchpadAddr)) | |
135 | - | ||
136 | - | let airdropMoneyBoxAddr = Address(getBase58FromOracle(kAirdropMoneyBoxAddr)) | |
137 | - | ||
138 | - | let SWOP = fromBase58String(getStringValue(farmingAddr, kSWOPid)) | |
139 | - | ||
140 | - | let scaleValue = 100000000 | |
141 | - | ||
142 | - | let totalVoteShare = 10000000000 | |
143 | - | ||
144 | - | let basePeriod = valueOrErrorMessage(getInteger(votingAddr, kBasePeriod), "Empty kBasePeriod at voting contract") | |
145 | - | ||
146 | - | let startHeight = valueOrErrorMessage(getInteger(votingAddr, kStartHeight), "Empty kStartHeight at voting contract") | |
147 | - | ||
148 | - | let periodLength = valueOrErrorMessage(getInteger(votingAddr, kPeriodLength), "Empty kPeriodLength at voting contract") | |
149 | - | ||
150 | - | let firstActiveVote = valueOrElse(getString(votingNewPoolAddr, activeVoteFirst), "") | |
151 | - | ||
152 | - | let secondActiveVote = valueOrElse(getString(votingNewPoolAddr, activeVoteSecond), "") | |
153 | - | ||
154 | - | let thirdActiveVote = valueOrElse(getString(votingNewPoolAddr, activeVoteThird), "") | |
155 | - | ||
156 | - | let isActive = valueOrElse(getBoolean(this, kActive), true) | |
157 | - | ||
158 | - | let airdropFee = getIntegerValue(oracle, kAirdropFee) | |
159 | - | ||
160 | - | let currVotingPeriod = (basePeriod + ((height - startHeight) / periodLength)) | |
161 | - | ||
162 | - | func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)] | |
43 | + | func isSelfCall (i) = if ((i.caller == this)) | |
44 | + | then unit | |
45 | + | else throw("Only the Oracle itself can invoke this function") | |
163 | 46 | ||
164 | 47 | ||
165 | - | func throwNotEnoughSWOP () = throw("Not enough SWOP: userSWOPLocked - userTotalVoteAmount < voteSWOPAmount") | |
166 | - | ||
167 | - | ||
168 | - | func getLastInterestInfo () = valueOrElse(getInteger(this, kLastInterest), 0) | |
169 | - | ||
170 | - | ||
171 | - | func getUserSWOPLocked (user) = valueOrElse(getInteger(this, (toString(user) + kUserSWOPLocked)), 0) | |
172 | - | ||
173 | - | ||
174 | - | func getUserSWOPClaimedAmount (user) = valueOrElse(getInteger(this, (toString(user) + kUserSWOPClaimedAmount)), 0) | |
175 | - | ||
176 | - | ||
177 | - | func getUserTotalVoteAmount (user) = valueOrElse(getInteger(votingAddr, (toString(user) + kUserTotalVoteSWOP)), 0) | |
178 | - | ||
179 | - | ||
180 | - | func getUserInterestInfo (user,lastInterest) = { | |
181 | - | let userSWOPAmount = getUserSWOPLocked(user) | |
182 | - | let userLastInterest = getInteger(this, (toString(user) + kUserLastInterest)) | |
183 | - | let userLastInterestValue = match userLastInterest { | |
184 | - | case userLastInterest: Int => | |
185 | - | userLastInterest | |
186 | - | case _ => | |
187 | - | lastInterest | |
188 | - | } | |
189 | - | $Tuple2(userLastInterestValue, userSWOPAmount) | |
48 | + | func getPoolNameIfValid (poolName) = { | |
49 | + | let underscoreIndex = valueOrElse(indexOf(poolName, "_"), -1) | |
50 | + | let underscoreLastIndex = valueOrElse(lastIndexOf(poolName, "_"), -1) | |
51 | + | let hasSingleUnderscore = if (if ((underscoreIndex == underscoreLastIndex)) | |
52 | + | then (underscoreIndex > 0) | |
53 | + | else false) | |
54 | + | then (underscoreIndex != (size(poolName) - 1)) | |
55 | + | else false | |
56 | + | if (hasSingleUnderscore) | |
57 | + | then poolName | |
58 | + | else throw("Pool name must consist of two asset names separated by an underscore character") | |
190 | 59 | } | |
191 | 60 | ||
192 | 61 | ||
193 | - | func getUserTotalVoteAmountForOnePool (pool,user) = { | |
194 | - | let voting = valueOrElse(getInteger(votingNewPoolAddr, pool), -1) | |
195 | - | let heightOfVoting = valueOrElse(getInteger(votingNewPoolAddr, (toString(voting) + kHeightOfPoolVotingForNewPool)), 0) | |
196 | - | let statusOfVoting = valueOrElse(getBoolean(votingNewPoolAddr, (toString(voting) + kStatusOfVotingForNewPool)), true) | |
197 | - | let currentHeight = height | |
198 | - | if ((0 > voting)) | |
199 | - | then 0 | |
200 | - | else if (!(statusOfVoting)) | |
201 | - | then 0 | |
202 | - | else if ((heightOfVoting > currentHeight)) | |
203 | - | then (valueOrElse(getInteger(votingNewPoolAddr, (((toString(user) + "_") + toString(voting)) + kYesVotingForNewPool)), 0) + valueOrElse(getInteger(votingNewPoolAddr, (((toString(user) + "_") + toString(voting)) + kNoVotingForNewPool)), 0)) | |
204 | - | else 0 | |
205 | - | } | |
206 | - | ||
207 | - | ||
208 | - | func getUserTotalVoteForNewPoolAmount (user) = { | |
209 | - | let listOfVoting = [getUserTotalVoteAmountForOnePool(firstActiveVote, user), getUserTotalVoteAmountForOnePool(secondActiveVote, user), getUserTotalVoteAmountForOnePool(thirdActiveVote, user)] | |
210 | - | max(listOfVoting) | |
211 | - | } | |
212 | - | ||
213 | - | ||
214 | - | func getUserBlockedInLauchpad (user) = { | |
215 | - | let lauchpadId = toString(valueOrElse(getInteger(launchpadAddr, kLaunchpadActiveId), 0)) | |
216 | - | if ((lauchpadId == "0")) | |
217 | - | then 0 | |
218 | - | else { | |
219 | - | let lStartHeight = valueOrElse(getInteger(launchpadAddr, (lauchpadId + kLaunchpadStartHeight)), 0) | |
220 | - | let lDuration = valueOrElse(getInteger(launchpadAddr, (lauchpadId + kLaunchpadDuration)), 0) | |
221 | - | let lFreezeSwopDuration = valueOrElse(getInteger(launchpadAddr, (lauchpadId + kLauchpadFreezSwopDuration)), 0) | |
222 | - | let blockEndHeight = ((lStartHeight + lDuration) + lFreezeSwopDuration) | |
223 | - | if ((height > blockEndHeight)) | |
224 | - | then 0 | |
225 | - | else { | |
226 | - | let boughtTickets = valueOrElse(getInteger(launchpadAddr, (((toString(user) + "_") + lauchpadId) + kLaunchpadBoughtTickets)), 0) | |
227 | - | let swopPerTicket = valueOrElse(getInteger(launchpadAddr, (lauchpadId + kLaunchpadSwopPerTickets)), 0) | |
228 | - | (boughtTickets * swopPerTicket) | |
229 | - | } | |
230 | - | } | |
231 | - | } | |
232 | - | ||
233 | - | ||
234 | - | func getTotalSWOPLocked () = valueOrElse(getInteger(this, kTotalSWOPLocked), 0) | |
235 | - | ||
236 | - | ||
237 | - | func getUserVoteInfo (user) = { | |
238 | - | let $t075828115 = if (isDefined(getString(votingAddr, (toString(user) + kUserTotalStruc)))) | |
239 | - | then { | |
240 | - | let data = split(valueOrErrorMessage(getString(votingAddr, (toString(user) + kUserTotalStruc)), "Empty kUserTotalStruc"), "_") | |
241 | - | $Tuple3(parseIntValue(data[0]), parseIntValue(data[1]), parseIntValue(data[2])) | |
242 | - | } | |
243 | - | else { | |
244 | - | let uPoolTotalSWOP = valueOrElse(getInteger(votingAddr, (toString(user) + kUserTotalVoteSWOP)), 0) | |
245 | - | $Tuple3(uPoolTotalSWOP, 0, currVotingPeriod) | |
246 | - | } | |
247 | - | let userTotalVoteSWOP = $t075828115._1 | |
248 | - | let userUnvoted = $t075828115._2 | |
249 | - | let userUnvotedPeriod = $t075828115._3 | |
250 | - | let userUnvotedActual = if ((userUnvotedPeriod == currVotingPeriod)) | |
251 | - | then userUnvoted | |
252 | - | else 0 | |
253 | - | $Tuple2(userTotalVoteSWOP, userUnvotedActual) | |
254 | - | } | |
255 | - | ||
256 | - | ||
257 | - | func getUserVoteOptionAmount (user) = valueOrElse(getInteger(this, (toString(user) + kUserVoteOptionAmount)), 0) | |
258 | - | ||
259 | - | ||
260 | - | func getVotingStartHeight (voteName) = valueOrElse(getInteger(this, (voteName + kVotingStartHeight)), 0) | |
261 | - | ||
262 | - | ||
263 | - | func getPoolUpdateHeight (pool) = valueOrElse(getInteger(this, (pool + kHeightPoolFraction)), 0) | |
264 | - | ||
265 | - | ||
266 | - | func isDefinePoolUpdateHeight (pool) = isDefined(getInteger(this, (pool + kHeightPoolFraction))) | |
267 | - | ||
268 | - | ||
269 | - | func getCurPoolWeight (pool) = valueOrElse(getInteger(this, (pool + kRewardPoolFractionCurrent)), 0) | |
270 | - | ||
271 | - | ||
272 | - | func getPrevPoolWeight (pool) = valueOrElse(getInteger(this, (pool + kRewardPoolFractionPrevious)), 0) | |
273 | - | ||
274 | - | ||
275 | - | func getVoteOptionAmount (user,voteName,option) = { | |
276 | - | let userVoteOptionAmount = getInteger(this, (((voteName + option) + toString(user)) + kUserVoteOptionAmount)) | |
277 | - | let uvoa = match userVoteOptionAmount { | |
278 | - | case uvoa: Int => | |
279 | - | uvoa | |
280 | - | case uvoa: Unit => | |
281 | - | 0 | |
282 | - | case _ => | |
283 | - | throw("Match error") | |
284 | - | } | |
285 | - | valueOrErrorMessage(uvoa, (((("No data on the key: " + voteName) + option) + toString(user)) + kUserVoteOptionAmount)) | |
286 | - | } | |
287 | - | ||
288 | - | ||
289 | - | func getVoteDuration (voteName) = valueOrErrorMessage(getInteger(this, (voteName + kVoteDuration)), (("No data on the key: " + voteName) + kVoteDuration)) | |
290 | - | ||
291 | - | ||
292 | - | func getTotalVoteOptionAmount (voteName,option) = { | |
293 | - | let totalVoteOptionAmount = getInteger(this, ((voteName + option) + kTotalVoteOptionAmount)) | |
294 | - | let tvoa = match totalVoteOptionAmount { | |
295 | - | case tvoa: Int => | |
296 | - | tvoa | |
297 | - | case tvoa: Unit => | |
298 | - | 0 | |
299 | - | case _ => | |
300 | - | throw("Match error") | |
301 | - | } | |
302 | - | tvoa | |
303 | - | } | |
304 | - | ||
305 | - | ||
306 | - | func getUserGetBackAmount (voteName,option,user,getBackSWOPHeight) = { | |
307 | - | let key = ((((((voteName + "_") + option) + "_") + toString(user)) + "_") + toString(getBackSWOPHeight)) | |
308 | - | valueOrErrorMessage(getInteger(this, key), ("No data on the key: " + key)) | |
309 | - | } | |
310 | - | ||
311 | - | ||
312 | - | func claimCalc (caller) = { | |
313 | - | let lastInterest = getLastInterestInfo() | |
314 | - | let $t01050610588 = getUserInterestInfo(caller, lastInterest) | |
315 | - | let userLastInterest = $t01050610588._1 | |
316 | - | let userSWOPLocked = $t01050610588._2 | |
317 | - | let claimAmount = fraction(userSWOPLocked, (lastInterest - userLastInterest), scaleValue) | |
318 | - | let userNewInterest = lastInterest | |
319 | - | $Tuple2(userNewInterest, claimAmount) | |
320 | - | } | |
62 | + | func getAddressIfValid (address) = toString(valueOrErrorMessage(addressFromString(address), (("Can't parse \"" + address) + "\" as address"))) | |
321 | 63 | ||
322 | 64 | ||
323 | 65 | @Callable(i) | |
324 | - | func airDrop () = if (!(isActive)) | |
325 | - | then throw("DApp is inactive at this moment") | |
326 | - | else { | |
327 | - | let $t01085610931 = $Tuple2(i.payments[0].amount, i.payments[0].assetId) | |
328 | - | let pmtAmount = $t01085610931._1 | |
329 | - | let pmtAssetId = $t01085610931._2 | |
330 | - | if ((pmtAssetId != SWOP)) | |
331 | - | then throw("Incorrect pmtAssetId") | |
332 | - | else { | |
333 | - | let airdropFeeAmount = fraction(pmtAmount, airdropFee, 100, CEILING) | |
334 | - | let totalSWOPLocked = getTotalSWOPLocked() | |
335 | - | let lastInterest = getLastInterestInfo() | |
336 | - | let interestNew = (lastInterest + fraction((pmtAmount - airdropFeeAmount), scaleValue, totalSWOPLocked)) | |
337 | - | [IntegerEntry(kLastInterest, interestNew), ScriptTransfer(airdropMoneyBoxAddr, airdropFeeAmount, SWOP)] | |
338 | - | } | |
339 | - | } | |
66 | + | func setAdmin () = valueOrElse(isSelfCall(i), [StringEntry(kAdminPubKey1, toBase58String(adminPubKey1)), StringEntry(kAdminPubKey2, toBase58String(adminPubKey2)), StringEntry(kAdminPubKey3, toBase58String(adminPubKey3)), StringEntry(kAdminInvokePubKey, toBase58String(adminPubKeyInvoke))]) | |
340 | 67 | ||
341 | 68 | ||
342 | 69 | ||
343 | 70 | @Callable(i) | |
344 | - | func lockSWOP () = if (!(isActive)) | |
345 | - | then throw("DApp is inactive at this moment") | |
346 | - | else { | |
347 | - | let $t01155811633 = $Tuple2(i.payments[0].amount, i.payments[0].assetId) | |
348 | - | let pmtAmount = $t01155811633._1 | |
349 | - | let pmtAssetId = $t01155811633._2 | |
350 | - | if ((pmtAssetId != SWOP)) | |
351 | - | then throw("Incorrect pmtAssetId") | |
352 | - | else { | |
353 | - | let lastInterest = getLastInterestInfo() | |
354 | - | let $t01174911833 = getUserInterestInfo(i.caller, lastInterest) | |
355 | - | let userLastInterest = $t01174911833._1 | |
356 | - | let userSWOPLocked = $t01174911833._2 | |
357 | - | let claimAmount = fraction(userSWOPLocked, (lastInterest - userLastInterest), scaleValue) | |
358 | - | let userSWOPLockedNew = ((userSWOPLocked + pmtAmount) + claimAmount) | |
359 | - | let userNewInterest = lastInterest | |
360 | - | let totalSWOPLocked = getTotalSWOPLocked() | |
361 | - | let totalSWOPLockedNew = ((totalSWOPLocked + pmtAmount) + claimAmount) | |
362 | - | let userClaimedAmount = getUserSWOPClaimedAmount(i.caller) | |
363 | - | let userClaimedAmountNew = (userClaimedAmount + claimAmount) | |
364 | - | [IntegerEntry((toString(i.caller) + kUserLastInterest), userNewInterest), IntegerEntry((toString(i.caller) + kUserSWOPLocked), userSWOPLockedNew), IntegerEntry(kTotalSWOPLocked, totalSWOPLockedNew), IntegerEntry((toString(i.caller) + kUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((toString(i.caller) + kUserSWOPLastClaimedAmount), claimAmount)] | |
365 | - | } | |
366 | - | } | |
71 | + | func addPool (poolAddress,poolName) = valueOrElse(isSelfCall(i), { | |
72 | + | let validatedAddress = getAddressIfValid(poolAddress) | |
73 | + | let keyName = (kPrefixPoolName + validatedAddress) | |
74 | + | let keyIndex = (kPrefixPoolIndex + validatedAddress) | |
75 | + | let assetIdA = valueOrErrorMessage(getString(value(addressFromString(poolAddress)), kAssetIdA), "Asset id A is incorrect") | |
76 | + | let assetIdB = valueOrErrorMessage(getString(value(addressFromString(poolAddress)), kAssetIdB), "Asset id B is incorrect") | |
77 | + | let possiblyAlreadyAddedPool = getString(this, keyName) | |
78 | + | if (isDefined(possiblyAlreadyAddedPool)) | |
79 | + | then throw((((("Pool with address \"" + validatedAddress) + "\" is already defined with name \"") + value(possiblyAlreadyAddedPool)) + "\"")) | |
80 | + | else [IntegerEntry(keyIndex, size(pools)), StringEntry(keyName, getPoolNameIfValid(poolName)), StringEntry((((kPair + assetIdA) + "_") + assetIdB), poolAddress), StringEntry(kPoolsListName, makeString((pools :+ validatedAddress), ","))] | |
81 | + | }) | |
367 | 82 | ||
368 | 83 | ||
369 | 84 | ||
370 | 85 | @Callable(i) | |
371 | - | func withdrawSWOP (withdrawAmount) = if (!(isActive)) | |
372 | - | then throw("DApp is inactive at this moment") | |
373 | - | else if ((0 >= withdrawAmount)) | |
374 | - | then throw("withdrawAmount <= 0") | |
375 | - | else { | |
376 | - | let totalSWOPLocked = getTotalSWOPLocked() | |
377 | - | let userSWOPLocked = getUserSWOPLocked(i.caller) | |
378 | - | let $t01297413029 = claimCalc(i.caller) | |
379 | - | let userNewInterest = $t01297413029._1 | |
380 | - | let claimAmount = $t01297413029._2 | |
381 | - | let $t01303413099 = getUserVoteInfo(i.caller) | |
382 | - | let userVoteAmount = $t01303413099._1 | |
383 | - | let userUnvoteAmount = $t01303413099._2 | |
384 | - | let userVoteAmountForNewPool = getUserTotalVoteForNewPoolAmount(i.caller) | |
385 | - | let blockedInLaunchpad = getUserBlockedInLauchpad(i.caller) | |
386 | - | if (if (if ((0 > userUnvoteAmount)) | |
387 | - | then true | |
388 | - | else (0 > userVoteAmount)) | |
389 | - | then true | |
390 | - | else (0 > userVoteAmountForNewPool)) | |
391 | - | then throw("userUnvoteAmount < 0 || userVoteAmount < 0 || userVoteAmountForNewPool < 0") | |
392 | - | else { | |
393 | - | let availableToUnstake = (userSWOPLocked - max([userVoteAmountForNewPool, (userVoteAmount + userUnvoteAmount), blockedInLaunchpad])) | |
394 | - | if ((withdrawAmount > availableToUnstake)) | |
395 | - | then throw("withdrawAmount > availableToUnstake") | |
396 | - | else { | |
397 | - | let totalSWOPLockedNew = ((totalSWOPLocked + claimAmount) - withdrawAmount) | |
398 | - | let userSWOPamountNew = ((userSWOPLocked + claimAmount) - withdrawAmount) | |
399 | - | let userClaimedAmount = getUserSWOPClaimedAmount(i.caller) | |
400 | - | let userClaimedAmountNew = (userClaimedAmount + claimAmount) | |
401 | - | [IntegerEntry((toString(i.caller) + kUserLastInterest), userNewInterest), IntegerEntry((toString(i.caller) + kUserSWOPLocked), userSWOPamountNew), IntegerEntry(kTotalSWOPLocked, totalSWOPLockedNew), ScriptTransfer(i.caller, withdrawAmount, SWOP), IntegerEntry((toString(i.caller) + kUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((toString(i.caller) + kUserSWOPLastClaimedAmount), claimAmount)] | |
402 | - | } | |
403 | - | } | |
404 | - | } | |
86 | + | func renamePool (poolAddress,newPoolName) = valueOrElse(isSelfCall(i), { | |
87 | + | let validatedAddress = getAddressIfValid(poolAddress) | |
88 | + | let keyName = (kPrefixPoolName + validatedAddress) | |
89 | + | let possiblyAlreadyAddedPool = getString(this, keyName) | |
90 | + | if (isDefined(possiblyAlreadyAddedPool)) | |
91 | + | then [StringEntry(keyName, getPoolNameIfValid(newPoolName))] | |
92 | + | else throw((("Pool with address \"" + validatedAddress) + "\" has not yet been added")) | |
93 | + | }) | |
405 | 94 | ||
406 | 95 | ||
407 | 96 | ||
408 | 97 | @Callable(i) | |
409 | - | func claimAndWithdrawSWOP () = if (!(isActive)) | |
410 | - | then throw("DApp is inactive at this moment") | |
411 | - | else { | |
412 | - | let lastInterest = getLastInterestInfo() | |
413 | - | let $t01454914604 = claimCalc(i.caller) | |
414 | - | let userNewInterest = $t01454914604._1 | |
415 | - | let claimAmount = $t01454914604._2 | |
416 | - | let userClaimedAmount = getUserSWOPClaimedAmount(i.caller) | |
417 | - | let userClaimedAmountNew = (userClaimedAmount + claimAmount) | |
418 | - | if ((claimAmount == 0)) | |
419 | - | then throw("You have 0 available SWOP") | |
420 | - | else [IntegerEntry((toString(i.caller) + kUserLastInterest), userNewInterest), IntegerEntry((toString(i.caller) + kUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((toString(i.caller) + kUserSWOPLastClaimedAmount), claimAmount), ScriptTransfer(i.caller, claimAmount, SWOP)] | |
421 | - | } | |
98 | + | func launchpadDataTransactionStatus (status) = valueOrElse(isSelfCall(i), [BooleanEntry(kLaunchpadDataTransactionStatus, status)]) | |
422 | 99 | ||
423 | 100 | ||
424 | 101 | ||
425 | 102 | @Callable(i) | |
426 | - | func claimAndStakeSWOP () = if (!(isActive)) | |
427 | - | then throw("DApp is inactive at this moment") | |
428 | - | else { | |
429 | - | let totalSWOPLocked = getTotalSWOPLocked() | |
430 | - | let userSWOPLocked = getUserSWOPLocked(i.caller) | |
431 | - | let lastInterest = getLastInterestInfo() | |
432 | - | let $t01537715432 = claimCalc(i.caller) | |
433 | - | let userNewInterest = $t01537715432._1 | |
434 | - | let claimAmount = $t01537715432._2 | |
435 | - | let userSWOPLockedNew = (userSWOPLocked + claimAmount) | |
436 | - | let totalSWOPLockedNew = (totalSWOPLocked + claimAmount) | |
437 | - | let userClaimedAmount = getUserSWOPClaimedAmount(i.caller) | |
438 | - | let userClaimedAmountNew = (userClaimedAmount + claimAmount) | |
439 | - | if ((claimAmount == 0)) | |
440 | - | then throw("You have 0 available SWOP") | |
441 | - | else [IntegerEntry((toString(i.caller) + kUserLastInterest), userNewInterest), IntegerEntry(kTotalSWOPLocked, totalSWOPLockedNew), IntegerEntry((toString(i.caller) + kUserSWOPLocked), userSWOPLockedNew), IntegerEntry((toString(i.caller) + kUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((toString(i.caller) + kUserSWOPLastClaimedAmount), claimAmount)] | |
442 | - | } | |
103 | + | func addAchievementsWriter (address) = valueOrElse(isSelfCall(i), { | |
104 | + | let writers = valueOrElse(getString(this, kAchievementsWriters), "") | |
105 | + | let data = if ((writers == "")) | |
106 | + | then nil | |
107 | + | else split(writers, ",") | |
108 | + | [StringEntry(kAchievementsWriters, makeString((data :+ address), ","))] | |
109 | + | }) | |
443 | 110 | ||
444 | 111 | ||
445 | 112 | ||
446 | 113 | @Callable(i) | |
447 | - | func updateWeights (currentPools,currentRewards,rewardUpdateHeight,pagination) = if (!(isActive)) | |
448 | - | then throw("DApp is inactive at this moment") | |
449 | - | else { | |
450 | - | let amountPools = 10 | |
451 | - | let totalRewardUpdateHeight = valueOrElse(getInteger(this, kRewardUpdateHeight), 0) | |
452 | - | if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, moneyBoxPubKey], i.callerPublicKey))) | |
453 | - | then throw("Only admin can call this function") | |
454 | - | else if ((size(currentPools) > amountPools)) | |
455 | - | then throw(("Max amount of pool is " + toString(amountPools))) | |
456 | - | else if ((totalRewardUpdateHeight >= rewardUpdateHeight)) | |
457 | - | then throw("rewardUpdateHeight <= totalRewardUpdateHeight") | |
458 | - | else if ((height >= rewardUpdateHeight)) | |
459 | - | then throw("height >= rewardUpdateHeight") | |
460 | - | else if ((0 >= rewardUpdateHeight)) | |
461 | - | then throw("0 >= rewardUpdateHeight ") | |
462 | - | else { | |
463 | - | func sum (a,b) = (a + b) | |
464 | - | ||
465 | - | func changePreviousRewardEntry (accumulated,pool) = { | |
466 | - | let poolRewardUpdateHeight = getPoolUpdateHeight(pool) | |
467 | - | if (if (!(isDefinePoolUpdateHeight(pool))) | |
468 | - | then true | |
469 | - | else if ((rewardUpdateHeight != poolRewardUpdateHeight)) | |
470 | - | then (poolRewardUpdateHeight == totalRewardUpdateHeight) | |
471 | - | else false) | |
472 | - | then { | |
473 | - | let poolReward = getCurPoolWeight(pool) | |
474 | - | IntegerEntry((pool + kRewardPoolFractionPrevious), poolReward) :: accumulated | |
475 | - | } | |
476 | - | else { | |
477 | - | let poolReward = getPrevPoolWeight(pool) | |
478 | - | IntegerEntry((pool + kRewardPoolFractionPrevious), poolReward) :: accumulated | |
479 | - | } | |
480 | - | } | |
481 | - | ||
482 | - | func changeCurrentRewardEntry (accumulated,pool) = { | |
483 | - | let poolIndex = value(indexOf(currentPools, pool)) | |
484 | - | let poolReward = currentRewards[poolIndex] | |
485 | - | if ((0 > poolReward)) | |
486 | - | then throw("PoolReward < 0") | |
487 | - | else IntegerEntry((pool + kRewardPoolFractionCurrent), poolReward) :: accumulated | |
488 | - | } | |
489 | - | ||
490 | - | func changeHeightEntry (accumulated,pool) = { | |
491 | - | let poolHeight = rewardUpdateHeight | |
492 | - | IntegerEntry((pool + kHeightPoolFraction), poolHeight) :: accumulated | |
493 | - | } | |
494 | - | ||
495 | - | func getSumReward (curTempSum,pagination) = if ((pagination == 0)) | |
496 | - | then if ((curTempSum > totalVoteShare)) | |
497 | - | then throw(((("sumRewardPrevious > totalVoteShare or sumRewardCurrent > totalVoteShare - " + toString(pagination)) + " ") + toString(curTempSum))) | |
498 | - | else $Tuple2([IntegerEntry(kTempCurSum, curTempSum)], [IntegerEntry(kRewardUpdateFirstPaginationHeight, rewardUpdateHeight)]) | |
499 | - | else if ((pagination == 1)) | |
500 | - | then { | |
501 | - | let curTempSumFromKey = valueOrElse(getInteger(this, kTempCurSum), 0) | |
502 | - | let rewardUpdateHeightFirstPaginationEntry = valueOrElse(getInteger(this, kRewardUpdateFirstPaginationHeight), 0) | |
503 | - | if (((curTempSum + curTempSumFromKey) > totalVoteShare)) | |
504 | - | then throw(((("sumRewardPrevious > totalVoteShare or sumRewardCurrent > totalVoteShare - " + toString(pagination)) + " ") + toString((curTempSum + curTempSumFromKey)))) | |
505 | - | else if ((rewardUpdateHeightFirstPaginationEntry != rewardUpdateHeight)) | |
506 | - | then throw("current rewardUpdateHeight != rewardUpdateHeightFirstPaginationEntry") | |
507 | - | else $Tuple2([IntegerEntry(kTempCurSum, (curTempSum + curTempSumFromKey))], nil) | |
508 | - | } | |
509 | - | else if ((pagination == 2)) | |
510 | - | then { | |
511 | - | let curSum = (valueOrElse(getInteger(this, kTempCurSum), 0) + curTempSum) | |
512 | - | let rewardUpdateHeightFirstPaginationEntry = valueOrElse(getInteger(this, kRewardUpdateFirstPaginationHeight), 0) | |
513 | - | if ((curSum != totalVoteShare)) | |
514 | - | then throw("sumRewardPrevious != totalVoteShare or sumRewardCurrent != totalVoteShare") | |
515 | - | else if ((rewardUpdateHeightFirstPaginationEntry != rewardUpdateHeight)) | |
516 | - | then throw("current rewardUpdateHeight != rewardUpdateHeightFirstPaginationEntry") | |
517 | - | else $Tuple2([IntegerEntry(kTempCurSum, curSum)], nil) | |
518 | - | } | |
519 | - | else throw("Incorrect pagination") | |
520 | - | ||
521 | - | let previousRewardEntryNew = { | |
522 | - | let $l = currentPools | |
523 | - | let $s = size($l) | |
524 | - | let $acc0 = nil | |
525 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
526 | - | then $a | |
527 | - | else changePreviousRewardEntry($a, $l[$i]) | |
528 | - | ||
529 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
530 | - | then $a | |
531 | - | else throw("List size exceeds 10") | |
532 | - | ||
533 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
534 | - | } | |
535 | - | let currentRewardEntryNew = { | |
536 | - | let $l = currentPools | |
537 | - | let $s = size($l) | |
538 | - | let $acc0 = nil | |
539 | - | func $f1_1 ($a,$i) = if (($i >= $s)) | |
540 | - | then $a | |
541 | - | else changeCurrentRewardEntry($a, $l[$i]) | |
542 | - | ||
543 | - | func $f1_2 ($a,$i) = if (($i >= $s)) | |
544 | - | then $a | |
545 | - | else throw("List size exceeds 10") | |
546 | - | ||
547 | - | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
548 | - | } | |
549 | - | let heightEntryNewCur = { | |
550 | - | let $l = currentPools | |
551 | - | let $s = size($l) | |
552 | - | let $acc0 = nil | |
553 | - | func $f2_1 ($a,$i) = if (($i >= $s)) | |
554 | - | then $a | |
555 | - | else changeHeightEntry($a, $l[$i]) | |
556 | - | ||
557 | - | func $f2_2 ($a,$i) = if (($i >= $s)) | |
558 | - | then $a | |
559 | - | else throw("List size exceeds 10") | |
560 | - | ||
561 | - | $f2_2($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
562 | - | } | |
563 | - | let sumRewardCurrentTemp = { | |
564 | - | let $l = currentRewards | |
565 | - | let $s = size($l) | |
566 | - | let $acc0 = 0 | |
567 | - | func $f3_1 ($a,$i) = if (($i >= $s)) | |
568 | - | then $a | |
569 | - | else sum($a, $l[$i]) | |
570 | - | ||
571 | - | func $f3_2 ($a,$i) = if (($i >= $s)) | |
572 | - | then $a | |
573 | - | else throw("List size exceeds 10") | |
574 | - | ||
575 | - | $f3_2($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
576 | - | } | |
577 | - | let $t02052720638 = getSumReward(sumRewardCurrentTemp, pagination) | |
578 | - | let sumRewardCurrent = $t02052720638._1 | |
579 | - | let rewardUpdateHeightFirstPaginationEntry = $t02052720638._2 | |
580 | - | let rewardUpdateHeightEntry = if ((pagination == 2)) | |
581 | - | then [IntegerEntry(kRewardUpdateHeight, rewardUpdateHeight)] | |
582 | - | else nil | |
583 | - | if ((height > rewardUpdateHeight)) | |
584 | - | then throw("rewardUpdateHeight < height") | |
585 | - | else (((((previousRewardEntryNew ++ currentRewardEntryNew) ++ heightEntryNewCur) ++ sumRewardCurrent) ++ rewardUpdateHeightEntry) ++ rewardUpdateHeightFirstPaginationEntry) | |
586 | - | } | |
587 | - | } | |
588 | - | ||
589 | - | ||
590 | - | ||
591 | - | @Callable(i) | |
592 | - | func shutdown () = if (!(isActive)) | |
593 | - | then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified"))) | |
594 | - | else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey))) | |
595 | - | then throw("Only admin can call this function") | |
596 | - | else suspend("Paused by admin") | |
597 | - | ||
598 | - | ||
599 | - | ||
600 | - | @Callable(i) | |
601 | - | func activate () = if (isActive) | |
602 | - | then throw("DApp is already active") | |
603 | - | else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey))) | |
604 | - | then throw("Only admin can call this function") | |
605 | - | else [BooleanEntry(kActive, true), DeleteEntry(kCause)] | |
114 | + | func removeAchievementsWriter (address) = valueOrElse(isSelfCall(i), { | |
115 | + | let writers = split(valueOrElse(getString(this, kAchievementsWriters), ""), ",") | |
116 | + | let index = valueOrErrorMessage(indexOf(writers, address), "Can't find address in the list") | |
117 | + | [StringEntry(kAchievementsWriters, makeString(removeByIndex(writers, index), ","))] | |
118 | + | }) | |
606 | 119 | ||
607 | 120 | ||
608 | 121 | @Verifier(tx) | |
616 | 129 | let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3)) | |
617 | 130 | then 1 | |
618 | 131 | else 0 | |
619 | - | (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2) | |
132 | + | let signedByAdmin = (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2) | |
133 | + | let signedByAdminToCallAddPool = (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 1) | |
134 | + | match tx { | |
135 | + | case inv: InvokeScriptTransaction => | |
136 | + | let isSelfInvokeRenamePool = if ((inv.dApp == this)) | |
137 | + | then containsElement(["renamePool"], inv.function) | |
138 | + | else false | |
139 | + | let isSelfInvokeSetAdmin = if ((inv.dApp == this)) | |
140 | + | then containsElement(["setAdmin"], inv.function) | |
141 | + | else false | |
142 | + | let isSelfInvokeAddPool = if ((inv.dApp == this)) | |
143 | + | then containsElement(["addPool"], inv.function) | |
144 | + | else false | |
145 | + | let isSelfInvokeLaunchpadDataTxStatus = if ((inv.dApp == this)) | |
146 | + | then containsElement(["launchpadDataTransactionStatus"], inv.function) | |
147 | + | else false | |
148 | + | let isSelfInvokeAddAchievementsWriter = if ((inv.dApp == this)) | |
149 | + | then containsElement(["addAchievementsWriter"], inv.function) | |
150 | + | else false | |
151 | + | let isSelfInvokeRemoveAchievementsWriter = if ((inv.dApp == this)) | |
152 | + | then containsElement(["removeAchievementsWriter"], inv.function) | |
153 | + | else false | |
154 | + | if (if (if (if (if (if (if (signedByAdmin) | |
155 | + | then (size(inv.payments) == 0) | |
156 | + | else false) | |
157 | + | then isSelfInvokeRenamePool | |
158 | + | else false) | |
159 | + | then true | |
160 | + | else if (if (signedByAdminToCallAddPool) | |
161 | + | then (size(inv.payments) == 0) | |
162 | + | else false) | |
163 | + | then isSelfInvokeAddPool | |
164 | + | else false) | |
165 | + | then true | |
166 | + | else if (if (signedByAdmin) | |
167 | + | then (size(inv.payments) == 0) | |
168 | + | else false) | |
169 | + | then isSelfInvokeSetAdmin | |
170 | + | else false) | |
171 | + | then true | |
172 | + | else if (if (signedByAdmin) | |
173 | + | then (size(inv.payments) == 0) | |
174 | + | else false) | |
175 | + | then isSelfInvokeLaunchpadDataTxStatus | |
176 | + | else false) | |
177 | + | then true | |
178 | + | else if (if (signedByAdmin) | |
179 | + | then (size(inv.payments) == 0) | |
180 | + | else false) | |
181 | + | then isSelfInvokeAddAchievementsWriter | |
182 | + | else false) | |
183 | + | then true | |
184 | + | else if (if (signedByAdmin) | |
185 | + | then (size(inv.payments) == 0) | |
186 | + | else false) | |
187 | + | then isSelfInvokeRemoveAchievementsWriter | |
188 | + | else false | |
189 | + | case _: Order|DataTransaction|SponsorFeeTransaction|SetScriptTransaction|CreateAliasTransaction|LeaseCancelTransaction|LeaseTransaction|IssueTransaction|UpdateAssetInfoTransaction|InvokeScriptTransaction|SetAssetScriptTransaction|TransferTransaction|ExchangeTransaction|MassTransferTransaction|BurnTransaction|ReissueTransaction => | |
190 | + | signedByAdmin | |
191 | + | case _ => | |
192 | + | throw("Match error") | |
193 | + | } | |
620 | 194 | } | |
621 | 195 |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | - | let | |
4 | + | let kPoolsListName = "pools" | |
5 | 5 | ||
6 | - | let | |
6 | + | let kPrefixPoolName = "pool_" | |
7 | 7 | ||
8 | - | let | |
8 | + | let kPrefixPoolIndex = "index_" | |
9 | 9 | ||
10 | - | let | |
10 | + | let kPair = "pair_" | |
11 | 11 | ||
12 | - | let | |
12 | + | let kAssetIdA = "A_asset_id" | |
13 | 13 | ||
14 | - | let | |
14 | + | let kAssetIdB = "B_asset_id" | |
15 | 15 | ||
16 | - | let kTotalSWOPLocked = "total_SWOP_amount" | |
17 | - | ||
18 | - | let kUserTotalVoteSWOP = "_user_total_SWOP_vote" | |
19 | - | ||
20 | - | let kUserVoteOptionAmount = "_SWOP_option_amount" | |
21 | - | ||
22 | - | let kTotalVoteOptionAmount = "total_SWOP_option_amount" | |
23 | - | ||
24 | - | let kUserSWOPClaimedAmount = "_SWOP_claimed_amount" | |
25 | - | ||
26 | - | let kUserSWOPLastClaimedAmount = "_SWOP_last_claimed_amount" | |
27 | - | ||
28 | - | let kVoteName = "vote_name" | |
29 | - | ||
30 | - | let kOptionName = "_option_name" | |
31 | - | ||
32 | - | let kVotingStartHeight = "_startHeight" | |
33 | - | ||
34 | - | let kVoteDuration = "_vote_duration" | |
35 | - | ||
36 | - | let kRewardPoolFractionCurrent = "_current_pool_fraction_reward" | |
37 | - | ||
38 | - | let kRewardPoolFractionPrevious = "_previous_pool_fraction_reward" | |
39 | - | ||
40 | - | let kHeightPoolFraction = "_pool_reward_update_height" | |
41 | - | ||
42 | - | let kTotalRewardPerBlockCurrent = "total_reward_per_block_current" | |
43 | - | ||
44 | - | let kTotalRewardPerBlockPrevious = "total_reward_per_block_previous" | |
45 | - | ||
46 | - | let kRewardUpdateHeight = "reward_update_height" | |
47 | - | ||
48 | - | let kRewardUpdateFirstPaginationHeight = "reward_update_height_first_pagination" | |
49 | - | ||
50 | - | let kNoVotingForNewPool = "_vote_no" | |
51 | - | ||
52 | - | let kYesVotingForNewPool = "_vote_yes" | |
53 | - | ||
54 | - | let kAmountOfVotingForNewPool = "max_amount_voting" | |
55 | - | ||
56 | - | let kStatusOfVotingForNewPool = "_status" | |
57 | - | ||
58 | - | let kHeightOfPoolVotingForNewPool = "_finish_height" | |
59 | - | ||
60 | - | let activeVoteFirst = "voting_active_cell_1" | |
61 | - | ||
62 | - | let activeVoteSecond = "voting_active_cell_2" | |
63 | - | ||
64 | - | let activeVoteThird = "voting_active_cell_3" | |
65 | - | ||
66 | - | let kTempCurSum = "sum_reward_current" | |
67 | - | ||
68 | - | let kLaunchpadBoughtTickets = "_bought_tickets" | |
69 | - | ||
70 | - | let kLaunchpadSwopPerTickets = "_swop_per_ticket" | |
71 | - | ||
72 | - | let kLaunchpadActiveId = "launchpad_active_id" | |
73 | - | ||
74 | - | let kLaunchpadDuration = "_duration" | |
75 | - | ||
76 | - | let kLaunchpadStartHeight = "_start_height" | |
77 | - | ||
78 | - | let kStartHeight = "start_height" | |
79 | - | ||
80 | - | let kBasePeriod = "base_period" | |
81 | - | ||
82 | - | let kPeriodLength = "period_length" | |
83 | - | ||
84 | - | let kUserTotalStruc = "_user_total_struc" | |
85 | - | ||
86 | - | let kLauchpadFreezSwopDuration = "_freeze_swop_duration" | |
87 | - | ||
88 | - | let kSWOPid = "SWOP_id" | |
89 | - | ||
90 | - | let kAirdropFee = "airdrop_fee" | |
16 | + | let kLaunchpadDataTransactionStatus = "launchpad_data_transaction_status" | |
91 | 17 | ||
92 | 18 | let kAdminPubKey1 = "admin_pub_1" | |
93 | 19 | ||
94 | 20 | let kAdminPubKey2 = "admin_pub_2" | |
95 | 21 | ||
96 | 22 | let kAdminPubKey3 = "admin_pub_3" | |
97 | 23 | ||
98 | - | let | |
24 | + | let kAdminInvokePubKey = "admin_invoke_pub" | |
99 | 25 | ||
100 | - | let | |
26 | + | let kAchievementsWriters = "achievements_writers" | |
101 | 27 | ||
102 | - | let | |
28 | + | let adminPubKey1 = base58'GFmKZ2naZFRoCvNbwKAQVGmLb1uBeWGDgFabdGBuZiuy' | |
103 | 29 | ||
104 | - | let | |
30 | + | let adminPubKey2 = base58'GmJXRyhRA79g8yUGgKBAVdnFfQFDMjQG98b1MmLDh5kk' | |
105 | 31 | ||
106 | - | let | |
32 | + | let adminPubKey3 = base58'CFhbV6h41hVjbGHudGtS3fYUv7QAKRxFQzKNtx4B5PqP' | |
107 | 33 | ||
108 | - | let | |
34 | + | let adminPubKeyInvoke = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK' | |
109 | 35 | ||
110 | - | let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9') | |
111 | - | ||
112 | - | func getBase58FromOracle (key) = match getString(oracle, key) { | |
36 | + | let pools = match getString(this, kPoolsListName) { | |
113 | 37 | case string: String => | |
114 | - | | |
38 | + | split(string, ",") | |
115 | 39 | case nothing => | |
116 | - | | |
40 | + | nil | |
117 | 41 | } | |
118 | 42 | ||
119 | - | ||
120 | - | let adminPubKey1 = getBase58FromOracle(kAdminPubKey1) | |
121 | - | ||
122 | - | let adminPubKey2 = getBase58FromOracle(kAdminPubKey2) | |
123 | - | ||
124 | - | let adminPubKey3 = getBase58FromOracle(kAdminPubKey3) | |
125 | - | ||
126 | - | let moneyBoxPubKey = getBase58FromOracle(kMoneyBoxPubKey) | |
127 | - | ||
128 | - | let farmingAddr = Address(getBase58FromOracle(kFarmingAddr)) | |
129 | - | ||
130 | - | let votingAddr = Address(getBase58FromOracle(kVotingAddr)) | |
131 | - | ||
132 | - | let votingNewPoolAddr = Address(getBase58FromOracle(kVotingNewPoolAddr)) | |
133 | - | ||
134 | - | let launchpadAddr = Address(getBase58FromOracle(kLaunchpadAddr)) | |
135 | - | ||
136 | - | let airdropMoneyBoxAddr = Address(getBase58FromOracle(kAirdropMoneyBoxAddr)) | |
137 | - | ||
138 | - | let SWOP = fromBase58String(getStringValue(farmingAddr, kSWOPid)) | |
139 | - | ||
140 | - | let scaleValue = 100000000 | |
141 | - | ||
142 | - | let totalVoteShare = 10000000000 | |
143 | - | ||
144 | - | let basePeriod = valueOrErrorMessage(getInteger(votingAddr, kBasePeriod), "Empty kBasePeriod at voting contract") | |
145 | - | ||
146 | - | let startHeight = valueOrErrorMessage(getInteger(votingAddr, kStartHeight), "Empty kStartHeight at voting contract") | |
147 | - | ||
148 | - | let periodLength = valueOrErrorMessage(getInteger(votingAddr, kPeriodLength), "Empty kPeriodLength at voting contract") | |
149 | - | ||
150 | - | let firstActiveVote = valueOrElse(getString(votingNewPoolAddr, activeVoteFirst), "") | |
151 | - | ||
152 | - | let secondActiveVote = valueOrElse(getString(votingNewPoolAddr, activeVoteSecond), "") | |
153 | - | ||
154 | - | let thirdActiveVote = valueOrElse(getString(votingNewPoolAddr, activeVoteThird), "") | |
155 | - | ||
156 | - | let isActive = valueOrElse(getBoolean(this, kActive), true) | |
157 | - | ||
158 | - | let airdropFee = getIntegerValue(oracle, kAirdropFee) | |
159 | - | ||
160 | - | let currVotingPeriod = (basePeriod + ((height - startHeight) / periodLength)) | |
161 | - | ||
162 | - | func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)] | |
43 | + | func isSelfCall (i) = if ((i.caller == this)) | |
44 | + | then unit | |
45 | + | else throw("Only the Oracle itself can invoke this function") | |
163 | 46 | ||
164 | 47 | ||
165 | - | func throwNotEnoughSWOP () = throw("Not enough SWOP: userSWOPLocked - userTotalVoteAmount < voteSWOPAmount") | |
166 | - | ||
167 | - | ||
168 | - | func getLastInterestInfo () = valueOrElse(getInteger(this, kLastInterest), 0) | |
169 | - | ||
170 | - | ||
171 | - | func getUserSWOPLocked (user) = valueOrElse(getInteger(this, (toString(user) + kUserSWOPLocked)), 0) | |
172 | - | ||
173 | - | ||
174 | - | func getUserSWOPClaimedAmount (user) = valueOrElse(getInteger(this, (toString(user) + kUserSWOPClaimedAmount)), 0) | |
175 | - | ||
176 | - | ||
177 | - | func getUserTotalVoteAmount (user) = valueOrElse(getInteger(votingAddr, (toString(user) + kUserTotalVoteSWOP)), 0) | |
178 | - | ||
179 | - | ||
180 | - | func getUserInterestInfo (user,lastInterest) = { | |
181 | - | let userSWOPAmount = getUserSWOPLocked(user) | |
182 | - | let userLastInterest = getInteger(this, (toString(user) + kUserLastInterest)) | |
183 | - | let userLastInterestValue = match userLastInterest { | |
184 | - | case userLastInterest: Int => | |
185 | - | userLastInterest | |
186 | - | case _ => | |
187 | - | lastInterest | |
188 | - | } | |
189 | - | $Tuple2(userLastInterestValue, userSWOPAmount) | |
48 | + | func getPoolNameIfValid (poolName) = { | |
49 | + | let underscoreIndex = valueOrElse(indexOf(poolName, "_"), -1) | |
50 | + | let underscoreLastIndex = valueOrElse(lastIndexOf(poolName, "_"), -1) | |
51 | + | let hasSingleUnderscore = if (if ((underscoreIndex == underscoreLastIndex)) | |
52 | + | then (underscoreIndex > 0) | |
53 | + | else false) | |
54 | + | then (underscoreIndex != (size(poolName) - 1)) | |
55 | + | else false | |
56 | + | if (hasSingleUnderscore) | |
57 | + | then poolName | |
58 | + | else throw("Pool name must consist of two asset names separated by an underscore character") | |
190 | 59 | } | |
191 | 60 | ||
192 | 61 | ||
193 | - | func getUserTotalVoteAmountForOnePool (pool,user) = { | |
194 | - | let voting = valueOrElse(getInteger(votingNewPoolAddr, pool), -1) | |
195 | - | let heightOfVoting = valueOrElse(getInteger(votingNewPoolAddr, (toString(voting) + kHeightOfPoolVotingForNewPool)), 0) | |
196 | - | let statusOfVoting = valueOrElse(getBoolean(votingNewPoolAddr, (toString(voting) + kStatusOfVotingForNewPool)), true) | |
197 | - | let currentHeight = height | |
198 | - | if ((0 > voting)) | |
199 | - | then 0 | |
200 | - | else if (!(statusOfVoting)) | |
201 | - | then 0 | |
202 | - | else if ((heightOfVoting > currentHeight)) | |
203 | - | then (valueOrElse(getInteger(votingNewPoolAddr, (((toString(user) + "_") + toString(voting)) + kYesVotingForNewPool)), 0) + valueOrElse(getInteger(votingNewPoolAddr, (((toString(user) + "_") + toString(voting)) + kNoVotingForNewPool)), 0)) | |
204 | - | else 0 | |
205 | - | } | |
206 | - | ||
207 | - | ||
208 | - | func getUserTotalVoteForNewPoolAmount (user) = { | |
209 | - | let listOfVoting = [getUserTotalVoteAmountForOnePool(firstActiveVote, user), getUserTotalVoteAmountForOnePool(secondActiveVote, user), getUserTotalVoteAmountForOnePool(thirdActiveVote, user)] | |
210 | - | max(listOfVoting) | |
211 | - | } | |
212 | - | ||
213 | - | ||
214 | - | func getUserBlockedInLauchpad (user) = { | |
215 | - | let lauchpadId = toString(valueOrElse(getInteger(launchpadAddr, kLaunchpadActiveId), 0)) | |
216 | - | if ((lauchpadId == "0")) | |
217 | - | then 0 | |
218 | - | else { | |
219 | - | let lStartHeight = valueOrElse(getInteger(launchpadAddr, (lauchpadId + kLaunchpadStartHeight)), 0) | |
220 | - | let lDuration = valueOrElse(getInteger(launchpadAddr, (lauchpadId + kLaunchpadDuration)), 0) | |
221 | - | let lFreezeSwopDuration = valueOrElse(getInteger(launchpadAddr, (lauchpadId + kLauchpadFreezSwopDuration)), 0) | |
222 | - | let blockEndHeight = ((lStartHeight + lDuration) + lFreezeSwopDuration) | |
223 | - | if ((height > blockEndHeight)) | |
224 | - | then 0 | |
225 | - | else { | |
226 | - | let boughtTickets = valueOrElse(getInteger(launchpadAddr, (((toString(user) + "_") + lauchpadId) + kLaunchpadBoughtTickets)), 0) | |
227 | - | let swopPerTicket = valueOrElse(getInteger(launchpadAddr, (lauchpadId + kLaunchpadSwopPerTickets)), 0) | |
228 | - | (boughtTickets * swopPerTicket) | |
229 | - | } | |
230 | - | } | |
231 | - | } | |
232 | - | ||
233 | - | ||
234 | - | func getTotalSWOPLocked () = valueOrElse(getInteger(this, kTotalSWOPLocked), 0) | |
235 | - | ||
236 | - | ||
237 | - | func getUserVoteInfo (user) = { | |
238 | - | let $t075828115 = if (isDefined(getString(votingAddr, (toString(user) + kUserTotalStruc)))) | |
239 | - | then { | |
240 | - | let data = split(valueOrErrorMessage(getString(votingAddr, (toString(user) + kUserTotalStruc)), "Empty kUserTotalStruc"), "_") | |
241 | - | $Tuple3(parseIntValue(data[0]), parseIntValue(data[1]), parseIntValue(data[2])) | |
242 | - | } | |
243 | - | else { | |
244 | - | let uPoolTotalSWOP = valueOrElse(getInteger(votingAddr, (toString(user) + kUserTotalVoteSWOP)), 0) | |
245 | - | $Tuple3(uPoolTotalSWOP, 0, currVotingPeriod) | |
246 | - | } | |
247 | - | let userTotalVoteSWOP = $t075828115._1 | |
248 | - | let userUnvoted = $t075828115._2 | |
249 | - | let userUnvotedPeriod = $t075828115._3 | |
250 | - | let userUnvotedActual = if ((userUnvotedPeriod == currVotingPeriod)) | |
251 | - | then userUnvoted | |
252 | - | else 0 | |
253 | - | $Tuple2(userTotalVoteSWOP, userUnvotedActual) | |
254 | - | } | |
255 | - | ||
256 | - | ||
257 | - | func getUserVoteOptionAmount (user) = valueOrElse(getInteger(this, (toString(user) + kUserVoteOptionAmount)), 0) | |
258 | - | ||
259 | - | ||
260 | - | func getVotingStartHeight (voteName) = valueOrElse(getInteger(this, (voteName + kVotingStartHeight)), 0) | |
261 | - | ||
262 | - | ||
263 | - | func getPoolUpdateHeight (pool) = valueOrElse(getInteger(this, (pool + kHeightPoolFraction)), 0) | |
264 | - | ||
265 | - | ||
266 | - | func isDefinePoolUpdateHeight (pool) = isDefined(getInteger(this, (pool + kHeightPoolFraction))) | |
267 | - | ||
268 | - | ||
269 | - | func getCurPoolWeight (pool) = valueOrElse(getInteger(this, (pool + kRewardPoolFractionCurrent)), 0) | |
270 | - | ||
271 | - | ||
272 | - | func getPrevPoolWeight (pool) = valueOrElse(getInteger(this, (pool + kRewardPoolFractionPrevious)), 0) | |
273 | - | ||
274 | - | ||
275 | - | func getVoteOptionAmount (user,voteName,option) = { | |
276 | - | let userVoteOptionAmount = getInteger(this, (((voteName + option) + toString(user)) + kUserVoteOptionAmount)) | |
277 | - | let uvoa = match userVoteOptionAmount { | |
278 | - | case uvoa: Int => | |
279 | - | uvoa | |
280 | - | case uvoa: Unit => | |
281 | - | 0 | |
282 | - | case _ => | |
283 | - | throw("Match error") | |
284 | - | } | |
285 | - | valueOrErrorMessage(uvoa, (((("No data on the key: " + voteName) + option) + toString(user)) + kUserVoteOptionAmount)) | |
286 | - | } | |
287 | - | ||
288 | - | ||
289 | - | func getVoteDuration (voteName) = valueOrErrorMessage(getInteger(this, (voteName + kVoteDuration)), (("No data on the key: " + voteName) + kVoteDuration)) | |
290 | - | ||
291 | - | ||
292 | - | func getTotalVoteOptionAmount (voteName,option) = { | |
293 | - | let totalVoteOptionAmount = getInteger(this, ((voteName + option) + kTotalVoteOptionAmount)) | |
294 | - | let tvoa = match totalVoteOptionAmount { | |
295 | - | case tvoa: Int => | |
296 | - | tvoa | |
297 | - | case tvoa: Unit => | |
298 | - | 0 | |
299 | - | case _ => | |
300 | - | throw("Match error") | |
301 | - | } | |
302 | - | tvoa | |
303 | - | } | |
304 | - | ||
305 | - | ||
306 | - | func getUserGetBackAmount (voteName,option,user,getBackSWOPHeight) = { | |
307 | - | let key = ((((((voteName + "_") + option) + "_") + toString(user)) + "_") + toString(getBackSWOPHeight)) | |
308 | - | valueOrErrorMessage(getInteger(this, key), ("No data on the key: " + key)) | |
309 | - | } | |
310 | - | ||
311 | - | ||
312 | - | func claimCalc (caller) = { | |
313 | - | let lastInterest = getLastInterestInfo() | |
314 | - | let $t01050610588 = getUserInterestInfo(caller, lastInterest) | |
315 | - | let userLastInterest = $t01050610588._1 | |
316 | - | let userSWOPLocked = $t01050610588._2 | |
317 | - | let claimAmount = fraction(userSWOPLocked, (lastInterest - userLastInterest), scaleValue) | |
318 | - | let userNewInterest = lastInterest | |
319 | - | $Tuple2(userNewInterest, claimAmount) | |
320 | - | } | |
62 | + | func getAddressIfValid (address) = toString(valueOrErrorMessage(addressFromString(address), (("Can't parse \"" + address) + "\" as address"))) | |
321 | 63 | ||
322 | 64 | ||
323 | 65 | @Callable(i) | |
324 | - | func airDrop () = if (!(isActive)) | |
325 | - | then throw("DApp is inactive at this moment") | |
326 | - | else { | |
327 | - | let $t01085610931 = $Tuple2(i.payments[0].amount, i.payments[0].assetId) | |
328 | - | let pmtAmount = $t01085610931._1 | |
329 | - | let pmtAssetId = $t01085610931._2 | |
330 | - | if ((pmtAssetId != SWOP)) | |
331 | - | then throw("Incorrect pmtAssetId") | |
332 | - | else { | |
333 | - | let airdropFeeAmount = fraction(pmtAmount, airdropFee, 100, CEILING) | |
334 | - | let totalSWOPLocked = getTotalSWOPLocked() | |
335 | - | let lastInterest = getLastInterestInfo() | |
336 | - | let interestNew = (lastInterest + fraction((pmtAmount - airdropFeeAmount), scaleValue, totalSWOPLocked)) | |
337 | - | [IntegerEntry(kLastInterest, interestNew), ScriptTransfer(airdropMoneyBoxAddr, airdropFeeAmount, SWOP)] | |
338 | - | } | |
339 | - | } | |
66 | + | func setAdmin () = valueOrElse(isSelfCall(i), [StringEntry(kAdminPubKey1, toBase58String(adminPubKey1)), StringEntry(kAdminPubKey2, toBase58String(adminPubKey2)), StringEntry(kAdminPubKey3, toBase58String(adminPubKey3)), StringEntry(kAdminInvokePubKey, toBase58String(adminPubKeyInvoke))]) | |
340 | 67 | ||
341 | 68 | ||
342 | 69 | ||
343 | 70 | @Callable(i) | |
344 | - | func lockSWOP () = if (!(isActive)) | |
345 | - | then throw("DApp is inactive at this moment") | |
346 | - | else { | |
347 | - | let $t01155811633 = $Tuple2(i.payments[0].amount, i.payments[0].assetId) | |
348 | - | let pmtAmount = $t01155811633._1 | |
349 | - | let pmtAssetId = $t01155811633._2 | |
350 | - | if ((pmtAssetId != SWOP)) | |
351 | - | then throw("Incorrect pmtAssetId") | |
352 | - | else { | |
353 | - | let lastInterest = getLastInterestInfo() | |
354 | - | let $t01174911833 = getUserInterestInfo(i.caller, lastInterest) | |
355 | - | let userLastInterest = $t01174911833._1 | |
356 | - | let userSWOPLocked = $t01174911833._2 | |
357 | - | let claimAmount = fraction(userSWOPLocked, (lastInterest - userLastInterest), scaleValue) | |
358 | - | let userSWOPLockedNew = ((userSWOPLocked + pmtAmount) + claimAmount) | |
359 | - | let userNewInterest = lastInterest | |
360 | - | let totalSWOPLocked = getTotalSWOPLocked() | |
361 | - | let totalSWOPLockedNew = ((totalSWOPLocked + pmtAmount) + claimAmount) | |
362 | - | let userClaimedAmount = getUserSWOPClaimedAmount(i.caller) | |
363 | - | let userClaimedAmountNew = (userClaimedAmount + claimAmount) | |
364 | - | [IntegerEntry((toString(i.caller) + kUserLastInterest), userNewInterest), IntegerEntry((toString(i.caller) + kUserSWOPLocked), userSWOPLockedNew), IntegerEntry(kTotalSWOPLocked, totalSWOPLockedNew), IntegerEntry((toString(i.caller) + kUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((toString(i.caller) + kUserSWOPLastClaimedAmount), claimAmount)] | |
365 | - | } | |
366 | - | } | |
71 | + | func addPool (poolAddress,poolName) = valueOrElse(isSelfCall(i), { | |
72 | + | let validatedAddress = getAddressIfValid(poolAddress) | |
73 | + | let keyName = (kPrefixPoolName + validatedAddress) | |
74 | + | let keyIndex = (kPrefixPoolIndex + validatedAddress) | |
75 | + | let assetIdA = valueOrErrorMessage(getString(value(addressFromString(poolAddress)), kAssetIdA), "Asset id A is incorrect") | |
76 | + | let assetIdB = valueOrErrorMessage(getString(value(addressFromString(poolAddress)), kAssetIdB), "Asset id B is incorrect") | |
77 | + | let possiblyAlreadyAddedPool = getString(this, keyName) | |
78 | + | if (isDefined(possiblyAlreadyAddedPool)) | |
79 | + | then throw((((("Pool with address \"" + validatedAddress) + "\" is already defined with name \"") + value(possiblyAlreadyAddedPool)) + "\"")) | |
80 | + | else [IntegerEntry(keyIndex, size(pools)), StringEntry(keyName, getPoolNameIfValid(poolName)), StringEntry((((kPair + assetIdA) + "_") + assetIdB), poolAddress), StringEntry(kPoolsListName, makeString((pools :+ validatedAddress), ","))] | |
81 | + | }) | |
367 | 82 | ||
368 | 83 | ||
369 | 84 | ||
370 | 85 | @Callable(i) | |
371 | - | func withdrawSWOP (withdrawAmount) = if (!(isActive)) | |
372 | - | then throw("DApp is inactive at this moment") | |
373 | - | else if ((0 >= withdrawAmount)) | |
374 | - | then throw("withdrawAmount <= 0") | |
375 | - | else { | |
376 | - | let totalSWOPLocked = getTotalSWOPLocked() | |
377 | - | let userSWOPLocked = getUserSWOPLocked(i.caller) | |
378 | - | let $t01297413029 = claimCalc(i.caller) | |
379 | - | let userNewInterest = $t01297413029._1 | |
380 | - | let claimAmount = $t01297413029._2 | |
381 | - | let $t01303413099 = getUserVoteInfo(i.caller) | |
382 | - | let userVoteAmount = $t01303413099._1 | |
383 | - | let userUnvoteAmount = $t01303413099._2 | |
384 | - | let userVoteAmountForNewPool = getUserTotalVoteForNewPoolAmount(i.caller) | |
385 | - | let blockedInLaunchpad = getUserBlockedInLauchpad(i.caller) | |
386 | - | if (if (if ((0 > userUnvoteAmount)) | |
387 | - | then true | |
388 | - | else (0 > userVoteAmount)) | |
389 | - | then true | |
390 | - | else (0 > userVoteAmountForNewPool)) | |
391 | - | then throw("userUnvoteAmount < 0 || userVoteAmount < 0 || userVoteAmountForNewPool < 0") | |
392 | - | else { | |
393 | - | let availableToUnstake = (userSWOPLocked - max([userVoteAmountForNewPool, (userVoteAmount + userUnvoteAmount), blockedInLaunchpad])) | |
394 | - | if ((withdrawAmount > availableToUnstake)) | |
395 | - | then throw("withdrawAmount > availableToUnstake") | |
396 | - | else { | |
397 | - | let totalSWOPLockedNew = ((totalSWOPLocked + claimAmount) - withdrawAmount) | |
398 | - | let userSWOPamountNew = ((userSWOPLocked + claimAmount) - withdrawAmount) | |
399 | - | let userClaimedAmount = getUserSWOPClaimedAmount(i.caller) | |
400 | - | let userClaimedAmountNew = (userClaimedAmount + claimAmount) | |
401 | - | [IntegerEntry((toString(i.caller) + kUserLastInterest), userNewInterest), IntegerEntry((toString(i.caller) + kUserSWOPLocked), userSWOPamountNew), IntegerEntry(kTotalSWOPLocked, totalSWOPLockedNew), ScriptTransfer(i.caller, withdrawAmount, SWOP), IntegerEntry((toString(i.caller) + kUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((toString(i.caller) + kUserSWOPLastClaimedAmount), claimAmount)] | |
402 | - | } | |
403 | - | } | |
404 | - | } | |
86 | + | func renamePool (poolAddress,newPoolName) = valueOrElse(isSelfCall(i), { | |
87 | + | let validatedAddress = getAddressIfValid(poolAddress) | |
88 | + | let keyName = (kPrefixPoolName + validatedAddress) | |
89 | + | let possiblyAlreadyAddedPool = getString(this, keyName) | |
90 | + | if (isDefined(possiblyAlreadyAddedPool)) | |
91 | + | then [StringEntry(keyName, getPoolNameIfValid(newPoolName))] | |
92 | + | else throw((("Pool with address \"" + validatedAddress) + "\" has not yet been added")) | |
93 | + | }) | |
405 | 94 | ||
406 | 95 | ||
407 | 96 | ||
408 | 97 | @Callable(i) | |
409 | - | func claimAndWithdrawSWOP () = if (!(isActive)) | |
410 | - | then throw("DApp is inactive at this moment") | |
411 | - | else { | |
412 | - | let lastInterest = getLastInterestInfo() | |
413 | - | let $t01454914604 = claimCalc(i.caller) | |
414 | - | let userNewInterest = $t01454914604._1 | |
415 | - | let claimAmount = $t01454914604._2 | |
416 | - | let userClaimedAmount = getUserSWOPClaimedAmount(i.caller) | |
417 | - | let userClaimedAmountNew = (userClaimedAmount + claimAmount) | |
418 | - | if ((claimAmount == 0)) | |
419 | - | then throw("You have 0 available SWOP") | |
420 | - | else [IntegerEntry((toString(i.caller) + kUserLastInterest), userNewInterest), IntegerEntry((toString(i.caller) + kUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((toString(i.caller) + kUserSWOPLastClaimedAmount), claimAmount), ScriptTransfer(i.caller, claimAmount, SWOP)] | |
421 | - | } | |
98 | + | func launchpadDataTransactionStatus (status) = valueOrElse(isSelfCall(i), [BooleanEntry(kLaunchpadDataTransactionStatus, status)]) | |
422 | 99 | ||
423 | 100 | ||
424 | 101 | ||
425 | 102 | @Callable(i) | |
426 | - | func claimAndStakeSWOP () = if (!(isActive)) | |
427 | - | then throw("DApp is inactive at this moment") | |
428 | - | else { | |
429 | - | let totalSWOPLocked = getTotalSWOPLocked() | |
430 | - | let userSWOPLocked = getUserSWOPLocked(i.caller) | |
431 | - | let lastInterest = getLastInterestInfo() | |
432 | - | let $t01537715432 = claimCalc(i.caller) | |
433 | - | let userNewInterest = $t01537715432._1 | |
434 | - | let claimAmount = $t01537715432._2 | |
435 | - | let userSWOPLockedNew = (userSWOPLocked + claimAmount) | |
436 | - | let totalSWOPLockedNew = (totalSWOPLocked + claimAmount) | |
437 | - | let userClaimedAmount = getUserSWOPClaimedAmount(i.caller) | |
438 | - | let userClaimedAmountNew = (userClaimedAmount + claimAmount) | |
439 | - | if ((claimAmount == 0)) | |
440 | - | then throw("You have 0 available SWOP") | |
441 | - | else [IntegerEntry((toString(i.caller) + kUserLastInterest), userNewInterest), IntegerEntry(kTotalSWOPLocked, totalSWOPLockedNew), IntegerEntry((toString(i.caller) + kUserSWOPLocked), userSWOPLockedNew), IntegerEntry((toString(i.caller) + kUserSWOPClaimedAmount), userClaimedAmountNew), IntegerEntry((toString(i.caller) + kUserSWOPLastClaimedAmount), claimAmount)] | |
442 | - | } | |
103 | + | func addAchievementsWriter (address) = valueOrElse(isSelfCall(i), { | |
104 | + | let writers = valueOrElse(getString(this, kAchievementsWriters), "") | |
105 | + | let data = if ((writers == "")) | |
106 | + | then nil | |
107 | + | else split(writers, ",") | |
108 | + | [StringEntry(kAchievementsWriters, makeString((data :+ address), ","))] | |
109 | + | }) | |
443 | 110 | ||
444 | 111 | ||
445 | 112 | ||
446 | 113 | @Callable(i) | |
447 | - | func updateWeights (currentPools,currentRewards,rewardUpdateHeight,pagination) = if (!(isActive)) | |
448 | - | then throw("DApp is inactive at this moment") | |
449 | - | else { | |
450 | - | let amountPools = 10 | |
451 | - | let totalRewardUpdateHeight = valueOrElse(getInteger(this, kRewardUpdateHeight), 0) | |
452 | - | if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, moneyBoxPubKey], i.callerPublicKey))) | |
453 | - | then throw("Only admin can call this function") | |
454 | - | else if ((size(currentPools) > amountPools)) | |
455 | - | then throw(("Max amount of pool is " + toString(amountPools))) | |
456 | - | else if ((totalRewardUpdateHeight >= rewardUpdateHeight)) | |
457 | - | then throw("rewardUpdateHeight <= totalRewardUpdateHeight") | |
458 | - | else if ((height >= rewardUpdateHeight)) | |
459 | - | then throw("height >= rewardUpdateHeight") | |
460 | - | else if ((0 >= rewardUpdateHeight)) | |
461 | - | then throw("0 >= rewardUpdateHeight ") | |
462 | - | else { | |
463 | - | func sum (a,b) = (a + b) | |
464 | - | ||
465 | - | func changePreviousRewardEntry (accumulated,pool) = { | |
466 | - | let poolRewardUpdateHeight = getPoolUpdateHeight(pool) | |
467 | - | if (if (!(isDefinePoolUpdateHeight(pool))) | |
468 | - | then true | |
469 | - | else if ((rewardUpdateHeight != poolRewardUpdateHeight)) | |
470 | - | then (poolRewardUpdateHeight == totalRewardUpdateHeight) | |
471 | - | else false) | |
472 | - | then { | |
473 | - | let poolReward = getCurPoolWeight(pool) | |
474 | - | IntegerEntry((pool + kRewardPoolFractionPrevious), poolReward) :: accumulated | |
475 | - | } | |
476 | - | else { | |
477 | - | let poolReward = getPrevPoolWeight(pool) | |
478 | - | IntegerEntry((pool + kRewardPoolFractionPrevious), poolReward) :: accumulated | |
479 | - | } | |
480 | - | } | |
481 | - | ||
482 | - | func changeCurrentRewardEntry (accumulated,pool) = { | |
483 | - | let poolIndex = value(indexOf(currentPools, pool)) | |
484 | - | let poolReward = currentRewards[poolIndex] | |
485 | - | if ((0 > poolReward)) | |
486 | - | then throw("PoolReward < 0") | |
487 | - | else IntegerEntry((pool + kRewardPoolFractionCurrent), poolReward) :: accumulated | |
488 | - | } | |
489 | - | ||
490 | - | func changeHeightEntry (accumulated,pool) = { | |
491 | - | let poolHeight = rewardUpdateHeight | |
492 | - | IntegerEntry((pool + kHeightPoolFraction), poolHeight) :: accumulated | |
493 | - | } | |
494 | - | ||
495 | - | func getSumReward (curTempSum,pagination) = if ((pagination == 0)) | |
496 | - | then if ((curTempSum > totalVoteShare)) | |
497 | - | then throw(((("sumRewardPrevious > totalVoteShare or sumRewardCurrent > totalVoteShare - " + toString(pagination)) + " ") + toString(curTempSum))) | |
498 | - | else $Tuple2([IntegerEntry(kTempCurSum, curTempSum)], [IntegerEntry(kRewardUpdateFirstPaginationHeight, rewardUpdateHeight)]) | |
499 | - | else if ((pagination == 1)) | |
500 | - | then { | |
501 | - | let curTempSumFromKey = valueOrElse(getInteger(this, kTempCurSum), 0) | |
502 | - | let rewardUpdateHeightFirstPaginationEntry = valueOrElse(getInteger(this, kRewardUpdateFirstPaginationHeight), 0) | |
503 | - | if (((curTempSum + curTempSumFromKey) > totalVoteShare)) | |
504 | - | then throw(((("sumRewardPrevious > totalVoteShare or sumRewardCurrent > totalVoteShare - " + toString(pagination)) + " ") + toString((curTempSum + curTempSumFromKey)))) | |
505 | - | else if ((rewardUpdateHeightFirstPaginationEntry != rewardUpdateHeight)) | |
506 | - | then throw("current rewardUpdateHeight != rewardUpdateHeightFirstPaginationEntry") | |
507 | - | else $Tuple2([IntegerEntry(kTempCurSum, (curTempSum + curTempSumFromKey))], nil) | |
508 | - | } | |
509 | - | else if ((pagination == 2)) | |
510 | - | then { | |
511 | - | let curSum = (valueOrElse(getInteger(this, kTempCurSum), 0) + curTempSum) | |
512 | - | let rewardUpdateHeightFirstPaginationEntry = valueOrElse(getInteger(this, kRewardUpdateFirstPaginationHeight), 0) | |
513 | - | if ((curSum != totalVoteShare)) | |
514 | - | then throw("sumRewardPrevious != totalVoteShare or sumRewardCurrent != totalVoteShare") | |
515 | - | else if ((rewardUpdateHeightFirstPaginationEntry != rewardUpdateHeight)) | |
516 | - | then throw("current rewardUpdateHeight != rewardUpdateHeightFirstPaginationEntry") | |
517 | - | else $Tuple2([IntegerEntry(kTempCurSum, curSum)], nil) | |
518 | - | } | |
519 | - | else throw("Incorrect pagination") | |
520 | - | ||
521 | - | let previousRewardEntryNew = { | |
522 | - | let $l = currentPools | |
523 | - | let $s = size($l) | |
524 | - | let $acc0 = nil | |
525 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
526 | - | then $a | |
527 | - | else changePreviousRewardEntry($a, $l[$i]) | |
528 | - | ||
529 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
530 | - | then $a | |
531 | - | else throw("List size exceeds 10") | |
532 | - | ||
533 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
534 | - | } | |
535 | - | let currentRewardEntryNew = { | |
536 | - | let $l = currentPools | |
537 | - | let $s = size($l) | |
538 | - | let $acc0 = nil | |
539 | - | func $f1_1 ($a,$i) = if (($i >= $s)) | |
540 | - | then $a | |
541 | - | else changeCurrentRewardEntry($a, $l[$i]) | |
542 | - | ||
543 | - | func $f1_2 ($a,$i) = if (($i >= $s)) | |
544 | - | then $a | |
545 | - | else throw("List size exceeds 10") | |
546 | - | ||
547 | - | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
548 | - | } | |
549 | - | let heightEntryNewCur = { | |
550 | - | let $l = currentPools | |
551 | - | let $s = size($l) | |
552 | - | let $acc0 = nil | |
553 | - | func $f2_1 ($a,$i) = if (($i >= $s)) | |
554 | - | then $a | |
555 | - | else changeHeightEntry($a, $l[$i]) | |
556 | - | ||
557 | - | func $f2_2 ($a,$i) = if (($i >= $s)) | |
558 | - | then $a | |
559 | - | else throw("List size exceeds 10") | |
560 | - | ||
561 | - | $f2_2($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
562 | - | } | |
563 | - | let sumRewardCurrentTemp = { | |
564 | - | let $l = currentRewards | |
565 | - | let $s = size($l) | |
566 | - | let $acc0 = 0 | |
567 | - | func $f3_1 ($a,$i) = if (($i >= $s)) | |
568 | - | then $a | |
569 | - | else sum($a, $l[$i]) | |
570 | - | ||
571 | - | func $f3_2 ($a,$i) = if (($i >= $s)) | |
572 | - | then $a | |
573 | - | else throw("List size exceeds 10") | |
574 | - | ||
575 | - | $f3_2($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
576 | - | } | |
577 | - | let $t02052720638 = getSumReward(sumRewardCurrentTemp, pagination) | |
578 | - | let sumRewardCurrent = $t02052720638._1 | |
579 | - | let rewardUpdateHeightFirstPaginationEntry = $t02052720638._2 | |
580 | - | let rewardUpdateHeightEntry = if ((pagination == 2)) | |
581 | - | then [IntegerEntry(kRewardUpdateHeight, rewardUpdateHeight)] | |
582 | - | else nil | |
583 | - | if ((height > rewardUpdateHeight)) | |
584 | - | then throw("rewardUpdateHeight < height") | |
585 | - | else (((((previousRewardEntryNew ++ currentRewardEntryNew) ++ heightEntryNewCur) ++ sumRewardCurrent) ++ rewardUpdateHeightEntry) ++ rewardUpdateHeightFirstPaginationEntry) | |
586 | - | } | |
587 | - | } | |
588 | - | ||
589 | - | ||
590 | - | ||
591 | - | @Callable(i) | |
592 | - | func shutdown () = if (!(isActive)) | |
593 | - | then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified"))) | |
594 | - | else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey))) | |
595 | - | then throw("Only admin can call this function") | |
596 | - | else suspend("Paused by admin") | |
597 | - | ||
598 | - | ||
599 | - | ||
600 | - | @Callable(i) | |
601 | - | func activate () = if (isActive) | |
602 | - | then throw("DApp is already active") | |
603 | - | else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey))) | |
604 | - | then throw("Only admin can call this function") | |
605 | - | else [BooleanEntry(kActive, true), DeleteEntry(kCause)] | |
114 | + | func removeAchievementsWriter (address) = valueOrElse(isSelfCall(i), { | |
115 | + | let writers = split(valueOrElse(getString(this, kAchievementsWriters), ""), ",") | |
116 | + | let index = valueOrErrorMessage(indexOf(writers, address), "Can't find address in the list") | |
117 | + | [StringEntry(kAchievementsWriters, makeString(removeByIndex(writers, index), ","))] | |
118 | + | }) | |
606 | 119 | ||
607 | 120 | ||
608 | 121 | @Verifier(tx) | |
609 | 122 | func verify () = { | |
610 | 123 | let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1)) | |
611 | 124 | then 1 | |
612 | 125 | else 0 | |
613 | 126 | let adminPubKey2Signed = if (sigVerify(tx.bodyBytes, tx.proofs[1], adminPubKey2)) | |
614 | 127 | then 1 | |
615 | 128 | else 0 | |
616 | 129 | let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3)) | |
617 | 130 | then 1 | |
618 | 131 | else 0 | |
619 | - | (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2) | |
132 | + | let signedByAdmin = (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2) | |
133 | + | let signedByAdminToCallAddPool = (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 1) | |
134 | + | match tx { | |
135 | + | case inv: InvokeScriptTransaction => | |
136 | + | let isSelfInvokeRenamePool = if ((inv.dApp == this)) | |
137 | + | then containsElement(["renamePool"], inv.function) | |
138 | + | else false | |
139 | + | let isSelfInvokeSetAdmin = if ((inv.dApp == this)) | |
140 | + | then containsElement(["setAdmin"], inv.function) | |
141 | + | else false | |
142 | + | let isSelfInvokeAddPool = if ((inv.dApp == this)) | |
143 | + | then containsElement(["addPool"], inv.function) | |
144 | + | else false | |
145 | + | let isSelfInvokeLaunchpadDataTxStatus = if ((inv.dApp == this)) | |
146 | + | then containsElement(["launchpadDataTransactionStatus"], inv.function) | |
147 | + | else false | |
148 | + | let isSelfInvokeAddAchievementsWriter = if ((inv.dApp == this)) | |
149 | + | then containsElement(["addAchievementsWriter"], inv.function) | |
150 | + | else false | |
151 | + | let isSelfInvokeRemoveAchievementsWriter = if ((inv.dApp == this)) | |
152 | + | then containsElement(["removeAchievementsWriter"], inv.function) | |
153 | + | else false | |
154 | + | if (if (if (if (if (if (if (signedByAdmin) | |
155 | + | then (size(inv.payments) == 0) | |
156 | + | else false) | |
157 | + | then isSelfInvokeRenamePool | |
158 | + | else false) | |
159 | + | then true | |
160 | + | else if (if (signedByAdminToCallAddPool) | |
161 | + | then (size(inv.payments) == 0) | |
162 | + | else false) | |
163 | + | then isSelfInvokeAddPool | |
164 | + | else false) | |
165 | + | then true | |
166 | + | else if (if (signedByAdmin) | |
167 | + | then (size(inv.payments) == 0) | |
168 | + | else false) | |
169 | + | then isSelfInvokeSetAdmin | |
170 | + | else false) | |
171 | + | then true | |
172 | + | else if (if (signedByAdmin) | |
173 | + | then (size(inv.payments) == 0) | |
174 | + | else false) | |
175 | + | then isSelfInvokeLaunchpadDataTxStatus | |
176 | + | else false) | |
177 | + | then true | |
178 | + | else if (if (signedByAdmin) | |
179 | + | then (size(inv.payments) == 0) | |
180 | + | else false) | |
181 | + | then isSelfInvokeAddAchievementsWriter | |
182 | + | else false) | |
183 | + | then true | |
184 | + | else if (if (signedByAdmin) | |
185 | + | then (size(inv.payments) == 0) | |
186 | + | else false) | |
187 | + | then isSelfInvokeRemoveAchievementsWriter | |
188 | + | else false | |
189 | + | case _: Order|DataTransaction|SponsorFeeTransaction|SetScriptTransaction|CreateAliasTransaction|LeaseCancelTransaction|LeaseTransaction|IssueTransaction|UpdateAssetInfoTransaction|InvokeScriptTransaction|SetAssetScriptTransaction|TransferTransaction|ExchangeTransaction|MassTransferTransaction|BurnTransaction|ReissueTransaction => | |
190 | + | signedByAdmin | |
191 | + | case _ => | |
192 | + | throw("Match error") | |
193 | + | } | |
620 | 194 | } | |
621 | 195 |
github/deemru/w8io/169f3d6 73.16 ms ◑