tx · BufGtpBmQXbwF79168vLrt8gUWLdKH8HH6NdQkT3Vtah

3NAnrRUttuM8z2xyQdcZDZ9siKDcExnMD7h:  -0.01400000 Waves

2022.11.23 16:55 [2329839] smart account 3NAnrRUttuM8z2xyQdcZDZ9siKDcExnMD7h > SELF 0.00000000 Waves

{ "type": 13, "id": "BufGtpBmQXbwF79168vLrt8gUWLdKH8HH6NdQkT3Vtah", "fee": 1400000, "feeAssetId": null, "timestamp": 1669211811774, "version": 2, "chainId": 84, "sender": "3NAnrRUttuM8z2xyQdcZDZ9siKDcExnMD7h", "senderPublicKey": "9N3y4L5Mhfn5nsh2J2sfe2wNG7t8TFXQVHJb1mXXSahb", "proofs": [ "5S9tYNcjYoNW212RgjKmjFbayh1gaHcJo7UMdtFNUCBrKPAZNuE4LgFumW7EE65uihmc4VBa4xFyWKzEXp3r2oQU" ], "script": "base64:BgIjCAISBAoCGAESAwoBCBIDCgEIEgMKAQESBAoCCAgSBAoCCAgIAAlTRVBBUkFUT1ICAl9fAAxLRVlfTVVMVElTSUcCCE1VTFRJU0lHAA9LRVlfUFVCTElDX0tFWVMCC1BVQkxJQ19LRVlTAApLRVlfUVVPUlVNAgZRVU9SVU0AC0tFWV9DT05GSVJNAgdDT05GSVJNAApLRVlfU1RBVFVTAgZTVEFUVVMBEF92YWxpZGF0ZUFkZHJlc3MBCGFkZHJlc3NfBAckbWF0Y2gwCQCmCAEFCGFkZHJlc3NfAwkAAQIFByRtYXRjaDACB0FkZHJlc3MEAWEFByRtYXRjaDAGBwEOX3ZhbGlkYXRlT3duZXICBGFjY18FZWxlbV8DCQAAAgUFZWxlbV8CAAkAAgECDWludmFsaWQgb3duZXIDCQECIT0CCQDIAQEJANkEAQUFZWxlbV8AIAkAAgECGGludmFsaWQgb3duZXIgcHVibGljIGtleQUEYWNjXwYBaQEEaW5pdAIHb3duZXJzXwdxdW9ydW1fBANlcnIDCQEJaXNEZWZpbmVkAQkAoggBBQxLRVlfTVVMVElTSUcJAAIBAhlpbml0OiBhbHJlYWR5IGluaXRpYWxpemVkBQR1bml0AwkAAAIFA2VycgUDZXJyBARlcnIxAwMJAGcCAAAJAJADAQUHb3duZXJzXwYJAGYCCQCQAwEFB293bmVyc18ACgkAAgECFGluaXQ6IGludmFsaWQgb3duZXJzAwMJAGcCAAAFB3F1b3J1bV8GCQBmAgUHcXVvcnVtXwkAkAMBBQdvd25lcnNfCQACAQIUaW5pdDogaW52YWxpZCBxdW9ydW0FBHVuaXQDCQAAAgUEZXJyMQUEZXJyMQQEZXJyMgoAAiRsBQdvd25lcnNfCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQ5fdmFsaWRhdGVPd25lcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgMJAAACBQRlcnIyBQRlcnIyCQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgUMS0VZX01VTFRJU0lHCQClCAEFBHRoaXMJAMwIAgkBC1N0cmluZ0VudHJ5AgUPS0VZX1BVQkxJQ19LRVlTCQC5CQIFB293bmVyc18FCVNFUEFSQVRPUgkAzAgCCQEMSW50ZWdlckVudHJ5AgUKS0VZX1FVT1JVTQUHcXVvcnVtXwUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCGFkZE93bmVyAQpwdWJsaWNLZXlfBApwdWJsaWNLZXlzCQERQGV4dHJOYXRpdmUoMTA1OCkBBQ9LRVlfUFVCTElDX0tFWVMEDnB1YmxpY0tleXNMaXN0CQC1CQIFCnB1YmxpY0tleXMFCVNFUEFSQVRPUgMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECFWFkZE93bmVyOiBub3QgYWxsb3dlZAMJAAACCQEOX3ZhbGlkYXRlT3duZXICAAAFCnB1YmxpY0tleV8AAAkAAgECHGFkZE93bmVyOiBpbnZhbGlkIHB1YmxpYyBrZXkDCQAAAgkAkAMBBQ5wdWJsaWNLZXlzTGlzdAAKCQACAQIZYWRkT3duZXI6IHRvbyBtYW55IG93bmVycwQVcHVibGljS2V5c0xpc3RVcGRhdGVkCQDNCAIFDnB1YmxpY0tleXNMaXN0BQpwdWJsaWNLZXlfBBFwdWJsaWNLZXlzVXBkYXRlZAkAzAgCCQELU3RyaW5nRW50cnkCBQ9LRVlfUFVCTElDX0tFWVMJALkJAgUVcHVibGljS2V5c0xpc3RVcGRhdGVkBQlTRVBBUkFUT1IFA25pbAkAlAoCBRFwdWJsaWNLZXlzVXBkYXRlZAUEdW5pdAFpAQtyZW1vdmVPd25lcgEKcHVibGljS2V5XwQGcXVvcnVtCQERQGV4dHJOYXRpdmUoMTA1NSkBBQpLRVlfUVVPUlVNBApwdWJsaWNLZXlzCQERQGV4dHJOYXRpdmUoMTA1OCkBBQ9LRVlfUFVCTElDX0tFWVMEDnB1YmxpY0tleXNMaXN0CQC1CQIFCnB1YmxpY0tleXMFCVNFUEFSQVRPUgMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECGHJlbW92ZU93bmVyOiBub3QgYWxsb3dlZAMJAAACBQpwdWJsaWNLZXlfAgAJAAIBAh9yZW1vdmVPd25lcjogaW52YWxpZCBwdWJsaWMga2V5AwkAAAIJAJADAQUOcHVibGljS2V5c0xpc3QAAQkAAgECG3JlbW92ZU93bmVyOiB0b28gZmV3IG93bmVycwQFaW5kZXgEByRtYXRjaDAJAM8IAgUOcHVibGljS2V5c0xpc3QFCnB1YmxpY0tleV8DCQABAgUHJG1hdGNoMAIDSW50BAFhBQckbWF0Y2gwBQFhCQACAQIacmVtb3ZlT3duZXI6IG5vIHN1Y2ggb3duZXIEFXB1YmxpY0tleXNMaXN0VXBkYXRlZAkA0QgCBQ5wdWJsaWNLZXlzTGlzdAUFaW5kZXgEEXB1YmxpY0tleXNVcGRhdGVkCQDMCAIJAQtTdHJpbmdFbnRyeQIFD0tFWV9QVUJMSUNfS0VZUwkAuQkCBRVwdWJsaWNLZXlzTGlzdFVwZGF0ZWQFCVNFUEFSQVRPUgUDbmlsBA1xdW9ydW1VcGRhdGVkAwkAZgIFBnF1b3J1bQkAkAMBBRVwdWJsaWNLZXlzTGlzdFVwZGF0ZWQJAMwIAgkBDEludGVnZXJFbnRyeQIFCktFWV9RVU9SVU0JAJADAQUVcHVibGljS2V5c0xpc3RVcGRhdGVkBQNuaWwFA25pbAkAlAoCCQDOCAIFEXB1YmxpY0tleXNVcGRhdGVkBQ1xdW9ydW1VcGRhdGVkBQR1bml0AWkBCXNldFF1b3J1bQEHcXVvcnVtXwQKcHVibGljS2V5cwkBEUBleHRyTmF0aXZlKDEwNTgpAQUPS0VZX1BVQkxJQ19LRVlTBA5wdWJsaWNLZXlzTGlzdAkAtQkCBQpwdWJsaWNLZXlzBQlTRVBBUkFUT1IDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAhZzZXRRdW9ydW06IG5vdCBhbGxvd2VkAwMJAGcCAAAFB3F1b3J1bV8GCQBmAgUHcXVvcnVtXwkAkAMBBQ5wdWJsaWNLZXlzTGlzdAkAAgECGXNldFF1b3J1bTogaW52YWxpZCBxdW9ydW0JAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUKS0VZX1FVT1JVTQUHcXVvcnVtXwUDbmlsBQR1bml0AWkBEmNvbmZpcm1UcmFuc2FjdGlvbgIFZGFwcF8FdHhJZF8ED2NhbGxlclB1YmxpY0tleQkA2AQBCAUBaQ9jYWxsZXJQdWJsaWNLZXkEBnF1b3J1bQkBEUBleHRyTmF0aXZlKDEwNTUpAQUKS0VZX1FVT1JVTQQKcHVibGljS2V5cwkBEUBleHRyTmF0aXZlKDEwNTgpAQUPS0VZX1BVQkxJQ19LRVlTBA5wdWJsaWNLZXlzTGlzdAkAtQkCBQpwdWJsaWNLZXlzBQlTRVBBUkFUT1IEEGNvbmZpcm1hdGlvbnNLZXkJALkJAgkAzAgCBQtLRVlfQ09ORklSTQkAzAgCBQVkYXBwXwkAzAgCBQV0eElkXwUDbmlsBQlTRVBBUkFUT1IEDWNvbmZpcm1hdGlvbnMJAQt2YWx1ZU9yRWxzZQIJAKIIAQUQY29uZmlybWF0aW9uc0tleQIABAlzdGF0dXNLZXkJALkJAgkAzAgCBQpLRVlfU1RBVFVTCQDMCAIFBWRhcHBfCQDMCAIFBXR4SWRfBQNuaWwFCVNFUEFSQVRPUgQDZXJyAwkBASEBCQEPY29udGFpbnNFbGVtZW50AgUOcHVibGljS2V5c0xpc3QFD2NhbGxlclB1YmxpY0tleQkAAgECHmNvbmZpcm1UcmFuc2FjdGlvbjogb25seSBhZG1pbgMJAQIhPQIJAMgBAQkA2QQBBQV0eElkXwAgCQACAQIgY29uZmlybVRyYW5zYWN0aW9uOiBpbnZhbGlkIHR4SWQDCQEBIQEJARBfdmFsaWRhdGVBZGRyZXNzAQUFZGFwcF8JAAIBAihjb25maXJtVHJhbnNhY3Rpb246IGludmFsaWQgZGFwcCBhZGRyZXNzAwkBCGNvbnRhaW5zAgUNY29uZmlybWF0aW9ucwUPY2FsbGVyUHVibGljS2V5CQACAQIlY29uZmlybVRyYW5zYWN0aW9uOiBhbHJlYWR5IGNvbmZpcm1lZAUEdW5pdAMJAAACBQNlcnIFA2VycgQSY29uZmlybWF0aW9uc0NvdW50CQBkAgABAwkAAAIFDWNvbmZpcm1hdGlvbnMCAAAACQCQAwEJALUJAgUNY29uZmlybWF0aW9ucwUJU0VQQVJBVE9SBBRjb25maXJtYXRpb25zVXBkYXRlZAMJAAACBQ1jb25maXJtYXRpb25zAgAFD2NhbGxlclB1YmxpY0tleQkArAICCQCsAgIFDWNvbmZpcm1hdGlvbnMFCVNFUEFSQVRPUgUPY2FsbGVyUHVibGljS2V5CQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgUQY29uZmlybWF0aW9uc0tleQUUY29uZmlybWF0aW9uc1VwZGF0ZWQJAMwIAgkBDEJvb2xlYW5FbnRyeQIFCXN0YXR1c0tleQkAZwIFEmNvbmZpcm1hdGlvbnNDb3VudAUGcXVvcnVtBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEScmV2b2tlQ29uZmlybWF0aW9uAgVkYXBwXwV0eElkXwQPY2FsbGVyUHVibGljS2V5CQDYBAEIBQFpD2NhbGxlclB1YmxpY0tleQQGcXVvcnVtCQERQGV4dHJOYXRpdmUoMTA1NSkBBQpLRVlfUVVPUlVNBApwdWJsaWNLZXlzCQERQGV4dHJOYXRpdmUoMTA1OCkBBQ9LRVlfUFVCTElDX0tFWVMEDnB1YmxpY0tleXNMaXN0CQC1CQIFCnB1YmxpY0tleXMFCVNFUEFSQVRPUgQQY29uZmlybWF0aW9uc0tleQkAuQkCCQDMCAIFC0tFWV9DT05GSVJNCQDMCAIFBWRhcHBfCQDMCAIFBXR4SWRfBQNuaWwFCVNFUEFSQVRPUgQNY29uZmlybWF0aW9ucwkBC3ZhbHVlT3JFbHNlAgkAoggBBRBjb25maXJtYXRpb25zS2V5AgAEEWNvbmZpcm1hdGlvbnNMaXN0CQC1CQIFDWNvbmZpcm1hdGlvbnMFCVNFUEFSQVRPUgQJc3RhdHVzS2V5CQC5CQIJAMwIAgUKS0VZX1NUQVRVUwkAzAgCBQVkYXBwXwkAzAgCBQV0eElkXwUDbmlsBQlTRVBBUkFUT1IEBnN0YXR1cwkBC3ZhbHVlT3JFbHNlAgkAoAgBBQlzdGF0dXNLZXkHBANlcnIDCQEBIQEJAQ9jb250YWluc0VsZW1lbnQCBQ5wdWJsaWNLZXlzTGlzdAUPY2FsbGVyUHVibGljS2V5CQACAQIecmV2b2tlQ29uZmlybWF0aW9uOiBvbmx5IGFkbWluAwkBAiE9AgkAyAEBCQDZBAEFBXR4SWRfACAJAAIBAiByZXZva2VDb25maXJtYXRpb246IGludmFsaWQgdHhJZAMJAQEhAQkBEF92YWxpZGF0ZUFkZHJlc3MBBQVkYXBwXwkAAgECKHJldm9rZUNvbmZpcm1hdGlvbjogaW52YWxpZCBkYXBwIGFkZHJlc3MDCQEBIQEJAQ9jb250YWluc0VsZW1lbnQCBRFjb25maXJtYXRpb25zTGlzdAUPY2FsbGVyUHVibGljS2V5CQACAQIhcmV2b2tlQ29uZmlybWF0aW9uOiBub3QgY29uZmlybWVkAwUGc3RhdHVzCQACAQIqcmV2b2tlQ29uZmlybWF0aW9uOiBxdW9ydW0gYWxyZWFkeSByZWFjaGVkBQR1bml0AwkAAAIFA2VycgUDZXJyBBhjb25maXJtYXRpb25zTGlzdFVwZGF0ZWQJANEIAgURY29uZmlybWF0aW9uc0xpc3QJAQV2YWx1ZQEJAM8IAgURY29uZmlybWF0aW9uc0xpc3QFD2NhbGxlclB1YmxpY0tleQQSY29uZmlybWF0aW9uc0NvdW50CQCQAwEFGGNvbmZpcm1hdGlvbnNMaXN0VXBkYXRlZAkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIFEGNvbmZpcm1hdGlvbnNLZXkJALkJAgUYY29uZmlybWF0aW9uc0xpc3RVcGRhdGVkBQlTRVBBUkFUT1IJAMwIAgkBDEJvb2xlYW5FbnRyeQIFCXN0YXR1c0tleQkAZwIFEmNvbmZpcm1hdGlvbnNDb3VudAUGcXVvcnVtBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAnR4AQZ2ZXJpZnkABAckbWF0Y2gwCQCiCAEFDEtFWV9NVUxUSVNJRwMJAAECBQckbWF0Y2gwAgZTdHJpbmcECG11bHRpc2lnBQckbWF0Y2gwCQELdmFsdWVPckVsc2UCCQCbCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFCG11bHRpc2lnCQC5CQIJAMwIAgUKS0VZX1NUQVRVUwkAzAgCCQClCAEFBHRoaXMJAMwIAgkA2AQBCAUCdHgCaWQFA25pbAUJU0VQQVJBVE9SBwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tleQdNVM4=", "height": 2329839, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: 3Np9XXsZAAF6myzAQ6XNZwDBDyzkgeJkFxcQXxu5GNrr Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let SEPARATOR = "__"
5+
6+let KEY_MULTISIG = "MULTISIG"
7+
8+let KEY_PUBLIC_KEYS = "PUBLIC_KEYS"
9+
10+let KEY_QUORUM = "QUORUM"
11+
12+let KEY_CONFIRM = "CONFIRM"
13+
14+let KEY_STATUS = "STATUS"
15+
16+func _validateAddress (address_) = match addressFromString(address_) {
17+ case a: Address =>
18+ true
19+ case _ =>
20+ false
21+}
22+
23+
24+func _validateOwner (acc_,elem_) = if ((elem_ == ""))
25+ then throw("invalid owner")
26+ else if ((size(fromBase58String(elem_)) != 32))
27+ then throw("invalid owner public key")
28+ else acc_
29+
30+
31+@Callable(i)
32+func init (owners_,quorum_) = {
33+ let err = if (isDefined(getString(KEY_MULTISIG)))
34+ then throw("init: already initialized")
35+ else unit
36+ if ((err == err))
37+ then {
38+ let err1 = if (if ((0 >= size(owners_)))
39+ then true
40+ else (size(owners_) > 10))
41+ then throw("init: invalid owners")
42+ else if (if ((0 >= quorum_))
43+ then true
44+ else (quorum_ > size(owners_)))
45+ then throw("init: invalid quorum")
46+ else unit
47+ if ((err1 == err1))
48+ then {
49+ let err2 = {
50+ let $l = owners_
51+ let $s = size($l)
52+ let $acc0 = 0
53+ func $f0_1 ($a,$i) = if (($i >= $s))
54+ then $a
55+ else _validateOwner($a, $l[$i])
56+
57+ func $f0_2 ($a,$i) = if (($i >= $s))
58+ then $a
59+ else throw("List size exceeds 10")
60+
61+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
62+ }
63+ if ((err2 == err2))
64+ then $Tuple2([StringEntry(KEY_MULTISIG, toString(this)), StringEntry(KEY_PUBLIC_KEYS, makeString(owners_, SEPARATOR)), IntegerEntry(KEY_QUORUM, quorum_)], unit)
65+ else throw("Strict value is not equal to itself.")
66+ }
67+ else throw("Strict value is not equal to itself.")
68+ }
69+ else throw("Strict value is not equal to itself.")
70+ }
71+
72+
73+
74+@Callable(i)
75+func addOwner (publicKey_) = {
76+ let publicKeys = getStringValue(KEY_PUBLIC_KEYS)
77+ let publicKeysList = split(publicKeys, SEPARATOR)
78+ if ((i.caller != this))
79+ then throw("addOwner: not allowed")
80+ else if ((_validateOwner(0, publicKey_) == 0))
81+ then throw("addOwner: invalid public key")
82+ else if ((size(publicKeysList) == 10))
83+ then throw("addOwner: too many owners")
84+ else {
85+ let publicKeysListUpdated = (publicKeysList :+ publicKey_)
86+ let publicKeysUpdated = [StringEntry(KEY_PUBLIC_KEYS, makeString(publicKeysListUpdated, SEPARATOR))]
87+ $Tuple2(publicKeysUpdated, unit)
88+ }
89+ }
90+
91+
92+
93+@Callable(i)
94+func removeOwner (publicKey_) = {
95+ let quorum = getIntegerValue(KEY_QUORUM)
96+ let publicKeys = getStringValue(KEY_PUBLIC_KEYS)
97+ let publicKeysList = split(publicKeys, SEPARATOR)
98+ if ((i.caller != this))
99+ then throw("removeOwner: not allowed")
100+ else if ((publicKey_ == ""))
101+ then throw("removeOwner: invalid public key")
102+ else if ((size(publicKeysList) == 1))
103+ then throw("removeOwner: too few owners")
104+ else {
105+ let index = match indexOf(publicKeysList, publicKey_) {
106+ case a: Int =>
107+ a
108+ case _ =>
109+ throw("removeOwner: no such owner")
110+ }
111+ let publicKeysListUpdated = removeByIndex(publicKeysList, index)
112+ let publicKeysUpdated = [StringEntry(KEY_PUBLIC_KEYS, makeString(publicKeysListUpdated, SEPARATOR))]
113+ let quorumUpdated = if ((quorum > size(publicKeysListUpdated)))
114+ then [IntegerEntry(KEY_QUORUM, size(publicKeysListUpdated))]
115+ else nil
116+ $Tuple2((publicKeysUpdated ++ quorumUpdated), unit)
117+ }
118+ }
119+
120+
121+
122+@Callable(i)
123+func setQuorum (quorum_) = {
124+ let publicKeys = getStringValue(KEY_PUBLIC_KEYS)
125+ let publicKeysList = split(publicKeys, SEPARATOR)
126+ if ((i.caller != this))
127+ then throw("setQuorum: not allowed")
128+ else if (if ((0 >= quorum_))
129+ then true
130+ else (quorum_ > size(publicKeysList)))
131+ then throw("setQuorum: invalid quorum")
132+ else $Tuple2([IntegerEntry(KEY_QUORUM, quorum_)], unit)
133+ }
134+
135+
136+
137+@Callable(i)
138+func confirmTransaction (dapp_,txId_) = {
139+ let callerPublicKey = toBase58String(i.callerPublicKey)
140+ let quorum = getIntegerValue(KEY_QUORUM)
141+ let publicKeys = getStringValue(KEY_PUBLIC_KEYS)
142+ let publicKeysList = split(publicKeys, SEPARATOR)
143+ let confirmationsKey = makeString([KEY_CONFIRM, dapp_, txId_], SEPARATOR)
144+ let confirmations = valueOrElse(getString(confirmationsKey), "")
145+ let statusKey = makeString([KEY_STATUS, dapp_, txId_], SEPARATOR)
146+ let err = if (!(containsElement(publicKeysList, callerPublicKey)))
147+ then throw("confirmTransaction: only admin")
148+ else if ((size(fromBase58String(txId_)) != 32))
149+ then throw("confirmTransaction: invalid txId")
150+ else if (!(_validateAddress(dapp_)))
151+ then throw("confirmTransaction: invalid dapp address")
152+ else if (contains(confirmations, callerPublicKey))
153+ then throw("confirmTransaction: already confirmed")
154+ else unit
155+ if ((err == err))
156+ then {
157+ let confirmationsCount = (1 + (if ((confirmations == ""))
158+ then 0
159+ else size(split(confirmations, SEPARATOR))))
160+ let confirmationsUpdated = if ((confirmations == ""))
161+ then callerPublicKey
162+ else ((confirmations + SEPARATOR) + callerPublicKey)
163+ $Tuple2([StringEntry(confirmationsKey, confirmationsUpdated), BooleanEntry(statusKey, (confirmationsCount >= quorum))], unit)
164+ }
165+ else throw("Strict value is not equal to itself.")
166+ }
167+
168+
169+
170+@Callable(i)
171+func revokeConfirmation (dapp_,txId_) = {
172+ let callerPublicKey = toBase58String(i.callerPublicKey)
173+ let quorum = getIntegerValue(KEY_QUORUM)
174+ let publicKeys = getStringValue(KEY_PUBLIC_KEYS)
175+ let publicKeysList = split(publicKeys, SEPARATOR)
176+ let confirmationsKey = makeString([KEY_CONFIRM, dapp_, txId_], SEPARATOR)
177+ let confirmations = valueOrElse(getString(confirmationsKey), "")
178+ let confirmationsList = split(confirmations, SEPARATOR)
179+ let statusKey = makeString([KEY_STATUS, dapp_, txId_], SEPARATOR)
180+ let status = valueOrElse(getBoolean(statusKey), false)
181+ let err = if (!(containsElement(publicKeysList, callerPublicKey)))
182+ then throw("revokeConfirmation: only admin")
183+ else if ((size(fromBase58String(txId_)) != 32))
184+ then throw("revokeConfirmation: invalid txId")
185+ else if (!(_validateAddress(dapp_)))
186+ then throw("revokeConfirmation: invalid dapp address")
187+ else if (!(containsElement(confirmationsList, callerPublicKey)))
188+ then throw("revokeConfirmation: not confirmed")
189+ else if (status)
190+ then throw("revokeConfirmation: quorum already reached")
191+ else unit
192+ if ((err == err))
193+ then {
194+ let confirmationsListUpdated = removeByIndex(confirmationsList, value(indexOf(confirmationsList, callerPublicKey)))
195+ let confirmationsCount = size(confirmationsListUpdated)
196+ $Tuple2([StringEntry(confirmationsKey, makeString(confirmationsListUpdated, SEPARATOR)), BooleanEntry(statusKey, (confirmationsCount >= quorum))], unit)
197+ }
198+ else throw("Strict value is not equal to itself.")
199+ }
200+
201+
202+@Verifier(tx)
203+func verify () = match getString(KEY_MULTISIG) {
204+ case multisig: String =>
205+ valueOrElse(getBoolean(addressFromStringValue(multisig), makeString([KEY_STATUS, toString(this), toBase58String(tx.id)], SEPARATOR)), false)
206+ case _ =>
207+ sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
208+}
209+

github/deemru/w8io/169f3d6 
33.21 ms