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:
OldNewDifferences
1-{-# STDLIB_VERSION 6 #-}
1+{-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func writeConstString (key,value) = if (!(isDefined(getString(this, key))))
66 else throw(("already initialized: " + key))
77
88
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-
229 let configStore = "config"
2310
2411 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+
2524
2625 let maybeOracleAddress = match getString(configAddress, "oracle_address") {
2726 case s: String =>
3231
3332 let HEIGHT = height
3433
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+ }
4381
4482
4583 func mainOnly (i) = if (contains(getStringValue(configAddress, "main"), toString(i.caller)))
4684 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")
13986
14087
14188 @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)]
14590
14691
14792
14893 @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))
17597 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")
183175 }
184176 else throw("Strict value is not equal to itself.")
185177 }
186-
187-
188-
189-@Callable(i)
190-func adviseU (acc) = $Tuple2(nil, adviseUser(acc))
191178
192179
Full:
OldNewDifferences
1-{-# STDLIB_VERSION 6 #-}
1+{-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func writeConstString (key,value) = if (!(isDefined(getString(this, key))))
55 then StringEntry(key, value)
66 else throw(("already initialized: " + key))
77
88
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-
229 let configStore = "config"
2310
2411 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+
2524
2625 let maybeOracleAddress = match getString(configAddress, "oracle_address") {
2726 case s: String =>
2827 addressFromString(s)
2928 case _ =>
3029 unit
3130 }
3231
3332 let HEIGHT = height
3433
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+ }
4381
4482
4583 func mainOnly (i) = if (contains(getStringValue(configAddress, "main"), toString(i.caller)))
4684 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")
13986
14087
14188 @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)]
14590
14691
14792
14893 @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))
17597 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")
183175 }
184176 else throw("Strict value is not equal to itself.")
185177 }
186-
187-
188-
189-@Callable(i)
190-func adviseU (acc) = $Tuple2(nil, adviseUser(acc))
191178
192179

github/deemru/w8io/3ef1775 
41.99 ms