tx · 32rWApqw4nfbKJoFxdMFrUFXtGB8yYeLgj8qWy66mrff

3Mu5kJR7ECoKqV4RjdtjBkeKaQoTgR1WBZc:  -0.01800000 Waves

2022.11.25 17:46 [2332761] smart account 3Mu5kJR7ECoKqV4RjdtjBkeKaQoTgR1WBZc > SELF 0.00000000 Waves

{ "type": 13, "id": "32rWApqw4nfbKJoFxdMFrUFXtGB8yYeLgj8qWy66mrff", "fee": 1800000, "feeAssetId": null, "timestamp": 1669387549434, "version": 2, "chainId": 84, "sender": "3Mu5kJR7ECoKqV4RjdtjBkeKaQoTgR1WBZc", "senderPublicKey": "242mibE5dTci8wD6vghuCGxjDZdnNJr88H7gcWWehpEX", "proofs": [ "5Lff5og8D5kEf9wamXEFUfnwA9UtvZmmZ4GGi5Zdpjt9hGxxmJZQwr4XYwc6o6E5waL8oYaopC1tPtW8ubaUjpLz" ], "script": "base64:BgIvCAISBwoFCAEBAQESBAoCAQESBwoFCAgBARgSBwoFCAgBARgSAwoBARIDCgEBEgBXAAtyZXZpc2lvbk51bQIAAANTRVACAl9fAAdMSVNUU0VQAgE6AA1ERUZBVUxUUVVPUlVNAKDCHgAKVVJMUEFUVEVSTgIaaHR0cHM6Ly9mb3J1bS5uZXV0cmluby5hdC8ACE1BWFRJVExFAKABAAZNQVhVUkwA+gEADU1BWFZPVElOR1RJTUUAgJDkwAQABU1VTFQ2AMCEPQAOREVGQVVMVFBBWU1FTlQAgJTr3AMAFERFRkFVTFRDUkVBVElPTkdOU0JUAICU69wDAApQQVNUTUFSR0lOAIC6twMADEZVVFVSRU1BUkdJTgDAy8kCABJnb3ZJZHhQcm9wb3NhbFR4SWQAAQAKZ292SWR4VHlwZQACAAxnb3ZJZHhBdXRob3IAAwAJZ292SWR4VXJsAAQAC2dvdklkeFRpdGxlAAUAEmdvdklkeENyZWF0aW9uVGltZQAGAAtnb3ZJZHhTdGFydAAHAAlnb3ZJZHhFbmQACAALZ292SWR4VHhJZHMACQAMZ292SWR4UXVvcnVtAAoADWdvdklkeE9wdGlvbnMACwATZ292U3RhdHVzSWR4SXNWYWxpZAABABJnb3ZTdGF0dXNJZHhXaW5PcHQAAgAUZ292U3RhdHVzSWR4V2luVm90ZXMAAwAWZ292U3RhdHVzSWR4VG90YWxWb3RlcwAEABVnb3ZTdGF0dXNJZHhTY0FwcGxpZWQABQASZ292U3RhdHVzSWR4U2NUaW1lAAYAFmdvdlN0YXR1c0lkeElzQ2FuY2VsZWQABwEPZ2V0U3RyaW5nT3JGYWlsAgdhZGRyZXNzA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFB2FkZHJlc3MFA2tleQkAuQkCCQDMCAICCm1hbmRhdG9yeSAJAMwIAgkApQgBBQdhZGRyZXNzCQDMCAICAS4JAMwIAgUDa2V5CQDMCAICDyBpcyBub3QgZGVmaW5lZAUDbmlsAgABDGdldEludE9yRWxzZQIDa2V5CmRlZmF1bHRWYWwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUDa2V5BQpkZWZhdWx0VmFsABlJZHhDb250cm9sQ2ZnTmV1dHJpbm9EYXBwAAEAGElkeENvbnRyb2xDZmdBdWN0aW9uRGFwcAACABRJZHhDb250cm9sQ2ZnUnBkRGFwcAADABVJZHhDb250cm9sQ2ZnTWF0aERhcHAABAAcSWR4Q29udHJvbENmZ0xpcXVpZGF0aW9uRGFwcAAFABVJZHhDb250cm9sQ2ZnUmVzdERhcHAABgAdSWR4Q29udHJvbENmZ05vZGVSZWdpc3RyeURhcHAABwAcSWR4Q29udHJvbENmZ05zYnRTdGFraW5nRGFwcAAIABlJZHhDb250cm9sQ2ZnTWVkaWF0b3JEYXBwAAkAHElkeENvbnRyb2xDZmdTdXJmU3Rha2luZ0RhcHAACgAgSWR4Q29udHJvbENmZ0duc2J0Q29udHJvbGxlckRhcHAACwAXSWR4Q29udHJvbENmZ1Jlc3RWMkRhcHAADAAbSWR4Q29udHJvbENmZ0dvdmVybmFuY2VEYXBwAA0BEWtleUNvbnRyb2xBZGRyZXNzAAIcJXMlc19fY29uZmlnX19jb250cm9sQWRkcmVzcwENa2V5Q29udHJvbENmZwACESVzX19jb250cm9sQ29uZmlnARRyZWFkQ29udHJvbENmZ09yRmFpbAEHY29udHJvbAkAvAkCCQEPZ2V0U3RyaW5nT3JGYWlsAgUHY29udHJvbAkBDWtleUNvbnRyb2xDZmcABQNTRVABGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIKY29udHJvbENmZwNpZHgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIFCmNvbnRyb2xDZmcFA2lkeAkArAICAi1Db250cm9sIGNmZyBkb2Vzbid0IGNvbnRhaW4gYWRkcmVzcyBhdCBpbmRleCAJAKQDAQUDaWR4AA9jb250cm9sQ29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkBEWtleUNvbnRyb2xBZGRyZXNzAAIjM1A1QmZkNThQUGZOdkJNMkh5OFFmYmNEcU1lTnR6ZzdLZlAACmNvbnRyb2xDZmcJARRyZWFkQ29udHJvbENmZ09yRmFpbAEFD2NvbnRyb2xDb250cmFjdAAQbmV1dHJpbm9Db250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFGUlkeENvbnRyb2xDZmdOZXV0cmlub0RhcHAAF2duc2J0Q29udHJvbGxlckNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUgSWR4Q29udHJvbENmZ0duc2J0Q29udHJvbGxlckRhcHABGGtleVF1b3J1bVJlcXVpcmVkUGVyY2VudAEEdHlwZQkArAICAhYlcyVzX19xdW9ydW1SZXF1aXJlZF9fBQR0eXBlARJrZXlQYXltZW50UmVxdWlyZWQAAhMlc19fcGF5bWVudFJlcXVpcmVkARBrZXlHbnNidFJlcXVpcmVkAAIRJXNfX2dOc2J0UmVxdWlyZWQBEWtleUxhc3RQcm9wb3NhbElkAAIOJXNfX3Byb3Bvc2FsSWQBFGtleUxhc3RVcGRhdGVWZXJzaW9uAAIRJXNfX3VwZGF0ZVZlcnNpb24BGWtleVByb3Bvc2FsU3RhdHVzRGF0YUJ5SWQBCnByb3Bvc2FsSWQJAKwCAgIaJXMlZF9fcHJvcG9zYWxTdGF0dXNEYXRhX18JAKQDAQUKcHJvcG9zYWxJZAETa2V5UHJvcG9zYWxEYXRhQnlJZAEKcHJvcG9zYWxJZAkArAICAhQlcyVkX19wcm9wb3NhbERhdGFfXwkApAMBBQpwcm9wb3NhbElkAR1rZXlQcm9wb3NhbFZvdGVzQnlJZEFuZE9wdGlvbgIKcHJvcG9zYWxJZANvcHQJALkJAgkAzAgCAgYlcyVkJWQJAMwIAgIKdm90ZXNCeU9wdAkAzAgCCQCkAwEFCnByb3Bvc2FsSWQJAMwIAgkApAMBBQNvcHQFA25pbAUDU0VQARtrZXlQcm9wb3NhbFZvdGVzQnlJZEFuZFVzZXICCnByb3Bvc2FsSWQIdXNlckFkZHIJALkJAgkAzAgCAgYlcyVkJXMJAMwIAgILdm90ZXNCeVVzZXIJAMwIAgkApAMBBQpwcm9wb3NhbElkCQDMCAIFCHVzZXJBZGRyBQNuaWwFA1NFUAEca2V5UHJvcG9zYWxDaG9pY2VCeUlkQW5kVXNlcgIKcHJvcG9zYWxJZAh1c2VyQWRkcgkAuQkCCQDMCAICBiVzJWQlcwkAzAgCAgxvcHRpb25CeVVzZXIJAMwIAgkApAMBBQpwcm9wb3NhbElkCQDMCAIFCHVzZXJBZGRyBQNuaWwFA1NFUAESa2V5QXBwbHlJblByb2dyZXNzAAITJXNfX2FwcGx5SW5Qcm9ncmVzcwEWa2V5UHJvcG9zYWxJZEJ5VG9waWNJZAEHdG9waWNJZAkArAICAhslcyVkX19wcm9wb3NhbElkQnlUb3BpY0lkX18JAKQDAQUHdG9waWNJZAEXa2V5VXNlckduc2J0UmVsZWFzZVRpbWUBCHVzZXJBZGRyCQCsAgICGyVzJXNfdXNlckduc2J0UmVsZWFzZVRpbWVfXwUIdXNlckFkZHIBHmtleU51bVVuaXF1ZVZvdGVyc0J5UHJvcG9zYWxJZAEKcHJvcG9zYWxJZAkArAICAhElcyVkX19udW1Wb3RlcnNfXwkApAMBBQpwcm9wb3NhbElkARhrZXlTdGF0c0F2ZXJVbmlxdWVWb3RlcnMAAiAlcyVzJXNfX3N0YXRzX19hdmdfX3VuaXF1ZVZvdGVycwEWa2V5U3RhdHNBdmVyR25zYnRWb3RlZAACHiVzJXMlc19fc3RhdHNfX2F2Z19fZ25zYnRWb3RlZAEVa2V5U3RhdHNVbmlxdWVBdXRob3JzAAIaJXMlc19fc3RhdHNfX3VuaXF1ZUF1dGhvcnMBF2tleU51bVByb3Bvc2Fsc0J5QXV0aG9yAQphZGRyZXNzU3RyCQCsAgICHCVzJXNfX251bVByb3Bvc2Fsc0J5QXV0aG9yX18FCmFkZHJlc3NTdHIBD2tleUFwcGx5SGlzdG9yeQEJdGltZXN0YW1wCQCsAgICFCVzJWRfX2FwcGx5SGlzdG9yeV9fCQCkAwEFCXRpbWVzdGFtcAEJYXNBbnlMaXN0AQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACCUxpc3RbQW55XQQBbAUHJG1hdGNoMAUBbAkAAgECG2ZhaWwgdG8gY2FzdCBpbnRvIExpc3RbQW55XQEFYXNJbnQBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIDSW50BAFpBQckbWF0Y2gwBQFpCQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50AQpzdGF0dXNEYXRhBw1pc1ZvdGluZ1ZhbGlkCXdpbk9wdGlvbg53aW5PcHRpb25Wb3Rlcwp0b3RhbFZvdGVzEWFyZVNjcmlwdHNBcHBsaWVkEHNjcmlwdHNUaW1lc3RhbXAOY2FuY2VsZWRCeVRlYW0JALkJAgkAzAgCAg4lYiVkJWQlZCViJWQlYgkAzAgCCQClAwEFDWlzVm90aW5nVmFsaWQJAMwIAgkApAMBBQl3aW5PcHRpb24JAMwIAgkApAMBBQ53aW5PcHRpb25Wb3RlcwkAzAgCCQCkAwEFCnRvdGFsVm90ZXMJAMwIAgkApQMBBRFhcmVTY3JpcHRzQXBwbGllZAkAzAgCCQCkAwEFEHNjcmlwdHNUaW1lc3RhbXAJAMwIAgkApQMBBQ5jYW5jZWxlZEJ5VGVhbQUDbmlsBQNTRVABDHByb3Bvc2FsRGF0YQsMcHJvcG9zYWxUeElkBHR5cGUGYXV0aG9yCWZvcnVtTGluawV0aXRsZQxwcm9wb3NhbFRpbWUPdm90aW5nU3RhcnRUaW1lDXZvdGluZ0VuZFRpbWUFdHhJZHMNcXVvcnVtSW5HbnNidAdvcHRpb25zCQC5CQIJAMwIAgIWJXMlcyVzJXMlcyVkJWQlZCVzJWQlcwkAzAgCBQxwcm9wb3NhbFR4SWQJAMwIAgUEdHlwZQkAzAgCBQZhdXRob3IJAMwIAgUJZm9ydW1MaW5rCQDMCAIFBXRpdGxlCQDMCAIJAKQDAQUMcHJvcG9zYWxUaW1lCQDMCAIJAKQDAQUPdm90aW5nU3RhcnRUaW1lCQDMCAIJAKQDAQUNdm90aW5nRW5kVGltZQkAzAgCBQV0eElkcwkAzAgCCQCkAwEFDXF1b3J1bUluR25zYnQJAMwIAgUHb3B0aW9ucwUDbmlsBQNTRVABC2NoZWNrVHhMaXN0AQZ0eExpc3QDCQBmAgkAkAMBBQZ0eExpc3QAFAkAAgEJAKwCAgIXVG9vIG1hbnkgdHJhbnNhY3Rpb25zOiAJAKQDAQkAkAMBBQZ0eExpc3QKAQhjb21iaW5lcgIDYWNjAnR4AwkBAiE9AgkAyAEBCQDZBAEFAnR4ACAJAAIBCQCsAgICDFdyb25nIHR4SWQ6IAUCdHgDCQAAAgUDYWNjAgAFAnR4CQCsAgIJAKwCAgUDYWNjBQdMSVNUU0VQBQJ0eAoAAiRsBQZ0eExpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCGNvbWJpbmVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAyMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAC0lkeEVmZlRvdGFsAAAACklkeEVmZlVzZXIAAQERZ2V0RWZmZWN0aXZlR25zYnQBEnVzZXJBZGRyU3RyT3JFbXB0eQQJZ25zYnREYXRhCQEJYXNBbnlMaXN0AQkA/AcEBRdnbnNidENvbnRyb2xsZXJDb250cmFjdAIUZ25zYnRJbmZvU1lTUkVBRE9OTFkJAMwIAgUSdXNlckFkZHJTdHJPckVtcHR5CQDMCAIAAAkAzAgCAAAFA25pbAUDbmlsBAhuc2J0RGF0YQkBCWFzQW55TGlzdAEJAJEDAgUJZ25zYnREYXRhAAIEDHVzZXJGcm9tTnNidAkBBWFzSW50AQkAkQMCBQhuc2J0RGF0YQACBA10b3RhbEZyb21Oc2J0CQEFYXNJbnQBCQCRAwIFCG5zYnREYXRhAAMEEnVzZXJNYXR1cmVGcm9tU3VyZgkBBWFzSW50AQkAkQMCBQlnbnNidERhdGEACQQTdG90YWxNYXR1cmVGcm9tU3VyZgkBBWFzSW50AQkAkQMCBQlnbnNidERhdGEABgkAzAgCCQBkAgUNdG90YWxGcm9tTnNidAUTdG90YWxNYXR1cmVGcm9tU3VyZgkAzAgCCQBkAgUMdXNlckZyb21Oc2J0BRJ1c2VyTWF0dXJlRnJvbVN1cmYFA25pbAEMdmFsaWRhdGVMaW5rAQN1cmwDCQECIT0CCQEFdmFsdWUBCQCzCQIFA3VybAUKVVJMUEFUVEVSTgAACQACAQILSW52YWxpZCB1cmwDCQBmAgkAsQIBBQN1cmwFBk1BWFVSTAkAAgECDVVybCB0b28gbG9uZyEEB3RvcGljSWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAtgkBCQCwAgIFA3VybAkAZAIJAQV2YWx1ZQEJALcJAgUDdXJsAgEvAAECDVdyb25nIHRvcGljSWQEDHJlZ2lzdGVyZWRJZAkAnwgBCQEWa2V5UHJvcG9zYWxJZEJ5VG9waWNJZAEFB3RvcGljSWQDCQEJaXNEZWZpbmVkAQUMcmVnaXN0ZXJlZElkCQACAQkArAICAjhWb3Rpbmcgd2l0aCBzdWNoIGZvcnVtIGxpbmsgaXMgYWxyZWFkeSByZWdpc3RlcmVkIGJ5IGlkPQkApAMBCQEFdmFsdWUBBQxyZWdpc3RlcmVkSWQFB3RvcGljSWQBDmluaXRpYXRlVm90aW5nCwdwYXltZW50DHByb3Bvc2FsVHhJZAR0eXBlBmF1dGhvcglmb3J1bUxpbmsFdGl0bGUPdm90aW5nU3RhcnRUaW1lDXZvdGluZ0VuZFRpbWUGc3RhdHVzBnR4TGlzdAtvcHRpb25zTGlzdAMJAQIhPQIIBQdwYXltZW50B2Fzc2V0SWQFBHVuaXQJAAIBAhtBbGxvd2VkIFdBVkVTIHBheW1lbnQgb25seSEEBnBtdFJlcQkBDGdldEludE9yRWxzZQIJARJrZXlQYXltZW50UmVxdWlyZWQABQ5ERUZBVUxUUEFZTUVOVAMJAGYCBQZwbXRSZXEIBQdwYXltZW50BmFtb3VudAkAAgEJAKwCAgIkUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgYXQgbGVhc3QgCQCkAwEFBnBtdFJlcQQHdG9waWNJZAkBDHZhbGlkYXRlTGluawEFCWZvcnVtTGluawMJAAACBQV0aXRsZQIACQACAQIOVGl0bGUgaXMgZW1wdHkDCQBmAgkAsQIBBQV0aXRsZQUITUFYVElUTEUJAAIBAg5Ub28gbG9uZyB0aXRsZQQMcHJvcG9zYWxUaW1lCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAMJAGYCBQxwcm9wb3NhbFRpbWUFD3ZvdGluZ1N0YXJ0VGltZQkAAgEJAKwCAgkArAICCQCsAgICEHZvdGluZ1N0YXJ0VGltZT0JAKQDAQUPdm90aW5nU3RhcnRUaW1lAhAgPCBwcm9wb3NhbFRpbWU9CQCkAwEFDHByb3Bvc2FsVGltZQMJAGYCBQ92b3RpbmdTdGFydFRpbWUFDXZvdGluZ0VuZFRpbWUJAAIBCQCsAgIJAKwCAgkArAICAg52b3RpbmdFbmRUaW1lPQkApAMBBQ12b3RpbmdFbmRUaW1lAhMgPCB2b3RpbmdTdGFydFRpbWU9CQCkAwEFD3ZvdGluZ1N0YXJ0VGltZQMJAGYCCQBlAgUNdm90aW5nRW5kVGltZQUPdm90aW5nU3RhcnRUaW1lBQ1NQVhWT1RJTkdUSU1FCQACAQkArAICCQCsAgIJAKwCAgIbVm90aW5nIHBlcmlvZCBleGNlZWRzIG1heDogCQCkAwEJAGUCBQ12b3RpbmdFbmRUaW1lBQ92b3RpbmdTdGFydFRpbWUCAyA+IAkApAMBBQ1NQVhWT1RJTkdUSU1FBAV0eElkcwMJAAACBQR0eXBlAgRJREVBAgAJAQtjaGVja1R4TGlzdAEFBnR4TGlzdAMJAGcCAAEJAJADAQULb3B0aW9uc0xpc3QJAAIBAhdUb28gZmV3IGNob2ljZXMgdG8gdm90ZQQDZWZmCQERZ2V0RWZmZWN0aXZlR25zYnQBBQZhdXRob3IECmduc2J0VG90YWwJAJEDAgUDZWZmBQtJZHhFZmZUb3RhbAQJZ05zYnRVc2VyCQCRAwIFA2VmZgUKSWR4RWZmVXNlcgQIZ25zYnRSZXEJAQxnZXRJbnRPckVsc2UCCQEQa2V5R25zYnRSZXF1aXJlZAAFFERFRkFVTFRDUkVBVElPTkdOU0JUAwkAZgIFCGduc2J0UmVxBQlnTnNidFVzZXIJAAIBCQCsAgIJAKwCAgISWW91IG5lZWQgYXQgbGVhc3QgCQCkAwEFCGduc2J0UmVxAhcgZ05zYnQgdG8gY3JlYXRlIHZvdGluZwQMYW1vdW50TGVhc2VkCQD8BwQFEG5ldXRyaW5vQ29udHJhY3QCC2FjY2VwdFdhdmVzBQNuaWwJAMwIAgUHcGF5bWVudAUDbmlsAwkAAAIFDGFtb3VudExlYXNlZAUMYW1vdW50TGVhc2VkBAZxdW9ydW0JAQxnZXRJbnRPckVsc2UCCQEYa2V5UXVvcnVtUmVxdWlyZWRQZXJjZW50AQUEdHlwZQUNREVGQVVMVFFVT1JVTQQNcXVvcnVtSW5HbnNidAkAawMFBnF1b3J1bQUKZ25zYnRUb3RhbAUFTVVMVDYECnByb3Bvc2FsSWQJAGQCCQEMZ2V0SW50T3JFbHNlAgkBEWtleUxhc3RQcm9wb3NhbElkAAAAAAEEFG51bVByb3Bvc2Fsc0J5QXV0aG9yCQBkAgkBDGdldEludE9yRWxzZQIJARdrZXlOdW1Qcm9wb3NhbHNCeUF1dGhvcgEFBmF1dGhvcgAAAAEEC3VuaXFBdXRob3JzCQBkAgkBDGdldEludE9yRWxzZQIJARVrZXlTdGF0c1VuaXF1ZUF1dGhvcnMAAAADCQAAAgUUbnVtUHJvcG9zYWxzQnlBdXRob3IAAQABAAAECm9wdGlvbnNTdHIJALkJAgULb3B0aW9uc0xpc3QFB0xJU1RTRVAJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEWtleUxhc3RQcm9wb3NhbElkAAUKcHJvcG9zYWxJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleVByb3Bvc2FsSWRCeVRvcGljSWQBBQd0b3BpY0lkBQpwcm9wb3NhbElkCQDMCAIJAQtTdHJpbmdFbnRyeQIJARlrZXlQcm9wb3NhbFN0YXR1c0RhdGFCeUlkAQUKcHJvcG9zYWxJZAkBCnN0YXR1c0RhdGEHBwAAAAAAAAcAAAcJAMwIAgkBC1N0cmluZ0VudHJ5AgkBE2tleVByb3Bvc2FsRGF0YUJ5SWQBBQpwcm9wb3NhbElkCQEMcHJvcG9zYWxEYXRhCwUMcHJvcG9zYWxUeElkBQR0eXBlBQZhdXRob3IJANgEAQkAmwMBBQlmb3J1bUxpbmsJANgEAQkAmwMBBQV0aXRsZQUMcHJvcG9zYWxUaW1lBQ92b3RpbmdTdGFydFRpbWUFDXZvdGluZ0VuZFRpbWUFBXR4SWRzBQ1xdW9ydW1Jbkduc2J0BQpvcHRpb25zU3RyCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEXa2V5TnVtUHJvcG9zYWxzQnlBdXRob3IBBQZhdXRob3IFFG51bVByb3Bvc2Fsc0J5QXV0aG9yCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEVa2V5U3RhdHNVbmlxdWVBdXRob3JzAAULdW5pcUF1dGhvcnMFA25pbAUMcHJvcG9zYWxUeElkCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQ1jYWxjV2luT3B0aW9uBwpwcm9wb3NhbElkC29wdGlvbnNMaXN0DmlzUHJldk9wdGlvbmFsCW9sZENob2ljZRBvcHRpb25hbFRvdGFsT2xkCW5ld0Nob2ljZRNuZXdUb3RhbEJ5TmV3Q2hvaWNlCgEIZmluZEJlc3QCA2FjYwRlbGVtBANpZHgJAQV2YWx1ZQEJAM8IAgULb3B0aW9uc0xpc3QFBGVsZW0EA3ZhbAMFDmlzUHJldk9wdGlvbmFsAwkAAAIFA2lkeAUJbmV3Q2hvaWNlBRNuZXdUb3RhbEJ5TmV3Q2hvaWNlCQEMZ2V0SW50T3JFbHNlAgkBHWtleVByb3Bvc2FsVm90ZXNCeUlkQW5kT3B0aW9uAgUKcHJvcG9zYWxJZAUDaWR4AAADCQAAAgUDaWR4CQEFdmFsdWUBBQlvbGRDaG9pY2UFEG9wdGlvbmFsVG90YWxPbGQDCQAAAgUDaWR4BQluZXdDaG9pY2UFE25ld1RvdGFsQnlOZXdDaG9pY2UJAQxnZXRJbnRPckVsc2UCCQEda2V5UHJvcG9zYWxWb3Rlc0J5SWRBbmRPcHRpb24CBQpwcm9wb3NhbElkBQNpZHgAAAMJAGYCCAUDYWNjAl8yBQN2YWwFA2FjYwkAlAoCBQNpZHgFA3ZhbAoAAiRsBQtvcHRpb25zTGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgAAAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCGZpbmRCZXN0AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKARB1cGRhdGVTdGF0dXNEYXRhBAdvbGREYXRhB2lzVmFsaWQJbmV3V2luT3B0DW5ld1RvdGFsVm90ZXMJALkJAgkAzAgCAg4lYiVkJWQlZCViJWQlYgkAzAgCCQClAwEFB2lzVmFsaWQJAMwIAgkApAMBCAUJbmV3V2luT3B0Al8xCQDMCAIJAKQDAQgFCW5ld1dpbk9wdAJfMgkAzAgCCQCkAwEFDW5ld1RvdGFsVm90ZXMJAMwIAgkAkQMCBQdvbGREYXRhBRVnb3ZTdGF0dXNJZHhTY0FwcGxpZWQJAMwIAgkAkQMCBQdvbGREYXRhBRJnb3ZTdGF0dXNJZHhTY1RpbWUJAMwIAgkAkQMCBQdvbGREYXRhBRZnb3ZTdGF0dXNJZHhJc0NhbmNlbGVkBQNuaWwFA1NFUAERc3RhdHVzQXBwbHlTY3JpcHQBB29sZERhdGEJALkJAgkAzAgCAg4lYiVkJWQlZCViJWQlYgkAzAgCCQCRAwIFB29sZERhdGEFE2dvdlN0YXR1c0lkeElzVmFsaWQJAMwIAgkAkQMCBQdvbGREYXRhBRJnb3ZTdGF0dXNJZHhXaW5PcHQJAMwIAgkAkQMCBQdvbGREYXRhBRRnb3ZTdGF0dXNJZHhXaW5Wb3RlcwkAzAgCCQCRAwIFB29sZERhdGEFFmdvdlN0YXR1c0lkeFRvdGFsVm90ZXMJAMwIAgIEdHJ1ZQkAzAgCCQCRAwIFB29sZERhdGEFEmdvdlN0YXR1c0lkeFNjVGltZQkAzAgCCQCRAwIFB29sZERhdGEFFmdvdlN0YXR1c0lkeElzQ2FuY2VsZWQFA25pbAUDU0VQARBFeGVjdXRpb25IaXN0b3J5BA11cGRhdGVWZXJzaW9uBXRpdGxlA3VybApwcm9wb3NhbElkBApnbnNidFRvdGFsCQCRAwIJARFnZXRFZmZlY3RpdmVHbnNidAECAAULSWR4RWZmVG90YWwEB3R1cm5vdXQAoMIeCQELU3RyaW5nRW50cnkCCQEPa2V5QXBwbHlIaXN0b3J5AQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJALkJAgkAzAgCAgwlZCVkJWQlcyVzJWQJAMwIAgkApAMBBQ11cGRhdGVWZXJzaW9uCQDMCAIJAKQDAQUKZ25zYnRUb3RhbAkAzAgCCQCkAwEFB3R1cm5vdXQJAMwIAgUFdGl0bGUJAMwIAgUDdXJsCQDMCAIJAKQDAQUKcHJvcG9zYWxJZAUDbmlsBQNTRVAHAWkBC2NvbnN0cnVjdG9yBQtjb250cm9sQWRkcg5nTnNidFJlcVRvSW5pdA53YXZlc1JlcVRvSW5pdBFxdW9ydW1SZXFQZXJjSWRlYRNxdW9ydW1SZXFQZXJjVXBkYXRlAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIRUGVybWlzc2lvbiBkZW5pZWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleUNvbnRyb2xBZGRyZXNzAAULY29udHJvbEFkZHIJAMwIAgkBDEludGVnZXJFbnRyeQIJARBrZXlHbnNidFJlcXVpcmVkAAUOZ05zYnRSZXFUb0luaXQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJrZXlQYXltZW50UmVxdWlyZWQABQ53YXZlc1JlcVRvSW5pdAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBGGtleVF1b3J1bVJlcXVpcmVkUGVyY2VudAECBElERUEFEXF1b3J1bVJlcVBlcmNJZGVhCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEYa2V5UXVvcnVtUmVxdWlyZWRQZXJjZW50AQIGVVBEQVRFBRNxdW9ydW1SZXFQZXJjVXBkYXRlBQNuaWwBaQEIY2FzdFZvdGUCCnByb3Bvc2FsSWQGY2hvaWNlBA51c2VyQWRkcmVzc1N0cgkApQgBCAUBaQZjYWxsZXIEC2R5bmFtaWNEYXRhCQC1CQIJAQ9nZXRTdHJpbmdPckZhaWwCBQR0aGlzCQEZa2V5UHJvcG9zYWxTdGF0dXNEYXRhQnlJZAEFCnByb3Bvc2FsSWQFA1NFUAMJAAACCQCRAwIFC2R5bmFtaWNEYXRhBRZnb3ZTdGF0dXNJZHhJc0NhbmNlbGVkAgR0cnVlCQACAQIaVm90aW5nIGlzIGNhbmNlbGVkIGJ5IHRlYW0ECHByb3BEYXRhCQC1CQIJAQ9nZXRTdHJpbmdPckZhaWwCBQR0aGlzCQETa2V5UHJvcG9zYWxEYXRhQnlJZAEFCnByb3Bvc2FsSWQFA1NFUAQFc3RhcnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhwcm9wRGF0YQULZ292SWR4U3RhcnQEA2VuZAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHByb3BEYXRhBQlnb3ZJZHhFbmQEA25vdwgFCWxhc3RCbG9jawl0aW1lc3RhbXADCQBmAgUFc3RhcnQFA25vdwkAAgECFlZvdGluZyBub3Qgc3RhcnRlZCB5ZXQDCQBnAgUDbm93BQNlbmQJAAIBAhdWb3RpbmcgYWxyZWFkeSBmaW5pc2hlZAQQYXZhaWxhYmxlT3B0aW9ucwkAtQkCCQCRAwIFCHByb3BEYXRhBQ1nb3ZJZHhPcHRpb25zBQdMSVNUU0VQBApudW1PcHRpb25zCQCQAwEFEGF2YWlsYWJsZU9wdGlvbnMDCQBnAgABBQpudW1PcHRpb25zCQACAQIXVG9vIGZldyBjaG9pY2VzIHRvIHZvdGUDCQBnAgUGY2hvaWNlBQpudW1PcHRpb25zCQACAQkArAICAhtVbmtub3duIGNob2ljZSEgTXVzdCBiZSAwLi4JAKQDAQkAZQIFCm51bU9wdGlvbnMAAQQDZWZmCQERZ2V0RWZmZWN0aXZlR25zYnQBBQ51c2VyQWRkcmVzc1N0cgQIZ25zYnRBbXQJAJEDAgUDZWZmBQpJZHhFZmZVc2VyAwkAZwIAAAUIZ25zYnRBbXQJAAIBAhBubyBnbnNidCB0byB2b3RlBApnbnNidFRvdGFsCQCRAwIFA2VmZgULSWR4RWZmVG90YWwECW9sZENob2ljZQkAnwgBCQEca2V5UHJvcG9zYWxDaG9pY2VCeUlkQW5kVXNlcgIFCnByb3Bvc2FsSWQFDnVzZXJBZGRyZXNzU3RyBAxvbGRVc2VyVm90ZXMDCQEBIQEJAQlpc0RlZmluZWQBBQlvbGRDaG9pY2UAAAkBDGdldEludE9yRWxzZQIJARtrZXlQcm9wb3NhbFZvdGVzQnlJZEFuZFVzZXICBQpwcm9wb3NhbElkBQ51c2VyQWRkcmVzc1N0cgAABBNvbGRUb3RhbEJ5T2xkQ2hvaWNlAwkBCWlzRGVmaW5lZAEFCW9sZENob2ljZQkBDGdldEludE9yRWxzZQIJAR1rZXlQcm9wb3NhbFZvdGVzQnlJZEFuZE9wdGlvbgIFCnByb3Bvc2FsSWQJAQV2YWx1ZQEFCW9sZENob2ljZQAAAAAEE29sZFRvdGFsQnlOZXdDaG9pY2UJAQxnZXRJbnRPckVsc2UCCQEda2V5UHJvcG9zYWxWb3Rlc0J5SWRBbmRPcHRpb24CBQpwcm9wb3NhbElkBQZjaG9pY2UAAAQIb2xkVG90YWwJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQtkeW5hbWljRGF0YQUWZ292U3RhdHVzSWR4VG90YWxWb3RlcwQTbmV3VG90YWxCeU9sZENob2ljZQMJAQEhAQkBCWlzRGVmaW5lZAEFCW9sZENob2ljZQAACQBkAgkAZQIFE29sZFRvdGFsQnlPbGRDaG9pY2UFDG9sZFVzZXJWb3RlcwMJAAACCQEFdmFsdWUBBQlvbGRDaG9pY2UFBmNob2ljZQUIZ25zYnRBbXQAAAQTbmV3VG90YWxCeU5ld0Nob2ljZQMDCQEJaXNEZWZpbmVkAQUJb2xkQ2hvaWNlCQAAAgkBBXZhbHVlAQUJb2xkQ2hvaWNlBQZjaG9pY2UHBRNuZXdUb3RhbEJ5T2xkQ2hvaWNlCQBkAgUTb2xkVG90YWxCeU5ld0Nob2ljZQUIZ25zYnRBbXQECG5ld1RvdGFsCQBkAgkAZQIFCG9sZFRvdGFsBQxvbGRVc2VyVm90ZXMFCGduc2J0QW10BA9pc1F1b3J1bVJlYWNoZWQJAGcCBQhuZXdUb3RhbAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHByb3BEYXRhBQxnb3ZJZHhRdW9ydW0EFW51bVZvdGVyc0J5UHJvcG9zYWxJZAkBDGdldEludE9yRWxzZQIJAR5rZXlOdW1VbmlxdWVWb3RlcnNCeVByb3Bvc2FsSWQBBQpwcm9wb3NhbElkAAAEFG9sZEF2ZXJVbmlxdWVWb3RlcnM2CQEMZ2V0SW50T3JFbHNlAgkBGGtleVN0YXRzQXZlclVuaXF1ZVZvdGVycwAAAAQMbnVtUHJvcG9zYWxzCQERQGV4dHJOYXRpdmUoMTA1NSkBCQERa2V5TGFzdFByb3Bvc2FsSWQABAp1bmlxdWVEaWZmAwkAAAIFDG9sZFVzZXJWb3RlcwAAAAEAAAQUbmV3QXZlclVuaXF1ZVZvdGVyczYJAGQCBRRvbGRBdmVyVW5pcXVlVm90ZXJzNgkAawMFCnVuaXF1ZURpZmYFBU1VTFQ2BQxudW1Qcm9wb3NhbHMEDG9sZEF2ZXJHbnNidAkBDGdldEludE9yRWxzZQIJARZrZXlTdGF0c0F2ZXJHbnNidFZvdGVkAAAABAxuZXdBdmVyR25zYnQJAGQCBQxvbGRBdmVyR25zYnQJAGkCCQBlAgUIZ25zYnRBbXQFDG9sZFVzZXJWb3RlcwUMbnVtUHJvcG9zYWxzBA5pc1ByZXZPcHRpb25hbAMJAQEhAQkBCWlzRGVmaW5lZAEFCW9sZENob2ljZQYJAAACCQEFdmFsdWUBBQlvbGRDaG9pY2UFBmNob2ljZQQQb3B0aW9uYWxUb3RhbE9sZAMFDmlzUHJldk9wdGlvbmFsBQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAR1rZXlQcm9wb3NhbFZvdGVzQnlJZEFuZE9wdGlvbgIFCnByb3Bvc2FsSWQJAQV2YWx1ZQEFCW9sZENob2ljZQUTbmV3VG90YWxCeU9sZENob2ljZQUDbmlsBAZ3aW5PcHQJAQ1jYWxjV2luT3B0aW9uBwUKcHJvcG9zYWxJZAUQYXZhaWxhYmxlT3B0aW9ucwUOaXNQcmV2T3B0aW9uYWwFCW9sZENob2ljZQUTbmV3VG90YWxCeU9sZENob2ljZQUGY2hvaWNlBRNuZXdUb3RhbEJ5TmV3Q2hvaWNlBAtyZWxlYXNlVGltZQkAlgMBCQDMCAIFA2VuZAkAzAgCCQEMZ2V0SW50T3JFbHNlAgkBF2tleVVzZXJHbnNidFJlbGVhc2VUaW1lAQUOdXNlckFkZHJlc3NTdHIAAAUDbmlsCQCUCgIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHGtleVByb3Bvc2FsQ2hvaWNlQnlJZEFuZFVzZXICBQpwcm9wb3NhbElkBQ51c2VyQWRkcmVzc1N0cgUGY2hvaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEba2V5UHJvcG9zYWxWb3Rlc0J5SWRBbmRVc2VyAgUKcHJvcG9zYWxJZAUOdXNlckFkZHJlc3NTdHIFCGduc2J0QW10CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEda2V5UHJvcG9zYWxWb3Rlc0J5SWRBbmRPcHRpb24CBQpwcm9wb3NhbElkBQZjaG9pY2UFE25ld1RvdGFsQnlOZXdDaG9pY2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAR5rZXlOdW1VbmlxdWVWb3RlcnNCeVByb3Bvc2FsSWQBBQpwcm9wb3NhbElkCQBkAgUVbnVtVm90ZXJzQnlQcm9wb3NhbElkBQp1bmlxdWVEaWZmCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEXa2V5VXNlckduc2J0UmVsZWFzZVRpbWUBBQ51c2VyQWRkcmVzc1N0cgULcmVsZWFzZVRpbWUJAMwIAgkBDEludGVnZXJFbnRyeQIJARhrZXlTdGF0c0F2ZXJVbmlxdWVWb3RlcnMABRRuZXdBdmVyVW5pcXVlVm90ZXJzNgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleVN0YXRzQXZlckduc2J0Vm90ZWQABQxuZXdBdmVyR25zYnQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBGWtleVByb3Bvc2FsU3RhdHVzRGF0YUJ5SWQBBQpwcm9wb3NhbElkCQEQdXBkYXRlU3RhdHVzRGF0YQQFC2R5bmFtaWNEYXRhBQ9pc1F1b3J1bVJlYWNoZWQFBndpbk9wdAUIbmV3VG90YWwFA25pbAUQb3B0aW9uYWxUb3RhbE9sZAUEdW5pdAFpARJpbml0aWF0ZUlkZWFWb3RpbmcFCWZvcnVtTGluawV0aXRsZQ92b3RpbmdTdGFydFRpbWUNdm90aW5nRW5kVGltZQtvcHRpb25zTGlzdAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQDCQECIT0CCQCQAwEFC29wdGlvbnNMaXN0AAIJAAIBAitFeGFjdGx5IDIgb3B0aW9uIFsnTk8nLCAnWUVTJ10gYXJlIGV4cGVjdGVkAwkBAiE9AgkAkQMCBQtvcHRpb25zTGlzdAAAAgJOTwkAAgECHU9wdGlvbiBOTyBzaG91bGQgYmUgdGhlIGZpcnN0AwkBAiE9AgkAkQMCBQtvcHRpb25zTGlzdAABAgNZRVMJAAIBAh9PcHRpb24gWUVTIHNob3VsZCBiZSB0aGUgc2Vjb25kCQEOaW5pdGlhdGVWb3RpbmcLCQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAJANgEAQgFAWkNdHJhbnNhY3Rpb25JZAIESURFQQkApQgBCAUBaQZjYWxsZXIFCWZvcnVtTGluawUFdGl0bGUFD3ZvdGluZ1N0YXJ0VGltZQUNdm90aW5nRW5kVGltZQIHUEVORElORwUDbmlsBQtvcHRpb25zTGlzdAFpARRpbml0aWF0ZVVwZGF0ZVZvdGluZwUJZm9ydW1MaW5rBXRpdGxlD3ZvdGluZ1N0YXJ0VGltZQ12b3RpbmdFbmRUaW1lBnR4TGlzdAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQDCQBmAgABCQCQAwEFBnR4TGlzdAkAAgECGlRyYW5zYWN0aW9ucyBsaXN0IGlzIGVtcHR5AwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIObm90IGF1dGhvcml6ZWQJAQ5pbml0aWF0ZVZvdGluZwsJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAkA2AQBCAUBaQ10cmFuc2FjdGlvbklkAgZVUERBVEUJAKUIAQgFAWkGY2FsbGVyBQlmb3J1bUxpbmsFBXRpdGxlBQ92b3RpbmdTdGFydFRpbWUFDXZvdGluZ0VuZFRpbWUCB1BFTkRJTkcFBnR4TGlzdAkAzAgCAgJOTwkAzAgCAgNZRVMFA25pbAFpAQxjYW5jZWxWb3RpbmcBCnByb3Bvc2FsSWQDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAg5ub3QgYXV0aG9yaXplZAQLY3VycmVudERhdGEJAQ9nZXRTdHJpbmdPckZhaWwCBQR0aGlzCQEZa2V5UHJvcG9zYWxTdGF0dXNEYXRhQnlJZAEFCnByb3Bvc2FsSWQEC3VwZGF0ZWREYXRhCQCsAgIJAKwCAgkArwICBQtjdXJyZW50RGF0YQkBBXZhbHVlAQkAtwkCBQtjdXJyZW50RGF0YQUDU0VQBQNTRVACBHRydWUJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCCQEZa2V5UHJvcG9zYWxTdGF0dXNEYXRhQnlJZAEFCnByb3Bvc2FsSWQFC3VwZGF0ZWREYXRhBQNuaWwFBHVuaXQBaQELYXBwbHlVcGRhdGUBCnByb3Bvc2FsSWQECHByb3BEYXRhCQC1CQIJAQ9nZXRTdHJpbmdPckZhaWwCBQR0aGlzCQETa2V5UHJvcG9zYWxEYXRhQnlJZAEFCnByb3Bvc2FsSWQFA1NFUAQDZW5kCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIcHJvcERhdGEFCWdvdklkeEVuZAQDbm93CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAMJAGYCBQNlbmQFA25vdwkAAgECGlZvdGluZyBpcyBub3QgZmluaXNoZWQgeWV0AwkBAiE9AgIGVVBEQVRFCQCRAwIFCHByb3BEYXRhBQpnb3ZJZHhUeXBlCQACAQIfT25seSBVUERBVEUgdHlwZSBjYW4gYmUgYXBwbGllZAQLZHluYW1pY0RhdGEJALUJAgkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMJARlrZXlQcm9wb3NhbFN0YXR1c0RhdGFCeUlkAQUKcHJvcG9zYWxJZAUDU0VQAwkAAAIJAJEDAgULZHluYW1pY0RhdGEFFmdvdlN0YXR1c0lkeElzQ2FuY2VsZWQCBHRydWUJAAIBAhJWb3RpbmcgaXMgY2FuY2VsZWQDCQECIT0CCQCRAwIFC2R5bmFtaWNEYXRhBRNnb3ZTdGF0dXNJZHhJc1ZhbGlkAgR0cnVlCQACAQIVVm90aW5nIHN0YXR1cyBpbnZhbGlkAwkBAiE9AgkAkQMCBQtkeW5hbWljRGF0YQUSZ292U3RhdHVzSWR4V2luT3B0AgExCQACAQIhV2lubmVyIGlzICdOTycgLSBub3RoaW5nIHRvIGFwcGx5AwkAAAIJAJEDAgULZHluYW1pY0RhdGEFFWdvdlN0YXR1c0lkeFNjQXBwbGllZAIEdHJ1ZQkAAgECG1NjcmlwdHMgYXJlIGFscmVhZHkgYXBwbGllZAQKc2NyaXB0VGltZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFC2R5bmFtaWNEYXRhBRJnb3ZTdGF0dXNJZHhTY1RpbWUDCQBmAgkAZQIFA25vdwUKUEFTVE1BUkdJTgUKc2NyaXB0VGltZQkAAgEJAKwCAgkArAICAhJTY3JpcHRzIHRpbWVzdGFtcD0JAKQDAQUKc2NyaXB0VGltZQIqIGlzIHRvbyBmYXIgaW4gdGhlIHBhc3QsIG1heCAyIGhycyBhbGxvd2VkAwkAZgIFCnNjcmlwdFRpbWUJAGQCBQNub3cFDEZVVFVSRU1BUkdJTgkAAgEJAKwCAgkArAICAhJTY3JpcHRzIHRpbWVzdGFtcD0JAKQDAQUKc2NyaXB0VGltZQIuIGlzIHRvbyBmYXIgaW4gdGhlIGZ1dHVyZSwgbWF4IDEuNSBocnMgYWxsb3dlZAQMaW5Qcm9ncmVzc0lkCQEMZ2V0SW50T3JFbHNlAgkBEmtleUFwcGx5SW5Qcm9ncmVzcwAA////////////AQMJAQIhPQIFDGluUHJvZ3Jlc3NJZAD///////////8BCQACAQkArAICCQCsAgICC3Byb3Bvc2FsSWQ9CQCkAwEFDGluUHJvZ3Jlc3NJZAIrIGlzIGFscmVhZHkgYmVpbmcgYXBwbGllZC4gRmluaXNoIGl0IGZpcnN0IQQIc2h1dGRvd24JAPwHBAUPY29udHJvbENvbnRyYWN0AhVjYWxsRW1lcmdlbmN5U2h1dGRvd24JAMwIAgIaQXBwbHlpbmcgR292ZXJuYW5jZSBVUERBVEUFA25pbAUDbmlsAwkAAAIFCHNodXRkb3duBQhzaHV0ZG93bgkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESa2V5QXBwbHlJblByb2dyZXNzAAUKcHJvcG9zYWxJZAUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBC2ZpbmlzaEFwcGx5AAQKcHJvcG9zYWxJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEJARJrZXlBcHBseUluUHJvZ3Jlc3MAAidObyBhcHBseSBpbiBwcm9ncmVzcywgbm90aGluZyB0byBmaW5pc2gECHByb3BEYXRhCQC1CQIJAQ9nZXRTdHJpbmdPckZhaWwCBQR0aGlzCQETa2V5UHJvcG9zYWxEYXRhQnlJZAEFCnByb3Bvc2FsSWQFA1NFUAQGdHhMaXN0CQC1CQIJAJEDAgUIcHJvcERhdGEFC2dvdklkeFR4SWRzBQdMSVNUU0VQBAtkeW5hbWljRGF0YQkAtQkCCQEPZ2V0U3RyaW5nT3JGYWlsAgUEdGhpcwkBGWtleVByb3Bvc2FsU3RhdHVzRGF0YUJ5SWQBBQpwcm9wb3NhbElkBQNTRVADCQAAAgkAkQMCBQtkeW5hbWljRGF0YQUVZ292U3RhdHVzSWR4U2NBcHBsaWVkAgR0cnVlCQACAQIbU2NyaXB0cyBhcmUgYWxyZWFkeSBhcHBsaWVkCgEHY2hlY2tlcgIDYWNjAnR4AwkBASEBCQEJaXNEZWZpbmVkAQkA6QcBCQDZBAEFAnR4CQACAQkArAICAhJOT1QgYXBwbGllZCB0eElkOiAFAnR4BQR1bml0BAdpZ25vcmVkCgACJGwFBnR4TGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFBHVuaXQKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB2NoZWNrZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAQHdmVyc2lvbgkAZAIJAQxnZXRJbnRPckVsc2UCCQEUa2V5TGFzdFVwZGF0ZVZlcnNpb24AAAAAAQkAlAoCCQDMCAIJAQtEZWxldGVFbnRyeQEJARJrZXlBcHBseUluUHJvZ3Jlc3MACQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEUa2V5TGFzdFVwZGF0ZVZlcnNpb24ABQd2ZXJzaW9uCQDMCAIJAQtTdHJpbmdFbnRyeQIJARlrZXlQcm9wb3NhbFN0YXR1c0RhdGFCeUlkAQUKcHJvcG9zYWxJZAkBEXN0YXR1c0FwcGx5U2NyaXB0AQULZHluYW1pY0RhdGEJAMwIAgkBEEV4ZWN1dGlvbkhpc3RvcnkEBQd2ZXJzaW9uCQCRAwIFCHByb3BEYXRhBQtnb3ZJZHhUaXRsZQkAkQMCBQhwcm9wRGF0YQUJZ292SWR4VXJsBQpwcm9wb3NhbElkBQNuaWwFB2lnbm9yZWQAAIfGLw==", "height": 2332761, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 7yi5kjcnMygdpLjk43ua7TnSBwiqNdAfrXZqrffrb2ZY Next: GxL9CvM9LxmCNdf1RrDZFwMfLEhe8SWsSvSPpLvvbZ78 Diff:
OldNewDifferences
340340 func statusApplyScript (oldData) = makeString(["%b%d%d%d%b%d%b", oldData[govStatusIdxIsValid], oldData[govStatusIdxWinOpt], oldData[govStatusIdxWinVotes], oldData[govStatusIdxTotalVotes], "true", oldData[govStatusIdxScTime], oldData[govStatusIdxIsCanceled]], SEP)
341341
342342
343-func ExecutionHistory (proposalId,title,url) = {
343+func ExecutionHistory (updateVersion,title,url,proposalId) = {
344344 let gnsbtTotal = getEffectiveGnsbt("")[IdxEffTotal]
345345 let turnout = 500000
346- StringEntry(keyApplyHistory(lastBlock.timestamp), makeString(["%d%d%d%s%s", toString(proposalId), toString(gnsbtTotal), toString(turnout), title, url], SEP))
346+ StringEntry(keyApplyHistory(lastBlock.timestamp), makeString(["%d%d%d%s%s%d", toString(updateVersion), toString(gnsbtTotal), toString(turnout), title, url, toString(proposalId)], SEP))
347347 }
348348
349349
535535 $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($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
536536 }
537537 let version = (getIntOrElse(keyLastUpdateVersion(), 0) + 1)
538- $Tuple2([DeleteEntry(keyApplyInProgress()), IntegerEntry(keyLastUpdateVersion(), version), StringEntry(keyProposalStatusDataById(proposalId), statusApplyScript(dynamicData)), ExecutionHistory(version, propData[govIdxTitle], propData[govIdxUrl])], ignored)
538+ $Tuple2([DeleteEntry(keyApplyInProgress()), IntegerEntry(keyLastUpdateVersion(), version), StringEntry(keyProposalStatusDataById(proposalId), statusApplyScript(dynamicData)), ExecutionHistory(version, propData[govIdxTitle], propData[govIdxUrl], proposalId)], ignored)
539539 }
540540 }
541541
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let revisionNum = ""
55
66 let SEP = "__"
77
88 let LISTSEP = ":"
99
1010 let DEFAULTQUORUM = 500000
1111
1212 let URLPATTERN = "https://forum.neutrino.at/"
1313
1414 let MAXTITLE = 160
1515
1616 let MAXURL = 250
1717
1818 let MAXVOTINGTIME = 1209600000
1919
2020 let MULT6 = 1000000
2121
2222 let DEFAULTPAYMENT = 1000000000
2323
2424 let DEFAULTCREATIONGNSBT = 1000000000
2525
2626 let PASTMARGIN = 7200000
2727
2828 let FUTUREMARGIN = 5400000
2929
3030 let govIdxProposalTxId = 1
3131
3232 let govIdxType = 2
3333
3434 let govIdxAuthor = 3
3535
3636 let govIdxUrl = 4
3737
3838 let govIdxTitle = 5
3939
4040 let govIdxCreationTime = 6
4141
4242 let govIdxStart = 7
4343
4444 let govIdxEnd = 8
4545
4646 let govIdxTxIds = 9
4747
4848 let govIdxQuorum = 10
4949
5050 let govIdxOptions = 11
5151
5252 let govStatusIdxIsValid = 1
5353
5454 let govStatusIdxWinOpt = 2
5555
5656 let govStatusIdxWinVotes = 3
5757
5858 let govStatusIdxTotalVotes = 4
5959
6060 let govStatusIdxScApplied = 5
6161
6262 let govStatusIdxScTime = 6
6363
6464 let govStatusIdxIsCanceled = 7
6565
6666 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
6767
6868
6969 func getIntOrElse (key,defaultVal) = valueOrElse(getInteger(this, key), defaultVal)
7070
7171
7272 let IdxControlCfgNeutrinoDapp = 1
7373
7474 let IdxControlCfgAuctionDapp = 2
7575
7676 let IdxControlCfgRpdDapp = 3
7777
7878 let IdxControlCfgMathDapp = 4
7979
8080 let IdxControlCfgLiquidationDapp = 5
8181
8282 let IdxControlCfgRestDapp = 6
8383
8484 let IdxControlCfgNodeRegistryDapp = 7
8585
8686 let IdxControlCfgNsbtStakingDapp = 8
8787
8888 let IdxControlCfgMediatorDapp = 9
8989
9090 let IdxControlCfgSurfStakingDapp = 10
9191
9292 let IdxControlCfgGnsbtControllerDapp = 11
9393
9494 let IdxControlCfgRestV2Dapp = 12
9595
9696 let IdxControlCfgGovernanceDapp = 13
9797
9898 func keyControlAddress () = "%s%s__config__controlAddress"
9999
100100
101101 func keyControlCfg () = "%s__controlConfig"
102102
103103
104104 func readControlCfgOrFail (control) = split_4C(getStringOrFail(control, keyControlCfg()), SEP)
105105
106106
107107 func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
108108
109109
110110 let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP"))
111111
112112 let controlCfg = readControlCfgOrFail(controlContract)
113113
114114 let neutrinoContract = getContractAddressOrFail(controlCfg, IdxControlCfgNeutrinoDapp)
115115
116116 let gnsbtControllerContract = getContractAddressOrFail(controlCfg, IdxControlCfgGnsbtControllerDapp)
117117
118118 func keyQuorumRequiredPercent (type) = ("%s%s__quorumRequired__" + type)
119119
120120
121121 func keyPaymentRequired () = "%s__paymentRequired"
122122
123123
124124 func keyGnsbtRequired () = "%s__gNsbtRequired"
125125
126126
127127 func keyLastProposalId () = "%s__proposalId"
128128
129129
130130 func keyLastUpdateVersion () = "%s__updateVersion"
131131
132132
133133 func keyProposalStatusDataById (proposalId) = ("%s%d__proposalStatusData__" + toString(proposalId))
134134
135135
136136 func keyProposalDataById (proposalId) = ("%s%d__proposalData__" + toString(proposalId))
137137
138138
139139 func keyProposalVotesByIdAndOption (proposalId,opt) = makeString(["%s%d%d", "votesByOpt", toString(proposalId), toString(opt)], SEP)
140140
141141
142142 func keyProposalVotesByIdAndUser (proposalId,userAddr) = makeString(["%s%d%s", "votesByUser", toString(proposalId), userAddr], SEP)
143143
144144
145145 func keyProposalChoiceByIdAndUser (proposalId,userAddr) = makeString(["%s%d%s", "optionByUser", toString(proposalId), userAddr], SEP)
146146
147147
148148 func keyApplyInProgress () = "%s__applyInProgress"
149149
150150
151151 func keyProposalIdByTopicId (topicId) = ("%s%d__proposalIdByTopicId__" + toString(topicId))
152152
153153
154154 func keyUserGnsbtReleaseTime (userAddr) = ("%s%s_userGnsbtReleaseTime__" + userAddr)
155155
156156
157157 func keyNumUniqueVotersByProposalId (proposalId) = ("%s%d__numVoters__" + toString(proposalId))
158158
159159
160160 func keyStatsAverUniqueVoters () = "%s%s%s__stats__avg__uniqueVoters"
161161
162162
163163 func keyStatsAverGnsbtVoted () = "%s%s%s__stats__avg__gnsbtVoted"
164164
165165
166166 func keyStatsUniqueAuthors () = "%s%s__stats__uniqueAuthors"
167167
168168
169169 func keyNumProposalsByAuthor (addressStr) = ("%s%s__numProposalsByAuthor__" + addressStr)
170170
171171
172172 func keyApplyHistory (timestamp) = ("%s%d__applyHistory__" + toString(timestamp))
173173
174174
175175 func asAnyList (v) = match v {
176176 case l: List[Any] =>
177177 l
178178 case _ =>
179179 throw("fail to cast into List[Any]")
180180 }
181181
182182
183183 func asInt (v) = match v {
184184 case i: Int =>
185185 i
186186 case _ =>
187187 throw("fail to cast into Int")
188188 }
189189
190190
191191 func statusData (isVotingValid,winOption,winOptionVotes,totalVotes,areScriptsApplied,scriptsTimestamp,canceledByTeam) = makeString(["%b%d%d%d%b%d%b", toString(isVotingValid), toString(winOption), toString(winOptionVotes), toString(totalVotes), toString(areScriptsApplied), toString(scriptsTimestamp), toString(canceledByTeam)], SEP)
192192
193193
194194 func proposalData (proposalTxId,type,author,forumLink,title,proposalTime,votingStartTime,votingEndTime,txIds,quorumInGnsbt,options) = makeString(["%s%s%s%s%s%d%d%d%s%d%s", proposalTxId, type, author, forumLink, title, toString(proposalTime), toString(votingStartTime), toString(votingEndTime), txIds, toString(quorumInGnsbt), options], SEP)
195195
196196
197197 func checkTxList (txList) = if ((size(txList) > 20))
198198 then throw(("Too many transactions: " + toString(size(txList))))
199199 else {
200200 func combiner (acc,tx) = if ((size(fromBase58String(tx)) != 32))
201201 then throw(("Wrong txId: " + tx))
202202 else if ((acc == ""))
203203 then tx
204204 else ((acc + LISTSEP) + tx)
205205
206206 let $l = txList
207207 let $s = size($l)
208208 let $acc0 = ""
209209 func $f0_1 ($a,$i) = if (($i >= $s))
210210 then $a
211211 else combiner($a, $l[$i])
212212
213213 func $f0_2 ($a,$i) = if (($i >= $s))
214214 then $a
215215 else throw("List size exceeds 20")
216216
217217 $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($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
218218 }
219219
220220
221221 let IdxEffTotal = 0
222222
223223 let IdxEffUser = 1
224224
225225 func getEffectiveGnsbt (userAddrStrOrEmpty) = {
226226 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", [userAddrStrOrEmpty, 0, 0], nil))
227227 let nsbtData = asAnyList(gnsbtData[2])
228228 let userFromNsbt = asInt(nsbtData[2])
229229 let totalFromNsbt = asInt(nsbtData[3])
230230 let userMatureFromSurf = asInt(gnsbtData[9])
231231 let totalMatureFromSurf = asInt(gnsbtData[6])
232232 [(totalFromNsbt + totalMatureFromSurf), (userFromNsbt + userMatureFromSurf)]
233233 }
234234
235235
236236 func validateLink (url) = if ((value(indexOf(url, URLPATTERN)) != 0))
237237 then throw("Invalid url")
238238 else if ((size(url) > MAXURL))
239239 then throw("Url too long!")
240240 else {
241241 let topicId = valueOrErrorMessage(parseInt(drop(url, (value(lastIndexOf(url, "/")) + 1))), "Wrong topicId")
242242 let registeredId = getInteger(keyProposalIdByTopicId(topicId))
243243 if (isDefined(registeredId))
244244 then throw(("Voting with such forum link is already registered by id=" + toString(value(registeredId))))
245245 else topicId
246246 }
247247
248248
249249 func initiateVoting (payment,proposalTxId,type,author,forumLink,title,votingStartTime,votingEndTime,status,txList,optionsList) = if ((payment.assetId != unit))
250250 then throw("Allowed WAVES payment only!")
251251 else {
252252 let pmtReq = getIntOrElse(keyPaymentRequired(), DEFAULTPAYMENT)
253253 if ((pmtReq > payment.amount))
254254 then throw(("Payment attached should be at least " + toString(pmtReq)))
255255 else {
256256 let topicId = validateLink(forumLink)
257257 if ((title == ""))
258258 then throw("Title is empty")
259259 else if ((size(title) > MAXTITLE))
260260 then throw("Too long title")
261261 else {
262262 let proposalTime = lastBlock.timestamp
263263 if ((proposalTime > votingStartTime))
264264 then throw(((("votingStartTime=" + toString(votingStartTime)) + " < proposalTime=") + toString(proposalTime)))
265265 else if ((votingStartTime > votingEndTime))
266266 then throw(((("votingEndTime=" + toString(votingEndTime)) + " < votingStartTime=") + toString(votingStartTime)))
267267 else if (((votingEndTime - votingStartTime) > MAXVOTINGTIME))
268268 then throw(((("Voting period exceeds max: " + toString((votingEndTime - votingStartTime))) + " > ") + toString(MAXVOTINGTIME)))
269269 else {
270270 let txIds = if ((type == "IDEA"))
271271 then ""
272272 else checkTxList(txList)
273273 if ((1 >= size(optionsList)))
274274 then throw("Too few choices to vote")
275275 else {
276276 let eff = getEffectiveGnsbt(author)
277277 let gnsbtTotal = eff[IdxEffTotal]
278278 let gNsbtUser = eff[IdxEffUser]
279279 let gnsbtReq = getIntOrElse(keyGnsbtRequired(), DEFAULTCREATIONGNSBT)
280280 if ((gnsbtReq > gNsbtUser))
281281 then throw((("You need at least " + toString(gnsbtReq)) + " gNsbt to create voting"))
282282 else {
283283 let amountLeased = invoke(neutrinoContract, "acceptWaves", nil, [payment])
284284 if ((amountLeased == amountLeased))
285285 then {
286286 let quorum = getIntOrElse(keyQuorumRequiredPercent(type), DEFAULTQUORUM)
287287 let quorumInGnsbt = fraction(quorum, gnsbtTotal, MULT6)
288288 let proposalId = (getIntOrElse(keyLastProposalId(), 0) + 1)
289289 let numProposalsByAuthor = (getIntOrElse(keyNumProposalsByAuthor(author), 0) + 1)
290290 let uniqAuthors = (getIntOrElse(keyStatsUniqueAuthors(), 0) + (if ((numProposalsByAuthor == 1))
291291 then 1
292292 else 0))
293293 let optionsStr = makeString(optionsList, LISTSEP)
294294 $Tuple2([IntegerEntry(keyLastProposalId(), proposalId), IntegerEntry(keyProposalIdByTopicId(topicId), proposalId), StringEntry(keyProposalStatusDataById(proposalId), statusData(false, 0, 0, 0, false, 0, false)), StringEntry(keyProposalDataById(proposalId), proposalData(proposalTxId, type, author, toBase58String(toBytes(forumLink)), toBase58String(toBytes(title)), proposalTime, votingStartTime, votingEndTime, txIds, quorumInGnsbt, optionsStr)), IntegerEntry(keyNumProposalsByAuthor(author), numProposalsByAuthor), IntegerEntry(keyStatsUniqueAuthors(), uniqAuthors)], proposalTxId)
295295 }
296296 else throw("Strict value is not equal to itself.")
297297 }
298298 }
299299 }
300300 }
301301 }
302302 }
303303
304304
305305 func calcWinOption (proposalId,optionsList,isPrevOptional,oldChoice,optionalTotalOld,newChoice,newTotalByNewChoice) = {
306306 func findBest (acc,elem) = {
307307 let idx = value(indexOf(optionsList, elem))
308308 let val = if (isPrevOptional)
309309 then if ((idx == newChoice))
310310 then newTotalByNewChoice
311311 else getIntOrElse(keyProposalVotesByIdAndOption(proposalId, idx), 0)
312312 else if ((idx == value(oldChoice)))
313313 then optionalTotalOld
314314 else if ((idx == newChoice))
315315 then newTotalByNewChoice
316316 else getIntOrElse(keyProposalVotesByIdAndOption(proposalId, idx), 0)
317317 if ((acc._2 > val))
318318 then acc
319319 else $Tuple2(idx, val)
320320 }
321321
322322 let $l = optionsList
323323 let $s = size($l)
324324 let $acc0 = $Tuple2(0, 0)
325325 func $f0_1 ($a,$i) = if (($i >= $s))
326326 then $a
327327 else findBest($a, $l[$i])
328328
329329 func $f0_2 ($a,$i) = if (($i >= $s))
330330 then $a
331331 else throw("List size exceeds 10")
332332
333333 $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)
334334 }
335335
336336
337337 func updateStatusData (oldData,isValid,newWinOpt,newTotalVotes) = makeString(["%b%d%d%d%b%d%b", toString(isValid), toString(newWinOpt._1), toString(newWinOpt._2), toString(newTotalVotes), oldData[govStatusIdxScApplied], oldData[govStatusIdxScTime], oldData[govStatusIdxIsCanceled]], SEP)
338338
339339
340340 func statusApplyScript (oldData) = makeString(["%b%d%d%d%b%d%b", oldData[govStatusIdxIsValid], oldData[govStatusIdxWinOpt], oldData[govStatusIdxWinVotes], oldData[govStatusIdxTotalVotes], "true", oldData[govStatusIdxScTime], oldData[govStatusIdxIsCanceled]], SEP)
341341
342342
343-func ExecutionHistory (proposalId,title,url) = {
343+func ExecutionHistory (updateVersion,title,url,proposalId) = {
344344 let gnsbtTotal = getEffectiveGnsbt("")[IdxEffTotal]
345345 let turnout = 500000
346- StringEntry(keyApplyHistory(lastBlock.timestamp), makeString(["%d%d%d%s%s", toString(proposalId), toString(gnsbtTotal), toString(turnout), title, url], SEP))
346+ StringEntry(keyApplyHistory(lastBlock.timestamp), makeString(["%d%d%d%s%s%d", toString(updateVersion), toString(gnsbtTotal), toString(turnout), title, url, toString(proposalId)], SEP))
347347 }
348348
349349
350350 @Callable(i)
351351 func constructor (controlAddr,gNsbtReqToInit,wavesReqToInit,quorumReqPercIdea,quorumReqPercUpdate) = if ((i.caller != this))
352352 then throw("Permission denied")
353353 else [StringEntry(keyControlAddress(), controlAddr), IntegerEntry(keyGnsbtRequired(), gNsbtReqToInit), IntegerEntry(keyPaymentRequired(), wavesReqToInit), IntegerEntry(keyQuorumRequiredPercent("IDEA"), quorumReqPercIdea), IntegerEntry(keyQuorumRequiredPercent("UPDATE"), quorumReqPercUpdate)]
354354
355355
356356
357357 @Callable(i)
358358 func castVote (proposalId,choice) = {
359359 let userAddressStr = toString(i.caller)
360360 let dynamicData = split(getStringOrFail(this, keyProposalStatusDataById(proposalId)), SEP)
361361 if ((dynamicData[govStatusIdxIsCanceled] == "true"))
362362 then throw("Voting is canceled by team")
363363 else {
364364 let propData = split(getStringOrFail(this, keyProposalDataById(proposalId)), SEP)
365365 let start = parseIntValue(propData[govIdxStart])
366366 let end = parseIntValue(propData[govIdxEnd])
367367 let now = lastBlock.timestamp
368368 if ((start > now))
369369 then throw("Voting not started yet")
370370 else if ((now >= end))
371371 then throw("Voting already finished")
372372 else {
373373 let availableOptions = split(propData[govIdxOptions], LISTSEP)
374374 let numOptions = size(availableOptions)
375375 if ((1 >= numOptions))
376376 then throw("Too few choices to vote")
377377 else if ((choice >= numOptions))
378378 then throw(("Unknown choice! Must be 0.." + toString((numOptions - 1))))
379379 else {
380380 let eff = getEffectiveGnsbt(userAddressStr)
381381 let gnsbtAmt = eff[IdxEffUser]
382382 if ((0 >= gnsbtAmt))
383383 then throw("no gnsbt to vote")
384384 else {
385385 let gnsbtTotal = eff[IdxEffTotal]
386386 let oldChoice = getInteger(keyProposalChoiceByIdAndUser(proposalId, userAddressStr))
387387 let oldUserVotes = if (!(isDefined(oldChoice)))
388388 then 0
389389 else getIntOrElse(keyProposalVotesByIdAndUser(proposalId, userAddressStr), 0)
390390 let oldTotalByOldChoice = if (isDefined(oldChoice))
391391 then getIntOrElse(keyProposalVotesByIdAndOption(proposalId, value(oldChoice)), 0)
392392 else 0
393393 let oldTotalByNewChoice = getIntOrElse(keyProposalVotesByIdAndOption(proposalId, choice), 0)
394394 let oldTotal = parseIntValue(dynamicData[govStatusIdxTotalVotes])
395395 let newTotalByOldChoice = if (!(isDefined(oldChoice)))
396396 then 0
397397 else ((oldTotalByOldChoice - oldUserVotes) + (if ((value(oldChoice) == choice))
398398 then gnsbtAmt
399399 else 0))
400400 let newTotalByNewChoice = if (if (isDefined(oldChoice))
401401 then (value(oldChoice) == choice)
402402 else false)
403403 then newTotalByOldChoice
404404 else (oldTotalByNewChoice + gnsbtAmt)
405405 let newTotal = ((oldTotal - oldUserVotes) + gnsbtAmt)
406406 let isQuorumReached = (newTotal >= parseIntValue(propData[govIdxQuorum]))
407407 let numVotersByProposalId = getIntOrElse(keyNumUniqueVotersByProposalId(proposalId), 0)
408408 let oldAverUniqueVoters6 = getIntOrElse(keyStatsAverUniqueVoters(), 0)
409409 let numProposals = getIntegerValue(keyLastProposalId())
410410 let uniqueDiff = if ((oldUserVotes == 0))
411411 then 1
412412 else 0
413413 let newAverUniqueVoters6 = (oldAverUniqueVoters6 + fraction(uniqueDiff, MULT6, numProposals))
414414 let oldAverGnsbt = getIntOrElse(keyStatsAverGnsbtVoted(), 0)
415415 let newAverGnsbt = (oldAverGnsbt + ((gnsbtAmt - oldUserVotes) / numProposals))
416416 let isPrevOptional = if (!(isDefined(oldChoice)))
417417 then true
418418 else (value(oldChoice) == choice)
419419 let optionalTotalOld = if (isPrevOptional)
420420 then nil
421421 else [IntegerEntry(keyProposalVotesByIdAndOption(proposalId, value(oldChoice)), newTotalByOldChoice)]
422422 let winOpt = calcWinOption(proposalId, availableOptions, isPrevOptional, oldChoice, newTotalByOldChoice, choice, newTotalByNewChoice)
423423 let releaseTime = max([end, getIntOrElse(keyUserGnsbtReleaseTime(userAddressStr), 0)])
424424 $Tuple2(([IntegerEntry(keyProposalChoiceByIdAndUser(proposalId, userAddressStr), choice), IntegerEntry(keyProposalVotesByIdAndUser(proposalId, userAddressStr), gnsbtAmt), IntegerEntry(keyProposalVotesByIdAndOption(proposalId, choice), newTotalByNewChoice), IntegerEntry(keyNumUniqueVotersByProposalId(proposalId), (numVotersByProposalId + uniqueDiff)), IntegerEntry(keyUserGnsbtReleaseTime(userAddressStr), releaseTime), IntegerEntry(keyStatsAverUniqueVoters(), newAverUniqueVoters6), IntegerEntry(keyStatsAverGnsbtVoted(), newAverGnsbt), StringEntry(keyProposalStatusDataById(proposalId), updateStatusData(dynamicData, isQuorumReached, winOpt, newTotal))] ++ optionalTotalOld), unit)
425425 }
426426 }
427427 }
428428 }
429429 }
430430
431431
432432
433433 @Callable(i)
434434 func initiateIdeaVoting (forumLink,title,votingStartTime,votingEndTime,optionsList) = if ((size(i.payments) != 1))
435435 then throw("Exactly one payment required")
436436 else if ((size(optionsList) != 2))
437437 then throw("Exactly 2 option ['NO', 'YES'] are expected")
438438 else if ((optionsList[0] != "NO"))
439439 then throw("Option NO should be the first")
440440 else if ((optionsList[1] != "YES"))
441441 then throw("Option YES should be the second")
442442 else initiateVoting(value(i.payments[0]), toBase58String(i.transactionId), "IDEA", toString(i.caller), forumLink, title, votingStartTime, votingEndTime, "PENDING", nil, optionsList)
443443
444444
445445
446446 @Callable(i)
447447 func initiateUpdateVoting (forumLink,title,votingStartTime,votingEndTime,txList) = if ((size(i.payments) != 1))
448448 then throw("Exactly one payment required")
449449 else if ((1 > size(txList)))
450450 then throw("Transactions list is empty")
451451 else if ((i.caller != this))
452452 then throw("not authorized")
453453 else initiateVoting(value(i.payments[0]), toBase58String(i.transactionId), "UPDATE", toString(i.caller), forumLink, title, votingStartTime, votingEndTime, "PENDING", txList, ["NO", "YES"])
454454
455455
456456
457457 @Callable(i)
458458 func cancelVoting (proposalId) = if ((i.caller != this))
459459 then throw("not authorized")
460460 else {
461461 let currentData = getStringOrFail(this, keyProposalStatusDataById(proposalId))
462462 let updatedData = ((take(currentData, value(lastIndexOf(currentData, SEP))) + SEP) + "true")
463463 $Tuple2([StringEntry(keyProposalStatusDataById(proposalId), updatedData)], unit)
464464 }
465465
466466
467467
468468 @Callable(i)
469469 func applyUpdate (proposalId) = {
470470 let propData = split(getStringOrFail(this, keyProposalDataById(proposalId)), SEP)
471471 let end = parseIntValue(propData[govIdxEnd])
472472 let now = lastBlock.timestamp
473473 if ((end > now))
474474 then throw("Voting is not finished yet")
475475 else if (("UPDATE" != propData[govIdxType]))
476476 then throw("Only UPDATE type can be applied")
477477 else {
478478 let dynamicData = split(getStringOrFail(this, keyProposalStatusDataById(proposalId)), SEP)
479479 if ((dynamicData[govStatusIdxIsCanceled] == "true"))
480480 then throw("Voting is canceled")
481481 else if ((dynamicData[govStatusIdxIsValid] != "true"))
482482 then throw("Voting status invalid")
483483 else if ((dynamicData[govStatusIdxWinOpt] != "1"))
484484 then throw("Winner is 'NO' - nothing to apply")
485485 else if ((dynamicData[govStatusIdxScApplied] == "true"))
486486 then throw("Scripts are already applied")
487487 else {
488488 let scriptTime = parseIntValue(dynamicData[govStatusIdxScTime])
489489 if (((now - PASTMARGIN) > scriptTime))
490490 then throw((("Scripts timestamp=" + toString(scriptTime)) + " is too far in the past, max 2 hrs allowed"))
491491 else if ((scriptTime > (now + FUTUREMARGIN)))
492492 then throw((("Scripts timestamp=" + toString(scriptTime)) + " is too far in the future, max 1.5 hrs allowed"))
493493 else {
494494 let inProgressId = getIntOrElse(keyApplyInProgress(), -1)
495495 if ((inProgressId != -1))
496496 then throw((("proposalId=" + toString(inProgressId)) + " is already being applied. Finish it first!"))
497497 else {
498498 let shutdown = invoke(controlContract, "callEmergencyShutdown", ["Applying Governance UPDATE"], nil)
499499 if ((shutdown == shutdown))
500500 then $Tuple2([IntegerEntry(keyApplyInProgress(), proposalId)], unit)
501501 else throw("Strict value is not equal to itself.")
502502 }
503503 }
504504 }
505505 }
506506 }
507507
508508
509509
510510 @Callable(i)
511511 func finishApply () = {
512512 let proposalId = valueOrErrorMessage(getInteger(keyApplyInProgress()), "No apply in progress, nothing to finish")
513513 let propData = split(getStringOrFail(this, keyProposalDataById(proposalId)), SEP)
514514 let txList = split(propData[govIdxTxIds], LISTSEP)
515515 let dynamicData = split(getStringOrFail(this, keyProposalStatusDataById(proposalId)), SEP)
516516 if ((dynamicData[govStatusIdxScApplied] == "true"))
517517 then throw("Scripts are already applied")
518518 else {
519519 func checker (acc,tx) = if (!(isDefined(transactionHeightById(fromBase58String(tx)))))
520520 then throw(("NOT applied txId: " + tx))
521521 else unit
522522
523523 let ignored = {
524524 let $l = txList
525525 let $s = size($l)
526526 let $acc0 = unit
527527 func $f0_1 ($a,$i) = if (($i >= $s))
528528 then $a
529529 else checker($a, $l[$i])
530530
531531 func $f0_2 ($a,$i) = if (($i >= $s))
532532 then $a
533533 else throw("List size exceeds 20")
534534
535535 $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($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
536536 }
537537 let version = (getIntOrElse(keyLastUpdateVersion(), 0) + 1)
538- $Tuple2([DeleteEntry(keyApplyInProgress()), IntegerEntry(keyLastUpdateVersion(), version), StringEntry(keyProposalStatusDataById(proposalId), statusApplyScript(dynamicData)), ExecutionHistory(version, propData[govIdxTitle], propData[govIdxUrl])], ignored)
538+ $Tuple2([DeleteEntry(keyApplyInProgress()), IntegerEntry(keyLastUpdateVersion(), version), StringEntry(keyProposalStatusDataById(proposalId), statusApplyScript(dynamicData)), ExecutionHistory(version, propData[govIdxTitle], propData[govIdxUrl], proposalId)], ignored)
539539 }
540540 }
541541
542542

github/deemru/w8io/026f985 
75.88 ms