tx · 8KeJAT4FmrHhoZBhEnuqifRZDBXJ9PKZ4C1WM6RJmpDk

3P86ne9inVG1Cf4smrEGSdcXyBuEApPcMAc:  -0.00600000 Waves

2023.02.20 11:52 [3523291] smart account 3P86ne9inVG1Cf4smrEGSdcXyBuEApPcMAc > SELF 0.00000000 Waves

{ "type": 13, "id": "8KeJAT4FmrHhoZBhEnuqifRZDBXJ9PKZ4C1WM6RJmpDk", "fee": 600000, "feeAssetId": null, "timestamp": 1676883147161, "version": 1, "sender": "3P86ne9inVG1Cf4smrEGSdcXyBuEApPcMAc", "senderPublicKey": "6hjWe2YQdsZKtjcACiKTUMEGGnow19LjCF763eE2Tt91", "proofs": [ "3FNjYLCSEAkUs9izSsPdZ8nEf1ahD92XqSKtMZfesJ6jdoY4GBT5suW3B2f5KHLkt4hKrhdFuVbNDr1ayPinompP" ], "script": "base64:BgIaCAISABIDCgEIEgMKAQESAwoBCBIAEgMKAQgjARB3cml0ZUNvbnN0U3RyaW5nAgNrZXkFdmFsdWUDCQEBIQEJAQlpc0RlZmluZWQBCQCdCAIFBHRoaXMFA2tleQkBC1N0cmluZ0VudHJ5AgUDa2V5BQV2YWx1ZQkAAgEJAKwCAgIVYWxyZWFkeSBpbml0aWFsaXplZDogBQNrZXkBCHdyaXRlSW50AgNrZXkFdmFsdWUDCQBmAgAABQV2YWx1ZQkAAgEJAKwCAgkArAICCQCsAgICF3dyaXRpbmcgbmVnYXRpdmUgdmFsdWUgCQCkAwEFBXZhbHVlAgkgZm9yIGtleSAFA2tleQkBDEludGVnZXJFbnRyeQIFA2tleQUFdmFsdWUBCGNoYW5nZUJ5AgNrZXkFdmFsdWUJAQh3cml0ZUludAIFA2tleQkAZAIJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUDa2V5AAAFBXZhbHVlABJjb25maWdBZGRyZXNzU3RvcmUCBmNvbmZpZwANY29uZmlnQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQR0aGlzBRJjb25maWdBZGRyZXNzU3RvcmUCGGNvbmZpZyBhZGRyZXNzIG5vdCBmb3VuZAIWaW52YWxpZCBjb25maWcgYWRkcmVzcwEHYWxsb3dlZAECb3AJAPwHBAUNY29uZmlnQWRkcmVzcwIJb3BBbGxvd2VkCQDMCAIFAm9wBQNuaWwFA25pbAANcHdyQXNzZXRJZFN0cgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFDWNvbmZpZ0FkZHJlc3MCDHBvd2VyQXNzZXRJZAIWcHdyIGFzc2V0IGlkIG5vdCBmb3VuZAAKcHdyQXNzZXRJZAkA2QQBBQ1wd3JBc3NldElkU3RyAA5taW50ZXJDb250cmFjdAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ1jb25maWdBZGRyZXNzAg9jb250cmFjdF9taW50ZXICEm5vIGNvbnRyYWN0X21pbnRlcgIXaW52YWxpZCBtaW50ZXIgY29udHJhY3QAEHN0YWtpbmdBZGRyZXNzZXMJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUNY29uZmlnQWRkcmVzcwkArAICCQClCAEFBHRoaXMCCF9zdGFrZXJzAgAAC21pbkxvY2tUaW1lCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUNY29uZmlnQWRkcmVzcwkArAICCQClCAEFBHRoaXMCDl9taW5fbG9ja190aW1lAhVtaW5fbG9ja190aW1lIG5vdCBzZXQBD3VzZXJTaGFyZXNTdG9yZQEEdXNlcgkArAICBQR1c2VyAgdfc2hhcmVzAQtzdG9yZUhlaWdodAEFc3RvcmUJAKwCAgUFc3RvcmUCB19oZWlnaHQBC3N0YWtlSGVpZ2h0AQdhZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUEdGhpcwkBC3N0b3JlSGVpZ2h0AQkBD3VzZXJTaGFyZXNTdG9yZQEFB2FkZHJlc3MCD25vIHN0YWtlIGhlaWdodAENdW5zdGFrZUhlaWdodAEHYWRkcmVzcwkAZAIJAQtzdGFrZUhlaWdodAEFB2FkZHJlc3MFC21pbkxvY2tUaW1lAAxtaW5TZW50aW5lbHMJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQ1jb25maWdBZGRyZXNzAg1taW5fc2VudGluZWxzAhVtaW5fc2VudGluZWxzIG5vdCBzZXQACXNlbnRpbmVscwkAkAMBCQC1CQIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ1jb25maWdBZGRyZXNzAglzZW50aW5lbHMCDG5vIHNlbnRpbmVscwIBLAAIc2xhc2hlcnMJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUNY29uZmlnQWRkcmVzcwkArAICCQClCAEFBHRoaXMCCV9zbGFzaGVycwIAAAZIRUlHSFQFBmhlaWdodAARc3Rha2VkSGVpZ2h0U3RvcmUCDHN0YWtlZEhlaWdodAAQdG90YWxTaGFyZXNTdG9yZQILdG90YWxTaGFyZXMAC3N0YWtlZFN0b3JlAgZzdGFrZWQABVJCYXNlAICAhP6m3uERAANhcHIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQ1jb25maWdBZGRyZXNzCQCsAgIJAKUIAQUEdGhpcwILX3N0YWtlcl9hcHICDW5vIHN0YWtlcl9hcHIADWJsb2Nrc1BlclllYXIJAGgCCQBoAgDtAgAYADwACVJQZXJCbG9jawkAawMFA2FwcgUFUkJhc2UJAGgCAOgHBQ1ibG9ja3NQZXJZZWFyAA1jdXJyZW50U3Rha2VkBAxzdGFrZWRIZWlnaHQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwURc3Rha2VkSGVpZ2h0U3RvcmUAAAQGc3Rha2VkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFC3N0YWtlZFN0b3JlAAAEAWQJAGUCBQZIRUlHSFQFDHN0YWtlZEhlaWdodAQBcgkAZAIFBVJCYXNlCQBoAgUBZAUJUlBlckJsb2NrCQBrAwUGc3Rha2VkBQFyBQVSQmFzZQELcHdyVG9TaGFyZXMBCXB3ckFtb3VudAQLdG90YWxTaGFyZXMJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUQdG90YWxTaGFyZXNTdG9yZQAAAwkAAAIFC3RvdGFsU2hhcmVzAAAFCXB3ckFtb3VudAkAawMFCXB3ckFtb3VudAULdG90YWxTaGFyZXMFDWN1cnJlbnRTdGFrZWQBC3NoYXJlc1RvUHdyAQxzaGFyZXNBbW91bnQEC3RvdGFsU2hhcmVzCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFEHRvdGFsU2hhcmVzU3RvcmUAAAMJAAACBQt0b3RhbFNoYXJlcwAABQxzaGFyZXNBbW91bnQJAGsDBQxzaGFyZXNBbW91bnQFDWN1cnJlbnRTdGFrZWQFC3RvdGFsU2hhcmVzARBlbnN1cmVQd3JCYWxhbmNlAQZhbW91bnQECnB3ckJhbGFuY2UJAPAHAgUEdGhpcwUKcHdyQXNzZXRJZAMJAGYCBQZhbW91bnQFCnB3ckJhbGFuY2UEBG1pbnQJAPwHBAUObWludGVyQ29udHJhY3QCBG1pbnQJAMwIAgkAZQIFBmFtb3VudAUKcHdyQmFsYW5jZQUDbmlsBQNuaWwDCQAAAgUEbWludAUEbWludAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwBBnBheW91dAIEdXNlcgZhbW91bnQEBmVuc3VyZQkBEGVuc3VyZVB3ckJhbGFuY2UBBQZhbW91bnQDCQAAAgUGZW5zdXJlBQZlbnN1cmUJAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBHVzZXIFBmFtb3VudAUKcHdyQXNzZXRJZAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEGc3Rha2VkAQdhZGRyZXNzBAp1c2VyU2hhcmVzCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ91c2VyU2hhcmVzU3RvcmUBBQdhZGRyZXNzAAAJAQtzaGFyZXNUb1B3cgEFCnVzZXJTaGFyZXMBBmFkdmlzZQAEC3RvdGFsU2hhcmVzCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFEHRvdGFsU2hhcmVzU3RvcmUAAAQMdG90YWxTdGFrZWQxCQELc2hhcmVzVG9Qd3IBBQt0b3RhbFNoYXJlcwkArAICAg10b3RhbFN0YWtlZDogCQCkAwEFDHRvdGFsU3Rha2VkMQEKYWR2aXNlVXNlcgEEdXNlcgQKdXNlclNoYXJlcwkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEPdXNlclNoYXJlc1N0b3JlAQUEdXNlcgAABAlhdmFpbGFibGUJAQtzaGFyZXNUb1B3cgEFCnVzZXJTaGFyZXMEDGhlaWdodEFuZEFjYwkArAICCQCsAgIJAKwCAgIIaGVpZ2h0OiAJAKQDAQUGSEVJR0hUAgssIGFjY291bnQ6IAUEdXNlcgMJAAACBQp1c2VyU2hhcmVzAAAJAKwCAgkArAICCQCsAgIFDGhlaWdodEFuZEFjYwILLCBzdGFrZWQ6IDACEiwgc3Rha2VfaGVpZ2h0OiAtMQIULCB1bnN0YWtlX2hlaWdodDogLTEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIFDGhlaWdodEFuZEFjYwIKLCBzdGFrZWQ6IAkApAMBBQlhdmFpbGFibGUCECwgc3Rha2VfaGVpZ2h0OiAJAKQDAQkBC3N0YWtlSGVpZ2h0AQUEdXNlcgISLCB1bnN0YWtlX2hlaWdodDogCQCkAwEJAQ11bnN0YWtlSGVpZ2h0AQUEdXNlcgELc3Rha2VGb3JJbnQCB2FkZHJlc3MBcAMJAQIhPQIIBQFwB2Fzc2V0SWQFCnB3ckFzc2V0SWQJAAIBAhBpbnZhbGlkIGFzc2V0IGlkBAphZGRpdGlvbmFsCAUBcAZhbW91bnQEDHNoYXJlc0Ftb3VudAkBC3B3clRvU2hhcmVzAQUKYWRkaXRpb25hbAkAzAgCCQEId3JpdGVJbnQCBQtzdGFrZWRTdG9yZQkAZAIFDWN1cnJlbnRTdGFrZWQFCmFkZGl0aW9uYWwJAMwIAgkBCHdyaXRlSW50AgURc3Rha2VkSGVpZ2h0U3RvcmUFBkhFSUdIVAkAzAgCCQEIY2hhbmdlQnkCBRB0b3RhbFNoYXJlc1N0b3JlBQxzaGFyZXNBbW91bnQJAMwIAgkBCGNoYW5nZUJ5AgkBD3VzZXJTaGFyZXNTdG9yZQEFB2FkZHJlc3MFDHNoYXJlc0Ftb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBC3N0b3JlSGVpZ2h0AQkBD3VzZXJTaGFyZXNTdG9yZQEFB2FkZHJlc3MFBkhFSUdIVAUDbmlsBgFpAQVzdGFrZQAEAWEJAQdhbGxvd2VkAQIFc3Rha2UDCQAAAgUBYQUBYQkBC3N0YWtlRm9ySW50AgkApQgBCAUBaQZjYWxsZXIJAJEDAggFAWkIcGF5bWVudHMAAAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQhzdGFrZUZvcgEHYWRkcmVzcwQBYQkBB2FsbG93ZWQBAghzdGFrZUZvcgMJAAACBQFhBQFhAwMJAQIhPQIFB2FkZHJlc3MJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyCQEBIQEJAQhjb250YWlucwIFEHN0YWtpbmdBZGRyZXNzZXMJAKUIAQgFAWkGY2FsbGVyBwkAAgECBmRlbmllZAkBC3N0YWtlRm9ySW50AgUHYWRkcmVzcwkAkQMCCAUBaQhwYXltZW50cwAACQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBB3Vuc3Rha2UBCXB3ckFtb3VudAQBYQkBB2FsbG93ZWQBAgd1bnN0YWtlAwkAAAIFAWEFAWEDCQBmAgUMbWluU2VudGluZWxzBQlzZW50aW5lbHMJAAIBAhlzZW50aW5lbHMgbm90IGVsZWN0ZWQgeWV0BAdhY2NvdW50CQClCAEIBQFpBmNhbGxlcgMJAGYCCQENdW5zdGFrZUhlaWdodAEFB2FjY291bnQFBkhFSUdIVAkAAgECDHN0aWxsIGxvY2tlZAQKdXNlclNoYXJlcwkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEPdXNlclNoYXJlc1N0b3JlAQUHYWNjb3VudAAAAwkAAAIFCnVzZXJTaGFyZXMAAAkAAgECEm5vdGhpbmcgdG8gdW5zdGFrZQQMbWF4QXZhaWxhYmxlCQELc2hhcmVzVG9Qd3IBBQp1c2VyU2hhcmVzBAZhbW91bnQDCQAAAgUJcHdyQW1vdW50AP///////////wEFDG1heEF2YWlsYWJsZQUJcHdyQW1vdW50AwkAZgIAAAUGYW1vdW50CQACAQIeY2Fubm90IHVuc3Rha2UgbmVnYXRpdmUgYW1vdW50AwkAZgIFBmFtb3VudAUMbWF4QXZhaWxhYmxlCQACAQIhY2Fubm90IHVuc3Rha2UgbW9yZSB0aGFuIHlvdSBoYXZlBAxzaGFyZXNBbW91bnQJAJcDAQkAzAgCCQELcHdyVG9TaGFyZXMBBQZhbW91bnQJAMwIAgUKdXNlclNoYXJlcwUDbmlsAwkAAAIFDHNoYXJlc0Ftb3VudAAACQACAQIXY2Fubm90IHVuc3Rha2UgMCBzaGFyZXMJAMwIAgkBCHdyaXRlSW50AgULc3Rha2VkU3RvcmUJAGUCBQ1jdXJyZW50U3Rha2VkBQZhbW91bnQJAMwIAgkBCHdyaXRlSW50AgURc3Rha2VkSGVpZ2h0U3RvcmUFBkhFSUdIVAkAzAgCCQEIY2hhbmdlQnkCBRB0b3RhbFNoYXJlc1N0b3JlCQEBLQEFDHNoYXJlc0Ftb3VudAkAzAgCCQEIY2hhbmdlQnkCCQEPdXNlclNoYXJlc1N0b3JlAQUHYWNjb3VudAkBAS0BBQxzaGFyZXNBbW91bnQJAMwIAgkBBnBheW91dAIFB2FjY291bnQFBmFtb3VudAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCXVzZXJQb3dlcgEHYWRkcmVzcwkAlAoCBQNuaWwJAQZzdGFrZWQBBQdhZGRyZXNzAWkBCnRvdGFsUG93ZXIACQCUCgIFA25pbAUNY3VycmVudFN0YWtlZAFpAQRpbml0AQRjb25mCQDMCAIJARB3cml0ZUNvbnN0U3RyaW5nAgUSY29uZmlnQWRkcmVzc1N0b3JlBQRjb25mBQNuaWwAaAxuTw==", "chainId": 87, "height": 3523291, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: 3UUptsikgKCj112zBsATb7bVuSv6R9vYwAs52jZwe8Q8 Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+func writeConstString (key,value) = if (!(isDefined(getString(this, key))))
5+ then StringEntry(key, value)
6+ else throw(("already initialized: " + key))
7+
8+
9+func writeInt (key,value) = if ((0 > value))
10+ then throw(((("writing negative value " + toString(value)) + " for key ") + key))
11+ else IntegerEntry(key, value)
12+
13+
14+func changeBy (key,value) = writeInt(key, (valueOrElse(getInteger(this, key), 0) + value))
15+
16+
17+let configAddressStore = "config"
18+
19+let configAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(this, configAddressStore), "config address not found")), "invalid config address")
20+
21+func allowed (op) = invoke(configAddress, "opAllowed", [op], nil)
22+
23+
24+let pwrAssetIdStr = valueOrErrorMessage(getString(configAddress, "powerAssetId"), "pwr asset id not found")
25+
26+let pwrAssetId = fromBase58String(pwrAssetIdStr)
27+
28+let minterContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "contract_minter"), "no contract_minter")), "invalid minter contract")
29+
30+let stakingAddresses = valueOrElse(getString(configAddress, (toString(this) + "_stakers")), "")
31+
32+let minLockTime = valueOrErrorMessage(getInteger(configAddress, (toString(this) + "_min_lock_time")), "min_lock_time not set")
33+
34+func userSharesStore (user) = (user + "_shares")
35+
36+
37+func storeHeight (store) = (store + "_height")
38+
39+
40+func stakeHeight (address) = valueOrErrorMessage(getInteger(this, storeHeight(userSharesStore(address))), "no stake height")
41+
42+
43+func unstakeHeight (address) = (stakeHeight(address) + minLockTime)
44+
45+
46+let minSentinels = valueOrErrorMessage(getInteger(configAddress, "min_sentinels"), "min_sentinels not set")
47+
48+let sentinels = size(split(valueOrErrorMessage(getString(configAddress, "sentinels"), "no sentinels"), ","))
49+
50+let slashers = valueOrElse(getString(configAddress, (toString(this) + "_slashers")), "")
51+
52+let HEIGHT = height
53+
54+let stakedHeightStore = "stakedHeight"
55+
56+let totalSharesStore = "totalShares"
57+
58+let stakedStore = "staked"
59+
60+let RBase = 10000000000000000
61+
62+let apr = valueOrErrorMessage(getInteger(configAddress, (toString(this) + "_staker_apr")), "no staker_apr")
63+
64+let blocksPerYear = ((365 * 24) * 60)
65+
66+let RPerBlock = fraction(apr, RBase, (1000 * blocksPerYear))
67+
68+let currentStaked = {
69+ let stakedHeight = valueOrElse(getInteger(this, stakedHeightStore), 0)
70+ let staked = valueOrElse(getInteger(this, stakedStore), 0)
71+ let d = (HEIGHT - stakedHeight)
72+ let r = (RBase + (d * RPerBlock))
73+ fraction(staked, r, RBase)
74+ }
75+
76+func pwrToShares (pwrAmount) = {
77+ let totalShares = valueOrElse(getInteger(this, totalSharesStore), 0)
78+ if ((totalShares == 0))
79+ then pwrAmount
80+ else fraction(pwrAmount, totalShares, currentStaked)
81+ }
82+
83+
84+func sharesToPwr (sharesAmount) = {
85+ let totalShares = valueOrElse(getInteger(this, totalSharesStore), 0)
86+ if ((totalShares == 0))
87+ then sharesAmount
88+ else fraction(sharesAmount, currentStaked, totalShares)
89+ }
90+
91+
92+func ensurePwrBalance (amount) = {
93+ let pwrBalance = assetBalance(this, pwrAssetId)
94+ if ((amount > pwrBalance))
95+ then {
96+ let mint = invoke(minterContract, "mint", [(amount - pwrBalance)], nil)
97+ if ((mint == mint))
98+ then nil
99+ else throw("Strict value is not equal to itself.")
100+ }
101+ else nil
102+ }
103+
104+
105+func payout (user,amount) = {
106+ let ensure = ensurePwrBalance(amount)
107+ if ((ensure == ensure))
108+ then ScriptTransfer(addressFromStringValue(user), amount, pwrAssetId)
109+ else throw("Strict value is not equal to itself.")
110+ }
111+
112+
113+func staked (address) = {
114+ let userShares = valueOrElse(getInteger(this, userSharesStore(address)), 0)
115+ sharesToPwr(userShares)
116+ }
117+
118+
119+func advise () = {
120+ let totalShares = valueOrElse(getInteger(this, totalSharesStore), 0)
121+ let totalStaked1 = sharesToPwr(totalShares)
122+ ("totalStaked: " + toString(totalStaked1))
123+ }
124+
125+
126+func adviseUser (user) = {
127+ let userShares = valueOrElse(getInteger(this, userSharesStore(user)), 0)
128+ let available = sharesToPwr(userShares)
129+ let heightAndAcc = ((("height: " + toString(HEIGHT)) + ", account: ") + user)
130+ if ((userShares == 0))
131+ then (((heightAndAcc + ", staked: 0") + ", stake_height: -1") + ", unstake_height: -1")
132+ else ((((((heightAndAcc + ", staked: ") + toString(available)) + ", stake_height: ") + toString(stakeHeight(user))) + ", unstake_height: ") + toString(unstakeHeight(user)))
133+ }
134+
135+
136+func stakeForInt (address,p) = if ((p.assetId != pwrAssetId))
137+ then throw("invalid asset id")
138+ else {
139+ let additional = p.amount
140+ let sharesAmount = pwrToShares(additional)
141+[writeInt(stakedStore, (currentStaked + additional)), writeInt(stakedHeightStore, HEIGHT), changeBy(totalSharesStore, sharesAmount), changeBy(userSharesStore(address), sharesAmount), IntegerEntry(storeHeight(userSharesStore(address)), HEIGHT)]
142+ }
143+
144+
145+@Callable(i)
146+func stake () = {
147+ let a = allowed("stake")
148+ if ((a == a))
149+ then stakeForInt(toString(i.caller), i.payments[0])
150+ else throw("Strict value is not equal to itself.")
151+ }
152+
153+
154+
155+@Callable(i)
156+func stakeFor (address) = {
157+ let a = allowed("stakeFor")
158+ if ((a == a))
159+ then if (if ((address != toString(i.originCaller)))
160+ then !(contains(stakingAddresses, toString(i.caller)))
161+ else false)
162+ then throw("denied")
163+ else stakeForInt(address, i.payments[0])
164+ else throw("Strict value is not equal to itself.")
165+ }
166+
167+
168+
169+@Callable(i)
170+func unstake (pwrAmount) = {
171+ let a = allowed("unstake")
172+ if ((a == a))
173+ then if ((minSentinels > sentinels))
174+ then throw("sentinels not elected yet")
175+ else {
176+ let account = toString(i.caller)
177+ if ((unstakeHeight(account) > HEIGHT))
178+ then throw("still locked")
179+ else {
180+ let userShares = valueOrElse(getInteger(userSharesStore(account)), 0)
181+ if ((userShares == 0))
182+ then throw("nothing to unstake")
183+ else {
184+ let maxAvailable = sharesToPwr(userShares)
185+ let amount = if ((pwrAmount == -1))
186+ then maxAvailable
187+ else pwrAmount
188+ if ((0 > amount))
189+ then throw("cannot unstake negative amount")
190+ else if ((amount > maxAvailable))
191+ then throw("cannot unstake more than you have")
192+ else {
193+ let sharesAmount = min([pwrToShares(amount), userShares])
194+ if ((sharesAmount == 0))
195+ then throw("cannot unstake 0 shares")
196+ else [writeInt(stakedStore, (currentStaked - amount)), writeInt(stakedHeightStore, HEIGHT), changeBy(totalSharesStore, -(sharesAmount)), changeBy(userSharesStore(account), -(sharesAmount)), payout(account, amount)]
197+ }
198+ }
199+ }
200+ }
201+ else throw("Strict value is not equal to itself.")
202+ }
203+
204+
205+
206+@Callable(i)
207+func userPower (address) = $Tuple2(nil, staked(address))
208+
209+
210+
211+@Callable(i)
212+func totalPower () = $Tuple2(nil, currentStaked)
213+
214+
215+
216+@Callable(i)
217+func init (conf) = [writeConstString(configAddressStore, conf)]
218+
219+

github/deemru/w8io/6500d08 
31.64 ms