tx · 7wEZeLyst2CAxsZ8XLi4JN4fLqq1422ngaQfXfFMgkry

3N7hFU6dFSFKGGwDyF9WJ1jVsrB9w8RHT37:  -0.01800000 Waves

2023.01.12 15:04 [2401712] smart account 3N7hFU6dFSFKGGwDyF9WJ1jVsrB9w8RHT37 > SELF 0.00000000 Waves

{ "type": 13, "id": "7wEZeLyst2CAxsZ8XLi4JN4fLqq1422ngaQfXfFMgkry", "fee": 1800000, "feeAssetId": null, "timestamp": 1673525020399, "version": 2, "chainId": 84, "sender": "3N7hFU6dFSFKGGwDyF9WJ1jVsrB9w8RHT37", "senderPublicKey": "J6bcbr8r9usSLYw72NzzrKVCvKDDLe1uDx8bnWp3uFAV", "proofs": [ "456qdkTNFhZ7FUruVXFPNHVpmE1MoMHUTQozaZRMaVmA4iG5ABtDkA1tCPcmDKvy96sTTETRiEWy1b5MobFARCZs" ], "script": "base64:BgIvCAISBwoFCAEBAQESBAoCAQESBwoFCAgBARgSBwoFCAgBARgSAwoBARIDCgEBEgBZAAtyZXZpc2lvbk51bQIAAANTRVACAl9fAAdMSVNUU0VQAgE6AA1ERUZBVUxUUVVPUlVNAKDCHgAKVVJMUEFUVEVSTgIaaHR0cHM6Ly9mb3J1bS5uZXV0cmluby5hdC8ACE1BWFRJVExFAPoBAAZNQVhVUkwA+gEADU1BWFZPVElOR1RJTUUAgJDkwAQABU1VTFQ2AMCEPQAOREVGQVVMVFBBWU1FTlQAgJTr3AMAFERFRkFVTFRDUkVBVElPTkdOU0JUAICU69wDAApQQVNUTUFSR0lOAIC6twMADEZVVFVSRU1BUkdJTgDAy8kCABRERUZBVUxURklSU1RQUk9QT1NBTABvABJnb3ZJZHhQcm9wb3NhbFR4SWQAAQAKZ292SWR4VHlwZQACAAxnb3ZJZHhBdXRob3IAAwAJZ292SWR4VXJsAAQAC2dvdklkeFRpdGxlAAUAEmdvdklkeENyZWF0aW9uVGltZQAGAAtnb3ZJZHhTdGFydAAHAAlnb3ZJZHhFbmQACAALZ292SWR4VHhJZHMACQAMZ292SWR4UXVvcnVtAAoADWdvdklkeE9wdGlvbnMACwATZ292U3RhdHVzSWR4SXNWYWxpZAABABJnb3ZTdGF0dXNJZHhXaW5PcHQAAgAUZ292U3RhdHVzSWR4V2luVm90ZXMAAwAWZ292U3RhdHVzSWR4VG90YWxWb3RlcwAEABVnb3ZTdGF0dXNJZHhTY0FwcGxpZWQABQASZ292U3RhdHVzSWR4U2NUaW1lAAYAFmdvdlN0YXR1c0lkeElzQ2FuY2VsZWQABwEPZ2V0U3RyaW5nT3JGYWlsAgdhZGRyZXNzA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFB2FkZHJlc3MFA2tleQkAuQkCCQDMCAICCm1hbmRhdG9yeSAJAMwIAgkApQgBBQdhZGRyZXNzCQDMCAICAS4JAMwIAgUDa2V5CQDMCAICDyBpcyBub3QgZGVmaW5lZAUDbmlsAgABDGdldEludE9yRWxzZQIDa2V5CmRlZmF1bHRWYWwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUDa2V5BQpkZWZhdWx0VmFsABlJZHhDb250cm9sQ2ZnTmV1dHJpbm9EYXBwAAEAGElkeENvbnRyb2xDZmdBdWN0aW9uRGFwcAACABRJZHhDb250cm9sQ2ZnUnBkRGFwcAADABVJZHhDb250cm9sQ2ZnTWF0aERhcHAABAAcSWR4Q29udHJvbENmZ0xpcXVpZGF0aW9uRGFwcAAFABVJZHhDb250cm9sQ2ZnUmVzdERhcHAABgAdSWR4Q29udHJvbENmZ05vZGVSZWdpc3RyeURhcHAABwAcSWR4Q29udHJvbENmZ05zYnRTdGFraW5nRGFwcAAIABlJZHhDb250cm9sQ2ZnTWVkaWF0b3JEYXBwAAkAHElkeENvbnRyb2xDZmdTdXJmU3Rha2luZ0RhcHAACgAgSWR4Q29udHJvbENmZ0duc2J0Q29udHJvbGxlckRhcHAACwAXSWR4Q29udHJvbENmZ1Jlc3RWMkRhcHAADAAbSWR4Q29udHJvbENmZ0dvdmVybmFuY2VEYXBwAA0BEWtleUNvbnRyb2xBZGRyZXNzAAIcJXMlc19fY29uZmlnX19jb250cm9sQWRkcmVzcwENa2V5Q29udHJvbENmZwACESVzX19jb250cm9sQ29uZmlnARRyZWFkQ29udHJvbENmZ09yRmFpbAEHY29udHJvbAkAvAkCCQEPZ2V0U3RyaW5nT3JGYWlsAgUHY29udHJvbAkBDWtleUNvbnRyb2xDZmcABQNTRVABGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIKY29udHJvbENmZwNpZHgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIFCmNvbnRyb2xDZmcFA2lkeAkArAICAi1Db250cm9sIGNmZyBkb2Vzbid0IGNvbnRhaW4gYWRkcmVzcyBhdCBpbmRleCAJAKQDAQUDaWR4AA9jb250cm9sQ29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkBEWtleUNvbnRyb2xBZGRyZXNzAAIjM1A1QmZkNThQUGZOdkJNMkh5OFFmYmNEcU1lTnR6ZzdLZlAACmNvbnRyb2xDZmcJARRyZWFkQ29udHJvbENmZ09yRmFpbAEFD2NvbnRyb2xDb250cmFjdAAQbmV1dHJpbm9Db250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFGUlkeENvbnRyb2xDZmdOZXV0cmlub0RhcHAAF2duc2J0Q29udHJvbGxlckNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUgSWR4Q29udHJvbENmZ0duc2J0Q29udHJvbGxlckRhcHABGGtleVF1b3J1bVJlcXVpcmVkUGVyY2VudAEEdHlwZQkArAICAhYlcyVzX19xdW9ydW1SZXF1aXJlZF9fBQR0eXBlARJrZXlQYXltZW50UmVxdWlyZWQAAhMlc19fcGF5bWVudFJlcXVpcmVkARBrZXlHbnNidFJlcXVpcmVkAAIRJXNfX2dOc2J0UmVxdWlyZWQBEWtleUxhc3RQcm9wb3NhbElkAAIOJXNfX3Byb3Bvc2FsSWQBEmtleUZpcnN0UHJvcG9zYWxJZAACEyVzX19maXJzdFByb3Bvc2FsSWQBFGtleUxhc3RVcGRhdGVWZXJzaW9uAAIRJXNfX3VwZGF0ZVZlcnNpb24BGWtleVByb3Bvc2FsU3RhdHVzRGF0YUJ5SWQBCnByb3Bvc2FsSWQJAKwCAgIaJXMlZF9fcHJvcG9zYWxTdGF0dXNEYXRhX18JAKQDAQUKcHJvcG9zYWxJZAETa2V5UHJvcG9zYWxEYXRhQnlJZAEKcHJvcG9zYWxJZAkArAICAhQlcyVkX19wcm9wb3NhbERhdGFfXwkApAMBBQpwcm9wb3NhbElkAR1rZXlQcm9wb3NhbFZvdGVzQnlJZEFuZE9wdGlvbgIKcHJvcG9zYWxJZANvcHQJALkJAgkAzAgCAgYlcyVkJWQJAMwIAgIKdm90ZXNCeU9wdAkAzAgCCQCkAwEFCnByb3Bvc2FsSWQJAMwIAgkApAMBBQNvcHQFA25pbAUDU0VQARtrZXlQcm9wb3NhbFZvdGVzQnlJZEFuZFVzZXICCnByb3Bvc2FsSWQIdXNlckFkZHIJALkJAgkAzAgCAgYlcyVkJXMJAMwIAgILdm90ZXNCeVVzZXIJAMwIAgkApAMBBQpwcm9wb3NhbElkCQDMCAIFCHVzZXJBZGRyBQNuaWwFA1NFUAEca2V5UHJvcG9zYWxDaG9pY2VCeUlkQW5kVXNlcgIKcHJvcG9zYWxJZAh1c2VyQWRkcgkAuQkCCQDMCAICBiVzJWQlcwkAzAgCAgxvcHRpb25CeVVzZXIJAMwIAgkApAMBBQpwcm9wb3NhbElkCQDMCAIFCHVzZXJBZGRyBQNuaWwFA1NFUAESa2V5QXBwbHlJblByb2dyZXNzAAITJXNfX2FwcGx5SW5Qcm9ncmVzcwEWa2V5UHJvcG9zYWxJZEJ5VG9waWNJZAEHdG9waWNJZAkArAICAhslcyVkX19wcm9wb3NhbElkQnlUb3BpY0lkX18JAKQDAQUHdG9waWNJZAEXa2V5VXNlckduc2J0UmVsZWFzZVRpbWUBCHVzZXJBZGRyCQCsAgICGyVzJXNfdXNlckduc2J0UmVsZWFzZVRpbWVfXwUIdXNlckFkZHIBHmtleU51bVVuaXF1ZVZvdGVyc0J5UHJvcG9zYWxJZAEKcHJvcG9zYWxJZAkArAICAhElcyVkX19udW1Wb3RlcnNfXwkApAMBBQpwcm9wb3NhbElkARhrZXlTdGF0c0F2ZXJVbmlxdWVWb3RlcnMAAiAlcyVzJXNfX3N0YXRzX19hdmdfX3VuaXF1ZVZvdGVycwEWa2V5U3RhdHNBdmVyR25zYnRWb3RlZAACHiVzJXMlc19fc3RhdHNfX2F2Z19fZ25zYnRWb3RlZAEVa2V5U3RhdHNVbmlxdWVBdXRob3JzAAIaJXMlc19fc3RhdHNfX3VuaXF1ZUF1dGhvcnMBF2tleU51bVByb3Bvc2Fsc0J5QXV0aG9yAQphZGRyZXNzU3RyCQCsAgICHCVzJXNfX251bVByb3Bvc2Fsc0J5QXV0aG9yX18FCmFkZHJlc3NTdHIBD2tleUFwcGx5SGlzdG9yeQEJdGltZXN0YW1wCQCsAgICFCVzJWRfX2FwcGx5SGlzdG9yeV9fCQCkAwEFCXRpbWVzdGFtcAEJYXNBbnlMaXN0AQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACCUxpc3RbQW55XQQBbAUHJG1hdGNoMAUBbAkAAgECG2ZhaWwgdG8gY2FzdCBpbnRvIExpc3RbQW55XQEFYXNJbnQBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIDSW50BAFpBQckbWF0Y2gwBQFpCQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50AQpzdGF0dXNEYXRhBw1pc1ZvdGluZ1ZhbGlkCXdpbk9wdGlvbg53aW5PcHRpb25Wb3Rlcwp0b3RhbFZvdGVzEWFyZVNjcmlwdHNBcHBsaWVkEHNjcmlwdHNUaW1lc3RhbXAOY2FuY2VsZWRCeVRlYW0JALkJAgkAzAgCAg4lYiVkJWQlZCViJWQlYgkAzAgCCQClAwEFDWlzVm90aW5nVmFsaWQJAMwIAgkApAMBBQl3aW5PcHRpb24JAMwIAgkApAMBBQ53aW5PcHRpb25Wb3RlcwkAzAgCCQCkAwEFCnRvdGFsVm90ZXMJAMwIAgkApQMBBRFhcmVTY3JpcHRzQXBwbGllZAkAzAgCCQCkAwEFEHNjcmlwdHNUaW1lc3RhbXAJAMwIAgkApQMBBQ5jYW5jZWxlZEJ5VGVhbQUDbmlsBQNTRVABDHByb3Bvc2FsRGF0YQsMcHJvcG9zYWxUeElkBHR5cGUGYXV0aG9yCWZvcnVtTGluawV0aXRsZQxwcm9wb3NhbFRpbWUPdm90aW5nU3RhcnRUaW1lDXZvdGluZ0VuZFRpbWUFdHhJZHMNcXVvcnVtSW5HbnNidAdvcHRpb25zCQC5CQIJAMwIAgIWJXMlcyVzJXMlcyVkJWQlZCVzJWQlcwkAzAgCBQxwcm9wb3NhbFR4SWQJAMwIAgUEdHlwZQkAzAgCBQZhdXRob3IJAMwIAgUJZm9ydW1MaW5rCQDMCAIFBXRpdGxlCQDMCAIJAKQDAQUMcHJvcG9zYWxUaW1lCQDMCAIJAKQDAQUPdm90aW5nU3RhcnRUaW1lCQDMCAIJAKQDAQUNdm90aW5nRW5kVGltZQkAzAgCBQV0eElkcwkAzAgCCQCkAwEFDXF1b3J1bUluR25zYnQJAMwIAgUHb3B0aW9ucwUDbmlsBQNTRVABC2NoZWNrVHhMaXN0AQZ0eExpc3QDCQBmAgkAkAMBBQZ0eExpc3QAFAkAAgEJAKwCAgIXVG9vIG1hbnkgdHJhbnNhY3Rpb25zOiAJAKQDAQkAkAMBBQZ0eExpc3QKAQhjb21iaW5lcgIDYWNjAnR4AwkBAiE9AgkAyAEBCQDZBAEFAnR4ACAJAAIBCQCsAgICDFdyb25nIHR4SWQ6IAUCdHgDCQAAAgUDYWNjAgAFAnR4CQCsAgIJAKwCAgUDYWNjBQdMSVNUU0VQBQJ0eAoAAiRsBQZ0eExpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCGNvbWJpbmVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAyMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAC0lkeEVmZlRvdGFsAAAACklkeEVmZlVzZXIAAQERZ2V0RWZmZWN0aXZlR25zYnQBEnVzZXJBZGRyU3RyT3JFbXB0eQQJZ25zYnREYXRhCQEJYXNBbnlMaXN0AQkA/AcEBRdnbnNidENvbnRyb2xsZXJDb250cmFjdAIUZ25zYnRJbmZvU1lTUkVBRE9OTFkJAMwIAgUSdXNlckFkZHJTdHJPckVtcHR5CQDMCAIAAAkAzAgCAAAFA25pbAUDbmlsBAhuc2J0RGF0YQkBCWFzQW55TGlzdAEJAJEDAgUJZ25zYnREYXRhAAIEDHVzZXJGcm9tTnNidAkBBWFzSW50AQkAkQMCBQhuc2J0RGF0YQACBA10b3RhbEZyb21Oc2J0CQEFYXNJbnQBCQCRAwIFCG5zYnREYXRhAAMEEnVzZXJNYXR1cmVGcm9tU3VyZgkBBWFzSW50AQkAkQMCBQlnbnNidERhdGEACQQTdG90YWxNYXR1cmVGcm9tU3VyZgkBBWFzSW50AQkAkQMCBQlnbnNidERhdGEABgkAzAgCCQBkAgUNdG90YWxGcm9tTnNidAUTdG90YWxNYXR1cmVGcm9tU3VyZgkAzAgCCQBkAgUMdXNlckZyb21Oc2J0BRJ1c2VyTWF0dXJlRnJvbVN1cmYFA25pbAEMdmFsaWRhdGVMaW5rAQN1cmwDCQECIT0CCQEFdmFsdWUBCQCzCQIFA3VybAUKVVJMUEFUVEVSTgAACQACAQILSW52YWxpZCB1cmwDCQBmAgkAsQIBBQN1cmwFBk1BWFVSTAkAAgECDVVybCB0b28gbG9uZyEEB3RvcGljSWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAtgkBCQCwAgIFA3VybAkAZAIJAQV2YWx1ZQEJALcJAgUDdXJsAgEvAAECDVdyb25nIHRvcGljSWQEDHJlZ2lzdGVyZWRJZAkAnwgBCQEWa2V5UHJvcG9zYWxJZEJ5VG9waWNJZAEFB3RvcGljSWQDCQEJaXNEZWZpbmVkAQUMcmVnaXN0ZXJlZElkCQACAQkArAICAjhWb3Rpbmcgd2l0aCBzdWNoIGZvcnVtIGxpbmsgaXMgYWxyZWFkeSByZWdpc3RlcmVkIGJ5IGlkPQkApAMBCQEFdmFsdWUBBQxyZWdpc3RlcmVkSWQFB3RvcGljSWQBDmluaXRpYXRlVm90aW5nCwdwYXltZW50DHByb3Bvc2FsVHhJZAR0eXBlBmF1dGhvcglmb3J1bUxpbmsFdGl0bGUPdm90aW5nU3RhcnRUaW1lDXZvdGluZ0VuZFRpbWUGc3RhdHVzBnR4TGlzdAtvcHRpb25zTGlzdAMJAQIhPQIIBQdwYXltZW50B2Fzc2V0SWQFBHVuaXQJAAIBAhtBbGxvd2VkIFdBVkVTIHBheW1lbnQgb25seSEEBnBtdFJlcQkBDGdldEludE9yRWxzZQIJARJrZXlQYXltZW50UmVxdWlyZWQABQ5ERUZBVUxUUEFZTUVOVAMJAGYCBQZwbXRSZXEIBQdwYXltZW50BmFtb3VudAkAAgEJAKwCAgIkUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgYXQgbGVhc3QgCQCkAwEFBnBtdFJlcQQHdG9waWNJZAkBDHZhbGlkYXRlTGluawEFCWZvcnVtTGluawMJAAACBQV0aXRsZQIACQACAQIOVGl0bGUgaXMgZW1wdHkDCQBmAgkAsQIBBQV0aXRsZQUITUFYVElUTEUJAAIBAg5Ub28gbG9uZyB0aXRsZQQMcHJvcG9zYWxUaW1lCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAMJAGYCBQxwcm9wb3NhbFRpbWUFD3ZvdGluZ1N0YXJ0VGltZQkAAgEJAKwCAgkArAICCQCsAgICEHZvdGluZ1N0YXJ0VGltZT0JAKQDAQUPdm90aW5nU3RhcnRUaW1lAhAgPCBwcm9wb3NhbFRpbWU9CQCkAwEFDHByb3Bvc2FsVGltZQMJAGYCBQ92b3RpbmdTdGFydFRpbWUFDXZvdGluZ0VuZFRpbWUJAAIBCQCsAgIJAKwCAgkArAICAg52b3RpbmdFbmRUaW1lPQkApAMBBQ12b3RpbmdFbmRUaW1lAhMgPCB2b3RpbmdTdGFydFRpbWU9CQCkAwEFD3ZvdGluZ1N0YXJ0VGltZQMJAGYCCQBlAgUNdm90aW5nRW5kVGltZQUPdm90aW5nU3RhcnRUaW1lBQ1NQVhWT1RJTkdUSU1FCQACAQkArAICCQCsAgIJAKwCAgIbVm90aW5nIHBlcmlvZCBleGNlZWRzIG1heDogCQCkAwEJAGUCBQ12b3RpbmdFbmRUaW1lBQ92b3RpbmdTdGFydFRpbWUCAyA+IAkApAMBBQ1NQVhWT1RJTkdUSU1FBAV0eElkcwMJAAACBQR0eXBlAgRJREVBAgAJAQtjaGVja1R4TGlzdAEFBnR4TGlzdAMJAGcCAAEJAJADAQULb3B0aW9uc0xpc3QJAAIBAhdUb28gZmV3IGNob2ljZXMgdG8gdm90ZQQDZWZmCQERZ2V0RWZmZWN0aXZlR25zYnQBBQZhdXRob3IECmduc2J0VG90YWwJAJEDAgUDZWZmBQtJZHhFZmZUb3RhbAQJZ05zYnRVc2VyCQCRAwIFA2VmZgUKSWR4RWZmVXNlcgQIZ25zYnRSZXEJAQxnZXRJbnRPckVsc2UCCQEQa2V5R25zYnRSZXF1aXJlZAAFFERFRkFVTFRDUkVBVElPTkdOU0JUAwkAZgIFCGduc2J0UmVxBQlnTnNidFVzZXIJAAIBCQCsAgIJAKwCAgISWW91IG5lZWQgYXQgbGVhc3QgCQCkAwEFCGduc2J0UmVxAhcgZ05zYnQgdG8gY3JlYXRlIHZvdGluZwQMYW1vdW50TGVhc2VkCQD8BwQFEG5ldXRyaW5vQ29udHJhY3QCC2FjY2VwdFdhdmVzBQNuaWwJAMwIAgUHcGF5bWVudAUDbmlsAwkAAAIFDGFtb3VudExlYXNlZAUMYW1vdW50TGVhc2VkBAZxdW9ydW0JAQxnZXRJbnRPckVsc2UCCQEYa2V5UXVvcnVtUmVxdWlyZWRQZXJjZW50AQUEdHlwZQUNREVGQVVMVFFVT1JVTQQNcXVvcnVtSW5HbnNidAkAawMFBnF1b3J1bQUKZ25zYnRUb3RhbAUFTVVMVDYECnByb3Bvc2FsSWQJAGQCCQEMZ2V0SW50T3JFbHNlAgkBEWtleUxhc3RQcm9wb3NhbElkAAAAAAEEFG51bVByb3Bvc2Fsc0J5QXV0aG9yCQBkAgkBDGdldEludE9yRWxzZQIJARdrZXlOdW1Qcm9wb3NhbHNCeUF1dGhvcgEFBmF1dGhvcgAAAAEEC3VuaXFBdXRob3JzCQBkAgkBDGdldEludE9yRWxzZQIJARVrZXlTdGF0c1VuaXF1ZUF1dGhvcnMAAAADCQAAAgUUbnVtUHJvcG9zYWxzQnlBdXRob3IAAQABAAAECm9wdGlvbnNTdHIJALkJAgULb3B0aW9uc0xpc3QFB0xJU1RTRVAJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEWtleUxhc3RQcm9wb3NhbElkAAUKcHJvcG9zYWxJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleVByb3Bvc2FsSWRCeVRvcGljSWQBBQd0b3BpY0lkBQpwcm9wb3NhbElkCQDMCAIJAQtTdHJpbmdFbnRyeQIJARlrZXlQcm9wb3NhbFN0YXR1c0RhdGFCeUlkAQUKcHJvcG9zYWxJZAkBCnN0YXR1c0RhdGEHBwAAAAAAAAcAAAcJAMwIAgkBC1N0cmluZ0VudHJ5AgkBE2tleVByb3Bvc2FsRGF0YUJ5SWQBBQpwcm9wb3NhbElkCQEMcHJvcG9zYWxEYXRhCwUMcHJvcG9zYWxUeElkBQR0eXBlBQZhdXRob3IJANgEAQkAmwMBBQlmb3J1bUxpbmsJANgEAQkAmwMBBQV0aXRsZQUMcHJvcG9zYWxUaW1lBQ92b3RpbmdTdGFydFRpbWUFDXZvdGluZ0VuZFRpbWUFBXR4SWRzBQ1xdW9ydW1Jbkduc2J0BQpvcHRpb25zU3RyCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEXa2V5TnVtUHJvcG9zYWxzQnlBdXRob3IBBQZhdXRob3IFFG51bVByb3Bvc2Fsc0J5QXV0aG9yCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEVa2V5U3RhdHNVbmlxdWVBdXRob3JzAAULdW5pcUF1dGhvcnMFA25pbAUMcHJvcG9zYWxUeElkCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQ1jYWxjV2luT3B0aW9uBwpwcm9wb3NhbElkC29wdGlvbnNMaXN0DmlzUHJldk9wdGlvbmFsCW9sZENob2ljZRBvcHRpb25hbFRvdGFsT2xkCW5ld0Nob2ljZRNuZXdUb3RhbEJ5TmV3Q2hvaWNlCgEIZmluZEJlc3QCA2FjYwRlbGVtBANpZHgJAQV2YWx1ZQEJAM8IAgULb3B0aW9uc0xpc3QFBGVsZW0EA3ZhbAMFDmlzUHJldk9wdGlvbmFsAwkAAAIFA2lkeAUJbmV3Q2hvaWNlBRNuZXdUb3RhbEJ5TmV3Q2hvaWNlCQEMZ2V0SW50T3JFbHNlAgkBHWtleVByb3Bvc2FsVm90ZXNCeUlkQW5kT3B0aW9uAgUKcHJvcG9zYWxJZAUDaWR4AAADCQAAAgUDaWR4CQEFdmFsdWUBBQlvbGRDaG9pY2UFEG9wdGlvbmFsVG90YWxPbGQDCQAAAgUDaWR4BQluZXdDaG9pY2UFE25ld1RvdGFsQnlOZXdDaG9pY2UJAQxnZXRJbnRPckVsc2UCCQEda2V5UHJvcG9zYWxWb3Rlc0J5SWRBbmRPcHRpb24CBQpwcm9wb3NhbElkBQNpZHgAAAMJAGYCCAUDYWNjAl8yBQN2YWwFA2FjYwkAlAoCBQNpZHgFA3ZhbAoAAiRsBQtvcHRpb25zTGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgAAAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCGZpbmRCZXN0AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKARB1cGRhdGVTdGF0dXNEYXRhBAdvbGREYXRhB2lzVmFsaWQJbmV3V2luT3B0DW5ld1RvdGFsVm90ZXMJALkJAgkAzAgCAg4lYiVkJWQlZCViJWQlYgkAzAgCCQClAwEFB2lzVmFsaWQJAMwIAgkApAMBCAUJbmV3V2luT3B0Al8xCQDMCAIJAKQDAQgFCW5ld1dpbk9wdAJfMgkAzAgCCQCkAwEFDW5ld1RvdGFsVm90ZXMJAMwIAgkAkQMCBQdvbGREYXRhBRVnb3ZTdGF0dXNJZHhTY0FwcGxpZWQJAMwIAgkAkQMCBQdvbGREYXRhBRJnb3ZTdGF0dXNJZHhTY1RpbWUJAMwIAgkAkQMCBQdvbGREYXRhBRZnb3ZTdGF0dXNJZHhJc0NhbmNlbGVkBQNuaWwFA1NFUAERc3RhdHVzQXBwbHlTY3JpcHQBB29sZERhdGEJALkJAgkAzAgCAg4lYiVkJWQlZCViJWQlYgkAzAgCCQCRAwIFB29sZERhdGEFE2dvdlN0YXR1c0lkeElzVmFsaWQJAMwIAgkAkQMCBQdvbGREYXRhBRJnb3ZTdGF0dXNJZHhXaW5PcHQJAMwIAgkAkQMCBQdvbGREYXRhBRRnb3ZTdGF0dXNJZHhXaW5Wb3RlcwkAzAgCCQCRAwIFB29sZERhdGEFFmdvdlN0YXR1c0lkeFRvdGFsVm90ZXMJAMwIAgIEdHJ1ZQkAzAgCCQCRAwIFB29sZERhdGEFEmdvdlN0YXR1c0lkeFNjVGltZQkAzAgCCQCRAwIFB29sZERhdGEFFmdvdlN0YXR1c0lkeElzQ2FuY2VsZWQFA25pbAUDU0VQARBFeGVjdXRpb25IaXN0b3J5BA11cGRhdGVWZXJzaW9uBXRpdGxlA3VybApwcm9wb3NhbElkBApnbnNidFRvdGFsCQCRAwIJARFnZXRFZmZlY3RpdmVHbnNidAECAAULSWR4RWZmVG90YWwEB3R1cm5vdXQAoMIeCQELU3RyaW5nRW50cnkCCQEPa2V5QXBwbHlIaXN0b3J5AQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJALkJAgkAzAgCAgwlZCVkJWQlcyVzJWQJAMwIAgkApAMBBQ11cGRhdGVWZXJzaW9uCQDMCAIJAKQDAQUKZ25zYnRUb3RhbAkAzAgCCQCkAwEFB3R1cm5vdXQJAMwIAgUFdGl0bGUJAMwIAgUDdXJsCQDMCAIJAKQDAQUKcHJvcG9zYWxJZAUDbmlsBQNTRVAHAWkBDWNvbnN0cnVjdG9yVjEFC2NvbnRyb2xBZGRyDmdOc2J0UmVxVG9Jbml0DndhdmVzUmVxVG9Jbml0EXF1b3J1bVJlcVBlcmNJZGVhE3F1b3J1bVJlcVBlcmNVcGRhdGUDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAhFQZXJtaXNzaW9uIGRlbmllZAkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5Q29udHJvbEFkZHJlc3MABQtjb250cm9sQWRkcgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEGtleUduc2J0UmVxdWlyZWQABQ5nTnNidFJlcVRvSW5pdAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmtleVBheW1lbnRSZXF1aXJlZAAFDndhdmVzUmVxVG9Jbml0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEYa2V5UXVvcnVtUmVxdWlyZWRQZXJjZW50AQIESURFQQURcXVvcnVtUmVxUGVyY0lkZWEJAMwIAgkBDEludGVnZXJFbnRyeQIJARhrZXlRdW9ydW1SZXF1aXJlZFBlcmNlbnQBAgZVUERBVEUFE3F1b3J1bVJlcVBlcmNVcGRhdGUFA25pbAFpAQhjYXN0Vm90ZQIKcHJvcG9zYWxJZAZjaG9pY2UEDnVzZXJBZGRyZXNzU3RyCQClCAEIBQFpBmNhbGxlcgQLZHluYW1pY0RhdGEJALUJAgkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMJARlrZXlQcm9wb3NhbFN0YXR1c0RhdGFCeUlkAQUKcHJvcG9zYWxJZAUDU0VQAwkAAAIJAJEDAgULZHluYW1pY0RhdGEFFmdvdlN0YXR1c0lkeElzQ2FuY2VsZWQCBHRydWUJAAIBAhpWb3RpbmcgaXMgY2FuY2VsZWQgYnkgdGVhbQQIcHJvcERhdGEJALUJAgkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMJARNrZXlQcm9wb3NhbERhdGFCeUlkAQUKcHJvcG9zYWxJZAUDU0VQBAVzdGFydAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHByb3BEYXRhBQtnb3ZJZHhTdGFydAQDZW5kCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIcHJvcERhdGEFCWdvdklkeEVuZAQDbm93CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAMJAGYCBQVzdGFydAUDbm93CQACAQIWVm90aW5nIG5vdCBzdGFydGVkIHlldAMJAGcCBQNub3cFA2VuZAkAAgECF1ZvdGluZyBhbHJlYWR5IGZpbmlzaGVkBBBhdmFpbGFibGVPcHRpb25zCQC1CQIJAJEDAgUIcHJvcERhdGEFDWdvdklkeE9wdGlvbnMFB0xJU1RTRVAECm51bU9wdGlvbnMJAJADAQUQYXZhaWxhYmxlT3B0aW9ucwMJAGcCAAEFCm51bU9wdGlvbnMJAAIBAhdUb28gZmV3IGNob2ljZXMgdG8gdm90ZQMJAGcCBQZjaG9pY2UFCm51bU9wdGlvbnMJAAIBCQCsAgICG1Vua25vd24gY2hvaWNlISBNdXN0IGJlIDAuLgkApAMBCQBlAgUKbnVtT3B0aW9ucwABBANlZmYJARFnZXRFZmZlY3RpdmVHbnNidAEFDnVzZXJBZGRyZXNzU3RyBAhnbnNidEFtdAkAkQMCBQNlZmYFCklkeEVmZlVzZXIDCQBnAgAABQhnbnNidEFtdAkAAgECEG5vIGduc2J0IHRvIHZvdGUECmduc2J0VG90YWwJAJEDAgUDZWZmBQtJZHhFZmZUb3RhbAQJb2xkQ2hvaWNlCQCfCAEJARxrZXlQcm9wb3NhbENob2ljZUJ5SWRBbmRVc2VyAgUKcHJvcG9zYWxJZAUOdXNlckFkZHJlc3NTdHIEDG9sZFVzZXJWb3RlcwMJAQEhAQkBCWlzRGVmaW5lZAEFCW9sZENob2ljZQAACQEMZ2V0SW50T3JFbHNlAgkBG2tleVByb3Bvc2FsVm90ZXNCeUlkQW5kVXNlcgIFCnByb3Bvc2FsSWQFDnVzZXJBZGRyZXNzU3RyAAAEE29sZFRvdGFsQnlPbGRDaG9pY2UDCQEJaXNEZWZpbmVkAQUJb2xkQ2hvaWNlCQEMZ2V0SW50T3JFbHNlAgkBHWtleVByb3Bvc2FsVm90ZXNCeUlkQW5kT3B0aW9uAgUKcHJvcG9zYWxJZAkBBXZhbHVlAQUJb2xkQ2hvaWNlAAAAAAQTb2xkVG90YWxCeU5ld0Nob2ljZQkBDGdldEludE9yRWxzZQIJAR1rZXlQcm9wb3NhbFZvdGVzQnlJZEFuZE9wdGlvbgIFCnByb3Bvc2FsSWQFBmNob2ljZQAABAhvbGRUb3RhbAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFC2R5bmFtaWNEYXRhBRZnb3ZTdGF0dXNJZHhUb3RhbFZvdGVzBBNuZXdUb3RhbEJ5T2xkQ2hvaWNlAwkBASEBCQEJaXNEZWZpbmVkAQUJb2xkQ2hvaWNlAAAJAGQCCQBlAgUTb2xkVG90YWxCeU9sZENob2ljZQUMb2xkVXNlclZvdGVzAwkAAAIJAQV2YWx1ZQEFCW9sZENob2ljZQUGY2hvaWNlBQhnbnNidEFtdAAABBNuZXdUb3RhbEJ5TmV3Q2hvaWNlAwMJAQlpc0RlZmluZWQBBQlvbGRDaG9pY2UJAAACCQEFdmFsdWUBBQlvbGRDaG9pY2UFBmNob2ljZQcFE25ld1RvdGFsQnlPbGRDaG9pY2UJAGQCBRNvbGRUb3RhbEJ5TmV3Q2hvaWNlBQhnbnNidEFtdAQIbmV3VG90YWwJAGQCCQBlAgUIb2xkVG90YWwFDG9sZFVzZXJWb3RlcwUIZ25zYnRBbXQED2lzUXVvcnVtUmVhY2hlZAkAZwIFCG5ld1RvdGFsCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIcHJvcERhdGEFDGdvdklkeFF1b3J1bQQVbnVtVm90ZXJzQnlQcm9wb3NhbElkCQEMZ2V0SW50T3JFbHNlAgkBHmtleU51bVVuaXF1ZVZvdGVyc0J5UHJvcG9zYWxJZAEFCnByb3Bvc2FsSWQAAAQUb2xkQXZlclVuaXF1ZVZvdGVyczYJAQxnZXRJbnRPckVsc2UCCQEYa2V5U3RhdHNBdmVyVW5pcXVlVm90ZXJzAAAABAxudW1Qcm9wb3NhbHMJAGQCCQBlAgkBEUBleHRyTmF0aXZlKDEwNTUpAQkBEWtleUxhc3RQcm9wb3NhbElkAAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQESa2V5Rmlyc3RQcm9wb3NhbElkAAUUREVGQVVMVEZJUlNUUFJPUE9TQUwAAQQKdW5pcXVlRGlmZgMJAAACBQxvbGRVc2VyVm90ZXMAAAABAAAEFG5ld0F2ZXJVbmlxdWVWb3RlcnM2CQBkAgUUb2xkQXZlclVuaXF1ZVZvdGVyczYJAGsDBQp1bmlxdWVEaWZmBQVNVUxUNgUMbnVtUHJvcG9zYWxzBAxvbGRBdmVyR25zYnQJAQxnZXRJbnRPckVsc2UCCQEWa2V5U3RhdHNBdmVyR25zYnRWb3RlZAAAAAQMbmV3QXZlckduc2J0CQBkAgUMb2xkQXZlckduc2J0CQBpAgkAZQIFCGduc2J0QW10BQxvbGRVc2VyVm90ZXMFDG51bVByb3Bvc2FscwQOaXNQcmV2T3B0aW9uYWwDCQEBIQEJAQlpc0RlZmluZWQBBQlvbGRDaG9pY2UGCQAAAgkBBXZhbHVlAQUJb2xkQ2hvaWNlBQZjaG9pY2UEEG9wdGlvbmFsVG90YWxPbGQDBQ5pc1ByZXZPcHRpb25hbAUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEda2V5UHJvcG9zYWxWb3Rlc0J5SWRBbmRPcHRpb24CBQpwcm9wb3NhbElkCQEFdmFsdWUBBQlvbGRDaG9pY2UFE25ld1RvdGFsQnlPbGRDaG9pY2UFA25pbAQGd2luT3B0CQENY2FsY1dpbk9wdGlvbgcFCnByb3Bvc2FsSWQFEGF2YWlsYWJsZU9wdGlvbnMFDmlzUHJldk9wdGlvbmFsBQlvbGRDaG9pY2UFE25ld1RvdGFsQnlPbGRDaG9pY2UFBmNob2ljZQUTbmV3VG90YWxCeU5ld0Nob2ljZQQLcmVsZWFzZVRpbWUJAJYDAQkAzAgCBQNlbmQJAMwIAgkBDGdldEludE9yRWxzZQIJARdrZXlVc2VyR25zYnRSZWxlYXNlVGltZQEFDnVzZXJBZGRyZXNzU3RyAAAFA25pbAkAlAoCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJARxrZXlQcm9wb3NhbENob2ljZUJ5SWRBbmRVc2VyAgUKcHJvcG9zYWxJZAUOdXNlckFkZHJlc3NTdHIFBmNob2ljZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBG2tleVByb3Bvc2FsVm90ZXNCeUlkQW5kVXNlcgIFCnByb3Bvc2FsSWQFDnVzZXJBZGRyZXNzU3RyBQhnbnNidEFtdAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHWtleVByb3Bvc2FsVm90ZXNCeUlkQW5kT3B0aW9uAgUKcHJvcG9zYWxJZAUGY2hvaWNlBRNuZXdUb3RhbEJ5TmV3Q2hvaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEea2V5TnVtVW5pcXVlVm90ZXJzQnlQcm9wb3NhbElkAQUKcHJvcG9zYWxJZAkAZAIFFW51bVZvdGVyc0J5UHJvcG9zYWxJZAUKdW5pcXVlRGlmZgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBF2tleVVzZXJHbnNidFJlbGVhc2VUaW1lAQUOdXNlckFkZHJlc3NTdHIFC3JlbGVhc2VUaW1lCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEYa2V5U3RhdHNBdmVyVW5pcXVlVm90ZXJzAAUUbmV3QXZlclVuaXF1ZVZvdGVyczYJAMwIAgkBDEludGVnZXJFbnRyeQIJARZrZXlTdGF0c0F2ZXJHbnNidFZvdGVkAAUMbmV3QXZlckduc2J0CQDMCAIJAQtTdHJpbmdFbnRyeQIJARlrZXlQcm9wb3NhbFN0YXR1c0RhdGFCeUlkAQUKcHJvcG9zYWxJZAkBEHVwZGF0ZVN0YXR1c0RhdGEEBQtkeW5hbWljRGF0YQUPaXNRdW9ydW1SZWFjaGVkBQZ3aW5PcHQFCG5ld1RvdGFsBQNuaWwFEG9wdGlvbmFsVG90YWxPbGQFBHVuaXQBaQESaW5pdGlhdGVJZGVhVm90aW5nBQlmb3J1bUxpbmsFdGl0bGUPdm90aW5nU3RhcnRUaW1lDXZvdGluZ0VuZFRpbWULb3B0aW9uc0xpc3QDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhxFeGFjdGx5IG9uZSBwYXltZW50IHJlcXVpcmVkAwkBAiE9AgkAkAMBBQtvcHRpb25zTGlzdAACCQACAQIrRXhhY3RseSAyIG9wdGlvbiBbJ05PJywgJ1lFUyddIGFyZSBleHBlY3RlZAMJAQIhPQIJAJEDAgULb3B0aW9uc0xpc3QAAAICTk8JAAIBAh1PcHRpb24gTk8gc2hvdWxkIGJlIHRoZSBmaXJzdAMJAQIhPQIJAJEDAgULb3B0aW9uc0xpc3QAAQIDWUVTCQACAQIfT3B0aW9uIFlFUyBzaG91bGQgYmUgdGhlIHNlY29uZAkBDmluaXRpYXRlVm90aW5nCwkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAACQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQCBElERUEJAKUIAQgFAWkGY2FsbGVyBQlmb3J1bUxpbmsFBXRpdGxlBQ92b3RpbmdTdGFydFRpbWUFDXZvdGluZ0VuZFRpbWUCB1BFTkRJTkcFA25pbAULb3B0aW9uc0xpc3QBaQEUaW5pdGlhdGVVcGRhdGVWb3RpbmcFCWZvcnVtTGluawV0aXRsZQ92b3RpbmdTdGFydFRpbWUNdm90aW5nRW5kVGltZQZ0eExpc3QDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhxFeGFjdGx5IG9uZSBwYXltZW50IHJlcXVpcmVkAwkAZgIAAQkAkAMBBQZ0eExpc3QJAAIBAhpUcmFuc2FjdGlvbnMgbGlzdCBpcyBlbXB0eQkBDmluaXRpYXRlVm90aW5nCwkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAACQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQCBlVQREFURQkApQgBCAUBaQZjYWxsZXIFCWZvcnVtTGluawUFdGl0bGUFD3ZvdGluZ1N0YXJ0VGltZQUNdm90aW5nRW5kVGltZQIHUEVORElORwUGdHhMaXN0CQDMCAICAk5PCQDMCAICA1lFUwUDbmlsAWkBDGNhbmNlbFZvdGluZwEKcHJvcG9zYWxJZAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECDm5vdCBhdXRob3JpemVkBAtjdXJyZW50RGF0YQkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMJARlrZXlQcm9wb3NhbFN0YXR1c0RhdGFCeUlkAQUKcHJvcG9zYWxJZAQLdXBkYXRlZERhdGEJAKwCAgkArAICCQCvAgIFC2N1cnJlbnREYXRhCQEFdmFsdWUBCQC3CQIFC2N1cnJlbnREYXRhBQNTRVAFA1NFUAIEdHJ1ZQkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIJARlrZXlQcm9wb3NhbFN0YXR1c0RhdGFCeUlkAQUKcHJvcG9zYWxJZAULdXBkYXRlZERhdGEFA25pbAUEdW5pdAFpAQthcHBseVVwZGF0ZQEKcHJvcG9zYWxJZAQIcHJvcERhdGEJALUJAgkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMJARNrZXlQcm9wb3NhbERhdGFCeUlkAQUKcHJvcG9zYWxJZAUDU0VQBANlbmQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhwcm9wRGF0YQUJZ292SWR4RW5kBANub3cIBQlsYXN0QmxvY2sJdGltZXN0YW1wAwkAZgIFA2VuZAUDbm93CQACAQIaVm90aW5nIGlzIG5vdCBmaW5pc2hlZCB5ZXQDCQECIT0CAgZVUERBVEUJAJEDAgUIcHJvcERhdGEFCmdvdklkeFR5cGUJAAIBAh9Pbmx5IFVQREFURSB0eXBlIGNhbiBiZSBhcHBsaWVkBAtkeW5hbWljRGF0YQkAtQkCCQEPZ2V0U3RyaW5nT3JGYWlsAgUEdGhpcwkBGWtleVByb3Bvc2FsU3RhdHVzRGF0YUJ5SWQBBQpwcm9wb3NhbElkBQNTRVADCQAAAgkAkQMCBQtkeW5hbWljRGF0YQUWZ292U3RhdHVzSWR4SXNDYW5jZWxlZAIEdHJ1ZQkAAgECElZvdGluZyBpcyBjYW5jZWxlZAMJAQIhPQIJAJEDAgULZHluYW1pY0RhdGEFE2dvdlN0YXR1c0lkeElzVmFsaWQCBHRydWUJAAIBAhVWb3Rpbmcgc3RhdHVzIGludmFsaWQDCQECIT0CCQCRAwIFC2R5bmFtaWNEYXRhBRJnb3ZTdGF0dXNJZHhXaW5PcHQCATEJAAIBAiFXaW5uZXIgaXMgJ05PJyAtIG5vdGhpbmcgdG8gYXBwbHkDCQAAAgkAkQMCBQtkeW5hbWljRGF0YQUVZ292U3RhdHVzSWR4U2NBcHBsaWVkAgR0cnVlCQACAQIbU2NyaXB0cyBhcmUgYWxyZWFkeSBhcHBsaWVkBApzY3JpcHRUaW1lCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgULZHluYW1pY0RhdGEFEmdvdlN0YXR1c0lkeFNjVGltZQMJAGYCCQBlAgUDbm93BQpQQVNUTUFSR0lOBQpzY3JpcHRUaW1lCQACAQkArAICCQCsAgICElNjcmlwdHMgdGltZXN0YW1wPQkApAMBBQpzY3JpcHRUaW1lAiogaXMgdG9vIGZhciBpbiB0aGUgcGFzdCwgbWF4IDIgaHJzIGFsbG93ZWQDCQBmAgUKc2NyaXB0VGltZQkAZAIFA25vdwUMRlVUVVJFTUFSR0lOCQACAQkArAICCQCsAgICElNjcmlwdHMgdGltZXN0YW1wPQkApAMBBQpzY3JpcHRUaW1lAi4gaXMgdG9vIGZhciBpbiB0aGUgZnV0dXJlLCBtYXggMS41IGhycyBhbGxvd2VkBAxpblByb2dyZXNzSWQJAQxnZXRJbnRPckVsc2UCCQESa2V5QXBwbHlJblByb2dyZXNzAAD///////////8BAwkBAiE9AgUMaW5Qcm9ncmVzc0lkAP///////////wEJAAIBCQCsAgIJAKwCAgILcHJvcG9zYWxJZD0JAKQDAQUMaW5Qcm9ncmVzc0lkAisgaXMgYWxyZWFkeSBiZWluZyBhcHBsaWVkLiBGaW5pc2ggaXQgZmlyc3QhBAhzaHV0ZG93bgkA/AcEBQ9jb250cm9sQ29udHJhY3QCFWNhbGxFbWVyZ2VuY3lTaHV0ZG93bgkAzAgCAhpBcHBseWluZyBHb3Zlcm5hbmNlIFVQREFURQUDbmlsBQNuaWwDCQAAAgUIc2h1dGRvd24FCHNodXRkb3duCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIJARJrZXlBcHBseUluUHJvZ3Jlc3MABQpwcm9wb3NhbElkBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQELZmluaXNoQXBwbHkABApwcm9wb3NhbElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ8IAQkBEmtleUFwcGx5SW5Qcm9ncmVzcwACJ05vIGFwcGx5IGluIHByb2dyZXNzLCBub3RoaW5nIHRvIGZpbmlzaAQIcHJvcERhdGEJALUJAgkBD2dldFN0cmluZ09yRmFpbAIFBHRoaXMJARNrZXlQcm9wb3NhbERhdGFCeUlkAQUKcHJvcG9zYWxJZAUDU0VQBAZ0eExpc3QJALUJAgkAkQMCBQhwcm9wRGF0YQULZ292SWR4VHhJZHMFB0xJU1RTRVAEC2R5bmFtaWNEYXRhCQC1CQIJAQ9nZXRTdHJpbmdPckZhaWwCBQR0aGlzCQEZa2V5UHJvcG9zYWxTdGF0dXNEYXRhQnlJZAEFCnByb3Bvc2FsSWQFA1NFUAMJAAACCQCRAwIFC2R5bmFtaWNEYXRhBRVnb3ZTdGF0dXNJZHhTY0FwcGxpZWQCBHRydWUJAAIBAhtTY3JpcHRzIGFyZSBhbHJlYWR5IGFwcGxpZWQKAQdjaGVja2VyAgNhY2MCdHgDCQEBIQEJAQlpc0RlZmluZWQBCQDpBwEJANkEAQUCdHgJAAIBCQCsAgICEk5PVCBhcHBsaWVkIHR4SWQ6IAUCdHgFBHVuaXQEB2lnbm9yZWQKAAIkbAUGdHhMaXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAUEdW5pdAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEHY2hlY2tlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMjAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUBAd2ZXJzaW9uCQBkAgkBDGdldEludE9yRWxzZQIJARRrZXlMYXN0VXBkYXRlVmVyc2lvbgAAAAABCQCUCgIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBEmtleUFwcGx5SW5Qcm9ncmVzcwAJAMwIAgkBDEludGVnZXJFbnRyeQIJARRrZXlMYXN0VXBkYXRlVmVyc2lvbgAFB3ZlcnNpb24JAMwIAgkBC1N0cmluZ0VudHJ5AgkBGWtleVByb3Bvc2FsU3RhdHVzRGF0YUJ5SWQBBQpwcm9wb3NhbElkCQERc3RhdHVzQXBwbHlTY3JpcHQBBQtkeW5hbWljRGF0YQkAzAgCCQEQRXhlY3V0aW9uSGlzdG9yeQQFB3ZlcnNpb24JAJEDAgUIcHJvcERhdGEFC2dvdklkeFRpdGxlCQCRAwIFCHByb3BEYXRhBQlnb3ZJZHhVcmwFCnByb3Bvc2FsSWQFA25pbAUHaWdub3JlZADLHHCX", "height": 2401712, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: D5wQzkdWpj4boutAXTFcWFxCNGd7x17QjMUpfBuPrZqf Next: FX6dTevMCcgLnir8vUMaqu18wz1YHqn521sb5XHX97yM Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let ONE = toBigInt(1)
4+let revisionNum = ""
55
6-let numbers = [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, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
6+let SEP = "__"
77
8-let MBI = parseBigIntValue("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
8+let LISTSEP = ":"
99
10-func zzz () = {
11- func fff (acc,n) = {
12- let $t0662686 = acc
13- let result = $t0662686._1
14- let fact = $t0662686._2
15- let newFact = fraction(fact, toBigInt(n), ONE)
16- if ((newFact > MBI))
17- then acc
18- else $Tuple2((result + fraction(MBI, ONE, newFact)), newFact)
19- }
10+let DEFAULTQUORUM = 500000
2011
21- let x = {
22- let $l = numbers
12+let URLPATTERN = "https://forum.neutrino.at/"
13+
14+let MAXTITLE = 250
15+
16+let MAXURL = 250
17+
18+let MAXVOTINGTIME = 1209600000
19+
20+let MULT6 = 1000000
21+
22+let DEFAULTPAYMENT = 1000000000
23+
24+let DEFAULTCREATIONGNSBT = 1000000000
25+
26+let PASTMARGIN = 7200000
27+
28+let FUTUREMARGIN = 5400000
29+
30+let DEFAULTFIRSTPROPOSAL = 111
31+
32+let govIdxProposalTxId = 1
33+
34+let govIdxType = 2
35+
36+let govIdxAuthor = 3
37+
38+let govIdxUrl = 4
39+
40+let govIdxTitle = 5
41+
42+let govIdxCreationTime = 6
43+
44+let govIdxStart = 7
45+
46+let govIdxEnd = 8
47+
48+let govIdxTxIds = 9
49+
50+let govIdxQuorum = 10
51+
52+let govIdxOptions = 11
53+
54+let govStatusIdxIsValid = 1
55+
56+let govStatusIdxWinOpt = 2
57+
58+let govStatusIdxWinVotes = 3
59+
60+let govStatusIdxTotalVotes = 4
61+
62+let govStatusIdxScApplied = 5
63+
64+let govStatusIdxScTime = 6
65+
66+let govStatusIdxIsCanceled = 7
67+
68+func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
69+
70+
71+func getIntOrElse (key,defaultVal) = valueOrElse(getInteger(this, key), defaultVal)
72+
73+
74+let IdxControlCfgNeutrinoDapp = 1
75+
76+let IdxControlCfgAuctionDapp = 2
77+
78+let IdxControlCfgRpdDapp = 3
79+
80+let IdxControlCfgMathDapp = 4
81+
82+let IdxControlCfgLiquidationDapp = 5
83+
84+let IdxControlCfgRestDapp = 6
85+
86+let IdxControlCfgNodeRegistryDapp = 7
87+
88+let IdxControlCfgNsbtStakingDapp = 8
89+
90+let IdxControlCfgMediatorDapp = 9
91+
92+let IdxControlCfgSurfStakingDapp = 10
93+
94+let IdxControlCfgGnsbtControllerDapp = 11
95+
96+let IdxControlCfgRestV2Dapp = 12
97+
98+let IdxControlCfgGovernanceDapp = 13
99+
100+func keyControlAddress () = "%s%s__config__controlAddress"
101+
102+
103+func keyControlCfg () = "%s__controlConfig"
104+
105+
106+func readControlCfgOrFail (control) = split_4C(getStringOrFail(control, keyControlCfg()), SEP)
107+
108+
109+func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
110+
111+
112+let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP"))
113+
114+let controlCfg = readControlCfgOrFail(controlContract)
115+
116+let neutrinoContract = getContractAddressOrFail(controlCfg, IdxControlCfgNeutrinoDapp)
117+
118+let gnsbtControllerContract = getContractAddressOrFail(controlCfg, IdxControlCfgGnsbtControllerDapp)
119+
120+func keyQuorumRequiredPercent (type) = ("%s%s__quorumRequired__" + type)
121+
122+
123+func keyPaymentRequired () = "%s__paymentRequired"
124+
125+
126+func keyGnsbtRequired () = "%s__gNsbtRequired"
127+
128+
129+func keyLastProposalId () = "%s__proposalId"
130+
131+
132+func keyFirstProposalId () = "%s__firstProposalId"
133+
134+
135+func keyLastUpdateVersion () = "%s__updateVersion"
136+
137+
138+func keyProposalStatusDataById (proposalId) = ("%s%d__proposalStatusData__" + toString(proposalId))
139+
140+
141+func keyProposalDataById (proposalId) = ("%s%d__proposalData__" + toString(proposalId))
142+
143+
144+func keyProposalVotesByIdAndOption (proposalId,opt) = makeString(["%s%d%d", "votesByOpt", toString(proposalId), toString(opt)], SEP)
145+
146+
147+func keyProposalVotesByIdAndUser (proposalId,userAddr) = makeString(["%s%d%s", "votesByUser", toString(proposalId), userAddr], SEP)
148+
149+
150+func keyProposalChoiceByIdAndUser (proposalId,userAddr) = makeString(["%s%d%s", "optionByUser", toString(proposalId), userAddr], SEP)
151+
152+
153+func keyApplyInProgress () = "%s__applyInProgress"
154+
155+
156+func keyProposalIdByTopicId (topicId) = ("%s%d__proposalIdByTopicId__" + toString(topicId))
157+
158+
159+func keyUserGnsbtReleaseTime (userAddr) = ("%s%s_userGnsbtReleaseTime__" + userAddr)
160+
161+
162+func keyNumUniqueVotersByProposalId (proposalId) = ("%s%d__numVoters__" + toString(proposalId))
163+
164+
165+func keyStatsAverUniqueVoters () = "%s%s%s__stats__avg__uniqueVoters"
166+
167+
168+func keyStatsAverGnsbtVoted () = "%s%s%s__stats__avg__gnsbtVoted"
169+
170+
171+func keyStatsUniqueAuthors () = "%s%s__stats__uniqueAuthors"
172+
173+
174+func keyNumProposalsByAuthor (addressStr) = ("%s%s__numProposalsByAuthor__" + addressStr)
175+
176+
177+func keyApplyHistory (timestamp) = ("%s%d__applyHistory__" + toString(timestamp))
178+
179+
180+func asAnyList (v) = match v {
181+ case l: List[Any] =>
182+ l
183+ case _ =>
184+ throw("fail to cast into List[Any]")
185+}
186+
187+
188+func asInt (v) = match v {
189+ case i: Int =>
190+ i
191+ case _ =>
192+ throw("fail to cast into Int")
193+}
194+
195+
196+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)
197+
198+
199+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)
200+
201+
202+func checkTxList (txList) = if ((size(txList) > 20))
203+ then throw(("Too many transactions: " + toString(size(txList))))
204+ else {
205+ func combiner (acc,tx) = if ((size(fromBase58String(tx)) != 32))
206+ then throw(("Wrong txId: " + tx))
207+ else if ((acc == ""))
208+ then tx
209+ else ((acc + LISTSEP) + tx)
210+
211+ let $l = txList
23212 let $s = size($l)
24- let $acc0 = $Tuple2(MBI, ONE)
213+ let $acc0 = ""
25214 func $f0_1 ($a,$i) = if (($i >= $s))
26215 then $a
27- else fff($a, $l[$i])
216+ else combiner($a, $l[$i])
28217
29218 func $f0_2 ($a,$i) = if (($i >= $s))
30219 then $a
31- else throw("List size exceeds 99")
220+ else throw("List size exceeds 20")
32221
33- $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($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), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99)
222+ $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)
34223 }
35- x._1
224+
225+
226+let IdxEffTotal = 0
227+
228+let IdxEffUser = 1
229+
230+func getEffectiveGnsbt (userAddrStrOrEmpty) = {
231+ let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", [userAddrStrOrEmpty, 0, 0], nil))
232+ let nsbtData = asAnyList(gnsbtData[2])
233+ let userFromNsbt = asInt(nsbtData[2])
234+ let totalFromNsbt = asInt(nsbtData[3])
235+ let userMatureFromSurf = asInt(gnsbtData[9])
236+ let totalMatureFromSurf = asInt(gnsbtData[6])
237+[(totalFromNsbt + totalMatureFromSurf), (userFromNsbt + userMatureFromSurf)]
36238 }
37239
240+
241+func validateLink (url) = if ((value(indexOf(url, URLPATTERN)) != 0))
242+ then throw("Invalid url")
243+ else if ((size(url) > MAXURL))
244+ then throw("Url too long!")
245+ else {
246+ let topicId = valueOrErrorMessage(parseInt(drop(url, (value(lastIndexOf(url, "/")) + 1))), "Wrong topicId")
247+ let registeredId = getInteger(keyProposalIdByTopicId(topicId))
248+ if (isDefined(registeredId))
249+ then throw(("Voting with such forum link is already registered by id=" + toString(value(registeredId))))
250+ else topicId
251+ }
252+
253+
254+func initiateVoting (payment,proposalTxId,type,author,forumLink,title,votingStartTime,votingEndTime,status,txList,optionsList) = if ((payment.assetId != unit))
255+ then throw("Allowed WAVES payment only!")
256+ else {
257+ let pmtReq = getIntOrElse(keyPaymentRequired(), DEFAULTPAYMENT)
258+ if ((pmtReq > payment.amount))
259+ then throw(("Payment attached should be at least " + toString(pmtReq)))
260+ else {
261+ let topicId = validateLink(forumLink)
262+ if ((title == ""))
263+ then throw("Title is empty")
264+ else if ((size(title) > MAXTITLE))
265+ then throw("Too long title")
266+ else {
267+ let proposalTime = lastBlock.timestamp
268+ if ((proposalTime > votingStartTime))
269+ then throw(((("votingStartTime=" + toString(votingStartTime)) + " < proposalTime=") + toString(proposalTime)))
270+ else if ((votingStartTime > votingEndTime))
271+ then throw(((("votingEndTime=" + toString(votingEndTime)) + " < votingStartTime=") + toString(votingStartTime)))
272+ else if (((votingEndTime - votingStartTime) > MAXVOTINGTIME))
273+ then throw(((("Voting period exceeds max: " + toString((votingEndTime - votingStartTime))) + " > ") + toString(MAXVOTINGTIME)))
274+ else {
275+ let txIds = if ((type == "IDEA"))
276+ then ""
277+ else checkTxList(txList)
278+ if ((1 >= size(optionsList)))
279+ then throw("Too few choices to vote")
280+ else {
281+ let eff = getEffectiveGnsbt(author)
282+ let gnsbtTotal = eff[IdxEffTotal]
283+ let gNsbtUser = eff[IdxEffUser]
284+ let gnsbtReq = getIntOrElse(keyGnsbtRequired(), DEFAULTCREATIONGNSBT)
285+ if ((gnsbtReq > gNsbtUser))
286+ then throw((("You need at least " + toString(gnsbtReq)) + " gNsbt to create voting"))
287+ else {
288+ let amountLeased = invoke(neutrinoContract, "acceptWaves", nil, [payment])
289+ if ((amountLeased == amountLeased))
290+ then {
291+ let quorum = getIntOrElse(keyQuorumRequiredPercent(type), DEFAULTQUORUM)
292+ let quorumInGnsbt = fraction(quorum, gnsbtTotal, MULT6)
293+ let proposalId = (getIntOrElse(keyLastProposalId(), 0) + 1)
294+ let numProposalsByAuthor = (getIntOrElse(keyNumProposalsByAuthor(author), 0) + 1)
295+ let uniqAuthors = (getIntOrElse(keyStatsUniqueAuthors(), 0) + (if ((numProposalsByAuthor == 1))
296+ then 1
297+ else 0))
298+ let optionsStr = makeString(optionsList, LISTSEP)
299+ $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)
300+ }
301+ else throw("Strict value is not equal to itself.")
302+ }
303+ }
304+ }
305+ }
306+ }
307+ }
308+
309+
310+func calcWinOption (proposalId,optionsList,isPrevOptional,oldChoice,optionalTotalOld,newChoice,newTotalByNewChoice) = {
311+ func findBest (acc,elem) = {
312+ let idx = value(indexOf(optionsList, elem))
313+ let val = if (isPrevOptional)
314+ then if ((idx == newChoice))
315+ then newTotalByNewChoice
316+ else getIntOrElse(keyProposalVotesByIdAndOption(proposalId, idx), 0)
317+ else if ((idx == value(oldChoice)))
318+ then optionalTotalOld
319+ else if ((idx == newChoice))
320+ then newTotalByNewChoice
321+ else getIntOrElse(keyProposalVotesByIdAndOption(proposalId, idx), 0)
322+ if ((acc._2 > val))
323+ then acc
324+ else $Tuple2(idx, val)
325+ }
326+
327+ let $l = optionsList
328+ let $s = size($l)
329+ let $acc0 = $Tuple2(0, 0)
330+ func $f0_1 ($a,$i) = if (($i >= $s))
331+ then $a
332+ else findBest($a, $l[$i])
333+
334+ func $f0_2 ($a,$i) = if (($i >= $s))
335+ then $a
336+ else throw("List size exceeds 10")
337+
338+ $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)
339+ }
340+
341+
342+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)
343+
344+
345+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)
346+
347+
348+func ExecutionHistory (updateVersion,title,url,proposalId) = {
349+ let gnsbtTotal = getEffectiveGnsbt("")[IdxEffTotal]
350+ let turnout = 500000
351+ StringEntry(keyApplyHistory(lastBlock.timestamp), makeString(["%d%d%d%s%s%d", toString(updateVersion), toString(gnsbtTotal), toString(turnout), title, url, toString(proposalId)], SEP))
352+ }
353+
354+
355+@Callable(i)
356+func constructorV1 (controlAddr,gNsbtReqToInit,wavesReqToInit,quorumReqPercIdea,quorumReqPercUpdate) = if ((i.caller != this))
357+ then throw("Permission denied")
358+ else [StringEntry(keyControlAddress(), controlAddr), IntegerEntry(keyGnsbtRequired(), gNsbtReqToInit), IntegerEntry(keyPaymentRequired(), wavesReqToInit), IntegerEntry(keyQuorumRequiredPercent("IDEA"), quorumReqPercIdea), IntegerEntry(keyQuorumRequiredPercent("UPDATE"), quorumReqPercUpdate)]
359+
360+
361+
362+@Callable(i)
363+func castVote (proposalId,choice) = {
364+ let userAddressStr = toString(i.caller)
365+ let dynamicData = split(getStringOrFail(this, keyProposalStatusDataById(proposalId)), SEP)
366+ if ((dynamicData[govStatusIdxIsCanceled] == "true"))
367+ then throw("Voting is canceled by team")
368+ else {
369+ let propData = split(getStringOrFail(this, keyProposalDataById(proposalId)), SEP)
370+ let start = parseIntValue(propData[govIdxStart])
371+ let end = parseIntValue(propData[govIdxEnd])
372+ let now = lastBlock.timestamp
373+ if ((start > now))
374+ then throw("Voting not started yet")
375+ else if ((now >= end))
376+ then throw("Voting already finished")
377+ else {
378+ let availableOptions = split(propData[govIdxOptions], LISTSEP)
379+ let numOptions = size(availableOptions)
380+ if ((1 >= numOptions))
381+ then throw("Too few choices to vote")
382+ else if ((choice >= numOptions))
383+ then throw(("Unknown choice! Must be 0.." + toString((numOptions - 1))))
384+ else {
385+ let eff = getEffectiveGnsbt(userAddressStr)
386+ let gnsbtAmt = eff[IdxEffUser]
387+ if ((0 >= gnsbtAmt))
388+ then throw("no gnsbt to vote")
389+ else {
390+ let gnsbtTotal = eff[IdxEffTotal]
391+ let oldChoice = getInteger(keyProposalChoiceByIdAndUser(proposalId, userAddressStr))
392+ let oldUserVotes = if (!(isDefined(oldChoice)))
393+ then 0
394+ else getIntOrElse(keyProposalVotesByIdAndUser(proposalId, userAddressStr), 0)
395+ let oldTotalByOldChoice = if (isDefined(oldChoice))
396+ then getIntOrElse(keyProposalVotesByIdAndOption(proposalId, value(oldChoice)), 0)
397+ else 0
398+ let oldTotalByNewChoice = getIntOrElse(keyProposalVotesByIdAndOption(proposalId, choice), 0)
399+ let oldTotal = parseIntValue(dynamicData[govStatusIdxTotalVotes])
400+ let newTotalByOldChoice = if (!(isDefined(oldChoice)))
401+ then 0
402+ else ((oldTotalByOldChoice - oldUserVotes) + (if ((value(oldChoice) == choice))
403+ then gnsbtAmt
404+ else 0))
405+ let newTotalByNewChoice = if (if (isDefined(oldChoice))
406+ then (value(oldChoice) == choice)
407+ else false)
408+ then newTotalByOldChoice
409+ else (oldTotalByNewChoice + gnsbtAmt)
410+ let newTotal = ((oldTotal - oldUserVotes) + gnsbtAmt)
411+ let isQuorumReached = (newTotal >= parseIntValue(propData[govIdxQuorum]))
412+ let numVotersByProposalId = getIntOrElse(keyNumUniqueVotersByProposalId(proposalId), 0)
413+ let oldAverUniqueVoters6 = getIntOrElse(keyStatsAverUniqueVoters(), 0)
414+ let numProposals = ((getIntegerValue(keyLastProposalId()) - valueOrElse(getInteger(keyFirstProposalId()), DEFAULTFIRSTPROPOSAL)) + 1)
415+ let uniqueDiff = if ((oldUserVotes == 0))
416+ then 1
417+ else 0
418+ let newAverUniqueVoters6 = (oldAverUniqueVoters6 + fraction(uniqueDiff, MULT6, numProposals))
419+ let oldAverGnsbt = getIntOrElse(keyStatsAverGnsbtVoted(), 0)
420+ let newAverGnsbt = (oldAverGnsbt + ((gnsbtAmt - oldUserVotes) / numProposals))
421+ let isPrevOptional = if (!(isDefined(oldChoice)))
422+ then true
423+ else (value(oldChoice) == choice)
424+ let optionalTotalOld = if (isPrevOptional)
425+ then nil
426+ else [IntegerEntry(keyProposalVotesByIdAndOption(proposalId, value(oldChoice)), newTotalByOldChoice)]
427+ let winOpt = calcWinOption(proposalId, availableOptions, isPrevOptional, oldChoice, newTotalByOldChoice, choice, newTotalByNewChoice)
428+ let releaseTime = max([end, getIntOrElse(keyUserGnsbtReleaseTime(userAddressStr), 0)])
429+ $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)
430+ }
431+ }
432+ }
433+ }
434+ }
435+
436+
437+
438+@Callable(i)
439+func initiateIdeaVoting (forumLink,title,votingStartTime,votingEndTime,optionsList) = if ((size(i.payments) != 1))
440+ then throw("Exactly one payment required")
441+ else if ((size(optionsList) != 2))
442+ then throw("Exactly 2 option ['NO', 'YES'] are expected")
443+ else if ((optionsList[0] != "NO"))
444+ then throw("Option NO should be the first")
445+ else if ((optionsList[1] != "YES"))
446+ then throw("Option YES should be the second")
447+ else initiateVoting(value(i.payments[0]), toBase58String(i.transactionId), "IDEA", toString(i.caller), forumLink, title, votingStartTime, votingEndTime, "PENDING", nil, optionsList)
448+
449+
450+
451+@Callable(i)
452+func initiateUpdateVoting (forumLink,title,votingStartTime,votingEndTime,txList) = if ((size(i.payments) != 1))
453+ then throw("Exactly one payment required")
454+ else if ((1 > size(txList)))
455+ then throw("Transactions list is empty")
456+ else initiateVoting(value(i.payments[0]), toBase58String(i.transactionId), "UPDATE", toString(i.caller), forumLink, title, votingStartTime, votingEndTime, "PENDING", txList, ["NO", "YES"])
457+
458+
459+
460+@Callable(i)
461+func cancelVoting (proposalId) = if ((i.caller != this))
462+ then throw("not authorized")
463+ else {
464+ let currentData = getStringOrFail(this, keyProposalStatusDataById(proposalId))
465+ let updatedData = ((take(currentData, value(lastIndexOf(currentData, SEP))) + SEP) + "true")
466+ $Tuple2([StringEntry(keyProposalStatusDataById(proposalId), updatedData)], unit)
467+ }
468+
469+
470+
471+@Callable(i)
472+func applyUpdate (proposalId) = {
473+ let propData = split(getStringOrFail(this, keyProposalDataById(proposalId)), SEP)
474+ let end = parseIntValue(propData[govIdxEnd])
475+ let now = lastBlock.timestamp
476+ if ((end > now))
477+ then throw("Voting is not finished yet")
478+ else if (("UPDATE" != propData[govIdxType]))
479+ then throw("Only UPDATE type can be applied")
480+ else {
481+ let dynamicData = split(getStringOrFail(this, keyProposalStatusDataById(proposalId)), SEP)
482+ if ((dynamicData[govStatusIdxIsCanceled] == "true"))
483+ then throw("Voting is canceled")
484+ else if ((dynamicData[govStatusIdxIsValid] != "true"))
485+ then throw("Voting status invalid")
486+ else if ((dynamicData[govStatusIdxWinOpt] != "1"))
487+ then throw("Winner is 'NO' - nothing to apply")
488+ else if ((dynamicData[govStatusIdxScApplied] == "true"))
489+ then throw("Scripts are already applied")
490+ else {
491+ let scriptTime = parseIntValue(dynamicData[govStatusIdxScTime])
492+ if (((now - PASTMARGIN) > scriptTime))
493+ then throw((("Scripts timestamp=" + toString(scriptTime)) + " is too far in the past, max 2 hrs allowed"))
494+ else if ((scriptTime > (now + FUTUREMARGIN)))
495+ then throw((("Scripts timestamp=" + toString(scriptTime)) + " is too far in the future, max 1.5 hrs allowed"))
496+ else {
497+ let inProgressId = getIntOrElse(keyApplyInProgress(), -1)
498+ if ((inProgressId != -1))
499+ then throw((("proposalId=" + toString(inProgressId)) + " is already being applied. Finish it first!"))
500+ else {
501+ let shutdown = invoke(controlContract, "callEmergencyShutdown", ["Applying Governance UPDATE"], nil)
502+ if ((shutdown == shutdown))
503+ then $Tuple2([IntegerEntry(keyApplyInProgress(), proposalId)], unit)
504+ else throw("Strict value is not equal to itself.")
505+ }
506+ }
507+ }
508+ }
509+ }
510+
511+
512+
513+@Callable(i)
514+func finishApply () = {
515+ let proposalId = valueOrErrorMessage(getInteger(keyApplyInProgress()), "No apply in progress, nothing to finish")
516+ let propData = split(getStringOrFail(this, keyProposalDataById(proposalId)), SEP)
517+ let txList = split(propData[govIdxTxIds], LISTSEP)
518+ let dynamicData = split(getStringOrFail(this, keyProposalStatusDataById(proposalId)), SEP)
519+ if ((dynamicData[govStatusIdxScApplied] == "true"))
520+ then throw("Scripts are already applied")
521+ else {
522+ func checker (acc,tx) = if (!(isDefined(transactionHeightById(fromBase58String(tx)))))
523+ then throw(("NOT applied txId: " + tx))
524+ else unit
525+
526+ let ignored = {
527+ let $l = txList
528+ let $s = size($l)
529+ let $acc0 = unit
530+ func $f0_1 ($a,$i) = if (($i >= $s))
531+ then $a
532+ else checker($a, $l[$i])
533+
534+ func $f0_2 ($a,$i) = if (($i >= $s))
535+ then $a
536+ else throw("List size exceeds 20")
537+
538+ $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)
539+ }
540+ let version = (getIntOrElse(keyLastUpdateVersion(), 0) + 1)
541+ $Tuple2([DeleteEntry(keyApplyInProgress()), IntegerEntry(keyLastUpdateVersion(), version), StringEntry(keyProposalStatusDataById(proposalId), statusApplyScript(dynamicData)), ExecutionHistory(version, propData[govIdxTitle], propData[govIdxUrl], proposalId)], ignored)
542+ }
543+ }
38544
39545

github/deemru/w8io/3ef1775 
100.70 ms