tx · 8CfJRrbiFPx4hyb9GUP2pQy9asF8vnZ8SPUwgPVP3gD9

3MvCgypmBZFTRqL5HuRwCgS7maC7Fkv7pZY:  -0.01200000 Waves

2022.10.20 18:40 [2280924] smart account 3MvCgypmBZFTRqL5HuRwCgS7maC7Fkv7pZY > SELF 0.00000000 Waves

{ "type": 13, "id": "8CfJRrbiFPx4hyb9GUP2pQy9asF8vnZ8SPUwgPVP3gD9", "fee": 1200000, "feeAssetId": null, "timestamp": 1666280392700, "version": 2, "chainId": 84, "sender": "3MvCgypmBZFTRqL5HuRwCgS7maC7Fkv7pZY", "senderPublicKey": "BqGSAiYghM27RZ2Axx3bmTudq9koHT4575AeK31Wx2Pp", "proofs": [ "FJU95k6WQva2hYwGUR1bSBaxUk7Js4cnTRovE4cGqhzS4hG1wLZyd4sbqW3vpWZM7YXJzDAZo3tR2XNWe6zmABt" ], "script": "base64:AAIFAAAAAAAAAEYIAhIDCgEBEgMKAQgSAwoBCBIDCgEIEgMKAQgSAwoBCBIDCgEIEgMKAQgSBAoCCAgSAwoBCBIDCgEIEgUKAwgIARIDCgEIAAAAKQEAAAAQZ2V0U3RyaW5nT3JUaHJvdwAAAAIAAAAHYWRkcmVzcwAAAANrZXkJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABB0AAAACBQAAAAdhZGRyZXNzBQAAAANrZXkJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAADENhbid0IHJlYWQgJwUAAAADa2V5AgAAAA0nIGF0IGFkZHJlc3MgCQAEJQAAAAEFAAAAB2FkZHJlc3MBAAAAEWdldEludGVnZXJPclRocm93AAAAAgAAAAdhZGRyZXNzAAAAA2tleQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAAB2FkZHJlc3MFAAAAA2tleQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAMQ2FuJ3QgcmVhZCAnBQAAAANrZXkCAAAADScgYXQgYWRkcmVzcyAJAAQlAAAAAQUAAAAHYWRkcmVzcwEAAAATcGFyc2VBZGRyZXNzT3JUaHJvdwAAAAEAAAAMbWF5YmVBZGRyZXNzCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQmAAAAAQUAAAAMbWF5YmVBZGRyZXNzCQABLAAAAAIJAAEsAAAAAgIAAAAaQ2FuJ3QgcGFyc2UgYWRkcmVzcyBmcm9tICcFAAAADG1heWJlQWRkcmVzcwIAAAABJwEAAAAKa2V5X2VudGl0eQAAAAMAAAAEbmFtZQAAAAJwawAAAAhwcm9wZXJ0eQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACBQAAAARuYW1lAgAAAAFfBQAAAAJwawIAAAABXwUAAAAIcHJvcGVydHkBAAAADmtleV9Ub2tlbl9uYW1lAAAAAQAAAAd0b2tlbklkCQEAAAAKa2V5X2VudGl0eQAAAAMCAAAABVRva2VuBQAAAAd0b2tlbklkAgAAAARuYW1lAQAAAA5rZXlfTmFtZV90b2tlbgAAAAEAAAAEbmFtZQkBAAAACmtleV9lbnRpdHkAAAADAgAAAAROYW1lBQAAAARuYW1lAgAAAAV0b2tlbgEAAAAOa2V5X05hbWVfb3duZXIAAAABAAAABG5hbWUJAQAAAAprZXlfZW50aXR5AAAAAwIAAAAETmFtZQUAAAAEbmFtZQIAAAAFb3duZXIBAAAAEWtleV9OYW1lX3Jlc29sdmVyAAAAAQAAAARuYW1lCQEAAAAKa2V5X2VudGl0eQAAAAMCAAAABE5hbWUFAAAABG5hbWUCAAAACHJlc29sdmVyAQAAABJrZXlfTmFtZV9leHBpcmVzQXQAAAABAAAABG5hbWUJAQAAAAprZXlfZW50aXR5AAAAAwIAAAAETmFtZQUAAAAEbmFtZQIAAAAJZXhwaXJlc0F0AQAAABJrZXlfTmFtZV9jcmVhdGVkQXQAAAABAAAABG5hbWUJAQAAAAprZXlfZW50aXR5AAAAAwIAAAAETmFtZQUAAAAEbmFtZQIAAAAJY3JlYXRlZEF0AAAAAAtrZXlfbmFtZVRUTAIAAAAHbmFtZVRUTAAAAAAPa2V5X2NvbnRyb2xsZXJzAgAAAAtjb250cm9sbGVycwEAAAAJX3NldE93bmVyAAAAAgAAAARuYW1lAAAABW93bmVyCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAAA5rZXlfTmFtZV9vd25lcgAAAAEFAAAABG5hbWUFAAAABW93bmVyBQAAAANuaWwBAAAACV9nZXRPd25lcgAAAAEAAAAEbmFtZQkABB0AAAACBQAAAAR0aGlzCQEAAAAOa2V5X05hbWVfb3duZXIAAAABBQAAAARuYW1lAQAAAAxfc2V0UmVzb2x2ZXIAAAACAAAABG5hbWUAAAAIcmVzb2x2ZXIJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEWtleV9OYW1lX3Jlc29sdmVyAAAAAQUAAAAEbmFtZQUAAAAIcmVzb2x2ZXIFAAAAA25pbAEAAAAMX2dldFJlc29sdmVyAAAAAQAAAARuYW1lCQAEHQAAAAIFAAAABHRoaXMJAQAAABFrZXlfTmFtZV9yZXNvbHZlcgAAAAEFAAAABG5hbWUBAAAACV9nZXRUb2tlbgAAAAEAAAAEbmFtZQkABB0AAAACBQAAAAR0aGlzCQEAAAAOa2V5X05hbWVfdG9rZW4AAAABBQAAAARuYW1lAQAAAA1fZ2V0Q3Jl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BSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgkBAAAABSRmMF8xAAAAAgUAAAAFJGFjYzAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAIAAAAAAAAAAAMAAAAAAAAAAAQAAAAAAAAAAAUAAAAAAAAAAAYAAAAAAAAAAAcAAAAAAAAAAAgAAAAAAAAAAAkAAAAAAAAAAAoAAAAAAAAAAAsAAAAAAAAAAAwAAAAAAAAAAA0AAAAA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YXRpdmUJAARMAAAAAgMJAABnAAAAAggFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXAFAAAACWNyZWF0ZWRBdAUAAAAEdW5pdAkAAAIAAAABAgAAACFDcmVhdGVkQXQgY2Fubm90IGJlIGluIHRoZSBmdXR1cmUFAAAAA25pbAQAAAAOaXNzdWVOYW1lVG9rZW4JAQAAAA9faXNzdWVOYW1lVG9rZW4AAAABBQAAAARuYW1lBAAAAAd0b2tlbklkCQAEOAAAAAEJAAGRAAAAAgUAAAAOaXNzdWVOYW1lVG9rZW4AAAAAAAAAAAAEAAAACHRva2VuU3RyCQACWAAAAAEFAAAAB3Rva2VuSWQEAAAAFXJlZ2lzdGVyTmFtZVdpdGhUb2tlbgkBAAAAFl9yZWdpc3Rlck5hbWVXaXRoVG9rZW4AAAADBQAAAARuYW1lBQAAAAh0b2tlblN0cgUAAAAJY3JlYXRlZEF0BAAAABR0cmFuc2ZlclRva2VuVG9Pd25lcgkBAAAAFV90cmFuc2ZlclRva2VuVG9Pd25lcgAAAAIFAAAACHRva2VuU3RyBQAAAAVvd25lcgQAAAAMc2V0T3duZXJzaGlwCQEAAAAJX3NldE93bmVyAAAAAgUAAAAEbmFtZQUAAAAFb3duZXIJAAROAAAAAgkABE4AAAACCQAETgAAAAIFAAAADmlzc3VlTmFtZVRva2VuBQAAABVyZWdpc3Rlck5hbWVXaXRoVG9rZW4FAAAAFHRyYW5zZmVyVG9rZW5Ub093bmVyBQAAAAxzZXRPd25lcnNoaXAAAAADaW52AQAAAAdyZWNsYWltAAAAAQAAAARuYW1lCQEAAAALdmFsdWVPckVsc2UAAAACCQEAAAAJbW9kaWZpZXJzAAAAAQkABEwAAAACAwkBAAAADGlzQWN0aXZlTmFtZQAAAAEFAAAABG5hbWUFAAAABHVuaXQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAAAWAFAAAABG5hbWUCAAAAD2AgaXMgbm90IGFjdGl2ZQUAAAADbmlsBAAAAAhuZXdPd25lcggFAAAAA2ludgAAAAZjYWxsZXIEAAAAD25ld093bmVyQWRkcmVzcwkABCUAAAABBQAAAAhuZXdPd25lcgQAAAAIdG9rZW5TdHIJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkBAAAACV9nZXRUb2tlbgAAAAEFAAAABG5hbWUJAAEsAAAAAgkAASwAAAACAgAAABhObyB0b2tlbiBpcyBpc3N1ZWQgZm9yIGAFAAAABG5hbWUCAAAAAWAEAAAAB3Rva2VuSWQJAAJZAAAAAQUAAAAIdG9rZW5TdHIEAAAACGhhc1Rva2VuCQAAAAAAAAIJAAPwAAAAAgUAAAAIbmV3T3duZXIFAAAAB3Rva2VuSWQAAAAAAAAAAAEEAAAADGlzVG9rZW5Pd25lcgkBAAAAB2lzT3duZXIAAAACBQAAAANpbnYFAAAABG5hbWUEAAAADWlzVG9rZW5FeGlzdHMEAAAAByRtYXRjaDAJAAPsAAAAAQUAAAAHdG9rZW5JZAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAFQXNzZXQEAAAABXRva2VuBQAAAAckbWF0Y2gwCQAAAAAAAAIIBQAAAAV0b2tlbgAAAAhxdWFudGl0eQAAAAAAAAAAAQcDAwUAAAAMaXNUb2tlbk93bmVyCQEAAAABIQAAAAEFAAAADWlzVG9rZW5FeGlzdHMHBAAAAA1pc3N1ZU5ld1Rva2VuCQEAAAAPX2lzc3VlTmFtZVRva2VuAAAAAQUAAAAEbmFtZQQAAAAKbmV3VG9rZW5JZAkABDgAAAABCQABkQAAAAIFAAAADWlzc3VlTmV3VG9rZW4AAAAAAAAAAAAEAAAAC25ld1Rva2VuU3RyCQACWAAAAAEFAAAACm5ld1Rva2VuSWQEAAAAF3Jlc3RvcmVOYW1lV2l0aE5ld1Rva2VuCQEAAAAVX3Jlc3RvcmVOYW1lV2l0aFRva2VuAAAAAgUAAAAEbmFtZQUAAAALbmV3VG9rZW5TdHIEAAAAF3RyYW5zZmVyTmV3VG9rZW5Ub093bmVyCQEAAAAVX3RyYW5zZmVyVG9rZW5Ub093bmVyAAAAAgUAAAALbmV3VG9rZW5TdHIFAAAAD25ld093bmVyQWRkcmVzcwkABE4AAAACCQAETgAAAAIFAAAADWlzc3VlTmV3VG9rZW4FAAAAF3Jlc3RvcmVOYW1lV2l0aE5ld1Rva2VuBQAAABd0cmFuc2Zlck5ld1Rva2VuVG9Pd25lcgMDBQAAAAxpc1Rva2VuT3duZXIFAAAACGhhc1Rva2VuBwkAAAIAAAABAgAAABxZb3UgYWxyZWFkeSBvd24gYSBuYW1lIHRva2VuAwkBAAAAASEAAAABBQAAAAhoYXNUb2tlbgkAAAIAAAABAgAAABtZb3UgZG9uJ3QgaGF2ZSBhIG5hbWUgdG9rZW4JAQAAAAlfc2V0T3duZXIAAAACBQAAAARuYW1lBQAAAA9uZXdPd25lckFkZHJlc3MAAAAAGEgy+A==", "height": 2280924, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: HDyUfaRxWPV3FKrdF6et8zv8SLf3T75DAJ9jedtmEdk5 Next: HQKJNcgRN3YhsZ2sAG5HFQ6LGi9FbojNaB2yCrm51qis Diff:
OldNewDifferences
1313 func key_entity (name,pk,property) = ((((name + "_") + pk) + "_") + property)
1414
1515
16-func key_Name_owner (node) = key_entity("Name", node, "owner")
16+func key_Token_name (tokenId) = key_entity("Token", tokenId, "name")
1717
1818
19-func key_Name_resolver (node) = key_entity("Name", node, "resolver")
19+func key_Name_token (name) = key_entity("Name", name, "token")
2020
2121
22-func key_Name_createdAt (node) = key_entity("Name", node, "createdAt")
22+func key_Name_owner (name) = key_entity("Name", name, "owner")
2323
2424
25-func _getOwner (node) = getString(this, key_Name_owner(node))
25+func key_Name_resolver (name) = key_entity("Name", name, "resolver")
2626
2727
28-func _setOwner (node,owner) = [StringEntry(key_Name_owner(node), owner)]
28+func key_Name_expiresAt (name) = key_entity("Name", name, "expiresAt")
2929
3030
31-func _getResolver (node) = getString(this, key_Name_resolver(node))
31+func key_Name_createdAt (name) = key_entity("Name", name, "createdAt")
3232
3333
34-func _setResolver (node,resolver) = [StringEntry(key_Name_resolver(node), resolver)]
34+let key_nameTTL = "nameTTL"
35+
36+let key_controllers = "controllers"
37+
38+func _setOwner (name,owner) = [StringEntry(key_Name_owner(name), owner)]
3539
3640
37-func _getCreatedAt (node) = getInteger(this, key_Name_createdAt(node))
41+func _getOwner (name) = getString(this, key_Name_owner(name))
3842
3943
40-func _setCreatedAt (node,createdAt) = [IntegerEntry(key_Name_createdAt(node), createdAt)]
44+func _setResolver (name,resolver) = [StringEntry(key_Name_resolver(name), resolver)]
45+
46+
47+func _getResolver (name) = getString(this, key_Name_resolver(name))
48+
49+
50+func _getToken (name) = getString(this, key_Name_token(name))
51+
52+
53+func _getCreatedAt (name) = getInteger(this, key_Name_createdAt(name))
54+
55+
56+func _getExpiresAt (name) = getInteger(this, key_Name_expiresAt(name))
57+
58+
59+func _getControllers () = getString(this, key_controllers)
60+
61+
62+let controllers = match _getControllers() {
63+ case repr: String =>
64+ split(repr, ",")
65+ case _ =>
66+ nil
67+}
68+
69+let nameTTL = getIntegerOrThrow(this, key_nameTTL)
70+
71+func isRegisteredName (name) = isDefined(getString(this, key_Name_token(name)))
72+
73+
74+func isCreatedName (name) = isDefined(_getCreatedAt(name))
75+
76+
77+func isExpiredName (name) = match _getExpiresAt(name) {
78+ case expiresAt: Int =>
79+ (lastBlock.timestamp > expiresAt)
80+ case _ =>
81+ false
82+}
83+
84+
85+func isActiveName (name) = if (if (isRegisteredName(name))
86+ then isCreatedName(name)
87+ else false)
88+ then !(isExpiredName(name))
89+ else false
90+
91+
92+func isValidName (name) = {
93+ let symbols = "abcdefghijklmnopqrstuvwxyz1234567890-"
94+ func validateChars (isValid,char) = if (isValid)
95+ then contains(symbols, char)
96+ else false
97+
98+ if (if (if (if (if ((size(name) > 0))
99+ then (63 >= size(name))
100+ else false)
101+ then (indexOf(name, "--") != 2)
102+ else false)
103+ then (indexOf(name, "-") != 0)
104+ else false)
105+ then (lastIndexOf(name, "-") != (size(name) - 1))
106+ else false)
107+ then {
108+ let $l = split(name, "")
109+ let $s = size($l)
110+ let $acc0 = true
111+ func $f0_1 ($a,$i) = if (($i >= $s))
112+ then $a
113+ else validateChars($a, $l[$i])
114+
115+ func $f0_2 ($a,$i) = if (($i >= $s))
116+ then $a
117+ else throw("List size exceeds 63")
118+
119+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63)
120+ }
121+ else false
122+ }
123+
124+
125+func isAvailableName (name) = if (isValidName(name))
126+ then if (!(isRegisteredName(name)))
127+ then true
128+ else isExpiredName(name)
129+ else false
130+
131+
132+func isValidAddress (maybeAddress) = isDefined(addressFromString(maybeAddress))
41133
42134
43135 func isAdmin (inv) = (inv.caller == this)
44136
45137
46-func isOwner (inv,node) = (toString(inv.caller) == valueOrElse(_getOwner(node), ""))
138+func isOwner (inv,name) = (toString(inv.caller) == valueOrElse(_getOwner(name), ""))
47139
48140
49-func isValidAddress (maybeAddress) = isDefined(addressFromString(maybeAddress))
141+func isController (address) = containsElement(controllers, address)
50142
51143
52144 func _splitLastLabel (name) = {
58150 }
59151
60152
61-func _supportedInterfaceAsString (registrant,interfaceId,restLabels) = match invoke(registrant, "supportsInterface", [interfaceId], nil) {
62- case supportsInterface: Boolean =>
63- if (!(supportsInterface))
64- then unit
65- else match invoke(value(registrant), interfaceId, [restLabels], nil) {
66- case mayBeString: String =>
67- mayBeString
68- case _ =>
69- unit
70- }
71- case _ =>
72- unit
73-}
153+func _issueNameToken (name) = [Issue(if ((size(name) > 16))
154+ then (take(name, 15) + "~")
155+ else take(name, 16), (name + ".waves"), 1, 0, false)]
74156
75157
76-func _supportedInterfaceAsInt (registrant,interfaceId,restLabels) = match invoke(registrant, "supportsInterface", [interfaceId], nil) {
77- case supportsInterface: Boolean =>
78- if (!(supportsInterface))
79- then unit
80- else match invoke(value(registrant), interfaceId, [restLabels], nil) {
81- case mayBeInt: Int =>
82- mayBeInt
83- case _ =>
84- unit
85- }
86- case _ =>
87- unit
88-}
158+func _registerNameWithToken (name,tokenId,createdAt) = [StringEntry(key_Name_token(name), tokenId), StringEntry(key_Token_name(tokenId), name), IntegerEntry(key_Name_createdAt(name), createdAt), IntegerEntry(key_Name_expiresAt(name), (createdAt + nameTTL))]
159+
160+
161+func _restoreNameWithToken (name,tokenId) = [StringEntry(key_Name_token(name), tokenId), StringEntry(key_Token_name(tokenId), name)]
162+
163+
164+func _transferTokenToOwner (tokenId,owner) = [ScriptTransfer(parseAddressOrThrow(owner), 1, fromBase58String(tokenId))]
89165
90166
91167 func modifiers (validations) = unit
96172 else throw("Permission denied")
97173
98174
99-func onlyOwner (inv,node) = if (if (isAdmin(inv))
175+func onlyController (inv) = if (if (isAdmin(inv))
100176 then true
101- else isOwner(inv, node))
177+ else isController(toString(inv.caller)))
178+ then unit
179+ else throw("Permission denied")
180+
181+
182+func onlyOwner (inv,name) = if (if (isAdmin(inv))
183+ then true
184+ else isOwner(inv, name))
102185 then unit
103186 else throw("Permission denied")
104187
105188
106189 @Callable(inv)
107-func setOwner (node,owner) = valueOrElse(modifiers([onlyOwner(inv, node), if (isValidAddress(owner))
190+func init (nameTTL) = valueOrElse(modifiers([onlyAdmin(inv), if ((nameTTL > 0))
108191 then unit
109- else throw("Owner must be a valid address")]), _setOwner(node, owner))
192+ else throw("TTL cannot be negative")]), [IntegerEntry(key_nameTTL, nameTTL)])
110193
111194
112195
113196 @Callable(inv)
114-func owner (node) = $Tuple2(nil, _getOwner(node))
197+func supportsInterface (interfaceId) = $Tuple2(nil, containsElement(["owner", "resolver", "nameCreated", "nameExpires"], interfaceId))
115198
116199
117200
118201 @Callable(inv)
119-func resolver (node) = $Tuple2(nil, _getResolver(node))
202+func addController (address) = valueOrElse(modifiers([onlyAdmin(inv), if (isValidAddress(address))
203+ then unit
204+ else throw("Controller must be a valid address"), if (!(isController(address)))
205+ then unit
206+ else throw((("Controller `" + address) + "` is already registered"))]), [StringEntry(key_controllers, makeString((controllers :+ address), ","))])
120207
121208
122209
123210 @Callable(inv)
124-func setResolver (node,resolver) = valueOrElse(modifiers([onlyOwner(inv, node), if (isValidAddress(resolver))
211+func removeController (address) = valueOrElse(modifiers([onlyAdmin(inv), if (isController(address))
125212 then unit
126- else throw("Resolver must be a valid contract address")]), _setResolver(node, resolver))
213+ else throw((("Controller `" + address) + "` is not registered"))]), {
214+ let controllerIndex = value(indexOf(controllers, address))
215+[StringEntry(key_controllers, makeString(removeByIndex(controllers, controllerIndex), ","))]
216+ })
127217
128218
129219
130220 @Callable(inv)
131-func nameCreated (node) = $Tuple2(nil, _getCreatedAt(node))
221+func validate (name) = $Tuple2(nil, isValidName(name))
132222
133223
134224
135225 @Callable(inv)
136-func setRecord (node,owner,resolver) = valueOrElse(modifiers([onlyAdmin(inv)]), ((_setOwner(node, owner) ++ _setResolver(node, resolver)) ++ _setCreatedAt(node, lastBlock.timestamp)))
226+func available (name) = $Tuple2(nil, isAvailableName(name))
137227
138228
139229
140230 @Callable(inv)
141-func whoIs (name) = valueOrElse(modifiers([if ((size(name) > 0))
231+func owner (name) = $Tuple2(nil, _getOwner(_splitLastLabel(name)._1))
232+
233+
234+
235+@Callable(inv)
236+func resolver (name) = $Tuple2(nil, _getResolver(_splitLastLabel(name)._1))
237+
238+
239+
240+@Callable(inv)
241+func setResolver (name,resolver) = valueOrElse(modifiers([if (isActiveName(name))
142242 then unit
143- else throw("Name cannot be empty")]), {
144- let $t047164767 = _splitLastLabel(name)
145- let lastLabel = $t047164767._1
146- let restLabels = $t047164767._2
147- let registrantAddress = _getOwner(lastLabel)
148- let registrant = match registrantAddress {
149- case owner: String =>
150- addressFromString(owner)
243+ else throw("Name expired or not registered"), onlyOwner(inv, name), if (isValidAddress(resolver))
244+ then unit
245+ else throw("Resolver must be a valid contract address")]), $Tuple2(nil, _setResolver(name, resolver)))
246+
247+
248+
249+@Callable(inv)
250+func nameCreated (name) = $Tuple2(nil, _getCreatedAt(_splitLastLabel(name)._1))
251+
252+
253+
254+@Callable(inv)
255+func nameExpires (name) = $Tuple2(nil, _getExpiresAt(_splitLastLabel(name)._1))
256+
257+
258+
259+@Callable(inv)
260+func register (name,owner,createdAt) = valueOrElse(modifiers([onlyController(inv), if (isAvailableName(name))
261+ then unit
262+ else throw((("`" + name) + "` cannot be registered")), if (isValidAddress(owner))
263+ then unit
264+ else throw("Owner must be a valid address"), if ((createdAt > 0))
265+ then unit
266+ else throw("CreatedAt cannot be negative"), if ((lastBlock.timestamp >= createdAt))
267+ then unit
268+ else throw("CreatedAt cannot be in the future")]), {
269+ let issueNameToken = _issueNameToken(name)
270+ let tokenId = calculateAssetId(issueNameToken[0])
271+ let tokenStr = toBase58String(tokenId)
272+ let registerNameWithToken = _registerNameWithToken(name, tokenStr, createdAt)
273+ let transferTokenToOwner = _transferTokenToOwner(tokenStr, owner)
274+ let setOwnership = _setOwner(name, owner)
275+ (((issueNameToken ++ registerNameWithToken) ++ transferTokenToOwner) ++ setOwnership)
276+ })
277+
278+
279+
280+@Callable(inv)
281+func reclaim (name) = valueOrElse(modifiers([if (isActiveName(name))
282+ then unit
283+ else throw((("`" + name) + "` is not active"))]), {
284+ let newOwner = inv.caller
285+ let newOwnerAddress = toString(newOwner)
286+ let tokenStr = valueOrErrorMessage(_getToken(name), (("No token is issued for `" + name) + "`"))
287+ let tokenId = fromBase58String(tokenStr)
288+ let hasToken = (assetBalance(newOwner, tokenId) == 1)
289+ let isTokenOwner = isOwner(inv, name)
290+ let isTokenExists = match assetInfo(tokenId) {
291+ case token: Asset =>
292+ (token.quantity == 1)
151293 case _ =>
152- unit
294+ false
153295 }
154- let parentResolver = _getResolver(lastLabel)
155- let parentCreated = _getCreatedAt(lastLabel)
156- let owner = _supportedInterfaceAsString(value(registrant), "owner", restLabels)
157- let resolver = _supportedInterfaceAsString(value(registrant), "resolver", restLabels)
158- let nameCreated = _supportedInterfaceAsInt(value(registrant), "nameCreated", restLabels)
159- let nameExpires = _supportedInterfaceAsInt(value(registrant), "nameExpires", restLabels)
160- let isRootName = if ((size(lastLabel) > 0))
161- then (size(restLabels) == 0)
162- else false
163- if (if (isRootName)
164- then true
165- else !(isDefined(registrant)))
166- then $Tuple2(nil, $Tuple4(registrantAddress, parentResolver, parentCreated, unit))
167- else $Tuple2(nil, $Tuple4( match owner {
168- case owner: String =>
169- owner
170- case _ =>
171- registrantAddress
172- }, match resolver {
173- case resolver: String =>
174- resolver
175- case _ =>
176- parentResolver
177- }, match nameCreated {
178- case nameCreated: Int =>
179- nameCreated
180- case _ =>
181- parentCreated
182- }, nameExpires))
296+ if (if (isTokenOwner)
297+ then !(isTokenExists)
298+ else false)
299+ then {
300+ let issueNewToken = _issueNameToken(name)
301+ let newTokenId = calculateAssetId(issueNewToken[0])
302+ let newTokenStr = toBase58String(newTokenId)
303+ let restoreNameWithNewToken = _restoreNameWithToken(name, newTokenStr)
304+ let transferNewTokenToOwner = _transferTokenToOwner(newTokenStr, newOwnerAddress)
305+ ((issueNewToken ++ restoreNameWithNewToken) ++ transferNewTokenToOwner)
306+ }
307+ else if (if (isTokenOwner)
308+ then hasToken
309+ else false)
310+ then throw("You already own a name token")
311+ else if (!(hasToken))
312+ then throw("You don't have a name token")
313+ else _setOwner(name, newOwnerAddress)
183314 })
184315
185316
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func getStringOrThrow (address,key) = valueOrErrorMessage(getString(address, key), ((("Can't read '" + key) + "' at address ") + toString(address)))
55
66
77 func getIntegerOrThrow (address,key) = valueOrErrorMessage(getInteger(address, key), ((("Can't read '" + key) + "' at address ") + toString(address)))
88
99
1010 func parseAddressOrThrow (maybeAddress) = valueOrErrorMessage(addressFromString(maybeAddress), (("Can't parse address from '" + maybeAddress) + "'"))
1111
1212
1313 func key_entity (name,pk,property) = ((((name + "_") + pk) + "_") + property)
1414
1515
16-func key_Name_owner (node) = key_entity("Name", node, "owner")
16+func key_Token_name (tokenId) = key_entity("Token", tokenId, "name")
1717
1818
19-func key_Name_resolver (node) = key_entity("Name", node, "resolver")
19+func key_Name_token (name) = key_entity("Name", name, "token")
2020
2121
22-func key_Name_createdAt (node) = key_entity("Name", node, "createdAt")
22+func key_Name_owner (name) = key_entity("Name", name, "owner")
2323
2424
25-func _getOwner (node) = getString(this, key_Name_owner(node))
25+func key_Name_resolver (name) = key_entity("Name", name, "resolver")
2626
2727
28-func _setOwner (node,owner) = [StringEntry(key_Name_owner(node), owner)]
28+func key_Name_expiresAt (name) = key_entity("Name", name, "expiresAt")
2929
3030
31-func _getResolver (node) = getString(this, key_Name_resolver(node))
31+func key_Name_createdAt (name) = key_entity("Name", name, "createdAt")
3232
3333
34-func _setResolver (node,resolver) = [StringEntry(key_Name_resolver(node), resolver)]
34+let key_nameTTL = "nameTTL"
35+
36+let key_controllers = "controllers"
37+
38+func _setOwner (name,owner) = [StringEntry(key_Name_owner(name), owner)]
3539
3640
37-func _getCreatedAt (node) = getInteger(this, key_Name_createdAt(node))
41+func _getOwner (name) = getString(this, key_Name_owner(name))
3842
3943
40-func _setCreatedAt (node,createdAt) = [IntegerEntry(key_Name_createdAt(node), createdAt)]
44+func _setResolver (name,resolver) = [StringEntry(key_Name_resolver(name), resolver)]
45+
46+
47+func _getResolver (name) = getString(this, key_Name_resolver(name))
48+
49+
50+func _getToken (name) = getString(this, key_Name_token(name))
51+
52+
53+func _getCreatedAt (name) = getInteger(this, key_Name_createdAt(name))
54+
55+
56+func _getExpiresAt (name) = getInteger(this, key_Name_expiresAt(name))
57+
58+
59+func _getControllers () = getString(this, key_controllers)
60+
61+
62+let controllers = match _getControllers() {
63+ case repr: String =>
64+ split(repr, ",")
65+ case _ =>
66+ nil
67+}
68+
69+let nameTTL = getIntegerOrThrow(this, key_nameTTL)
70+
71+func isRegisteredName (name) = isDefined(getString(this, key_Name_token(name)))
72+
73+
74+func isCreatedName (name) = isDefined(_getCreatedAt(name))
75+
76+
77+func isExpiredName (name) = match _getExpiresAt(name) {
78+ case expiresAt: Int =>
79+ (lastBlock.timestamp > expiresAt)
80+ case _ =>
81+ false
82+}
83+
84+
85+func isActiveName (name) = if (if (isRegisteredName(name))
86+ then isCreatedName(name)
87+ else false)
88+ then !(isExpiredName(name))
89+ else false
90+
91+
92+func isValidName (name) = {
93+ let symbols = "abcdefghijklmnopqrstuvwxyz1234567890-"
94+ func validateChars (isValid,char) = if (isValid)
95+ then contains(symbols, char)
96+ else false
97+
98+ if (if (if (if (if ((size(name) > 0))
99+ then (63 >= size(name))
100+ else false)
101+ then (indexOf(name, "--") != 2)
102+ else false)
103+ then (indexOf(name, "-") != 0)
104+ else false)
105+ then (lastIndexOf(name, "-") != (size(name) - 1))
106+ else false)
107+ then {
108+ let $l = split(name, "")
109+ let $s = size($l)
110+ let $acc0 = true
111+ func $f0_1 ($a,$i) = if (($i >= $s))
112+ then $a
113+ else validateChars($a, $l[$i])
114+
115+ func $f0_2 ($a,$i) = if (($i >= $s))
116+ then $a
117+ else throw("List size exceeds 63")
118+
119+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63)
120+ }
121+ else false
122+ }
123+
124+
125+func isAvailableName (name) = if (isValidName(name))
126+ then if (!(isRegisteredName(name)))
127+ then true
128+ else isExpiredName(name)
129+ else false
130+
131+
132+func isValidAddress (maybeAddress) = isDefined(addressFromString(maybeAddress))
41133
42134
43135 func isAdmin (inv) = (inv.caller == this)
44136
45137
46-func isOwner (inv,node) = (toString(inv.caller) == valueOrElse(_getOwner(node), ""))
138+func isOwner (inv,name) = (toString(inv.caller) == valueOrElse(_getOwner(name), ""))
47139
48140
49-func isValidAddress (maybeAddress) = isDefined(addressFromString(maybeAddress))
141+func isController (address) = containsElement(controllers, address)
50142
51143
52144 func _splitLastLabel (name) = {
53145 let labels = split(name, ".")
54146 let lastIndex = (size(labels) - 1)
55147 let lastLabel = labels[lastIndex]
56148 let restLabels = makeString(removeByIndex(labels, lastIndex), ".")
57149 $Tuple2(lastLabel, restLabels)
58150 }
59151
60152
61-func _supportedInterfaceAsString (registrant,interfaceId,restLabels) = match invoke(registrant, "supportsInterface", [interfaceId], nil) {
62- case supportsInterface: Boolean =>
63- if (!(supportsInterface))
64- then unit
65- else match invoke(value(registrant), interfaceId, [restLabels], nil) {
66- case mayBeString: String =>
67- mayBeString
68- case _ =>
69- unit
70- }
71- case _ =>
72- unit
73-}
153+func _issueNameToken (name) = [Issue(if ((size(name) > 16))
154+ then (take(name, 15) + "~")
155+ else take(name, 16), (name + ".waves"), 1, 0, false)]
74156
75157
76-func _supportedInterfaceAsInt (registrant,interfaceId,restLabels) = match invoke(registrant, "supportsInterface", [interfaceId], nil) {
77- case supportsInterface: Boolean =>
78- if (!(supportsInterface))
79- then unit
80- else match invoke(value(registrant), interfaceId, [restLabels], nil) {
81- case mayBeInt: Int =>
82- mayBeInt
83- case _ =>
84- unit
85- }
86- case _ =>
87- unit
88-}
158+func _registerNameWithToken (name,tokenId,createdAt) = [StringEntry(key_Name_token(name), tokenId), StringEntry(key_Token_name(tokenId), name), IntegerEntry(key_Name_createdAt(name), createdAt), IntegerEntry(key_Name_expiresAt(name), (createdAt + nameTTL))]
159+
160+
161+func _restoreNameWithToken (name,tokenId) = [StringEntry(key_Name_token(name), tokenId), StringEntry(key_Token_name(tokenId), name)]
162+
163+
164+func _transferTokenToOwner (tokenId,owner) = [ScriptTransfer(parseAddressOrThrow(owner), 1, fromBase58String(tokenId))]
89165
90166
91167 func modifiers (validations) = unit
92168
93169
94170 func onlyAdmin (inv) = if (isAdmin(inv))
95171 then unit
96172 else throw("Permission denied")
97173
98174
99-func onlyOwner (inv,node) = if (if (isAdmin(inv))
175+func onlyController (inv) = if (if (isAdmin(inv))
100176 then true
101- else isOwner(inv, node))
177+ else isController(toString(inv.caller)))
178+ then unit
179+ else throw("Permission denied")
180+
181+
182+func onlyOwner (inv,name) = if (if (isAdmin(inv))
183+ then true
184+ else isOwner(inv, name))
102185 then unit
103186 else throw("Permission denied")
104187
105188
106189 @Callable(inv)
107-func setOwner (node,owner) = valueOrElse(modifiers([onlyOwner(inv, node), if (isValidAddress(owner))
190+func init (nameTTL) = valueOrElse(modifiers([onlyAdmin(inv), if ((nameTTL > 0))
108191 then unit
109- else throw("Owner must be a valid address")]), _setOwner(node, owner))
192+ else throw("TTL cannot be negative")]), [IntegerEntry(key_nameTTL, nameTTL)])
110193
111194
112195
113196 @Callable(inv)
114-func owner (node) = $Tuple2(nil, _getOwner(node))
197+func supportsInterface (interfaceId) = $Tuple2(nil, containsElement(["owner", "resolver", "nameCreated", "nameExpires"], interfaceId))
115198
116199
117200
118201 @Callable(inv)
119-func resolver (node) = $Tuple2(nil, _getResolver(node))
202+func addController (address) = valueOrElse(modifiers([onlyAdmin(inv), if (isValidAddress(address))
203+ then unit
204+ else throw("Controller must be a valid address"), if (!(isController(address)))
205+ then unit
206+ else throw((("Controller `" + address) + "` is already registered"))]), [StringEntry(key_controllers, makeString((controllers :+ address), ","))])
120207
121208
122209
123210 @Callable(inv)
124-func setResolver (node,resolver) = valueOrElse(modifiers([onlyOwner(inv, node), if (isValidAddress(resolver))
211+func removeController (address) = valueOrElse(modifiers([onlyAdmin(inv), if (isController(address))
125212 then unit
126- else throw("Resolver must be a valid contract address")]), _setResolver(node, resolver))
213+ else throw((("Controller `" + address) + "` is not registered"))]), {
214+ let controllerIndex = value(indexOf(controllers, address))
215+[StringEntry(key_controllers, makeString(removeByIndex(controllers, controllerIndex), ","))]
216+ })
127217
128218
129219
130220 @Callable(inv)
131-func nameCreated (node) = $Tuple2(nil, _getCreatedAt(node))
221+func validate (name) = $Tuple2(nil, isValidName(name))
132222
133223
134224
135225 @Callable(inv)
136-func setRecord (node,owner,resolver) = valueOrElse(modifiers([onlyAdmin(inv)]), ((_setOwner(node, owner) ++ _setResolver(node, resolver)) ++ _setCreatedAt(node, lastBlock.timestamp)))
226+func available (name) = $Tuple2(nil, isAvailableName(name))
137227
138228
139229
140230 @Callable(inv)
141-func whoIs (name) = valueOrElse(modifiers([if ((size(name) > 0))
231+func owner (name) = $Tuple2(nil, _getOwner(_splitLastLabel(name)._1))
232+
233+
234+
235+@Callable(inv)
236+func resolver (name) = $Tuple2(nil, _getResolver(_splitLastLabel(name)._1))
237+
238+
239+
240+@Callable(inv)
241+func setResolver (name,resolver) = valueOrElse(modifiers([if (isActiveName(name))
142242 then unit
143- else throw("Name cannot be empty")]), {
144- let $t047164767 = _splitLastLabel(name)
145- let lastLabel = $t047164767._1
146- let restLabels = $t047164767._2
147- let registrantAddress = _getOwner(lastLabel)
148- let registrant = match registrantAddress {
149- case owner: String =>
150- addressFromString(owner)
243+ else throw("Name expired or not registered"), onlyOwner(inv, name), if (isValidAddress(resolver))
244+ then unit
245+ else throw("Resolver must be a valid contract address")]), $Tuple2(nil, _setResolver(name, resolver)))
246+
247+
248+
249+@Callable(inv)
250+func nameCreated (name) = $Tuple2(nil, _getCreatedAt(_splitLastLabel(name)._1))
251+
252+
253+
254+@Callable(inv)
255+func nameExpires (name) = $Tuple2(nil, _getExpiresAt(_splitLastLabel(name)._1))
256+
257+
258+
259+@Callable(inv)
260+func register (name,owner,createdAt) = valueOrElse(modifiers([onlyController(inv), if (isAvailableName(name))
261+ then unit
262+ else throw((("`" + name) + "` cannot be registered")), if (isValidAddress(owner))
263+ then unit
264+ else throw("Owner must be a valid address"), if ((createdAt > 0))
265+ then unit
266+ else throw("CreatedAt cannot be negative"), if ((lastBlock.timestamp >= createdAt))
267+ then unit
268+ else throw("CreatedAt cannot be in the future")]), {
269+ let issueNameToken = _issueNameToken(name)
270+ let tokenId = calculateAssetId(issueNameToken[0])
271+ let tokenStr = toBase58String(tokenId)
272+ let registerNameWithToken = _registerNameWithToken(name, tokenStr, createdAt)
273+ let transferTokenToOwner = _transferTokenToOwner(tokenStr, owner)
274+ let setOwnership = _setOwner(name, owner)
275+ (((issueNameToken ++ registerNameWithToken) ++ transferTokenToOwner) ++ setOwnership)
276+ })
277+
278+
279+
280+@Callable(inv)
281+func reclaim (name) = valueOrElse(modifiers([if (isActiveName(name))
282+ then unit
283+ else throw((("`" + name) + "` is not active"))]), {
284+ let newOwner = inv.caller
285+ let newOwnerAddress = toString(newOwner)
286+ let tokenStr = valueOrErrorMessage(_getToken(name), (("No token is issued for `" + name) + "`"))
287+ let tokenId = fromBase58String(tokenStr)
288+ let hasToken = (assetBalance(newOwner, tokenId) == 1)
289+ let isTokenOwner = isOwner(inv, name)
290+ let isTokenExists = match assetInfo(tokenId) {
291+ case token: Asset =>
292+ (token.quantity == 1)
151293 case _ =>
152- unit
294+ false
153295 }
154- let parentResolver = _getResolver(lastLabel)
155- let parentCreated = _getCreatedAt(lastLabel)
156- let owner = _supportedInterfaceAsString(value(registrant), "owner", restLabels)
157- let resolver = _supportedInterfaceAsString(value(registrant), "resolver", restLabels)
158- let nameCreated = _supportedInterfaceAsInt(value(registrant), "nameCreated", restLabels)
159- let nameExpires = _supportedInterfaceAsInt(value(registrant), "nameExpires", restLabels)
160- let isRootName = if ((size(lastLabel) > 0))
161- then (size(restLabels) == 0)
162- else false
163- if (if (isRootName)
164- then true
165- else !(isDefined(registrant)))
166- then $Tuple2(nil, $Tuple4(registrantAddress, parentResolver, parentCreated, unit))
167- else $Tuple2(nil, $Tuple4( match owner {
168- case owner: String =>
169- owner
170- case _ =>
171- registrantAddress
172- }, match resolver {
173- case resolver: String =>
174- resolver
175- case _ =>
176- parentResolver
177- }, match nameCreated {
178- case nameCreated: Int =>
179- nameCreated
180- case _ =>
181- parentCreated
182- }, nameExpires))
296+ if (if (isTokenOwner)
297+ then !(isTokenExists)
298+ else false)
299+ then {
300+ let issueNewToken = _issueNameToken(name)
301+ let newTokenId = calculateAssetId(issueNewToken[0])
302+ let newTokenStr = toBase58String(newTokenId)
303+ let restoreNameWithNewToken = _restoreNameWithToken(name, newTokenStr)
304+ let transferNewTokenToOwner = _transferTokenToOwner(newTokenStr, newOwnerAddress)
305+ ((issueNewToken ++ restoreNameWithNewToken) ++ transferNewTokenToOwner)
306+ }
307+ else if (if (isTokenOwner)
308+ then hasToken
309+ else false)
310+ then throw("You already own a name token")
311+ else if (!(hasToken))
312+ then throw("You don't have a name token")
313+ else _setOwner(name, newOwnerAddress)
183314 })
184315
185316

github/deemru/w8io/169f3d6 
55.62 ms