2020.11.25 22:17 [2345063] smart account 3P9ZegsKUtsEpdRPNVrMH7nHEEqY5MrmjDp > SELF 0.00000000 Waves

{ "type": 13, "id": "5i1hDiMHv7QhuYsVhcggdNTP3dd8P66tbbnySD1yyLsj", "fee": 1400000, "feeAssetId": null, "timestamp": 1606331779730, "version": 1, "sender": "3P9ZegsKUtsEpdRPNVrMH7nHEEqY5MrmjDp", "senderPublicKey": "7ziFsWp9eo6kUB6ovqQzJfjgQarifNfpCGNW9DZi8YhN", "proofs": [ "5P2wt8kGF1ZwjaUjCpbxFQsxDry2x1xhvKCasFT7kDcnmnyEc5XKMJ3rYjtLhjyEA5wFJLhZdLZfZfWbezUYCgnC", "4wNQtbgvkvY3jiHLMyZruELZTSGLJ7eG5cvGAX4Ccci31vPZWF8R4Maff9LJQ57YHTrvjQiMmqNvbNrCvMcHkw4d" ], "script": "base64:AAIEAAAAAAAAADgIAhINCgsICAgICAgICAgBARIDCgEBEgASAwoBARIDCgEIEgQKAggBEgASAwoBARIAEgMKAQESAAAAAG0BAAAAAlNFAAAAAgAAAAFrAAAAAXYJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAAWsFAAAAAXYBAAAAAklFAAAAAgAAAAFrAAAAAXYJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAFrBQAAAAF2AQAAAAJTVAAAAAMAAAABYQAAAANhbXQAAAABdAkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAABYQUAAAADYW10BQAAAAF0AQAAAAVkZWJ1ZwAAAAIAAAABawAAAAF2CQEAAAACU0UAAAACCQABLAAAAAICAAAAB19fZGJnX18FAAAAAWsFAAAAAXYAAAAABHRlbjYAAAAAAAAPQkAAAAAABHRlbjgAAAAAAAX14QAAAAAAA01BWAB//////////wAAAAARY29uZmlnUHJvdmlkZXJLZXkCAAAADmNvbmZpZ1Byb3ZpZGVyAAAAAA5jb25maWdQcm92aWRlcgQAAAAHJG1hdGNoMAkABB0AAAACBQAAAAR0aGlzBQAAABFjb25maWdQcm92aWRlcktleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAGU3RyaW5nBAAAAAFzBQAAAAckbWF0Y2gwCQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAAFzBQAAAAR0aGlzAQAAAAZsb2NhbEkAAAACAAAAAWsAAAABZQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAAAWsFAAAAAWUBAAAABmxvY2FsUwAAAAIAAAABawAAAAFlCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwUAAAABawUAAAABZQEAAAAFY29uZkkAAAACAAAAAWsAAAABZQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAADmNvbmZpZ1Byb3ZpZGVyBQAAAAFrBQAAAAFlAQAAAAVjb25mUwAAAAIAAAABawAAAAFlCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAOY29uZmlnUHJvdmlkZXIFAAAAAWsFAAAAAWUAAAAABUJVTExLAgAAAAZCVUxMSWQAAAAABUJFQVJLAgAAAAZCRUFSSWQAAAAABVVTRE5LAgAAAAttYWluVG9rZW5JZAAAAAAIQlVMTENPTEsCAAAADmJ1bGxDb2xsYXRlcmFsAAAAAAhCRUFSQ09MSwIAAAAOYmVhckNvbGxhdGVyYWwAAAAACUJVTExDSVJDSwIAAAAPYnVsbENpcmN1bGF0aW9uAAAAAAlCRUFSQ0lSQ0sCAAAAD2JlYXJDaXJjdWxhdGlvbgAAAAAISVNTUEVSQ0sCAAAAD2lzc3VlUGVyY2VudGlsZQAAAAAIUkVEUEVSQ0sCAAAAEHJlZGVlbVBlcmNlbnRpbGUAAAAAB01JTklTU0sCAAAACG1pbklzc3VlAAAAAAdNSU5SRURLAgAAAAltaW5SZWRlZW0AAAAACE1JTlBPT0xLAgAAAAdtaW5Qb29sAAAAAAdGRUVBQ0NLAgAAAA9mZWVzQWNjdW11bGF0ZWQAAAAABldMSVNUSwIAAAAOaXNzdWVXaGl0ZUxpc3QAAAAACFJFQlBFUkNLAgAAABNyZWJhbGFuY2VQZXJjZW50aWxlAAAAAAdSRUJJRFhLAgAAABVsYXN0U2V0dGxlbWVudFByaWNlSWQAAAAABUhFQURLAgAAAAtoZWFkUG9pbnRlcgAAAAAFVEFJTEsCAAAAC3RhaWxQb2ludGVyAAAAAAZRU0laRUsCAAAACXF1ZXVlU2l6ZQAAAAAJUE9PTFVTRE5LAgAAABJwb29sTWFpblRva2VuVmFsdWUAAAAAB1BPT0xVUEsCAAAABnBvb2xVcAAAAAAIUE9PTERXTksCAAAAB3Bvb2xEd24AAAAACVBPT0xDSVJDSwIAAAAUcG9vbFRva2VuQ2lyY3VsYXRpb24AAAAABVBPT0xLAgAAAAlwb29sVG9rZW4AAAAACEFTU05BTUVLAgAAAA1kZWZvQXNzZXROYW1lAAAAAARMRVZLAgAAAAhsZXZlcmFnZQAAAAAJV0FWRVNGRUVLAgAAABF3YXZlc1BhY2VtYWtlckZlZQAAAAAIVVNETkZFRUsCAAAAEHVzZG5QYWNlbWFrZXJGZWUAAAAAC29yYWNsZVBLS2V5AgAAAAZvcmFjbGUBAAAAEWxhc3RQcmljZUluZGV4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ZQkAAGsAAAADBQAAAAdidWxsQ29sBQAAAAZwb29sVXAFAAAACGJ1bGxDaXJjAAAAABBwb29sQmVhckV4cG9zdXJlCQAAawAAAAMFAAAAB2JlYXJDb2wFAAAAB3Bvb2xEd24FAAAACGJlYXJDaXJjAAAAAAlwb29sVmFsdWUJAABkAAAAAgkAAGQAAAACBQAAAAhwb29sTWFpbgUAAAAQcG9vbEJ1bGxFeHBvc3VyZQUAAAAQcG9vbEJlYXJFeHBvc3VyZQAAAAAGb3JhY2xlCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAQAAABRhZGRyZXNzRnJvbVB1YmxpY0tleQAAAAEJAAJZAAAAAQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAABHRoaXMFAAAAC29yYWNsZVBLS2V5AgAAAA5ubyBvcmFjbGVQS0tleQIAAAASYmFkIG9yYWNsZSBhZGRyZXNzAAAAABRyZWJhbGFuY2VkUHJpY2VJbmRleAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAAB1JFQklEWEsCAAAAF25vIGxhc3QgcmViYWxhbmNlIHByaWNlAAAAABBvcmFjbGVQcmljZUluZGV4CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAGb3JhY2xlCQEAAAARbGFzdFByaWNlSW5kZXhLZXkAAAABBQAAAAlhc3NldE5hbWUJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAE2JhZCBvcmFjbGUgZGF0YSBhdCAJAAQlAAAAAQUAAAAGb3JhY2xlAgAAABA6IG5vIGludGVnZXIgYXQgCQEAAAARbGFzdFByaWNlSW5kZXhLZXkAAAABBQAAAAlhc3NldE5hbWUAAAAACGxldmVyYWdlCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMFAAAABExFVksAAAAAAAAAAAMBAAAADWhlaWdodEJ5SW5kZXgAAAACAAAACWFzc2V0TmFtZQAAAApwcmljZUluZGV4CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAGb3JhY2xlCQABLAAAAAIJAQAAABBwcmljZUluZGV4UHJlZml4AAAAAQUAAAAJYXNzZXROYW1lCQABpAAAAAEFAAAACnByaWNlSW5kZXgJAAEsAAAAAgIAAAARbm8gZGF0YSBhdCBpbmRleCAJAAGkAAAAAQUAAAAKcHJpY2VJbmRleAEAAAANcHJpY2VCeUhlaWdodAAAAAIAAAAJYXNzZXROYW1lAAAAC3ByaWNlSGVpZ2h0CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQaAAAAAgUAAAAGb3JhY2xlCQABLAAAAAIJAQAAABFwcmljZUhlaWdodFByZWZpeAAAAAEFAAAACWFzc2V0TmFtZQkAAaQAAAABBQAAAAtwcmljZUhlaWdodAkAASwAAAACAgAAABNubyBkYXRhIGZvciBoZWlnaHQgCQABpAAAAAEFAAAAC3ByaWNlSGVpZ2h0AQAAAAxwcmljZUJ5SW5kZXgAAAACAAAACWFzc2V0TmFtZQAAAApwcmljZUluZGV4CQEAAAANcHJpY2VCeUhlaWdodAAAAAIFAAAACWFzc2V0TmFtZQkBAAAADWhlaWdodEJ5SW5kZXgAAAACBQAAAAlhc3NldE5hbWUFAAAACnByaWNlSW5kZXgAAAAACXF1ZXVlU2l6ZQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAAAZRU0laRUsAAAAAAAAAAAAAAAAAC2hlYWRQb2ludGVyCQEAAAALdmFsdWVPckVsc2UAAAACCQAEHQAAAAIFAAAABHRoaXMFAAAABUhFQURLAgAAAAAAAAAAC3RhaWxQb2ludGVyCQEAAAALdmFsdWVPckVsc2UAAAACCQAEHQAAAAIFAAAABHRoaXMFAAAABVRBSUxLAgAAAAAAAAAAD2ZlZXNBY2N1bXVsYXRlZAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABBoAAAACBQAAAAR0aGlzBQAAAAdGRUVBQ0NLAAAAAAAAAAAAAAAAAAVJU1NVRQIAAAAFSVNTVUUAAAAABlJFREVFTQIAAAAGUkVERUVNAAAAAARQT09MAgAAAARQT09MAAAAAAZVTlBPT0wCAAAABlVOUE9PTAAAAAAKZmVlQWRkcktleQIAAAAKZmVlQWRkcmVzcwAAAAAOc3Rha2luZ0FkZHJLZXkCAAAADnN0YWtpbmdBZGRyZXNzAAAAAA9kYWVtb25QdWJLZXlLZXkCAAAAD2RhZW1vblB1YmxpY0tleQAAAAAKZmVlQWRkcmVzcwkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEJgAAAAEJAQAAAAVjb25mUwAAAAIFAAAACmZlZUFkZHJLZXkCAAAADW5vIGZlZUFkZHJlc3MCAAAADmJhZCBmZWVBZGRyZXNzAAAAAA5zdGFraW5nQWRkcmVzcwkBAAAABWNvbmZTAAAAAgUAAAAOc3Rha2luZ0FkZHJLZXkCAAAAEW5vIHN0YWtpbmdBZGRyZXNzAAAAAA9kYWVtb25QdWJsaWNLZXkJAAJZAAAAAQkBAAAABWNvbmZTAAAAAgUAAAAPZGFlbW9uUHViS2V5S2V5AgAAABJubyBkYWVtb25QdWJsaWNLZXkAAAAACnJwZEFkZHJlc3MJAAQmAAAAAQIAAAAjM1BOaWtNNnlwNE5xY1NVOGd1eFF0bVI1b25yMkQ0ZTh5VEoAAAAABmFkbWlucwkABEwAAAACAgAAACwySEhxVjhXOURKYXlWNVI2dEJEMlNiOHNycGhwb2JvRGk3cjF0MWFQaXVtQwkABEwAAAACAgAAACw1WlhlODJSUkFTVTdxc2hYTTJKOUpOWWhxSjlHV1lqalZxMmd3VVY1TmF6OQkABEwAAAACAgAAACw1V1JYRlNqd2NUYk5mS2NKczhacVhtU1NXWXNTVkpVdE12TXFaajVoSDROYwUAAAADbmlsAQAAAAxidWlsZE5ld0l0ZW0AAAAHAAAABmFjdGlvbgAAAANhbXQAAAAFdG9rZW4AAAAKcHJpY2VJbmRleAAAAAdpbnZva2VyAAAACW1pblBheW91dAAAAAltYXhQYXlvdXQJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgUAAAAGYWN0aW9uAgAAAAF8CQABpAAAAAEFAAAAA2FtdAIAAAABfAUAAAAFdG9rZW4CAAAAAXwJAAGkAAAAAQUAAAAKcHJpY2VJbmRleAIAAAABfAUAAAAHaW52b2tlcgIAAAABfAkA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AAIJAAQaAAAAAgUAAAAEdGhpcwUAAAAHUkVCSURYSwIAAAARaW5jb25zaXN0ZW50IGRhdGEEAAAAE3Vuc2V0dGxlZFByaWNlSW5kZXgJAABkAAAAAgUAAAARc2V0dGxlZFByaWNlSW5kZXgAAAAAAAAAAAEEAAAADHNldHRsZWRQcmljZQkBAAAADHByaWNlQnlJbmRleAAAAAIFAAAACWFzc2V0TmFtZQUAAAARc2V0dGxlZFByaWNlSW5kZXgEAAAACW5leHRQcmljZQkBAAAADHByaWNlQnlJbmRleAAAAAIFAAAACWFzc2V0TmFtZQUAAAATdW5zZXR0bGVkUHJpY2VJbmRleAQAAAAGbWluVm9sAwkAAGYAAAACBQAAAAdiZWFyQ29sBQAAAAdidWxsQ29sBQAAAAdidWxsQ29sBQAAAAdiZWFyQ29sBAAAAAZyZWRpc3QJAQAAAAJMVgAAAAQFAAAABm1pblZvbAUAAAAMc2V0dGxlZFByaWNlBQAAAAluZXh0UHJpY2UFAAAACGxldmVyYWdlBAAAABNwcmljZVVwR29vZEZvckJ1bGxzCQAAAAAAAAIFAAAACWFzc2V0TmFtZQIAAAAABAAAAAtwcmljZUdvZXNVcAkAAGYAAAACBQAAAAluZXh0UHJpY2UFAAAADHNldHRsZWRQcmljZQQAAAAJYnVsbHNFYXJuCQAAAAAAAAIFAAAAE3ByaWNlVXBHb29kRm9yQnVsbHMFAAAAC3ByaWNlR29lc1VwBAAAAApuZXdCdWxsQ29sAwUAAAAJYnVsbHNFYXJuCQAAZAAAAAIFAAAAB2J1bGxDb2wFAAAABnJlZGlzdAkAAGUAAAACBQAAAAdidWxsQ29sBQAAAAZyZWRpc3QEAAAACm5ld0JlYXJDb2wDBQAAAAlidWxsc0Vhcm4JAABlAAAAAgUAAAAHYmVhckNvbAUAAAAGcmVkaXN0CQAAZAAAAAIFAAAAB2JlYXJDb2wFAAAABnJlZGlzdAQAAAANJHQwMTk2MDgxOTc5NAkBAAAAC3Bvb2xTdXBwb3J0AAAABwUAAAAKbmV3QnVsbENvbAUAAAAKbmV3QmVhckNvbAUAAAAIYnVsbENpcmMFAAAACGJlYXJDaXJjBQAAAAhwb29sTWFpbgUAAAAGcG9vbFVwBQAAAAdwb29sRHduBAAAAAp1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", "chainId": 87, "height": 2345063, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: H5XQMYij4pYQCbR2oGmk5yYmxhkNhSjH5Yz2XMT6xTHD Next: FME1ftFJS9X58ARtT2mSb19qHiAZf6Y7HYhDKVbNxNbc Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 4 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+func SE (k,v) = StringEntry(k, v)
5+
6+
7+func IE (k,v) = IntegerEntry(k, v)
8+
9+
10+func ST (a,amt,t) = ScriptTransfer(a, amt, t)
11+
12+
13+func debug (k,v) = SE(("__dbg__" + k), v)
14+
15+
416 let ten6 = 1000000
517
618 let ten8 = 100000000
19+
20+let MAX = 9223372036854775807
721
822 let configProviderKey = "configProvider"
923
1428 this
1529 }
1630
17-let BULLKey = "BULLId"
31+func localI (k,e) = valueOrErrorMessage(getInteger(this, k), e)
1832
19-let BEARKey = "BEARId"
2033
21-let mainTokenKey = "mainTokenId"
34+func localS (k,e) = valueOrErrorMessage(getString(this, k), e)
2235
23-let bullCollateralKey = "bullCollateral"
2436
25-let bearCollateralKey = "bearCollateral"
37+func confI (k,e) = valueOrErrorMessage(getInteger(configProvider, k), e)
2638
27-let bullCirculationKey = "bullCirculation"
2839
29-let bearCirculationKey = "bearCirculation"
40+func confS (k,e) = valueOrErrorMessage(getString(configProvider, k), e)
3041
31-let issuePercentileKey = "issuePercentile"
3242
33-let redeemPercentileKey = "redeemPercentile"
43+let BULLK = "BULLId"
3444
35-let minIssueKey = "minIssue"
45+let BEARK = "BEARId"
3646
37-let minRedeemKey = "minRedeem"
47+let USDNK = "mainTokenId"
3848
39-let minPoolKey = "minPool"
49+let BULLCOLK = "bullCollateral"
4050
41-let feesAccumulatedKey = "feesAccumulated"
51+let BEARCOLK = "bearCollateral"
4252
43-let whitelistKey = "issueWhiteList"
53+let BULLCIRCK = "bullCirculation"
54+
55+let BEARCIRCK = "bearCirculation"
56+
57+let ISSPERCK = "issuePercentile"
58+
59+let REDPERCK = "redeemPercentile"
60+
61+let MINISSK = "minIssue"
62+
63+let MINREDK = "minRedeem"
64+
65+let MINPOOLK = "minPool"
66+
67+let FEEACCK = "feesAccumulated"
68+
69+let WLISTK = "issueWhiteList"
70+
71+let REBPERCK = "rebalancePercentile"
72+
73+let REBIDXK = "lastSettlementPriceId"
74+
75+let HEADK = "headPointer"
76+
77+let TAILK = "tailPointer"
78+
79+let QSIZEK = "queueSize"
80+
81+let POOLUSDNK = "poolMainTokenValue"
82+
83+let POOLUPK = "poolUp"
84+
85+let POOLDWNK = "poolDwn"
86+
87+let POOLCIRCK = "poolTokenCirculation"
88+
89+let POOLK = "poolToken"
90+
91+let ASSNAMEK = "defoAssetName"
92+
93+let LEVK = "leverage"
94+
95+let WAVESFEEK = "wavesPacemakerFee"
96+
97+let USDNFEEK = "usdnPacemakerFee"
4498
4599 let oraclePKKey = "oracle"
46100
47-let lastPriceIndexKey = "price_index"
101+func lastPriceIndexKey (assetId) = if ((assetId == ""))
102+ then "price_index"
103+ else ("%s%s__idxCurrent__" + assetId)
48104
49-let priceIndexPrefix = "price_index_"
50105
51-let priceHeightPrefix = "price_"
106+func priceIndexPrefix (assetId) = if ((assetId == ""))
107+ then "price_index_"
108+ else (("%s%s%d__idx2Height__" + assetId) + "__")
52109
53-let oracleCurrentPriceIndexKey = "price_index"
54110
55-let lastRebalancePriceIndexKey = "lastSettlementPriceId"
111+func priceHeightPrefix (assetId) = if ((assetId == ""))
112+ then "price_"
113+ else (("%s%s%d__priceByHeight__" + assetId) + "__")
56114
57-let headPointerKey = "headPointer"
58115
59-let tailPointerKey = "tailPointer"
116+let minUsdnFee = valueOrElse(getInteger(configProvider, USDNFEEK), 0)
60117
61-let queueSizeKey = "queueSize"
118+let minWavesFee = valueOrElse(getInteger(configProvider, WAVESFEEK), 0)
62119
63-let poolMainTokenValueKey = "poolMainTokenValue"
120+let assetName = valueOrElse(getString(this, ASSNAMEK), "")
64121
65-let poolUpKey = "poolUp"
122+let bullCol = localI(BULLCOLK, "no 0")
66123
67-let poolDwnKey = "poolDwn"
124+let bearCol = localI(BEARCOLK, "no 1")
68125
69-let poolTokenCirculationKey = "poolTokenCirculation"
126+let bullCirc = localI(BULLCIRCK, "no 2")
70127
71-let poolTokenKey = "poolToken"
128+let bearCirc = localI(BEARCIRCK, "no 3")
72129
73-let bullCol = valueOrErrorMessage(getInteger(this, bullCollateralKey), "no bullCollateralKey")
130+let BULL = localS(BULLK, "no 14")
74131
75-let bearCol = valueOrErrorMessage(getInteger(this, bearCollateralKey), "no bearCollateralKey")
132+let BEAR = localS(BEARK, "no 15")
76133
77-let bullCirc = valueOrErrorMessage(getInteger(this, bullCirculationKey), "no bullCirculationKey")
134+let mainToken = localS(USDNK, "no 16")
78135
79-let bearCirc = valueOrErrorMessage(getInteger(this, bearCirculationKey), "no bearCirculationKey")
136+let issuePercentile = confI(ISSPERCK, "no 4")
80137
81-let BULL = valueOrErrorMessage(getString(this, BULLKey), "no BULLKey")
138+let redeemPercentile = confI(REDPERCK, "no 5")
82139
83-let BEAR = valueOrErrorMessage(getString(this, BEARKey), "no BEARKey")
140+let minIssue = confI(MINISSK, "no 6")
84141
85-let mainToken = valueOrErrorMessage(getString(this, mainTokenKey), "no mainTokenKey")
142+let minRedeem = confI(MINREDK, "no 7")
86143
87-let issuePercentile = valueOrErrorMessage(getInteger(configProvider, issuePercentileKey), "no issuePercentileKey")
144+let minPool = confI(MINPOOLK, "no 8")
88145
89-let redeemPercentile = valueOrErrorMessage(getInteger(configProvider, redeemPercentileKey), "no redeemPercentileKey")
146+let rebalancePercentile = valueOrElse(getInteger(configProvider, ((toString(this) + "_") + REBPERCK)), 0)
90147
91-let minIssue = valueOrErrorMessage(getInteger(configProvider, minIssueKey), "no minIssueKey")
92-
93-let minRedeem = valueOrErrorMessage(getInteger(configProvider, minRedeemKey), "no minRedeemKey")
94-
95-let minPool = valueOrErrorMessage(getInteger(configProvider, minPoolKey), "no minPoolKey")
96-
97-let whitelist = valueOrErrorMessage(getString(configProvider, whitelistKey), "no whitelistKey")
148+let whitelist = confS(WLISTK, "no 9")
98149
99150 func allowed (a) = if ((whitelist == ""))
100151 then true
101152 else isDefined(indexOf(whitelist, toString(a)))
102153
103154
104-let poolMain = valueOrErrorMessage(getInteger(this, poolMainTokenValueKey), "no poolMainTokenValueKey")
155+let poolMain = localI(POOLUSDNK, "no")
105156
106-let poolUp = valueOrErrorMessage(getInteger(this, poolUpKey), "no poolUpKey")
157+let poolUp = localI(POOLUPK, "no 10")
107158
108-let poolDwn = valueOrErrorMessage(getInteger(this, poolDwnKey), "no poolDwnKey")
159+let poolDwn = localI(POOLDWNK, "no 11")
109160
110-let poolToken = valueOrErrorMessage(getString(this, poolTokenKey), "no poolTokenKey")
161+let poolToken = localS(POOLK, "no 12")
111162
112-let poolTokenCirculation = valueOrErrorMessage(getInteger(this, poolTokenCirculationKey), "no poolTokenCirculationKey")
163+let poolTokenCirculation = localI(POOLCIRCK, "no 13")
113164
114-let poolValue = ((poolMain + fraction(bullCol, poolUp, bullCirc)) + fraction(bearCol, poolDwn, bearCirc))
165+let poolBullExposure = fraction(bullCol, poolUp, bullCirc)
166+
167+let poolBearExposure = fraction(bearCol, poolDwn, bearCirc)
168+
169+let poolValue = ((poolMain + poolBullExposure) + poolBearExposure)
115170
116171 let oracle = valueOrErrorMessage(addressFromPublicKey(fromBase58String(valueOrErrorMessage(getString(this, oraclePKKey), "no oraclePKKey"))), "bad oracle address")
117172
118-let rebalancedPriceIndex = valueOrErrorMessage(getInteger(this, lastRebalancePriceIndexKey), "no last rebalance price")
173+let rebalancedPriceIndex = valueOrErrorMessage(getInteger(this, REBIDXK), "no last rebalance price")
119174
120-let oraclePriceIndex = valueOrErrorMessage(getInteger(oracle, lastPriceIndexKey), ((("bad oracle data at " + toString(oracle)) + ": no integer at ") + lastPriceIndexKey))
175+let oraclePriceIndex = valueOrErrorMessage(getInteger(oracle, lastPriceIndexKey(assetName)), ((("bad oracle data at " + toString(oracle)) + ": no integer at ") + lastPriceIndexKey(assetName)))
121176
122-let queueSize = valueOrElse(getInteger(this, queueSizeKey), 0)
177+let leverage = valueOrElse(getInteger(this, LEVK), 3)
123178
124-let headPointer = valueOrElse(getString(this, headPointerKey), "")
179+func heightByIndex (assetName,priceIndex) = valueOrErrorMessage(getInteger(oracle, (priceIndexPrefix(assetName) + toString(priceIndex))), ("no data at index " + toString(priceIndex)))
125180
126-let tailPointer = valueOrElse(getString(this, tailPointerKey), "")
127181
128-let feesAccumulated = valueOrElse(getInteger(this, feesAccumulatedKey), 0)
182+func priceByHeight (assetName,priceHeight) = valueOrErrorMessage(getInteger(oracle, (priceHeightPrefix(assetName) + toString(priceHeight))), ("no data for height " + toString(priceHeight)))
183+
184+
185+func priceByIndex (assetName,priceIndex) = priceByHeight(assetName, heightByIndex(assetName, priceIndex))
186+
187+
188+let queueSize = valueOrElse(getInteger(this, QSIZEK), 0)
189+
190+let headPointer = valueOrElse(getString(this, HEADK), "")
191+
192+let tailPointer = valueOrElse(getString(this, TAILK), "")
193+
194+let feesAccumulated = valueOrElse(getInteger(this, FEEACCK), 0)
129195
130196 let ISSUE = "ISSUE"
131197
141207
142208 let daemonPubKeyKey = "daemonPublicKey"
143209
144-let feeAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configProvider, feeAddrKey), "no feeAddress")), "bad feeAddress")
210+let feeAddress = valueOrErrorMessage(addressFromString(confS(feeAddrKey, "no feeAddress")), "bad feeAddress")
145211
146-let stakingAddress = valueOrErrorMessage(getString(configProvider, stakingAddrKey), "no stakingAddress")
212+let stakingAddress = confS(stakingAddrKey, "no stakingAddress")
147213
148-let daemonPublicKey = fromBase58String(valueOrErrorMessage(getString(configProvider, daemonPubKeyKey), "no daemonPublicKey"))
214+let daemonPublicKey = fromBase58String(confS(daemonPubKeyKey, "no daemonPublicKey"))
149215
150216 let rpdAddress = addressFromString("3PNikM6yp4NqcSU8guxQtmR5onr2D4e8yTJ")
151217
152-let pubKeyAdminsList = ["2HHqV8W9DJayV5R6tBD2Sb8srphpoboDi7r1t1aPiumC", "5ZXe82RRASU7qshXM2J9JNYhqJ9GWYjjVq2gwUV5Naz9", "5WRXFSjwcTbNfKcJs8ZqXmSSWYsSVJUtMvMqZj5hH4Nc"]
218+let admins = ["2HHqV8W9DJayV5R6tBD2Sb8srphpoboDi7r1t1aPiumC", "5ZXe82RRASU7qshXM2J9JNYhqJ9GWYjjVq2gwUV5Naz9", "5WRXFSjwcTbNfKcJs8ZqXmSSWYsSVJUtMvMqZj5hH4Nc"]
153219
154-func safeFraction (a,b,c) = if (if ((a == 0))
155- then true
156- else (b == 0))
157- then 0
158- else fraction(a, b, c)
220+func buildNewItem (action,amt,token,priceIndex,invoker,minPayout,maxPayout) = (((((((((((((action + "|") + toString(amt)) + "|") + token) + "|") + toString(priceIndex)) + "|") + invoker) + "|") + toString(minPayout)) + "|") + toString(maxPayout)) + "|")
159221
160222
161-func buildNewItem (action,amt,token,priceIndex,invoker) = (((((((((action + "|") + toString(amt)) + "|") + token) + "|") + toString(priceIndex)) + "|") + invoker) + "|")
223+func userDiffAbs () = {
224+ let $t057975886 = $Tuple2((bullCol - poolBullExposure), (bearCol - poolBearExposure))
225+ let userBullCol = $t057975886._1
226+ let userBearCol = $t057975886._2
227+ let diff = (userBullCol - userBearCol)
228+ if ((diff > 0))
229+ then diff
230+ else (0 - diff)
231+ }
162232
163233
164234 func maxIssue (tokenId) = {
165235 let poolInvestment = if ((poolUp > 0))
166236 then BULL
167237 else BEAR
168- if ((poolInvestment == tokenId))
238+ if ((tokenId != poolInvestment))
169239 then poolMain
170- else ((2 * poolValue) - poolMain)
240+ else (userDiffAbs() + poolValue)
171241 }
242+
243+
244+func validatePMFee (i,minPayout) = if ((0 > minPayout))
245+ then throw("negative min payout")
246+ else {
247+ let p = i.payments[1]
248+ let ok = match p.assetId {
249+ case bv: ByteVector =>
250+ if ((toBase58String(bv) == mainToken))
251+ then (p.amount >= minUsdnFee)
252+ else false
253+ case waves: Unit =>
254+ (p.amount >= minWavesFee)
255+ case _ =>
256+ throw("Match error")
257+ }
258+ if (!(ok))
259+ then throw("incorrect pacemaker fee")
260+ else true
261+ }
172262
173263
174264 func validateRequestRedeem (inv) = if ((inv.caller == this))
175265 then throw("can't do")
176266 else {
177- func errorMessage (got) = throw(((((("only BULL(" + BULL) + ") or BEAR(") + BEAR) + ") tokens are accepted, received: ") + got))
267+ func errorMessage (got) = throw(((((("bad token att: only BULL(" + BULL) + ") or BEAR(") + BEAR) + ") tokens are accepted, received: ") + got))
178268
179- let assetId = toBase58String(valueOrErrorMessage(value(inv.payments[0]).assetId, "waves are not accepted here"))
269+ let assetId = toBase58String(valueOrErrorMessage(value(inv.payments[0]).assetId, "bad token att"))
180270 if (if ((assetId != BEAR))
181271 then (assetId != BULL)
182272 else false)
197287 }
198288
199289
200-func enqueue (id,action,amt,token,priceIndex,invoker) = {
201- let increaseQueueSize = IntegerEntry(queueSizeKey, (queueSize + 1))
202- let itm = buildNewItem(action, amt, token, priceIndex, invoker)
290+func enqueue (id,action,amt,token,priceIndex,invoker,minPayout,maxPayout) = {
291+ let increaseQueueSize = IE(QSIZEK, (queueSize + 1))
292+ let itm = buildNewItem(action, amt, token, priceIndex, invoker, minPayout, maxPayout)
203293 if ((queueSize == 0))
204- then [StringEntry(headPointerKey, id), StringEntry(tailPointerKey, id), StringEntry(id, itm), increaseQueueSize]
294+ then [SE(HEADK, id), SE(TAILK, id), SE(id, itm), increaseQueueSize]
205295 else {
206- let prevId = valueOrErrorMessage(getString(this, tailPointerKey), "can't get tail pointer")
207- let prevItm = split(valueOrErrorMessage(getString(this, prevId), "can't resolve pointer"), "|")
208- let updatedPrevItm = ((((((((((prevItm[0] + "|") + prevItm[1]) + "|") + prevItm[2]) + "|") + prevItm[3]) + "|") + prevItm[4]) + "|") + id)
209-[StringEntry(prevId, updatedPrevItm), StringEntry(id, itm), StringEntry(tailPointerKey, id), increaseQueueSize]
296+ let prevId = localS(TAILK, "can't get tail pointer")
297+ let prevItm = localS(prevId, "can't resolve pointer")
298+ let updatedPrevItm = (prevItm + id)
299+[SE(prevId, updatedPrevItm), SE(id, itm), SE(TAILK, id), increaseQueueSize]
210300 }
211301 }
212302
213303
214304 func poolSupport (curBullCol0,curBearCol0,curBullCirc0,curBearCirc0,curPoolMain0,curPoolUp0,curPoolDwn0) = {
215- func closeUp (curBullCol,curBearCol,curBullCirc,curBearCirc,curPoolMain,curPoolUp,curPoolDwn) = {
216- let diff = (curBullCol - curBearCol)
217- let exposure = fraction(curBullCol, curPoolUp, curBullCirc)
218- let liquidatedTokens = if ((diff > exposure))
219- then curPoolUp
220- else fraction(diff, curBullCirc, curBullCol)
221- let liquidatedValue = if ((diff > exposure))
222- then exposure
223- else fraction(liquidatedTokens, curBullCol, curBullCirc)
224- $Tuple7((curBullCol - liquidatedValue), curBearCol, (curBullCirc - liquidatedTokens), curBearCirc, (curPoolMain + liquidatedValue), (curPoolUp - liquidatedTokens), curPoolDwn)
305+ func closeUp (c1,c2,a0,a1,c0,pu,pd) = {
306+ let diff = (c1 - c2)
307+ let exp = fraction(c1, pu, a0)
308+ let liquidatedTokens = if ((diff > exp))
309+ then pu
310+ else fraction(diff, a0, c1)
311+ let liquidatedValue = if ((diff > exp))
312+ then exp
313+ else fraction(liquidatedTokens, c1, a0)
314+ $Tuple7((c1 - liquidatedValue), c2, (a0 - liquidatedTokens), a1, (c0 + liquidatedValue), (pu - liquidatedTokens), pd)
225315 }
226316
227- func closeDwn (curBullCol,curBearCol,curBullCirc,curBearCirc,curPoolMain,curPoolUp,curPoolDwn) = {
228- let diff = (curBearCol - curBullCol)
229- let exposure = fraction(curBearCol, curPoolDwn, curBearCirc)
230- let liquidatedTokens = if ((diff > exposure))
231- then curPoolDwn
232- else fraction(diff, curBearCirc, curBearCol)
233- let liquidatedValue = if ((diff > exposure))
234- then exposure
235- else fraction(liquidatedTokens, curBearCol, curBearCirc)
236- $Tuple7(curBullCol, (curBearCol - liquidatedValue), curBullCirc, (curBearCirc - liquidatedTokens), (curPoolMain + liquidatedValue), curPoolUp, (curPoolDwn - liquidatedTokens))
317+ func closeDwn (c1,c2,a0,a1,c0,pu,pd) = {
318+ let diff = (c2 - c1)
319+ let exp = fraction(c2, pd, a1)
320+ let liquidatedTokens = if ((diff > exp))
321+ then pd
322+ else fraction(diff, a1, c2)
323+ let liquidatedValue = if ((diff > exp))
324+ then exp
325+ else fraction(liquidatedTokens, c2, a1)
326+ $Tuple7(c1, (c2 - liquidatedValue), a0, (a1 - liquidatedTokens), (c0 + liquidatedValue), pu, (pd - liquidatedTokens))
237327 }
238328
239- func openDwn (curBullCol,curBearCol,curBullCirc,curBearCirc,curPoolMain,curPoolUp,curPoolDwn) = {
240- let diff = (curBullCol - curBearCol)
241- let spentPoolValue = if ((curPoolMain > diff))
329+ func openDwn (c1,c2,a0,a1,c0,pu,pd) = {
330+ let diff = (c1 - c2)
331+ let spentPoolValue = if ((c0 > diff))
242332 then diff
243- else curPoolMain
244- let acquiredTokens = fraction(spentPoolValue, curBearCirc, curBearCol)
245- $Tuple7(curBullCol, (curBearCol + spentPoolValue), curBullCirc, (curBearCirc + acquiredTokens), (curPoolMain - spentPoolValue), curPoolUp, (curPoolDwn + acquiredTokens))
333+ else c0
334+ let acquiredTokens = fraction(spentPoolValue, a1, c2)
335+ $Tuple7(c1, (c2 + spentPoolValue), a0, (a1 + acquiredTokens), (c0 - spentPoolValue), pu, (pd + acquiredTokens))
246336 }
247337
248- func openUp (curBullCol,curBearCol,curBullCirc,curBearCirc,curPoolMain,curPoolUp,curPoolDwn) = {
249- let diff = (curBearCol - curBullCol)
250- let spentPoolValue = if ((curPoolMain > diff))
338+ func openUp (c1,c2,a0,a1,c0,pu,pd) = {
339+ let diff = (c2 - c1)
340+ let spentPoolValue = if ((c0 > diff))
251341 then diff
252- else curPoolMain
253- let acquiredTokens = fraction(spentPoolValue, curBullCirc, curBullCol)
254- $Tuple7((curBullCol + spentPoolValue), curBearCol, (curBullCirc + acquiredTokens), curBearCirc, (curPoolMain - spentPoolValue), (curPoolUp + acquiredTokens), curPoolDwn)
342+ else c0
343+ let acquiredTokens = fraction(spentPoolValue, a0, c1)
344+ $Tuple7((c1 + spentPoolValue), c2, (a0 + acquiredTokens), a1, (c0 - spentPoolValue), (pu + acquiredTokens), pd)
255345 }
256346
257- if ((curBullCol0 > curBearCol0))
347+ let $t01025511290 = if ((curBullCol0 > curBearCol0))
258348 then {
259349 let afterCloseUp = closeUp(curBullCol0, curBearCol0, curBullCirc0, curBearCirc0, curPoolMain0, curPoolUp0, curPoolDwn0)
260- let $t01028610423 = afterCloseUp
261- let a = $t01028610423._1
262- let b = $t01028610423._2
263- let c = $t01028610423._3
264- let d = $t01028610423._4
265- let e = $t01028610423._5
266- let f = $t01028610423._6
267- let g = $t01028610423._7
350+ let $t01048110618 = afterCloseUp
351+ let a = $t01048110618._1
352+ let b = $t01048110618._2
353+ let c = $t01048110618._3
354+ let d = $t01048110618._4
355+ let e = $t01048110618._5
356+ let f = $t01048110618._6
357+ let g = $t01048110618._7
268358 if ((f > 0))
269359 then afterCloseUp
270360 else if ((f == 0))
273363 }
274364 else {
275365 let afterCloseDwn = closeDwn(curBullCol0, curBearCol0, curBullCirc0, curBearCirc0, curPoolMain0, curPoolUp0, curPoolDwn0)
276- let $t01077410914 = afterCloseDwn
277- let a = $t01077410914._1
278- let b = $t01077410914._2
279- let c = $t01077410914._3
280- let d = $t01077410914._4
281- let e = $t01077410914._5
282- let f = $t01077410914._6
283- let g = $t01077410914._7
366+ let $t01096911109 = afterCloseDwn
367+ let a = $t01096911109._1
368+ let b = $t01096911109._2
369+ let c = $t01096911109._3
370+ let d = $t01096911109._4
371+ let e = $t01096911109._5
372+ let f = $t01096911109._6
373+ let g = $t01096911109._7
284374 if ((g > 0))
285375 then afterCloseDwn
286376 else if ((g == 0))
287377 then openUp(a, b, c, d, e, f, g)
288378 else throw("poolDwn < 0")
289379 }
380+ let c1 = $t01025511290._1
381+ let c2 = $t01025511290._2
382+ let a0 = $t01025511290._3
383+ let a1 = $t01025511290._4
384+ let c0 = $t01025511290._5
385+ let pu = $t01025511290._6
386+ let pd = $t01025511290._7
387+ let charge = fraction(userDiffAbs(), rebalancePercentile, ((1440 * 100) * 100))
388+ let percentileActivated = (height >= valueOrElse(getInteger(configProvider, "percentileActivationHeight"), 10000000))
389+ let c1SplitP = if (if (percentileActivated)
390+ then (pd > 0)
391+ else false)
392+ then charge
393+ else 0
394+ let c2SplitP = if (if (percentileActivated)
395+ then (pu > 0)
396+ else false)
397+ then charge
398+ else 0
399+ $Tuple7((c1 - c1SplitP), (c2 - c2SplitP), a0, a1, ((c0 + c1SplitP) + c2SplitP), pu, pd)
290400 }
291401
292402
293-func actionsWithMaybePool (curBullCol0,curBearCol0,curBullCirc0,curBearCirc0) = {
294- let $t01121111394 = poolSupport(curBullCol0, curBearCol0, curBullCirc0, curBearCirc0, poolMain, poolUp, poolDwn)
295- let bullCol1 = $t01121111394._1
296- let bearCol1 = $t01121111394._2
297- let bullCic1 = $t01121111394._3
298- let bearCirc1 = $t01121111394._4
299- let poolMain1 = $t01121111394._5
300- let poolUp1 = $t01121111394._6
301- let poolDwn1 = $t01121111394._7
302-[IntegerEntry(bullCollateralKey, bullCol1), IntegerEntry(bullCirculationKey, bullCic1), IntegerEntry(bearCollateralKey, bearCol1), IntegerEntry(bearCirculationKey, bearCirc1), IntegerEntry(poolMainTokenValueKey, poolMain1), IntegerEntry(poolUpKey, poolUp1), IntegerEntry(poolDwnKey, poolDwn1)]
403+func poolSup (curBullCol0,curBearCol0,curBullCirc0,curBearCirc0) = {
404+ let $t01187112053 = poolSupport(curBullCol0, curBearCol0, curBullCirc0, curBearCirc0, poolMain, poolUp, poolDwn)
405+ let bullCol1 = $t01187112053._1
406+ let bearCol1 = $t01187112053._2
407+ let bullCic1 = $t01187112053._3
408+ let bearCirc1 = $t01187112053._4
409+ let poolMain1 = $t01187112053._5
410+ let poolUp1 = $t01187112053._6
411+ let poolDwn1 = $t01187112053._7
412+[IE(BULLCOLK, bullCol1), IE(BULLCIRCK, bullCic1), IE(BEARCOLK, bearCol1), IE(BEARCIRCK, bearCirc1), IE(POOLUSDNK, poolMain1), IE(POOLUPK, poolUp1), IE(POOLDWNK, poolDwn1)]
303413 }
304414
305415
306-func dequeue () = if ((queueSize == 0))
307- then throw("nothing to settle")
308- else {
309- func collectFee (fees) = IntegerEntry(feesAccumulatedKey, (feesAccumulated + fees))
416+func dequeue () = {
417+ func sp (a,mx) = if ((mx >= a))
418+ then $Tuple2(a, 0)
419+ else $Tuple2(mx, (a - mx))
310420
311- let decreaseQueueSize = IntegerEntry(queueSizeKey, (queueSize - 1))
312- let isLastElement = (headPointer == tailPointer)
313- let overwriteTail = StringEntry(tailPointerKey, "")
314- let data = split(valueOrErrorMessage(getString(this, headPointer), "bad head pointer"), "|")
315- let action = data[0]
316- let amt = parseIntValue(data[1])
317- let token = data[2]
318- let priceIndex = parseIntValue(data[3])
319- let invoker = addressFromStringValue(data[4])
320- let next = data[5]
321- let items = if ((rebalancedPriceIndex > priceIndex))
322- then throw(((("corrupt state, rebalancedPriceIndex=" + toString(rebalancedPriceIndex)) + ", request price id=") + toString(priceIndex)))
323- else if ((priceIndex > rebalancedPriceIndex))
324- then throw("can't dequeue, too early, rebalance first")
325- else if ((action == ISSUE))
326- then {
327- let feeSize = fraction(amt, issuePercentile, 10000)
328- let addedCollateral = (amt - feeSize)
329- if ((token == BULL))
421+ if ((queueSize == 0))
422+ then throw("nothing to settle")
423+ else {
424+ func collectFee (fees) = IE(FEEACCK, (feesAccumulated + fees))
425+
426+ let decreaseQueueSize = IE(QSIZEK, (queueSize - 1))
427+ let isLastElement = (headPointer == tailPointer)
428+ let overwriteTail = SE(TAILK, "")
429+ let dataStr = localS(headPointer, "bad head pointer(dequeue)")
430+ let data = split(dataStr, "|")
431+ let action = data[0]
432+ let amt = parseIntValue(data[1])
433+ let token = data[2]
434+ let priceIndex = parseIntValue(data[3])
435+ let invoker = addressFromStringValue(data[4])
436+ let minPayout = if ((8 > size(data)))
437+ then 0
438+ else parseIntValue(data[5])
439+ let maxPayout = if ((8 > size(data)))
440+ then MAX
441+ else parseIntValue(data[6])
442+ let next = data[(size(data) - 1)]
443+ func payback (tkn) = [SE(HEADK, next), decreaseQueueSize, ST(invoker, amt, fromBase58String(tkn))]
444+
445+ let items = if ((rebalancedPriceIndex > priceIndex))
446+ then throw(((("corrupt state, rebalancedPriceIndex=" + toString(rebalancedPriceIndex)) + ", request price id=") + toString(priceIndex)))
447+ else if ((priceIndex > rebalancedPriceIndex))
448+ then throw("can't dequeue, too early, rebalance first")
449+ else if ((action == ISSUE))
450+ then {
451+ let feeSize = fraction(amt, issuePercentile, 10000)
452+ let addedCollateral = (amt - feeSize)
453+ let a = if ((token == BULL))
454+ then fraction(bullCirc, addedCollateral, bullCol)
455+ else if ((token == BEAR))
456+ then fraction(bearCirc, addedCollateral, bearCol)
457+ else throw("bad token id")
458+ let $t01416714223 = sp(a, maxPayout)
459+ let addedToCirculation = $t01416714223._1
460+ let extraTokens = $t01416714223._2
461+ let $t01424014411 = if ((token == BULL))
462+ then $Tuple4(addedToCirculation, addedCollateral, 0, 0)
463+ else $Tuple4(0, 0, addedToCirculation, addedCollateral)
464+ let plusBulls = $t01424014411._1
465+ let plusBullCol = $t01424014411._2
466+ let plusBears = $t01424014411._3
467+ let plusBearCol = $t01424014411._4
468+ if ((minPayout > addedToCirculation))
469+ then payback(mainToken)
470+ else (poolSup((bullCol + plusBullCol), (bearCol + plusBearCol), (bullCirc + plusBulls), (bearCirc + plusBears)) ++ [SE(HEADK, next), collectFee(feeSize), decreaseQueueSize, ST(invoker, addedToCirculation, fromBase58String(token)), ST(feeAddress, extraTokens, fromBase58String(token))])
471+ }
472+ else if ((action == REDEEM))
330473 then {
331- let addedToCirculation = fraction(bullCirc, addedCollateral, bullCol)
332- (actionsWithMaybePool((bullCol + addedCollateral), bearCol, (bullCirc + addedToCirculation), bearCirc) ++ [StringEntry(headPointerKey, next), collectFee(feeSize), decreaseQueueSize, ScriptTransfer(invoker, addedToCirculation, fromBase58String(BULL))])
474+ let removedTokens = amt
475+ let calcPo = if ((token == BULL))
476+ then fraction(bullCol, removedTokens, bullCirc)
477+ else if ((token == BEAR))
478+ then fraction(bearCol, removedTokens, bearCirc)
479+ else throw("bad token id")
480+ let $t01532615375 = sp(calcPo, maxPayout)
481+ let payoutCapped = $t01532615375._1
482+ let extra = $t01532615375._2
483+ let feeSize = fraction(payoutCapped, redeemPercentile, 10000)
484+ let payout = if ((payoutCapped > feeSize))
485+ then (payoutCapped - feeSize)
486+ else 0
487+ let $t01556115720 = if ((token == BULL))
488+ then $Tuple4(removedTokens, payoutCapped, 0, 0)
489+ else $Tuple4(0, 0, removedTokens, payoutCapped)
490+ let minusBulls = $t01556115720._1
491+ let minusBullCol = $t01556115720._2
492+ let minusBears = $t01556115720._3
493+ let minusBearCol = $t01556115720._4
494+ if ((minPayout > payout))
495+ then payback(token)
496+ else (poolSup((bullCol - minusBullCol), (bearCol - minusBearCol), (bullCirc - minusBulls), (bearCirc - minusBears)) ++ [SE(HEADK, next), collectFee(feeSize), decreaseQueueSize, ST(invoker, payout, fromBase58String(mainToken)), ST(feeAddress, extra, fromBase58String(mainToken))])
333497 }
334- else if ((token == BEAR))
498+ else if ((action == POOL))
335499 then {
336- let addedToCirculation = fraction(bearCirc, addedCollateral, bearCol)
337- (actionsWithMaybePool(bullCol, (bearCol + addedCollateral), bullCirc, (bearCirc + addedToCirculation)) ++ [StringEntry(headPointerKey, next), collectFee(feeSize), decreaseQueueSize, ScriptTransfer(invoker, addedToCirculation, fromBase58String(BEAR))])
500+ let issueTokens = fraction(poolTokenCirculation, amt, poolValue)
501+ if ((minPayout > issueTokens))
502+ then payback(mainToken)
503+ else [IE(POOLUSDNK, (poolMain + amt)), IE(POOLCIRCK, (poolTokenCirculation + issueTokens)), SE(HEADK, next), decreaseQueueSize, ST(invoker, issueTokens, fromBase58String(poolToken))]
338504 }
339- else throw("bad token id")
340- }
341- else if ((action == REDEEM))
342- then {
343- let removedTokens = amt
344- if ((token == BULL))
345- then {
346- let removedCollateral = fraction(bullCol, removedTokens, bullCirc)
347- let feeSize = fraction(removedCollateral, redeemPercentile, 10000)
348- let payout = if ((removedCollateral > feeSize))
349- then (removedCollateral - feeSize)
350- else 0
351- (actionsWithMaybePool((bullCol - removedCollateral), bearCol, (bullCirc - removedTokens), bearCirc) ++ [StringEntry(headPointerKey, next), collectFee(feeSize), decreaseQueueSize, ScriptTransfer(invoker, payout, fromBase58String(mainToken))])
352- }
353- else if ((token == BEAR))
505+ else if ((action == UNPOOL))
354506 then {
355- let removedCollateral = fraction(bearCol, removedTokens, bearCirc)
356- let feeSize = fraction(removedCollateral, redeemPercentile, 10000)
357- let payout = if ((removedCollateral > feeSize))
358- then (removedCollateral - feeSize)
359- else 0
360- (actionsWithMaybePool(bullCol, (bearCol - removedCollateral), bullCirc, (bearCirc - removedTokens)) ++ [StringEntry(headPointerKey, next), collectFee(feeSize), decreaseQueueSize, ScriptTransfer(invoker, payout, fromBase58String(mainToken))])
507+ func share (a) = fraction(a, amt, poolTokenCirculation)
508+
509+ let unpooledMain = share(poolMain)
510+ let unpooledUp = share(poolUp)
511+ let unpooledDwn = share(poolDwn)
512+ let unpooledUpValue = fraction(unpooledUp, bullCol, bullCirc)
513+ let unpooledDwnValue = fraction(unpooledDwn, bearCol, bearCirc)
514+ let totalUnpooledValue = ((unpooledMain + unpooledUpValue) + unpooledDwnValue)
515+ if ((minPayout > totalUnpooledValue))
516+ then payback(poolToken)
517+ else [IE(POOLUSDNK, (poolMain - unpooledMain)), IE(POOLCIRCK, (poolTokenCirculation - amt)), IE(POOLUPK, (poolUp - unpooledUp)), IE(POOLDWNK, (poolDwn - unpooledDwn)), IE(BULLCIRCK, (bullCirc - unpooledUp)), IE(BEARCIRCK, (bearCirc - unpooledDwn)), IE(BULLCOLK, (bullCol - unpooledUpValue)), IE(BEARCOLK, (bearCol - unpooledDwnValue)), SE(HEADK, next), decreaseQueueSize, ST(invoker, totalUnpooledValue, fromBase58String(mainToken))]
361518 }
362- else throw("bad token id")
363- }
364- else if ((action == POOL))
365- then {
366- let issueTokens = fraction(poolTokenCirculation, amt, poolValue)
367-[IntegerEntry(poolMainTokenValueKey, (poolMain + amt)), IntegerEntry(poolTokenCirculationKey, (poolTokenCirculation + issueTokens)), StringEntry(headPointerKey, next), decreaseQueueSize, ScriptTransfer(invoker, issueTokens, fromBase58String(poolToken))]
368- }
369- else if ((action == UNPOOL))
370- then {
371- func share (a) = fraction(a, amt, poolTokenCirculation)
372-
373- let unpooledMain = share(poolMain)
374- let unpooledUp = share(poolUp)
375- let unpooledDwn = share(poolDwn)
376- let unpooledUpValue = fraction(unpooledUp, bullCol, bullCirc)
377- let unpooledDwnValue = fraction(unpooledDwn, bearCol, bearCirc)
378-[IntegerEntry(poolMainTokenValueKey, (poolMain - unpooledMain)), IntegerEntry(poolTokenCirculationKey, (poolTokenCirculation - amt)), IntegerEntry(poolUpKey, (poolUp - unpooledUp)), IntegerEntry(poolDwnKey, (poolDwn - unpooledDwn)), IntegerEntry(bullCirculationKey, (bullCirc - unpooledUp)), IntegerEntry(bearCirculationKey, (bearCirc - unpooledDwn)), IntegerEntry(bullCollateralKey, (bullCol - unpooledUpValue)), IntegerEntry(bearCollateralKey, (bearCol - unpooledDwnValue)), StringEntry(headPointerKey, next), decreaseQueueSize, ScriptTransfer(invoker, ((unpooledMain + unpooledUpValue) + unpooledDwnValue), fromBase58String(mainToken))]
379- }
380- else throw(("bad action: " + action))
381- if (isLastElement)
382- then overwriteTail :: items
383- else items
384- }
519+ else throw(("bad action: " + action))
520+ if (isLastElement)
521+ then overwriteTail :: items
522+ else items
523+ }
524+ }
385525
386526
387527 func rebalance () = {
388- func LV (v,p0,p1) = {
389- let denom = 100
528+ func LV (v,p0,p1,m) = {
529+ let denom = {
530+ let md = (((2 * (if ((p1 > p0))
531+ then p1
532+ else p0)) * m) / 3037000499)
533+ if ((10 > md))
534+ then 10
535+ else if ((100 > md))
536+ then 100
537+ else 1000
538+ }
390539 let pmax = ((if ((p1 > p0))
391540 then p1
392541 else p0) / denom)
394543 then p1
395544 else p0) / denom)
396545 let a = (pmin * pmin)
397- let b = (((9 * pmax) * pmax) - ((15 * pmax) * pmin))
398- fraction(v, ((6 * a) + b), ((7 * a) + b))
546+ let b = ((((m * m) * pmax) * pmax) - (((((2 * m) * m) - m) * pmax) * pmin))
547+ let ma = ((m * m) - m)
548+ fraction(v, ((ma * a) + b), (((ma + 1) * a) + b))
399549 }
400550
401- let settledPriceIndex = valueOrErrorMessage(getInteger(this, lastRebalancePriceIndexKey), "inconsistent data")
551+ let settledPriceIndex = valueOrErrorMessage(getInteger(this, REBIDXK), "inconsistent data")
402552 let unsettledPriceIndex = (settledPriceIndex + 1)
403- let settledPriceHeight = valueOrErrorMessage(getInteger(oracle, ("price_index_" + toString(settledPriceIndex))), "bad oracle data for settled price height")
404- let settledPrice = valueOrErrorMessage(getInteger(oracle, ("price_" + toString(settledPriceHeight))), "bad oracle data for price")
405- let nextPriceHeight = valueOrErrorMessage(getInteger(oracle, ("price_index_" + toString(unsettledPriceIndex))), "no next price height")
406- let nextPrice = valueOrErrorMessage(getInteger(oracle, ("price_" + toString(nextPriceHeight))), "no next price")
553+ let settledPrice = priceByIndex(assetName, settledPriceIndex)
554+ let nextPrice = priceByIndex(assetName, unsettledPriceIndex)
407555 let minVol = if ((bearCol > bullCol))
408556 then bullCol
409557 else bearCol
410- let redist = LV(minVol, settledPrice, nextPrice)
411- let newBullCol = if ((nextPrice > settledPrice))
558+ let redist = LV(minVol, settledPrice, nextPrice, leverage)
559+ let priceUpGoodForBulls = (assetName == "")
560+ let priceGoesUp = (nextPrice > settledPrice)
561+ let bullsEarn = (priceUpGoodForBulls == priceGoesUp)
562+ let newBullCol = if (bullsEarn)
412563 then (bullCol + redist)
413564 else (bullCol - redist)
414- let newBearCol = if ((nextPrice > settledPrice))
565+ let newBearCol = if (bullsEarn)
415566 then (bearCol - redist)
416567 else (bearCol + redist)
417- let $t01926019447 = poolSupport(newBullCol, newBearCol, bullCirc, bearCirc, poolMain, poolUp, poolDwn)
418- let updBullCol = $t01926019447._1
419- let updBearCol = $t01926019447._2
420- let updBullCirc = $t01926019447._3
421- let updBearCirc = $t01926019447._4
422- let updPoolMain = $t01926019447._5
423- let updPoolUp = $t01926019447._6
424- let updPoolDwn = $t01926019447._7
425-[IntegerEntry(bullCollateralKey, updBullCol), IntegerEntry(bearCollateralKey, updBearCol), IntegerEntry(bullCirculationKey, updBullCirc), IntegerEntry(bearCirculationKey, updBearCirc), IntegerEntry(poolMainTokenValueKey, updPoolMain), IntegerEntry(poolUpKey, updPoolUp), IntegerEntry(poolDwnKey, updPoolDwn), IntegerEntry(lastRebalancePriceIndexKey, unsettledPriceIndex)]
568+ let $t01960819794 = poolSupport(newBullCol, newBearCol, bullCirc, bearCirc, poolMain, poolUp, poolDwn)
569+ let updBullCol = $t01960819794._1
570+ let updBearCol = $t01960819794._2
571+ let updBullCirc = $t01960819794._3
572+ let updBearCirc = $t01960819794._4
573+ let updPoolMain = $t01960819794._5
574+ let updPoolUp = $t01960819794._6
575+ let updPoolDwn = $t01960819794._7
576+[IE(BULLCOLK, updBullCol), IE(BEARCOLK, updBearCol), IE(BULLCIRCK, updBullCirc), IE(BEARCIRCK, updBearCirc), IE(POOLUSDNK, updPoolMain), IE(POOLUPK, updPoolUp), IE(POOLDWNK, updPoolDwn), IE(REBIDXK, unsettledPriceIndex)]
577+ }
578+
579+
580+func calcMax (min,avg) = if ((min > avg))
581+ then throw(((("price too old: minPayout " + toString(min)) + " > avg = ") + toString(avg)))
582+ else ((avg + avg) - min)
583+
584+
585+func requestIssueInternal (inv,tokenId,minPayout) = if (if ((tokenId != BULL))
586+ then (tokenId != BEAR)
587+ else false)
588+ then throw("bad token req")
589+ else if ((inv.caller == this))
590+ then throw("can't do")
591+ else if (!(allowed(inv.caller)))
592+ then throw("only whitelisted can do")
593+ else {
594+ let errorMessage = (((("bad token req, only BULL(" + BULL) + ") or BEAR(") + BEAR) + ") allowed")
595+ if ((inv.payments[0].assetId != fromBase58String(mainToken)))
596+ then throw("bad token att")
597+ else {
598+ let amt = inv.payments[0].amount
599+ let $t02080020978 = if ((tokenId == BULL))
600+ then $Tuple2(bullCol, bullCirc)
601+ else if ((tokenId == BEAR))
602+ then $Tuple2(bearCol, bearCirc)
603+ else throw(errorMessage)
604+ let col = $t02080020978._1
605+ let circ = $t02080020978._2
606+ let est = fraction(amt, circ, col)
607+ let $t02102021114 = if ((minPayout == 0))
608+ then $Tuple2(0, MAX)
609+ else $Tuple2(minPayout, calcMax(minPayout, est))
610+ let minP = $t02102021114._1
611+ let maxP = $t02102021114._2
612+ if ((minIssue > amt))
613+ then throw((("Attached payment too small. Min required: " + toString((minIssue / 1000000))) + " USDN"))
614+ else {
615+ let maxAllowed = maxIssue(tokenId)
616+ if (if ((whitelist == ""))
617+ then (inv.payments[0].amount > maxAllowed)
618+ else false)
619+ then throw((("trying to issue more than pool can handle. Max attachment allowed = " + toString((maxAllowed / 1000000))) + " USDN"))
620+ else (enqueue(toBase58String(inv.transactionId), ISSUE, amt, tokenId, (oraclePriceIndex + 1), toString(inv.caller), minP, maxP) ++ [debug("requested", tokenId), debug("bull", BULL), debug("bear", BEAR)])
621+ }
622+ }
623+ }
624+
625+
626+func requestRedeemInternal (inv,minPayout) = {
627+ let amt = inv.payments[0].amount
628+ let tokenId = toBase58String(valueOrErrorMessage(inv.payments[0].assetId, "bad token att"))
629+ if (if ((tokenId != BULL))
630+ then (tokenId != BEAR)
631+ else false)
632+ then throw("bad token req")
633+ else {
634+ let $t02215122290 = if ((tokenId == BULL))
635+ then $Tuple2(bullCol, bullCirc)
636+ else if ((tokenId == BEAR))
637+ then $Tuple2(bearCol, bearCirc)
638+ else throw("bad token req")
639+ let col = $t02215122290._1
640+ let circ = $t02215122290._2
641+ let est = fraction(amt, col, circ)
642+ let $t02233822432 = if ((minPayout == 0))
643+ then $Tuple2(0, MAX)
644+ else $Tuple2(minPayout, calcMax(minPayout, est))
645+ let minP = $t02233822432._1
646+ let maxP = $t02233822432._2
647+ if ((validateRequestRedeem(inv) == unit))
648+ then enqueue(toBase58String(inv.transactionId), REDEEM, amt, tokenId, (oraclePriceIndex + 1), toString(inv.caller), minP, maxP)
649+ else throw("doesn't happen")
650+ }
651+ }
652+
653+
654+func requestPoolInternal (inv,minPayout) = if (!(allowed(inv.caller)))
655+ then throw("only whitelisted can do")
656+ else {
657+ let errMessage = (("main token must be attached(" + mainToken) + ")")
658+ let pmt = inv.payments[0]
659+ if ((pmt.assetId != fromBase58String(mainToken)))
660+ then throw(errMessage)
661+ else if ((minPool > pmt.amount))
662+ then throw(((("pool at least " + toString(minPool)) + " ") + mainToken))
663+ else {
664+ let estimate = fraction(poolTokenCirculation, pmt.amount, poolValue)
665+ let $t02328023379 = if ((minPayout == 0))
666+ then $Tuple2(0, MAX)
667+ else $Tuple2(minPayout, calcMax(minPayout, estimate))
668+ let minP = $t02328023379._1
669+ let maxP = $t02328023379._2
670+ enqueue(toBase58String(inv.transactionId), POOL, inv.payments[0].amount, "", (oraclePriceIndex + 1), toString(inv.caller), minP, maxP)
671+ }
672+ }
673+
674+
675+func requestUnpoolInternal (inv,minPayout) = {
676+ let errMessage = (("only pool token allowed(" + poolToken) + ")")
677+ let pmt = inv.payments[0]
678+ if ((pmt.assetId != fromBase58String(poolToken)))
679+ then throw(errMessage)
680+ else {
681+ let estimate = fraction(poolValue, pmt.amount, poolTokenCirculation)
682+ if ((minPool > estimate))
683+ then throw(((("unpool at least for" + toString(minPool)) + " ") + mainToken))
684+ else {
685+ let $t02403624135 = if ((minPayout == 0))
686+ then $Tuple2(0, MAX)
687+ else $Tuple2(minPayout, calcMax(minPayout, estimate))
688+ let minP = $t02403624135._1
689+ let maxP = $t02403624135._2
690+ enqueue(toBase58String(inv.transactionId), UNPOOL, inv.payments[0].amount, "", (oraclePriceIndex + 1), toString(inv.caller), minP, maxP)
691+ }
692+ }
426693 }
427694
428695
429696 @Callable(inv)
430-func init (config,oraclePK,nameup,namedwn,descUp,descDwn,poolName,poolDesc,denom) = if (isDefined(getString(this, BULLKey)))
697+func init (config,oraclePK,nameup,namedwn,descUp,descDwn,poolName,poolDesc,defoAssetName,denom,lev) = if (isDefined(getString(this, BULLK)))
431698 then throw("already initialized")
432699 else {
433700 let totalOwnedMainToken = inv.payments[0].amount
441708 else (pools == 0))
442709 then throw("can't init balances")
443710 else {
444- let oracleCurrentPriceIndex = valueOrErrorMessage(getInteger(valueOrErrorMessage(addressFromPublicKey(fromBase58String(oraclePK)), "bad oracle address"), lastPriceIndexKey), "can't find last oracle price index")
711+ let oracleCurrentPriceIndex = valueOrErrorMessage(getInteger(valueOrErrorMessage(addressFromPublicKey(fromBase58String(oraclePK)), "bad oracle address"), lastPriceIndexKey(defoAssetName)), "can't find last oracle price index")
445712 let bull = Issue(nameup, descUp, ((100 * ten6) * ten6), 6, true)
446713 let bear = Issue(namedwn, descDwn, ((100 * ten6) * ten6), 6, true)
447714 let pool = Issue(poolName, poolDesc, ((100 * ten6) * ten6), 6, true)
448715 let buid = calculateAssetId(bull)
449716 let beid = calculateAssetId(bear)
450717 let poid = calculateAssetId(pool)
451-[bull, bear, pool, StringEntry(BULLKey, toBase58String(buid)), StringEntry(BEARKey, toBase58String(beid)), StringEntry(mainTokenKey, toBase58String(value(inv.payments[0].assetId))), StringEntry(poolTokenKey, toBase58String(poid)), StringEntry(oraclePKKey, oraclePK), IntegerEntry(lastRebalancePriceIndexKey, oracleCurrentPriceIndex), IntegerEntry(bullCollateralKey, bulls), IntegerEntry(bearCollateralKey, bears), IntegerEntry(bullCirculationKey, (bulls / denom)), IntegerEntry(bearCirculationKey, (bears / denom)), IntegerEntry(poolTokenCirculationKey, (pools / denom)), IntegerEntry(poolDwnKey, 0), IntegerEntry(poolUpKey, 0), IntegerEntry(poolMainTokenValueKey, pools), StringEntry(configProviderKey, config), ScriptTransfer(inv.caller, (bulls / denom), buid), ScriptTransfer(inv.caller, (bears / denom), beid), ScriptTransfer(inv.caller, (pools / denom), poid)]
718+[bull, bear, pool, SE(BULLK, toBase58String(buid)), SE(BEARK, toBase58String(beid)), SE(USDNK, toBase58String(value(inv.payments[0].assetId))), SE(POOLK, toBase58String(poid)), SE(ASSNAMEK, defoAssetName), SE(oraclePKKey, oraclePK), IE(REBIDXK, oracleCurrentPriceIndex), IE(BULLCOLK, bulls), IE(BEARCOLK, bears), IE(BULLCIRCK, (bulls / denom)), IE(BEARCIRCK, (bears / denom)), IE(POOLCIRCK, (pools / denom)), IE(POOLDWNK, 0), IE(POOLUPK, 0), IE(POOLUSDNK, pools), SE(configProviderKey, config), IE(LEVK, lev), ST(inv.caller, (bulls / denom), buid), ST(inv.caller, (bears / denom), beid), ST(inv.caller, (pools / denom), poid)]
452719 }
453720 }
454721
457724 @Callable(i)
458725 func withdrawFee (amount) = if ((amount > feesAccumulated))
459726 then throw(("too much. available: " + toString(feesAccumulated)))
460- else [IntegerEntry(feesAccumulatedKey, (feesAccumulated - amount)), ScriptTransfer(feeAddress, amount, fromBase58String(mainToken))]
727+ else [IE(FEEACCK, (feesAccumulated - amount)), ST(feeAddress, amount, fromBase58String(mainToken))]
461728
462729
463730
464731 @Callable(inv)
465-func requestRedeem () = if ((validateRequestRedeem(inv) == unit))
466- then {
467- let assetId = toBase58String(valueOrErrorMessage(inv.payments[0].assetId, "waves are not accepted here"))
468- enqueue(toBase58String(inv.transactionId), REDEEM, inv.payments[0].amount, assetId, (oraclePriceIndex + 1), toString(inv.caller))
469- }
470- else throw("doesn't happen")
732+func requestRedeem () = requestRedeemInternal(inv, 0)
471733
472734
473735
474736 @Callable(inv)
475-func requestIssue (tokenId) = if ((inv.caller == this))
476- then throw("can't do")
477- else if (!(allowed(inv.caller)))
478- then throw("only whitelisted can do")
479- else {
480- let errorMessage = throw((((((("only BULL(" + BULL) + ") or BEAR(") + BEAR) + ") tokens are available in exchange for USDN(") + mainToken) + ")"))
481- if (if ((tokenId != BULL))
482- then (tokenId != BEAR)
483- else false)
484- then errorMessage
485- else if ((inv.payments[0].assetId != fromBase58String(mainToken)))
486- then errorMessage
487- else if ((minIssue > inv.payments[0].amount))
488- then throw((("Attached payment too small. Min required: " + toString((minIssue / 1000000))) + " USDN"))
489- else {
490- let maxAllowed = maxIssue(tokenId)
491- if (if ((whitelist == ""))
492- then (inv.payments[0].amount > maxAllowed)
493- else false)
494- then throw((("trying to issue more than pool can handle. Max attachment allowed = " + toString((maxAllowed / 1000000))) + " USDN"))
495- else enqueue(toBase58String(inv.transactionId), ISSUE, inv.payments[0].amount, tokenId, (oraclePriceIndex + 1), toString(inv.caller))
496- }
497- }
737+func requestRedeemSl (sl) = if (validatePMFee(inv, sl))
738+ then requestRedeemInternal(inv, sl)
739+ else throw()
740+
741+
742+
743+@Callable(inv)
744+func requestIssue (tokenId) = requestIssueInternal(inv, tokenId, 0)
745+
746+
747+
748+@Callable(inv)
749+func requestIssueSl (tokenId,sl) = if (validatePMFee(inv, sl))
750+ then requestIssueInternal(inv, tokenId, sl)
751+ else throw()
752+
753+
754+
755+@Callable(inv)
756+func requestPool () = requestPoolInternal(inv, 0)
757+
758+
759+
760+@Callable(inv)
761+func requestPoolSl (sl) = if (validatePMFee(inv, sl))
762+ then requestPoolInternal(inv, sl)
763+ else throw()
764+
765+
766+
767+@Callable(inv)
768+func requestUnpool () = requestUnpoolInternal(inv, 0)
769+
770+
771+
772+@Callable(inv)
773+func requestUnpoolSl (sl) = if (validatePMFee(inv, sl))
774+ then requestUnpoolInternal(inv, sl)
775+ else throw()
498776
499777
500778
507785 then rebalance()
508786 else throw("[OK] all done, carry on")
509787 else {
510- let data = split(valueOrErrorMessage(getString(this, headPointer), "bad head pointer"), "|")
788+ let data = split(valueOrErrorMessage(getString(this, headPointer), ("bad head pointer(settle): " + headPointer)), "|")
511789 let priceIndex = parseIntValue(data[3])
512790 if ((priceIndex > rebalancedPriceIndex))
513791 then if (canRebalance)
515793 else throw("[OK] need to wait")
516794 else if ((priceIndex == rebalancedPriceIndex))
517795 then dequeue()
518- else throw("corrupt data, future price id already rebalanced")
519- }
520- }
521-
522-
523-
524-@Callable(inv)
525-func requestPool () = if (!(allowed(inv.caller)))
526- then throw("only whitelisted can do")
527- else {
528- let errMessage = (("main token must be attached(" + mainToken) + ")")
529- let pmt = inv.payments[0]
530- if ((pmt.assetId != fromBase58String(mainToken)))
531- then throw(errMessage)
532- else if ((minPool > pmt.amount))
533- then throw(((("pool at least " + toString(minPool)) + " ") + mainToken))
534- else enqueue(toBase58String(inv.transactionId), POOL, inv.payments[0].amount, "", (oraclePriceIndex + 1), toString(inv.caller))
535- }
536-
537-
538-
539-@Callable(inv)
540-func requestUnpool () = {
541- let errMessage = (("only pool token allowed(" + poolToken) + ")")
542- let pmt = inv.payments[0]
543- if ((pmt.assetId != fromBase58String(poolToken)))
544- then throw(errMessage)
545- else {
546- let estimate = fraction(poolValue, pmt.amount, poolTokenCirculation)
547- if ((minPool > estimate))
548- then throw(((("unpool at least for" + toString(minPool)) + " ") + mainToken))
549- else enqueue(toBase58String(inv.transactionId), UNPOOL, inv.payments[0].amount, "", (oraclePriceIndex + 1), toString(inv.caller))
796+ else throw("future price already rebalanced")
550797 }
551798 }
552799
553800
554801 @Verifier(tx)
555802 func verify () = {
556- let initial = if (!(isDefined(getString(this, BULLKey))))
803+ let initial = if (!(isDefined(getString(this, BULLK))))
557804 then sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
558805 else false
559- let adminAction = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(pubKeyAdminsList[0])))
806+ let adminAction = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(admins[0])))
560807 then 1
561- else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(pubKeyAdminsList[1])))
808+ else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(admins[1])))
562809 then 1
563- else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(pubKeyAdminsList[2])))
810+ else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(admins[2])))
564811 then 1
565812 else 0)) > 1)
566813 let stakingAction = match tx {
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 4 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+func SE (k,v) = StringEntry(k, v)
5+
6+
7+func IE (k,v) = IntegerEntry(k, v)
8+
9+
10+func ST (a,amt,t) = ScriptTransfer(a, amt, t)
11+
12+
13+func debug (k,v) = SE(("__dbg__" + k), v)
14+
15+
416 let ten6 = 1000000
517
618 let ten8 = 100000000
19+
20+let MAX = 9223372036854775807
721
822 let configProviderKey = "configProvider"
923
1024 let configProvider = match getString(this, configProviderKey) {
1125 case s: String =>
1226 addressFromStringValue(s)
1327 case _ =>
1428 this
1529 }
1630
17-let BULLKey = "BULLId"
31+func localI (k,e) = valueOrErrorMessage(getInteger(this, k), e)
1832
19-let BEARKey = "BEARId"
2033
21-let mainTokenKey = "mainTokenId"
34+func localS (k,e) = valueOrErrorMessage(getString(this, k), e)
2235
23-let bullCollateralKey = "bullCollateral"
2436
25-let bearCollateralKey = "bearCollateral"
37+func confI (k,e) = valueOrErrorMessage(getInteger(configProvider, k), e)
2638
27-let bullCirculationKey = "bullCirculation"
2839
29-let bearCirculationKey = "bearCirculation"
40+func confS (k,e) = valueOrErrorMessage(getString(configProvider, k), e)
3041
31-let issuePercentileKey = "issuePercentile"
3242
33-let redeemPercentileKey = "redeemPercentile"
43+let BULLK = "BULLId"
3444
35-let minIssueKey = "minIssue"
45+let BEARK = "BEARId"
3646
37-let minRedeemKey = "minRedeem"
47+let USDNK = "mainTokenId"
3848
39-let minPoolKey = "minPool"
49+let BULLCOLK = "bullCollateral"
4050
41-let feesAccumulatedKey = "feesAccumulated"
51+let BEARCOLK = "bearCollateral"
4252
43-let whitelistKey = "issueWhiteList"
53+let BULLCIRCK = "bullCirculation"
54+
55+let BEARCIRCK = "bearCirculation"
56+
57+let ISSPERCK = "issuePercentile"
58+
59+let REDPERCK = "redeemPercentile"
60+
61+let MINISSK = "minIssue"
62+
63+let MINREDK = "minRedeem"
64+
65+let MINPOOLK = "minPool"
66+
67+let FEEACCK = "feesAccumulated"
68+
69+let WLISTK = "issueWhiteList"
70+
71+let REBPERCK = "rebalancePercentile"
72+
73+let REBIDXK = "lastSettlementPriceId"
74+
75+let HEADK = "headPointer"
76+
77+let TAILK = "tailPointer"
78+
79+let QSIZEK = "queueSize"
80+
81+let POOLUSDNK = "poolMainTokenValue"
82+
83+let POOLUPK = "poolUp"
84+
85+let POOLDWNK = "poolDwn"
86+
87+let POOLCIRCK = "poolTokenCirculation"
88+
89+let POOLK = "poolToken"
90+
91+let ASSNAMEK = "defoAssetName"
92+
93+let LEVK = "leverage"
94+
95+let WAVESFEEK = "wavesPacemakerFee"
96+
97+let USDNFEEK = "usdnPacemakerFee"
4498
4599 let oraclePKKey = "oracle"
46100
47-let lastPriceIndexKey = "price_index"
101+func lastPriceIndexKey (assetId) = if ((assetId == ""))
102+ then "price_index"
103+ else ("%s%s__idxCurrent__" + assetId)
48104
49-let priceIndexPrefix = "price_index_"
50105
51-let priceHeightPrefix = "price_"
106+func priceIndexPrefix (assetId) = if ((assetId == ""))
107+ then "price_index_"
108+ else (("%s%s%d__idx2Height__" + assetId) + "__")
52109
53-let oracleCurrentPriceIndexKey = "price_index"
54110
55-let lastRebalancePriceIndexKey = "lastSettlementPriceId"
111+func priceHeightPrefix (assetId) = if ((assetId == ""))
112+ then "price_"
113+ else (("%s%s%d__priceByHeight__" + assetId) + "__")
56114
57-let headPointerKey = "headPointer"
58115
59-let tailPointerKey = "tailPointer"
116+let minUsdnFee = valueOrElse(getInteger(configProvider, USDNFEEK), 0)
60117
61-let queueSizeKey = "queueSize"
118+let minWavesFee = valueOrElse(getInteger(configProvider, WAVESFEEK), 0)
62119
63-let poolMainTokenValueKey = "poolMainTokenValue"
120+let assetName = valueOrElse(getString(this, ASSNAMEK), "")
64121
65-let poolUpKey = "poolUp"
122+let bullCol = localI(BULLCOLK, "no 0")
66123
67-let poolDwnKey = "poolDwn"
124+let bearCol = localI(BEARCOLK, "no 1")
68125
69-let poolTokenCirculationKey = "poolTokenCirculation"
126+let bullCirc = localI(BULLCIRCK, "no 2")
70127
71-let poolTokenKey = "poolToken"
128+let bearCirc = localI(BEARCIRCK, "no 3")
72129
73-let bullCol = valueOrErrorMessage(getInteger(this, bullCollateralKey), "no bullCollateralKey")
130+let BULL = localS(BULLK, "no 14")
74131
75-let bearCol = valueOrErrorMessage(getInteger(this, bearCollateralKey), "no bearCollateralKey")
132+let BEAR = localS(BEARK, "no 15")
76133
77-let bullCirc = valueOrErrorMessage(getInteger(this, bullCirculationKey), "no bullCirculationKey")
134+let mainToken = localS(USDNK, "no 16")
78135
79-let bearCirc = valueOrErrorMessage(getInteger(this, bearCirculationKey), "no bearCirculationKey")
136+let issuePercentile = confI(ISSPERCK, "no 4")
80137
81-let BULL = valueOrErrorMessage(getString(this, BULLKey), "no BULLKey")
138+let redeemPercentile = confI(REDPERCK, "no 5")
82139
83-let BEAR = valueOrErrorMessage(getString(this, BEARKey), "no BEARKey")
140+let minIssue = confI(MINISSK, "no 6")
84141
85-let mainToken = valueOrErrorMessage(getString(this, mainTokenKey), "no mainTokenKey")
142+let minRedeem = confI(MINREDK, "no 7")
86143
87-let issuePercentile = valueOrErrorMessage(getInteger(configProvider, issuePercentileKey), "no issuePercentileKey")
144+let minPool = confI(MINPOOLK, "no 8")
88145
89-let redeemPercentile = valueOrErrorMessage(getInteger(configProvider, redeemPercentileKey), "no redeemPercentileKey")
146+let rebalancePercentile = valueOrElse(getInteger(configProvider, ((toString(this) + "_") + REBPERCK)), 0)
90147
91-let minIssue = valueOrErrorMessage(getInteger(configProvider, minIssueKey), "no minIssueKey")
92-
93-let minRedeem = valueOrErrorMessage(getInteger(configProvider, minRedeemKey), "no minRedeemKey")
94-
95-let minPool = valueOrErrorMessage(getInteger(configProvider, minPoolKey), "no minPoolKey")
96-
97-let whitelist = valueOrErrorMessage(getString(configProvider, whitelistKey), "no whitelistKey")
148+let whitelist = confS(WLISTK, "no 9")
98149
99150 func allowed (a) = if ((whitelist == ""))
100151 then true
101152 else isDefined(indexOf(whitelist, toString(a)))
102153
103154
104-let poolMain = valueOrErrorMessage(getInteger(this, poolMainTokenValueKey), "no poolMainTokenValueKey")
155+let poolMain = localI(POOLUSDNK, "no")
105156
106-let poolUp = valueOrErrorMessage(getInteger(this, poolUpKey), "no poolUpKey")
157+let poolUp = localI(POOLUPK, "no 10")
107158
108-let poolDwn = valueOrErrorMessage(getInteger(this, poolDwnKey), "no poolDwnKey")
159+let poolDwn = localI(POOLDWNK, "no 11")
109160
110-let poolToken = valueOrErrorMessage(getString(this, poolTokenKey), "no poolTokenKey")
161+let poolToken = localS(POOLK, "no 12")
111162
112-let poolTokenCirculation = valueOrErrorMessage(getInteger(this, poolTokenCirculationKey), "no poolTokenCirculationKey")
163+let poolTokenCirculation = localI(POOLCIRCK, "no 13")
113164
114-let poolValue = ((poolMain + fraction(bullCol, poolUp, bullCirc)) + fraction(bearCol, poolDwn, bearCirc))
165+let poolBullExposure = fraction(bullCol, poolUp, bullCirc)
166+
167+let poolBearExposure = fraction(bearCol, poolDwn, bearCirc)
168+
169+let poolValue = ((poolMain + poolBullExposure) + poolBearExposure)
115170
116171 let oracle = valueOrErrorMessage(addressFromPublicKey(fromBase58String(valueOrErrorMessage(getString(this, oraclePKKey), "no oraclePKKey"))), "bad oracle address")
117172
118-let rebalancedPriceIndex = valueOrErrorMessage(getInteger(this, lastRebalancePriceIndexKey), "no last rebalance price")
173+let rebalancedPriceIndex = valueOrErrorMessage(getInteger(this, REBIDXK), "no last rebalance price")
119174
120-let oraclePriceIndex = valueOrErrorMessage(getInteger(oracle, lastPriceIndexKey), ((("bad oracle data at " + toString(oracle)) + ": no integer at ") + lastPriceIndexKey))
175+let oraclePriceIndex = valueOrErrorMessage(getInteger(oracle, lastPriceIndexKey(assetName)), ((("bad oracle data at " + toString(oracle)) + ": no integer at ") + lastPriceIndexKey(assetName)))
121176
122-let queueSize = valueOrElse(getInteger(this, queueSizeKey), 0)
177+let leverage = valueOrElse(getInteger(this, LEVK), 3)
123178
124-let headPointer = valueOrElse(getString(this, headPointerKey), "")
179+func heightByIndex (assetName,priceIndex) = valueOrErrorMessage(getInteger(oracle, (priceIndexPrefix(assetName) + toString(priceIndex))), ("no data at index " + toString(priceIndex)))
125180
126-let tailPointer = valueOrElse(getString(this, tailPointerKey), "")
127181
128-let feesAccumulated = valueOrElse(getInteger(this, feesAccumulatedKey), 0)
182+func priceByHeight (assetName,priceHeight) = valueOrErrorMessage(getInteger(oracle, (priceHeightPrefix(assetName) + toString(priceHeight))), ("no data for height " + toString(priceHeight)))
183+
184+
185+func priceByIndex (assetName,priceIndex) = priceByHeight(assetName, heightByIndex(assetName, priceIndex))
186+
187+
188+let queueSize = valueOrElse(getInteger(this, QSIZEK), 0)
189+
190+let headPointer = valueOrElse(getString(this, HEADK), "")
191+
192+let tailPointer = valueOrElse(getString(this, TAILK), "")
193+
194+let feesAccumulated = valueOrElse(getInteger(this, FEEACCK), 0)
129195
130196 let ISSUE = "ISSUE"
131197
132198 let REDEEM = "REDEEM"
133199
134200 let POOL = "POOL"
135201
136202 let UNPOOL = "UNPOOL"
137203
138204 let feeAddrKey = "feeAddress"
139205
140206 let stakingAddrKey = "stakingAddress"
141207
142208 let daemonPubKeyKey = "daemonPublicKey"
143209
144-let feeAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configProvider, feeAddrKey), "no feeAddress")), "bad feeAddress")
210+let feeAddress = valueOrErrorMessage(addressFromString(confS(feeAddrKey, "no feeAddress")), "bad feeAddress")
145211
146-let stakingAddress = valueOrErrorMessage(getString(configProvider, stakingAddrKey), "no stakingAddress")
212+let stakingAddress = confS(stakingAddrKey, "no stakingAddress")
147213
148-let daemonPublicKey = fromBase58String(valueOrErrorMessage(getString(configProvider, daemonPubKeyKey), "no daemonPublicKey"))
214+let daemonPublicKey = fromBase58String(confS(daemonPubKeyKey, "no daemonPublicKey"))
149215
150216 let rpdAddress = addressFromString("3PNikM6yp4NqcSU8guxQtmR5onr2D4e8yTJ")
151217
152-let pubKeyAdminsList = ["2HHqV8W9DJayV5R6tBD2Sb8srphpoboDi7r1t1aPiumC", "5ZXe82RRASU7qshXM2J9JNYhqJ9GWYjjVq2gwUV5Naz9", "5WRXFSjwcTbNfKcJs8ZqXmSSWYsSVJUtMvMqZj5hH4Nc"]
218+let admins = ["2HHqV8W9DJayV5R6tBD2Sb8srphpoboDi7r1t1aPiumC", "5ZXe82RRASU7qshXM2J9JNYhqJ9GWYjjVq2gwUV5Naz9", "5WRXFSjwcTbNfKcJs8ZqXmSSWYsSVJUtMvMqZj5hH4Nc"]
153219
154-func safeFraction (a,b,c) = if (if ((a == 0))
155- then true
156- else (b == 0))
157- then 0
158- else fraction(a, b, c)
220+func buildNewItem (action,amt,token,priceIndex,invoker,minPayout,maxPayout) = (((((((((((((action + "|") + toString(amt)) + "|") + token) + "|") + toString(priceIndex)) + "|") + invoker) + "|") + toString(minPayout)) + "|") + toString(maxPayout)) + "|")
159221
160222
161-func buildNewItem (action,amt,token,priceIndex,invoker) = (((((((((action + "|") + toString(amt)) + "|") + token) + "|") + toString(priceIndex)) + "|") + invoker) + "|")
223+func userDiffAbs () = {
224+ let $t057975886 = $Tuple2((bullCol - poolBullExposure), (bearCol - poolBearExposure))
225+ let userBullCol = $t057975886._1
226+ let userBearCol = $t057975886._2
227+ let diff = (userBullCol - userBearCol)
228+ if ((diff > 0))
229+ then diff
230+ else (0 - diff)
231+ }
162232
163233
164234 func maxIssue (tokenId) = {
165235 let poolInvestment = if ((poolUp > 0))
166236 then BULL
167237 else BEAR
168- if ((poolInvestment == tokenId))
238+ if ((tokenId != poolInvestment))
169239 then poolMain
170- else ((2 * poolValue) - poolMain)
240+ else (userDiffAbs() + poolValue)
171241 }
242+
243+
244+func validatePMFee (i,minPayout) = if ((0 > minPayout))
245+ then throw("negative min payout")
246+ else {
247+ let p = i.payments[1]
248+ let ok = match p.assetId {
249+ case bv: ByteVector =>
250+ if ((toBase58String(bv) == mainToken))
251+ then (p.amount >= minUsdnFee)
252+ else false
253+ case waves: Unit =>
254+ (p.amount >= minWavesFee)
255+ case _ =>
256+ throw("Match error")
257+ }
258+ if (!(ok))
259+ then throw("incorrect pacemaker fee")
260+ else true
261+ }
172262
173263
174264 func validateRequestRedeem (inv) = if ((inv.caller == this))
175265 then throw("can't do")
176266 else {
177- func errorMessage (got) = throw(((((("only BULL(" + BULL) + ") or BEAR(") + BEAR) + ") tokens are accepted, received: ") + got))
267+ func errorMessage (got) = throw(((((("bad token att: only BULL(" + BULL) + ") or BEAR(") + BEAR) + ") tokens are accepted, received: ") + got))
178268
179- let assetId = toBase58String(valueOrErrorMessage(value(inv.payments[0]).assetId, "waves are not accepted here"))
269+ let assetId = toBase58String(valueOrErrorMessage(value(inv.payments[0]).assetId, "bad token att"))
180270 if (if ((assetId != BEAR))
181271 then (assetId != BULL)
182272 else false)
183273 then errorMessage(assetId)
184274 else {
185275 let attachedAmount = inv.payments[0].amount
186276 let col = if ((assetId == BEAR))
187277 then bearCol
188278 else bullCol
189279 let circ = if ((assetId == BEAR))
190280 then bearCirc
191281 else bullCirc
192282 let estimated = fraction(col, attachedAmount, circ)
193283 if ((minRedeem > estimated))
194284 then throw((((((((((("Attached payment too small. Min redeem amount is " + toString((minRedeem / 1000000))) + " USDN, ") + "attached amount: ") + toString(attachedAmount)) + ", col: ") + toString(col)) + ", circ: ") + toString(circ)) + ", estimated: ") + toString(estimated)))
195285 else unit
196286 }
197287 }
198288
199289
200-func enqueue (id,action,amt,token,priceIndex,invoker) = {
201- let increaseQueueSize = IntegerEntry(queueSizeKey, (queueSize + 1))
202- let itm = buildNewItem(action, amt, token, priceIndex, invoker)
290+func enqueue (id,action,amt,token,priceIndex,invoker,minPayout,maxPayout) = {
291+ let increaseQueueSize = IE(QSIZEK, (queueSize + 1))
292+ let itm = buildNewItem(action, amt, token, priceIndex, invoker, minPayout, maxPayout)
203293 if ((queueSize == 0))
204- then [StringEntry(headPointerKey, id), StringEntry(tailPointerKey, id), StringEntry(id, itm), increaseQueueSize]
294+ then [SE(HEADK, id), SE(TAILK, id), SE(id, itm), increaseQueueSize]
205295 else {
206- let prevId = valueOrErrorMessage(getString(this, tailPointerKey), "can't get tail pointer")
207- let prevItm = split(valueOrErrorMessage(getString(this, prevId), "can't resolve pointer"), "|")
208- let updatedPrevItm = ((((((((((prevItm[0] + "|") + prevItm[1]) + "|") + prevItm[2]) + "|") + prevItm[3]) + "|") + prevItm[4]) + "|") + id)
209-[StringEntry(prevId, updatedPrevItm), StringEntry(id, itm), StringEntry(tailPointerKey, id), increaseQueueSize]
296+ let prevId = localS(TAILK, "can't get tail pointer")
297+ let prevItm = localS(prevId, "can't resolve pointer")
298+ let updatedPrevItm = (prevItm + id)
299+[SE(prevId, updatedPrevItm), SE(id, itm), SE(TAILK, id), increaseQueueSize]
210300 }
211301 }
212302
213303
214304 func poolSupport (curBullCol0,curBearCol0,curBullCirc0,curBearCirc0,curPoolMain0,curPoolUp0,curPoolDwn0) = {
215- func closeUp (curBullCol,curBearCol,curBullCirc,curBearCirc,curPoolMain,curPoolUp,curPoolDwn) = {
216- let diff = (curBullCol - curBearCol)
217- let exposure = fraction(curBullCol, curPoolUp, curBullCirc)
218- let liquidatedTokens = if ((diff > exposure))
219- then curPoolUp
220- else fraction(diff, curBullCirc, curBullCol)
221- let liquidatedValue = if ((diff > exposure))
222- then exposure
223- else fraction(liquidatedTokens, curBullCol, curBullCirc)
224- $Tuple7((curBullCol - liquidatedValue), curBearCol, (curBullCirc - liquidatedTokens), curBearCirc, (curPoolMain + liquidatedValue), (curPoolUp - liquidatedTokens), curPoolDwn)
305+ func closeUp (c1,c2,a0,a1,c0,pu,pd) = {
306+ let diff = (c1 - c2)
307+ let exp = fraction(c1, pu, a0)
308+ let liquidatedTokens = if ((diff > exp))
309+ then pu
310+ else fraction(diff, a0, c1)
311+ let liquidatedValue = if ((diff > exp))
312+ then exp
313+ else fraction(liquidatedTokens, c1, a0)
314+ $Tuple7((c1 - liquidatedValue), c2, (a0 - liquidatedTokens), a1, (c0 + liquidatedValue), (pu - liquidatedTokens), pd)
225315 }
226316
227- func closeDwn (curBullCol,curBearCol,curBullCirc,curBearCirc,curPoolMain,curPoolUp,curPoolDwn) = {
228- let diff = (curBearCol - curBullCol)
229- let exposure = fraction(curBearCol, curPoolDwn, curBearCirc)
230- let liquidatedTokens = if ((diff > exposure))
231- then curPoolDwn
232- else fraction(diff, curBearCirc, curBearCol)
233- let liquidatedValue = if ((diff > exposure))
234- then exposure
235- else fraction(liquidatedTokens, curBearCol, curBearCirc)
236- $Tuple7(curBullCol, (curBearCol - liquidatedValue), curBullCirc, (curBearCirc - liquidatedTokens), (curPoolMain + liquidatedValue), curPoolUp, (curPoolDwn - liquidatedTokens))
317+ func closeDwn (c1,c2,a0,a1,c0,pu,pd) = {
318+ let diff = (c2 - c1)
319+ let exp = fraction(c2, pd, a1)
320+ let liquidatedTokens = if ((diff > exp))
321+ then pd
322+ else fraction(diff, a1, c2)
323+ let liquidatedValue = if ((diff > exp))
324+ then exp
325+ else fraction(liquidatedTokens, c2, a1)
326+ $Tuple7(c1, (c2 - liquidatedValue), a0, (a1 - liquidatedTokens), (c0 + liquidatedValue), pu, (pd - liquidatedTokens))
237327 }
238328
239- func openDwn (curBullCol,curBearCol,curBullCirc,curBearCirc,curPoolMain,curPoolUp,curPoolDwn) = {
240- let diff = (curBullCol - curBearCol)
241- let spentPoolValue = if ((curPoolMain > diff))
329+ func openDwn (c1,c2,a0,a1,c0,pu,pd) = {
330+ let diff = (c1 - c2)
331+ let spentPoolValue = if ((c0 > diff))
242332 then diff
243- else curPoolMain
244- let acquiredTokens = fraction(spentPoolValue, curBearCirc, curBearCol)
245- $Tuple7(curBullCol, (curBearCol + spentPoolValue), curBullCirc, (curBearCirc + acquiredTokens), (curPoolMain - spentPoolValue), curPoolUp, (curPoolDwn + acquiredTokens))
333+ else c0
334+ let acquiredTokens = fraction(spentPoolValue, a1, c2)
335+ $Tuple7(c1, (c2 + spentPoolValue), a0, (a1 + acquiredTokens), (c0 - spentPoolValue), pu, (pd + acquiredTokens))
246336 }
247337
248- func openUp (curBullCol,curBearCol,curBullCirc,curBearCirc,curPoolMain,curPoolUp,curPoolDwn) = {
249- let diff = (curBearCol - curBullCol)
250- let spentPoolValue = if ((curPoolMain > diff))
338+ func openUp (c1,c2,a0,a1,c0,pu,pd) = {
339+ let diff = (c2 - c1)
340+ let spentPoolValue = if ((c0 > diff))
251341 then diff
252- else curPoolMain
253- let acquiredTokens = fraction(spentPoolValue, curBullCirc, curBullCol)
254- $Tuple7((curBullCol + spentPoolValue), curBearCol, (curBullCirc + acquiredTokens), curBearCirc, (curPoolMain - spentPoolValue), (curPoolUp + acquiredTokens), curPoolDwn)
342+ else c0
343+ let acquiredTokens = fraction(spentPoolValue, a0, c1)
344+ $Tuple7((c1 + spentPoolValue), c2, (a0 + acquiredTokens), a1, (c0 - spentPoolValue), (pu + acquiredTokens), pd)
255345 }
256346
257- if ((curBullCol0 > curBearCol0))
347+ let $t01025511290 = if ((curBullCol0 > curBearCol0))
258348 then {
259349 let afterCloseUp = closeUp(curBullCol0, curBearCol0, curBullCirc0, curBearCirc0, curPoolMain0, curPoolUp0, curPoolDwn0)
260- let $t01028610423 = afterCloseUp
261- let a = $t01028610423._1
262- let b = $t01028610423._2
263- let c = $t01028610423._3
264- let d = $t01028610423._4
265- let e = $t01028610423._5
266- let f = $t01028610423._6
267- let g = $t01028610423._7
350+ let $t01048110618 = afterCloseUp
351+ let a = $t01048110618._1
352+ let b = $t01048110618._2
353+ let c = $t01048110618._3
354+ let d = $t01048110618._4
355+ let e = $t01048110618._5
356+ let f = $t01048110618._6
357+ let g = $t01048110618._7
268358 if ((f > 0))
269359 then afterCloseUp
270360 else if ((f == 0))
271361 then openDwn(a, b, c, d, e, f, g)
272362 else throw("poolUp < 0")
273363 }
274364 else {
275365 let afterCloseDwn = closeDwn(curBullCol0, curBearCol0, curBullCirc0, curBearCirc0, curPoolMain0, curPoolUp0, curPoolDwn0)
276- let $t01077410914 = afterCloseDwn
277- let a = $t01077410914._1
278- let b = $t01077410914._2
279- let c = $t01077410914._3
280- let d = $t01077410914._4
281- let e = $t01077410914._5
282- let f = $t01077410914._6
283- let g = $t01077410914._7
366+ let $t01096911109 = afterCloseDwn
367+ let a = $t01096911109._1
368+ let b = $t01096911109._2
369+ let c = $t01096911109._3
370+ let d = $t01096911109._4
371+ let e = $t01096911109._5
372+ let f = $t01096911109._6
373+ let g = $t01096911109._7
284374 if ((g > 0))
285375 then afterCloseDwn
286376 else if ((g == 0))
287377 then openUp(a, b, c, d, e, f, g)
288378 else throw("poolDwn < 0")
289379 }
380+ let c1 = $t01025511290._1
381+ let c2 = $t01025511290._2
382+ let a0 = $t01025511290._3
383+ let a1 = $t01025511290._4
384+ let c0 = $t01025511290._5
385+ let pu = $t01025511290._6
386+ let pd = $t01025511290._7
387+ let charge = fraction(userDiffAbs(), rebalancePercentile, ((1440 * 100) * 100))
388+ let percentileActivated = (height >= valueOrElse(getInteger(configProvider, "percentileActivationHeight"), 10000000))
389+ let c1SplitP = if (if (percentileActivated)
390+ then (pd > 0)
391+ else false)
392+ then charge
393+ else 0
394+ let c2SplitP = if (if (percentileActivated)
395+ then (pu > 0)
396+ else false)
397+ then charge
398+ else 0
399+ $Tuple7((c1 - c1SplitP), (c2 - c2SplitP), a0, a1, ((c0 + c1SplitP) + c2SplitP), pu, pd)
290400 }
291401
292402
293-func actionsWithMaybePool (curBullCol0,curBearCol0,curBullCirc0,curBearCirc0) = {
294- let $t01121111394 = poolSupport(curBullCol0, curBearCol0, curBullCirc0, curBearCirc0, poolMain, poolUp, poolDwn)
295- let bullCol1 = $t01121111394._1
296- let bearCol1 = $t01121111394._2
297- let bullCic1 = $t01121111394._3
298- let bearCirc1 = $t01121111394._4
299- let poolMain1 = $t01121111394._5
300- let poolUp1 = $t01121111394._6
301- let poolDwn1 = $t01121111394._7
302-[IntegerEntry(bullCollateralKey, bullCol1), IntegerEntry(bullCirculationKey, bullCic1), IntegerEntry(bearCollateralKey, bearCol1), IntegerEntry(bearCirculationKey, bearCirc1), IntegerEntry(poolMainTokenValueKey, poolMain1), IntegerEntry(poolUpKey, poolUp1), IntegerEntry(poolDwnKey, poolDwn1)]
403+func poolSup (curBullCol0,curBearCol0,curBullCirc0,curBearCirc0) = {
404+ let $t01187112053 = poolSupport(curBullCol0, curBearCol0, curBullCirc0, curBearCirc0, poolMain, poolUp, poolDwn)
405+ let bullCol1 = $t01187112053._1
406+ let bearCol1 = $t01187112053._2
407+ let bullCic1 = $t01187112053._3
408+ let bearCirc1 = $t01187112053._4
409+ let poolMain1 = $t01187112053._5
410+ let poolUp1 = $t01187112053._6
411+ let poolDwn1 = $t01187112053._7
412+[IE(BULLCOLK, bullCol1), IE(BULLCIRCK, bullCic1), IE(BEARCOLK, bearCol1), IE(BEARCIRCK, bearCirc1), IE(POOLUSDNK, poolMain1), IE(POOLUPK, poolUp1), IE(POOLDWNK, poolDwn1)]
303413 }
304414
305415
306-func dequeue () = if ((queueSize == 0))
307- then throw("nothing to settle")
308- else {
309- func collectFee (fees) = IntegerEntry(feesAccumulatedKey, (feesAccumulated + fees))
416+func dequeue () = {
417+ func sp (a,mx) = if ((mx >= a))
418+ then $Tuple2(a, 0)
419+ else $Tuple2(mx, (a - mx))
310420
311- let decreaseQueueSize = IntegerEntry(queueSizeKey, (queueSize - 1))
312- let isLastElement = (headPointer == tailPointer)
313- let overwriteTail = StringEntry(tailPointerKey, "")
314- let data = split(valueOrErrorMessage(getString(this, headPointer), "bad head pointer"), "|")
315- let action = data[0]
316- let amt = parseIntValue(data[1])
317- let token = data[2]
318- let priceIndex = parseIntValue(data[3])
319- let invoker = addressFromStringValue(data[4])
320- let next = data[5]
321- let items = if ((rebalancedPriceIndex > priceIndex))
322- then throw(((("corrupt state, rebalancedPriceIndex=" + toString(rebalancedPriceIndex)) + ", request price id=") + toString(priceIndex)))
323- else if ((priceIndex > rebalancedPriceIndex))
324- then throw("can't dequeue, too early, rebalance first")
325- else if ((action == ISSUE))
326- then {
327- let feeSize = fraction(amt, issuePercentile, 10000)
328- let addedCollateral = (amt - feeSize)
329- if ((token == BULL))
421+ if ((queueSize == 0))
422+ then throw("nothing to settle")
423+ else {
424+ func collectFee (fees) = IE(FEEACCK, (feesAccumulated + fees))
425+
426+ let decreaseQueueSize = IE(QSIZEK, (queueSize - 1))
427+ let isLastElement = (headPointer == tailPointer)
428+ let overwriteTail = SE(TAILK, "")
429+ let dataStr = localS(headPointer, "bad head pointer(dequeue)")
430+ let data = split(dataStr, "|")
431+ let action = data[0]
432+ let amt = parseIntValue(data[1])
433+ let token = data[2]
434+ let priceIndex = parseIntValue(data[3])
435+ let invoker = addressFromStringValue(data[4])
436+ let minPayout = if ((8 > size(data)))
437+ then 0
438+ else parseIntValue(data[5])
439+ let maxPayout = if ((8 > size(data)))
440+ then MAX
441+ else parseIntValue(data[6])
442+ let next = data[(size(data) - 1)]
443+ func payback (tkn) = [SE(HEADK, next), decreaseQueueSize, ST(invoker, amt, fromBase58String(tkn))]
444+
445+ let items = if ((rebalancedPriceIndex > priceIndex))
446+ then throw(((("corrupt state, rebalancedPriceIndex=" + toString(rebalancedPriceIndex)) + ", request price id=") + toString(priceIndex)))
447+ else if ((priceIndex > rebalancedPriceIndex))
448+ then throw("can't dequeue, too early, rebalance first")
449+ else if ((action == ISSUE))
450+ then {
451+ let feeSize = fraction(amt, issuePercentile, 10000)
452+ let addedCollateral = (amt - feeSize)
453+ let a = if ((token == BULL))
454+ then fraction(bullCirc, addedCollateral, bullCol)
455+ else if ((token == BEAR))
456+ then fraction(bearCirc, addedCollateral, bearCol)
457+ else throw("bad token id")
458+ let $t01416714223 = sp(a, maxPayout)
459+ let addedToCirculation = $t01416714223._1
460+ let extraTokens = $t01416714223._2
461+ let $t01424014411 = if ((token == BULL))
462+ then $Tuple4(addedToCirculation, addedCollateral, 0, 0)
463+ else $Tuple4(0, 0, addedToCirculation, addedCollateral)
464+ let plusBulls = $t01424014411._1
465+ let plusBullCol = $t01424014411._2
466+ let plusBears = $t01424014411._3
467+ let plusBearCol = $t01424014411._4
468+ if ((minPayout > addedToCirculation))
469+ then payback(mainToken)
470+ else (poolSup((bullCol + plusBullCol), (bearCol + plusBearCol), (bullCirc + plusBulls), (bearCirc + plusBears)) ++ [SE(HEADK, next), collectFee(feeSize), decreaseQueueSize, ST(invoker, addedToCirculation, fromBase58String(token)), ST(feeAddress, extraTokens, fromBase58String(token))])
471+ }
472+ else if ((action == REDEEM))
330473 then {
331- let addedToCirculation = fraction(bullCirc, addedCollateral, bullCol)
332- (actionsWithMaybePool((bullCol + addedCollateral), bearCol, (bullCirc + addedToCirculation), bearCirc) ++ [StringEntry(headPointerKey, next), collectFee(feeSize), decreaseQueueSize, ScriptTransfer(invoker, addedToCirculation, fromBase58String(BULL))])
474+ let removedTokens = amt
475+ let calcPo = if ((token == BULL))
476+ then fraction(bullCol, removedTokens, bullCirc)
477+ else if ((token == BEAR))
478+ then fraction(bearCol, removedTokens, bearCirc)
479+ else throw("bad token id")
480+ let $t01532615375 = sp(calcPo, maxPayout)
481+ let payoutCapped = $t01532615375._1
482+ let extra = $t01532615375._2
483+ let feeSize = fraction(payoutCapped, redeemPercentile, 10000)
484+ let payout = if ((payoutCapped > feeSize))
485+ then (payoutCapped - feeSize)
486+ else 0
487+ let $t01556115720 = if ((token == BULL))
488+ then $Tuple4(removedTokens, payoutCapped, 0, 0)
489+ else $Tuple4(0, 0, removedTokens, payoutCapped)
490+ let minusBulls = $t01556115720._1
491+ let minusBullCol = $t01556115720._2
492+ let minusBears = $t01556115720._3
493+ let minusBearCol = $t01556115720._4
494+ if ((minPayout > payout))
495+ then payback(token)
496+ else (poolSup((bullCol - minusBullCol), (bearCol - minusBearCol), (bullCirc - minusBulls), (bearCirc - minusBears)) ++ [SE(HEADK, next), collectFee(feeSize), decreaseQueueSize, ST(invoker, payout, fromBase58String(mainToken)), ST(feeAddress, extra, fromBase58String(mainToken))])
333497 }
334- else if ((token == BEAR))
498+ else if ((action == POOL))
335499 then {
336- let addedToCirculation = fraction(bearCirc, addedCollateral, bearCol)
337- (actionsWithMaybePool(bullCol, (bearCol + addedCollateral), bullCirc, (bearCirc + addedToCirculation)) ++ [StringEntry(headPointerKey, next), collectFee(feeSize), decreaseQueueSize, ScriptTransfer(invoker, addedToCirculation, fromBase58String(BEAR))])
500+ let issueTokens = fraction(poolTokenCirculation, amt, poolValue)
501+ if ((minPayout > issueTokens))
502+ then payback(mainToken)
503+ else [IE(POOLUSDNK, (poolMain + amt)), IE(POOLCIRCK, (poolTokenCirculation + issueTokens)), SE(HEADK, next), decreaseQueueSize, ST(invoker, issueTokens, fromBase58String(poolToken))]
338504 }
339- else throw("bad token id")
340- }
341- else if ((action == REDEEM))
342- then {
343- let removedTokens = amt
344- if ((token == BULL))
345- then {
346- let removedCollateral = fraction(bullCol, removedTokens, bullCirc)
347- let feeSize = fraction(removedCollateral, redeemPercentile, 10000)
348- let payout = if ((removedCollateral > feeSize))
349- then (removedCollateral - feeSize)
350- else 0
351- (actionsWithMaybePool((bullCol - removedCollateral), bearCol, (bullCirc - removedTokens), bearCirc) ++ [StringEntry(headPointerKey, next), collectFee(feeSize), decreaseQueueSize, ScriptTransfer(invoker, payout, fromBase58String(mainToken))])
352- }
353- else if ((token == BEAR))
505+ else if ((action == UNPOOL))
354506 then {
355- let removedCollateral = fraction(bearCol, removedTokens, bearCirc)
356- let feeSize = fraction(removedCollateral, redeemPercentile, 10000)
357- let payout = if ((removedCollateral > feeSize))
358- then (removedCollateral - feeSize)
359- else 0
360- (actionsWithMaybePool(bullCol, (bearCol - removedCollateral), bullCirc, (bearCirc - removedTokens)) ++ [StringEntry(headPointerKey, next), collectFee(feeSize), decreaseQueueSize, ScriptTransfer(invoker, payout, fromBase58String(mainToken))])
507+ func share (a) = fraction(a, amt, poolTokenCirculation)
508+
509+ let unpooledMain = share(poolMain)
510+ let unpooledUp = share(poolUp)
511+ let unpooledDwn = share(poolDwn)
512+ let unpooledUpValue = fraction(unpooledUp, bullCol, bullCirc)
513+ let unpooledDwnValue = fraction(unpooledDwn, bearCol, bearCirc)
514+ let totalUnpooledValue = ((unpooledMain + unpooledUpValue) + unpooledDwnValue)
515+ if ((minPayout > totalUnpooledValue))
516+ then payback(poolToken)
517+ else [IE(POOLUSDNK, (poolMain - unpooledMain)), IE(POOLCIRCK, (poolTokenCirculation - amt)), IE(POOLUPK, (poolUp - unpooledUp)), IE(POOLDWNK, (poolDwn - unpooledDwn)), IE(BULLCIRCK, (bullCirc - unpooledUp)), IE(BEARCIRCK, (bearCirc - unpooledDwn)), IE(BULLCOLK, (bullCol - unpooledUpValue)), IE(BEARCOLK, (bearCol - unpooledDwnValue)), SE(HEADK, next), decreaseQueueSize, ST(invoker, totalUnpooledValue, fromBase58String(mainToken))]
361518 }
362- else throw("bad token id")
363- }
364- else if ((action == POOL))
365- then {
366- let issueTokens = fraction(poolTokenCirculation, amt, poolValue)
367-[IntegerEntry(poolMainTokenValueKey, (poolMain + amt)), IntegerEntry(poolTokenCirculationKey, (poolTokenCirculation + issueTokens)), StringEntry(headPointerKey, next), decreaseQueueSize, ScriptTransfer(invoker, issueTokens, fromBase58String(poolToken))]
368- }
369- else if ((action == UNPOOL))
370- then {
371- func share (a) = fraction(a, amt, poolTokenCirculation)
372-
373- let unpooledMain = share(poolMain)
374- let unpooledUp = share(poolUp)
375- let unpooledDwn = share(poolDwn)
376- let unpooledUpValue = fraction(unpooledUp, bullCol, bullCirc)
377- let unpooledDwnValue = fraction(unpooledDwn, bearCol, bearCirc)
378-[IntegerEntry(poolMainTokenValueKey, (poolMain - unpooledMain)), IntegerEntry(poolTokenCirculationKey, (poolTokenCirculation - amt)), IntegerEntry(poolUpKey, (poolUp - unpooledUp)), IntegerEntry(poolDwnKey, (poolDwn - unpooledDwn)), IntegerEntry(bullCirculationKey, (bullCirc - unpooledUp)), IntegerEntry(bearCirculationKey, (bearCirc - unpooledDwn)), IntegerEntry(bullCollateralKey, (bullCol - unpooledUpValue)), IntegerEntry(bearCollateralKey, (bearCol - unpooledDwnValue)), StringEntry(headPointerKey, next), decreaseQueueSize, ScriptTransfer(invoker, ((unpooledMain + unpooledUpValue) + unpooledDwnValue), fromBase58String(mainToken))]
379- }
380- else throw(("bad action: " + action))
381- if (isLastElement)
382- then overwriteTail :: items
383- else items
384- }
519+ else throw(("bad action: " + action))
520+ if (isLastElement)
521+ then overwriteTail :: items
522+ else items
523+ }
524+ }
385525
386526
387527 func rebalance () = {
388- func LV (v,p0,p1) = {
389- let denom = 100
528+ func LV (v,p0,p1,m) = {
529+ let denom = {
530+ let md = (((2 * (if ((p1 > p0))
531+ then p1
532+ else p0)) * m) / 3037000499)
533+ if ((10 > md))
534+ then 10
535+ else if ((100 > md))
536+ then 100
537+ else 1000
538+ }
390539 let pmax = ((if ((p1 > p0))
391540 then p1
392541 else p0) / denom)
393542 let pmin = ((if ((p0 > p1))
394543 then p1
395544 else p0) / denom)
396545 let a = (pmin * pmin)
397- let b = (((9 * pmax) * pmax) - ((15 * pmax) * pmin))
398- fraction(v, ((6 * a) + b), ((7 * a) + b))
546+ let b = ((((m * m) * pmax) * pmax) - (((((2 * m) * m) - m) * pmax) * pmin))
547+ let ma = ((m * m) - m)
548+ fraction(v, ((ma * a) + b), (((ma + 1) * a) + b))
399549 }
400550
401- let settledPriceIndex = valueOrErrorMessage(getInteger(this, lastRebalancePriceIndexKey), "inconsistent data")
551+ let settledPriceIndex = valueOrErrorMessage(getInteger(this, REBIDXK), "inconsistent data")
402552 let unsettledPriceIndex = (settledPriceIndex + 1)
403- let settledPriceHeight = valueOrErrorMessage(getInteger(oracle, ("price_index_" + toString(settledPriceIndex))), "bad oracle data for settled price height")
404- let settledPrice = valueOrErrorMessage(getInteger(oracle, ("price_" + toString(settledPriceHeight))), "bad oracle data for price")
405- let nextPriceHeight = valueOrErrorMessage(getInteger(oracle, ("price_index_" + toString(unsettledPriceIndex))), "no next price height")
406- let nextPrice = valueOrErrorMessage(getInteger(oracle, ("price_" + toString(nextPriceHeight))), "no next price")
553+ let settledPrice = priceByIndex(assetName, settledPriceIndex)
554+ let nextPrice = priceByIndex(assetName, unsettledPriceIndex)
407555 let minVol = if ((bearCol > bullCol))
408556 then bullCol
409557 else bearCol
410- let redist = LV(minVol, settledPrice, nextPrice)
411- let newBullCol = if ((nextPrice > settledPrice))
558+ let redist = LV(minVol, settledPrice, nextPrice, leverage)
559+ let priceUpGoodForBulls = (assetName == "")
560+ let priceGoesUp = (nextPrice > settledPrice)
561+ let bullsEarn = (priceUpGoodForBulls == priceGoesUp)
562+ let newBullCol = if (bullsEarn)
412563 then (bullCol + redist)
413564 else (bullCol - redist)
414- let newBearCol = if ((nextPrice > settledPrice))
565+ let newBearCol = if (bullsEarn)
415566 then (bearCol - redist)
416567 else (bearCol + redist)
417- let $t01926019447 = poolSupport(newBullCol, newBearCol, bullCirc, bearCirc, poolMain, poolUp, poolDwn)
418- let updBullCol = $t01926019447._1
419- let updBearCol = $t01926019447._2
420- let updBullCirc = $t01926019447._3
421- let updBearCirc = $t01926019447._4
422- let updPoolMain = $t01926019447._5
423- let updPoolUp = $t01926019447._6
424- let updPoolDwn = $t01926019447._7
425-[IntegerEntry(bullCollateralKey, updBullCol), IntegerEntry(bearCollateralKey, updBearCol), IntegerEntry(bullCirculationKey, updBullCirc), IntegerEntry(bearCirculationKey, updBearCirc), IntegerEntry(poolMainTokenValueKey, updPoolMain), IntegerEntry(poolUpKey, updPoolUp), IntegerEntry(poolDwnKey, updPoolDwn), IntegerEntry(lastRebalancePriceIndexKey, unsettledPriceIndex)]
568+ let $t01960819794 = poolSupport(newBullCol, newBearCol, bullCirc, bearCirc, poolMain, poolUp, poolDwn)
569+ let updBullCol = $t01960819794._1
570+ let updBearCol = $t01960819794._2
571+ let updBullCirc = $t01960819794._3
572+ let updBearCirc = $t01960819794._4
573+ let updPoolMain = $t01960819794._5
574+ let updPoolUp = $t01960819794._6
575+ let updPoolDwn = $t01960819794._7
576+[IE(BULLCOLK, updBullCol), IE(BEARCOLK, updBearCol), IE(BULLCIRCK, updBullCirc), IE(BEARCIRCK, updBearCirc), IE(POOLUSDNK, updPoolMain), IE(POOLUPK, updPoolUp), IE(POOLDWNK, updPoolDwn), IE(REBIDXK, unsettledPriceIndex)]
577+ }
578+
579+
580+func calcMax (min,avg) = if ((min > avg))
581+ then throw(((("price too old: minPayout " + toString(min)) + " > avg = ") + toString(avg)))
582+ else ((avg + avg) - min)
583+
584+
585+func requestIssueInternal (inv,tokenId,minPayout) = if (if ((tokenId != BULL))
586+ then (tokenId != BEAR)
587+ else false)
588+ then throw("bad token req")
589+ else if ((inv.caller == this))
590+ then throw("can't do")
591+ else if (!(allowed(inv.caller)))
592+ then throw("only whitelisted can do")
593+ else {
594+ let errorMessage = (((("bad token req, only BULL(" + BULL) + ") or BEAR(") + BEAR) + ") allowed")
595+ if ((inv.payments[0].assetId != fromBase58String(mainToken)))
596+ then throw("bad token att")
597+ else {
598+ let amt = inv.payments[0].amount
599+ let $t02080020978 = if ((tokenId == BULL))
600+ then $Tuple2(bullCol, bullCirc)
601+ else if ((tokenId == BEAR))
602+ then $Tuple2(bearCol, bearCirc)
603+ else throw(errorMessage)
604+ let col = $t02080020978._1
605+ let circ = $t02080020978._2
606+ let est = fraction(amt, circ, col)
607+ let $t02102021114 = if ((minPayout == 0))
608+ then $Tuple2(0, MAX)
609+ else $Tuple2(minPayout, calcMax(minPayout, est))
610+ let minP = $t02102021114._1
611+ let maxP = $t02102021114._2
612+ if ((minIssue > amt))
613+ then throw((("Attached payment too small. Min required: " + toString((minIssue / 1000000))) + " USDN"))
614+ else {
615+ let maxAllowed = maxIssue(tokenId)
616+ if (if ((whitelist == ""))
617+ then (inv.payments[0].amount > maxAllowed)
618+ else false)
619+ then throw((("trying to issue more than pool can handle. Max attachment allowed = " + toString((maxAllowed / 1000000))) + " USDN"))
620+ else (enqueue(toBase58String(inv.transactionId), ISSUE, amt, tokenId, (oraclePriceIndex + 1), toString(inv.caller), minP, maxP) ++ [debug("requested", tokenId), debug("bull", BULL), debug("bear", BEAR)])
621+ }
622+ }
623+ }
624+
625+
626+func requestRedeemInternal (inv,minPayout) = {
627+ let amt = inv.payments[0].amount
628+ let tokenId = toBase58String(valueOrErrorMessage(inv.payments[0].assetId, "bad token att"))
629+ if (if ((tokenId != BULL))
630+ then (tokenId != BEAR)
631+ else false)
632+ then throw("bad token req")
633+ else {
634+ let $t02215122290 = if ((tokenId == BULL))
635+ then $Tuple2(bullCol, bullCirc)
636+ else if ((tokenId == BEAR))
637+ then $Tuple2(bearCol, bearCirc)
638+ else throw("bad token req")
639+ let col = $t02215122290._1
640+ let circ = $t02215122290._2
641+ let est = fraction(amt, col, circ)
642+ let $t02233822432 = if ((minPayout == 0))
643+ then $Tuple2(0, MAX)
644+ else $Tuple2(minPayout, calcMax(minPayout, est))
645+ let minP = $t02233822432._1
646+ let maxP = $t02233822432._2
647+ if ((validateRequestRedeem(inv) == unit))
648+ then enqueue(toBase58String(inv.transactionId), REDEEM, amt, tokenId, (oraclePriceIndex + 1), toString(inv.caller), minP, maxP)
649+ else throw("doesn't happen")
650+ }
651+ }
652+
653+
654+func requestPoolInternal (inv,minPayout) = if (!(allowed(inv.caller)))
655+ then throw("only whitelisted can do")
656+ else {
657+ let errMessage = (("main token must be attached(" + mainToken) + ")")
658+ let pmt = inv.payments[0]
659+ if ((pmt.assetId != fromBase58String(mainToken)))
660+ then throw(errMessage)
661+ else if ((minPool > pmt.amount))
662+ then throw(((("pool at least " + toString(minPool)) + " ") + mainToken))
663+ else {
664+ let estimate = fraction(poolTokenCirculation, pmt.amount, poolValue)
665+ let $t02328023379 = if ((minPayout == 0))
666+ then $Tuple2(0, MAX)
667+ else $Tuple2(minPayout, calcMax(minPayout, estimate))
668+ let minP = $t02328023379._1
669+ let maxP = $t02328023379._2
670+ enqueue(toBase58String(inv.transactionId), POOL, inv.payments[0].amount, "", (oraclePriceIndex + 1), toString(inv.caller), minP, maxP)
671+ }
672+ }
673+
674+
675+func requestUnpoolInternal (inv,minPayout) = {
676+ let errMessage = (("only pool token allowed(" + poolToken) + ")")
677+ let pmt = inv.payments[0]
678+ if ((pmt.assetId != fromBase58String(poolToken)))
679+ then throw(errMessage)
680+ else {
681+ let estimate = fraction(poolValue, pmt.amount, poolTokenCirculation)
682+ if ((minPool > estimate))
683+ then throw(((("unpool at least for" + toString(minPool)) + " ") + mainToken))
684+ else {
685+ let $t02403624135 = if ((minPayout == 0))
686+ then $Tuple2(0, MAX)
687+ else $Tuple2(minPayout, calcMax(minPayout, estimate))
688+ let minP = $t02403624135._1
689+ let maxP = $t02403624135._2
690+ enqueue(toBase58String(inv.transactionId), UNPOOL, inv.payments[0].amount, "", (oraclePriceIndex + 1), toString(inv.caller), minP, maxP)
691+ }
692+ }
426693 }
427694
428695
429696 @Callable(inv)
430-func init (config,oraclePK,nameup,namedwn,descUp,descDwn,poolName,poolDesc,denom) = if (isDefined(getString(this, BULLKey)))
697+func init (config,oraclePK,nameup,namedwn,descUp,descDwn,poolName,poolDesc,defoAssetName,denom,lev) = if (isDefined(getString(this, BULLK)))
431698 then throw("already initialized")
432699 else {
433700 let totalOwnedMainToken = inv.payments[0].amount
434701 let bulls = (totalOwnedMainToken / 3)
435702 let bears = bulls
436703 let pools = ((totalOwnedMainToken - bulls) - bears)
437704 if (if (if ((bears == 0))
438705 then true
439706 else (bulls == 0))
440707 then true
441708 else (pools == 0))
442709 then throw("can't init balances")
443710 else {
444- let oracleCurrentPriceIndex = valueOrErrorMessage(getInteger(valueOrErrorMessage(addressFromPublicKey(fromBase58String(oraclePK)), "bad oracle address"), lastPriceIndexKey), "can't find last oracle price index")
711+ let oracleCurrentPriceIndex = valueOrErrorMessage(getInteger(valueOrErrorMessage(addressFromPublicKey(fromBase58String(oraclePK)), "bad oracle address"), lastPriceIndexKey(defoAssetName)), "can't find last oracle price index")
445712 let bull = Issue(nameup, descUp, ((100 * ten6) * ten6), 6, true)
446713 let bear = Issue(namedwn, descDwn, ((100 * ten6) * ten6), 6, true)
447714 let pool = Issue(poolName, poolDesc, ((100 * ten6) * ten6), 6, true)
448715 let buid = calculateAssetId(bull)
449716 let beid = calculateAssetId(bear)
450717 let poid = calculateAssetId(pool)
451-[bull, bear, pool, StringEntry(BULLKey, toBase58String(buid)), StringEntry(BEARKey, toBase58String(beid)), StringEntry(mainTokenKey, toBase58String(value(inv.payments[0].assetId))), StringEntry(poolTokenKey, toBase58String(poid)), StringEntry(oraclePKKey, oraclePK), IntegerEntry(lastRebalancePriceIndexKey, oracleCurrentPriceIndex), IntegerEntry(bullCollateralKey, bulls), IntegerEntry(bearCollateralKey, bears), IntegerEntry(bullCirculationKey, (bulls / denom)), IntegerEntry(bearCirculationKey, (bears / denom)), IntegerEntry(poolTokenCirculationKey, (pools / denom)), IntegerEntry(poolDwnKey, 0), IntegerEntry(poolUpKey, 0), IntegerEntry(poolMainTokenValueKey, pools), StringEntry(configProviderKey, config), ScriptTransfer(inv.caller, (bulls / denom), buid), ScriptTransfer(inv.caller, (bears / denom), beid), ScriptTransfer(inv.caller, (pools / denom), poid)]
718+[bull, bear, pool, SE(BULLK, toBase58String(buid)), SE(BEARK, toBase58String(beid)), SE(USDNK, toBase58String(value(inv.payments[0].assetId))), SE(POOLK, toBase58String(poid)), SE(ASSNAMEK, defoAssetName), SE(oraclePKKey, oraclePK), IE(REBIDXK, oracleCurrentPriceIndex), IE(BULLCOLK, bulls), IE(BEARCOLK, bears), IE(BULLCIRCK, (bulls / denom)), IE(BEARCIRCK, (bears / denom)), IE(POOLCIRCK, (pools / denom)), IE(POOLDWNK, 0), IE(POOLUPK, 0), IE(POOLUSDNK, pools), SE(configProviderKey, config), IE(LEVK, lev), ST(inv.caller, (bulls / denom), buid), ST(inv.caller, (bears / denom), beid), ST(inv.caller, (pools / denom), poid)]
452719 }
453720 }
454721
455722
456723
457724 @Callable(i)
458725 func withdrawFee (amount) = if ((amount > feesAccumulated))
459726 then throw(("too much. available: " + toString(feesAccumulated)))
460- else [IntegerEntry(feesAccumulatedKey, (feesAccumulated - amount)), ScriptTransfer(feeAddress, amount, fromBase58String(mainToken))]
727+ else [IE(FEEACCK, (feesAccumulated - amount)), ST(feeAddress, amount, fromBase58String(mainToken))]
461728
462729
463730
464731 @Callable(inv)
465-func requestRedeem () = if ((validateRequestRedeem(inv) == unit))
466- then {
467- let assetId = toBase58String(valueOrErrorMessage(inv.payments[0].assetId, "waves are not accepted here"))
468- enqueue(toBase58String(inv.transactionId), REDEEM, inv.payments[0].amount, assetId, (oraclePriceIndex + 1), toString(inv.caller))
469- }
470- else throw("doesn't happen")
732+func requestRedeem () = requestRedeemInternal(inv, 0)
471733
472734
473735
474736 @Callable(inv)
475-func requestIssue (tokenId) = if ((inv.caller == this))
476- then throw("can't do")
477- else if (!(allowed(inv.caller)))
478- then throw("only whitelisted can do")
479- else {
480- let errorMessage = throw((((((("only BULL(" + BULL) + ") or BEAR(") + BEAR) + ") tokens are available in exchange for USDN(") + mainToken) + ")"))
481- if (if ((tokenId != BULL))
482- then (tokenId != BEAR)
483- else false)
484- then errorMessage
485- else if ((inv.payments[0].assetId != fromBase58String(mainToken)))
486- then errorMessage
487- else if ((minIssue > inv.payments[0].amount))
488- then throw((("Attached payment too small. Min required: " + toString((minIssue / 1000000))) + " USDN"))
489- else {
490- let maxAllowed = maxIssue(tokenId)
491- if (if ((whitelist == ""))
492- then (inv.payments[0].amount > maxAllowed)
493- else false)
494- then throw((("trying to issue more than pool can handle. Max attachment allowed = " + toString((maxAllowed / 1000000))) + " USDN"))
495- else enqueue(toBase58String(inv.transactionId), ISSUE, inv.payments[0].amount, tokenId, (oraclePriceIndex + 1), toString(inv.caller))
496- }
497- }
737+func requestRedeemSl (sl) = if (validatePMFee(inv, sl))
738+ then requestRedeemInternal(inv, sl)
739+ else throw()
740+
741+
742+
743+@Callable(inv)
744+func requestIssue (tokenId) = requestIssueInternal(inv, tokenId, 0)
745+
746+
747+
748+@Callable(inv)
749+func requestIssueSl (tokenId,sl) = if (validatePMFee(inv, sl))
750+ then requestIssueInternal(inv, tokenId, sl)
751+ else throw()
752+
753+
754+
755+@Callable(inv)
756+func requestPool () = requestPoolInternal(inv, 0)
757+
758+
759+
760+@Callable(inv)
761+func requestPoolSl (sl) = if (validatePMFee(inv, sl))
762+ then requestPoolInternal(inv, sl)
763+ else throw()
764+
765+
766+
767+@Callable(inv)
768+func requestUnpool () = requestUnpoolInternal(inv, 0)
769+
770+
771+
772+@Callable(inv)
773+func requestUnpoolSl (sl) = if (validatePMFee(inv, sl))
774+ then requestUnpoolInternal(inv, sl)
775+ else throw()
498776
499777
500778
501779 @Callable(inv)
502780 func settle () = {
503781 let queueEmpty = (headPointer == "")
504782 let canRebalance = (oraclePriceIndex > rebalancedPriceIndex)
505783 if (queueEmpty)
506784 then if (canRebalance)
507785 then rebalance()
508786 else throw("[OK] all done, carry on")
509787 else {
510- let data = split(valueOrErrorMessage(getString(this, headPointer), "bad head pointer"), "|")
788+ let data = split(valueOrErrorMessage(getString(this, headPointer), ("bad head pointer(settle): " + headPointer)), "|")
511789 let priceIndex = parseIntValue(data[3])
512790 if ((priceIndex > rebalancedPriceIndex))
513791 then if (canRebalance)
514792 then rebalance()
515793 else throw("[OK] need to wait")
516794 else if ((priceIndex == rebalancedPriceIndex))
517795 then dequeue()
518- else throw("corrupt data, future price id already rebalanced")
519- }
520- }
521-
522-
523-
524-@Callable(inv)
525-func requestPool () = if (!(allowed(inv.caller)))
526- then throw("only whitelisted can do")
527- else {
528- let errMessage = (("main token must be attached(" + mainToken) + ")")
529- let pmt = inv.payments[0]
530- if ((pmt.assetId != fromBase58String(mainToken)))
531- then throw(errMessage)
532- else if ((minPool > pmt.amount))
533- then throw(((("pool at least " + toString(minPool)) + " ") + mainToken))
534- else enqueue(toBase58String(inv.transactionId), POOL, inv.payments[0].amount, "", (oraclePriceIndex + 1), toString(inv.caller))
535- }
536-
537-
538-
539-@Callable(inv)
540-func requestUnpool () = {
541- let errMessage = (("only pool token allowed(" + poolToken) + ")")
542- let pmt = inv.payments[0]
543- if ((pmt.assetId != fromBase58String(poolToken)))
544- then throw(errMessage)
545- else {
546- let estimate = fraction(poolValue, pmt.amount, poolTokenCirculation)
547- if ((minPool > estimate))
548- then throw(((("unpool at least for" + toString(minPool)) + " ") + mainToken))
549- else enqueue(toBase58String(inv.transactionId), UNPOOL, inv.payments[0].amount, "", (oraclePriceIndex + 1), toString(inv.caller))
796+ else throw("future price already rebalanced")
550797 }
551798 }
552799
553800
554801 @Verifier(tx)
555802 func verify () = {
556- let initial = if (!(isDefined(getString(this, BULLKey))))
803+ let initial = if (!(isDefined(getString(this, BULLK))))
557804 then sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
558805 else false
559- let adminAction = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(pubKeyAdminsList[0])))
806+ let adminAction = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(admins[0])))
560807 then 1
561- else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(pubKeyAdminsList[1])))
808+ else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(admins[1])))
562809 then 1
563- else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(pubKeyAdminsList[2])))
810+ else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(admins[2])))
564811 then 1
565812 else 0)) > 1)
566813 let stakingAction = match tx {
567814 case tx: InvokeScriptTransaction =>
568815 let signedCorrectly = sigVerify(tx.bodyBytes, tx.proofs[0], daemonPublicKey)
569816 let feesCorrect = if ((tx.feeAssetId == unit))
570817 then ((1000 * 1000) >= tx.fee)
571818 else false
572819 let dappCorrect = (tx.dApp == rpdAddress)
573820 let unlock = (tx.function == "unlockNeutrino")
574821 let lock = if (if ((tx.function == "lockNeutrinoSP"))
575822 then (tx.args[0] == stakingAddress)
576823 else false)
577824 then (wavesBalance(this).available >= ten8)
578825 else false
579826 let funcCorrect = if (lock)
580827 then true
581828 else unlock
582829 if (if (if (signedCorrectly)
583830 then feesCorrect
584831 else false)
585832 then dappCorrect
586833 else false)
587834 then funcCorrect
588835 else false
589836 case _ =>
590837 false
591838 }
592839 if (if (initial)
593840 then true
594841 else adminAction)
595842 then true
596843 else stakingAction
597844 }
598845

github/deemru/w8io/786bc32 
170.50 ms