tx · Eq8fuGgacUCLjqBMNrcgtCNm9boN8YaSSmnuyNqysJLu 3PRBVq52csUvTx77NYwLTULrt2e9jdsHfRB: -0.00700000 Waves 2022.09.09 18:17 [3287258] smart account 3PRBVq52csUvTx77NYwLTULrt2e9jdsHfRB > SELF 0.00000000 Waves
{ "type": 13, "id": "Eq8fuGgacUCLjqBMNrcgtCNm9boN8YaSSmnuyNqysJLu", "fee": 700000, "feeAssetId": null, "timestamp": 1662736638574, "version": 1, "sender": "3PRBVq52csUvTx77NYwLTULrt2e9jdsHfRB", "senderPublicKey": "9XcgkNhoevmBJ1hdDkEQ7joCc8LgpnGx6chYf8uiQZ7t", "proofs": [ "259ymfVzrL4v57FYdwAqehjpLwDuhEPzLwYz1CKHFrCE49fS5XLmSW5Z2cRVCVdWWUWZodHDQQEEhwQGSJzhapBT" ], "script": "base64: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", "chainId": 87, "height": 3287258, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: GHgruqPu9CdHAwBXaE6n8j9rc21YAT1xG2b9A2NY7VSY Next: Fmkiv7jrqs1VyFfy9Lk6F9J4TYoDx8vicWhwvUxoKukn Diff:
Old | New | Differences | |
---|---|---|---|
1 | - | {-# STDLIB_VERSION | |
1 | + | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | func writeConstString (key,value) = if (!(isDefined(getString(this, key)))) | |
6 | 6 | else throw(("already initialized: " + key)) | |
7 | 7 | ||
8 | 8 | ||
9 | - | func writeConstInt (key,value) = if (!(isDefined(getInteger(this, key)))) | |
10 | - | then IntegerEntry(key, value) | |
11 | - | else throw(("already initialized: " + key)) | |
12 | - | ||
13 | - | ||
14 | - | func writeInt (key,value) = if ((0 > value)) | |
15 | - | then throw(((("writing negative value " + toString(value)) + " for key ") + key)) | |
16 | - | else IntegerEntry(key, value) | |
17 | - | ||
18 | - | ||
19 | - | func changeBy (key,value) = writeInt(key, (valueOrElse(getInteger(this, key), 0) + value)) | |
20 | - | ||
21 | - | ||
22 | 9 | let configStore = "config" | |
23 | 10 | ||
24 | 11 | let configAddress = addressFromStringValue(getStringValue(this, configStore)) | |
12 | + | ||
13 | + | let aIdS = "assetId" | |
14 | + | ||
15 | + | let factorsBase = 1000 | |
16 | + | ||
17 | + | func asInt2 (value) = match value { | |
18 | + | case x: (Int, Int) => | |
19 | + | x | |
20 | + | case t => | |
21 | + | throw("wrong type, expected: Int2") | |
22 | + | } | |
23 | + | ||
25 | 24 | ||
26 | 25 | let maybeOracleAddress = match getString(configAddress, "oracle_address") { | |
27 | 26 | case s: String => | |
32 | 31 | ||
33 | 32 | let HEIGHT = height | |
34 | 33 | ||
35 | - | func opAllowed (op) = match invoke(configAddress, "opAllowed", ["usdn", op], nil) { | |
36 | - | case b: Boolean => | |
37 | - | if (b) | |
38 | - | then true | |
39 | - | else throw("not allowed") | |
40 | - | case _ => | |
41 | - | throw("opAllowed: unexpected result type") | |
42 | - | } | |
34 | + | let timeframe = valueOrElse(getInteger(configAddress, "WithdrawLimitTimeframe"), 1440) | |
35 | + | ||
36 | + | let currentEpochStart = ((HEIGHT / timeframe) * timeframe) | |
37 | + | ||
38 | + | func userWithdrawnWithinEpochStore (user,assetId) = ((user + "_used_") + assetId) | |
39 | + | ||
40 | + | ||
41 | + | func globalImportedPerEpochPerReserveStore (reserve) = ((("global_imported_" + reserve) + "_") + toString(currentEpochStart)) | |
42 | + | ||
43 | + | ||
44 | + | let breakpoints = (split(valueOrElse(getString(configAddress, "LimitUtilizationBreakpoints"), "0"), "|") ++ ["0"]) | |
45 | + | ||
46 | + | func actionThreshold (action,assetId) = { | |
47 | + | let key = (((assetId + "_") + action) + "_utilization_threshold") | |
48 | + | valueOrElse(getInteger(configAddress, key), 1100) | |
49 | + | } | |
50 | + | ||
51 | + | ||
52 | + | func limit (assetId,util) = { | |
53 | + | let breakpoint = { | |
54 | + | func fold (a,bp) = if ((util >= a)) | |
55 | + | then a | |
56 | + | else parseIntValue(bp) | |
57 | + | ||
58 | + | let $l = breakpoints | |
59 | + | let $s = size($l) | |
60 | + | let $acc0 = parseIntValue(breakpoints[0]) | |
61 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
62 | + | then $a | |
63 | + | else fold($a, $l[$i]) | |
64 | + | ||
65 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
66 | + | then $a | |
67 | + | else throw("List size exceeds 10") | |
68 | + | ||
69 | + | $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) | |
70 | + | } | |
71 | + | getInteger(configAddress, (((assetId + "_") + toString(breakpoint)) + "_acc_limit")) | |
72 | + | } | |
73 | + | ||
74 | + | ||
75 | + | func ensureActionThreshold (action,assetId,util) = { | |
76 | + | let at = actionThreshold(action, assetId) | |
77 | + | if ((util >= at)) | |
78 | + | then throw(((((((action + " of ") + assetId) + " paused due to high utilization: ") + toString(util)) + " >= ") + toString(at))) | |
79 | + | else true | |
80 | + | } | |
43 | 81 | ||
44 | 82 | ||
45 | 83 | func mainOnly (i) = if (contains(getStringValue(configAddress, "main"), toString(i.caller))) | |
46 | 84 | then true | |
47 | - | else throw("only main can do") | |
48 | - | ||
49 | - | ||
50 | - | func throwIf (condition,error) = if (condition) | |
51 | - | then throw(error) | |
52 | - | else true | |
53 | - | ||
54 | - | ||
55 | - | let TIMEFRAME = 1440 | |
56 | - | ||
57 | - | let usdn = getStringValue(this, "usdn") | |
58 | - | ||
59 | - | func addressTotalStoreLegacy (address) = (address + "_usdn") | |
60 | - | ||
61 | - | ||
62 | - | func addressTotalStore (address) = (address + "_USDN") | |
63 | - | ||
64 | - | ||
65 | - | func vestingStartStore (address) = (address + "_vesting_start") | |
66 | - | ||
67 | - | ||
68 | - | func vestingClaimedStore (address) = (address + "_claimed") | |
69 | - | ||
70 | - | ||
71 | - | func withdrawnWithinEpochStore (epochStart,address,assetId) = (((((address + "_") + assetId) + "_") + toString(epochStart)) + "_withdrawn_within_epoch") | |
72 | - | ||
73 | - | ||
74 | - | let currentEpochStart = ((HEIGHT / TIMEFRAME) * TIMEFRAME) | |
75 | - | ||
76 | - | let minClaimUsdn = valueOrElse(getInteger(configAddress, "minimaxVestingUsdnAll"), (100 * 1000000)) | |
77 | - | ||
78 | - | let maxTotalPerDay = valueOrElse(getInteger(configAddress, "maxDailyVestingUsdnAll"), ((100 * 1000) * 1000000)) | |
79 | - | ||
80 | - | let totalUSDNStore = "total_usdn" | |
81 | - | ||
82 | - | func withdrawnTodayStore (address) = withdrawnWithinEpochStore(currentEpochStart, address, usdn) | |
83 | - | ||
84 | - | ||
85 | - | func withdrawnToday (address) = valueOrElse(getInteger(withdrawnTodayStore(address)), 0) | |
86 | - | ||
87 | - | ||
88 | - | let withdrawnTodayTotalStore = withdrawnWithinEpochStore(currentEpochStart, "total", usdn) | |
89 | - | ||
90 | - | let withdrawnTodayTotal = valueOrElse(getInteger(withdrawnTodayTotalStore), 0) | |
91 | - | ||
92 | - | let totalAvailableToday = (maxTotalPerDay - withdrawnTodayTotal) | |
93 | - | ||
94 | - | func userVestingBalance (address) = { | |
95 | - | let totalVesting = valueOrElse(getInteger(addressTotalStore(address)), valueOrElse(getInteger(addressTotalStoreLegacy(address)), 0)) | |
96 | - | let alreadyClaimed = valueOrElse(getInteger(vestingClaimedStore(address)), 0) | |
97 | - | let claimedToday = withdrawnToday(address) | |
98 | - | match getInteger(this, vestingStartStore(address)) { | |
99 | - | case vestingStart: Int => | |
100 | - | let totalNonClaimed = (totalVesting - alreadyClaimed) | |
101 | - | let dailyLimit = max([minClaimUsdn, (totalVesting / 500)]) | |
102 | - | let availableToday = min([totalNonClaimed, totalAvailableToday, (dailyLimit - claimedToday)]) | |
103 | - | $Tuple5(totalVesting, alreadyClaimed, vestingStart, claimedToday, availableToday) | |
104 | - | case _ => | |
105 | - | $Tuple7(totalVesting, 0, -1, -1, -1, -1, -1) | |
106 | - | } | |
107 | - | } | |
108 | - | ||
109 | - | ||
110 | - | func adviseUser (address) = { | |
111 | - | let $t035153616 = userVestingBalance(address) | |
112 | - | let totalVesting = $t035153616._1 | |
113 | - | let alreadyClaimed = $t035153616._2 | |
114 | - | let start = $t035153616._3 | |
115 | - | let claimedToday = $t035153616._4 | |
116 | - | let availableToday = $t035153616._5 | |
117 | - | ((((((((((((((("markets_address: " + address) + ", markets_totalVesting: ") + toString(totalVesting)) + ", markets_alreadyClaimed: ") + toString(alreadyClaimed)) + ", markets_startHeight: ") + toString(start)) + ", markets_dailyLimit: ") + toString(max([minClaimUsdn, (totalVesting / 500)]))) + ", markets_claimedToday: ") + toString(claimedToday)) + ", markets_availableToday: ") + toString(availableToday)) + ", markets_globallyAvailableToday: ") + toString(totalAvailableToday)) | |
118 | - | } | |
119 | - | ||
120 | - | ||
121 | - | func withdrawVestedInternal (address,to) = { | |
122 | - | let checks = opAllowed("liquidao_all_withdrawVested") | |
123 | - | if ((checks == checks)) | |
124 | - | then { | |
125 | - | let $t042594360 = userVestingBalance(address) | |
126 | - | let totalVesting = $t042594360._1 | |
127 | - | let alreadyClaimed = $t042594360._2 | |
128 | - | let start = $t042594360._3 | |
129 | - | let claimedToday = $t042594360._4 | |
130 | - | let availableToday = $t042594360._5 | |
131 | - | if ((0 > start)) | |
132 | - | then throw("no vesting enabled") | |
133 | - | else if ((0 >= availableToday)) | |
134 | - | then throw("nothing available") | |
135 | - | else $Tuple2([ScriptTransfer(addressFromStringValue(to), availableToday, fromBase58String(usdn)), IntegerEntry(vestingClaimedStore(address), (alreadyClaimed + availableToday)), changeBy(withdrawnTodayStore(address), availableToday), changeBy(withdrawnTodayTotalStore, availableToday)], availableToday) | |
136 | - | } | |
137 | - | else throw("Strict value is not equal to itself.") | |
138 | - | } | |
85 | + | else throw("limiter2: only main can do") | |
139 | 86 | ||
140 | 87 | ||
141 | 88 | @Callable(i) | |
142 | - | func init (conf,nId) = if ((i.caller != this)) | |
143 | - | then throw("only self can init") | |
144 | - | else [writeConstString(configStore, conf), writeConstString("usdn", nId)] | |
89 | + | func initialize (ca) = [writeConstString(configStore, ca)] | |
145 | 90 | ||
146 | 91 | ||
147 | 92 | ||
148 | 93 | @Callable(i) | |
149 | - | func withdrawVested () = { | |
150 | - | let address = toString(i.caller) | |
151 | - | withdrawVestedInternal(address, address) | |
152 | - | } | |
153 | - | ||
154 | - | ||
155 | - | ||
156 | - | @Callable(i) | |
157 | - | func withdrawVestedForTo (acc,to) = { | |
158 | - | let checks = mainOnly(i) | |
159 | - | if ((checks == checks)) | |
160 | - | then withdrawVestedInternal(acc, to) | |
161 | - | else throw("Strict value is not equal to itself.") | |
162 | - | } | |
163 | - | ||
164 | - | ||
165 | - | ||
166 | - | @Callable(i) | |
167 | - | func accountFor (address) = { | |
168 | - | let attached = i.payments[0] | |
169 | - | let checks = if (if (mainOnly(i)) | |
170 | - | then opAllowed("liquidao_all_move") | |
171 | - | else false) | |
172 | - | then throwIf((toBase58String(value(attached.assetId)) != usdn), "usdn must be attached") | |
173 | - | else false | |
174 | - | if ((checks == checks)) | |
94 | + | func validateLimit (action,reserve,user,amount) = { | |
95 | + | let m = mainOnly(i) | |
96 | + | if ((m == m)) | |
175 | 97 | then { | |
176 | - | let $t055445645 = userVestingBalance(address) | |
177 | - | let totalVesting = $t055445645._1 | |
178 | - | let alreadyClaimed = $t055445645._2 | |
179 | - | let start = $t055445645._3 | |
180 | - | let claimedToday = $t055445645._4 | |
181 | - | let availableToday = $t055445645._5 | |
182 | - | [writeInt(vestingStartStore(address), HEIGHT), writeInt(addressTotalStore(address), (totalVesting + attached.amount)), changeBy(totalUSDNStore, attached.amount)] | |
98 | + | let rsr = addressFromStringValue(reserve) | |
99 | + | let assetId = valueOrErrorMessage(getString(rsr, aIdS), "no assetId") | |
100 | + | let $t024842564 = asInt2(invoke(rsr, "storedDepositBorrow", nil, nil)) | |
101 | + | let totalDeposit = $t024842564._1 | |
102 | + | let totalDebt = $t024842564._2 | |
103 | + | let util = if ((totalDeposit > 0)) | |
104 | + | then min([factorsBase, fraction(totalDebt, factorsBase, totalDeposit)]) | |
105 | + | else 0 | |
106 | + | if (if ((action == "borrow")) | |
107 | + | then true | |
108 | + | else (action == "withdraw")) | |
109 | + | then { | |
110 | + | let at = ensureActionThreshold(action, assetId, util) | |
111 | + | if ((at == at)) | |
112 | + | then match limit(assetId, util) { | |
113 | + | case lmt: Int => | |
114 | + | if ((0 > lmt)) | |
115 | + | then $Tuple2(nil, -1) | |
116 | + | else if ((lmt == 0)) | |
117 | + | then throw((action + " is denied")) | |
118 | + | else { | |
119 | + | let store = userWithdrawnWithinEpochStore(user, assetId) | |
120 | + | let $t030473279 = match getString(store) { | |
121 | + | case s: String => | |
122 | + | let data = split(s, "|") | |
123 | + | $Tuple2(parseIntValue(data[0]), parseIntValue(data[1])) | |
124 | + | case _ => | |
125 | + | $Tuple2(0, 0) | |
126 | + | } | |
127 | + | let epoch = $t030473279._1 | |
128 | + | let withdrawn = $t030473279._2 | |
129 | + | let userWithdrawnWithinCurrentEpoch = if ((epoch == currentEpochStart)) | |
130 | + | then withdrawn | |
131 | + | else 0 | |
132 | + | let newTotal = (userWithdrawnWithinCurrentEpoch + amount) | |
133 | + | if ((newTotal > lmt)) | |
134 | + | then { | |
135 | + | let currentEpochEnd = ((1 + (HEIGHT / timeframe)) * timeframe) | |
136 | + | throw(((((((((((((("breaching " + action) + " limit ") + toString(lmt)) + " ") + assetId) + " over ") + toString(timeframe)) + " blocks. Available: ") + toString((lmt - userWithdrawnWithinCurrentEpoch))) + " current epoch: ") + toString(currentEpochStart)) + "-") + toString(currentEpochEnd))) | |
137 | + | } | |
138 | + | else { | |
139 | + | let data = ((toString(currentEpochStart) + "|") + toString(newTotal)) | |
140 | + | $Tuple2([StringEntry(store, data)], (lmt - newTotal)) | |
141 | + | } | |
142 | + | } | |
143 | + | case _ => | |
144 | + | $Tuple2(nil, -1) | |
145 | + | } | |
146 | + | else throw("Strict value is not equal to itself.") | |
147 | + | } | |
148 | + | else if ((action == "import")) | |
149 | + | then { | |
150 | + | let at = actionThreshold(action, assetId) | |
151 | + | let importAllowedReserves = valueOrElse(getString(configAddress, "import_always_allowed_reserves"), "") | |
152 | + | let importException = contains(importAllowedReserves, reserve) | |
153 | + | if (if (!(importException)) | |
154 | + | then (util >= at) | |
155 | + | else false) | |
156 | + | then throw(((((((action + " of ") + assetId) + " paused due to high utilization: ") + toString(util)) + " >= ") + toString(at))) | |
157 | + | else { | |
158 | + | let globalLimit = valueOrElse(getInteger(configAddress, ("daily_import_limit_" + reserve)), 1000000000000000) | |
159 | + | let store = globalImportedPerEpochPerReserveStore(reserve) | |
160 | + | let globalImported = valueOrElse(getInteger(this, store), 0) | |
161 | + | let newTotal = (globalImported + amount) | |
162 | + | if ((newTotal > globalLimit)) | |
163 | + | then throw("import limit exceeded") | |
164 | + | else $Tuple2([IntegerEntry(store, newTotal)], (globalLimit - newTotal)) | |
165 | + | } | |
166 | + | } | |
167 | + | else if ((action == "redeem")) | |
168 | + | then { | |
169 | + | let at = ensureActionThreshold(action, assetId, util) | |
170 | + | if ((at == at)) | |
171 | + | then $Tuple2(nil, -1) | |
172 | + | else throw("Strict value is not equal to itself.") | |
173 | + | } | |
174 | + | else throw("limiter2: invalid action") | |
183 | 175 | } | |
184 | 176 | else throw("Strict value is not equal to itself.") | |
185 | 177 | } | |
186 | - | ||
187 | - | ||
188 | - | ||
189 | - | @Callable(i) | |
190 | - | func adviseU (acc) = $Tuple2(nil, adviseUser(acc)) | |
191 | 178 | ||
192 | 179 |
Old | New | Differences | |
---|---|---|---|
1 | - | {-# STDLIB_VERSION | |
1 | + | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | func writeConstString (key,value) = if (!(isDefined(getString(this, key)))) | |
5 | 5 | then StringEntry(key, value) | |
6 | 6 | else throw(("already initialized: " + key)) | |
7 | 7 | ||
8 | 8 | ||
9 | - | func writeConstInt (key,value) = if (!(isDefined(getInteger(this, key)))) | |
10 | - | then IntegerEntry(key, value) | |
11 | - | else throw(("already initialized: " + key)) | |
12 | - | ||
13 | - | ||
14 | - | func writeInt (key,value) = if ((0 > value)) | |
15 | - | then throw(((("writing negative value " + toString(value)) + " for key ") + key)) | |
16 | - | else IntegerEntry(key, value) | |
17 | - | ||
18 | - | ||
19 | - | func changeBy (key,value) = writeInt(key, (valueOrElse(getInteger(this, key), 0) + value)) | |
20 | - | ||
21 | - | ||
22 | 9 | let configStore = "config" | |
23 | 10 | ||
24 | 11 | let configAddress = addressFromStringValue(getStringValue(this, configStore)) | |
12 | + | ||
13 | + | let aIdS = "assetId" | |
14 | + | ||
15 | + | let factorsBase = 1000 | |
16 | + | ||
17 | + | func asInt2 (value) = match value { | |
18 | + | case x: (Int, Int) => | |
19 | + | x | |
20 | + | case t => | |
21 | + | throw("wrong type, expected: Int2") | |
22 | + | } | |
23 | + | ||
25 | 24 | ||
26 | 25 | let maybeOracleAddress = match getString(configAddress, "oracle_address") { | |
27 | 26 | case s: String => | |
28 | 27 | addressFromString(s) | |
29 | 28 | case _ => | |
30 | 29 | unit | |
31 | 30 | } | |
32 | 31 | ||
33 | 32 | let HEIGHT = height | |
34 | 33 | ||
35 | - | func opAllowed (op) = match invoke(configAddress, "opAllowed", ["usdn", op], nil) { | |
36 | - | case b: Boolean => | |
37 | - | if (b) | |
38 | - | then true | |
39 | - | else throw("not allowed") | |
40 | - | case _ => | |
41 | - | throw("opAllowed: unexpected result type") | |
42 | - | } | |
34 | + | let timeframe = valueOrElse(getInteger(configAddress, "WithdrawLimitTimeframe"), 1440) | |
35 | + | ||
36 | + | let currentEpochStart = ((HEIGHT / timeframe) * timeframe) | |
37 | + | ||
38 | + | func userWithdrawnWithinEpochStore (user,assetId) = ((user + "_used_") + assetId) | |
39 | + | ||
40 | + | ||
41 | + | func globalImportedPerEpochPerReserveStore (reserve) = ((("global_imported_" + reserve) + "_") + toString(currentEpochStart)) | |
42 | + | ||
43 | + | ||
44 | + | let breakpoints = (split(valueOrElse(getString(configAddress, "LimitUtilizationBreakpoints"), "0"), "|") ++ ["0"]) | |
45 | + | ||
46 | + | func actionThreshold (action,assetId) = { | |
47 | + | let key = (((assetId + "_") + action) + "_utilization_threshold") | |
48 | + | valueOrElse(getInteger(configAddress, key), 1100) | |
49 | + | } | |
50 | + | ||
51 | + | ||
52 | + | func limit (assetId,util) = { | |
53 | + | let breakpoint = { | |
54 | + | func fold (a,bp) = if ((util >= a)) | |
55 | + | then a | |
56 | + | else parseIntValue(bp) | |
57 | + | ||
58 | + | let $l = breakpoints | |
59 | + | let $s = size($l) | |
60 | + | let $acc0 = parseIntValue(breakpoints[0]) | |
61 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
62 | + | then $a | |
63 | + | else fold($a, $l[$i]) | |
64 | + | ||
65 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
66 | + | then $a | |
67 | + | else throw("List size exceeds 10") | |
68 | + | ||
69 | + | $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) | |
70 | + | } | |
71 | + | getInteger(configAddress, (((assetId + "_") + toString(breakpoint)) + "_acc_limit")) | |
72 | + | } | |
73 | + | ||
74 | + | ||
75 | + | func ensureActionThreshold (action,assetId,util) = { | |
76 | + | let at = actionThreshold(action, assetId) | |
77 | + | if ((util >= at)) | |
78 | + | then throw(((((((action + " of ") + assetId) + " paused due to high utilization: ") + toString(util)) + " >= ") + toString(at))) | |
79 | + | else true | |
80 | + | } | |
43 | 81 | ||
44 | 82 | ||
45 | 83 | func mainOnly (i) = if (contains(getStringValue(configAddress, "main"), toString(i.caller))) | |
46 | 84 | then true | |
47 | - | else throw("only main can do") | |
48 | - | ||
49 | - | ||
50 | - | func throwIf (condition,error) = if (condition) | |
51 | - | then throw(error) | |
52 | - | else true | |
53 | - | ||
54 | - | ||
55 | - | let TIMEFRAME = 1440 | |
56 | - | ||
57 | - | let usdn = getStringValue(this, "usdn") | |
58 | - | ||
59 | - | func addressTotalStoreLegacy (address) = (address + "_usdn") | |
60 | - | ||
61 | - | ||
62 | - | func addressTotalStore (address) = (address + "_USDN") | |
63 | - | ||
64 | - | ||
65 | - | func vestingStartStore (address) = (address + "_vesting_start") | |
66 | - | ||
67 | - | ||
68 | - | func vestingClaimedStore (address) = (address + "_claimed") | |
69 | - | ||
70 | - | ||
71 | - | func withdrawnWithinEpochStore (epochStart,address,assetId) = (((((address + "_") + assetId) + "_") + toString(epochStart)) + "_withdrawn_within_epoch") | |
72 | - | ||
73 | - | ||
74 | - | let currentEpochStart = ((HEIGHT / TIMEFRAME) * TIMEFRAME) | |
75 | - | ||
76 | - | let minClaimUsdn = valueOrElse(getInteger(configAddress, "minimaxVestingUsdnAll"), (100 * 1000000)) | |
77 | - | ||
78 | - | let maxTotalPerDay = valueOrElse(getInteger(configAddress, "maxDailyVestingUsdnAll"), ((100 * 1000) * 1000000)) | |
79 | - | ||
80 | - | let totalUSDNStore = "total_usdn" | |
81 | - | ||
82 | - | func withdrawnTodayStore (address) = withdrawnWithinEpochStore(currentEpochStart, address, usdn) | |
83 | - | ||
84 | - | ||
85 | - | func withdrawnToday (address) = valueOrElse(getInteger(withdrawnTodayStore(address)), 0) | |
86 | - | ||
87 | - | ||
88 | - | let withdrawnTodayTotalStore = withdrawnWithinEpochStore(currentEpochStart, "total", usdn) | |
89 | - | ||
90 | - | let withdrawnTodayTotal = valueOrElse(getInteger(withdrawnTodayTotalStore), 0) | |
91 | - | ||
92 | - | let totalAvailableToday = (maxTotalPerDay - withdrawnTodayTotal) | |
93 | - | ||
94 | - | func userVestingBalance (address) = { | |
95 | - | let totalVesting = valueOrElse(getInteger(addressTotalStore(address)), valueOrElse(getInteger(addressTotalStoreLegacy(address)), 0)) | |
96 | - | let alreadyClaimed = valueOrElse(getInteger(vestingClaimedStore(address)), 0) | |
97 | - | let claimedToday = withdrawnToday(address) | |
98 | - | match getInteger(this, vestingStartStore(address)) { | |
99 | - | case vestingStart: Int => | |
100 | - | let totalNonClaimed = (totalVesting - alreadyClaimed) | |
101 | - | let dailyLimit = max([minClaimUsdn, (totalVesting / 500)]) | |
102 | - | let availableToday = min([totalNonClaimed, totalAvailableToday, (dailyLimit - claimedToday)]) | |
103 | - | $Tuple5(totalVesting, alreadyClaimed, vestingStart, claimedToday, availableToday) | |
104 | - | case _ => | |
105 | - | $Tuple7(totalVesting, 0, -1, -1, -1, -1, -1) | |
106 | - | } | |
107 | - | } | |
108 | - | ||
109 | - | ||
110 | - | func adviseUser (address) = { | |
111 | - | let $t035153616 = userVestingBalance(address) | |
112 | - | let totalVesting = $t035153616._1 | |
113 | - | let alreadyClaimed = $t035153616._2 | |
114 | - | let start = $t035153616._3 | |
115 | - | let claimedToday = $t035153616._4 | |
116 | - | let availableToday = $t035153616._5 | |
117 | - | ((((((((((((((("markets_address: " + address) + ", markets_totalVesting: ") + toString(totalVesting)) + ", markets_alreadyClaimed: ") + toString(alreadyClaimed)) + ", markets_startHeight: ") + toString(start)) + ", markets_dailyLimit: ") + toString(max([minClaimUsdn, (totalVesting / 500)]))) + ", markets_claimedToday: ") + toString(claimedToday)) + ", markets_availableToday: ") + toString(availableToday)) + ", markets_globallyAvailableToday: ") + toString(totalAvailableToday)) | |
118 | - | } | |
119 | - | ||
120 | - | ||
121 | - | func withdrawVestedInternal (address,to) = { | |
122 | - | let checks = opAllowed("liquidao_all_withdrawVested") | |
123 | - | if ((checks == checks)) | |
124 | - | then { | |
125 | - | let $t042594360 = userVestingBalance(address) | |
126 | - | let totalVesting = $t042594360._1 | |
127 | - | let alreadyClaimed = $t042594360._2 | |
128 | - | let start = $t042594360._3 | |
129 | - | let claimedToday = $t042594360._4 | |
130 | - | let availableToday = $t042594360._5 | |
131 | - | if ((0 > start)) | |
132 | - | then throw("no vesting enabled") | |
133 | - | else if ((0 >= availableToday)) | |
134 | - | then throw("nothing available") | |
135 | - | else $Tuple2([ScriptTransfer(addressFromStringValue(to), availableToday, fromBase58String(usdn)), IntegerEntry(vestingClaimedStore(address), (alreadyClaimed + availableToday)), changeBy(withdrawnTodayStore(address), availableToday), changeBy(withdrawnTodayTotalStore, availableToday)], availableToday) | |
136 | - | } | |
137 | - | else throw("Strict value is not equal to itself.") | |
138 | - | } | |
85 | + | else throw("limiter2: only main can do") | |
139 | 86 | ||
140 | 87 | ||
141 | 88 | @Callable(i) | |
142 | - | func init (conf,nId) = if ((i.caller != this)) | |
143 | - | then throw("only self can init") | |
144 | - | else [writeConstString(configStore, conf), writeConstString("usdn", nId)] | |
89 | + | func initialize (ca) = [writeConstString(configStore, ca)] | |
145 | 90 | ||
146 | 91 | ||
147 | 92 | ||
148 | 93 | @Callable(i) | |
149 | - | func withdrawVested () = { | |
150 | - | let address = toString(i.caller) | |
151 | - | withdrawVestedInternal(address, address) | |
152 | - | } | |
153 | - | ||
154 | - | ||
155 | - | ||
156 | - | @Callable(i) | |
157 | - | func withdrawVestedForTo (acc,to) = { | |
158 | - | let checks = mainOnly(i) | |
159 | - | if ((checks == checks)) | |
160 | - | then withdrawVestedInternal(acc, to) | |
161 | - | else throw("Strict value is not equal to itself.") | |
162 | - | } | |
163 | - | ||
164 | - | ||
165 | - | ||
166 | - | @Callable(i) | |
167 | - | func accountFor (address) = { | |
168 | - | let attached = i.payments[0] | |
169 | - | let checks = if (if (mainOnly(i)) | |
170 | - | then opAllowed("liquidao_all_move") | |
171 | - | else false) | |
172 | - | then throwIf((toBase58String(value(attached.assetId)) != usdn), "usdn must be attached") | |
173 | - | else false | |
174 | - | if ((checks == checks)) | |
94 | + | func validateLimit (action,reserve,user,amount) = { | |
95 | + | let m = mainOnly(i) | |
96 | + | if ((m == m)) | |
175 | 97 | then { | |
176 | - | let $t055445645 = userVestingBalance(address) | |
177 | - | let totalVesting = $t055445645._1 | |
178 | - | let alreadyClaimed = $t055445645._2 | |
179 | - | let start = $t055445645._3 | |
180 | - | let claimedToday = $t055445645._4 | |
181 | - | let availableToday = $t055445645._5 | |
182 | - | [writeInt(vestingStartStore(address), HEIGHT), writeInt(addressTotalStore(address), (totalVesting + attached.amount)), changeBy(totalUSDNStore, attached.amount)] | |
98 | + | let rsr = addressFromStringValue(reserve) | |
99 | + | let assetId = valueOrErrorMessage(getString(rsr, aIdS), "no assetId") | |
100 | + | let $t024842564 = asInt2(invoke(rsr, "storedDepositBorrow", nil, nil)) | |
101 | + | let totalDeposit = $t024842564._1 | |
102 | + | let totalDebt = $t024842564._2 | |
103 | + | let util = if ((totalDeposit > 0)) | |
104 | + | then min([factorsBase, fraction(totalDebt, factorsBase, totalDeposit)]) | |
105 | + | else 0 | |
106 | + | if (if ((action == "borrow")) | |
107 | + | then true | |
108 | + | else (action == "withdraw")) | |
109 | + | then { | |
110 | + | let at = ensureActionThreshold(action, assetId, util) | |
111 | + | if ((at == at)) | |
112 | + | then match limit(assetId, util) { | |
113 | + | case lmt: Int => | |
114 | + | if ((0 > lmt)) | |
115 | + | then $Tuple2(nil, -1) | |
116 | + | else if ((lmt == 0)) | |
117 | + | then throw((action + " is denied")) | |
118 | + | else { | |
119 | + | let store = userWithdrawnWithinEpochStore(user, assetId) | |
120 | + | let $t030473279 = match getString(store) { | |
121 | + | case s: String => | |
122 | + | let data = split(s, "|") | |
123 | + | $Tuple2(parseIntValue(data[0]), parseIntValue(data[1])) | |
124 | + | case _ => | |
125 | + | $Tuple2(0, 0) | |
126 | + | } | |
127 | + | let epoch = $t030473279._1 | |
128 | + | let withdrawn = $t030473279._2 | |
129 | + | let userWithdrawnWithinCurrentEpoch = if ((epoch == currentEpochStart)) | |
130 | + | then withdrawn | |
131 | + | else 0 | |
132 | + | let newTotal = (userWithdrawnWithinCurrentEpoch + amount) | |
133 | + | if ((newTotal > lmt)) | |
134 | + | then { | |
135 | + | let currentEpochEnd = ((1 + (HEIGHT / timeframe)) * timeframe) | |
136 | + | throw(((((((((((((("breaching " + action) + " limit ") + toString(lmt)) + " ") + assetId) + " over ") + toString(timeframe)) + " blocks. Available: ") + toString((lmt - userWithdrawnWithinCurrentEpoch))) + " current epoch: ") + toString(currentEpochStart)) + "-") + toString(currentEpochEnd))) | |
137 | + | } | |
138 | + | else { | |
139 | + | let data = ((toString(currentEpochStart) + "|") + toString(newTotal)) | |
140 | + | $Tuple2([StringEntry(store, data)], (lmt - newTotal)) | |
141 | + | } | |
142 | + | } | |
143 | + | case _ => | |
144 | + | $Tuple2(nil, -1) | |
145 | + | } | |
146 | + | else throw("Strict value is not equal to itself.") | |
147 | + | } | |
148 | + | else if ((action == "import")) | |
149 | + | then { | |
150 | + | let at = actionThreshold(action, assetId) | |
151 | + | let importAllowedReserves = valueOrElse(getString(configAddress, "import_always_allowed_reserves"), "") | |
152 | + | let importException = contains(importAllowedReserves, reserve) | |
153 | + | if (if (!(importException)) | |
154 | + | then (util >= at) | |
155 | + | else false) | |
156 | + | then throw(((((((action + " of ") + assetId) + " paused due to high utilization: ") + toString(util)) + " >= ") + toString(at))) | |
157 | + | else { | |
158 | + | let globalLimit = valueOrElse(getInteger(configAddress, ("daily_import_limit_" + reserve)), 1000000000000000) | |
159 | + | let store = globalImportedPerEpochPerReserveStore(reserve) | |
160 | + | let globalImported = valueOrElse(getInteger(this, store), 0) | |
161 | + | let newTotal = (globalImported + amount) | |
162 | + | if ((newTotal > globalLimit)) | |
163 | + | then throw("import limit exceeded") | |
164 | + | else $Tuple2([IntegerEntry(store, newTotal)], (globalLimit - newTotal)) | |
165 | + | } | |
166 | + | } | |
167 | + | else if ((action == "redeem")) | |
168 | + | then { | |
169 | + | let at = ensureActionThreshold(action, assetId, util) | |
170 | + | if ((at == at)) | |
171 | + | then $Tuple2(nil, -1) | |
172 | + | else throw("Strict value is not equal to itself.") | |
173 | + | } | |
174 | + | else throw("limiter2: invalid action") | |
183 | 175 | } | |
184 | 176 | else throw("Strict value is not equal to itself.") | |
185 | 177 | } | |
186 | - | ||
187 | - | ||
188 | - | ||
189 | - | @Callable(i) | |
190 | - | func adviseU (acc) = $Tuple2(nil, adviseUser(acc)) | |
191 | 178 | ||
192 | 179 |
github/deemru/w8io/3ef1775 41.99 ms ◑