tx · FXysfMXWotzYPwq2GFksfrrdhN9x92yPNgiftrfZ6Ec1

3N9yMmmL5cJ7LJxr8o6GFbKFUbGz4XcAjeg:  -0.02000000 Waves

2023.06.01 15:35 [2603601] smart account 3N9yMmmL5cJ7LJxr8o6GFbKFUbGz4XcAjeg > SELF 0.00000000 Waves

{ "type": 13, "id": "FXysfMXWotzYPwq2GFksfrrdhN9x92yPNgiftrfZ6Ec1", "fee": 2000000, "feeAssetId": null, "timestamp": 1685623009901, "version": 2, "chainId": 84, "sender": "3N9yMmmL5cJ7LJxr8o6GFbKFUbGz4XcAjeg", "senderPublicKey": "C2aAS9D6FqfbrkCuCQCtPWAiopjyagvitFLjRuLcRPYt", "proofs": [ "2dEyEh4hRitmcuCsCt34Uu8AnX4u3uixybU9a6mDA6vUhNKbjQnK7LAQsDjbCjwXnBFhoUrH5mAPStK3jYkcCZ5X" ], "script": "base64:BgLwFwgCEgwKCggICAEIAQEBAQESBAoCCAgSBAoCCAQSAwoBCBIECgIIARIFCgMICAgSABIDCgEBEgASABIDCgEBEgASAwoBARIDCgEBEgMKAQgiCXNlcGFyYXRvciIPbWF4RGVwdGhEZWZhdWx0IgVhc0ludCIDdmFsIgckbWF0Y2gwIgZ2YWxJbnQiBmFzQm9vbCIHdmFsQm9vbCIMa2V5RmVlQW1vdW50IgxrZXlXeEFzc2V0SWQiEmtleVZvdGluZ1RocmVzaG9sZCIRa2V5Vm90aW5nRHVyYXRpb24iGGtleVZvdGVCZWZvcmVFbGltaW5hdGlvbiIOa2V5U3RhcnRIZWlnaHQiEGtleUN1cnJlbnRQZXJpb2QiE2tleUJvb3N0aW5nQ29udHJhY3QiE2tleUVtaXNzaW9uQ29udHJhY3QiFmtleUFzc2V0c1N0b3JlQ29udHJhY3QiF2tleUxhdGVzdFByb2Nlc3NlZEFzc2V0IhZrZXlMYXRlc3RQcm9jZXNzZWRVc2VyIhxrZXlMYXRlc3RQcm9jZXNzZWRVc2VyUmVtb3ZlIh9rZXlMYXRlc3RQcm9jZXNzZWRBc3NldFRyYW5zZmVyIh5rZXlMYXRlc3RQcm9jZXNzZWRVc2VyVHJhbnNmZXIiJGtleUxhdGVzdFByb2Nlc3NlZFVzZXJSZW1vdmVUcmFuc2ZlciILa2V5TWF4RGVwdGgiIGtleVZvdGVzVHJhbnNmZXJGaW5pc2hlZEJ5UGVyaW9kIgZwZXJpb2QiDmFzc2V0c0xpc3ROYW1lIhBnZXRWb3Rlc0xpc3ROYW1lIgdhc3NldElkIgtrZXlMaXN0SGVhZCIIbGlzdE5hbWUiC2tleUxpc3RTaXplIgtrZXlMaXN0UHJldiICaWQiC2tleUxpc3ROZXh0IhhrZXlBc3NldFZlcmlmaWVkQnlQZXJpb2QiEGtleUFzc2V0VmVyaWZpZWQiFWtleUFzc2V0V2FzRWxpbWluYXRlZCIVa2V5Vm90ZVJlc3VsdEJ5UGVyaW9kIhBmb3JtYXRWb3RlUmVzdWx0Igh0b3RhbFllcyIHdG90YWxObyIIdmVyaWZpZWQiD3BhcnNlVm90ZVJlc3VsdCIFaW5wdXQiBXBhcnRzIgt0b3RhbFllc0lkeCIKdG90YWxOb0lkeCILdmVyaWZpZWRJZHgiE2tleVVzZXJWb3RlQnlQZXJpb2QiC3VzZXJBZGRyZXNzIg5mb3JtYXRVc2VyVm90ZSIFdG90YWwiB2luRmF2b3IiDXBhcnNlVXNlclZvdGUiB2FnYWluc3QiC2NoZWNrVG90YWxzIhJrZXlVc2VyVm90ZUhpc3RvcnkiBHR5cGUiBHR4SWQiFmtleU1hbmFnZXJWYXVsdEFkZHJlc3MiE2tleU1hbmFnZXJQdWJsaWNLZXkiCHRoaXNPbmx5IgFpIhBnZXRJbnRlZ2VyT3JaZXJvIgNrZXkiEGdldEludGVnZXJPckZhaWwiEGdldFN0cmluZ09yRW1wdHkiD2dldFN0cmluZ09yRmFpbCIJZmVlQW1vdW50Igl3eEFzc2V0SWQiD3ZvdGluZ1RocmVzaG9sZCIOdm90aW5nRHVyYXRpb24iFXZvdGVCZWZvcmVFbGltaW5hdGlvbiILc3RhcnRIZWlnaHQiDWN1cnJlbnRQZXJpb2QiEGJvb3N0aW5nQ29udHJhY3QiEGVtaXNzaW9uQ29udHJhY3QiE2Fzc2V0c1N0b3JlQ29udHJhY3QiCG1heERlcHRoIgllbmRIZWlnaHQiHGdldE1hbmFnZXJWYXVsdEFkZHJlc3NPclRoaXMiAXMiFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQiE21hbmFnZXJWYXVsdEFkZHJlc3MiCWlzTWFuYWdlciICcGsiC211c3RNYW5hZ2VyIhhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQiDHRhcmdldEhlaWdodCIJZ3d4QW1vdW50IhNnZXRWb3RlUmVzdWx0QWN0aW9uIg12b3RlUmVzdWx0S2V5IgskdDA2OTE1NzIxOCIHJG1hdGNoMSILb2xkVG90YWxZZXMiCm9sZFRvdGFsTm8iC29sZFZlcmlmaWVkIgxjb250YWluc05vZGUiBGhlYWQiBHByZXYiBG5leHQiCmluc2VydE5vZGUiCGxpc3RTaXplIgljaGVja05vZGUiCmRlbGV0ZU5vZGUiC3Byb2Nlc3NWb3RlIhF1c2VyQWRkcmVzc09yVW5pdCIXbGF0ZXN0UHJvY2Vzc2VkQXNzZXRLZXkiFmxhdGVzdFByb2Nlc3NlZFVzZXJLZXkiHGxhdGVzdFByb2Nlc3NlZFVzZXJSZW1vdmVLZXkiIHVwZGF0ZUxhdGVzdFByb2Nlc3NlZEFzc2V0QWN0aW9uIh9kZWxldGVMYXRlc3RQcm9jZXNzZWRVc2VyQWN0aW9uIh91cGRhdGVMYXRlc3RQcm9jZXNzZWRVc2VyQWN0aW9uIgt1c2VyVm90ZUtleSIOdXNlclZvdGVPclVuaXQiC3ZvdGVBY3Rpb25zIhh1c2VyR3d4QW1vdW50QXRFbmRIZWlnaHQiDnByZXZpb3VzUGVyaW9kIhJhc3NldFdhc0VsaW1pbmF0ZWQiFnVzZXJQcmV2aW91c1ZvdGVPclVuaXQiDSR0MDExMzI5MTE0MDIiCXByZXZUb3RhbCIXYXNzZXRTaG91bGRCZUVsaW1pbmF0ZWQiEGVsaW1pbmF0aW9uQ2hlY2siE2Jvb3N0aW5nQ29udHJhY3RQcm0iE2VtaXNzaW9uQ29udHJhY3RQcm0iFmFzc2V0c1N0b3JlQ29udHJhY3RQcm0iDGZlZUFtb3VudFBybSIMd3hBc3NldElkUHJtIhJ2b3RpbmdUaHJlc2hvbGRQcm0iEXZvdGluZ0R1cmF0aW9uUHJtIhh2b3RlQmVmb3JlRWxpbWluYXRpb25Qcm0iDnN0YXJ0SGVpZ2h0UHJtIgttYXhEZXB0aFBybSIGY2hlY2tzIgphc3NldEltYWdlIgRpbmZvIgdwYXltZW50IgZpc1RoaXMiHGFzc2V0c1N0b3JlQ3JlYXRlT3JVcGRhdGVJbnYiCmJ1cm5GZWVJbnYiD2FkZEFzc2V0QWN0aW9ucyIKbmV4dFBlcmlvZCIMdGFyZ2V0UGVyaW9kIgpjaGVja0Fzc2V0IgtjaGVja0hlaWdodCIOZ3d4QW1vdW50QXRFbmQiE2NoZWNrR3d4QW1vdW50QXRFbmQiDXZvdGVzTGlzdE5hbWUiDWNhbmNlbFZvdGVJbnYiD3VzZXJWb3RlQWN0aW9ucyIQdm90ZXNMaXN0QWN0aW9ucyINJHQwMTY3MjgxNjgyMiILY2hlY2tDYWxsZXIiDSR0MDE3NDUzMTc2MjYiAXIiFGFzc2V0VmVyaWZpZWRBY3Rpb25zIhlhc3NldHNTdG9yZVNldFZlcmlmaWVkSW52IgllbGltaW5hdGUiGWFzc2V0V2FzRWxpbWluYXRlZEFjdGlvbnMiEXZvdGVSZXN1bHRBY3Rpb25zIhBvbkVsaW1pbmF0aW9uSW52IhpsYXRlc3RQcm9jZXNzZWRBc3NldE9yVW5pdCIZbGF0ZXN0UHJvY2Vzc2VkVXNlck9yVW5pdCIPbmV4dFBlcmlvZERlbGF5IgZmaW5pc2giEGFzc2V0c0hlYWRPclVuaXQiBWFzc2V0IhJwcm9jZXNzVm90ZUFjdGlvbnMiFGxhdGVzdFByb2Nlc3NlZEFzc2V0Igthc3NldE9yVW5pdCIQZmluYWxpemVBc3NldEludiITbGF0ZXN0UHJvY2Vzc2VkVXNlciIQcmVtb3ZlTGF0ZXN0VXNlciINZGVsZXRlVXNlckludiIHY291bnRlciIGcmVzdWx0IgNpbnYiGHZvdGVzVHJhbnNmZXJGaW5pc2hlZEtleSIVdm90ZXNUcmFuc2ZlckZpbmlzaGVkIgxuZXdUaHJlc2hvbGQiBm5ld0ZlZSICdHgiBnZlcmlmeSIPdGFyZ2V0UHVibGljS2V5RQABYQICX18AAWIACgEBYwEBZAQBZQUBZAMJAAECBQFlAgNJbnQEAWYFAWUFAWYJAAIBAhtGYWlsZWQgdG8gY2FzdCBpbnRvIEludGVnZXIBAWcBAWQEAWUFAWQDCQABAgUBZQIHQm9vbGVhbgQBaAUBZQUBaAkAAgECG0ZhaWxlZCB0byBjYXN0IGludG8gQm9vbGVhbgABaQkAuQkCCQDMCAICAiVzCQDMCAICA2ZlZQUDbmlsBQFhAAFqCQC5CQIJAMwIAgICJXMJAMwIAgIJd3hBc3NldElkBQNuaWwFAWEAAWsJALkJAgkAzAgCAgIlcwkAzAgCAg92b3RpbmdUaHJlc2hvbGQFA25pbAUBYQABbAkAuQkCCQDMCAICAiVzCQDMCAICC2Vwb2NoTGVuZ3RoBQNuaWwFAWEAAW0JALkJAgkAzAgCAgIlcwkAzAgCAhV2b3RlQmVmb3JlRWxpbWluYXRpb24FA25pbAUBYQABbgkAuQkCCQDMCAICAiVzCQDMCAICGGN1cnJlbnRWb3RpbmdIZWlnaHRTdGFydAUDbmlsBQFhAAFvCQC5CQIJAMwIAgICJXMJAMwIAgIMY3VycmVudEVwb2NoBQNuaWwFAWEAAXAJALkJAgkAzAgCAgIlcwkAzAgCAhBib29zdGluZ0NvbnRyYWN0BQNuaWwFAWEAAXEJALkJAgkAzAgCAgIlcwkAzAgCAhBlbWlzc2lvbkNvbnRyYWN0BQNuaWwFAWEAAXIJALkJAgkAzAgCAgIlcwkAzAgCAhNhc3NldHNTdG9yZUNvbnRyYWN0BQNuaWwFAWEAAXMJALkJAgkAzAgCAgIlcwkAzAgCAhRsYXRlc3RQcm9jZXNzZWRBc3NldAUDbmlsBQFhAAF0CQC5CQIJAMwIAgICJXMJAMwIAgITbGF0ZXN0UHJvY2Vzc2VkVXNlcgUDbmlsBQFhAAF1CQC5CQIJAMwIAgICJXMJAMwIAgIZbGF0ZXN0UHJvY2Vzc2VkVXNlclJlbW92ZQUDbmlsBQFhAAF2CQC5CQIJAMwIAgICJXMJAMwIAgIcbGF0ZXN0UHJvY2Vzc2VkQXNzZXRUcmFuc2ZlcgUDbmlsBQFhAAF3CQC5CQIJAMwIAgICJXMJAMwIAgIbbGF0ZXN0UHJvY2Vzc2VkVXNlclRyYW5zZmVyBQNuaWwFAWEAAXgJALkJAgkAzAgCAgIlcwkAzAgCAiFsYXRlc3RQcm9jZXNzZWRVc2VyUmVtb3ZlVHJhbnNmZXIFA25pbAUBYQABeQkAuQkCCQDMCAICAiVzCQDMCAICCG1heERlcHRoBQNuaWwFAWEBAXoBAUEJALkJAgkAzAgCAgIlcwkAzAgCAhV2b3Rlc1RyYW5zZmVyRmluaXNoZWQJAMwIAgkApAMBBQFBBQNuaWwFAWEAAUICCF9fYXNzZXRzAQFDAQFECQCsAgICCyVzX192b3Rlc19fBQFEAQFFAQFGCQC5CQIJAMwIAgkArAICAgQlcyVzBQFGCQDMCAICBGhlYWQFA25pbAUBYQEBRwEBRgkAuQkCCQDMCAIJAKwCAgIEJXMlcwUBRgkAzAgCAgRzaXplBQNuaWwFAWEBAUgCAUYBSQkAuQkCCQDMCAIJAKwCAgIGJXMlcyVzBQFGCQDMCAIFAUkJAMwIAgIEcHJldgUDbmlsBQFhAQFKAgFGAUkJALkJAgkAzAgCCQCsAgICBiVzJXMlcwUBRgkAzAgCBQFJCQDMCAICBG5leHQFA25pbAUBYQEBSwIBRAFBCQC5CQIJAMwIAgIGJXMlZCVzCQDMCAICCnZlcmlmaWVkQXQJAMwIAgkApAMBBQFBCQDMCAIFAUQFA25pbAUBYQEBTAEBRAkAuQkCCQDMCAICBCVzJXMJAMwIAgIIdmVyaWZpZWQJAMwIAgUBRAUDbmlsBQFhAQFNAgFEAUEJALkJAgkAzAgCAgYlcyVzJWQJAMwIAgIKZWxpbWluYXRlZAkAzAgCBQFECQDMCAIJAKQDAQUBQQUDbmlsBQFhAQFOAgFEAUEJALkJAgkAzAgCAgYlcyVkJXMJAMwIAgITdm90aW5nUmVzdWx0QXRBc3NldAkAzAgCCQCkAwEFAUEJAMwIAgUBRAUDbmlsBQFhAQFPAwFQAVEBUgkAuQkCCQDMCAICBiVkJWQlcwkAzAgCCQCkAwEFAVAJAMwIAgkApAMBBQFRCQDMCAIJAKUDAQUBUgUDbmlsBQFhAQFTAQFUBAFVCQC1CQIFAVQFAWEEAVYAAQQBVwACBAFYAAMEAVAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQFVBQFWBAFRCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUBVQUBVwQBUgMJAAACCQCQAwEFAVUABAkAAAIJAJEDAgUBVQUBWAIEdHJ1ZQcJAJUKAwUBUAUBUQUBUgEBWQMBWgFEAUEJALkJAgkAzAgCAgglcyVkJXMlcwkAzAgCAgN2cnUJAMwIAgkApAMBBQFBCQDMCAIFAUQJAMwIAgUBWgUDbmlsBQFhAQJhYQICYWICYWMEAVADBQJhYwUCYWIAAAQBUQMFAmFjAAAFAmFiCQC5CQIJAMwIAgIEJWQlZAkAzAgCCQCkAwEFAVAJAMwIAgkApAMBBQFRBQNuaWwFAWEBAmFkAQFUBAFVCQC1CQIFAVQFAWEEAVYAAQQBVwACBAFQCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUBVQUBVgQBUQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAVUFAVcEAmFjAwkAZgIFAVAAAAkAAAIFAVEAAAcEAmFlAwkAAAIFAVAAAAkAZgIFAVEAAAcEAmFmAwMFAmFjBgUCYWUGCQACAQIXSW52YWxpZCB1c2VyIHZvdGUgdmFsdWUDCQAAAgUCYWYFAmFmBAJhYgMFAmFjBQFQBQFRCQCUCgIFAmFiBQJhYwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECYWcFAmFoAVoBRAJhaQFBCQC5CQIJAMwIAgIMJXMlcyVzJXMlcyVkCQDMCAICB2hpc3RvcnkJAMwIAgUCYWgJAMwIAgUBRAkAzAgCBQFaCQDMCAIFAmFpCQDMCAIJAKQDAQUBQQUDbmlsBQFhAQJhagACFyVzX19tYW5hZ2VyVmF1bHRBZGRyZXNzAQJhawACFCVzX19tYW5hZ2VyUHVibGljS2V5AQJhbAECYW0DCQAAAggFAmFtBmNhbGxlcgUEdGhpcwYJAAIBAhFQZXJtaXNzaW9uIGRlbmllZAECYW4BAmFvCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAmFvAAABAmFwAQJhbwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBHRoaXMFAmFvCQCsAgIFAmFvAg8gaXMgbm90IGRlZmluZWQBAmFxAQJhbwkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQJhbwIAAQJhcgECYW8JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQR0aGlzBQJhbwkArAICBQJhbwIPIGlzIG5vdCBkZWZpbmVkAAJhcwkBAmFwAQUBaQACYXQJANkEAQkBAmFyAQUBagACYXUJAQJhcAEFAWsAAmF2CQECYXABBQFsAAJhdwkBAmFwAQUBbQACYXgJAQJhcAEFAW4AAmF5CQECYXABBQFvAAJhegkBEUBleHRyTmF0aXZlKDEwNjIpAQkBAmFyAQUBcAACYUEJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQJhcgEFAXEAAmFCCQERQGV4dHJOYXRpdmUoMTA2MikBCQECYXIBBQFyAAJhQwkBC3ZhbHVlT3JFbHNlAgkAnwgBBQF5BQFiAAJhRAkAZAIFAmF4BQJhdgECYUUABAFlCQCiCAEJAQJhagADCQABAgUBZQIGU3RyaW5nBAJhRgUBZQkBEUBleHRyTmF0aXZlKDEwNjIpAQUCYUYFBHRoaXMBAmFHAAQCYUgJAQJhRQAEAWUJAJ0IAgUCYUgJAQJhawADCQABAgUBZQIGU3RyaW5nBAJhRgUBZQkA2QQBBQJhRgMJAAECBQFlAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IBAmFJAQJhbQQBZQkBAmFHAAMJAAECBQFlAgpCeXRlVmVjdG9yBAJhSgUBZQkAAAIIBQJhbQ9jYWxsZXJQdWJsaWNLZXkFAmFKAwkAAQIFAWUCBFVuaXQJAAACCAUCYW0GY2FsbGVyBQR0aGlzCQACAQILTWF0Y2ggZXJyb3IBAmFLAQJhbQMJAQJhSQEFAmFtBgkAAgECEXBlcm1pc3Npb24gZGVuaWVkAQJhTAIBWgJhTQQCYU4JAPwHBAUCYXoCIGdldFVzZXJHd3hBbW91bnRBdEhlaWdodFJFQURPTkxZCQDMCAIFAVoJAMwIAgUCYU0FA25pbAUDbmlsCQEBYwEFAmFOAQJhTwUBRAJhYgJhYwFBAVIEAmFQCQEBTgIFAUQFAUEEAmFRBAFlCQCiCAEFAmFQAwkAAQIFAWUCBlN0cmluZwQCYUYFAWUJAQFTAQUCYUYDCQABAgUBZQIEVW5pdAQCYVIJAKIIAQkBAU4CBQFECQBlAgUBQQABAwkAAQIFAmFSAgZTdHJpbmcEAmFGBQJhUgkAlQoDAAAAAAgJAQFTAQUCYUYCXzMDCQABAgUCYVICBFVuaXQJAJUKAwAAAAAHCQACAQILTWF0Y2ggZXJyb3IJAAIBAgtNYXRjaCBlcnJvcgQCYVMIBQJhUQJfMQQCYVQIBQJhUQJfMgQCYVUIBQJhUQJfMwkBC1N0cmluZ0VudHJ5AgUCYVAJAQFPAwkAZAIFAmFTAwUCYWMFAmFiAAAJAGQCBQJhVAMFAmFjAAAFAmFiAwkAAAIFAVIFBHVuaXQFAmFVCQEFdmFsdWUBBQFSAQJhVgIBRgFJBAJhVwkAnQgCBQR0aGlzCQEBRQEFAUYEAmFYCQCdCAIFBHRoaXMJAQFIAgUBRgUBSQQCYVkJAJ0IAgUEdGhpcwkBAUoCBQFGBQFJAwMJAAACBQFJBQJhVwYJAQIhPQIFAmFYBQR1bml0BgkBAiE9AgUCYVkFBHVuaXQBAmFaAgFGAUkEAmFXCQCdCAIFBHRoaXMJAQFFAQUBRgQCYmEJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBAUcBBQFGAAAEAmJiAwkBASEBCQECYVYCBQFGBQFJBgkAAgECC05vZGUgZXhpc3RzAwkAAAIFAmJiBQJiYgkAzggCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQFHAQUBRgkAZAIFAmJhAAEFA25pbAMJAQlpc0RlZmluZWQBBQJhVwkAzAgCCQELU3RyaW5nRW50cnkCCQEBSgIFAUYFAUkJAQV2YWx1ZQEFAmFXCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFIAgUBRgkBBXZhbHVlAQUCYVcFAUkFA25pbAUDbmlsCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFFAQUBRgUBSQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJiYwIBRgFJBAJhVwkAnQgCBQR0aGlzCQEBRQEFAUYEAmJhCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQFHAQUBRgAABAJhWAkAnQgCBQR0aGlzCQEBSAIFAUYFAUkEAmFZCQCdCAIFBHRoaXMJAQFKAgUBRgUBSQkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEBRwEFAUYJAGUCBQJiYQABBQNuaWwDAwkBCWlzRGVmaW5lZAEFAmFYCQEJaXNEZWZpbmVkAQUCYVkHCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFKAgUBRgkBBXZhbHVlAQUCYVgJAQV2YWx1ZQEFAmFZCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFIAgUBRgkBBXZhbHVlAQUCYVkJAQV2YWx1ZQEFAmFYCQDMCAIJAQtEZWxldGVFbnRyeQEJAQFIAgUBRgUBSQkAzAgCCQELRGVsZXRlRW50cnkBCQEBSgIFAUYFAUkFA25pbAMJAQlpc0RlZmluZWQBBQJhWQkAzAgCCQELU3RyaW5nRW50cnkCCQEBRQEFAUYJAQV2YWx1ZQEFAmFZCQDMCAIJAQtEZWxldGVFbnRyeQEJAQFKAgUBRgUBSQkAzAgCCQELRGVsZXRlRW50cnkBCQEBSAIFAUYJAQV2YWx1ZQEFAmFZBQNuaWwDCQEJaXNEZWZpbmVkAQUCYVgJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBAUgCBQFGBQFJCQDMCAIJAQtEZWxldGVFbnRyeQEJAQFKAgUBRgkBBXZhbHVlAQUCYVgFA25pbAMJAAACBQFJBQJhVwkAzAgCCQELRGVsZXRlRW50cnkBCQEBRQEFAUYFA25pbAkAAgECDEludmFsaWQgbm9kZQECYmQFAUQCYmUCYmYCYmcCYmgEAmJpCQELU3RyaW5nRW50cnkCBQJiZgUBRAQCYmoJAQtEZWxldGVFbnRyeQEFAmJnAwkAAAIFAmJlBQR1bml0CQDMCAIFAmJpCQDMCAIFAmJqBQNuaWwEAVoJAQV2YWx1ZQEFAmJlBAJiawkBC1N0cmluZ0VudHJ5AgUCYmcFAVoEAmJsCQEBWQMFAVoFAUQFAmF5BAJibQkAoggBBQJibAQCYm4DCQAAAgUCYm0FBHVuaXQEAmJvCQECYUwCBQFaBQJhRAMJAAACBQJibwAACQDMCAIJAQxCb29sZWFuRW50cnkCBQJiaAYFA25pbAQCYnAJAGUCBQJheQABBAJicQkBC3ZhbHVlT3JFbHNlAgkAoAgBCQEBTQIFAUQFAmJwBwQCYnIDBQJicQUEdW5pdAkAoggBCQEBWQMFAVoFAUQFAmJwAwkAAAIFAmJyBQR1bml0BQNuaWwEAmJzCQECYWQBCQEFdmFsdWUBBQJicgQCYnQIBQJicwJfMQQCYWMIBQJicwJfMgQCYWIJAJcDAQkAzAgCBQJidAkAzAgCBQJibwUDbmlsCQDMCAIJAQtTdHJpbmdFbnRyeQIFAmJsCQECYWECBQJhYgUCYWMJAMwIAgkBAmFPBQUBRAUCYWIFAmFjBQJheQUEdW5pdAUDbmlsBQNuaWwJAM0IAgkAzQgCBQJibgUCYmkFAmJrAQJidQIBRAFBCQEBIQEJAQt2YWx1ZU9yRWxzZQIJAKAIAQkBAUsCBQFEBQFBBgECYnYBAUQDAwkBAmJ1AgUBRAkAZQIFAmF5AAEJAQJidQIFAUQJAGUCBQJheQACBwkBAmJ1AgUBRAkAZQIFAmF5AAMHDwJhbQELY29uc3RydWN0b3IKAmJ3AmJ4AmJ5AmJ6AmJBAmJCAmJDAmJEAmJFAmJGBAJiRwkAzAgCCQECYUsBBQJhbQkAzAgCAwkBCWlzRGVmaW5lZAEJAKYIAQUCYncGCQACAQIhSW52YWxpZCBib29zdGluZyBjb250cmFjdCBhZGRyZXNzCQDMCAIDCQEJaXNEZWZpbmVkAQkApggBBQJieAYJAAIBAiFJbnZhbGlkIGVtaXNzaW9uIGNvbnRyYWN0IGFkZHJlc3MJAMwIAgMJAQlpc0RlZmluZWQBCQCmCAEFAmJ5BgkAAgECJEludmFsaWQgYXNzZXRfc3RvcmUgY29udHJhY3QgYWRkcmVzcwkAzAgCAwkAZwIFAmJ6AAAGCQACAQISSW52YWxpZCBmZWUgYW1vdW50CQDMCAIDCQEJaXNEZWZpbmVkAQkA7AcBCQDZBAEFAmJBBgkAAgECE0ludmFsaWQgV1ggYXNzZXQgSUQJAMwIAgMJAGcCBQJiQgAABgkAAgECGEludmFsaWQgdm90aW5nIHRocmVzaG9sZAkAzAgCAwkAZgIFAmJDAAAGCQACAQIXSW52YWxpZCB2b3RpbmcgZHVyYXRpb24JAMwIAgMJAGYCCQBkAgUCYkUFAmJDBQZoZWlnaHQGCQACAQIUSW52YWxpZCBzdGFydCBoZWlnaHQFA25pbAMJAAACBQJiRwUCYkcJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQFwBQJidwkAzAgCCQELU3RyaW5nRW50cnkCBQFxBQJieAkAzAgCCQELU3RyaW5nRW50cnkCBQFyBQJieQkAzAgCCQEMSW50ZWdlckVudHJ5AgUBaQUCYnoJAMwIAgkBC1N0cmluZ0VudHJ5AgUBagUCYkEJAMwIAgkBDEludGVnZXJFbnRyeQIFAWsFAmJCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQFsBQJiQwkAzAgCCQEMSW50ZWdlckVudHJ5AgUBbQUCYkQJAMwIAgkBDEludGVnZXJFbnRyeQIFAW4FAmJFCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQFvAAAJAMwIAgkBDEludGVnZXJFbnRyeQIFAXkFAmJGBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYW0BB3N1Z2dlc3QCAUQCYkgEAmJJCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQkA2QQBBQFEAhBJbnZhbGlkIGFzc2V0IElEAwkAAAIFAmJJBQJiSQQCYkoJAQV2YWx1ZQEJAJEDAggFAmFtCHBheW1lbnRzAAAEAmJLCQAAAggFAmFtBmNhbGxlcgUEdGhpcwQCYkcJAMwIAgMDBQJiSwYJAAACCQEFdmFsdWUBCAUCYkoHYXNzZXRJZAUCYXQGCQACAQIRSW52YWxpZCBmZWUgYXNzZXQJAMwIAgMDBQJiSwYJAAACCAUCYkoGYW1vdW50BQJhcwYJAAIBAhJJbnZhbGlkIGZlZSBhbW91bnQFA25pbAMJAAACBQJiRwUCYkcEAmJMCQD8BwQFAmFCAg5jcmVhdGVPclVwZGF0ZQkAzAgCBQFECQDMCAIFAmJICQDMCAIHBQNuaWwFA25pbAMJAAACBQJiTAUCYkwEAmJNAwUCYksFBHVuaXQJAPwHBAUCYUECBGJ1cm4FA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AggFAmJKB2Fzc2V0SWQIBQJiSgZhbW91bnQFA25pbAMJAAACBQJiTQUCYk0EAmJOCQECYVoCBQFCBQFEBAJiTwkAZAIFAmF5AAEEAmJQAwkAZgIFAmFEBQZoZWlnaHQFAmF5BQJiTwkAlAoCCQDNCAIFAmJOCQECYU8FBQFEAAAGBQJiUAcFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYW0BBHZvdGUCAUQCYWMEAmJRAwkBAmFWAgUBQgUBRAYJAAIBAg1JbnZhbGlkIGFzc2V0AwkAAAIFAmJRBQJiUQQCYlIDCQBmAgUCYUQFBmhlaWdodAYJAAIBAjRDdXJyZW50IHZvdGluZyBpcyBvdmVyIGJ1dCByZXN1bHRzIGFyZSBub3QgZmluYWxpemVkAwkAAAIFAmJSBQJiUgQBWgkApQgBCAUCYW0GY2FsbGVyBAJiUwkBAmFMAgUBWgUCYUQEAmJUAwkAZgIFAmJTAAAGCQACAQIoWW91J2xsIG5vdCBoYXZlIGdXWCBhdCB0aGUgZW5kIG9mIHZvdGluZwMJAAACBQJiVAUCYlQEAmJVCQEBQwEFAUQEAmJsCQEBWQMFAVoFAUQFAmF5BAJibQkAoggBBQJibAQCYlYDCQAAAgUCYm0FBHVuaXQFBHVuaXQJAPwHBAUEdGhpcwIKY2FuY2VsVm90ZQkAzAgCBQFEBQNuaWwFA25pbAMJAAACBQJiVgUCYlYEAmJXCQDMCAIJAQtTdHJpbmdFbnRyeQIFAmJsCQECYWECBQJiUwUCYWMJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFnBQIEdm90ZQUBWgUBRAkA2AQBCAUCYW0NdHJhbnNhY3Rpb25JZAUCYXkJAQJhYQIFAmJTBQJhYwkAzAgCCQECYU8FBQFEBQJiUwUCYWMFAmF5BQR1bml0BQNuaWwEAmJYAwkBAmFWAgUCYlUFAVoFA25pbAkBAmFaAgUCYlUFAVoJAJQKAgkAzggCBQJiWAUCYlcFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYW0BCmNhbmNlbFZvdGUBAUQEAVoDCQAAAggFAmFtBmNhbGxlcgUEdGhpcwkApQgBCAUCYW0Mb3JpZ2luQ2FsbGVyCQClCAEIBQJhbQZjYWxsZXIEAmJVCQEBQwEFAUQEAmJsCQEBWQMFAVoFAUQFAmF5BAJibQkAoggBBQJibAQCYlkJAQJhZAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgUCYm0CEU5vdGhpbmcgdG8gY2FuY2VsBAJhYggFAmJZAl8xBAJhYwgFAmJZAl8yBAJiWAkBAmJjAgUCYlUFAVoEAmJXCQDMCAIJAQtEZWxldGVFbnRyeQEFAmJsCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhZwUCCmNhbmNlbFZvdGUFAVoFAUQJANgEAQgFAmFtDXRyYW5zYWN0aW9uSWQFAmF5CQECYWECAAAGCQDMCAIJAQJhTwUFAUQJAQEtAQUCYWIFAmFjBQJheQUEdW5pdAUDbmlsCQCUCgIJAM4IAgUCYlgFAmJXBQR1bml0AmFtARVmaW5hbGl6ZUFzc2V0SU5URVJOQUwCAUQBQQQCYloJAQJhbAEFAmFtAwkAAAIFAmJaBQJiWgQCYVAJAQFOAgUBRAUBQQQCY2EEAWUJAKIIAQUCYVADCQABAgUBZQIGU3RyaW5nBAJhRgUBZQQCY2IJAQFTAQUCYUYJAJQKAggFAmNiAl8xCAUCY2ICXzIDCQABAgUBZQIEVW5pdAkAlAoCAAAAAAkAAgECC01hdGNoIGVycm9yBAFQCAUCY2ECXzEEAVEIBQJjYQJfMgQCYWIJAGQCBQFQBQFRBAFSAwkAZwIFAmFiBQJhdQkAZgIFAVAFAVEHBAJjYwkAzAgCCQEMQm9vbGVhbkVudHJ5AgkBAUsCBQFEBQFBBQFSCQDMCAIDBQFSCQEMQm9vbGVhbkVudHJ5AgkBAUwBBQFEBgkBC0RlbGV0ZUVudHJ5AQkBAUwBBQFEBQNuaWwEAmNkCQD8BwQFAmFCAgtzZXRWZXJpZmllZAkAzAgCBQFECQDMCAIFAVIFA25pbAUDbmlsAwkAAAIFAmNkBQJjZAQCY2UDBQFSBwkBAmJ2AQUBRAQCY2YDBQJjZQkAzAgCCQEMQm9vbGVhbkVudHJ5AgkBAU0CBQFEBQJheQYFA25pbAUDbmlsBAJjZwMFAmNlBQNuaWwJAMwIAgkBAmFPBQUBRAAABgkAZAIFAmF5AAEFAVIFA25pbAQCYlgDBQJjZQkBAmJjAgUBQgUBRAUDbmlsBAJjaAMFAmNlCQD8BwQFAmFCAgtvbkVsaW1pbmF0ZQkAzAgCBQFEBQNuaWwFA25pbAUEdW5pdAMJAAACBQJjaAUCY2gJAJQKAgkAzggCCQDOCAIFAmJYBQJjZwUCY2MFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYW0BFmRlbGV0ZVVzZXJOb2RlSU5URVJOQUwDAUQBWgJiaAQCYloDCQAAAggFAmFtBmNhbGxlcgUEdGhpcwYJAQJhSwEFAmFtAwkAAAIFAmJaBQJiWgkAlAoCCQDNCAIJAQJiYwIJAQFDAQUBRAUBWgkBC0RlbGV0ZUVudHJ5AQUCYmgFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYW0BFGZpbmFsaXplVm90aW5nSGVscGVyAAMJAGYCBQJhRAUGaGVpZ2h0CQCUCgIFA25pbAcEAmNpCQCiCAEFAXMEAmNqCQCiCAEFAXQEAmNrAAAEAmNsCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIFAW4JAGQCBQZoZWlnaHQFAmNrCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQFvCQBkAgUCYXkAAQkAzAgCCQELRGVsZXRlRW50cnkBBQFzCQDMCAIJAQtEZWxldGVFbnRyeQEFAXQJAMwIAgkBC0RlbGV0ZUVudHJ5AQUBdgkAzAgCCQELRGVsZXRlRW50cnkBBQF3BQNuaWwGAwkAAAIFAmNpBQR1bml0BAJjbQkAoggBCQEBRQEFAUIDCQAAAgUCY20FBHVuaXQFAmNsBAJjbgkBBXZhbHVlAQUCY20EAmJlCQCiCAEJAQFFAQkBAUMBBQJjbgQCY28JAQJiZAUFAmNuBQJiZQUBcwUBdAUBdQkAlAoCBQJjbwYEAmNwCQEFdmFsdWUBBQJjaQMJAAACBQJjagUEdW5pdAQCY3EJAKIIAQkBAUoCBQFCBQJjcAMJAAACBQJjcQUCY3EEAmNyCQD8BwQFBHRoaXMCFWZpbmFsaXplQXNzZXRJTlRFUk5BTAkAzAgCBQJjcAkAzAgCBQJheQUDbmlsBQNuaWwDCQAAAgUCY3IFAmNyAwkAAAIFAmNxBQR1bml0BQJjbAQCY24JAQV2YWx1ZQEFAmNxBAJiZQkAoggBCQEBRQEJAQFDAQUCY24EAmNvCQECYmQFBQJjbgUCYmUFAXMFAXQFAXUJAJQKAgUCY28GCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBAJjcwkBBXZhbHVlAQUCY2oEAmJlCQCiCAEJAQFKAgkBAUMBBQJjcAUCY3MDCQAAAgUCYmUFAmJlBAJjdAkBC3ZhbHVlT3JFbHNlAgkAoAgBBQF1BwQCY3UDBQJjdAkA/AcEBQR0aGlzAhZkZWxldGVVc2VyTm9kZUlOVEVSTkFMCQDMCAIFAmNwCQDMCAIFAmNzCQDMCAIFAXUFA25pbAUDbmlsBQR1bml0AwkAAAIFAmN1BQJjdQQCY28JAQJiZAUFAmNwBQJiZQUBcwUBdAUBdQkAlAoCBQJjbwYJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYW0BFWZpbmFsaXplVm90aW5nV3JhcHBlcgECY3YEAmN3CQEBZwEJAPwHBAUEdGhpcwIUZmluYWxpemVWb3RpbmdIZWxwZXIFA25pbAUDbmlsAwkAAAIFAmN3BQJjdwMJAQEhAQUCY3cDCQAAAgUCY3YAAAkAAgECHkN1cnJlbnQgdm90aW5nIGlzIG5vdCBvdmVyIHlldAkAlAoCBQNuaWwFBHVuaXQDCQBmAgUCYUMFAmN2BAJjeAkA/AcEBQR0aGlzAhVmaW5hbGl6ZVZvdGluZ1dyYXBwZXIJAMwIAgkAZAIFAmN2AAEFA25pbAUDbmlsAwkAAAIFAmN4BQJjeAkAlAoCBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAJQKAgUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmFtAQ5maW5hbGl6ZVZvdGluZwAEAmN4CQD8BwQFBHRoaXMCFWZpbmFsaXplVm90aW5nV3JhcHBlcgkAzAgCAAAFA25pbAUDbmlsAwkAAAIFAmN4BQJjeAkAlAoCBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYW0BE3RyYW5zZmVyVm90ZXNIZWxwZXIABAJjeQkBAXoBBQJheQQCY3oJAQt2YWx1ZU9yRWxzZQIJAKAIAQUCY3kHAwMDCQBmAgUCYXgFBmhlaWdodAYJAGcCBQZoZWlnaHQFAmFEBgUCY3oJAJQKAgUDbmlsBwQCY2kJAKIIAQUBdgQCY2oJAKIIAQUBdwQCY2wJAJQKAgkAzAgCCQEMQm9vbGVhbkVudHJ5AgUCY3kGCQDMCAIJAQtEZWxldGVFbnRyeQEFAXYJAMwIAgkBC0RlbGV0ZUVudHJ5AQUBdwUDbmlsBgMJAAACBQJjaQUEdW5pdAQCY20JAKIIAQkBAUUBBQFCAwkAAAIFAmNtBQR1bml0BQJjbAQCY24JAQV2YWx1ZQEFAmNtBAJiZQkAoggBCQEBRQEJAQFDAQUCY24EAmNvCQECYmQFBQJjbgUCYmUFAXYFAXcFAXgJAJQKAgUCY28GBAJjcAkBBXZhbHVlAQUCY2kDCQAAAgUCY2oFBHVuaXQEAmNxCQCiCAEJAQFKAgUBQgUCY3ADCQAAAgUCY3EFBHVuaXQFAmNsBAJjbgkBBXZhbHVlAQUCY3EEAmJlCQCiCAEJAQFFAQkBAUMBBQJjbgQCY28JAQJiZAUFAmNuBQJiZQUBdgUBdwUBeAkAlAoCBQJjbwYEAmNzCQEFdmFsdWUBBQJjagQCYmUJAKIIAQkBAUoCCQEBQwEFAmNwBQJjcwMJAAACBQJiZQUCYmUEAmN0CQELdmFsdWVPckVsc2UCCQCgCAEFAXgHBAJjdQMFAmN0CQD8BwQFBHRoaXMCFmRlbGV0ZVVzZXJOb2RlSU5URVJOQUwJAMwIAgUCY3AJAMwIAgUCY3MJAMwIAgUBeAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUCY3UFAmN1BAJjbwkBAmJkBQUCY3AFAmJlBQF2BQF3BQF4CQCUCgIFAmNvBgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJhbQEUdHJhbnNmZXJWb3Rlc1dyYXBwZXIBAmN2BAJjdwkBAWcBCQD8BwQFBHRoaXMCE3RyYW5zZmVyVm90ZXNIZWxwZXIFA25pbAUDbmlsAwkAAAIFAmN3BQJjdwMJAQEhAQUCY3cDCQAAAgUCY3YAAAkAAgECGVZvdGluZyBpcyBub3Qgc3RhcnRlZCB5ZXQJAJQKAgUDbmlsBQR1bml0AwkAZgIFAmFDBQJjdgQCY3gJAPwHBAUEdGhpcwIUdHJhbnNmZXJWb3Rlc1dyYXBwZXIJAMwIAgkAZAIFAmN2AAEFA25pbAUDbmlsAwkAAAIFAmN4BQJjeAkAlAoCBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAJQKAgUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmFtAQ10cmFuc2ZlclZvdGVzAAQCY3gJAPwHBAUEdGhpcwIUdHJhbnNmZXJWb3Rlc1dyYXBwZXIJAMwIAgAABQNuaWwFA25pbAMJAAACBQJjeAUCY3gJAJQKAgUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAmFtARJzZXRWb3RpbmdUaHJlc2hvbGQBAmNBBAJiWgkBAmFLAQUCYW0DCQAAAgUCYloFAmJaCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIFAWsFAmNBBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CYW0BBnNldEZlZQECY0IEAmJaCQECYUsBBQJhbQMJAAACBQJiWgUCYloJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUBaQUCY0IFA25pbAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgJhbQEbZ3d4QXZhaWxhYmxlRm9yVm90ZVJFQURPTkxZAQFaBAJiUwkBAmFMAgUBWgUCYUQJAJQKAgUDbmlsBQJiUwECY0MBAmNEAAQCY0UEAWUJAQJhRwADCQABAgUBZQIKQnl0ZVZlY3RvcgQCYUoFAWUFAmFKAwkAAQIFAWUCBFVuaXQIBQJjQw9zZW5kZXJQdWJsaWNLZXkJAAIBAgtNYXRjaCBlcnJvcgkA9AMDCAUCY0MJYm9keUJ5dGVzCQCRAwIIBQJjQwZwcm9vZnMAAAUCY0VLmVyU", "height": 2603601, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 2zTE5yjR7CZtFePtK8QX2916EaGdb6DGdEKc8Dmz1vLr Next: none Diff:
OldNewDifferences
548548
549549 @Callable(i)
550550 func deleteUserNodeINTERNAL (assetId,userAddress,latestProcessedUserRemoveKey) = {
551- let checkCaller = mustManager(i)
551+ let checkCaller = if ((i.caller == this))
552+ then true
553+ else mustManager(i)
552554 if ((checkCaller == checkCaller))
553555 then $Tuple2((deleteNode(getVotesListName(assetId), userAddress) :+ DeleteEntry(latestProcessedUserRemoveKey)), unit)
554556 else throw("Strict value is not equal to itself.")
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let separator = "__"
55
66 let maxDepthDefault = 10
77
88 func asInt (val) = match val {
99 case valInt: Int =>
1010 valInt
1111 case _ =>
1212 throw("Failed to cast into Integer")
1313 }
1414
1515
1616 func asBool (val) = match val {
1717 case valBool: Boolean =>
1818 valBool
1919 case _ =>
2020 throw("Failed to cast into Boolean")
2121 }
2222
2323
2424 let keyFeeAmount = makeString(["%s", "fee"], separator)
2525
2626 let keyWxAssetId = makeString(["%s", "wxAssetId"], separator)
2727
2828 let keyVotingThreshold = makeString(["%s", "votingThreshold"], separator)
2929
3030 let keyVotingDuration = makeString(["%s", "epochLength"], separator)
3131
3232 let keyVoteBeforeElimination = makeString(["%s", "voteBeforeElimination"], separator)
3333
3434 let keyStartHeight = makeString(["%s", "currentVotingHeightStart"], separator)
3535
3636 let keyCurrentPeriod = makeString(["%s", "currentEpoch"], separator)
3737
3838 let keyBoostingContract = makeString(["%s", "boostingContract"], separator)
3939
4040 let keyEmissionContract = makeString(["%s", "emissionContract"], separator)
4141
4242 let keyAssetsStoreContract = makeString(["%s", "assetsStoreContract"], separator)
4343
4444 let keyLatestProcessedAsset = makeString(["%s", "latestProcessedAsset"], separator)
4545
4646 let keyLatestProcessedUser = makeString(["%s", "latestProcessedUser"], separator)
4747
4848 let keyLatestProcessedUserRemove = makeString(["%s", "latestProcessedUserRemove"], separator)
4949
5050 let keyLatestProcessedAssetTransfer = makeString(["%s", "latestProcessedAssetTransfer"], separator)
5151
5252 let keyLatestProcessedUserTransfer = makeString(["%s", "latestProcessedUserTransfer"], separator)
5353
5454 let keyLatestProcessedUserRemoveTransfer = makeString(["%s", "latestProcessedUserRemoveTransfer"], separator)
5555
5656 let keyMaxDepth = makeString(["%s", "maxDepth"], separator)
5757
5858 func keyVotesTransferFinishedByPeriod (period) = makeString(["%s", "votesTransferFinished", toString(period)], separator)
5959
6060
6161 let assetsListName = "__assets"
6262
6363 func getVotesListName (assetId) = ("%s__votes__" + assetId)
6464
6565
6666 func keyListHead (listName) = makeString([("%s%s" + listName), "head"], separator)
6767
6868
6969 func keyListSize (listName) = makeString([("%s%s" + listName), "size"], separator)
7070
7171
7272 func keyListPrev (listName,id) = makeString([("%s%s%s" + listName), id, "prev"], separator)
7373
7474
7575 func keyListNext (listName,id) = makeString([("%s%s%s" + listName), id, "next"], separator)
7676
7777
7878 func keyAssetVerifiedByPeriod (assetId,period) = makeString(["%s%d%s", "verifiedAt", toString(period), assetId], separator)
7979
8080
8181 func keyAssetVerified (assetId) = makeString(["%s%s", "verified", assetId], separator)
8282
8383
8484 func keyAssetWasEliminated (assetId,period) = makeString(["%s%s%d", "eliminated", assetId, toString(period)], separator)
8585
8686
8787 func keyVoteResultByPeriod (assetId,period) = makeString(["%s%d%s", "votingResultAtAsset", toString(period), assetId], separator)
8888
8989
9090 func formatVoteResult (totalYes,totalNo,verified) = makeString(["%d%d%s", toString(totalYes), toString(totalNo), toString(verified)], separator)
9191
9292
9393 func parseVoteResult (input) = {
9494 let parts = split(input, separator)
9595 let totalYesIdx = 1
9696 let totalNoIdx = 2
9797 let verifiedIdx = 3
9898 let totalYes = parseIntValue(parts[totalYesIdx])
9999 let totalNo = parseIntValue(parts[totalNoIdx])
100100 let verified = if ((size(parts) == 4))
101101 then (parts[verifiedIdx] == "true")
102102 else false
103103 $Tuple3(totalYes, totalNo, verified)
104104 }
105105
106106
107107 func keyUserVoteByPeriod (userAddress,assetId,period) = makeString(["%s%d%s%s", "vru", toString(period), assetId, userAddress], separator)
108108
109109
110110 func formatUserVote (total,inFavor) = {
111111 let totalYes = if (inFavor)
112112 then total
113113 else 0
114114 let totalNo = if (inFavor)
115115 then 0
116116 else total
117117 makeString(["%d%d", toString(totalYes), toString(totalNo)], separator)
118118 }
119119
120120
121121 func parseUserVote (input) = {
122122 let parts = split(input, separator)
123123 let totalYesIdx = 1
124124 let totalNoIdx = 2
125125 let totalYes = parseIntValue(parts[totalYesIdx])
126126 let totalNo = parseIntValue(parts[totalNoIdx])
127127 let inFavor = if ((totalYes > 0))
128128 then (totalNo == 0)
129129 else false
130130 let against = if ((totalYes == 0))
131131 then (totalNo > 0)
132132 else false
133133 let checkTotals = if (if (inFavor)
134134 then true
135135 else against)
136136 then true
137137 else throw("Invalid user vote value")
138138 if ((checkTotals == checkTotals))
139139 then {
140140 let total = if (inFavor)
141141 then totalYes
142142 else totalNo
143143 $Tuple2(total, inFavor)
144144 }
145145 else throw("Strict value is not equal to itself.")
146146 }
147147
148148
149149 func keyUserVoteHistory (type,userAddress,assetId,txId,period) = makeString(["%s%s%s%s%s%d", "history", type, assetId, userAddress, txId, toString(period)], separator)
150150
151151
152152 func keyManagerVaultAddress () = "%s__managerVaultAddress"
153153
154154
155155 func keyManagerPublicKey () = "%s__managerPublicKey"
156156
157157
158158 func thisOnly (i) = if ((i.caller == this))
159159 then true
160160 else throw("Permission denied")
161161
162162
163163 func getIntegerOrZero (key) = valueOrElse(getInteger(this, key), 0)
164164
165165
166166 func getIntegerOrFail (key) = valueOrErrorMessage(getInteger(this, key), (key + " is not defined"))
167167
168168
169169 func getStringOrEmpty (key) = valueOrElse(getString(this, key), "")
170170
171171
172172 func getStringOrFail (key) = valueOrErrorMessage(getString(this, key), (key + " is not defined"))
173173
174174
175175 let feeAmount = getIntegerOrFail(keyFeeAmount)
176176
177177 let wxAssetId = fromBase58String(getStringOrFail(keyWxAssetId))
178178
179179 let votingThreshold = getIntegerOrFail(keyVotingThreshold)
180180
181181 let votingDuration = getIntegerOrFail(keyVotingDuration)
182182
183183 let voteBeforeElimination = getIntegerOrFail(keyVoteBeforeElimination)
184184
185185 let startHeight = getIntegerOrFail(keyStartHeight)
186186
187187 let currentPeriod = getIntegerOrFail(keyCurrentPeriod)
188188
189189 let boostingContract = addressFromStringValue(getStringOrFail(keyBoostingContract))
190190
191191 let emissionContract = addressFromStringValue(getStringOrFail(keyEmissionContract))
192192
193193 let assetsStoreContract = addressFromStringValue(getStringOrFail(keyAssetsStoreContract))
194194
195195 let maxDepth = valueOrElse(getInteger(keyMaxDepth), maxDepthDefault)
196196
197197 let endHeight = (startHeight + votingDuration)
198198
199199 func getManagerVaultAddressOrThis () = match getString(keyManagerVaultAddress()) {
200200 case s: String =>
201201 addressFromStringValue(s)
202202 case _ =>
203203 this
204204 }
205205
206206
207207 func managerPublicKeyOrUnit () = {
208208 let managerVaultAddress = getManagerVaultAddressOrThis()
209209 match getString(managerVaultAddress, keyManagerPublicKey()) {
210210 case s: String =>
211211 fromBase58String(s)
212212 case _: Unit =>
213213 unit
214214 case _ =>
215215 throw("Match error")
216216 }
217217 }
218218
219219
220220 func isManager (i) = match managerPublicKeyOrUnit() {
221221 case pk: ByteVector =>
222222 (i.callerPublicKey == pk)
223223 case _: Unit =>
224224 (i.caller == this)
225225 case _ =>
226226 throw("Match error")
227227 }
228228
229229
230230 func mustManager (i) = if (isManager(i))
231231 then true
232232 else throw("permission denied")
233233
234234
235235 func getUserGwxAmountAtHeight (userAddress,targetHeight) = {
236236 let gwxAmount = invoke(boostingContract, "getUserGwxAmountAtHeightREADONLY", [userAddress, targetHeight], nil)
237237 asInt(gwxAmount)
238238 }
239239
240240
241241 func getVoteResultAction (assetId,total,inFavor,period,verified) = {
242242 let voteResultKey = keyVoteResultByPeriod(assetId, period)
243243 let $t069157218 = match getString(voteResultKey) {
244244 case s: String =>
245245 parseVoteResult(s)
246246 case _: Unit =>
247247 match getString(keyVoteResultByPeriod(assetId, (period - 1))) {
248248 case s: String =>
249249 $Tuple3(0, 0, parseVoteResult(s)._3)
250250 case _: Unit =>
251251 $Tuple3(0, 0, false)
252252 case _ =>
253253 throw("Match error")
254254 }
255255 case _ =>
256256 throw("Match error")
257257 }
258258 let oldTotalYes = $t069157218._1
259259 let oldTotalNo = $t069157218._2
260260 let oldVerified = $t069157218._3
261261 StringEntry(voteResultKey, formatVoteResult((oldTotalYes + (if (inFavor)
262262 then total
263263 else 0)), (oldTotalNo + (if (inFavor)
264264 then 0
265265 else total)), if ((verified == unit))
266266 then oldVerified
267267 else value(verified)))
268268 }
269269
270270
271271 func containsNode (listName,id) = {
272272 let head = getString(this, keyListHead(listName))
273273 let prev = getString(this, keyListPrev(listName, id))
274274 let next = getString(this, keyListNext(listName, id))
275275 if (if ((id == head))
276276 then true
277277 else (prev != unit))
278278 then true
279279 else (next != unit)
280280 }
281281
282282
283283 func insertNode (listName,id) = {
284284 let head = getString(this, keyListHead(listName))
285285 let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
286286 let checkNode = if (!(containsNode(listName, id)))
287287 then true
288288 else throw("Node exists")
289289 if ((checkNode == checkNode))
290290 then (([IntegerEntry(keyListSize(listName), (listSize + 1))] ++ (if (isDefined(head))
291291 then [StringEntry(keyListNext(listName, id), value(head)), StringEntry(keyListPrev(listName, value(head)), id)]
292292 else nil)) ++ [StringEntry(keyListHead(listName), id)])
293293 else throw("Strict value is not equal to itself.")
294294 }
295295
296296
297297 func deleteNode (listName,id) = {
298298 let head = getString(this, keyListHead(listName))
299299 let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
300300 let prev = getString(this, keyListPrev(listName, id))
301301 let next = getString(this, keyListNext(listName, id))
302302 ([IntegerEntry(keyListSize(listName), (listSize - 1))] ++ (if (if (isDefined(prev))
303303 then isDefined(next)
304304 else false)
305305 then [StringEntry(keyListNext(listName, value(prev)), value(next)), StringEntry(keyListPrev(listName, value(next)), value(prev)), DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, id))]
306306 else if (isDefined(next))
307307 then [StringEntry(keyListHead(listName), value(next)), DeleteEntry(keyListNext(listName, id)), DeleteEntry(keyListPrev(listName, value(next)))]
308308 else if (isDefined(prev))
309309 then [DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, value(prev)))]
310310 else if ((id == head))
311311 then [DeleteEntry(keyListHead(listName))]
312312 else throw("Invalid node")))
313313 }
314314
315315
316316 func processVote (assetId,userAddressOrUnit,latestProcessedAssetKey,latestProcessedUserKey,latestProcessedUserRemoveKey) = {
317317 let updateLatestProcessedAssetAction = StringEntry(latestProcessedAssetKey, assetId)
318318 let deleteLatestProcessedUserAction = DeleteEntry(latestProcessedUserKey)
319319 if ((userAddressOrUnit == unit))
320320 then [updateLatestProcessedAssetAction, deleteLatestProcessedUserAction]
321321 else {
322322 let userAddress = value(userAddressOrUnit)
323323 let updateLatestProcessedUserAction = StringEntry(latestProcessedUserKey, userAddress)
324324 let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod)
325325 let userVoteOrUnit = getString(userVoteKey)
326326 let voteActions = if ((userVoteOrUnit == unit))
327327 then {
328328 let userGwxAmountAtEndHeight = getUserGwxAmountAtHeight(userAddress, endHeight)
329329 if ((userGwxAmountAtEndHeight == 0))
330330 then [BooleanEntry(latestProcessedUserRemoveKey, true)]
331331 else {
332332 let previousPeriod = (currentPeriod - 1)
333333 let assetWasEliminated = valueOrElse(getBoolean(keyAssetWasEliminated(assetId, previousPeriod)), false)
334334 let userPreviousVoteOrUnit = if (assetWasEliminated)
335335 then unit
336336 else getString(keyUserVoteByPeriod(userAddress, assetId, previousPeriod))
337337 if ((userPreviousVoteOrUnit == unit))
338338 then nil
339339 else {
340340 let $t01132911402 = parseUserVote(value(userPreviousVoteOrUnit))
341341 let prevTotal = $t01132911402._1
342342 let inFavor = $t01132911402._2
343343 let total = min([prevTotal, userGwxAmountAtEndHeight])
344344 [StringEntry(userVoteKey, formatUserVote(total, inFavor)), getVoteResultAction(assetId, total, inFavor, currentPeriod, unit)]
345345 }
346346 }
347347 }
348348 else nil
349349 ((voteActions :+ updateLatestProcessedAssetAction) :+ updateLatestProcessedUserAction)
350350 }
351351 }
352352
353353
354354 func assetShouldBeEliminated (assetId,period) = !(valueOrElse(getBoolean(keyAssetVerifiedByPeriod(assetId, period)), true))
355355
356356
357357 func eliminationCheck (assetId) = if (if (assetShouldBeEliminated(assetId, (currentPeriod - 1)))
358358 then assetShouldBeEliminated(assetId, (currentPeriod - 2))
359359 else false)
360360 then assetShouldBeEliminated(assetId, (currentPeriod - 3))
361361 else false
362362
363363
364364 @Callable(i)
365365 func constructor (boostingContractPrm,emissionContractPrm,assetsStoreContractPrm,feeAmountPrm,wxAssetIdPrm,votingThresholdPrm,votingDurationPrm,voteBeforeEliminationPrm,startHeightPrm,maxDepthPrm) = {
366366 let checks = [mustManager(i), if (isDefined(addressFromString(boostingContractPrm)))
367367 then true
368368 else throw("Invalid boosting contract address"), if (isDefined(addressFromString(emissionContractPrm)))
369369 then true
370370 else throw("Invalid emission contract address"), if (isDefined(addressFromString(assetsStoreContractPrm)))
371371 then true
372372 else throw("Invalid asset_store contract address"), if ((feeAmountPrm >= 0))
373373 then true
374374 else throw("Invalid fee amount"), if (isDefined(assetInfo(fromBase58String(wxAssetIdPrm))))
375375 then true
376376 else throw("Invalid WX asset ID"), if ((votingThresholdPrm >= 0))
377377 then true
378378 else throw("Invalid voting threshold"), if ((votingDurationPrm > 0))
379379 then true
380380 else throw("Invalid voting duration"), if (((startHeightPrm + votingDurationPrm) > height))
381381 then true
382382 else throw("Invalid start height")]
383383 if ((checks == checks))
384384 then $Tuple2([StringEntry(keyBoostingContract, boostingContractPrm), StringEntry(keyEmissionContract, emissionContractPrm), StringEntry(keyAssetsStoreContract, assetsStoreContractPrm), IntegerEntry(keyFeeAmount, feeAmountPrm), StringEntry(keyWxAssetId, wxAssetIdPrm), IntegerEntry(keyVotingThreshold, votingThresholdPrm), IntegerEntry(keyVotingDuration, votingDurationPrm), IntegerEntry(keyVoteBeforeElimination, voteBeforeEliminationPrm), IntegerEntry(keyStartHeight, startHeightPrm), IntegerEntry(keyCurrentPeriod, 0), IntegerEntry(keyMaxDepth, maxDepthPrm)], unit)
385385 else throw("Strict value is not equal to itself.")
386386 }
387387
388388
389389
390390 @Callable(i)
391391 func suggest (assetId,assetImage) = {
392392 let info = valueOrErrorMessage(assetInfo(fromBase58String(assetId)), "Invalid asset ID")
393393 if ((info == info))
394394 then {
395395 let payment = value(i.payments[0])
396396 let isThis = (i.caller == this)
397397 let checks = [if (if (isThis)
398398 then true
399399 else (value(payment.assetId) == wxAssetId))
400400 then true
401401 else throw("Invalid fee asset"), if (if (isThis)
402402 then true
403403 else (payment.amount == feeAmount))
404404 then true
405405 else throw("Invalid fee amount")]
406406 if ((checks == checks))
407407 then {
408408 let assetsStoreCreateOrUpdateInv = invoke(assetsStoreContract, "createOrUpdate", [assetId, assetImage, false], nil)
409409 if ((assetsStoreCreateOrUpdateInv == assetsStoreCreateOrUpdateInv))
410410 then {
411411 let burnFeeInv = if (isThis)
412412 then unit
413413 else invoke(emissionContract, "burn", nil, [AttachedPayment(payment.assetId, payment.amount)])
414414 if ((burnFeeInv == burnFeeInv))
415415 then {
416416 let addAssetActions = insertNode(assetsListName, assetId)
417417 let nextPeriod = (currentPeriod + 1)
418418 let targetPeriod = if ((endHeight > height))
419419 then currentPeriod
420420 else nextPeriod
421421 $Tuple2((addAssetActions :+ getVoteResultAction(assetId, 0, true, targetPeriod, false)), unit)
422422 }
423423 else throw("Strict value is not equal to itself.")
424424 }
425425 else throw("Strict value is not equal to itself.")
426426 }
427427 else throw("Strict value is not equal to itself.")
428428 }
429429 else throw("Strict value is not equal to itself.")
430430 }
431431
432432
433433
434434 @Callable(i)
435435 func vote (assetId,inFavor) = {
436436 let checkAsset = if (containsNode(assetsListName, assetId))
437437 then true
438438 else throw("Invalid asset")
439439 if ((checkAsset == checkAsset))
440440 then {
441441 let checkHeight = if ((endHeight > height))
442442 then true
443443 else throw("Current voting is over but results are not finalized")
444444 if ((checkHeight == checkHeight))
445445 then {
446446 let userAddress = toString(i.caller)
447447 let gwxAmountAtEnd = getUserGwxAmountAtHeight(userAddress, endHeight)
448448 let checkGwxAmountAtEnd = if ((gwxAmountAtEnd > 0))
449449 then true
450450 else throw("You'll not have gWX at the end of voting")
451451 if ((checkGwxAmountAtEnd == checkGwxAmountAtEnd))
452452 then {
453453 let votesListName = getVotesListName(assetId)
454454 let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod)
455455 let userVoteOrUnit = getString(userVoteKey)
456456 let cancelVoteInv = if ((userVoteOrUnit == unit))
457457 then unit
458458 else invoke(this, "cancelVote", [assetId], nil)
459459 if ((cancelVoteInv == cancelVoteInv))
460460 then {
461461 let userVoteActions = [StringEntry(userVoteKey, formatUserVote(gwxAmountAtEnd, inFavor)), StringEntry(keyUserVoteHistory("vote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(gwxAmountAtEnd, inFavor)), getVoteResultAction(assetId, gwxAmountAtEnd, inFavor, currentPeriod, unit)]
462462 let votesListActions = if (containsNode(votesListName, userAddress))
463463 then nil
464464 else insertNode(votesListName, userAddress)
465465 $Tuple2((votesListActions ++ userVoteActions), unit)
466466 }
467467 else throw("Strict value is not equal to itself.")
468468 }
469469 else throw("Strict value is not equal to itself.")
470470 }
471471 else throw("Strict value is not equal to itself.")
472472 }
473473 else throw("Strict value is not equal to itself.")
474474 }
475475
476476
477477
478478 @Callable(i)
479479 func cancelVote (assetId) = {
480480 let userAddress = if ((i.caller == this))
481481 then toString(i.originCaller)
482482 else toString(i.caller)
483483 let votesListName = getVotesListName(assetId)
484484 let userVoteKey = keyUserVoteByPeriod(userAddress, assetId, currentPeriod)
485485 let userVoteOrUnit = getString(userVoteKey)
486486 let $t01672816822 = parseUserVote(valueOrErrorMessage(userVoteOrUnit, "Nothing to cancel"))
487487 let total = $t01672816822._1
488488 let inFavor = $t01672816822._2
489489 let votesListActions = deleteNode(votesListName, userAddress)
490490 let userVoteActions = [DeleteEntry(userVoteKey), StringEntry(keyUserVoteHistory("cancelVote", userAddress, assetId, toBase58String(i.transactionId), currentPeriod), formatUserVote(0, true)), getVoteResultAction(assetId, -(total), inFavor, currentPeriod, unit)]
491491 $Tuple2((votesListActions ++ userVoteActions), unit)
492492 }
493493
494494
495495
496496 @Callable(i)
497497 func finalizeAssetINTERNAL (assetId,period) = {
498498 let checkCaller = thisOnly(i)
499499 if ((checkCaller == checkCaller))
500500 then {
501501 let voteResultKey = keyVoteResultByPeriod(assetId, period)
502502 let $t01745317626 = match getString(voteResultKey) {
503503 case s: String =>
504504 let r = parseVoteResult(s)
505505 $Tuple2(r._1, r._2)
506506 case _: Unit =>
507507 $Tuple2(0, 0)
508508 case _ =>
509509 throw("Match error")
510510 }
511511 let totalYes = $t01745317626._1
512512 let totalNo = $t01745317626._2
513513 let total = (totalYes + totalNo)
514514 let verified = if ((total >= votingThreshold))
515515 then (totalYes > totalNo)
516516 else false
517517 let assetVerifiedActions = [BooleanEntry(keyAssetVerifiedByPeriod(assetId, period), verified), if (verified)
518518 then BooleanEntry(keyAssetVerified(assetId), true)
519519 else DeleteEntry(keyAssetVerified(assetId))]
520520 let assetsStoreSetVerifiedInv = invoke(assetsStoreContract, "setVerified", [assetId, verified], nil)
521521 if ((assetsStoreSetVerifiedInv == assetsStoreSetVerifiedInv))
522522 then {
523523 let eliminate = if (verified)
524524 then false
525525 else eliminationCheck(assetId)
526526 let assetWasEliminatedActions = if (eliminate)
527527 then [BooleanEntry(keyAssetWasEliminated(assetId, currentPeriod), true)]
528528 else nil
529529 let voteResultActions = if (eliminate)
530530 then nil
531531 else [getVoteResultAction(assetId, 0, true, (currentPeriod + 1), verified)]
532532 let votesListActions = if (eliminate)
533533 then deleteNode(assetsListName, assetId)
534534 else nil
535535 let onEliminationInv = if (eliminate)
536536 then invoke(assetsStoreContract, "onEliminate", [assetId], nil)
537537 else unit
538538 if ((onEliminationInv == onEliminationInv))
539539 then $Tuple2(((votesListActions ++ voteResultActions) ++ assetVerifiedActions), unit)
540540 else throw("Strict value is not equal to itself.")
541541 }
542542 else throw("Strict value is not equal to itself.")
543543 }
544544 else throw("Strict value is not equal to itself.")
545545 }
546546
547547
548548
549549 @Callable(i)
550550 func deleteUserNodeINTERNAL (assetId,userAddress,latestProcessedUserRemoveKey) = {
551- let checkCaller = mustManager(i)
551+ let checkCaller = if ((i.caller == this))
552+ then true
553+ else mustManager(i)
552554 if ((checkCaller == checkCaller))
553555 then $Tuple2((deleteNode(getVotesListName(assetId), userAddress) :+ DeleteEntry(latestProcessedUserRemoveKey)), unit)
554556 else throw("Strict value is not equal to itself.")
555557 }
556558
557559
558560
559561 @Callable(i)
560562 func finalizeVotingHelper () = if ((endHeight > height))
561563 then $Tuple2(nil, false)
562564 else {
563565 let latestProcessedAssetOrUnit = getString(keyLatestProcessedAsset)
564566 let latestProcessedUserOrUnit = getString(keyLatestProcessedUser)
565567 let nextPeriodDelay = 0
566568 let finish = $Tuple2([IntegerEntry(keyStartHeight, (height + nextPeriodDelay)), IntegerEntry(keyCurrentPeriod, (currentPeriod + 1)), DeleteEntry(keyLatestProcessedAsset), DeleteEntry(keyLatestProcessedUser), DeleteEntry(keyLatestProcessedAssetTransfer), DeleteEntry(keyLatestProcessedUserTransfer)], true)
567569 if ((latestProcessedAssetOrUnit == unit))
568570 then {
569571 let assetsHeadOrUnit = getString(keyListHead(assetsListName))
570572 if ((assetsHeadOrUnit == unit))
571573 then finish
572574 else {
573575 let asset = value(assetsHeadOrUnit)
574576 let userAddressOrUnit = getString(keyListHead(getVotesListName(asset)))
575577 let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAsset, keyLatestProcessedUser, keyLatestProcessedUserRemove)
576578 $Tuple2(processVoteActions, true)
577579 }
578580 }
579581 else {
580582 let latestProcessedAsset = value(latestProcessedAssetOrUnit)
581583 if ((latestProcessedUserOrUnit == unit))
582584 then {
583585 let assetOrUnit = getString(keyListNext(assetsListName, latestProcessedAsset))
584586 if ((assetOrUnit == assetOrUnit))
585587 then {
586588 let finalizeAssetInv = invoke(this, "finalizeAssetINTERNAL", [latestProcessedAsset, currentPeriod], nil)
587589 if ((finalizeAssetInv == finalizeAssetInv))
588590 then if ((assetOrUnit == unit))
589591 then finish
590592 else {
591593 let asset = value(assetOrUnit)
592594 let userAddressOrUnit = getString(keyListHead(getVotesListName(asset)))
593595 let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAsset, keyLatestProcessedUser, keyLatestProcessedUserRemove)
594596 $Tuple2(processVoteActions, true)
595597 }
596598 else throw("Strict value is not equal to itself.")
597599 }
598600 else throw("Strict value is not equal to itself.")
599601 }
600602 else {
601603 let latestProcessedUser = value(latestProcessedUserOrUnit)
602604 let userAddressOrUnit = getString(keyListNext(getVotesListName(latestProcessedAsset), latestProcessedUser))
603605 if ((userAddressOrUnit == userAddressOrUnit))
604606 then {
605607 let removeLatestUser = valueOrElse(getBoolean(keyLatestProcessedUserRemove), false)
606608 let deleteUserInv = if (removeLatestUser)
607609 then invoke(this, "deleteUserNodeINTERNAL", [latestProcessedAsset, latestProcessedUser, keyLatestProcessedUserRemove], nil)
608610 else unit
609611 if ((deleteUserInv == deleteUserInv))
610612 then {
611613 let processVoteActions = processVote(latestProcessedAsset, userAddressOrUnit, keyLatestProcessedAsset, keyLatestProcessedUser, keyLatestProcessedUserRemove)
612614 $Tuple2(processVoteActions, true)
613615 }
614616 else throw("Strict value is not equal to itself.")
615617 }
616618 else throw("Strict value is not equal to itself.")
617619 }
618620 }
619621 }
620622
621623
622624
623625 @Callable(i)
624626 func finalizeVotingWrapper (counter) = {
625627 let result = asBool(invoke(this, "finalizeVotingHelper", nil, nil))
626628 if ((result == result))
627629 then if (!(result))
628630 then if ((counter == 0))
629631 then throw("Current voting is not over yet")
630632 else $Tuple2(nil, unit)
631633 else if ((maxDepth > counter))
632634 then {
633635 let inv = invoke(this, "finalizeVotingWrapper", [(counter + 1)], nil)
634636 if ((inv == inv))
635637 then $Tuple2(nil, unit)
636638 else throw("Strict value is not equal to itself.")
637639 }
638640 else $Tuple2(nil, unit)
639641 else throw("Strict value is not equal to itself.")
640642 }
641643
642644
643645
644646 @Callable(i)
645647 func finalizeVoting () = {
646648 let inv = invoke(this, "finalizeVotingWrapper", [0], nil)
647649 if ((inv == inv))
648650 then $Tuple2(nil, unit)
649651 else throw("Strict value is not equal to itself.")
650652 }
651653
652654
653655
654656 @Callable(i)
655657 func transferVotesHelper () = {
656658 let votesTransferFinishedKey = keyVotesTransferFinishedByPeriod(currentPeriod)
657659 let votesTransferFinished = valueOrElse(getBoolean(votesTransferFinishedKey), false)
658660 if (if (if ((startHeight > height))
659661 then true
660662 else (height >= endHeight))
661663 then true
662664 else votesTransferFinished)
663665 then $Tuple2(nil, false)
664666 else {
665667 let latestProcessedAssetOrUnit = getString(keyLatestProcessedAssetTransfer)
666668 let latestProcessedUserOrUnit = getString(keyLatestProcessedUserTransfer)
667669 let finish = $Tuple2([BooleanEntry(votesTransferFinishedKey, true), DeleteEntry(keyLatestProcessedAssetTransfer), DeleteEntry(keyLatestProcessedUserTransfer)], true)
668670 if ((latestProcessedAssetOrUnit == unit))
669671 then {
670672 let assetsHeadOrUnit = getString(keyListHead(assetsListName))
671673 if ((assetsHeadOrUnit == unit))
672674 then finish
673675 else {
674676 let asset = value(assetsHeadOrUnit)
675677 let userAddressOrUnit = getString(keyListHead(getVotesListName(asset)))
676678 let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAssetTransfer, keyLatestProcessedUserTransfer, keyLatestProcessedUserRemoveTransfer)
677679 $Tuple2(processVoteActions, true)
678680 }
679681 }
680682 else {
681683 let latestProcessedAsset = value(latestProcessedAssetOrUnit)
682684 if ((latestProcessedUserOrUnit == unit))
683685 then {
684686 let assetOrUnit = getString(keyListNext(assetsListName, latestProcessedAsset))
685687 if ((assetOrUnit == unit))
686688 then finish
687689 else {
688690 let asset = value(assetOrUnit)
689691 let userAddressOrUnit = getString(keyListHead(getVotesListName(asset)))
690692 let processVoteActions = processVote(asset, userAddressOrUnit, keyLatestProcessedAssetTransfer, keyLatestProcessedUserTransfer, keyLatestProcessedUserRemoveTransfer)
691693 $Tuple2(processVoteActions, true)
692694 }
693695 }
694696 else {
695697 let latestProcessedUser = value(latestProcessedUserOrUnit)
696698 let userAddressOrUnit = getString(keyListNext(getVotesListName(latestProcessedAsset), latestProcessedUser))
697699 if ((userAddressOrUnit == userAddressOrUnit))
698700 then {
699701 let removeLatestUser = valueOrElse(getBoolean(keyLatestProcessedUserRemoveTransfer), false)
700702 let deleteUserInv = if (removeLatestUser)
701703 then invoke(this, "deleteUserNodeINTERNAL", [latestProcessedAsset, latestProcessedUser, keyLatestProcessedUserRemoveTransfer], nil)
702704 else unit
703705 if ((deleteUserInv == deleteUserInv))
704706 then {
705707 let processVoteActions = processVote(latestProcessedAsset, userAddressOrUnit, keyLatestProcessedAssetTransfer, keyLatestProcessedUserTransfer, keyLatestProcessedUserRemoveTransfer)
706708 $Tuple2(processVoteActions, true)
707709 }
708710 else throw("Strict value is not equal to itself.")
709711 }
710712 else throw("Strict value is not equal to itself.")
711713 }
712714 }
713715 }
714716 }
715717
716718
717719
718720 @Callable(i)
719721 func transferVotesWrapper (counter) = {
720722 let result = asBool(invoke(this, "transferVotesHelper", nil, nil))
721723 if ((result == result))
722724 then if (!(result))
723725 then if ((counter == 0))
724726 then throw("Voting is not started yet")
725727 else $Tuple2(nil, unit)
726728 else if ((maxDepth > counter))
727729 then {
728730 let inv = invoke(this, "transferVotesWrapper", [(counter + 1)], nil)
729731 if ((inv == inv))
730732 then $Tuple2(nil, unit)
731733 else throw("Strict value is not equal to itself.")
732734 }
733735 else $Tuple2(nil, unit)
734736 else throw("Strict value is not equal to itself.")
735737 }
736738
737739
738740
739741 @Callable(i)
740742 func transferVotes () = {
741743 let inv = invoke(this, "transferVotesWrapper", [0], nil)
742744 if ((inv == inv))
743745 then $Tuple2(nil, unit)
744746 else throw("Strict value is not equal to itself.")
745747 }
746748
747749
748750
749751 @Callable(i)
750752 func setVotingThreshold (newThreshold) = {
751753 let checkCaller = mustManager(i)
752754 if ((checkCaller == checkCaller))
753755 then $Tuple2([IntegerEntry(keyVotingThreshold, newThreshold)], unit)
754756 else throw("Strict value is not equal to itself.")
755757 }
756758
757759
758760
759761 @Callable(i)
760762 func setFee (newFee) = {
761763 let checkCaller = mustManager(i)
762764 if ((checkCaller == checkCaller))
763765 then $Tuple2([IntegerEntry(keyFeeAmount, newFee)], unit)
764766 else throw("Strict value is not equal to itself.")
765767 }
766768
767769
768770
769771 @Callable(i)
770772 func gwxAvailableForVoteREADONLY (userAddress) = {
771773 let gwxAmountAtEnd = getUserGwxAmountAtHeight(userAddress, endHeight)
772774 $Tuple2(nil, gwxAmountAtEnd)
773775 }
774776
775777
776778 @Verifier(tx)
777779 func verify () = {
778780 let targetPublicKey = match managerPublicKeyOrUnit() {
779781 case pk: ByteVector =>
780782 pk
781783 case _: Unit =>
782784 tx.senderPublicKey
783785 case _ =>
784786 throw("Match error")
785787 }
786788 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
787789 }
788790

github/deemru/w8io/3ef1775 
100.05 ms