tx · CPrDm4obDHeYaAhoYQV7sKzGXtLmw8BGVVwLz4Dpga33 3N8y4wxX3JC4TdrCJBXX16SjWf6X256hrep: -0.03900000 Waves 2023.06.21 17:47 [2632547] smart account 3N8y4wxX3JC4TdrCJBXX16SjWf6X256hrep > SELF 0.00000000 Waves
{ "type": 13, "id": "CPrDm4obDHeYaAhoYQV7sKzGXtLmw8BGVVwLz4Dpga33", "fee": 3900000, "feeAssetId": null, "timestamp": 1687358914620, "version": 2, "chainId": 84, "sender": "3N8y4wxX3JC4TdrCJBXX16SjWf6X256hrep", "senderPublicKey": "7v5L7QkXxfkirALdyqmox38QCsa9jtfAtgUfHTh34eWq", "proofs": [ "5tWRukYrfdrP1BJ7uHUJ9SVk1Mkq8RKSLT44dLtmz3pBTK4kRkFN64aKq5wjgz3e8pUKQH9RT4xPktWenR1wEdW2" ], "script": "base64:BgI7CAISBAoCCBgSAwoBCBIECgIRERIECgIRERIDCgEREgQKAgEBEgQKAggIEgUKAwgICBIDCgEREgMKAQiHAQAFY2hhaW4JAMkBAgkAygECCAUEdGhpcwVieXRlcwABAAEAC3VzZHRBc3NldElkBAckbWF0Y2gwBQVjaGFpbgMJAAACAQFXBQckbWF0Y2gwASCE2nqyCAM/TtG7yo7ui5O8yYLdC136B5ao1CP5qA//uQMJAAACAQFUBQckbWF0Y2gwASBVsdifcoeC7+XjW42sBatl3ppDoS8WuwXzGreHpfHFGAkAAgECDVVua25vd24gY2hhaW4AFWRlZmF1bHRSZXN0QWRkcmVzc1N0cgQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMAIjM1BRQ3V2RmJ2aDRMa1BVbnJuVTF6M2puYkExcDltM1dOaHYDCQAAAgEBVAUHJG1hdGNoMAIjM011bWtHR3p0Q0tBWHBXRHF4a2Rkb2ZxWFNVYnFRa3ZTSnkJAAIBAg1Vbmtub3duIGNoYWluABFJbmZyYVVwZ3JhZGVDb3N0UwQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMACAyK+gJQMJAAACAQFUBQckbWF0Y2gwAIDC1y8JAAIBAg1Vbmtub3duIGNoYWluAANTRVACAl9fAAVNVUxUNgDAhD0ABU1VTFQ3AICt4gQABU1VTFQ4AIDC1y8ABk1VTFQxMACAyK+gJQAKTEFORFBSRUZJWAIETEFORAAKRFVDS1BSRUZJWAIERFVDSwAKQVJUUFJFU0FMRQIHUFJFU0FMRQAGTlVNUkVTAAYABVNTSVpFABkABU1TSVpFAGQABUxTSVpFAOEBAAZYTFNJWkUAkAMAB1hYTFNJWkUA8QQAD0RBSUxZUkVTQllQSUVDRQCA+NIBAAlEQVlNSUxMSVMAgLiZKQAMV0hNVUxUSVBMSUVSAIDIr6AlAA9ERUZBVUxUTE9DQVRJT04CD0FmcmljYV9GX0FmcmljYQAQUkVTT1VSQ0VQUklDRU1JTgDVtQIADUVTTUFYUEFDS0FHRVMAAwAJRVNCVVlDT0VGAAQACkVTU0VMTENPRUYACgAFTUFYSFAAZAAIcmVzVHlwZXMJAMwIAgIDT2lsCQDMCAICA09yZQkAzAgCAgRXb29kCQDMCAICBFNhbmQJAMwIAgIEQ2xheQkAzAgCAgdPcmdhbmljBQNuaWwACG1hdFR5cGVzCQDMCAICBEZ1ZWwJAMwIAgIFTWV0YWwJAMwIAgIFUGxhbmsJAMwIAgIFR2xhc3MJAMwIAgIHUGxhc3RpYwkAzAgCAgdQcm90ZWluBQNuaWwACXByb2RUeXBlcwkAzAgCAhBGaXJzdCBBaWQgS2l0IEwxCQDMCAICEEZpcnN0IEFpZCBLaXQgTDIJAMwIAgIQRmlyc3QgQWlkIEtpdCBMMwkAzAgCAgtCYWNrcGFjayBMMQkAzAgCAgtCYWNrcGFjayBMMgkAzAgCAgtCYWNrcGFjayBMMwkAzAgCAg5Gb29kIFJhdGlvbiBMMQkAzAgCAg5Gb29kIFJhdGlvbiBMMgkAzAgCAg5Gb29kIFJhdGlvbiBMMwkAzAgCAgtKZXQgUGFjayBMMQkAzAgCAgtKZXQgUGFjayBMMgkAzAgCAgtKZXQgUGFjayBMMwkAzAgCAglTaGllbGQgTDEJAMwIAgIJU2hpZWxkIEwyCQDMCAICCVNoaWVsZCBMMwUDbmlsAApjb250aW5lbnRzCQDMCAICCEFtZXJpY2FzCQDMCAICBkV1cm9wZQkAzAgCAgRBc2lhCQDMCAICBkFmcmljYQkAzAgCAgdPY2VhbmlhBQNuaWwAEHByb2R1Y3Rpb25NYXRyaXgJAMwIAgISMV8xXzFfMl8yXzVfMV8xMF8wCQDMCAICEzJfMl8yXzRfNF8xMF8xXzEwXzAJAMwIAgITM18zXzNfNl82XzE1XzFfMTBfMAkAzAgCAhMyXzVfNV8yXzdfNV8yXzEwMF8xCQDMCAICFzRfMTBfMTBfNF8xNF8xMF8yXzEwMF8xCQDMCAICFzZfMTVfMTVfNl8yMV8xNV8yXzEwMF8xCQDMCAICEjFfMV8xXzFfMV84XzFfMTBfMgkAzAgCAhMyXzJfMl8yXzJfMTZfMV8xMF8yCQDMCAICEzNfM18zXzNfM18yNF8xXzEwXzIJAMwIAgITOV85XzFfNV81XzFfNV8xMDBfMwkAzAgCAhcxOF8xOF8yXzEwXzEwXzJfNV8xMDBfMwkAzAgCAhcyN18yN18zXzE1XzE1XzNfNV8xMDBfMwkAzAgCAhIyXzJfMV8yXzJfMl8xXzEwXzQJAMwIAgISNF80XzJfNF80XzRfMV8xMF80CQDMCAICEjZfNl8zXzZfNl82XzFfMTBfNAUDbmlsAA9jb250SWR4QW1lcmljYXMAAAANY29udElkeEV1cm9wZQABAAtjb250SWR4QXNpYQACAA1jb250SWR4QWZyaWNhAAMADmNvbnRJZHhPY2VhbmlhAAQADXJlY2lwZUlkeEZ1ZWwAAAAOcmVjaXBlSWR4TWV0YWwAAQAOcmVjaXBlSWR4UGxhbmsAAgAOcmVjaXBlSWR4R2xhc3MAAwAQcmVjaXBlSWR4UGxhc3RpYwAEABByZWNpcGVJZHhQcm90ZWluAAUAD3JlY2lwZUlkeFdlaWdodAAGABFyZWNpcGVJZHhQYWNrc2l6ZQAHABJyZWNpcGVJZHhDb250aW5lbnQACAAKcmVjTGFuZE51bQAAAAtyZWNMYW5kU2l6ZQABAAtyZWNUZXJyYWlucwACAAxyZWNDb250aW5lbnQAAwALd2hJZHhMZXZlbHMAAAAId2hJZHhSZXMAAQAId2hJZHhNYXQAAgAJd2hJZHhQcm9kAAMACXdoSWR4TE9GVAAEAAl2b2xMb2NrZWQAAAALdm9sT2NjdXBpZWQAAQAHdm9sRnJlZQACAAh2b2xUb3RhbAADAApicElkeExldmVsAAAACGJwSWR4UmVzAAEACGJwSWR4TWF0AAIACWJwSWR4UHJvZAADAQpnZXRQa2dTaXplAQdwcm9kSWR4CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgkAtQkCCQCRAwIFEHByb2R1Y3Rpb25NYXRyaXgFB3Byb2RJZHgCAV8FEXJlY2lwZUlkeFBhY2tzaXplAQ9nZXRTdHJpbmdPckZhaWwCB2FkZHJlc3MDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUHYWRkcmVzcwUDa2V5CQC5CQIJAMwIAgIKbWFuZGF0b3J5IAkAzAgCCQClCAEFB2FkZHJlc3MJAMwIAgIBLgkAzAgCBQNrZXkJAMwIAgIPIGlzIG5vdCBkZWZpbmVkBQNuaWwCAAEMZ2V0SW50T3JFbHNlAgNrZXkKZGVmYXVsdFZhbAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQNrZXkFCmRlZmF1bHRWYWwAEUlkeENmZ1N0YWtpbmdEYXBwAAEAEUlkeENmZ0Vjb25vbXlEYXBwAAIAFElkeENmZ0dvdmVybmFuY2VEYXBwAAMADUlkeENmZ1dsZ0RhcHAABAEKa2V5UmVzdENmZwACDiVzX19yZXN0Q29uZmlnAQ5rZXlSZXN0QWRkcmVzcwACDCVzX19yZXN0QWRkcgERcmVhZFJlc3RDZmdPckZhaWwBBHJlc3QJALwJAgkBD2dldFN0cmluZ09yRmFpbAIFBHJlc3QJAQprZXlSZXN0Q2ZnAAUDU0VQARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCB3Jlc3RDZmcDaWR4CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQdyZXN0Q2ZnBQNpZHgJAKwCAgIqUmVzdCBjZmcgZG9lc24ndCBjb250YWluIGFkZHJlc3MgYXQgaW5kZXggCQCkAwEFA2lkeAAMcmVzdENvbnRyYWN0CQERQGV4dHJOYXRpdmUoMTA2MikBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJAQ5rZXlSZXN0QWRkcmVzcwAFFWRlZmF1bHRSZXN0QWRkcmVzc1N0cgAHcmVzdENmZwkBEXJlYWRSZXN0Q2ZnT3JGYWlsAQUMcmVzdENvbnRyYWN0AA9zdGFraW5nQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQdyZXN0Q2ZnBRFJZHhDZmdTdGFraW5nRGFwcAAPZWNvbm9teUNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUHcmVzdENmZwURSWR4Q2ZnRWNvbm9teURhcHAAC2dvdkNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUHcmVzdENmZwUUSWR4Q2ZnR292ZXJuYW5jZURhcHAAC3dsZ0NvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUHcmVzdENmZwUNSWR4Q2ZnV2xnRGFwcAERa2V5TGFzdFR4SWRCeVVzZXIBBGFkZHIJAKwCAgIPbGFzdFR4SWRCeVVzZXJfBQRhZGRyARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBB2Fzc2V0SWQJAKwCAgIJbmZ0T3duZXJfBQdhc3NldElkARprZXlMYW5kQXNzZXRJZFRvQ3VzdG9tTmFtZQEHYXNzZXRJZAkArAICAhhsYW5kQ3VzdG9tTmFtZUJ5QXNzZXRJZF8FB2Fzc2V0SWQBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBB2Fzc2V0SWQJAKwCAgILc3Rha2VkVGltZV8FB2Fzc2V0SWQBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBB2Fzc2V0SWQJAKwCAgILaW5mcmFMZXZlbF8FB2Fzc2V0SWQBIGtleUxhbmRBcnRTdGF0dXNCeVR5cGVBbmRBc3NldElkAgR0eXBlB2Fzc2V0SWQJALkJAgkAzAgCAg1sYW5kQXJ0U3RhdHVzCQDMCAIFBHR5cGUJAMwIAgUHYXNzZXRJZAUDbmlsAgFfASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwduZnRUeXBlB2Fzc2V0SWQJb3duZXJBZGRyCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIgc3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcl8FB25mdFR5cGUCAV8FB2Fzc2V0SWQCAV8FCW93bmVyQWRkcgESa2V5V2FyZWhvdXNlQnlMYW5kAQtsYW5kQXNzZXRJZAkArAICAgp3YXJlSG91c2VfBQtsYW5kQXNzZXRJZAEVa2V5U3Rha2VkTGFuZHNCeU93bmVyAQlvd25lckFkZHIJAKwCAgITc3Rha2VkTGFuZHNCeU93bmVyXwUJb3duZXJBZGRyARZrZXlTdGFrZWRQaWVjZXNCeU93bmVyAQlvd25lckFkZHIJAKwCAgIUc3Rha2VkUGllY2VzQnlPd25lcl8FCW93bmVyQWRkcgEaa2V5RHVja0Fzc2V0SWRUb0N1c3RvbU5hbWUBB2Fzc2V0SWQJAKwCAgIYZHVja0N1c3RvbU5hbWVCeUFzc2V0SWRfBQdhc3NldElkARZrZXlBZGRyZXNzVG9DdXN0b21OYW1lAQRhZGRyCQCsAgICGGFjY291bnRDdXN0b21OYW1lQnlBZGRyXwUEYWRkcgEPa2V5QWRkcmVzc1JlZkJ5AQRhZGRyCQCsAgICCWFjY1JlZkJ5XwUEYWRkcgETa2V5QWRkcmVzc1JlZmVycmFscwEEYWRkcgkArAICAg1hY2NSZWZlcnJhbHNfBQRhZGRyARBrZXlEdWNrSWRUb093bmVyAQdhc3NldElkCQCsAgICCmR1Y2tPd25lcl8FB2Fzc2V0SWQBFGtleVN0YWtlZER1Y2tCeU93bmVyAQlvd25lckFkZHIJAKwCAgISc3Rha2VkRHVja0J5T3duZXJfBQlvd25lckFkZHIBEWtleUJhY2twYWNrQnlEdWNrAQtkdWNrQXNzZXRJZAkArAICAgliYWNrUGFja18FC2R1Y2tBc3NldElkAQ9rZXlEdWNrTG9jYXRpb24BC2R1Y2tBc3NldElkCQCsAgICDWR1Y2tMb2NhdGlvbl8FC2R1Y2tBc3NldElkAQ1rZXlEdWNrSGVhbHRoAQtkdWNrQXNzZXRJZAkArAICAgtkdWNrSGVhbHRoXwULZHVja0Fzc2V0SWQBEWtleVJlc1Byb3BvcnRpb25zAAITcmVzVHlwZXNQcm9wb3J0aW9ucwEKa2V5QmxvY2tlZAACEGNvbnRyYWN0c0Jsb2NrZWQBFWtleVVzZXJHd2xSZWxlYXNlVGltZQEIdXNlckFkZHIJAKwCAgIaJXMlc19fdXNlckd3bFJlbGVhc2VUaW1lX18FCHVzZXJBZGRyAQ5rZXlPcmRlckJ5TGFuZAELbGFuZEFzc2V0SWQJAKwCAgIKbGFuZE9yZGVyXwULbGFuZEFzc2V0SWQBDmtleUVzV2FyZWhvdXNlAAIaZW1lcmdlbmN5V2FyZWhvdXNlUHJvZHVjdHMAD2xvY0lkeENvbnRpbmVudAAAAApsb2NJZHhUeXBlAAEACGxvY0lkeElkAAIBCGFzU3RyaW5nAQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAUBcwkAAgECGGZhaWwgdG8gY2FzdCBpbnRvIFN0cmluZwEFYXNJbnQBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIDSW50BAFuBQckbWF0Y2gwBQFuCQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50AQlhc0FueUxpc3QBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIJTGlzdFtBbnldBAFsBQckbWF0Y2gwBQFsCQACAQIbZmFpbCB0byBjYXN0IGludG8gTGlzdFtBbnldAQlhc0Jvb2xlYW4BAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIHQm9vbGVhbgQBcwUHJG1hdGNoMAUBcwkAAgECGWZhaWwgdG8gY2FzdCBpbnRvIEJvb2xlYW4BD251bVBpZWNlc0J5U2l6ZQEIbGFuZFNpemUEByRtYXRjaDAFCGxhbmRTaXplAwkAAAICAVMFByRtYXRjaDAFBVNTSVpFAwkAAAICAU0FByRtYXRjaDAFBU1TSVpFAwkAAAICAUwFByRtYXRjaDAFBUxTSVpFAwkAAAICAlhMBQckbWF0Y2gwBQZYTFNJWkUDCQAAAgIDWFhMBQckbWF0Y2gwBQdYWExTSVpFCQACAQIRVW5rbm93biBsYW5kIHNpemUAC0lkeEVmZlRvdGFsAAAACklkeEVmZlVzZXIAAQEOZ2V0Vm90aW5nUG93ZXIBEnVzZXJBZGRyU3RyT3JFbXB0eQQFcHJvcHMJALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ9zdGFraW5nQ29udHJhY3QJARFrZXlSZXNQcm9wb3J0aW9ucwACCzBfMF8wXzBfMF8wAgFfCgEFYWRkZXICA2FjYwRpdGVtCQBkAgUDYWNjCQENcGFyc2VJbnRWYWx1ZQEFBGl0ZW0ECnRvdGFsUG93ZXIKAAIkbAUFcHJvcHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBWFkZGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGBAp1c2Vyc1Bvd2VyAwkAAAIFEnVzZXJBZGRyU3RyT3JFbXB0eQIAAAAECGxhbmRzU3RyCQCdCAIFD3N0YWtpbmdDb250cmFjdAkBFWtleVN0YWtlZExhbmRzQnlPd25lcgEFEnVzZXJBZGRyU3RyT3JFbXB0eQQFbGFuZHMDCQEJaXNEZWZpbmVkAQUIbGFuZHNTdHIJAL0JAgkBBXZhbHVlAQUIbGFuZHNTdHICAV8FA25pbAoBB29uZUxhbmQCA2FjYwtsYW5kQXNzZXRJZAQFYXNzZXQJ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QUNUT1JZTUFYV0FSRUhPVVNFAIDIr6AlAApNSU5QQVlNRU5UAJBOAA5TRUxMTVVMVElQTElFUgDIAQANQlVZTVVMVElQTElFUgCsAgAKQVVDVElPTkZFRQCQTgAOTUlOU0hPUFBBWU1FTlQAoI0GAR5rZXlGYWN0b3J5V2FyZWhvdXNlQnlJZEFuZFR5cGUCCWZhY3RvcnlJZAdyZXNUeXBlCQCsAgIJAKwCAgkArAICAhtmYWN0b3J5V2hCeUNvbnRpbmVudEFuZFJlc18FCWZhY3RvcnlJZAIBXwkApAMBBQdyZXNUeXBlAAlvcmRJZHhSZXMAAAAJb3JkSWR4TWF0AAEACm9yZElkeFByb2QAAgEIZ2V0T3JkZXIBBm9yZEtleQQBcAkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEFBm9yZEtleQIwMEAwXzBAMF8wQDBfMEAwXzBAMF8wQDA6MEAwXzBAMF8wQDBfMEAwXzBAMF8wQDA6AgE6CQDMCAIDCQAAAgkAkAMBCQC1CQIJAJEDAgUBcAUJb3JkSWR4UmVzAgFfBQZOVU1SRVMJAJEDAgUBcAUJb3JkSWR4UmVzAhcwQDBfMEAwXzBAMF8wQDBfMEAwXzBAMAkAzAgCAwkAAAIJAJADAQkAtQkCCQCRAwIFAXAFCW9yZElkeE1hdAIBXwUGTlVNUkVTCQCRAwIFAXAFCW9yZElkeE1hdAIXMEAwXzBAMF8wQDBfMEAwXzBAMF8wQDAJAMwIAgkAkQMCBQFwBQpvcmRJZHhQcm9kBQNuaWwBCHRvVm9sdW1lAwZhbW91bnQHcGtnU2l6ZQlpc1Byb2R1Y3QDBQlpc1Byb2R1Y3QEBHBrZ3MDCQBnAgUGYW1vdW50AAAJAGkCCQBlAgkAZAIFBmFtb3VudAUHcGtnU2l6ZQABBQdwa2dTaXplCQEBLQEJAGkCCQBlAgkAZAIJAQEtAQUGYW1vdW50BQdwa2dTaXplAAEFB3BrZ1NpemUJAGgCBQRwa2dzBQVNVUxUOAUGYW1vdW50AQxzZWxsSW50ZXJuYWwEBWxvY0lkB3Jlc1R5cGUGYW1vdW50CG1pblByaWNlBAV3aEtleQkBHmtleUZhY3RvcnlXYXJlaG91c2VCeUlkQW5kVHlwZQIFBWxvY0lkBQdyZXNUeXBlBAJ3MAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQV3aEtleQAABAJyMAMJAGYCBQJ3MAUTRkFDVE9SWU1BWFdBUkVIT1VTRQAAAwkAZgIJAGQCBQJ3MAUGYW1vdW50BRNGQUNUT1JZTUFYV0FSRUhPVVNFCQBlAgUTRkFDVE9SWU1BWFdBUkVIT1VTRQUCdzAFBmFtb3VudAQMdXNkdFJlY2VpdmVkCQBkAgkAawMFAnIwCQBlAgkAaAIFDlNFTExNVUxUSVBMSUVSBRBSRVNPVVJDRVBSSUNFTUlOCQBrAwkAZAIJAGgCAGQFAncwCQBoAgAyBQJyMAUQUkVTT1VSQ0VQUklDRU1JTgUTRkFDVE9SWU1BWFdBUkVIT1VTRQUGTVVMVDEwCQBrAwkAZQIFBmFtb3VudAUCcjAFEFJFU09VUkNFUFJJQ0VNSU4FBU1VTFQ4BAVtaW45OQkAZQIFCG1pblByaWNlCQBpAgUIbWluUHJpY2UAZAMJAGYCCQBoAgUFbWluOTkFBmFtb3VudAkAaAIFDHVzZHRSZWNlaXZlZAUFTVVMVDgJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICD0FjdHVhbCBwcmljZSA9IAkApAMBBQx1c2R0UmVjZWl2ZWQCAyAvIAkApAMBBQZhbW91bnQCDiA8IG1pblByaWNlID0gCQCkAwEFCG1pblByaWNlAgMsICgFBWxvY0lkAgIsIAkAkQMCBQhyZXNUeXBlcwUHcmVzVHlwZQIBKQkAlAoCCQEMSW50ZWdlckVudHJ5AgUFd2hLZXkJAGQCBQJ3MAUGYW1vdW50BQx1c2R0UmVjZWl2ZWQBC2J1eUludGVybmFsBAVsb2NJZAdtYXRUeXBlBmFtb3VudAhtYXhQcmljZQQFd2hLZXkJAR5rZXlGYWN0b3J5V2FyZWhvdXNlQnlJZEFuZFR5cGUCBQVsb2NJZAUHbWF0VHlwZQQCdzAJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUFd2hLZXkAAAQCbTEDCQBmAgUCdzAFE0ZBQ1RPUllNQVhXQVJFSE9VU0UJAJcDAQkAzAgCBQZhbW91bnQJAMwIAgkAZQIFAncwBRNGQUNUT1JZTUFYV0FSRUhPVVNFBQNuaWwAAAQCbTAJAJcDAQkAzAgCBQJ3MAkAzAgCCQBlAgUGYW1vdW50BQJtMQUDbmlsBAFtCQBkAgUCbTAFAm0xBAl1c2R0U3BlbnQJAGQCCQBrAwUCbTAJAGUCCQBoAgUNQlVZTVVMVElQTElFUgUQUkVTT1VSQ0VQUklDRU1JTgkAawMJAGUCCQBoAgBkBQJ3MAkAaAIAMgUCbTAFEFJFU09VUkNFUFJJQ0VNSU4FE0ZBQ1RPUllNQVhXQVJFSE9VU0UFBk1VTFQxMAkAawMFAm0xCQBoAgACBRBSRVNPVVJDRVBSSUNFTUlOBQVNVUxUOAQGbWF4MTAxCQBkAgUIbWF4UHJpY2UJAGkCBQhtYXhQcmljZQBkAwkAZgIJAGgCBQl1c2R0U3BlbnQFBU1VTFQ4CQBoAgUGbWF4MTAxBQFtCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAg9BY3R1YWwgcHJpY2UgPSAJAKQDAQUJdXNkdFNwZW50AgMgLyAJAKQDAQUBbQIOID4gbWF4UHJpY2UgPSAJAKQDAQUIbWF4UHJpY2UCAywgKAUFbG9jSWQCAiwgCQCRAwIFCG1hdFR5cGVzBQdtYXRUeXBlAgEpCQCVCgMJAQxJbnRlZ2VyRW50cnkCBQV3aEtleQkAZQIFAncwBQFtBQl1c2R0U3BlbnQFAW0BC2dldEJhY2twYWNrAQVicEtleQQBcAkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIFD3N0YWtpbmdDb250cmFjdAUFYnBLZXkCGjA6MF8wXzBfMF8wXzA6MF8wXzBfMF8wXzA6AgE6CQDMCAIJAKQDAQkBC3ZhbHVlT3JFbHNlAgkAtgkBCQCRAwIFAXAFCmJwSWR4TGV2ZWwAAAkAzAgCAwkAAAIJAJADAQkAtQkCCQCRAwIFAXAFCGJwSWR4UmVzAgFfBQZOVU1SRVMJAJEDAgUBcAUIYnBJZHhSZXMCCzBfMF8wXzBfMF8wCQDMCAIDCQAAAgkAkAMBCQC1CQIJAJEDAgUBcAUIYnBJZHhNYXQCAV8FBk5VTVJFUwkAkQMCBQFwBQhicElkeE1hdAILMF8wXzBfMF8wXzAJAMwIAgkAkQMCBQFwBQlicElkeFByb2QFA25pbAEMY2hlY2tCbG9ja2VkAAMJAQt2YWx1ZU9yRWxzZQIJAJsIAgUPc3Rha2luZ0NvbnRyYWN0CQEKa2V5QmxvY2tlZAAHCQACAQIfQ29udHJhY3RzIGFyZSB1bmRlciBtYWludGVuYW5jZQUEdW5pdAEJc2V0Q29tbW9uAgNhY2MEaXRlbQQBaggFA2FjYwJfMQQGaXNQcm9kCAUDYWNjAl84BAdwa2dTaXplAwUGaXNQcm9kCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgkAtQkCCQCRAwIFEHByb2R1Y3Rpb25NYXRyaXgFAWoCAV8FEXJlY2lwZUlkeFBhY2tzaXplAAAECWl0ZW1QYXJ0cwkAtQkCBQRpdGVtAgFAAwkBAiE9AgkAkAMBBQlpdGVtUGFydHMAAgkAAgECLkluY29ycmVjdCBvcmRlciBmb3JtYXQsIHNob3VsZCBiZSBhbW91bnRAcHJpY2UECG5ld09yZEFtCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJaXRlbVBhcnRzAAAECG5ld09yZFByCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJaXRlbVBhcnRzAAEECW5ld09yZFVzZAkAawMFCG5ld09yZEFtBQhuZXdPcmRQcgUFTVVMVDgECW5ld09yZFZvbAkBCHRvVm9sdW1lAwUIbmV3T3JkQW0FB3BrZ1NpemUFBmlzUHJvZAQGd2hJbml0AwkAZgIJAJADAQgFA2FjYwJfNgUBagkBDXBhcnNlSW50VmFsdWUBCQCRAwIIBQNhY2MCXzYFAWoAAAQLY3VyT3JkUGFydHMJALUJAgMJAGYCCQCQAwEIBQNhY2MCXzcFAWoJAJEDAggFA2FjYwJfNwUBagIDMEAwAgFABAhjdXJPcmRBbQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFC2N1ck9yZFBhcnRzAAAECGN1ck9yZFByCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgULY3VyT3JkUGFydHMAAQMDCQBmAgAABQhjdXJPcmRQcgYJAGYCAAAFCG5ld09yZFByCQACAQIXUHJpY2UgY2FuJ3QgYmUgbmVnYXRpdmUECWN1ck9yZFVzZAkAawMFCGN1ck9yZEFtBQhjdXJPcmRQcgUFTVVMVDgECWN1ck9yZFZvbAkBCHRvVm9sdW1lAwUIY3VyT3JkQW0FB3BrZ1NpemUFBmlzUHJvZAMJAAACBQhuZXdPcmRBbQAAAwkAZgIFCGN1ck9yZEFtAAAJAJoKCAkAZAIFAWoAAQkAzQgCCAUDYWNjAl8yCQCkAwEFBndoSW5pdAgFA2FjYwJfMwgFA2FjYwJfNAkAZQIIBQNhY2MCXzUFCWN1ck9yZFVzZAgFA2FjYwJfNggFA2FjYwJfNwUGaXNQcm9kCQCaCggJAGQCBQFqAAEJAM0IAggFA2FjYwJfMgkApAMBCQBlAgUGd2hJbml0BQhjdXJPcmRBbQgFA2FjYwJfMwgFA2FjYwJfNAgFA2FjYwJfNQgFA2FjYwJfNggFA2FjYwJfNwUGaXNQcm9kAwkAZgIFCG5ld09yZEFtAAADCQBmAgAABQhjdXJPcmRBbQkAmgoICQBkAgUBagABCQDNCAIIBQNhY2MCXzIJAKQDAQkAZQIFBndoSW5pdAUIY3VyT3JkQW0JAGQCCAUDYWNjAl8zBQluZXdPcmRWb2wIBQNhY2MCXzQJAGQCCAUDYWNjAl81BQluZXdPcmRVc2QIBQNhY2MCXzYIBQNhY2MCXzcFBmlzUHJvZAkAmgoICQBkAgUBagABCQDNCAIIBQNhY2MCXzIJAKQDAQUGd2hJbml0CQBkAggFA2FjYwJfMwUJbmV3T3JkVm9sCAUDYWNjAl80CQBlAgkAZAIIBQNhY2MCXzUFCW5ld09yZFVzZAUJY3VyT3JkVXNkCAUDYWNjAl82CAUDYWNjAl83BQZpc1Byb2QDCQBmAgAABQhjdXJPcmRBbQQGYW1EaWZmCQBlAgUIY3VyT3JkQW0FCG5ld09yZEFtAwkAZgIAAAkAZQIFBndoSW5pdAUGYW1EaWZmCQACAQkArAICCQCsAgIJAKwCAgkArAICAhBBdHRlbXB0IHRvIHRha2UgCQCkAwEFBmFtRGlmZgIaIGZyb20gd2FyZWhvdXNlLCBidXQgb25seSAJAKQDAQUGd2hJbml0AgogYXZhaWxhYmxlCQCaCggJAGQCBQFqAAEJAM0IAggFA2FjYwJfMgkApAMBCQBlAgUGd2hJbml0BQZhbURpZmYIBQNhY2MCXzMJAGUCCAUDYWNjAl80BQluZXdPcmRWb2wIBQNhY2MCXzUIBQNhY2MCXzYIBQNhY2MCXzcFBmlzUHJvZAMJAGYCAAAJAGQCBQZ3aEluaXQFCG5ld09yZEFtCQACAQkArAICCQCsAgIJAKwCAgkArAICAhBBdHRlbXB0IHRvIHRha2UgCQCkAwEJAQEtAQUIbmV3T3JkQW0CGiBmcm9tIHdhcmVob3VzZSwgYnV0IG9ubHkgCQCkAwEFBndoSW5pdAIKIGF2YWlsYWJsZQkAmgoICQBkAgUBagABCQDNCAIIBQNhY2MCXzIJAKQDAQkAZAIFBndoSW5pdAUIbmV3T3JkQW0IBQNhY2MCXzMJAGUCCAUDYWNjAl80BQluZXdPcmRWb2wJAGUCCAUDYWNjAl81BQljdXJPcmRVc2QIBQNhY2MCXzYIBQNhY2MCXzcFBmlzUHJvZAELc2V0SW50ZXJuYWwDCWN1cnJlbnRXaApjdXJyZW50T3JkBm5ld09yZAQJY3VycldoUmVzCQC1CQIJAJEDAgUJY3VycmVudFdoBQh3aElkeFJlcwIBXwQJY3VycldoTWF0CQC1CQIJAJEDAgUJY3VycmVudFdoBQh3aElkeE1hdAIBXwQKY3VycldoUHJvZAMJAAACCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhQcm9kAgAFA25pbAkAtQkCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhQcm9kAgFfBA1jdXJyZW50T3JkUmVzCQC1CQIJAJEDAgUKY3VycmVudE9yZAUJb3JkSWR4UmVzAgFfBA1jdXJyZW50T3JkTWF0CQC1CQIJAJEDAgUKY3VycmVudE9yZAUJb3JkSWR4TWF0AgFfBA5jdXJyZW50T3JkUHJvZAMJAAACCQCRAwIFCmN1cnJlbnRPcmQFCm9yZElkeFByb2QCAAUDbmlsCQC1CQIJAJEDAgUKY3VycmVudE9yZAUKb3JkSWR4UHJvZAIBXwMJAQIhPQIJAJADAQUGbmV3T3JkAAMJAAIBAjNuZXdPcmRlclN0ciBzaG91bGQgY29udGFpbiBleGFjdGx5IDIgJzonIHNlcGFyYXRvcnMECHJlc1BhcnRzCQC1CQIJAJEDAgUGbmV3T3JkAAACAV8ECG1hdFBhcnRzCQC1CQIJAJEDAgUGbmV3T3JkAAECAV8ECXByb2RQYXJ0cwMJAAACCQCRAwIFBm5ld09yZAACAgAFA25pbAkAtQkCCQCRAwIFBm5ld09yZAACAgFfAwkBAiE9AgkAkAMBBQhyZXNQYXJ0cwUGTlVNUkVTCQACAQIgQWxsIDYgcmVzb3Vy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IT0CCQCQAwEFCmJwT3JkUGFydHMAAgkAAgECLkluY29ycmVjdCBvcmRlciBmb3JtYXQsIHNob3VsZCBiZSBhbW91bnRAcHJpY2UEB2JwT3JkQW0JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQpicE9yZFBhcnRzAAAEB2JwT3JkUHIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQpicE9yZFBhcnRzAAEDCQBmAgAABQdicE9yZFByCQACAQIXUHJpY2UgY2FuJ3QgYmUgbmVnYXRpdmUECGJwT3JkVXNkCQBrAwUHYnBPcmRBbQUHYnBPcmRQcgUFTVVMVDgEBmJwSW5pdAMJAGYCCQCQAwEIBQNhY2MCXzgFAWoJAQ1wYXJzZUludFZhbHVlAQkAkQMCCAUDYWNjAl84BQFqAAAEBndoSW5pdAMJAGYCCQCQAwEIBQNhY2MCXzkFAWoJAQ1wYXJzZUludFZhbHVlAQkAkQMCCAUDYWNjAl85BQFqAAAECXdoT3JkSW5pdAMJAGYCCQCQAwEIBQNhY2MDXzEwBQFqCQCRAwIIBQNhY2MDXzEwBQFqAgMwQDAECndoT3JkUGFydHMJALUJAgUJd2hPcmRJbml0AgFABAd3aE9yZEFtCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUKd2hPcmRQYXJ0cwAABAd3aE9yZFByCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUKd2hPcmRQYXJ0cwABAwMJAQIhPQIFB2JwT3JkQW0AAAkBAiE9AgUHYnBPcmRQcgUHd2hPcmRQcgcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIKUHJpY2VzIG9mIAkAkQMCCAUDYWNjA18xMQUBagIXIGRvbid0IG1hdGNoISBXSCBwcmljZT0JAKQDAQUHd2hPcmRQcgINLCB5b3VyIHByaWNlPQkApAMBBQdicE9yZFByBAh3aE9yZFVzZAkAawMFB3doT3JkQW0FB3doT3JkUHIFBU1VTFQ4BAhkZWx0YVZvbAkBCHRvVm9sdW1lAwUHYnBPcmRBbQUHcGtnU2l6ZQUGaXNQcm9kAwkAAAIFB2JwT3JkQW0AAAkAngoMCQDNCAIIBQNhY2MCXzEJAKQDAQUGd2hJbml0CQDNCAIIBQNhY2MCXzIFCXdoT3JkSW5pdAkAzQgCCAUDYWNjAl8zCQCkAwEFBmJwSW5pdAgFA2FjYwJfNAgFA2FjYwJfNQgFA2FjYwJfNgkAZAIIBQNhY2MCXzcAAQgFA2FjYwJfOAgFA2FjYwJfOQgFA2FjYwNfMTAIBQNhY2MDXzExBQZpc1Byb2QDCQBmAgUHYnBPcmRBbQAAAwkAZgIAAAUHd2hPcmRBbQMJAGYCBQdicE9yZEFtCQEBLQEFB3doT3JkQW0JAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIPQXR0ZW1wdCB0byBidXkgCQCkAwEFB2JwT3JkQW0CBCBvZiAJAJEDAggFA2FjYwNfMTEFAWoCGywgYnV0IHdhcmVob3VzZSBvbmx5IHNlbGxzIAkApAMBCQEBLQEFB3doT3JkQW0JAJ4KDAkAzQgCCAUDYWNjAl8xCQCkAwEFBndoSW5pdAkAzQgCCAUDYWNjAl8yCQCsAgIJAKwCAgkApAMBCQBkAgUHd2hPcmRBbQUHYnBPcmRBbQIBQAkApAMBBQd3aE9yZFByCQDNCAIIBQNhY2MCXzMJAKQDAQkAZAIFBmJwSW5pdAUHYnBPcmRBbQkAZAIIBQNhY2MCXzQFCGRlbHRhVm9sCAUDYWNjAl81CQBkAggFA2FjYwJfNgUIYnBPcmRVc2QJAGQCCAUDYWNjAl83AAEIBQNhY2MCXzgIBQNhY2MCXzkIBQNhY2MDXzEwCAUDYWNjA18xMQUGaXNQcm9kCQACAQkArAICCQCsAgICD0F0dGVtcHQgdG8gYnV5IAkAkQMCCAUDYWNjA18xMQUBagIgIHdoaWxlIHdhcmVob3VzZSBkb2Vzbid0IHNlbGwgaXQDCQBmAgUHd2hPcmRBbQAAAwkAZgIJAQEtAQUHYnBPcmRBbQUHd2hPcmRBbQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhBBdHRlbXB0IHRvIHNlbGwgCQCkAwEJAQEtAQUHYnBPcmRBbQIEIG9mIAkAkQMCCAUDYWNjA18xMQUBagIaLCBidXQgd2FyZWhvdXNlIG9ubHkgYnV5cyAJAKQDAQUHd2hPcmRBbQMJAGYCCQEBLQEFB2JwT3JkQW0FBmJwSW5pdAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhBBdHRlbXB0IHRvIHNlbGwgCQCkAwEJAQEtAQUHYnBPcmRBbQIULCBidXQgeW91IG9ubHkgaGF2ZSAJAKQDAQUGYnBJbml0AgQgb2YgCQCRAwIIBQNhY2MDXzExBQFqCQCeCgwJAM0IAggFA2FjYwJfMQkApAMBCQBlAgUGd2hJbml0BQdicE9yZEFtCQDNCAIIBQNhY2MCXzIJAKwCAgkArAICCQCkAwEJAGQCBQd3aE9yZEFtBQdicE9yZEFtAgFACQCkAwEFB3doT3JkUHIJAM0IAggFA2FjYwJfMwkApAMBCQBkAgUGYnBJbml0BQdicE9yZEFtCQBlAggFA2FjYwJfNAUIZGVsdGFWb2wJAGUCCAUDYWNjAl81BQhicE9yZFVzZAgFA2FjYwJfNgkAZAIIBQNhY2MCXzcAAQgFA2FjYwJfOAgFA2FjYwJfOQgFA2FjYwNfMTAIBQNhY2MDXzExBQZpc1Byb2QJAAIBCQCsAgIJAKwCAgIQQXR0ZW1wdCB0byBzZWxsIAkAkQMCCAUDYWNjA18xMQUBagIfIHdoaWxlIHdhcmVob3VzZSBkb2Vzbid0IGJ1eSBpdAoBaQEacmVjYWxjTG9ja2VkVm9sdW1lUkVBRE9OTFkCC2xhbmRBc3NldElkAndoBApjdXJyZW50T3JkCQEIZ2V0T3JkZXIBCQEOa2V5T3JkZXJCeUxhbmQBBQtsYW5kQXNzZXRJZAQBegkBC3NldEludGVybmFsAwUCd2gFCmN1cnJlbnRPcmQFCmN1cnJlbnRPcmQJAJQKAgUDbmlsCQBkAggFAXoCXzQIBQF6Al81AWkBDWNvbnN0cnVjdG9yVjEBCHJlc3RBZGRyAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIRUGVybWlzc2lvbiBkZW5pZWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDmtleVJlc3RBZGRyZXNzAAUIcmVzdEFkZHIFA25pbAFpAQ1zZWxsUmVzb3VyY2VzAgdhbW91bnRzCW1pblByaWNlcwQHYmxvY2tlZAkBDGNoZWNrQmxvY2tlZAADCQAAAgUHYmxvY2tlZAUHYmxvY2tlZAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ9zdGFraW5nQ29udHJhY3QJARRrZXlTdGFrZWREdWNrQnlPd25lcgEJAKUIAQgFAWkGY2FsbGVyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIqc2VsbFJlc291cmNlcyBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBAtjdXJMb2NhdGlvbgkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIFD3N0YWtpbmdDb250cmFjdAkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkBQ9ERUZBVUxUTE9DQVRJT04CAV8DCQECIT0CCQCRAwIFC2N1ckxvY2F0aW9uBQpsb2NJZHhUeXBlAgFGCQACAQkArAICAi1EdWNrIGxvY2F0aW9uIHR5cGUgc2hvdWxkIGJlIEZhY3RvcnksIGJ1dCBpcyAJAJEDAgULY3VyTG9jYXRpb24FCmxvY0lkeFR5cGUEBWxvY0lkCQCRAwIFC2N1ckxvY2F0aW9uBQhsb2NJZHhJZAQLY3VycmVudFBhY2sJAQtnZXRCYWNrcGFjawEJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAdyZXNMaXN0CQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4UmVzAgFfCgEFYWRkZXICA2FjYwFqAwkAZgIJAJEDAgUHYW1vdW50cwUBagkBDXBhcnNlSW50VmFsdWUBCQCRAwIFB3Jlc0xpc3QFAWoJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIJWW91IGhhdmUgCQCRAwIFB3Jlc0xpc3QFAWoCBCBvZiAJAJEDAgUIcmVzVHlwZXMFAWoCFCwgYnV0IHRyaWVkIHRvIHNlbGwgCQCkAwEJAJEDAgUHYW1vdW50cwUBagMJAGYCAAAJAJEDAgUHYW1vdW50cwUBagkAAgEJAKwCAgkArAICCQCsAgICJVlvdSB0cmllZCB0byBzZWxsIG5lZ2F0aXZlIGFtb3VudCBvZiAJAJEDAgUIcmVzVHlwZXMFAWoCAjogCQCkAwEJAJEDAgUHYW1vdW50cwUBagMJAGYCCQCRAwIFB2Ftb3VudHMFAWoAAAQBYgkBDHNlbGxJbnRlcm5hbAQFBWxvY0lkBQFqCQCRAwIFB2Ftb3VudHMFAWoJAJEDAgUJbWluUHJpY2VzBQFqCQCVCgMJAM0IAggFA2FjYwJfMQgFAWICXzEJAM0IAggFA2FjYwJfMgkApAMBCQBlAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFB3Jlc0xpc3QFAWoJAJEDAgUHYW1vdW50cwUBagkAZAIIBQNhY2MCXzMIBQFiAl8yCQCVCgMIBQNhY2MCXzEJAM0IAggFA2FjYwJfMgkAkQMCBQdyZXNMaXN0BQFqCAUDYWNjAl8zBAZtZXJnZWQKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlQoDBQNuaWwFA25pbAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQVhZGRlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgQHbmV3UGFjawkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAuQkCCAUGbWVyZ2VkAl8yAgFfCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6BAZyZXN1bHQJAQhhc1N0cmluZwEJAPwHBAUPc3Rha2luZ0NvbnRyYWN0Ag51cGRhdGVCYWNrcGFjawkAzAgCBQtkdWNrQXNzZXRJZAkAzAgCBQduZXdQYWNrBQNuaWwFA25pbAkAlAoCCQDNCAIIBQZtZXJnZWQCXzEJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcggFBm1lcmdlZAJfMwULdXNkdEFzc2V0SWQFBnJlc3VsdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQxidXlNYXRlcmlhbHMCB2Ftb3VudHMJbWF4UHJpY2VzBAdibG9ja2VkCQEMY2hlY2tCbG9ja2VkAAMJAAACBQdibG9ja2VkBQdibG9ja2VkBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFD3N0YWtpbmdDb250cmFjdAkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQkApQgBCAUBaQZjYWxsZXICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAiJleGFjdGx5IDEgcGF5bWVudCBtdXN0IGJlIGF0dGFjaGVkBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAQDYW10CAUDcG10BmFtb3VudAQKcG10QXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCAUDcG10B2Fzc2V0SWQCHldBVkVTIGNhbid0IGJlIHVzZWQgYXMgcGF5bWVudAMJAQIhPQIFCnBtdEFzc2V0SWQFC3VzZHRBc3NldElkCQACAQITVVNEVCBwYXltZW50cyBvbmx5IQQLY3VyTG9jYXRpb24JALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ9zdGFraW5nQ29udHJhY3QJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAUPREVGQVVMVExPQ0FUSU9OAgFfAwkBAiE9AgkAkQMCBQtjdXJMb2NhdGlvbgUKbG9jSWR4VHlwZQIBRgkAAgEJAKwCAgItRHVjayBsb2NhdGlvbiB0eXBlIHNob3VsZCBiZSBGYWN0b3J5LCBidXQgaXMgCQCRAwIFC2N1ckxvY2F0aW9uBQpsb2NJZHhUeXBlBAVsb2NJZAkAkQMCBQtjdXJMb2NhdGlvbgUIbG9jSWR4SWQEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBCQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAQHbWF0TGlzdAkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAIBXwoBCG1VcGRhdGVyAgNhY2MBagMJAGYCAAAJAJEDAgUHYW1vdW50cwUBagkAAgEJAKwCAgkArAICCQCsAgICJFlvdSB0cmllZCB0byBidXkgbmVnYXRpdmUgYW1vdW50IG9mIAkAkQMCBQhtYXRUeXBlcwUBagICOiAJAKQDAQkAkQMCBQdhbW91bnRzBQFqAwkAZgIJAJEDAgUHYW1vdW50cwUBagAABAFiCQELYnV5SW50ZXJuYWwEBQVsb2NJZAUBagkAkQMCBQdhbW91bnRzBQFqCQCRAwIFCW1heFByaWNlcwUBagkAlQoDCQDNCAIIBQNhY2MCXzEIBQFiAl8xCQDNCAIIBQNhY2MCXzIJAKQDAQkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQdtYXRMaXN0BQFqCAUBYgJfMwkAZAIIBQNhY2MCXzMIBQFiAl8yCQCVCgMIBQNhY2MCXzEJAM0IAggFA2FjYwJfMgkAkQMCBQdtYXRMaXN0BQFqCAUDYWNjAl8zBAZtZXJnZWQKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlQoDBQNuaWwFA25pbAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQhtVXBkYXRlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgMJAGYCCAUGbWVyZ2VkAl8zBQNhbXQJAAIBCQCsAgIJAKwCAgkArAICAh9JbnN1ZmZpY2llbnQgcGF5bWVudCEgQXR0YWNoZWQ9CQCkAwEFA2FtdAILLCByZXF1aXJlZD0JAKQDAQgFBm1lcmdlZAJfMwQHbmV3UGFjawkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAMwIAgkAuQkCCAUGbWVyZ2VkAl8yAgFfCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6BAZyZXN1bHQJAQhhc1N0cmluZwEJAPwHBAUPc3Rha2luZ0NvbnRyYWN0Ag51cGRhdGVCYWNrcGFjawkAzAgCBQtkdWNrQXNzZXRJZAkAzAgCBQduZXdQYWNrBQNuaWwFA25pbAQEcmVzdAMJAGYCCQBlAgUDYW10CAUGbWVyZ2VkAl8zAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyCQBlAgUDYW10CAUGbWVyZ2VkAl8zBQt1c2R0QXNzZXRJZAUDbmlsBQNuaWwEEGFjdGl2aXRpZXNBbW91bnQJAGkCCAUGbWVyZ2VkAl8zAGQJAJQKAgkAzQgCCQDOCAIIBQZtZXJnZWQCXzEFBHJlc3QJAQ5TY3JpcHRUcmFuc2ZlcgMFDHJlc3RDb250cmFjdAUQYWN0aXZpdGllc0Ftb3VudAULdXNkdEFzc2V0SWQFBnJlc3VsdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARFleGNoYW5nZVJlc291cmNlcwEHYW1vdW50cwQHYmxvY2tlZAkBDGNoZWNrQmxvY2tlZAADCQAAAgUHYmxvY2tlZAUHYmxvY2tlZAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ9zdGFraW5nQ29udHJhY3QJARRrZXlTdGFrZWREdWNrQnlPd25lcgEJAKUIAQgFAWkGY2FsbGVyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIiZXhhY3RseSAxIHBheW1lbnQgbXVzdCBiZSBhdHRhY2hlZAQDcG10CQCRAwIIBQFpCHBheW1lbnRzAAAEA2FtdAgFA3BtdAZhbW91bnQECnBtdEFzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAggFA3BtdAdhc3NldElkAh5XQVZFUyBjYW4ndCBiZSB1c2VkIGFzIHBheW1lbnQDCQECIT0CBQpwbXRBc3NldElkBQt1c2R0QXNzZXRJZAkAAgECE1VTRFQgcGF5bWVudHMgb25seSEEC2N1ckxvY2F0aW9uCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUPc3Rha2luZ0NvbnRyYWN0CQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQFD0RFRkFVTFRMT0NBVElPTgIBXwMJAQIhPQIJAJEDAgULY3VyTG9jYXRpb24FCmxvY0lkeFR5cGUCAUYJAAIBCQCsAgICLUR1Y2sgbG9jYXRpb24gdHlwZSBzaG91bGQgYmUgRmFjdG9yeSwgYnV0IGlzIAkAkQMCBQtjdXJMb2NhdGlvbgUKbG9jSWR4VHlwZQQFbG9jSWQJAJEDAgULY3VyTG9jYXRpb24FCGxvY0lkeElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQEB3Jlc0xpc3QJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMCAV8EB21hdExpc3QJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQCAV8KAQlleGNoYW5nZXICA2FjYwFqBAV3aEtleQkBHmtleUZhY3RvcnlXYXJlaG91c2VCeUlkQW5kVHlwZQIFBWxvY0lkBQFqBAJ3MAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQV3aEtleQAABANhbWoJAJEDAgUHYW1vdW50cwUBagMJAGYCBQNhbWoJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQdyZXNMaXN0BQFqCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICCVlvdSBoYXZlIAkAkQMCBQdyZXNMaXN0BQFqAgQgb2YgCQCRAwIFCHJlc1R5cGVzBQFqAhgsIGJ1dCB0cmllZCB0byBleGNoYW5nZSAJAKQDAQUDYW1qAwkAZgIAAAUDYW1qCQACAQkArAICCQCsAgIJAKwCAgIpWW91IHRyaWVkIHRvIGV4Y2hhbmdlIG5lZ2F0aXZlIGFtb3VudCBvZiAJAJEDAgUIcmVzVHlwZXMFAWoCAjogCQCkAwEFA2FtagMJAGYCBQNhbWoAAAkAlgoECQDNCAIIBQNhY2MCXzEJAKQDAQkAZQIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQdyZXNMaXN0BQFqBQNhbWoJAM0IAggFA2FjYwJfMgkApAMBCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFB21hdExpc3QFAWoFA2FtagkAZAIIBQNhY2MCXzMJAGsDBQNhbWoFEFJFU09VUkNFUFJJQ0VNSU4FBU1VTFQ4CQDNCAIIBQNhY2MCXzQJAQxJbnRlZ2VyRW50cnkCBQV3aEtleQUCdzAJAJYKBAkAzQgCCAUDYWNjAl8xCQCRAwIFB3Jlc0xpc3QFAWoJAM0IAggFA2FjYwJfMgkAkQMCBQdtYXRMaXN0BQFqCAUDYWNjAl8zCAUDYWNjAl80BAZtZXJnZWQKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlgoEBQNuaWwFA25pbAAABQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCWV4Y2hhbmdlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgMJAGYCCAUGbWVyZ2VkAl8zBQNhbXQJAAIBCQCsAgIJAKwCAgkArAICAh9JbnN1ZmZpY2llbnQgcGF5bWVudCEgQXR0YWNoZWQ9CQCkAwEFA2FtdAILLCByZXF1aXJlZD0JAKQDAQgFBm1lcmdlZAJfMwQHbmV3UGFjawkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAuQkCCAUGbWVyZ2VkAl8xAgFfCQDMCAIJALkJAggFBm1lcmdlZAJfMgIBXwkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QFA25pbAIBOgQGcmVzdWx0CQEIYXNTdHJpbmcBCQD8BwQFD3N0YWtpbmdDb250cmFjdAIOdXBkYXRlQmFja3BhY2sJAMwIAgULZHVja0Fzc2V0SWQJAMwIAgUHbmV3UGFjawUDbmlsBQNuaWwEBHJlc3QDCQBmAgkAZQIFA2FtdAgFBm1lcmdlZAJfMwAACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgkAZQIFA2FtdAgFBm1lcmdlZAJfMwULdXNkdEFzc2V0SWQFA25pbAUDbmlsBBBhY3Rpdml0aWVzQW1vdW50CQBpAggFBm1lcmdlZAJfMwBkCQCUCgIJAM0IAgkAzggCBQRyZXN0CAUGbWVyZ2VkAl80CQEOU2NyaXB0VHJhbnNmZXIDBQxyZXN0Q29udHJhY3QFEGFjdGl2aXRpZXNBbW91bnQFC3VzZHRBc3NldElkBQZyZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEKY3JhZnRHb29kcwIKcHJvZHVjdElkeAhxdWFudGl0eQQHYmxvY2tlZAkBDGNoZWNrQmxvY2tlZAADCQAAAgUHYmxvY2tlZAUHYmxvY2tlZAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECImV4YWN0bHkgMSBwYXltZW50IG11c3QgYmUgYXR0YWNoZWQEA3BtdAkAkQMCCAUBaQhwYXltZW50cwAABANhbXQIBQNwbXQGYW1vdW50BApwbXRBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIIBQNwbXQHYXNzZXRJZAIeV0FWRVMgY2FuJ3QgYmUgdXNlZCBhcyBwYXltZW50AwkBAiE9AgUKcG10QXNzZXRJZAULdXNkdEFzc2V0SWQJAAIBAhNVU0RUIHBheW1lbnRzIG9ubHkhAwkBAiE9AgUDYW10BQVNVUxUNgkAAgECKmV4YWN0bHkgMSBVU0RUIG11c3QgYmUgYXR0YWNoZWQgYXMgcGF5bWVudAMJAGcCAAAFCHF1YW50aXR5CQACAQIbUXVhbnRpdHkgc2hvdWxkIGJlIHBvc2l0aXZlBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFD3N0YWtpbmdDb250cmFjdAkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQkApQgBCAUBaQZjYWxsZXICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQEC2N1ckxvY2F0aW9uCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUPc3Rha2luZ0NvbnRyYWN0CQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQFD0RFRkFVTFRMT0NBVElPTgIBXwMJAQIhPQIJAJEDAgULY3VyTG9jYXRpb24FCmxvY0lkeFR5cGUCAU0JAAIBCQCsAgICMUR1Y2sgbG9jYXRpb24gdHlwZSBzaG91bGQgYmUgTWFudWZhY3RvcnksIGJ1dCBpcyAJAJEDAgULY3VyTG9jYXRpb24FCmxvY0lkeFR5cGUEBGNvbnQJAJEDAgULY3VyTG9jYXRpb24FD2xvY0lkeENvbnRpbmVudAQLY3VycmVudFBhY2sJAQtnZXRCYWNrcGFjawEJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAdtYXRMaXN0CQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0AgFfAwMJAGYCAAAFCnByb2R1Y3RJZHgGCQBnAgUKcHJvZHVjdElkeAkAkAMBBRBwcm9kdWN0aW9uTWF0cml4CQACAQkArAICAhRVbmtub3duIHByb2R1Y3QgaWR4PQkApAMBBQpwcm9kdWN0SWR4BAZyZWNpcGUJALUJAgkAkQMCBRBwcm9kdWN0aW9uTWF0cml4BQpwcm9kdWN0SWR4AgFfAwkBAiE9AgkAkAMBBQZyZWNpcGUJAGQCBQZOVU1SRVMAAwkAAgEJAKwCAgIXRmF0YWw6IHVua25vd24gcmVjaXBlOiAJAJEDAgUQcHJvZHVjdGlvbk1hdHJpeAUKcHJvZHVjdElkeAQOcHJvZHVjdENvbnRJZHgJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZyZWNpcGUFEnJlY2lwZUlkeENvbnRpbmVudAMJAQIhPQIJAJEDAgUKY29udGluZW50cwUOcHJvZHVjdENvbnRJZHgFBGNvbnQJAAIBCQCsAgIJAKwCAgkArAICAh1UaGlzIHByb2R1Y3QgaXMgYXZhaWxhYmxlIGluIAkAkQMCBQpjb250aW5lbnRzBQ5wcm9kdWN0Q29udElkeAIRLCBidXQgeW91IGFyZSBpbiAFBGNvbnQECHByb2RMaXN0AwkAAAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAIABQNuaWwJALUJAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kAgFfCgEGZmlsbGVyAgNhY2MLaWdub3JlZEl0ZW0EAW4IBQNhY2MCXzIEAnhzAwkAZgIJAJADAQUIcHJvZExpc3QFAW4JAJEDAgUIcHJvZExpc3QFAW4CATAEAXgJAQ1wYXJzZUludFZhbHVlAQUC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bmV3UGFjawUDbmlsBQNuaWwJAJQKAgUDbmlsBQZyZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQERc2V0V2FyZWhvdXNlT3JkZXICC25ld09yZGVyU3RyC2xhbmRBc3NldElkBAR1c2VyCAUBaQxvcmlnaW5DYWxsZXIEBGFkZHIJAKUIAQUEdXNlcgQGcmVzdWx0AwkBAiE9AgUEdXNlcgUMcmVzdENvbnRyYWN0CQEMY2hlY2tCbG9ja2VkAAcEBWFzc2V0CQEFdmFsdWUBCQDsBwEJANkEAQULbGFuZEFzc2V0SWQDCQEBIQEJAQlpc0RlZmluZWQBCQCaCAIFD3N0YWtpbmdDb250cmFjdAkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAkAAgEJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUPc3Rha2luZ0NvbnRyYWN0CQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwMJAQIhPQIFBHVzZXIFDHJlc3RDb250cmFjdAkBAiE9AgUFb3duZXIFBGFkZHIHCQACAQkArAICBQpMQU5EUFJFRklYAg0gaXMgbm90IHlvdXJzBAhuZXdPcmRlcgkAvAkCBQtuZXdPcmRlclN0cgIBOgQCd2gJAQhhc1N0cmluZwEJAPwHBAUPc3Rha2luZ0NvbnRyYWN0AhRnZXRXYXJlaG91c2VSRUFET05MWQkAzAgCBQtsYW5kQXNzZXRJZAUDbmlsBQNuaWwECWN1cnJlbnRXaAkAvAkCBQJ3aAIBOgQEbG9mdAkAtQkCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhMT0ZUAgFfBAp3aE9jY3VwaWVkCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAULdm9sT2NjdXBpZWQEB3doVG90YWwJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQh2b2xUb3RhbAQGb3JkS2V5CQEOa2V5T3JkZXJCeUxhbmQBBQtsYW5kQXNzZXRJZAQKY3VycmVudE9yZAkBCGdldE9yZGVyAQUGb3JkS2V5BAF6CQELc2V0SW50ZXJuYWwDBQljdXJyZW50V2gFCmN1cnJlbnRPcmQFCG5ld09yZGVyBAtidXlWb2xTYWxkbwgFAXoCXzQEDHNlbGxWb2xTYWxkbwgFAXoCXzUECHdoTG9ja2VkCQBkAgULYnV5Vm9sU2FsZG8FDHNlbGxWb2xTYWxkbwQGd2hGcmVlCQBlAgkAZQIFB3doVG90YWwFCndoT2NjdXBpZWQFCHdoTG9ja2VkAwkAZgIAAAUGd2hGcmVlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgITQXR0ZW1wdCB0byByZXNlcnZlIAkApAMBBQtidXlWb2xTYWxkbwIbIHNwYWNlIGZvciBidXkgb3JkZXJzLCBhbmQgCQCkAwEFDHNlbGxWb2xTYWxkbwIlIHNwYWNlIGZvciBzZWxsIG9yZGVycyAoYW5kIG9jY3VwaWVkPQkApAMBBQp3aE9jY3VwaWVkAh8pLCBsZWFkcyB0byBuZWdhdGl2ZSBmcmVlIHNwYWNlBAV3aFN0cgkAugkCCQDMCAIJAJEDAgUJY3VycmVudFdoBQt3aElkeExldmVscwkAzAgCCQC5CQIIBQF6Al8xAgFfCQDMCAIJALkJAggFAXoCXzICAV8JAMwIAgkAuQkCCAUBegJfMwIBXwkAzAgCCQCkAwEFCHdoTG9ja2VkBQNuaWwCAToEBndoU2F2ZQkBCGFzU3RyaW5nAQkA/AcEBQ9zdGFraW5nQ29udHJhY3QCDXNhdmVXYXJlaG91c2UJAMwIAgUFd2hTdHIJAMwIAgULbGFuZEFzc2V0SWQFA25pbAUDbmlsBAh1c2RTYWxkbwgFAXoCXzYEB2FjdGlvbnMDCQBmAgUIdXNkU2FsZG8AAAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECImV4YWN0bHkgMSBwYXltZW50IG11c3QgYmUgYXR0YWNoZWQEA3BtdAkAkQMCCAUBaQhwYXltZW50cwAABANhbXQIBQNwbXQGYW1vdW50BApwbXRBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIIBQNwbXQHYXNzZXRJZAIeV0FWRVMgY2FuJ3QgYmUgdXNlZCBhcyBwYXltZW50AwkBAiE9AgUKcG10QXNzZXRJZAULdXNkdEFzc2V0SWQJAAIBAhNVU0RUIHBheW1lbnRzIG9ubHkhAwkBAiE9AgUDYW10BQh1c2RTYWxkbwkAAgEJAKwCAgISUGF5bWVudCBuZWVkZWQgaXMgCQCkAwEFCHVzZFNhbGRvCQDMCAIJAQtTdHJpbmdFbnRyeQIFBm9yZEtleQULbmV3T3JkZXJTdHIFA25pbAMJAAACBQh1c2RTYWxkbwAAAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQISTm8gcGF5bWVudHMgbmVlZGVkCQDMCAIJAQtTdHJpbmdFbnRyeQIFBm9yZEtleQULbmV3T3JkZXJTdHIFA25pbAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECEk5vIHBheW1lbnRzIG5lZWRlZAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBBQVvd25lcgkBAS0BBQh1c2RTYWxkbwULdXNkdEFzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUGb3JkS2V5BQtuZXdPcmRlclN0cgUDbmlsCQCUCgIFB2FjdGlvbnMJAJQKAgUGcmVzdWx0BQZ3aFNhdmUBaQEUYWNjZXB0V2FyZWhvdXNlT3JkZXIDCmJwT3JkZXJTdHILbGFuZEFzc2V0SWQLZHVja0Fzc2V0SWQEB2Jsb2NrZWQJAQxjaGVja0Jsb2NrZWQABAZjYWxsZXIIBQFpDG9yaWdpbkNhbGxlcgQKY2FsbGVyQWRkcgkApQgBBQZjYWxsZXIEEXN0YWtlZER1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUPc3Rha2luZ0NvbnRyYWN0CQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQpjYWxsZXJBZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAtjdXJMb2NhdGlvbgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ9zdGFraW5nQ29udHJhY3QJAQ9rZXlEdWNrTG9jYXRpb24BBRFzdGFrZWREdWNrQXNzZXRJZAUPREVGQVVMVExPQ0FUSU9OBANsb2MJALUJAgkBBXZhbHVlAQULY3VyTG9jYXRpb24CAV8DCQECIT0CCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIBTAkAAgEJAKwCAgkArAICAhZEdWNrIGxvY2F0aW9uIHR5cGUgaXMgCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIRLCBidXQgc2hvdWxkIGJlIEwDCQECIT0CBRFzdGFrZWREdWNrQXNzZXRJZAULZHVja0Fzc2V0SWQJAAIBCQCsAgIJAKwCAgkArAICAhRZb3VyIHN0YWtlZCBkdWNrIGlzIAURc3Rha2VkRHVja0Fzc2V0SWQCDSwgYnV0IHBhc3NlZCAFC2R1Y2tBc3NldElkBAlsYW5kQXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAMJAQEhAQkBCWlzRGVmaW5lZAEJAJoIAgUPc3Rha2luZ0NvbnRyYWN0CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkCQACAQkArAICCQCsAgICBE5GVCAIBQlsYW5kQXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQECWxhbmRPd25lcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFD3N0YWtpbmdDb250cmFjdAkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkCQCsAgIJAKwCAgIETkZUIAgFCWxhbmRBc3NldARuYW1lAgwgaXMgb3JwaGFuZWQDCQAAAgUJbGFuZE93bmVyBQpjYWxsZXJBZGRyCQACAQIeWW91IGNhbm5vdCB0cmFkZSB3aXRoIHlvdXJzZWxmBAxicE9yZGVyUGFydHMJALwJAgUKYnBPcmRlclN0cgIBOgMJAQIhPQIJAJADAQUMYnBPcmRlclBhcnRzAAMJAAIBAjJicE9yZGVyU3RyIHNob3VsZCBjb250YWluIGV4YWN0bHkgMiAnOicgc2VwYXJhdG9ycwQIYnBPcmRSZXMJALUJAgkAkQMCBQxicE9yZGVyUGFydHMAAAIBXwQIYnBPcmRNYXQJALUJAgkAkQMCBQxicE9yZGVyUGFydHMAAQIBXwQJYnBPcmRQcm9kAwkAAAIJAJEDAgUMYnBPcmRlclBhcnRzAAICAAUDbmlsCQC1CQIJAJEDAgUMYnBPcmRlclBhcnRzAAICAV8DCQECIT0CCQCQAwEFCGJwT3JkUmVzBQZOVU1SRVMJAAIBAiBBbGwgNiByZXNvdXJjZXMgc2hvdWxkIGJlIHBhc3NlZAMJAQIhPQIJAJADAQUIYnBPcmRNYXQFBk5VTVJFUwkAAgECIEFsbCA2IG1hdGVyaWFscyBzaG91bGQgYmUgcGFzc2VkBAJ3aAkBCGFzU3RyaW5nAQkA/AcEBQ9zdGFraW5nQ29udHJhY3QCFGdldFdhcmVob3VzZVJFQURPTkxZCQDMCAIFC2xhbmRBc3NldElkBQNuaWwFA25pbAQJY3VycmVudFdoCQC8CQIFAndoAgE6BAljdXJyV2hSZXMJALUJAgkAkQMCBQljdXJyZW50V2gFCHdoSWR4UmVzAgFfBAljdXJyV2hNYXQJALUJAgkAkQMCBQljdXJyZW50V2gFCHdoSWR4TWF0AgFfBApjdXJyV2hQcm9kAwkAAAIJAJEDAgUJY3VycmVudFdoBQl3aElkeFByb2QCAAUDbmlsCQC1CQIJAJEDAgUJY3VycmVudFdoBQl3aElkeFByb2QCAV8ED2N1cnJXaExvY2tlZFZvbAkBDXBhcnNlSW50VmFsdWUBCQCRAwIJALUJAgkAkQMCBQljdXJyZW50V2gFCXdoSWR4TE9GVAIBXwUJdm9sTG9ja2VkBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQJYnBSZXNMaXN0CQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4UmVzAgFfBAlicE1hdExpc3QJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQCAV8ECmJwUHJvZExpc3QDCQAAAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kAgAFA25pbAkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QCAV8EBm9yZEtleQkBDmtleU9yZGVyQnlMYW5kAQULbGFuZEFzc2V0SWQEBXdoT3JkCQEIZ2V0T3JkZXIBBQZvcmRLZXkECHdoT3JkUmVzCQC1CQIJAJEDAgUFd2hPcmQFCW9yZElkeFJlcwIBXwQId2hPcmRNYXQJALUJ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ZFZvbAUIdm9sU2FsZG8EBXdoU3RyCQC6CQIJAMwIAgkAkQMCBQljdXJyZW50V2gFC3doSWR4TGV2ZWxzCQDMCAIJALkJAggFAXICXzECAV8JAMwIAgkAuQkCCAUBbQJfMQIBXwkAzAgCCQC5CQIIBQFwAl8xAgFfCQDMCAIJAKQDAQUMbmV3TG9ja2VkVm9sBQNuaWwCAToEC25ld1doT3JkU3RyCQC6CQIJAMwIAgkAuQkCCAUBcgJfMgIBXwkAzAgCCQC5CQIIBQFtAl8yAgFfCQDMCAIJALkJAggFAXACXzICAV8FA25pbAIBOgQIbmV3QnBTdHIJALoJAgkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIJALkJAggFAXICXzMCAV8JAMwIAgkAuQkCCAUBbQJfMwIBXwkAzAgCCQC5CQIIBQFwAl8zAgFfBQNuaWwCAToEBndoU2F2ZQkBCGFzU3RyaW5nAQkA/AcEBQ9zdGFraW5nQ29udHJhY3QCDXNhdmVXYXJlaG91c2UJAMwIAgUFd2hTdHIJAMwIAgULbGFuZEFzc2V0SWQFA25pbAUDbmlsBAZicFNhdmUJAQhhc1N0cmluZwEJAPwHBAUPc3Rha2luZ0NvbnRyYWN0Ag51cGRhdGVCYWNrcGFjawkAzAgCBQtkdWNrQXNzZXRJZAkAzAgCBQhuZXdCcFN0cgUDbmlsBQNuaWwEB2FjdGlvbnMJAMwIAgkBC1N0cmluZ0VudHJ5AgUGb3JkS2V5BQtuZXdXaE9yZFN0cgUDbmlsBA11c2RXaDJCcFNhbGRvCAUBcAJfNQQIYWN0aW9uczEDCQBmAgUNdXNkV2gyQnBTYWxkbwAABAt1c2RXaDJCcEZlZQkAawMIBQFwAl81BQpBVUNUSU9ORkVFBQVNVUxUNgQIcmVmQnlLZXkJAQ9rZXlBZGRyZXNzUmVmQnkBBQpjYWxsZXJBZGRyBAVyZWZCeQkAnQgCBQ9zdGFraW5nQ29udHJhY3QFCHJlZkJ5S2V5AwkBCWlzRGVmaW5lZAEFBXJlZkJ5CQDNCAIJAM0IAgkAzQgCBQdhY3Rpb25zCQEOU2NyaXB0VHJhbnNmZXIDBQZjYWxsZXIJAGUCCAUBcAJfNQkAaAIAAwULdXNkV2gyQnBGZWUFC3VzZHRBc3NldElkCQEOU2NyaXB0VHJhbnNmZXIDBQxyZXN0Q29udHJhY3QFC3VzZFdoMkJwRmVlBQt1c2R0QXNzZXRJZAkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQkBBXZhbHVlAQUFcmVmQnkFC3VzZFdoMkJwRmVlBQt1c2R0QXNzZXRJZAkAzQgCCQDNCAIFB2FjdGlvbnMJAQ5TY3JpcHRUcmFuc2ZlcgMFBmNhbGxlcgkAZQIIBQFwAl81CQBoAgADBQt1c2RXaDJCcEZlZQULdXNkdEFzc2V0SWQJAQ5TY3JpcHRUcmFuc2ZlcgMFDHJlc3RDb250cmFjdAULdXNkV2gyQnBGZWUFC3VzZHRBc3NldElkBQdhY3Rpb25zBA11c2RCcDJXaFNhbGRvCAUBcAJfNgQIYWN0aW9uczIDCQBmAgUNdXNkQnAyV2hTYWxkbwAAAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIiZXhhY3RseSAxIHBheW1lbnQgbXVzdCBiZSBhdHRhY2hlZAQDcG10CQCRAwIIBQFpCHBheW1lbnRzAAAEA2FtdAgFA3BtdAZhbW91bnQECnBtdEFzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAggFA3BtdAdhc3NldElkAh5XQVZFUyBjYW4ndCBiZSB1c2VkIGFzIHBheW1lbnQDCQECIT0CBQpwbXRBc3NldElkBQt1c2R0QXNzZXRJZAkAAgECE1VTRFQgcGF5bWVudHMgb25seSEDCQECIT0CBQNhbXQFDXVzZEJwMldoU2FsZG8JAAIBCQCsAgICElBheW1lbnQgbmVlZGVkIGlzIAkApAMBBQ11c2RCcDJXaFNhbGRvAwkAZgIFDk1JTlNIT1BQQVlNRU5UBQNhbXQJAAIBCQCsAgICG1BheW1lbnQgc2hvdWxkIGJlIGF0IGxlYXN0IAkApAMBBQ5NSU5TSE9QUEFZTUVOVAQLdXNkQnAyV2hGZWUJAGsDCAUBcAJfNgUKQVVDVElPTkZFRQUFTVVMVDYECHJlZkJ5S2V5CQEPa2V5QWRkcmVzc1JlZkJ5AQUJbGFuZE93bmVyBAVyZWZCeQkAnQgCBQ9zdGFraW5nQ29udHJhY3QFCHJlZkJ5S2V5AwkBCWlzRGVmaW5lZAEFBXJlZkJ5CQDNCAIJAM0IAgkAzQgCBQhhY3Rpb25zMQkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUJbGFuZE93bmVyCQBlAggFAXACXzYJAGgCAAMFC3VzZEJwMldoRmVlBQt1c2R0QXNzZXRJZAkBDlNjcmlwdFRyYW5zZmVyAwUMcmVzdENvbnRyYWN0BQt1c2RCcDJXaEZlZQULdXNkdEFzc2V0SWQJAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQV2YWx1ZQEFBXJlZkJ5BQt1c2RCcDJXaEZlZQULdXNkdEFzc2V0SWQJAM0IAgkAzQgCBQhhY3Rpb25zMQkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUJbGFuZE93bmVyCQBlAggFAXACXzYJAGgCAAMFC3VzZEJwMldoRmVlBQt1c2R0QXNzZXRJZAkBDlNjcmlwdFRyYW5zZmVyAwUMcmVzdENvbnRyYWN0BQt1c2RCcDJXaEZlZQULdXNkdEFzc2V0SWQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhJObyBwYXltZW50cyBuZWVkZWQFCGFjdGlvbnMxCQCUCgIFCGFjdGlvbnMyCQCVCgMFB2Jsb2NrZWQFBndoU2F2ZQUGYnBTYXZlAWkBEHNlbGxQcm9kdWN0c1RvRVMBB2Ftb3VudHMEB2Jsb2NrZWQJAQxjaGVja0Jsb2NrZWQAAwkAAAIFB2Jsb2NrZWQFB2Jsb2NrZWQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhJObyBwYXltZW50cyBuZWVkZWQEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUPc3Rha2luZ0NvbnRyYWN0CQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQLY3VyTG9jYXRpb24JALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ9zdGFraW5nQ29udHJhY3QJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAUPREVGQVVMVExPQ0FUSU9OAgFfAwkBAiE9AgkAkQMCBQtjdXJMb2NhdGlvbgUKbG9jSWR4VHlwZQIBQQkAAgEJAKwCAgItRHVjayBsb2NhdGlvbiB0eXBlIHNob3VsZCBiZSBBaXJwb3J0LCBidXQgaXMgCQCRAwIFC2N1ckxvY2F0aW9uBQpsb2NJZHhUeXBlBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQECHByb2RMaXN0AwkAAAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAIABQNuaWwJALUJAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kAgFfBAVlc0tleQkBDmtleUVzV2FyZWhvdXNlAAQIZXhpc3RTdHIJAKIIAQUFZXNLZXkEDGV4aXN0QW1vdW50cwMJAQlpc0RlZmluZWQBBQhleGlzdFN0cgkAtQkCCQEFdmFsdWUBBQhleGlzdFN0cgIBXwUDbmlsCgEIbW92ZVByb2QCA2FjYwlyZWNpcGVTdHIEAWoIBQNhY2MCXzEECHF1YW50aXR5AwkAZgIJAJADAQUHYW1vdW50cwUBagkAkQMCBQdhbW91bnRzBQFqAAADCQBmAgAABQhxdWFudGl0eQkAAgECG1F1YW50aXR5IGNhbm5vdCBiZSBuZWdhdGl2ZQQGcmVjaXBlCQC1CQIFCXJlY2lwZVN0cgIBXwMJAQIhPQIJAJADAQUGcmVjaXBlCQBkAgUGTlVNUkVTAAMJAAIBCQCsAgICF0ZhdGFsOiB1bmtub3duIHJlY2lwZTogBQlyZWNpcGVTdHIECHBhY2tTaXplCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGcmVjaXBlBRFyZWNpcGVJZHhQYWNrc2l6ZQQJbWF4QW1vdW50CQBoAgUNRVNNQVhQQUNLQUdFUwUIcGFja1NpemUEC2V4aXN0QW1vdW50AwkAZgIJAJADAQUMZXhpc3RBbW91bnRzBQFqCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUMZXhpc3RBbW91bnRzBQFqAAAEBmNhbkJ1eQkAZQIFCW1heEFtb3VudAULZXhpc3RBbW91bnQDCQBmAgUIcXVhbnRpdHkFBmNhbkJ1eQkAAgEJAKwCAgkArAICCQCsAgICF1dhcmVo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", "height": 2632547, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 6HvfrK4zKzbeDbUs2YWW3UUbLkNvk119UBkwhsfdi6HM Next: BakS7xjhzDmNs3dopYyU59GWDFEnnYSRHkJTQmttissc Diff:
Old | New | Differences | |
---|---|---|---|
21 | 21 | else throw("Unknown chain") | |
22 | 22 | } | |
23 | 23 | ||
24 | + | let InfraUpgradeCostS = match chain { | |
25 | + | case _ => | |
26 | + | if ((base58'2W' == $match0)) | |
27 | + | then 10000000000 | |
28 | + | else if ((base58'2T' == $match0)) | |
29 | + | then 100000000 | |
30 | + | else throw("Unknown chain") | |
31 | + | } | |
32 | + | ||
24 | 33 | let SEP = "__" | |
25 | 34 | ||
26 | 35 | let MULT6 = 1000000 | |
33 | 42 | ||
34 | 43 | let LANDPREFIX = "LAND" | |
35 | 44 | ||
45 | + | let DUCKPREFIX = "DUCK" | |
46 | + | ||
47 | + | let ARTPRESALE = "PRESALE" | |
48 | + | ||
36 | 49 | let NUMRES = 6 | |
50 | + | ||
51 | + | let SSIZE = 25 | |
52 | + | ||
53 | + | let MSIZE = 100 | |
54 | + | ||
55 | + | let LSIZE = 225 | |
56 | + | ||
57 | + | let XLSIZE = 400 | |
58 | + | ||
59 | + | let XXLSIZE = 625 | |
60 | + | ||
61 | + | let DAILYRESBYPIECE = 3456000 | |
62 | + | ||
63 | + | let DAYMILLIS = 86400000 | |
64 | + | ||
65 | + | let WHMULTIPLIER = 10000000000 | |
37 | 66 | ||
38 | 67 | let DEFAULTLOCATION = "Africa_F_Africa" | |
39 | 68 | ||
42 | 71 | let ESMAXPACKAGES = 3 | |
43 | 72 | ||
44 | 73 | let ESBUYCOEF = 4 | |
74 | + | ||
75 | + | let ESSELLCOEF = 10 | |
76 | + | ||
77 | + | let MAXHP = 100 | |
45 | 78 | ||
46 | 79 | let resTypes = ["Oil", "Ore", "Wood", "Sand", "Clay", "Organic"] | |
47 | 80 | ||
53 | 86 | ||
54 | 87 | let productionMatrix = ["1_1_1_2_2_5_1_10_0", "2_2_2_4_4_10_1_10_0", "3_3_3_6_6_15_1_10_0", "2_5_5_2_7_5_2_100_1", "4_10_10_4_14_10_2_100_1", "6_15_15_6_21_15_2_100_1", "1_1_1_1_1_8_1_10_2", "2_2_2_2_2_16_1_10_2", "3_3_3_3_3_24_1_10_2", "9_9_1_5_5_1_5_100_3", "18_18_2_10_10_2_5_100_3", "27_27_3_15_15_3_5_100_3", "2_2_1_2_2_2_1_10_4", "4_4_2_4_4_4_1_10_4", "6_6_3_6_6_6_1_10_4"] | |
55 | 88 | ||
89 | + | let contIdxAmericas = 0 | |
90 | + | ||
91 | + | let contIdxEurope = 1 | |
92 | + | ||
93 | + | let contIdxAsia = 2 | |
94 | + | ||
95 | + | let contIdxAfrica = 3 | |
96 | + | ||
97 | + | let contIdxOceania = 4 | |
98 | + | ||
99 | + | let recipeIdxFuel = 0 | |
100 | + | ||
101 | + | let recipeIdxMetal = 1 | |
102 | + | ||
103 | + | let recipeIdxPlank = 2 | |
104 | + | ||
105 | + | let recipeIdxGlass = 3 | |
106 | + | ||
107 | + | let recipeIdxPlastic = 4 | |
108 | + | ||
109 | + | let recipeIdxProtein = 5 | |
110 | + | ||
111 | + | let recipeIdxWeight = 6 | |
112 | + | ||
56 | 113 | let recipeIdxPacksize = 7 | |
57 | 114 | ||
58 | 115 | let recipeIdxContinent = 8 | |
116 | + | ||
117 | + | let recLandNum = 0 | |
118 | + | ||
119 | + | let recLandSize = 1 | |
120 | + | ||
121 | + | let recTerrains = 2 | |
122 | + | ||
123 | + | let recContinent = 3 | |
59 | 124 | ||
60 | 125 | let whIdxLevels = 0 | |
61 | 126 | ||
71 | 136 | ||
72 | 137 | let volOccupied = 1 | |
73 | 138 | ||
139 | + | let volFree = 2 | |
140 | + | ||
74 | 141 | let volTotal = 3 | |
75 | 142 | ||
76 | 143 | let bpIdxLevel = 0 | |
81 | 148 | ||
82 | 149 | let bpIdxProd = 3 | |
83 | 150 | ||
151 | + | func getPkgSize (prodIdx) = parseIntValue(split(productionMatrix[prodIdx], "_")[recipeIdxPacksize]) | |
152 | + | ||
153 | + | ||
84 | 154 | func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], "")) | |
85 | 155 | ||
86 | 156 | ||
157 | + | func getIntOrElse (key,defaultVal) = valueOrElse(getInteger(this, key), defaultVal) | |
158 | + | ||
159 | + | ||
87 | 160 | let IdxCfgStakingDapp = 1 | |
161 | + | ||
162 | + | let IdxCfgEconomyDapp = 2 | |
163 | + | ||
164 | + | let IdxCfgGovernanceDapp = 3 | |
165 | + | ||
166 | + | let IdxCfgWlgDapp = 4 | |
88 | 167 | ||
89 | 168 | func keyRestCfg () = "%s__restConfig" | |
90 | 169 | ||
104 | 183 | ||
105 | 184 | let stakingContract = getContractAddressOrFail(restCfg, IdxCfgStakingDapp) | |
106 | 185 | ||
186 | + | let economyContract = getContractAddressOrFail(restCfg, IdxCfgEconomyDapp) | |
187 | + | ||
188 | + | let govContract = getContractAddressOrFail(restCfg, IdxCfgGovernanceDapp) | |
189 | + | ||
190 | + | let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp) | |
191 | + | ||
192 | + | func keyLastTxIdByUser (addr) = ("lastTxIdByUser_" + addr) | |
193 | + | ||
194 | + | ||
107 | 195 | func keyLandAssetIdToOwner (assetId) = ("nftOwner_" + assetId) | |
196 | + | ||
197 | + | ||
198 | + | func keyLandAssetIdToCustomName (assetId) = ("landCustomNameByAssetId_" + assetId) | |
108 | 199 | ||
109 | 200 | ||
110 | 201 | func keyStakedTimeByAssetId (assetId) = ("stakedTime_" + assetId) | |
111 | 202 | ||
112 | 203 | ||
204 | + | func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId) | |
205 | + | ||
206 | + | ||
207 | + | func keyLandArtStatusByTypeAndAssetId (type,assetId) = makeString(["landArtStatus", type, assetId], "_") | |
208 | + | ||
209 | + | ||
210 | + | func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr) | |
211 | + | ||
212 | + | ||
213 | + | func keyWarehouseByLand (landAssetId) = ("wareHouse_" + landAssetId) | |
214 | + | ||
215 | + | ||
216 | + | func keyStakedLandsByOwner (ownerAddr) = ("stakedLandsByOwner_" + ownerAddr) | |
217 | + | ||
218 | + | ||
219 | + | func keyStakedPiecesByOwner (ownerAddr) = ("stakedPiecesByOwner_" + ownerAddr) | |
220 | + | ||
221 | + | ||
222 | + | func keyDuckAssetIdToCustomName (assetId) = ("duckCustomNameByAssetId_" + assetId) | |
223 | + | ||
224 | + | ||
225 | + | func keyAddressToCustomName (addr) = ("accountCustomNameByAddr_" + addr) | |
226 | + | ||
227 | + | ||
113 | 228 | func keyAddressRefBy (addr) = ("accRefBy_" + addr) | |
229 | + | ||
230 | + | ||
231 | + | func keyAddressReferrals (addr) = ("accReferrals_" + addr) | |
232 | + | ||
233 | + | ||
234 | + | func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId) | |
114 | 235 | ||
115 | 236 | ||
116 | 237 | func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr) | |
122 | 243 | func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId) | |
123 | 244 | ||
124 | 245 | ||
246 | + | func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId) | |
247 | + | ||
248 | + | ||
249 | + | func keyResProportions () = "resTypesProportions" | |
250 | + | ||
251 | + | ||
125 | 252 | func keyBlocked () = "contractsBlocked" | |
253 | + | ||
254 | + | ||
255 | + | func keyUserGwlReleaseTime (userAddr) = ("%s%s__userGwlReleaseTime__" + userAddr) | |
126 | 256 | ||
127 | 257 | ||
128 | 258 | func keyOrderByLand (landAssetId) = ("landOrder_" + landAssetId) | |
145 | 275 | } | |
146 | 276 | ||
147 | 277 | ||
278 | + | func asInt (v) = match v { | |
279 | + | case n: Int => | |
280 | + | n | |
281 | + | case _ => | |
282 | + | throw("fail to cast into Int") | |
283 | + | } | |
284 | + | ||
285 | + | ||
286 | + | func asAnyList (v) = match v { | |
287 | + | case l: List[Any] => | |
288 | + | l | |
289 | + | case _ => | |
290 | + | throw("fail to cast into List[Any]") | |
291 | + | } | |
292 | + | ||
293 | + | ||
294 | + | func asBoolean (v) = match v { | |
295 | + | case s: Boolean => | |
296 | + | s | |
297 | + | case _ => | |
298 | + | throw("fail to cast into Boolean") | |
299 | + | } | |
300 | + | ||
301 | + | ||
302 | + | func numPiecesBySize (landSize) = match landSize { | |
303 | + | case _ => | |
304 | + | if (("S" == $match0)) | |
305 | + | then SSIZE | |
306 | + | else if (("M" == $match0)) | |
307 | + | then MSIZE | |
308 | + | else if (("L" == $match0)) | |
309 | + | then LSIZE | |
310 | + | else if (("XL" == $match0)) | |
311 | + | then XLSIZE | |
312 | + | else if (("XXL" == $match0)) | |
313 | + | then XXLSIZE | |
314 | + | else throw("Unknown land size") | |
315 | + | } | |
316 | + | ||
317 | + | ||
318 | + | let IdxEffTotal = 0 | |
319 | + | ||
320 | + | let IdxEffUser = 1 | |
321 | + | ||
322 | + | func getVotingPower (userAddrStrOrEmpty) = { | |
323 | + | let props = split(valueOrElse(getString(stakingContract, keyResProportions()), "0_0_0_0_0_0"), "_") | |
324 | + | func adder (acc,item) = (acc + parseIntValue(item)) | |
325 | + | ||
326 | + | let totalPower = { | |
327 | + | let $l = props | |
328 | + | let $s = size($l) | |
329 | + | let $acc0 = 0 | |
330 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
331 | + | then $a | |
332 | + | else adder($a, $l[$i]) | |
333 | + | ||
334 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
335 | + | then $a | |
336 | + | else throw("List size exceeds 6") | |
337 | + | ||
338 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
339 | + | } | |
340 | + | let usersPower = if ((userAddrStrOrEmpty == "")) | |
341 | + | then 0 | |
342 | + | else { | |
343 | + | let landsStr = getString(stakingContract, keyStakedLandsByOwner(userAddrStrOrEmpty)) | |
344 | + | let lands = if (isDefined(landsStr)) | |
345 | + | then split_51C(value(landsStr), "_") | |
346 | + | else nil | |
347 | + | func oneLand (acc,landAssetId) = { | |
348 | + | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
349 | + | let landSize = split(asset.description, "_")[recLandSize] | |
350 | + | (acc + numPiecesBySize(landSize)) | |
351 | + | } | |
352 | + | ||
353 | + | let $l = lands | |
354 | + | let $s = size($l) | |
355 | + | let $acc0 = 0 | |
356 | + | func $f1_1 ($a,$i) = if (($i >= $s)) | |
357 | + | then $a | |
358 | + | else oneLand($a, $l[$i]) | |
359 | + | ||
360 | + | func $f1_2 ($a,$i) = if (($i >= $s)) | |
361 | + | then $a | |
362 | + | else throw("List size exceeds 100") | |
363 | + | ||
364 | + | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_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), 100) | |
365 | + | } | |
366 | + | [totalPower, usersPower] | |
367 | + | } | |
368 | + | ||
369 | + | ||
148 | 370 | func getRecipeMaterials (recipe) = { | |
149 | 371 | func addMat (ac,j) = (ac + parseIntValue(recipe[j])) | |
150 | 372 | ||
164 | 386 | ||
165 | 387 | ||
166 | 388 | let FACTORYMAXWAREHOUSE = 10000000000 | |
389 | + | ||
390 | + | let MINPAYMENT = 10000 | |
167 | 391 | ||
168 | 392 | let SELLMULTIPLIER = 200 | |
169 | 393 | ||
769 | 993 | let whLocked = (buyVolSaldo + sellVolSaldo) | |
770 | 994 | let whFree = ((whTotal - whOccupied) - whLocked) | |
771 | 995 | if ((0 > whFree)) | |
772 | - | then throw((((("Attempt to reserve " + toString(buyVolSaldo)) + " space for buy orders, and ") + toString(sellVolSaldo)) + " space for sell orders, leads to negative free space")) | |
996 | + | then throw((((((("Attempt to reserve " + toString(buyVolSaldo)) + " space for buy orders, and ") + toString(sellVolSaldo)) + " space for sell orders (and occupied=") + toString(whOccupied)) + "), leads to negative free space")) | |
773 | 997 | else { | |
774 | 998 | let whStr = makeString_2C([currentWh[whIdxLevels], makeString(z._1, "_"), makeString(z._2, "_"), makeString(z._3, "_"), toString(whLocked)], ":") | |
775 | 999 | let whSave = asString(invoke(stakingContract, "saveWarehouse", [whStr, landAssetId], nil)) |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let chain = take(drop(this.bytes, 1), 1) | |
5 | 5 | ||
6 | 6 | let usdtAssetId = match chain { | |
7 | 7 | case _ => | |
8 | 8 | if ((base58'2W' == $match0)) | |
9 | 9 | then base58'9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi' | |
10 | 10 | else if ((base58'2T' == $match0)) | |
11 | 11 | then base58'6mWwf9mZBjVgkC54idpyaZLQfAosD914wT8fGf2iiY63' | |
12 | 12 | else throw("Unknown chain") | |
13 | 13 | } | |
14 | 14 | ||
15 | 15 | let defaultRestAddressStr = match chain { | |
16 | 16 | case _ => | |
17 | 17 | if ((base58'2W' == $match0)) | |
18 | 18 | then "3PQCuvFbvh4LkPUnrnU1z3jnbA1p9m3WNhv" | |
19 | 19 | else if ((base58'2T' == $match0)) | |
20 | 20 | then "3MumkGGztCKAXpWDqxkddofqXSUbqQkvSJy" | |
21 | 21 | else throw("Unknown chain") | |
22 | 22 | } | |
23 | 23 | ||
24 | + | let InfraUpgradeCostS = match chain { | |
25 | + | case _ => | |
26 | + | if ((base58'2W' == $match0)) | |
27 | + | then 10000000000 | |
28 | + | else if ((base58'2T' == $match0)) | |
29 | + | then 100000000 | |
30 | + | else throw("Unknown chain") | |
31 | + | } | |
32 | + | ||
24 | 33 | let SEP = "__" | |
25 | 34 | ||
26 | 35 | let MULT6 = 1000000 | |
27 | 36 | ||
28 | 37 | let MULT7 = 10000000 | |
29 | 38 | ||
30 | 39 | let MULT8 = 100000000 | |
31 | 40 | ||
32 | 41 | let MULT10 = 10000000000 | |
33 | 42 | ||
34 | 43 | let LANDPREFIX = "LAND" | |
35 | 44 | ||
45 | + | let DUCKPREFIX = "DUCK" | |
46 | + | ||
47 | + | let ARTPRESALE = "PRESALE" | |
48 | + | ||
36 | 49 | let NUMRES = 6 | |
50 | + | ||
51 | + | let SSIZE = 25 | |
52 | + | ||
53 | + | let MSIZE = 100 | |
54 | + | ||
55 | + | let LSIZE = 225 | |
56 | + | ||
57 | + | let XLSIZE = 400 | |
58 | + | ||
59 | + | let XXLSIZE = 625 | |
60 | + | ||
61 | + | let DAILYRESBYPIECE = 3456000 | |
62 | + | ||
63 | + | let DAYMILLIS = 86400000 | |
64 | + | ||
65 | + | let WHMULTIPLIER = 10000000000 | |
37 | 66 | ||
38 | 67 | let DEFAULTLOCATION = "Africa_F_Africa" | |
39 | 68 | ||
40 | 69 | let RESOURCEPRICEMIN = 39637 | |
41 | 70 | ||
42 | 71 | let ESMAXPACKAGES = 3 | |
43 | 72 | ||
44 | 73 | let ESBUYCOEF = 4 | |
74 | + | ||
75 | + | let ESSELLCOEF = 10 | |
76 | + | ||
77 | + | let MAXHP = 100 | |
45 | 78 | ||
46 | 79 | let resTypes = ["Oil", "Ore", "Wood", "Sand", "Clay", "Organic"] | |
47 | 80 | ||
48 | 81 | let matTypes = ["Fuel", "Metal", "Plank", "Glass", "Plastic", "Protein"] | |
49 | 82 | ||
50 | 83 | let prodTypes = ["First Aid Kit L1", "First Aid Kit L2", "First Aid Kit L3", "Backpack L1", "Backpack L2", "Backpack L3", "Food Ration L1", "Food Ration L2", "Food Ration L3", "Jet Pack L1", "Jet Pack L2", "Jet Pack L3", "Shield L1", "Shield L2", "Shield L3"] | |
51 | 84 | ||
52 | 85 | let continents = ["Americas", "Europe", "Asia", "Africa", "Oceania"] | |
53 | 86 | ||
54 | 87 | let productionMatrix = ["1_1_1_2_2_5_1_10_0", "2_2_2_4_4_10_1_10_0", "3_3_3_6_6_15_1_10_0", "2_5_5_2_7_5_2_100_1", "4_10_10_4_14_10_2_100_1", "6_15_15_6_21_15_2_100_1", "1_1_1_1_1_8_1_10_2", "2_2_2_2_2_16_1_10_2", "3_3_3_3_3_24_1_10_2", "9_9_1_5_5_1_5_100_3", "18_18_2_10_10_2_5_100_3", "27_27_3_15_15_3_5_100_3", "2_2_1_2_2_2_1_10_4", "4_4_2_4_4_4_1_10_4", "6_6_3_6_6_6_1_10_4"] | |
55 | 88 | ||
89 | + | let contIdxAmericas = 0 | |
90 | + | ||
91 | + | let contIdxEurope = 1 | |
92 | + | ||
93 | + | let contIdxAsia = 2 | |
94 | + | ||
95 | + | let contIdxAfrica = 3 | |
96 | + | ||
97 | + | let contIdxOceania = 4 | |
98 | + | ||
99 | + | let recipeIdxFuel = 0 | |
100 | + | ||
101 | + | let recipeIdxMetal = 1 | |
102 | + | ||
103 | + | let recipeIdxPlank = 2 | |
104 | + | ||
105 | + | let recipeIdxGlass = 3 | |
106 | + | ||
107 | + | let recipeIdxPlastic = 4 | |
108 | + | ||
109 | + | let recipeIdxProtein = 5 | |
110 | + | ||
111 | + | let recipeIdxWeight = 6 | |
112 | + | ||
56 | 113 | let recipeIdxPacksize = 7 | |
57 | 114 | ||
58 | 115 | let recipeIdxContinent = 8 | |
116 | + | ||
117 | + | let recLandNum = 0 | |
118 | + | ||
119 | + | let recLandSize = 1 | |
120 | + | ||
121 | + | let recTerrains = 2 | |
122 | + | ||
123 | + | let recContinent = 3 | |
59 | 124 | ||
60 | 125 | let whIdxLevels = 0 | |
61 | 126 | ||
62 | 127 | let whIdxRes = 1 | |
63 | 128 | ||
64 | 129 | let whIdxMat = 2 | |
65 | 130 | ||
66 | 131 | let whIdxProd = 3 | |
67 | 132 | ||
68 | 133 | let whIdxLOFT = 4 | |
69 | 134 | ||
70 | 135 | let volLocked = 0 | |
71 | 136 | ||
72 | 137 | let volOccupied = 1 | |
73 | 138 | ||
139 | + | let volFree = 2 | |
140 | + | ||
74 | 141 | let volTotal = 3 | |
75 | 142 | ||
76 | 143 | let bpIdxLevel = 0 | |
77 | 144 | ||
78 | 145 | let bpIdxRes = 1 | |
79 | 146 | ||
80 | 147 | let bpIdxMat = 2 | |
81 | 148 | ||
82 | 149 | let bpIdxProd = 3 | |
83 | 150 | ||
151 | + | func getPkgSize (prodIdx) = parseIntValue(split(productionMatrix[prodIdx], "_")[recipeIdxPacksize]) | |
152 | + | ||
153 | + | ||
84 | 154 | func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], "")) | |
85 | 155 | ||
86 | 156 | ||
157 | + | func getIntOrElse (key,defaultVal) = valueOrElse(getInteger(this, key), defaultVal) | |
158 | + | ||
159 | + | ||
87 | 160 | let IdxCfgStakingDapp = 1 | |
161 | + | ||
162 | + | let IdxCfgEconomyDapp = 2 | |
163 | + | ||
164 | + | let IdxCfgGovernanceDapp = 3 | |
165 | + | ||
166 | + | let IdxCfgWlgDapp = 4 | |
88 | 167 | ||
89 | 168 | func keyRestCfg () = "%s__restConfig" | |
90 | 169 | ||
91 | 170 | ||
92 | 171 | func keyRestAddress () = "%s__restAddr" | |
93 | 172 | ||
94 | 173 | ||
95 | 174 | func readRestCfgOrFail (rest) = split_4C(getStringOrFail(rest, keyRestCfg()), SEP) | |
96 | 175 | ||
97 | 176 | ||
98 | 177 | func getContractAddressOrFail (restCfg,idx) = valueOrErrorMessage(addressFromString(restCfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx))) | |
99 | 178 | ||
100 | 179 | ||
101 | 180 | let restContract = addressFromStringValue(valueOrElse(getString(this, keyRestAddress()), defaultRestAddressStr)) | |
102 | 181 | ||
103 | 182 | let restCfg = readRestCfgOrFail(restContract) | |
104 | 183 | ||
105 | 184 | let stakingContract = getContractAddressOrFail(restCfg, IdxCfgStakingDapp) | |
106 | 185 | ||
186 | + | let economyContract = getContractAddressOrFail(restCfg, IdxCfgEconomyDapp) | |
187 | + | ||
188 | + | let govContract = getContractAddressOrFail(restCfg, IdxCfgGovernanceDapp) | |
189 | + | ||
190 | + | let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp) | |
191 | + | ||
192 | + | func keyLastTxIdByUser (addr) = ("lastTxIdByUser_" + addr) | |
193 | + | ||
194 | + | ||
107 | 195 | func keyLandAssetIdToOwner (assetId) = ("nftOwner_" + assetId) | |
196 | + | ||
197 | + | ||
198 | + | func keyLandAssetIdToCustomName (assetId) = ("landCustomNameByAssetId_" + assetId) | |
108 | 199 | ||
109 | 200 | ||
110 | 201 | func keyStakedTimeByAssetId (assetId) = ("stakedTime_" + assetId) | |
111 | 202 | ||
112 | 203 | ||
204 | + | func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId) | |
205 | + | ||
206 | + | ||
207 | + | func keyLandArtStatusByTypeAndAssetId (type,assetId) = makeString(["landArtStatus", type, assetId], "_") | |
208 | + | ||
209 | + | ||
210 | + | func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr) | |
211 | + | ||
212 | + | ||
213 | + | func keyWarehouseByLand (landAssetId) = ("wareHouse_" + landAssetId) | |
214 | + | ||
215 | + | ||
216 | + | func keyStakedLandsByOwner (ownerAddr) = ("stakedLandsByOwner_" + ownerAddr) | |
217 | + | ||
218 | + | ||
219 | + | func keyStakedPiecesByOwner (ownerAddr) = ("stakedPiecesByOwner_" + ownerAddr) | |
220 | + | ||
221 | + | ||
222 | + | func keyDuckAssetIdToCustomName (assetId) = ("duckCustomNameByAssetId_" + assetId) | |
223 | + | ||
224 | + | ||
225 | + | func keyAddressToCustomName (addr) = ("accountCustomNameByAddr_" + addr) | |
226 | + | ||
227 | + | ||
113 | 228 | func keyAddressRefBy (addr) = ("accRefBy_" + addr) | |
229 | + | ||
230 | + | ||
231 | + | func keyAddressReferrals (addr) = ("accReferrals_" + addr) | |
232 | + | ||
233 | + | ||
234 | + | func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId) | |
114 | 235 | ||
115 | 236 | ||
116 | 237 | func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr) | |
117 | 238 | ||
118 | 239 | ||
119 | 240 | func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId) | |
120 | 241 | ||
121 | 242 | ||
122 | 243 | func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId) | |
123 | 244 | ||
124 | 245 | ||
246 | + | func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId) | |
247 | + | ||
248 | + | ||
249 | + | func keyResProportions () = "resTypesProportions" | |
250 | + | ||
251 | + | ||
125 | 252 | func keyBlocked () = "contractsBlocked" | |
253 | + | ||
254 | + | ||
255 | + | func keyUserGwlReleaseTime (userAddr) = ("%s%s__userGwlReleaseTime__" + userAddr) | |
126 | 256 | ||
127 | 257 | ||
128 | 258 | func keyOrderByLand (landAssetId) = ("landOrder_" + landAssetId) | |
129 | 259 | ||
130 | 260 | ||
131 | 261 | func keyEsWarehouse () = "emergencyWarehouseProducts" | |
132 | 262 | ||
133 | 263 | ||
134 | 264 | let locIdxContinent = 0 | |
135 | 265 | ||
136 | 266 | let locIdxType = 1 | |
137 | 267 | ||
138 | 268 | let locIdxId = 2 | |
139 | 269 | ||
140 | 270 | func asString (v) = match v { | |
141 | 271 | case s: String => | |
142 | 272 | s | |
143 | 273 | case _ => | |
144 | 274 | throw("fail to cast into String") | |
145 | 275 | } | |
146 | 276 | ||
147 | 277 | ||
278 | + | func asInt (v) = match v { | |
279 | + | case n: Int => | |
280 | + | n | |
281 | + | case _ => | |
282 | + | throw("fail to cast into Int") | |
283 | + | } | |
284 | + | ||
285 | + | ||
286 | + | func asAnyList (v) = match v { | |
287 | + | case l: List[Any] => | |
288 | + | l | |
289 | + | case _ => | |
290 | + | throw("fail to cast into List[Any]") | |
291 | + | } | |
292 | + | ||
293 | + | ||
294 | + | func asBoolean (v) = match v { | |
295 | + | case s: Boolean => | |
296 | + | s | |
297 | + | case _ => | |
298 | + | throw("fail to cast into Boolean") | |
299 | + | } | |
300 | + | ||
301 | + | ||
302 | + | func numPiecesBySize (landSize) = match landSize { | |
303 | + | case _ => | |
304 | + | if (("S" == $match0)) | |
305 | + | then SSIZE | |
306 | + | else if (("M" == $match0)) | |
307 | + | then MSIZE | |
308 | + | else if (("L" == $match0)) | |
309 | + | then LSIZE | |
310 | + | else if (("XL" == $match0)) | |
311 | + | then XLSIZE | |
312 | + | else if (("XXL" == $match0)) | |
313 | + | then XXLSIZE | |
314 | + | else throw("Unknown land size") | |
315 | + | } | |
316 | + | ||
317 | + | ||
318 | + | let IdxEffTotal = 0 | |
319 | + | ||
320 | + | let IdxEffUser = 1 | |
321 | + | ||
322 | + | func getVotingPower (userAddrStrOrEmpty) = { | |
323 | + | let props = split(valueOrElse(getString(stakingContract, keyResProportions()), "0_0_0_0_0_0"), "_") | |
324 | + | func adder (acc,item) = (acc + parseIntValue(item)) | |
325 | + | ||
326 | + | let totalPower = { | |
327 | + | let $l = props | |
328 | + | let $s = size($l) | |
329 | + | let $acc0 = 0 | |
330 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
331 | + | then $a | |
332 | + | else adder($a, $l[$i]) | |
333 | + | ||
334 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
335 | + | then $a | |
336 | + | else throw("List size exceeds 6") | |
337 | + | ||
338 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
339 | + | } | |
340 | + | let usersPower = if ((userAddrStrOrEmpty == "")) | |
341 | + | then 0 | |
342 | + | else { | |
343 | + | let landsStr = getString(stakingContract, keyStakedLandsByOwner(userAddrStrOrEmpty)) | |
344 | + | let lands = if (isDefined(landsStr)) | |
345 | + | then split_51C(value(landsStr), "_") | |
346 | + | else nil | |
347 | + | func oneLand (acc,landAssetId) = { | |
348 | + | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
349 | + | let landSize = split(asset.description, "_")[recLandSize] | |
350 | + | (acc + numPiecesBySize(landSize)) | |
351 | + | } | |
352 | + | ||
353 | + | let $l = lands | |
354 | + | let $s = size($l) | |
355 | + | let $acc0 = 0 | |
356 | + | func $f1_1 ($a,$i) = if (($i >= $s)) | |
357 | + | then $a | |
358 | + | else oneLand($a, $l[$i]) | |
359 | + | ||
360 | + | func $f1_2 ($a,$i) = if (($i >= $s)) | |
361 | + | then $a | |
362 | + | else throw("List size exceeds 100") | |
363 | + | ||
364 | + | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_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), 100) | |
365 | + | } | |
366 | + | [totalPower, usersPower] | |
367 | + | } | |
368 | + | ||
369 | + | ||
148 | 370 | func getRecipeMaterials (recipe) = { | |
149 | 371 | func addMat (ac,j) = (ac + parseIntValue(recipe[j])) | |
150 | 372 | ||
151 | 373 | let $l = [0, 1, 2, 3, 4, 5] | |
152 | 374 | let $s = size($l) | |
153 | 375 | let $acc0 = 0 | |
154 | 376 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
155 | 377 | then $a | |
156 | 378 | else addMat($a, $l[$i]) | |
157 | 379 | ||
158 | 380 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
159 | 381 | then $a | |
160 | 382 | else throw("List size exceeds 6") | |
161 | 383 | ||
162 | 384 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
163 | 385 | } | |
164 | 386 | ||
165 | 387 | ||
166 | 388 | let FACTORYMAXWAREHOUSE = 10000000000 | |
389 | + | ||
390 | + | let MINPAYMENT = 10000 | |
167 | 391 | ||
168 | 392 | let SELLMULTIPLIER = 200 | |
169 | 393 | ||
170 | 394 | let BUYMULTIPLIER = 300 | |
171 | 395 | ||
172 | 396 | let AUCTIONFEE = 10000 | |
173 | 397 | ||
174 | 398 | let MINSHOPPAYMENT = 100000 | |
175 | 399 | ||
176 | 400 | func keyFactoryWarehouseByIdAndType (factoryId,resType) = ((("factoryWhByContinentAndRes_" + factoryId) + "_") + toString(resType)) | |
177 | 401 | ||
178 | 402 | ||
179 | 403 | let ordIdxRes = 0 | |
180 | 404 | ||
181 | 405 | let ordIdxMat = 1 | |
182 | 406 | ||
183 | 407 | let ordIdxProd = 2 | |
184 | 408 | ||
185 | 409 | func getOrder (ordKey) = { | |
186 | 410 | let p = split(valueOrElse(getString(ordKey), "0@0_0@0_0@0_0@0_0@0_0@0:0@0_0@0_0@0_0@0_0@0_0@0:"), ":") | |
187 | 411 | [if ((size(split(p[ordIdxRes], "_")) == NUMRES)) | |
188 | 412 | then p[ordIdxRes] | |
189 | 413 | else "0@0_0@0_0@0_0@0_0@0_0@0", if ((size(split(p[ordIdxMat], "_")) == NUMRES)) | |
190 | 414 | then p[ordIdxMat] | |
191 | 415 | else "0@0_0@0_0@0_0@0_0@0_0@0", p[ordIdxProd]] | |
192 | 416 | } | |
193 | 417 | ||
194 | 418 | ||
195 | 419 | func toVolume (amount,pkgSize,isProduct) = if (isProduct) | |
196 | 420 | then { | |
197 | 421 | let pkgs = if ((amount >= 0)) | |
198 | 422 | then (((amount + pkgSize) - 1) / pkgSize) | |
199 | 423 | else -((((-(amount) + pkgSize) - 1) / pkgSize)) | |
200 | 424 | (pkgs * MULT8) | |
201 | 425 | } | |
202 | 426 | else amount | |
203 | 427 | ||
204 | 428 | ||
205 | 429 | func sellInternal (locId,resType,amount,minPrice) = { | |
206 | 430 | let whKey = keyFactoryWarehouseByIdAndType(locId, resType) | |
207 | 431 | let w0 = valueOrElse(getInteger(whKey), 0) | |
208 | 432 | let r0 = if ((w0 > FACTORYMAXWAREHOUSE)) | |
209 | 433 | then 0 | |
210 | 434 | else if (((w0 + amount) > FACTORYMAXWAREHOUSE)) | |
211 | 435 | then (FACTORYMAXWAREHOUSE - w0) | |
212 | 436 | else amount | |
213 | 437 | let usdtReceived = (fraction(r0, ((SELLMULTIPLIER * RESOURCEPRICEMIN) - fraction(((100 * w0) + (50 * r0)), RESOURCEPRICEMIN, FACTORYMAXWAREHOUSE)), MULT10) + fraction((amount - r0), RESOURCEPRICEMIN, MULT8)) | |
214 | 438 | let min99 = (minPrice - (minPrice / 100)) | |
215 | 439 | if (((min99 * amount) > (usdtReceived * MULT8))) | |
216 | 440 | then throw((((((((((("Actual price = " + toString(usdtReceived)) + " / ") + toString(amount)) + " < minPrice = ") + toString(minPrice)) + ", (") + locId) + ", ") + resTypes[resType]) + ")")) | |
217 | 441 | else $Tuple2(IntegerEntry(whKey, (w0 + amount)), usdtReceived) | |
218 | 442 | } | |
219 | 443 | ||
220 | 444 | ||
221 | 445 | func buyInternal (locId,matType,amount,maxPrice) = { | |
222 | 446 | let whKey = keyFactoryWarehouseByIdAndType(locId, matType) | |
223 | 447 | let w0 = valueOrElse(getInteger(whKey), 0) | |
224 | 448 | let m1 = if ((w0 > FACTORYMAXWAREHOUSE)) | |
225 | 449 | then min([amount, (w0 - FACTORYMAXWAREHOUSE)]) | |
226 | 450 | else 0 | |
227 | 451 | let m0 = min([w0, (amount - m1)]) | |
228 | 452 | let m = (m0 + m1) | |
229 | 453 | let usdtSpent = (fraction(m0, ((BUYMULTIPLIER * RESOURCEPRICEMIN) - fraction(((100 * w0) - (50 * m0)), RESOURCEPRICEMIN, FACTORYMAXWAREHOUSE)), MULT10) + fraction(m1, (2 * RESOURCEPRICEMIN), MULT8)) | |
230 | 454 | let max101 = (maxPrice + (maxPrice / 100)) | |
231 | 455 | if (((usdtSpent * MULT8) > (max101 * m))) | |
232 | 456 | then throw((((((((((("Actual price = " + toString(usdtSpent)) + " / ") + toString(m)) + " > maxPrice = ") + toString(maxPrice)) + ", (") + locId) + ", ") + matTypes[matType]) + ")")) | |
233 | 457 | else $Tuple3(IntegerEntry(whKey, (w0 - m)), usdtSpent, m) | |
234 | 458 | } | |
235 | 459 | ||
236 | 460 | ||
237 | 461 | func getBackpack (bpKey) = { | |
238 | 462 | let p = split(valueOrElse(getString(stakingContract, bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":") | |
239 | 463 | [toString(valueOrElse(parseInt(p[bpIdxLevel]), 0)), if ((size(split(p[bpIdxRes], "_")) == NUMRES)) | |
240 | 464 | then p[bpIdxRes] | |
241 | 465 | else "0_0_0_0_0_0", if ((size(split(p[bpIdxMat], "_")) == NUMRES)) | |
242 | 466 | then p[bpIdxMat] | |
243 | 467 | else "0_0_0_0_0_0", p[bpIdxProd]] | |
244 | 468 | } | |
245 | 469 | ||
246 | 470 | ||
247 | 471 | func checkBlocked () = if (valueOrElse(getBoolean(stakingContract, keyBlocked()), false)) | |
248 | 472 | then throw("Contracts are under maintenance") | |
249 | 473 | else unit | |
250 | 474 | ||
251 | 475 | ||
252 | 476 | func setCommon (acc,item) = { | |
253 | 477 | let j = acc._1 | |
254 | 478 | let isProd = acc._8 | |
255 | 479 | let pkgSize = if (isProd) | |
256 | 480 | then parseIntValue(split(productionMatrix[j], "_")[recipeIdxPacksize]) | |
257 | 481 | else 0 | |
258 | 482 | let itemParts = split(item, "@") | |
259 | 483 | if ((size(itemParts) != 2)) | |
260 | 484 | then throw("Incorrect order format, should be amount@price") | |
261 | 485 | else { | |
262 | 486 | let newOrdAm = parseIntValue(itemParts[0]) | |
263 | 487 | let newOrdPr = parseIntValue(itemParts[1]) | |
264 | 488 | let newOrdUsd = fraction(newOrdAm, newOrdPr, MULT8) | |
265 | 489 | let newOrdVol = toVolume(newOrdAm, pkgSize, isProd) | |
266 | 490 | let whInit = if ((size(acc._6) > j)) | |
267 | 491 | then parseIntValue(acc._6[j]) | |
268 | 492 | else 0 | |
269 | 493 | let curOrdParts = split(if ((size(acc._7) > j)) | |
270 | 494 | then acc._7[j] | |
271 | 495 | else "0@0", "@") | |
272 | 496 | let curOrdAm = parseIntValue(curOrdParts[0]) | |
273 | 497 | let curOrdPr = parseIntValue(curOrdParts[1]) | |
274 | 498 | if (if ((0 > curOrdPr)) | |
275 | 499 | then true | |
276 | 500 | else (0 > newOrdPr)) | |
277 | 501 | then throw("Price can't be negative") | |
278 | 502 | else { | |
279 | 503 | let curOrdUsd = fraction(curOrdAm, curOrdPr, MULT8) | |
280 | 504 | let curOrdVol = toVolume(curOrdAm, pkgSize, isProd) | |
281 | 505 | if ((newOrdAm == 0)) | |
282 | 506 | then if ((curOrdAm > 0)) | |
283 | 507 | then $Tuple8((j + 1), (acc._2 :+ toString(whInit)), acc._3, acc._4, (acc._5 - curOrdUsd), acc._6, acc._7, isProd) | |
284 | 508 | else $Tuple8((j + 1), (acc._2 :+ toString((whInit - curOrdAm))), acc._3, acc._4, acc._5, acc._6, acc._7, isProd) | |
285 | 509 | else if ((newOrdAm > 0)) | |
286 | 510 | then if ((0 > curOrdAm)) | |
287 | 511 | then $Tuple8((j + 1), (acc._2 :+ toString((whInit - curOrdAm))), (acc._3 + newOrdVol), acc._4, (acc._5 + newOrdUsd), acc._6, acc._7, isProd) | |
288 | 512 | else $Tuple8((j + 1), (acc._2 :+ toString(whInit)), (acc._3 + newOrdVol), acc._4, ((acc._5 + newOrdUsd) - curOrdUsd), acc._6, acc._7, isProd) | |
289 | 513 | else if ((0 > curOrdAm)) | |
290 | 514 | then { | |
291 | 515 | let amDiff = (curOrdAm - newOrdAm) | |
292 | 516 | if ((0 > (whInit - amDiff))) | |
293 | 517 | then throw((((("Attempt to take " + toString(amDiff)) + " from warehouse, but only ") + toString(whInit)) + " available")) | |
294 | 518 | else $Tuple8((j + 1), (acc._2 :+ toString((whInit - amDiff))), acc._3, (acc._4 - newOrdVol), acc._5, acc._6, acc._7, isProd) | |
295 | 519 | } | |
296 | 520 | else if ((0 > (whInit + newOrdAm))) | |
297 | 521 | then throw((((("Attempt to take " + toString(-(newOrdAm))) + " from warehouse, but only ") + toString(whInit)) + " available")) | |
298 | 522 | else $Tuple8((j + 1), (acc._2 :+ toString((whInit + newOrdAm))), acc._3, (acc._4 - newOrdVol), (acc._5 - curOrdUsd), acc._6, acc._7, isProd) | |
299 | 523 | } | |
300 | 524 | } | |
301 | 525 | } | |
302 | 526 | ||
303 | 527 | ||
304 | 528 | func setInternal (currentWh,currentOrd,newOrd) = { | |
305 | 529 | let currWhRes = split(currentWh[whIdxRes], "_") | |
306 | 530 | let currWhMat = split(currentWh[whIdxMat], "_") | |
307 | 531 | let currWhProd = if ((currentWh[whIdxProd] == "")) | |
308 | 532 | then nil | |
309 | 533 | else split(currentWh[whIdxProd], "_") | |
310 | 534 | let currentOrdRes = split(currentOrd[ordIdxRes], "_") | |
311 | 535 | let currentOrdMat = split(currentOrd[ordIdxMat], "_") | |
312 | 536 | let currentOrdProd = if ((currentOrd[ordIdxProd] == "")) | |
313 | 537 | then nil | |
314 | 538 | else split(currentOrd[ordIdxProd], "_") | |
315 | 539 | if ((size(newOrd) != 3)) | |
316 | 540 | then throw("newOrderStr should contain exactly 2 ':' separators") | |
317 | 541 | else { | |
318 | 542 | let resParts = split(newOrd[0], "_") | |
319 | 543 | let matParts = split(newOrd[1], "_") | |
320 | 544 | let prodParts = if ((newOrd[2] == "")) | |
321 | 545 | then nil | |
322 | 546 | else split(newOrd[2], "_") | |
323 | 547 | if ((size(resParts) != NUMRES)) | |
324 | 548 | then throw("All 6 resources should be passed") | |
325 | 549 | else if ((size(matParts) != NUMRES)) | |
326 | 550 | then throw("All 6 materials should be passed") | |
327 | 551 | else { | |
328 | 552 | let r = { | |
329 | 553 | let $l = resParts | |
330 | 554 | let $s = size($l) | |
331 | 555 | let $acc0 = $Tuple8(0, nil, 0, 0, 0, currWhRes, currentOrdRes, false) | |
332 | 556 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
333 | 557 | then $a | |
334 | 558 | else setCommon($a, $l[$i]) | |
335 | 559 | ||
336 | 560 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
337 | 561 | then $a | |
338 | 562 | else throw("List size exceeds 6") | |
339 | 563 | ||
340 | 564 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
341 | 565 | } | |
342 | 566 | let m = { | |
343 | 567 | let $l = matParts | |
344 | 568 | let $s = size($l) | |
345 | 569 | let $acc0 = $Tuple8(0, nil, r._3, r._4, r._5, currWhMat, currentOrdMat, false) | |
346 | 570 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
347 | 571 | then $a | |
348 | 572 | else setCommon($a, $l[$i]) | |
349 | 573 | ||
350 | 574 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
351 | 575 | then $a | |
352 | 576 | else throw("List size exceeds 6") | |
353 | 577 | ||
354 | 578 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
355 | 579 | } | |
356 | 580 | let p = if ((size(prodParts) != 0)) | |
357 | 581 | then { | |
358 | 582 | let $l = prodParts | |
359 | 583 | let $s = size($l) | |
360 | 584 | let $acc0 = $Tuple8(0, nil, m._3, m._4, m._5, currWhProd, currentOrdProd, true) | |
361 | 585 | func $f2_1 ($a,$i) = if (($i >= $s)) | |
362 | 586 | then $a | |
363 | 587 | else setCommon($a, $l[$i]) | |
364 | 588 | ||
365 | 589 | func $f2_2 ($a,$i) = if (($i >= $s)) | |
366 | 590 | then $a | |
367 | 591 | else throw("List size exceeds 50") | |
368 | 592 | ||
369 | 593 | $f2_2($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_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) | |
370 | 594 | } | |
371 | 595 | else $Tuple8(0, currWhProd, m._3, m._4, m._5, currWhProd, currentOrdProd, true) | |
372 | 596 | $Tuple6(r._2, m._2, p._2, p._3, p._4, p._5) | |
373 | 597 | } | |
374 | 598 | } | |
375 | 599 | } | |
376 | 600 | ||
377 | 601 | ||
378 | 602 | func acceptCommon (acc,bpOrdItem) = { | |
379 | 603 | let j = acc._7 | |
380 | 604 | let isProd = acc._12 | |
381 | 605 | let pkgSize = if (isProd) | |
382 | 606 | then parseIntValue(split(productionMatrix[j], "_")[recipeIdxPacksize]) | |
383 | 607 | else 0 | |
384 | 608 | let bpOrdParts = split(bpOrdItem, "@") | |
385 | 609 | if ((size(bpOrdParts) != 2)) | |
386 | 610 | then throw("Incorrect order format, should be amount@price") | |
387 | 611 | else { | |
388 | 612 | let bpOrdAm = parseIntValue(bpOrdParts[0]) | |
389 | 613 | let bpOrdPr = parseIntValue(bpOrdParts[1]) | |
390 | 614 | if ((0 > bpOrdPr)) | |
391 | 615 | then throw("Price can't be negative") | |
392 | 616 | else { | |
393 | 617 | let bpOrdUsd = fraction(bpOrdAm, bpOrdPr, MULT8) | |
394 | 618 | let bpInit = if ((size(acc._8) > j)) | |
395 | 619 | then parseIntValue(acc._8[j]) | |
396 | 620 | else 0 | |
397 | 621 | let whInit = if ((size(acc._9) > j)) | |
398 | 622 | then parseIntValue(acc._9[j]) | |
399 | 623 | else 0 | |
400 | 624 | let whOrdInit = if ((size(acc._10) > j)) | |
401 | 625 | then acc._10[j] | |
402 | 626 | else "0@0" | |
403 | 627 | let whOrdParts = split(whOrdInit, "@") | |
404 | 628 | let whOrdAm = parseIntValue(whOrdParts[0]) | |
405 | 629 | let whOrdPr = parseIntValue(whOrdParts[1]) | |
406 | 630 | if (if ((bpOrdAm != 0)) | |
407 | 631 | then (bpOrdPr != whOrdPr) | |
408 | 632 | else false) | |
409 | 633 | then throw(((((("Prices of " + acc._11[j]) + " don't match! WH price=") + toString(whOrdPr)) + ", your price=") + toString(bpOrdPr))) | |
410 | 634 | else { | |
411 | 635 | let whOrdUsd = fraction(whOrdAm, whOrdPr, MULT8) | |
412 | 636 | let deltaVol = toVolume(bpOrdAm, pkgSize, isProd) | |
413 | 637 | if ((bpOrdAm == 0)) | |
414 | 638 | then $Tuple12((acc._1 :+ toString(whInit)), (acc._2 :+ whOrdInit), (acc._3 :+ toString(bpInit)), acc._4, acc._5, acc._6, (acc._7 + 1), acc._8, acc._9, acc._10, acc._11, isProd) | |
415 | 639 | else if ((bpOrdAm > 0)) | |
416 | 640 | then if ((0 > whOrdAm)) | |
417 | 641 | then if ((bpOrdAm > -(whOrdAm))) | |
418 | 642 | then throw(((((("Attempt to buy " + toString(bpOrdAm)) + " of ") + acc._11[j]) + ", but warehouse only sells ") + toString(-(whOrdAm)))) | |
419 | 643 | else $Tuple12((acc._1 :+ toString(whInit)), (acc._2 :+ ((toString((whOrdAm + bpOrdAm)) + "@") + toString(whOrdPr))), (acc._3 :+ toString((bpInit + bpOrdAm))), (acc._4 + deltaVol), acc._5, (acc._6 + bpOrdUsd), (acc._7 + 1), acc._8, acc._9, acc._10, acc._11, isProd) | |
420 | 644 | else throw((("Attempt to buy " + acc._11[j]) + " while warehouse doesn't sell it")) | |
421 | 645 | else if ((whOrdAm > 0)) | |
422 | 646 | then if ((-(bpOrdAm) > whOrdAm)) | |
423 | 647 | then throw(((((("Attempt to sell " + toString(-(bpOrdAm))) + " of ") + acc._11[j]) + ", but warehouse only buys ") + toString(whOrdAm))) | |
424 | 648 | else if ((-(bpOrdAm) > bpInit)) | |
425 | 649 | then throw(((((("Attempt to sell " + toString(-(bpOrdAm))) + ", but you only have ") + toString(bpInit)) + " of ") + acc._11[j])) | |
426 | 650 | else $Tuple12((acc._1 :+ toString((whInit - bpOrdAm))), (acc._2 :+ ((toString((whOrdAm + bpOrdAm)) + "@") + toString(whOrdPr))), (acc._3 :+ toString((bpInit + bpOrdAm))), (acc._4 - deltaVol), (acc._5 - bpOrdUsd), acc._6, (acc._7 + 1), acc._8, acc._9, acc._10, acc._11, isProd) | |
427 | 651 | else throw((("Attempt to sell " + acc._11[j]) + " while warehouse doesn't buy it")) | |
428 | 652 | } | |
429 | 653 | } | |
430 | 654 | } | |
431 | 655 | } | |
432 | 656 | ||
433 | 657 | ||
434 | 658 | @Callable(i) | |
435 | 659 | func recalcLockedVolumeREADONLY (landAssetId,wh) = { | |
436 | 660 | let currentOrd = getOrder(keyOrderByLand(landAssetId)) | |
437 | 661 | let z = setInternal(wh, currentOrd, currentOrd) | |
438 | 662 | $Tuple2(nil, (z._4 + z._5)) | |
439 | 663 | } | |
440 | 664 | ||
441 | 665 | ||
442 | 666 | ||
443 | 667 | @Callable(i) | |
444 | 668 | func constructorV1 (restAddr) = if ((i.caller != this)) | |
445 | 669 | then throw("Permission denied") | |
446 | 670 | else [StringEntry(keyRestAddress(), restAddr)] | |
447 | 671 | ||
448 | 672 | ||
449 | 673 | ||
450 | 674 | @Callable(i) | |
451 | 675 | func sellResources (amounts,minPrices) = { | |
452 | 676 | let blocked = checkBlocked() | |
453 | 677 | if ((blocked == blocked)) | |
454 | 678 | then { | |
455 | 679 | let duckAssetId = valueOrErrorMessage(getString(stakingContract, keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
456 | 680 | if ((size(i.payments) != 0)) | |
457 | 681 | then throw("sellResources doesn't require any payments") | |
458 | 682 | else { | |
459 | 683 | let curLocation = split(valueOrElse(getString(stakingContract, keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_") | |
460 | 684 | if ((curLocation[locIdxType] != "F")) | |
461 | 685 | then throw(("Duck location type should be Factory, but is " + curLocation[locIdxType])) | |
462 | 686 | else { | |
463 | 687 | let locId = curLocation[locIdxId] | |
464 | 688 | let currentPack = getBackpack(keyBackpackByDuck(duckAssetId)) | |
465 | 689 | let resList = split(currentPack[bpIdxRes], "_") | |
466 | 690 | func adder (acc,j) = if ((amounts[j] > parseIntValue(resList[j]))) | |
467 | 691 | then throw(((((("You have " + resList[j]) + " of ") + resTypes[j]) + ", but tried to sell ") + toString(amounts[j]))) | |
468 | 692 | else if ((0 > amounts[j])) | |
469 | 693 | then throw(((("You tried to sell negative amount of " + resTypes[j]) + ": ") + toString(amounts[j]))) | |
470 | 694 | else if ((amounts[j] > 0)) | |
471 | 695 | then { | |
472 | 696 | let b = sellInternal(locId, j, amounts[j], minPrices[j]) | |
473 | 697 | $Tuple3((acc._1 :+ b._1), (acc._2 :+ toString((parseIntValue(resList[j]) - amounts[j]))), (acc._3 + b._2)) | |
474 | 698 | } | |
475 | 699 | else $Tuple3(acc._1, (acc._2 :+ resList[j]), acc._3) | |
476 | 700 | ||
477 | 701 | let merged = { | |
478 | 702 | let $l = [0, 1, 2, 3, 4, 5] | |
479 | 703 | let $s = size($l) | |
480 | 704 | let $acc0 = $Tuple3(nil, nil, 0) | |
481 | 705 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
482 | 706 | then $a | |
483 | 707 | else adder($a, $l[$i]) | |
484 | 708 | ||
485 | 709 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
486 | 710 | then $a | |
487 | 711 | else throw("List size exceeds 6") | |
488 | 712 | ||
489 | 713 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
490 | 714 | } | |
491 | 715 | let newPack = makeString([currentPack[bpIdxLevel], makeString(merged._2, "_"), currentPack[bpIdxMat], currentPack[bpIdxProd]], ":") | |
492 | 716 | let result = asString(invoke(stakingContract, "updateBackpack", [duckAssetId, newPack], nil)) | |
493 | 717 | $Tuple2((merged._1 :+ ScriptTransfer(i.caller, merged._3, usdtAssetId)), result) | |
494 | 718 | } | |
495 | 719 | } | |
496 | 720 | } | |
497 | 721 | else throw("Strict value is not equal to itself.") | |
498 | 722 | } | |
499 | 723 | ||
500 | 724 | ||
501 | 725 | ||
502 | 726 | @Callable(i) | |
503 | 727 | func buyMaterials (amounts,maxPrices) = { | |
504 | 728 | let blocked = checkBlocked() | |
505 | 729 | if ((blocked == blocked)) | |
506 | 730 | then { | |
507 | 731 | let duckAssetId = valueOrErrorMessage(getString(stakingContract, keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
508 | 732 | if ((size(i.payments) != 1)) | |
509 | 733 | then throw("exactly 1 payment must be attached") | |
510 | 734 | else { | |
511 | 735 | let pmt = i.payments[0] | |
512 | 736 | let amt = pmt.amount | |
513 | 737 | let pmtAssetId = valueOrErrorMessage(pmt.assetId, "WAVES can't be used as payment") | |
514 | 738 | if ((pmtAssetId != usdtAssetId)) | |
515 | 739 | then throw("USDT payments only!") | |
516 | 740 | else { | |
517 | 741 | let curLocation = split(valueOrElse(getString(stakingContract, keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_") | |
518 | 742 | if ((curLocation[locIdxType] != "F")) | |
519 | 743 | then throw(("Duck location type should be Factory, but is " + curLocation[locIdxType])) | |
520 | 744 | else { | |
521 | 745 | let locId = curLocation[locIdxId] | |
522 | 746 | let currentPack = getBackpack(keyBackpackByDuck(duckAssetId)) | |
523 | 747 | let matList = split(currentPack[bpIdxMat], "_") | |
524 | 748 | func mUpdater (acc,j) = if ((0 > amounts[j])) | |
525 | 749 | then throw(((("You tried to buy negative amount of " + matTypes[j]) + ": ") + toString(amounts[j]))) | |
526 | 750 | else if ((amounts[j] > 0)) | |
527 | 751 | then { | |
528 | 752 | let b = buyInternal(locId, j, amounts[j], maxPrices[j]) | |
529 | 753 | $Tuple3((acc._1 :+ b._1), (acc._2 :+ toString((parseIntValue(matList[j]) + b._3))), (acc._3 + b._2)) | |
530 | 754 | } | |
531 | 755 | else $Tuple3(acc._1, (acc._2 :+ matList[j]), acc._3) | |
532 | 756 | ||
533 | 757 | let merged = { | |
534 | 758 | let $l = [0, 1, 2, 3, 4, 5] | |
535 | 759 | let $s = size($l) | |
536 | 760 | let $acc0 = $Tuple3(nil, nil, 0) | |
537 | 761 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
538 | 762 | then $a | |
539 | 763 | else mUpdater($a, $l[$i]) | |
540 | 764 | ||
541 | 765 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
542 | 766 | then $a | |
543 | 767 | else throw("List size exceeds 6") | |
544 | 768 | ||
545 | 769 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
546 | 770 | } | |
547 | 771 | if ((merged._3 > amt)) | |
548 | 772 | then throw(((("Insufficient payment! Attached=" + toString(amt)) + ", required=") + toString(merged._3))) | |
549 | 773 | else { | |
550 | 774 | let newPack = makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], makeString(merged._2, "_"), currentPack[bpIdxProd]], ":") | |
551 | 775 | let result = asString(invoke(stakingContract, "updateBackpack", [duckAssetId, newPack], nil)) | |
552 | 776 | let rest = if (((amt - merged._3) > 0)) | |
553 | 777 | then [ScriptTransfer(i.caller, (amt - merged._3), usdtAssetId)] | |
554 | 778 | else nil | |
555 | 779 | let activitiesAmount = (merged._3 / 100) | |
556 | 780 | $Tuple2(((merged._1 ++ rest) :+ ScriptTransfer(restContract, activitiesAmount, usdtAssetId)), result) | |
557 | 781 | } | |
558 | 782 | } | |
559 | 783 | } | |
560 | 784 | } | |
561 | 785 | } | |
562 | 786 | else throw("Strict value is not equal to itself.") | |
563 | 787 | } | |
564 | 788 | ||
565 | 789 | ||
566 | 790 | ||
567 | 791 | @Callable(i) | |
568 | 792 | func exchangeResources (amounts) = { | |
569 | 793 | let blocked = checkBlocked() | |
570 | 794 | if ((blocked == blocked)) | |
571 | 795 | then { | |
572 | 796 | let duckAssetId = valueOrErrorMessage(getString(stakingContract, keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
573 | 797 | if ((size(i.payments) != 1)) | |
574 | 798 | then throw("exactly 1 payment must be attached") | |
575 | 799 | else { | |
576 | 800 | let pmt = i.payments[0] | |
577 | 801 | let amt = pmt.amount | |
578 | 802 | let pmtAssetId = valueOrErrorMessage(pmt.assetId, "WAVES can't be used as payment") | |
579 | 803 | if ((pmtAssetId != usdtAssetId)) | |
580 | 804 | then throw("USDT payments only!") | |
581 | 805 | else { | |
582 | 806 | let curLocation = split(valueOrElse(getString(stakingContract, keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_") | |
583 | 807 | if ((curLocation[locIdxType] != "F")) | |
584 | 808 | then throw(("Duck location type should be Factory, but is " + curLocation[locIdxType])) | |
585 | 809 | else { | |
586 | 810 | let locId = curLocation[locIdxId] | |
587 | 811 | let currentPack = getBackpack(keyBackpackByDuck(duckAssetId)) | |
588 | 812 | let resList = split(currentPack[bpIdxRes], "_") | |
589 | 813 | let matList = split(currentPack[bpIdxMat], "_") | |
590 | 814 | func exchanger (acc,j) = { | |
591 | 815 | let whKey = keyFactoryWarehouseByIdAndType(locId, j) | |
592 | 816 | let w0 = valueOrElse(getInteger(whKey), 0) | |
593 | 817 | let amj = amounts[j] | |
594 | 818 | if ((amj > parseIntValue(resList[j]))) | |
595 | 819 | then throw(((((("You have " + resList[j]) + " of ") + resTypes[j]) + ", but tried to exchange ") + toString(amj))) | |
596 | 820 | else if ((0 > amj)) | |
597 | 821 | then throw(((("You tried to exchange negative amount of " + resTypes[j]) + ": ") + toString(amj))) | |
598 | 822 | else if ((amj > 0)) | |
599 | 823 | then $Tuple4((acc._1 :+ toString((parseIntValue(resList[j]) - amj))), (acc._2 :+ toString((parseIntValue(matList[j]) + amj))), (acc._3 + fraction(amj, RESOURCEPRICEMIN, MULT8)), (acc._4 :+ IntegerEntry(whKey, w0))) | |
600 | 824 | else $Tuple4((acc._1 :+ resList[j]), (acc._2 :+ matList[j]), acc._3, acc._4) | |
601 | 825 | } | |
602 | 826 | ||
603 | 827 | let merged = { | |
604 | 828 | let $l = [0, 1, 2, 3, 4, 5] | |
605 | 829 | let $s = size($l) | |
606 | 830 | let $acc0 = $Tuple4(nil, nil, 0, nil) | |
607 | 831 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
608 | 832 | then $a | |
609 | 833 | else exchanger($a, $l[$i]) | |
610 | 834 | ||
611 | 835 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
612 | 836 | then $a | |
613 | 837 | else throw("List size exceeds 6") | |
614 | 838 | ||
615 | 839 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
616 | 840 | } | |
617 | 841 | if ((merged._3 > amt)) | |
618 | 842 | then throw(((("Insufficient payment! Attached=" + toString(amt)) + ", required=") + toString(merged._3))) | |
619 | 843 | else { | |
620 | 844 | let newPack = makeString([currentPack[bpIdxLevel], makeString(merged._1, "_"), makeString(merged._2, "_"), currentPack[bpIdxProd]], ":") | |
621 | 845 | let result = asString(invoke(stakingContract, "updateBackpack", [duckAssetId, newPack], nil)) | |
622 | 846 | let rest = if (((amt - merged._3) > 0)) | |
623 | 847 | then [ScriptTransfer(i.caller, (amt - merged._3), usdtAssetId)] | |
624 | 848 | else nil | |
625 | 849 | let activitiesAmount = (merged._3 / 100) | |
626 | 850 | $Tuple2(((rest ++ merged._4) :+ ScriptTransfer(restContract, activitiesAmount, usdtAssetId)), result) | |
627 | 851 | } | |
628 | 852 | } | |
629 | 853 | } | |
630 | 854 | } | |
631 | 855 | } | |
632 | 856 | else throw("Strict value is not equal to itself.") | |
633 | 857 | } | |
634 | 858 | ||
635 | 859 | ||
636 | 860 | ||
637 | 861 | @Callable(i) | |
638 | 862 | func craftGoods (productIdx,quantity) = { | |
639 | 863 | let blocked = checkBlocked() | |
640 | 864 | if ((blocked == blocked)) | |
641 | 865 | then if ((size(i.payments) != 1)) | |
642 | 866 | then throw("exactly 1 payment must be attached") | |
643 | 867 | else { | |
644 | 868 | let pmt = i.payments[0] | |
645 | 869 | let amt = pmt.amount | |
646 | 870 | let pmtAssetId = valueOrErrorMessage(pmt.assetId, "WAVES can't be used as payment") | |
647 | 871 | if ((pmtAssetId != usdtAssetId)) | |
648 | 872 | then throw("USDT payments only!") | |
649 | 873 | else if ((amt != MULT6)) | |
650 | 874 | then throw("exactly 1 USDT must be attached as payment") | |
651 | 875 | else if ((0 >= quantity)) | |
652 | 876 | then throw("Quantity should be positive") | |
653 | 877 | else { | |
654 | 878 | let duckAssetId = valueOrErrorMessage(getString(stakingContract, keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
655 | 879 | let curLocation = split(valueOrElse(getString(stakingContract, keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_") | |
656 | 880 | if ((curLocation[locIdxType] != "M")) | |
657 | 881 | then throw(("Duck location type should be Manufactory, but is " + curLocation[locIdxType])) | |
658 | 882 | else { | |
659 | 883 | let cont = curLocation[locIdxContinent] | |
660 | 884 | let currentPack = getBackpack(keyBackpackByDuck(duckAssetId)) | |
661 | 885 | let matList = split(currentPack[bpIdxMat], "_") | |
662 | 886 | if (if ((0 > productIdx)) | |
663 | 887 | then true | |
664 | 888 | else (productIdx >= size(productionMatrix))) | |
665 | 889 | then throw(("Unknown product idx=" + toString(productIdx))) | |
666 | 890 | else { | |
667 | 891 | let recipe = split(productionMatrix[productIdx], "_") | |
668 | 892 | if ((size(recipe) != (NUMRES + 3))) | |
669 | 893 | then throw(("Fatal: unknown recipe: " + productionMatrix[productIdx])) | |
670 | 894 | else { | |
671 | 895 | let productContIdx = parseIntValue(recipe[recipeIdxContinent]) | |
672 | 896 | if ((continents[productContIdx] != cont)) | |
673 | 897 | then throw(((("This product is available in " + continents[productContIdx]) + ", but you are in ") + cont)) | |
674 | 898 | else { | |
675 | 899 | let prodList = if ((currentPack[bpIdxProd] == "")) | |
676 | 900 | then nil | |
677 | 901 | else split(currentPack[bpIdxProd], "_") | |
678 | 902 | func filler (acc,ignoredItem) = { | |
679 | 903 | let n = acc._2 | |
680 | 904 | let xs = if ((size(prodList) > n)) | |
681 | 905 | then prodList[n] | |
682 | 906 | else "0" | |
683 | 907 | let x = parseIntValue(xs) | |
684 | 908 | let amount = (quantity * parseIntValue(recipe[recipeIdxPacksize])) | |
685 | 909 | let y = if ((n == productIdx)) | |
686 | 910 | then toString((x + amount)) | |
687 | 911 | else xs | |
688 | 912 | $Tuple2((acc._1 :+ y), (n + 1)) | |
689 | 913 | } | |
690 | 914 | ||
691 | 915 | let bpProd = ( let $l = productionMatrix | |
692 | 916 | let $s = size($l) | |
693 | 917 | let $acc0 = $Tuple2(nil, 0) | |
694 | 918 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
695 | 919 | then $a | |
696 | 920 | else filler($a, $l[$i]) | |
697 | 921 | ||
698 | 922 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
699 | 923 | then $a | |
700 | 924 | else throw("List size exceeds 50") | |
701 | 925 | ||
702 | 926 | $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($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))._1 | |
703 | 927 | func producer (acc,j) = { | |
704 | 928 | let needMat = ((parseIntValue(recipe[j]) * MULT7) * quantity) | |
705 | 929 | let haveMat = parseIntValue(matList[j]) | |
706 | 930 | if ((needMat > haveMat)) | |
707 | 931 | then throw(((((((("You have " + matList[j]) + " of ") + matTypes[j]) + ", but recipe requires ") + toString(needMat)) + " for quantity ") + toString(quantity))) | |
708 | 932 | else if ((needMat > 0)) | |
709 | 933 | then (acc :+ toString((haveMat - needMat))) | |
710 | 934 | else (acc :+ matList[j]) | |
711 | 935 | } | |
712 | 936 | ||
713 | 937 | let merged = { | |
714 | 938 | let $l = [0, 1, 2, 3, 4, 5] | |
715 | 939 | let $s = size($l) | |
716 | 940 | let $acc0 = nil | |
717 | 941 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
718 | 942 | then $a | |
719 | 943 | else producer($a, $l[$i]) | |
720 | 944 | ||
721 | 945 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
722 | 946 | then $a | |
723 | 947 | else throw("List size exceeds 6") | |
724 | 948 | ||
725 | 949 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
726 | 950 | } | |
727 | 951 | let newPack = makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], makeString(merged, "_"), makeString(bpProd, "_")], ":") | |
728 | 952 | let result = asString(invoke(stakingContract, "updateBackpack", [duckAssetId, newPack], nil)) | |
729 | 953 | $Tuple2(nil, result) | |
730 | 954 | } | |
731 | 955 | } | |
732 | 956 | } | |
733 | 957 | } | |
734 | 958 | } | |
735 | 959 | } | |
736 | 960 | else throw("Strict value is not equal to itself.") | |
737 | 961 | } | |
738 | 962 | ||
739 | 963 | ||
740 | 964 | ||
741 | 965 | @Callable(i) | |
742 | 966 | func setWarehouseOrder (newOrderStr,landAssetId) = { | |
743 | 967 | let user = i.originCaller | |
744 | 968 | let addr = toString(user) | |
745 | 969 | let result = if ((user != restContract)) | |
746 | 970 | then checkBlocked() | |
747 | 971 | else false | |
748 | 972 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
749 | 973 | if (!(isDefined(getInteger(stakingContract, keyStakedTimeByAssetId(landAssetId))))) | |
750 | 974 | then throw((("NFT " + asset.name) + " is not staked")) | |
751 | 975 | else { | |
752 | 976 | let owner = valueOrErrorMessage(getString(stakingContract, keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned")) | |
753 | 977 | if (if ((user != restContract)) | |
754 | 978 | then (owner != addr) | |
755 | 979 | else false) | |
756 | 980 | then throw((LANDPREFIX + " is not yours")) | |
757 | 981 | else { | |
758 | 982 | let newOrder = split_4C(newOrderStr, ":") | |
759 | 983 | let wh = asString(invoke(stakingContract, "getWarehouseREADONLY", [landAssetId], nil)) | |
760 | 984 | let currentWh = split_4C(wh, ":") | |
761 | 985 | let loft = split(currentWh[whIdxLOFT], "_") | |
762 | 986 | let whOccupied = parseIntValue(loft[volOccupied]) | |
763 | 987 | let whTotal = parseIntValue(loft[volTotal]) | |
764 | 988 | let ordKey = keyOrderByLand(landAssetId) | |
765 | 989 | let currentOrd = getOrder(ordKey) | |
766 | 990 | let z = setInternal(currentWh, currentOrd, newOrder) | |
767 | 991 | let buyVolSaldo = z._4 | |
768 | 992 | let sellVolSaldo = z._5 | |
769 | 993 | let whLocked = (buyVolSaldo + sellVolSaldo) | |
770 | 994 | let whFree = ((whTotal - whOccupied) - whLocked) | |
771 | 995 | if ((0 > whFree)) | |
772 | - | then throw((((("Attempt to reserve " + toString(buyVolSaldo)) + " space for buy orders, and ") + toString(sellVolSaldo)) + " space for sell orders, leads to negative free space")) | |
996 | + | then throw((((((("Attempt to reserve " + toString(buyVolSaldo)) + " space for buy orders, and ") + toString(sellVolSaldo)) + " space for sell orders (and occupied=") + toString(whOccupied)) + "), leads to negative free space")) | |
773 | 997 | else { | |
774 | 998 | let whStr = makeString_2C([currentWh[whIdxLevels], makeString(z._1, "_"), makeString(z._2, "_"), makeString(z._3, "_"), toString(whLocked)], ":") | |
775 | 999 | let whSave = asString(invoke(stakingContract, "saveWarehouse", [whStr, landAssetId], nil)) | |
776 | 1000 | let usdSaldo = z._6 | |
777 | 1001 | let actions = if ((usdSaldo > 0)) | |
778 | 1002 | then if ((size(i.payments) != 1)) | |
779 | 1003 | then throw("exactly 1 payment must be attached") | |
780 | 1004 | else { | |
781 | 1005 | let pmt = i.payments[0] | |
782 | 1006 | let amt = pmt.amount | |
783 | 1007 | let pmtAssetId = valueOrErrorMessage(pmt.assetId, "WAVES can't be used as payment") | |
784 | 1008 | if ((pmtAssetId != usdtAssetId)) | |
785 | 1009 | then throw("USDT payments only!") | |
786 | 1010 | else if ((amt != usdSaldo)) | |
787 | 1011 | then throw(("Payment needed is " + toString(usdSaldo))) | |
788 | 1012 | else [StringEntry(ordKey, newOrderStr)] | |
789 | 1013 | } | |
790 | 1014 | else if ((usdSaldo == 0)) | |
791 | 1015 | then if ((size(i.payments) != 0)) | |
792 | 1016 | then throw("No payments needed") | |
793 | 1017 | else [StringEntry(ordKey, newOrderStr)] | |
794 | 1018 | else if ((size(i.payments) != 0)) | |
795 | 1019 | then throw("No payments needed") | |
796 | 1020 | else [ScriptTransfer(addressFromStringValue(owner), -(usdSaldo), usdtAssetId), StringEntry(ordKey, newOrderStr)] | |
797 | 1021 | $Tuple2(actions, $Tuple2(result, whSave)) | |
798 | 1022 | } | |
799 | 1023 | } | |
800 | 1024 | } | |
801 | 1025 | } | |
802 | 1026 | ||
803 | 1027 | ||
804 | 1028 | ||
805 | 1029 | @Callable(i) | |
806 | 1030 | func acceptWarehouseOrder (bpOrderStr,landAssetId,duckAssetId) = { | |
807 | 1031 | let blocked = checkBlocked() | |
808 | 1032 | let caller = i.originCaller | |
809 | 1033 | let callerAddr = toString(caller) | |
810 | 1034 | let stakedDuckAssetId = valueOrErrorMessage(getString(stakingContract, keyStakedDuckByOwner(callerAddr)), "You don't have a duck staked") | |
811 | 1035 | let curLocation = valueOrElse(getString(stakingContract, keyDuckLocation(stakedDuckAssetId)), DEFAULTLOCATION) | |
812 | 1036 | let loc = split(value(curLocation), "_") | |
813 | 1037 | if ((loc[locIdxType] != "L")) | |
814 | 1038 | then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L")) | |
815 | 1039 | else if ((stakedDuckAssetId != duckAssetId)) | |
816 | 1040 | then throw(((("Your staked duck is " + stakedDuckAssetId) + ", but passed ") + duckAssetId)) | |
817 | 1041 | else { | |
818 | 1042 | let landAsset = value(assetInfo(fromBase58String(landAssetId))) | |
819 | 1043 | if (!(isDefined(getInteger(stakingContract, keyStakedTimeByAssetId(landAssetId))))) | |
820 | 1044 | then throw((("NFT " + landAsset.name) + " is not staked")) | |
821 | 1045 | else { | |
822 | 1046 | let landOwner = valueOrErrorMessage(getString(stakingContract, keyLandAssetIdToOwner(landAssetId)), (("NFT " + landAsset.name) + " is orphaned")) | |
823 | 1047 | if ((landOwner == callerAddr)) | |
824 | 1048 | then throw("You cannot trade with yourself") | |
825 | 1049 | else { | |
826 | 1050 | let bpOrderParts = split_4C(bpOrderStr, ":") | |
827 | 1051 | if ((size(bpOrderParts) != 3)) | |
828 | 1052 | then throw("bpOrderStr should contain exactly 2 ':' separators") | |
829 | 1053 | else { | |
830 | 1054 | let bpOrdRes = split(bpOrderParts[0], "_") | |
831 | 1055 | let bpOrdMat = split(bpOrderParts[1], "_") | |
832 | 1056 | let bpOrdProd = if ((bpOrderParts[2] == "")) | |
833 | 1057 | then nil | |
834 | 1058 | else split(bpOrderParts[2], "_") | |
835 | 1059 | if ((size(bpOrdRes) != NUMRES)) | |
836 | 1060 | then throw("All 6 resources should be passed") | |
837 | 1061 | else if ((size(bpOrdMat) != NUMRES)) | |
838 | 1062 | then throw("All 6 materials should be passed") | |
839 | 1063 | else { | |
840 | 1064 | let wh = asString(invoke(stakingContract, "getWarehouseREADONLY", [landAssetId], nil)) | |
841 | 1065 | let currentWh = split_4C(wh, ":") | |
842 | 1066 | let currWhRes = split(currentWh[whIdxRes], "_") | |
843 | 1067 | let currWhMat = split(currentWh[whIdxMat], "_") | |
844 | 1068 | let currWhProd = if ((currentWh[whIdxProd] == "")) | |
845 | 1069 | then nil | |
846 | 1070 | else split(currentWh[whIdxProd], "_") | |
847 | 1071 | let currWhLockedVol = parseIntValue(split(currentWh[whIdxLOFT], "_")[volLocked]) | |
848 | 1072 | let bpKey = keyBackpackByDuck(duckAssetId) | |
849 | 1073 | let currentPack = getBackpack(bpKey) | |
850 | 1074 | let bpResList = split(currentPack[bpIdxRes], "_") | |
851 | 1075 | let bpMatList = split(currentPack[bpIdxMat], "_") | |
852 | 1076 | let bpProdList = if ((currentPack[bpIdxProd] == "")) | |
853 | 1077 | then nil | |
854 | 1078 | else split(currentPack[bpIdxProd], "_") | |
855 | 1079 | let ordKey = keyOrderByLand(landAssetId) | |
856 | 1080 | let whOrd = getOrder(ordKey) | |
857 | 1081 | let whOrdRes = split(whOrd[ordIdxRes], "_") | |
858 | 1082 | let whOrdMat = split(whOrd[ordIdxMat], "_") | |
859 | 1083 | let whOrdProd = if ((whOrd[ordIdxProd] == "")) | |
860 | 1084 | then nil | |
861 | 1085 | else split(whOrd[ordIdxProd], "_") | |
862 | 1086 | let r = { | |
863 | 1087 | let $l = bpOrdRes | |
864 | 1088 | let $s = size($l) | |
865 | 1089 | let $acc0 = $Tuple12(nil, nil, nil, 0, 0, 0, 0, bpResList, currWhRes, whOrdRes, resTypes, false) | |
866 | 1090 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
867 | 1091 | then $a | |
868 | 1092 | else acceptCommon($a, $l[$i]) | |
869 | 1093 | ||
870 | 1094 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
871 | 1095 | then $a | |
872 | 1096 | else throw("List size exceeds 6") | |
873 | 1097 | ||
874 | 1098 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
875 | 1099 | } | |
876 | 1100 | let m = { | |
877 | 1101 | let $l = bpOrdMat | |
878 | 1102 | let $s = size($l) | |
879 | 1103 | let $acc0 = $Tuple12(nil, nil, nil, r._4, r._5, r._6, 0, bpMatList, currWhMat, whOrdMat, matTypes, false) | |
880 | 1104 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
881 | 1105 | then $a | |
882 | 1106 | else acceptCommon($a, $l[$i]) | |
883 | 1107 | ||
884 | 1108 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
885 | 1109 | then $a | |
886 | 1110 | else throw("List size exceeds 6") | |
887 | 1111 | ||
888 | 1112 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
889 | 1113 | } | |
890 | 1114 | let p = if ((size(bpOrdProd) != 0)) | |
891 | 1115 | then { | |
892 | 1116 | let $l = bpOrdProd | |
893 | 1117 | let $s = size($l) | |
894 | 1118 | let $acc0 = $Tuple12(nil, nil, nil, m._4, m._5, m._6, 0, bpProdList, currWhProd, whOrdProd, prodTypes, true) | |
895 | 1119 | func $f2_1 ($a,$i) = if (($i >= $s)) | |
896 | 1120 | then $a | |
897 | 1121 | else acceptCommon($a, $l[$i]) | |
898 | 1122 | ||
899 | 1123 | func $f2_2 ($a,$i) = if (($i >= $s)) | |
900 | 1124 | then $a | |
901 | 1125 | else throw("List size exceeds 50") | |
902 | 1126 | ||
903 | 1127 | $f2_2($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_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) | |
904 | 1128 | } | |
905 | 1129 | else $Tuple12(currWhProd, whOrdProd, bpProdList, m._4, m._5, m._6, 0, bpProdList, currWhProd, whOrdProd, prodTypes, true) | |
906 | 1130 | let volSaldo = p._4 | |
907 | 1131 | let newLockedVol = if ((0 > (currWhLockedVol - volSaldo))) | |
908 | 1132 | then 0 | |
909 | 1133 | else (currWhLockedVol - volSaldo) | |
910 | 1134 | let whStr = makeString_2C([currentWh[whIdxLevels], makeString(r._1, "_"), makeString(m._1, "_"), makeString(p._1, "_"), toString(newLockedVol)], ":") | |
911 | 1135 | let newWhOrdStr = makeString_2C([makeString(r._2, "_"), makeString(m._2, "_"), makeString(p._2, "_")], ":") | |
912 | 1136 | let newBpStr = makeString_2C([currentPack[bpIdxLevel], makeString(r._3, "_"), makeString(m._3, "_"), makeString(p._3, "_")], ":") | |
913 | 1137 | let whSave = asString(invoke(stakingContract, "saveWarehouse", [whStr, landAssetId], nil)) | |
914 | 1138 | let bpSave = asString(invoke(stakingContract, "updateBackpack", [duckAssetId, newBpStr], nil)) | |
915 | 1139 | let actions = [StringEntry(ordKey, newWhOrdStr)] | |
916 | 1140 | let usdWh2BpSaldo = p._5 | |
917 | 1141 | let actions1 = if ((usdWh2BpSaldo > 0)) | |
918 | 1142 | then { | |
919 | 1143 | let usdWh2BpFee = fraction(p._5, AUCTIONFEE, MULT6) | |
920 | 1144 | let refByKey = keyAddressRefBy(callerAddr) | |
921 | 1145 | let refBy = getString(stakingContract, refByKey) | |
922 | 1146 | if (isDefined(refBy)) | |
923 | 1147 | then (((actions :+ ScriptTransfer(caller, (p._5 - (3 * usdWh2BpFee)), usdtAssetId)) :+ ScriptTransfer(restContract, usdWh2BpFee, usdtAssetId)) :+ ScriptTransfer(addressFromStringValue(value(refBy)), usdWh2BpFee, usdtAssetId)) | |
924 | 1148 | else ((actions :+ ScriptTransfer(caller, (p._5 - (3 * usdWh2BpFee)), usdtAssetId)) :+ ScriptTransfer(restContract, usdWh2BpFee, usdtAssetId)) | |
925 | 1149 | } | |
926 | 1150 | else actions | |
927 | 1151 | let usdBp2WhSaldo = p._6 | |
928 | 1152 | let actions2 = if ((usdBp2WhSaldo > 0)) | |
929 | 1153 | then if ((size(i.payments) != 1)) | |
930 | 1154 | then throw("exactly 1 payment must be attached") | |
931 | 1155 | else { | |
932 | 1156 | let pmt = i.payments[0] | |
933 | 1157 | let amt = pmt.amount | |
934 | 1158 | let pmtAssetId = valueOrErrorMessage(pmt.assetId, "WAVES can't be used as payment") | |
935 | 1159 | if ((pmtAssetId != usdtAssetId)) | |
936 | 1160 | then throw("USDT payments only!") | |
937 | 1161 | else if ((amt != usdBp2WhSaldo)) | |
938 | 1162 | then throw(("Payment needed is " + toString(usdBp2WhSaldo))) | |
939 | 1163 | else if ((MINSHOPPAYMENT > amt)) | |
940 | 1164 | then throw(("Payment should be at least " + toString(MINSHOPPAYMENT))) | |
941 | 1165 | else { | |
942 | 1166 | let usdBp2WhFee = fraction(p._6, AUCTIONFEE, MULT6) | |
943 | 1167 | let refByKey = keyAddressRefBy(landOwner) | |
944 | 1168 | let refBy = getString(stakingContract, refByKey) | |
945 | 1169 | if (isDefined(refBy)) | |
946 | 1170 | then (((actions1 :+ ScriptTransfer(addressFromStringValue(landOwner), (p._6 - (3 * usdBp2WhFee)), usdtAssetId)) :+ ScriptTransfer(restContract, usdBp2WhFee, usdtAssetId)) :+ ScriptTransfer(addressFromStringValue(value(refBy)), usdBp2WhFee, usdtAssetId)) | |
947 | 1171 | else ((actions1 :+ ScriptTransfer(addressFromStringValue(landOwner), (p._6 - (3 * usdBp2WhFee)), usdtAssetId)) :+ ScriptTransfer(restContract, usdBp2WhFee, usdtAssetId)) | |
948 | 1172 | } | |
949 | 1173 | } | |
950 | 1174 | else if ((size(i.payments) != 0)) | |
951 | 1175 | then throw("No payments needed") | |
952 | 1176 | else actions1 | |
953 | 1177 | $Tuple2(actions2, $Tuple3(blocked, whSave, bpSave)) | |
954 | 1178 | } | |
955 | 1179 | } | |
956 | 1180 | } | |
957 | 1181 | } | |
958 | 1182 | } | |
959 | 1183 | } | |
960 | 1184 | ||
961 | 1185 | ||
962 | 1186 | ||
963 | 1187 | @Callable(i) | |
964 | 1188 | func sellProductsToES (amounts) = { | |
965 | 1189 | let blocked = checkBlocked() | |
966 | 1190 | if ((blocked == blocked)) | |
967 | 1191 | then if ((size(i.payments) != 0)) | |
968 | 1192 | then throw("No payments needed") | |
969 | 1193 | else { | |
970 | 1194 | let duckAssetId = valueOrErrorMessage(getString(stakingContract, keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
971 | 1195 | let curLocation = split(valueOrElse(getString(stakingContract, keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_") | |
972 | 1196 | if ((curLocation[locIdxType] != "A")) | |
973 | 1197 | then throw(("Duck location type should be Airport, but is " + curLocation[locIdxType])) | |
974 | 1198 | else { | |
975 | 1199 | let currentPack = getBackpack(keyBackpackByDuck(duckAssetId)) | |
976 | 1200 | let prodList = if ((currentPack[bpIdxProd] == "")) | |
977 | 1201 | then nil | |
978 | 1202 | else split(currentPack[bpIdxProd], "_") | |
979 | 1203 | let esKey = keyEsWarehouse() | |
980 | 1204 | let existStr = getString(esKey) | |
981 | 1205 | let existAmounts = if (isDefined(existStr)) | |
982 | 1206 | then split(value(existStr), "_") | |
983 | 1207 | else nil | |
984 | 1208 | func moveProd (acc,recipeStr) = { | |
985 | 1209 | let j = acc._1 | |
986 | 1210 | let quantity = if ((size(amounts) > j)) | |
987 | 1211 | then amounts[j] | |
988 | 1212 | else 0 | |
989 | 1213 | if ((0 > quantity)) | |
990 | 1214 | then throw("Quantity cannot be negative") | |
991 | 1215 | else { | |
992 | 1216 | let recipe = split(recipeStr, "_") | |
993 | 1217 | if ((size(recipe) != (NUMRES + 3))) | |
994 | 1218 | then throw(("Fatal: unknown recipe: " + recipeStr)) | |
995 | 1219 | else { | |
996 | 1220 | let packSize = parseIntValue(recipe[recipeIdxPacksize]) | |
997 | 1221 | let maxAmount = (ESMAXPACKAGES * packSize) | |
998 | 1222 | let existAmount = if ((size(existAmounts) > j)) | |
999 | 1223 | then parseIntValue(existAmounts[j]) | |
1000 | 1224 | else 0 | |
1001 | 1225 | let canBuy = (maxAmount - existAmount) | |
1002 | 1226 | if ((quantity > canBuy)) | |
1003 | 1227 | then throw(((("Warehouse can buy only " + toString(canBuy)) + " of ") + prodTypes[j])) | |
1004 | 1228 | else { | |
1005 | 1229 | let totalMat = getRecipeMaterials(recipe) | |
1006 | 1230 | let unitPrice = fraction((totalMat * ESBUYCOEF), RESOURCEPRICEMIN, (10 * packSize)) | |
1007 | 1231 | let bpProdAmount = if ((size(prodList) > j)) | |
1008 | 1232 | then parseIntValue(prodList[j]) | |
1009 | 1233 | else 0 | |
1010 | 1234 | if ((quantity > bpProdAmount)) | |
1011 | 1235 | then throw(((("You have only " + toString(bpProdAmount)) + " of ") + prodTypes[j])) | |
1012 | 1236 | else $Tuple4((j + 1), (acc._2 + (unitPrice * quantity)), (acc._3 :+ toString((bpProdAmount - quantity))), (acc._4 :+ toString((existAmount + quantity)))) | |
1013 | 1237 | } | |
1014 | 1238 | } | |
1015 | 1239 | } | |
1016 | 1240 | } | |
1017 | 1241 | ||
1018 | 1242 | let merged = { | |
1019 | 1243 | let $l = productionMatrix | |
1020 | 1244 | let $s = size($l) | |
1021 | 1245 | let $acc0 = $Tuple4(0, 0, nil, nil) | |
1022 | 1246 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1023 | 1247 | then $a | |
1024 | 1248 | else moveProd($a, $l[$i]) | |
1025 | 1249 | ||
1026 | 1250 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1027 | 1251 | then $a | |
1028 | 1252 | else throw("List size exceeds 50") | |
1029 | 1253 | ||
1030 | 1254 | $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($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) | |
1031 | 1255 | } | |
1032 | 1256 | let newBpStr = makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], makeString(merged._3, "_")], ":") | |
1033 | 1257 | let bpSave = asString(invoke(stakingContract, "updateBackpack", [duckAssetId, newBpStr], nil)) | |
1034 | 1258 | $Tuple2([StringEntry(esKey, makeString(merged._4, "_")), ScriptTransfer(i.caller, merged._2, usdtAssetId)], bpSave) | |
1035 | 1259 | } | |
1036 | 1260 | } | |
1037 | 1261 | else throw("Strict value is not equal to itself.") | |
1038 | 1262 | } | |
1039 | 1263 | ||
1040 | 1264 | ||
1041 | 1265 | ||
1042 | 1266 | @Callable(i) | |
1043 | 1267 | func updateEsStorage (newStorage) = if ((i.caller != stakingContract)) | |
1044 | 1268 | then throw("Permission denied") | |
1045 | 1269 | else $Tuple2([StringEntry(keyEsWarehouse(), newStorage)], newStorage) | |
1046 | 1270 | ||
1047 | 1271 |
github/deemru/w8io/169f3d6 138.90 ms ◑