tx · 3RSsrMipRS1JTc1qaA7zr383JRgs8LAirkghcVrY4Xwo

3N86AryjXNvAuNs3mV9xKPTjXnAYQimiHDF:  -0.01000000 Waves

2023.11.16 15:48 [2845958] smart account 3N86AryjXNvAuNs3mV9xKPTjXnAYQimiHDF > SELF 0.00000000 Waves

{ "type": 13, "id": "3RSsrMipRS1JTc1qaA7zr383JRgs8LAirkghcVrY4Xwo", "fee": 1000000, "feeAssetId": null, "timestamp": 1700138916962, "version": 2, "chainId": 84, "sender": "3N86AryjXNvAuNs3mV9xKPTjXnAYQimiHDF", "senderPublicKey": "7Zo8C4qkZishvcPg5SUixQPySKeM49Jeui21Tih7iPr9", "proofs": [ "ubnPkDGfVUHkughjn2wNdn5H1YhtSMp82cPGpJtvzyAE5uhBpRKyXukFiJ7peybr5bvhZFc334MP4EC6M33EEi5" ], "script": "base64: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", "height": 2845958, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 64e2puVpfDrwBNNJqpKT399YncThTazbBgdqWawMYaPJ Next: none Diff:
OldNewDifferences
1-{-# STDLIB_VERSION 6 #-}
1+{-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+let STAKE_ASSET = base58'HuV7L2uJ4v2SDS5xqZLWPHhimTUgEMKstmxwfBY17SX3'
5+
6+let EARN_ASSET = base58'HuV7L2uJ4v2SDS5xqZLWPHhimTUgEMKstmxwfBY17SX3'
7+
8+let TOKENS_PER_MS = 1
9+
410 let SEP = "__"
511
6-let reputationAsset = base58'88Tkdpqchhiqc9tNNG3SWQ2gfhZB4rBJKhMNS5Xmxhqw'
7-
8-let proposalTime = ((((1000 * 60) * 60) * 24) * 3)
9-
10-func countProposalsKey () = "cp"
11-
12-
13-func proposalKey (proposalId) = makeString(["p", toString(proposalId)], SEP)
14-
15-
16-func unlockTimestampKey (user) = makeString(["ut", toBase58String(user.bytes)], SEP)
17-
12+let DENOMINATOR = 1000000000000000000
1813
1914 func userDepositedKey (user) = makeString(["ud", toBase58String(user.bytes)], SEP)
2015
2116
22-func userProposalVoteKey (proposalId,user) = makeString(["up", toString(proposalId), toBase58String(user.bytes)], SEP)
17+func totalDepositedKey () = "td"
2318
2419
25-func setUserVote (proposalId,user,votePower) = StringEntry(userProposalVoteKey(proposalId, user), toString(votePower))
20+func lastUpdateKey () = "lu"
2621
2722
28-func getUserVote (proposalId,user) = match getInteger(userProposalVoteKey(proposalId, user)) {
29- case i: Int =>
30- i
31- case _ =>
32- 0
33-}
23+func rewardPerTokenStoredKey () = "rpts"
3424
3525
36-func setProposal (id,creator,title,text,timestampCreation,countVotesFor,CountVotesAgainst) = StringEntry(proposalKey(id), makeString_11C([toBase16String(creator.bytes), title, text, toString(timestampCreation), toString(countVotesFor), toString(CountVotesAgainst)], SEP))
26+func userRewardPerTokenPaidKey (user) = makeString(["urpd", toBase58String(user.bytes)], SEP)
3727
3828
39-func getProposal (id) = {
40- let savedString = split( match getString(this, proposalKey(id)) {
41- case s: String =>
42- s
29+func userRewards (user) = makeString(["ur", toBase58String(user.bytes)], SEP)
30+
31+
32+func calcRewardPerTokenStored () = {
33+ let totalDeposited = toBigInt( match getInteger(totalDepositedKey()) {
34+ case a: Int =>
35+ a
4336 case _ =>
44- throw("proposal not found")
45- }, SEP)
46- $Tuple6(addressFromStringValue(savedString[0]), savedString[1], savedString[2], parseIntValue(savedString[3]), parseIntValue(savedString[4]), parseIntValue(savedString[5]))
37+ 0
38+ })
39+ let lastUpdate = toBigInt( match getInteger(lastUpdateKey()) {
40+ case a: Int =>
41+ a
42+ case _ =>
43+ lastBlock.timestamp
44+ })
45+ let rewardPerTokenStored = parseBigIntValue( match getString(rewardPerTokenStoredKey()) {
46+ case a: String =>
47+ a
48+ case _ =>
49+ "0"
50+ })
51+ if ((totalDeposited == toBigInt(0)))
52+ then rewardPerTokenStored
53+ else (rewardPerTokenStored + (((toBigInt(TOKENS_PER_MS) * (toBigInt(lastBlock.timestamp) - lastUpdate)) * toBigInt(DENOMINATOR)) / totalDeposited))
4754 }
4855
4956
50-func isPayReputationAsset (i) = if ((size(i.payments) == 1))
51- then if ((i.payments[0].assetId == reputationAsset))
52- then true
53- else throw("only reputation assets")
54- else throw("only 1 payment")
55-
56-
57-func getUnlockTimestamp (user) = match getInteger(this, unlockTimestampKey(user)) {
58- case a: Int =>
59- a
60- case _ =>
61- 0
62-}
63-
64-
65-func countProposals () = match getInteger(this, countProposalsKey()) {
66- case a: Int =>
67- a
68- case _ =>
69- 0
70-}
71-
72-
73-func userDepositedReputationAsset (user) = match getInteger(this, userDepositedKey(user)) {
74- case a: Int =>
75- a
76- case _ =>
77- 0
78-}
79-
80-
81-func isProposalAlive (id) = if (if ((countProposals() > id))
82- then ((getProposal(id)._4 + proposalTime) > lastBlock.timestamp)
83- else false)
84- then true
85- else throw("proposal not alive")
57+func earned (user) = {
58+ let userDeposited = toBigInt( match getInteger(userDepositedKey(user)) {
59+ case a: Int =>
60+ a
61+ case _ =>
62+ 0
63+ })
64+ let userRewardPerTokenPaid = parseBigIntValue(getStringValue(userRewardPerTokenPaidKey(user)))
65+ let rewards = toBigInt( match getInteger(userRewards(user)) {
66+ case a: Int =>
67+ a
68+ case _ =>
69+ 0
70+ })
71+ (fraction(userDeposited, (calcRewardPerTokenStored() - userRewardPerTokenPaid), toBigInt(DENOMINATOR)) + rewards)
72+ }
8673
8774
8875 @Callable(i)
89-func deposit () = {
90- let checks = [isPayReputationAsset(i)]
91- if ((checks == checks))
92- then {
93- let currentKey = toBase58String(i.caller.bytes)
94- let currentAmount = userDepositedReputationAsset(i.caller)
95- let newAmount = (currentAmount + i.payments[0].amount)
96-[IntegerEntry(currentKey, newAmount)]
97- }
98- else throw("onlyReputationAsset")
99- }
76+func update () = [IntegerEntry(lastUpdateKey(), lastBlock.timestamp), StringEntry(rewardPerTokenStoredKey(), toString(calcRewardPerTokenStored()))]
10077
10178
10279
10380 @Callable(i)
104-func withdraw (amount) = {
105- let currentKey = toBase58String(i.caller.bytes)
106- let currentAmount = match getInteger(this, currentKey) {
81+func deposit () = if (if ((size(i.payments) != 1))
82+ then true
83+ else (i.payments[0].assetId != STAKE_ASSET))
84+ then throw("incorrect asset deposits")
85+ else {
86+ let userDeposited = match getInteger(userDepositedKey(i.caller)) {
87+ case a: Int =>
88+ a
89+ case _ =>
90+ 0
91+ }
92+ let totalDeposited = match getInteger(totalDepositedKey()) {
93+ case a: Int =>
94+ a
95+ case _ =>
96+ 0
97+ }
98+[IntegerEntry(userDepositedKey(i.caller), (userDeposited + i.payments[0].amount)), IntegerEntry(totalDepositedKey(), (totalDeposited + i.payments[0].amount)), IntegerEntry(lastUpdateKey(), lastBlock.timestamp), StringEntry(rewardPerTokenStoredKey(), toString(calcRewardPerTokenStored())), StringEntry(userRewardPerTokenPaidKey(i.caller), toString(calcRewardPerTokenStored())), IntegerEntry(userRewards(i.caller), if ((userDeposited == 0))
99+ then 0
100+ else toInt(earned(i.caller)))]
101+ }
102+
103+
104+
105+@Callable(i)
106+func withdraw () = {
107+ let userDeposited = match getInteger(userDepositedKey(i.caller)) {
107108 case a: Int =>
108109 a
109110 case _ =>
110111 0
111112 }
112- let newAmount = (currentAmount - amount)
113- if ((0 > amount))
114- then throw("Can't withdraw negative amount")
115- else if ((getUnlockTimestamp(i.caller) > lastBlock.timestamp))
116- then throw("Locked")
117- else if ((0 > newAmount))
118- then throw("Not enough balance")
119- else [IntegerEntry(currentKey, newAmount), ScriptTransfer(i.caller, amount, reputationAsset)]
113+ let totalDeposited = match getInteger(totalDepositedKey()) {
114+ case a: Int =>
115+ a
116+ case _ =>
117+ 0
120118 }
121-
122-
123-
124-@Callable(i)
125-func createProposal (title,text) = {
126- let count = countProposals()
127-[setProposal(count, i.caller, toBase16String(title), toBase16String(text), lastBlock.timestamp, 0, 0)]
119+ let earnedTokens = toInt(earned(i.caller))
120+ if ((userDeposited == 0))
121+ then throw("empty deposit")
122+ else [IntegerEntry(userDepositedKey(i.caller), 0), IntegerEntry(totalDepositedKey(), (totalDeposited - userDeposited)), IntegerEntry(lastUpdateKey(), lastBlock.timestamp), ScriptTransfer(i.caller, userDeposited, STAKE_ASSET), ScriptTransfer(i.caller, earnedTokens, EARN_ASSET), StringEntry(rewardPerTokenStoredKey(), toString(calcRewardPerTokenStored())), StringEntry(userRewardPerTokenPaidKey(i.caller), toString(calcRewardPerTokenStored())), IntegerEntry(userRewards(i.caller), 0)]
128123 }
129-
130-
131-
132-@Callable(i)
133-func vote (id,vote) = if (!(isProposalAlive(id)))
134- then throw("proposalNotAlive")
135- else {
136- let proposal = getProposal(id)
137- let unlockTime = max([(proposal._4 + proposalTime), getUnlockTimestamp(i.caller)])
138- let previusVote = getUserVote(id, i.caller)
139- let votePower = userDepositedReputationAsset(i.caller)
140-[setProposal(id, proposal._1, proposal._2, proposal._3, proposal._4, (proposal._5 - (if ((previusVote > 0))
141- then previusVote
142- else (0 + (if (vote)
143- then votePower
144- else 0)))), (proposal._6 - (if ((0 > previusVote))
145- then previusVote
146- else (0 + (if (vote)
147- then 0
148- else votePower)))))]
149- }
150124
151125
152126 @Verifier(tx)
Full:
OldNewDifferences
1-{-# STDLIB_VERSION 6 #-}
1+{-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+let STAKE_ASSET = base58'HuV7L2uJ4v2SDS5xqZLWPHhimTUgEMKstmxwfBY17SX3'
5+
6+let EARN_ASSET = base58'HuV7L2uJ4v2SDS5xqZLWPHhimTUgEMKstmxwfBY17SX3'
7+
8+let TOKENS_PER_MS = 1
9+
410 let SEP = "__"
511
6-let reputationAsset = base58'88Tkdpqchhiqc9tNNG3SWQ2gfhZB4rBJKhMNS5Xmxhqw'
7-
8-let proposalTime = ((((1000 * 60) * 60) * 24) * 3)
9-
10-func countProposalsKey () = "cp"
11-
12-
13-func proposalKey (proposalId) = makeString(["p", toString(proposalId)], SEP)
14-
15-
16-func unlockTimestampKey (user) = makeString(["ut", toBase58String(user.bytes)], SEP)
17-
12+let DENOMINATOR = 1000000000000000000
1813
1914 func userDepositedKey (user) = makeString(["ud", toBase58String(user.bytes)], SEP)
2015
2116
22-func userProposalVoteKey (proposalId,user) = makeString(["up", toString(proposalId), toBase58String(user.bytes)], SEP)
17+func totalDepositedKey () = "td"
2318
2419
25-func setUserVote (proposalId,user,votePower) = StringEntry(userProposalVoteKey(proposalId, user), toString(votePower))
20+func lastUpdateKey () = "lu"
2621
2722
28-func getUserVote (proposalId,user) = match getInteger(userProposalVoteKey(proposalId, user)) {
29- case i: Int =>
30- i
31- case _ =>
32- 0
33-}
23+func rewardPerTokenStoredKey () = "rpts"
3424
3525
36-func setProposal (id,creator,title,text,timestampCreation,countVotesFor,CountVotesAgainst) = StringEntry(proposalKey(id), makeString_11C([toBase16String(creator.bytes), title, text, toString(timestampCreation), toString(countVotesFor), toString(CountVotesAgainst)], SEP))
26+func userRewardPerTokenPaidKey (user) = makeString(["urpd", toBase58String(user.bytes)], SEP)
3727
3828
39-func getProposal (id) = {
40- let savedString = split( match getString(this, proposalKey(id)) {
41- case s: String =>
42- s
29+func userRewards (user) = makeString(["ur", toBase58String(user.bytes)], SEP)
30+
31+
32+func calcRewardPerTokenStored () = {
33+ let totalDeposited = toBigInt( match getInteger(totalDepositedKey()) {
34+ case a: Int =>
35+ a
4336 case _ =>
44- throw("proposal not found")
45- }, SEP)
46- $Tuple6(addressFromStringValue(savedString[0]), savedString[1], savedString[2], parseIntValue(savedString[3]), parseIntValue(savedString[4]), parseIntValue(savedString[5]))
37+ 0
38+ })
39+ let lastUpdate = toBigInt( match getInteger(lastUpdateKey()) {
40+ case a: Int =>
41+ a
42+ case _ =>
43+ lastBlock.timestamp
44+ })
45+ let rewardPerTokenStored = parseBigIntValue( match getString(rewardPerTokenStoredKey()) {
46+ case a: String =>
47+ a
48+ case _ =>
49+ "0"
50+ })
51+ if ((totalDeposited == toBigInt(0)))
52+ then rewardPerTokenStored
53+ else (rewardPerTokenStored + (((toBigInt(TOKENS_PER_MS) * (toBigInt(lastBlock.timestamp) - lastUpdate)) * toBigInt(DENOMINATOR)) / totalDeposited))
4754 }
4855
4956
50-func isPayReputationAsset (i) = if ((size(i.payments) == 1))
51- then if ((i.payments[0].assetId == reputationAsset))
52- then true
53- else throw("only reputation assets")
54- else throw("only 1 payment")
55-
56-
57-func getUnlockTimestamp (user) = match getInteger(this, unlockTimestampKey(user)) {
58- case a: Int =>
59- a
60- case _ =>
61- 0
62-}
63-
64-
65-func countProposals () = match getInteger(this, countProposalsKey()) {
66- case a: Int =>
67- a
68- case _ =>
69- 0
70-}
71-
72-
73-func userDepositedReputationAsset (user) = match getInteger(this, userDepositedKey(user)) {
74- case a: Int =>
75- a
76- case _ =>
77- 0
78-}
79-
80-
81-func isProposalAlive (id) = if (if ((countProposals() > id))
82- then ((getProposal(id)._4 + proposalTime) > lastBlock.timestamp)
83- else false)
84- then true
85- else throw("proposal not alive")
57+func earned (user) = {
58+ let userDeposited = toBigInt( match getInteger(userDepositedKey(user)) {
59+ case a: Int =>
60+ a
61+ case _ =>
62+ 0
63+ })
64+ let userRewardPerTokenPaid = parseBigIntValue(getStringValue(userRewardPerTokenPaidKey(user)))
65+ let rewards = toBigInt( match getInteger(userRewards(user)) {
66+ case a: Int =>
67+ a
68+ case _ =>
69+ 0
70+ })
71+ (fraction(userDeposited, (calcRewardPerTokenStored() - userRewardPerTokenPaid), toBigInt(DENOMINATOR)) + rewards)
72+ }
8673
8774
8875 @Callable(i)
89-func deposit () = {
90- let checks = [isPayReputationAsset(i)]
91- if ((checks == checks))
92- then {
93- let currentKey = toBase58String(i.caller.bytes)
94- let currentAmount = userDepositedReputationAsset(i.caller)
95- let newAmount = (currentAmount + i.payments[0].amount)
96-[IntegerEntry(currentKey, newAmount)]
97- }
98- else throw("onlyReputationAsset")
99- }
76+func update () = [IntegerEntry(lastUpdateKey(), lastBlock.timestamp), StringEntry(rewardPerTokenStoredKey(), toString(calcRewardPerTokenStored()))]
10077
10178
10279
10380 @Callable(i)
104-func withdraw (amount) = {
105- let currentKey = toBase58String(i.caller.bytes)
106- let currentAmount = match getInteger(this, currentKey) {
81+func deposit () = if (if ((size(i.payments) != 1))
82+ then true
83+ else (i.payments[0].assetId != STAKE_ASSET))
84+ then throw("incorrect asset deposits")
85+ else {
86+ let userDeposited = match getInteger(userDepositedKey(i.caller)) {
87+ case a: Int =>
88+ a
89+ case _ =>
90+ 0
91+ }
92+ let totalDeposited = match getInteger(totalDepositedKey()) {
93+ case a: Int =>
94+ a
95+ case _ =>
96+ 0
97+ }
98+[IntegerEntry(userDepositedKey(i.caller), (userDeposited + i.payments[0].amount)), IntegerEntry(totalDepositedKey(), (totalDeposited + i.payments[0].amount)), IntegerEntry(lastUpdateKey(), lastBlock.timestamp), StringEntry(rewardPerTokenStoredKey(), toString(calcRewardPerTokenStored())), StringEntry(userRewardPerTokenPaidKey(i.caller), toString(calcRewardPerTokenStored())), IntegerEntry(userRewards(i.caller), if ((userDeposited == 0))
99+ then 0
100+ else toInt(earned(i.caller)))]
101+ }
102+
103+
104+
105+@Callable(i)
106+func withdraw () = {
107+ let userDeposited = match getInteger(userDepositedKey(i.caller)) {
107108 case a: Int =>
108109 a
109110 case _ =>
110111 0
111112 }
112- let newAmount = (currentAmount - amount)
113- if ((0 > amount))
114- then throw("Can't withdraw negative amount")
115- else if ((getUnlockTimestamp(i.caller) > lastBlock.timestamp))
116- then throw("Locked")
117- else if ((0 > newAmount))
118- then throw("Not enough balance")
119- else [IntegerEntry(currentKey, newAmount), ScriptTransfer(i.caller, amount, reputationAsset)]
113+ let totalDeposited = match getInteger(totalDepositedKey()) {
114+ case a: Int =>
115+ a
116+ case _ =>
117+ 0
120118 }
121-
122-
123-
124-@Callable(i)
125-func createProposal (title,text) = {
126- let count = countProposals()
127-[setProposal(count, i.caller, toBase16String(title), toBase16String(text), lastBlock.timestamp, 0, 0)]
119+ let earnedTokens = toInt(earned(i.caller))
120+ if ((userDeposited == 0))
121+ then throw("empty deposit")
122+ else [IntegerEntry(userDepositedKey(i.caller), 0), IntegerEntry(totalDepositedKey(), (totalDeposited - userDeposited)), IntegerEntry(lastUpdateKey(), lastBlock.timestamp), ScriptTransfer(i.caller, userDeposited, STAKE_ASSET), ScriptTransfer(i.caller, earnedTokens, EARN_ASSET), StringEntry(rewardPerTokenStoredKey(), toString(calcRewardPerTokenStored())), StringEntry(userRewardPerTokenPaidKey(i.caller), toString(calcRewardPerTokenStored())), IntegerEntry(userRewards(i.caller), 0)]
128123 }
129-
130-
131-
132-@Callable(i)
133-func vote (id,vote) = if (!(isProposalAlive(id)))
134- then throw("proposalNotAlive")
135- else {
136- let proposal = getProposal(id)
137- let unlockTime = max([(proposal._4 + proposalTime), getUnlockTimestamp(i.caller)])
138- let previusVote = getUserVote(id, i.caller)
139- let votePower = userDepositedReputationAsset(i.caller)
140-[setProposal(id, proposal._1, proposal._2, proposal._3, proposal._4, (proposal._5 - (if ((previusVote > 0))
141- then previusVote
142- else (0 + (if (vote)
143- then votePower
144- else 0)))), (proposal._6 - (if ((0 > previusVote))
145- then previusVote
146- else (0 + (if (vote)
147- then 0
148- else votePower)))))]
149- }
150124
151125
152126 @Verifier(tx)
153127 func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
154128

github/deemru/w8io/6500d08 
36.38 ms