tx · EPMpHrbGh5EBXXjXR73zsJDT76zqWryQvP4juczHoz3r

3MqQ9ihYKGehfUnXYf5WmkYSZUD71ByeCQe:  -0.01400000 Waves

2020.04.06 11:04 [942100] smart account 3MqQ9ihYKGehfUnXYf5WmkYSZUD71ByeCQe > SELF 0.00000000 Waves

{ "type": 13, "id": "EPMpHrbGh5EBXXjXR73zsJDT76zqWryQvP4juczHoz3r", "fee": 1400000, "feeAssetId": null, "timestamp": 1586160288618, "version": 1, "sender": "3MqQ9ihYKGehfUnXYf5WmkYSZUD71ByeCQe", "senderPublicKey": "HcUXEkA9JTGp78LcTKsu4FmEpbDmnqntL4aMNLx1BHMB", "proofs": [ "5MrYit6oY7CPDBimuf3XFMUNf73NnZNkYjvsKNv54ySEBhFzn7c2KqwLqgYrBPdhw3A5hHA3frMUdaBPMF4ME61e" ], "script": "base64:AAIDAAAAAAAAABIIARIDCgEEEgMKAQgSBAoCCAIAAAAzAAAAAAdXQVZFTEVUCQAAaAAAAAIJAABoAAAAAgAAAAAAAAAAZAAAAAAAAAAD6AAAAAAAAAAD6AAAAAAKQ09NTUlTU0lPTgkAAGkAAAACCQAAaAAAAAIAAAAAAAAAAAUFAAAAB1dBVkVMRVQAAAAAAAAAA+gAAAAACVJTQVBVQkxJQwkAAlsAAAABAgAAAY9iYXNlNjQ6TUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFtcHVYY0kvbzRwSUI1eXd2OURPT0dhcFRCVXdSVmxNLzYrSDZoRmVsT1h0a3J3WS9ZSXRtUHhFRHB6N3JBZXJRUFFlOXREUEVhQXYvR25sRXp0eWJPRlhndTlEekRlOFlvTVJEMXZha2dvQWNvZ21iWTU4UUQ2S01qNUhrb1ZqL3lUTkljOXN6ajVxaElsckFkbWIzS0xMNmhRVTd5OCtKajY5QldWUHNhUWdrc3BTZGVZdGIxdEhRYzd0OTVuN09aNTZyMkE3RzMrYlFmNm5TTWtQa0FoSXJFcGJDbTU4b2lHQmN6ZFRkL0xxRlNWb3Rac2JMN1loNlNITGZuSGVEK1FnY2ZKcm5hbThPSE1HSkVKVFJYaklMZUhHamxSQ1A4b1ZwaW9IcnkxUzJ4UHg1c1Z6SW0yTU0rQ3pZZW5BR2xvMGoyNmF0QmhpVUxvVHVsd0QzcFFJREFRQUIAAAAABlNFUlZFUgkBAAAAHEBleHRyVXNlcihhZGRyZXNzRnJvbVN0cmluZykAAAABAgAAACMzTkNpRzI4TG1XeVRpZ1dHMTNFNVFudmRIQnNaRllYU1MyagAAAAATUkFORE9SQUNMRVRJTUVGUkFNRQAAAAAAAAAQ4AAAAAAOTUFYQkFMQU5DRURJRkYAAAAAAAX14QAAAAAABEJFVDEJAABoAAAAAgAAAAAAAAAAAQUAAAAHV0FWRUxFVAAAAAAEQkVUMgkAAGgAAAACAAAAAAAAAAACBQAAAAdXQVZFTEVUAAAAAARCRVQ0CQAAaAAAAAIAAAAAAAAAAAQFAAAAB1dBVkVMRVQAAAAABEJFVDgJAABoAAAAAgAAAAAAAAAACAUAAAAHV0FWRUxFVAAAAAAFQkVUMTQJAABoAAAAAgAAAAAAAAAADgUAAAAHV0FWRUxFVAAAAAAIUkFURU1VTFQAAAAAAAAAJxAAAAAABVJBVEUxAAAAAAAAAJrnAAAAAAVSQVRFMgAAAAAAAABgGAAAAAAFUkFURTMAAAAAAAAASjgAAAAABVJBVEU0AAAAAAAAADd4AAAAAAVSQVRFNQAAAAAAAAAsiAAAAAAFUkFURVMJAARMAAAAAgUAAAAFUkFURTEJAARMAAAAAgUAAAAFUkFURTIJAARMAAAAAgUAAAAFUkFURTMJAARMAAAAAgUAAAAFUkFURTQJAARMAAAAAgUAAAAFUkFURTUFAAAAA25pbAAAAAAEQkVUUwkABEwAAAACBQAAAARCRVQxCQAETAAAAAIFAAAABEJFVDIJAARMAAAAAgUAAAAEQkVUNAkABEwAAAACBQAAAARCRVQ4CQAETAAAAAIFAAAABUJFVDE0BQAAAANuaWwAAAAADElkeEdhbWVTdGF0ZQAAAAAAAAAAAAAAAAAPSWR4UGxheWVyQ2hvaWNlAAAAAAAAAAABAAAAABFJZHhQbGF5ZXJQdWJLZXk1OAAAAAAAAAAAAgAAAAAQSWR4U3RhcnRlZEhlaWdodAAAAAAAAAAAAwAAAAAJSWR4V2luQW10AAAAAAAAAAAEAAAAAA5JZHhSYW5kT3JFbXB0eQAAAAAAAAAABQAAAAAOUkVTRVJWQVRJT05LRVkCAAAAECRSRVNFUlZFRF9BTU9VTlQAAAAAD0dBTUVTQ09VTlRFUktFWQIAAAAJJEdBTUVfTlVNAAAAAAlEQVBQVVBLRVkCAAAACCREQVBQX1VQAAAAAA1NQVhCQUxBTkNFS0VZAgAAAAwkTUFYX0JBTEFOQ0UAAAAADlNUQVRFU1VCTUlUVEVEAgAAAAlTVUJNSVRURUQAAAAACFNUQVRFV09OAgAAAANXT04AAAAACVNUQVRFTE9TVAIAAAAETE9TVAEAAAAIZ2V0SW50T3IAAAACAAAAA2tleQAAAAdkZWZhdWx0AwkBAAAACWlzRGVmaW5lZAAAAAEJAAQaAAAAAgUAAAAEdGhpcwUAAAADa2V5CQEAAAARQGV4dHJOYXRpdmUoMTA1MCkAAAACBQAAAAR0aGlzBQAAAANrZXkFAAAAB2RlZmF1bHQBAAAABnNldEludAAAAAIAAAADa2V5AAAABXZhbHVlCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAADa2V5BQAAAAV2YWx1ZQEAAAAMaW5jcmVtZW50SW50AAAAAQAAAANrZXkJAQAAAAZzZXRJbnQAAAACBQAAAANrZXkJAABkAAAAAgkBAAAACGdldEludE9yAAAAAgUAAAADa2V5AP//////////AAAAAAAAAAABAQAAABJFeHRyYWN0UmVzZXJ2ZWRBbXQAAAAABAAAAAckbWF0Y2gwCQAEGgAAAAIFAAAABHRoaXMFAAAADlJFU0VSVkFUSU9OS0VZAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAAAWEFAAAAByRtYXRjaDAFAAAAAWEAAAAAAAAAAAABAAAAHlZhbGlkYXRlQW5kSW5jcmVhc2VSZXNlcnZlZEFtdAAAAAEAAAAGd2luQW10BAAAABFuZXdSZXNlcnZlZEFtb3VudAkAAGQAAAACCQEAAAASRXh0cmFjdFJlc2VydmVkQW10AAAAAAUAAAAGd2luQW10BAAAAAdiYWxhbmNlCQEAAAAMd2F2ZXNCYWxhbmNlAAAAAQUAAAAEdGhpcwMJAABmAAAAAgUAAAARbmV3UmVzZXJ2ZWRBbW91bnQFAAAAB2JhbGFuY2UJAAACAAAAAQIAAABUSW5zdWZmaWNpZW50IGZ1bmRzIG9uIERpY2UgUm9sbGVyIGFjY291bnQuIFRyYW5zYWN0aW9uIHdhcyByZWplY3RlZCBmb3IgeW91ciBzYWZldHkuBQAAABFuZXdSZXNlcnZlZEFtb3VudAEAAAATRGVjcmVhc2VSZXNlcnZlZEFtdAAAAAIAAAAGZ2FtZUlkAAAABndpbkFtdAQAAAARbmV3UmVzZXJ2ZWRBbW91bnQJAABlAAAAAgkBAAAAEkV4dHJhY3RSZXNlcnZlZEFtdAAAAAAFAAAABndpbkFtdAMJAABmAAAAAgAAAAAAAAAAAAUAAAARbmV3UmVzZXJ2ZWRBbW91bnQJAAACAAAAAQIAAABCSW52YWxpZCBEaWNlIFJvbGxlciBhY2NvdW50IHN0YXRlIC0gcmVzZXJ2ZWQgYW1vdW50IGlzIGxlc3MgdGhhbiAwCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAAOUkVTRVJWQVRJT05LRVkFAAAAEW5ld1Jlc2VydmVkQW1vdW50AQAAABpWYWxpZGF0ZUJldEFuZERlZmluZVdpbkFtdAAAAAIAAAAGYmV0QW10AAAADHBsYXllckNob2ljZQQAAAALYmV0QW10VmFsaWQDAwMDCQAAAAAAAAIFAAAABmJldEFtdAkAAGQAAAACBQAAAARCRVQxBQAAAApDT01NSVNTSU9OBgkAAAAAAAACBQAAAAZiZXRBbXQJAABkAAAAAgUAAAAEQkVUMgUAAAAKQ09NTUlTU0lPTgYJAAAAAAAAAgUAAAAGYmV0QW10CQAAZAAAAAIFAAAABEJFVDQFAAAACkNPTU1JU1NJT04GCQAAAAAAAAIFAAAABmJldEFtdAkAAGQAAAACBQAAAARCRVQ4BQAAAApDT01NSVNTSU9OBgkAAAAAAAACBQAAAAZiZXRBbXQJAABkAAAAAgUAAAAFQkVUMTQFAAAACkNPTU1JU1NJT04DBQAAAAtiZXRBbXRWYWxpZAkAAAIAAAABAgAAABpCZXQgYW1vdW50IGlzIG5vdCBpbiByYW5nZQQAAAAKZGljZXNDb3VudAkAATEAAAABBQAAAAxwbGF5ZXJDaG9pY2UEAAAAA2JldAkAAGUAAAACBQAAAAZiZXRBbXQFAAAACkNPTU1JU1NJT04DCQAAAAAAAAIFAAAACmRpY2VzQ291bnQAAAAAAAAAAAEJAABpAAAAAgkAAGgAAAACBQAAAANiZXQFAAAABVJBVEUxBQAAAAhSQVRFTVVMVAMJAAAAAAAAAgUAAAAKZGljZXNDb3VudAAAAAAAAAAAAgkAAGkAAAACCQAAaAAAAAIFAAAAA2JldAUAAAAFUkFURTIFAAAACFJBVEVNVUxUAwkAAAAAAAACBQAAAApkaWNlc0NvdW50AAAAAAAAAAADCQAAaQAAAAIJAABoAAAAAgUAAAADYmV0BQAAAAVSQVRFMwUAAAAIUkFURU1VTFQDCQAAAAAAAAIFAAAACmRpY2VzQ291bnQAAAAAAAAAAAQJAABpAAAAAgkAAGgAAAACBQAAAANiZXQFAAAABVJBVEU0BQAAAAhSQVRFTVVMVAMJAAAAAAAAAgUAAAAKZGljZXNDb3VudAAAAAAAAAAABQkAAGkAAAACCQAAaAAAAAIFAAAAA2JldAUAAAAFUkFURTUFAAAACFJBVEVNVUxUCQAAAgAAAAECAAAAJkludmFsaWQgZGljZXMgY291bnQgaW4gcGxheWVyJ3MgY2hvaWNlAQAAAAlSYW5kVG9TdHIAAAABAAAAAXIDCQAAAAAAAAIFAAAAAXIAAAAAAAAAAAACAAAAATEDCQAAAAAAAAIFAAAAAXIAAAAAAAAAAAECAAAAATIDCQAAAAAAAAIFAAAAAXIAAAAAAAAAAAICAAAAATMDCQAAAAAAAAIFAAAAAXIAAAAAAAAAAAMCAAAAATQDCQAAAAAAAAIFAAAAAXIAAAAAAAAAAAQCAAAAATUDCQAAAAAAAAIFAAAAAXIAAAAAAAAAAAUCAAAAATYJAAACAAAAAQkAASwAAAACAgAAADpVbnN1cHBvcnRlZCByIHBhcmFtZXRlciBwYXNzZWQ6IGV4cGVjdGVkPVswLC4uLiw1XSBhY3R1YWw9CQABpAAAAAEFAAAAAXIBAAAAD0dlbmVyYXRlUmFuZEludAAAAAIAAAAGZ2FtZUlkAAAAB3JzYVNpZ24EAAAAC3JzYVNpZ1ZhbGlkCQAB+AAAAAQFAAAABlNIQTI1NgkAAZsAAAABBQAAAAZnYW1lSWQFAAAAB3JzYVNpZ24FAAAACVJTQVBVQkxJQwMFAAAAC3JzYVNpZ1ZhbGlkBAAAAARyYW5kCQAAagAAAAIJAASxAAAAAQkAAfcAAAABBQAAAAdyc2FTaWduAAAAAAAAAAAGAwkAAGYAAAACAAAAAAAAAAAABQAAAARyYW5kCQAAaAAAAAIA//////////8FAAAABHJhbmQFAAAABHJhbmQJAAACAAAAAQIAAAAVSW52YWxpZCBSU0Egc2lnbmF0dXJlAQAAAAtJc1BsYXllcldpbgAAAAIAAAAMcGxheWVyQ2hvaWNlAAAAB3JhbmRTdHIEAAAAAXMJAAExAAAAAQUAAAAMcGxheWVyQ2hvaWNlAwMDAwMJAABnAAAAAgUAAAABcwAAAAAAAAAAAQkAAAAAAAACCQABLwAAAAIJAAEwAAAAAgUAAAAMcGxheWVyQ2hvaWNlAAAAAAAAAAAAAAAAAAAAAAABBQAAAAdyYW5kU3RyBwYDCQAAZwAAAAIFAAAAAXMAAAAAAAAAAAIJAAAAAAAAAgkAAS8AAAACCQABMAAAAAIFAAAADHBsYXllckNob2ljZQAAAAAAAAAAAQAAAAAAAAAAAQUAAAAHcmFuZFN0cgcGAwkAAGcAAAACBQAAAAFzAAAAAAAAAAADCQAAAAAAAAIJAAEvAAAAAgkAATAAAAACBQAAAAxwbGF5ZXJDaG9pY2UAAAAAAAAAAAIAAAAAAAAAAAEFAAAAB3JhbmRTdHIHBgMJAABnAAAAAgUAAAABcwAAAAAAAAAABAkAAAAAAAACCQABLwAAAAIJAAEwAAAAAgUAAAAMcGxheWVyQ2hvaWNlAAAAAAAAAAADAAAAAAAAAAABBQAAAAdyYW5kU3RyBwYDCQAAAAAAAAIFAAAAAXMAAAAAAAAAAAUJAAAAAAAAAgkAAS8AAAACCQABMAAAAAIFAAAADHBsYXllckNob2ljZQAAAAAAAAAABAAAAAAAAAAAAQUAAAAHcmFuZFN0cgcBAAAAE0Zvcm1hdEdhbWVEYXRhUGFyYW0AAAABAAAAAXAEAAAAAXMJAAExAAAAAQUAAAABcAMJAAAAAAAAAgUAAAABcwAAAAAAAAAAAAkAAAIAAAABAgAAACVQYXJhbWV0ZXIgc2l6ZSBtdXN0IGJlIGdyZWF0ZXIgdGhlbiAwAwkAAGYAAAACBQAAAAFzAAAAAAAAAABjCQAAAgAAAAECAAAAJFBhcmFtZXRlciBzaXplIG11c3QgYmUgbGVzcyB0aGVuIDEwMAMJAABmAAAAAgAAAAAAAAAACgUAAAABcwkAASwAAAACCQABLAAAAAICAAAAATAJAAGkAAAAAQUAAAABcwUAAAABcAkAASwAAAACCQABpAAAAAEFAAAAAXMFAAAAAXABAAAAEUZvcm1hdEdhbWVEYXRhU3RyAAAABgAAAAlnYW1lU3RhdGUAAAAMcGxheWVyQ2hvaWNlAAAADnBsYXllclB1YktleTU4AAAADXN0YXJ0ZWRIZWlnaHQAAAAGd2luQW10AAAAC3JhbmRPckVtcHR5BAAAAAxmdWxsU3RhdGVTdHIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQEAAAATRm9ybWF0R2FtZURhdGFQYXJhbQAAAAEFAAAACWdhbWVTdGF0ZQIAAAABXwkBAAAAE0Zvcm1hdEdhbWVEYXRhUGFyYW0AAAABBQAAAAxwbGF5ZXJDaG9pY2UCAAAAAV8JAQAAABNGb3JtYXRHYW1lRGF0YVBhcmFtAAAAAQUAAAAOcGxheWVyUHViS2V5NTgCAAAAAV8JAQAAABNGb3JtYXRHYW1lRGF0YVBhcmFtAAAAAQkAAaQAAAABBQAAAA1zdGFydGVkSGVpZ2h0AgAAAAFfCQEAAAATRm9ybWF0R2FtZURhdGFQYXJhbQAAAAEJAAGkAAAAAQUAAAAGd2luQW10AwkAAAAAAAACBQAAAAtyYW5kT3JFbXB0eQIAAAAABQAAAAxmdWxsU3RhdGVTdHIJAAEsAAAAAgkAASwAAAACBQAAAAxmdWxsU3RhdGVTdHICAAAAAV8JAQAAABNGb3JtYXRHYW1lRGF0YVBhcmFtAAAAAQUAAAALcmFuZE9yRW1wdHkBAAAAGVJlbW92ZVVuZGVyc2NvcmVJZlByZXNlbnQAAAABAAAACXJlbWFpbmluZwMJAABmAAAAAgkAATEAAAABBQAAAAlyZW1haW5pbmcAAAAAAAAAAAAJAAEwAAAAAgUAAAAJcmVtYWluaW5nAAAAAAAAAAABBQAAAAlyZW1haW5pbmcBAAAAElBhcnNlTmV4dEF0dHJpYnV0ZQAAAAEAAAAJcmVtYWluaW5nBAAAAAFzCQABMQAAAAEFAAAACXJlbWFpbmluZwMJAABmAAAAAgUAAAABcwAAAAAAAAAAAAQAAAACbm4JAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAS8AAAACBQAAAAlyZW1haW5pbmcAAAAAAAAAAAIEAAAAAXYJAAEvAAAAAgkAATAAAAACBQAAAAlyZW1haW5pbmcAAAAAAAAAAAIFAAAAAm5uBAAAAAx0bXBSZW1haW5pbmcJAAEwAAAAAgUAAAAJcmVtYWluaW5nCQAAZAAAAAIFAAAAAm5uAAAAAAAAAAACBAAAAA5yZW1haW5pbmdTdGF0ZQkBAAAAGVJlbW92ZVVuZGVyc2NvcmVJZlByZXNlbnQAAAABBQAAAAx0bXBSZW1haW5pbmcJAARMAAAAAgUAAAABdgkABEwAAAACBQAAAA5yZW1haW5pbmdTdGF0ZQUAAAADbmlsCQAAAgAAAAECAAAANEVtcHR5IHN0cmluZyB3YXMgcGFzc2VkIGludG8gcGFyc2VOZXh0QXR0cmlidXRlIGZ1bmMBAAAAE1BhcnNlR2FtZVJhd0RhdGFTdHIAAAABAAAAC3Jhd1N0YXRlU3RyBAAAAAlnYW1lU3RhdGUJAQAAABJQYXJzZU5leHRBdHRyaWJ1dGUAAAABBQAAAAtyYXdTdGF0ZVN0cgQAAAAMcGxheWVyQ2hvaWNlCQEAAAASUGFyc2VOZXh0QXR0cmlidXRlAAAAAQkAAZEAAAACBQAAAAlnYW1lU3RhdGUAAAAAAAAAAAEEAAAADnBsYXllclB1YktleTU4CQEAAAASUGFyc2VOZXh0QXR0cmlidXRlAAAAAQkAAZEAAAACBQAAAAxwbGF5ZXJDaG9pY2UAAAAAAAAAAAEEAAAADXN0YXJ0ZWRIZWlnaHQJAQAAABJQYXJzZU5leHRBdHRyaWJ1dGUAAAABCQABkQAAAAIFAAAADnBsYXllclB1YktleTU4AAAAAAAAAAABBAAAAAZ3aW5BbXQJAQAAABJQYXJzZU5leHRBdHRyaWJ1dGUAAAABCQABkQAAAAIFAAAADXN0YXJ0ZWRIZWlnaHQAAAAAAAAAAAEJAARMAAAAAgkAAZEAAAACBQAAAAlnYW1lU3RhdGUAAAAAAAAAAAAJAARMAAAAAgkAAZEAAAACBQAAAAxwbGF5ZXJDaG9pY2UAAAAAAAAAAAAJAARMAAAAAgkAAZEAAAACBQAAAA5wbGF5ZXJQdWJLZXk1OAAAAAAAAAAAAAkABEwAAAACCQABkQAAAAIFAAAADXN0YXJ0ZWRIZWlnaHQAAAAAAAAAAAAJAARMAAAAAgkAAZEAAAACBQAAAAZ3aW5BbXQAAAAAAAAAAAAFAAAAA25pbAEAAAATRXh0cmFjdEdhbWVEYXRhTGlzdAAAAAEAAAAGZ2FtZUlkBAAAAApyYXdEYXRhU3RyBAAAAAckbWF0Y2gwCQAEHQAAAAIFAAAABHRoaXMFAAAABmdhbWVJZAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAGU3RyaW5nBAAAAANzdHIFAAAAByRtYXRjaDAFAAAAA3N0cgkAAAIAAAABCQABLAAAAAICAAAAFkNvdWxkbid0IGZpbmQgZ2FtZSBieSAFAAAABmdhbWVJZAkBAAAAE1BhcnNlR2FtZVJhd0RhdGFTdHIAAAABBQAAAApyYXdEYXRhU3RyAQAAAAxXaW5TY3JpcHRTZXQAAAAGAAAABmdhbWVJZAAAAA1wbGF5ZXJBZGRyZXNzAAAABndpbkFtdAAAAA5uZXdHYW1lRGF0YVN0cgAAAAx3aW5CeVRpbWVvdXQAAAARZGVjcmVhc2VkUmVzZXJ2ZXMEAAAADndTZXRDb21tb25EYXRhCQAETAAAAAIFAAAAEWRlY3JlYXNlZFJlc2VydmVzBQAAAANuaWwEAAAADnRTZXRDb21tb25EYXRhCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMFAAAADXBsYXllckFkZHJlc3MFAAAABndpbkFtdAUAAAAEdW5pdAUAAAADbmlsAwUAAAAMd2luQnlUaW1lb3V0BAAAABZuZXdHYW1lRGF0YVN0ckFkanVzdGVkCQABLAAAAAIJAAEsAAAAAgUAAAAObmV3R2FtZURhdGFTdHICAAAAAV8JAQAAABNGb3JtYXRHYW1lRGF0YVBhcmFtAAAAAQIAAAAHVElNRU9VVAQAAAAIZ2FtZURhdGEJAQAAAAlEYXRhRW50cnkAAAACBQAAAAZnYW1lSWQFAAAAFm5ld0dhbWVEYXRhU3RyQWRqdXN0ZWQJAQAAAAxTY3JpcHRSZXN1bHQAAAACCQEAAAAIV3JpdGVTZXQAAAABCQAETAAAAAIFAAAACGdhbWVEYXRhBQAAAA53U2V0Q29tbW9uRGF0YQkBAAAAC1RyYW5zZmVyU2V0AAAAAQUAAAAOdFNldENvbW1vbkRhdGEEAAAACGdhbWVEYXRhCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAAGZ2FtZUlkBQAAAA5uZXdHYW1lRGF0YVN0cgkBAAAADFNjcmlwdFJlc3VsdAAAAAIJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgUAAAAIZ2FtZURhdGEFAAAADndTZXRDb21tb25EYXRhCQEAAAALVHJhbnNmZXJTZXQAAAABBQAAAA50U2V0Q29tbW9uRGF0YQEAAAAISXNEQXBwVXAAAAAABAAAAAlkQXBwVXBPcHQJAAQbAAAAAgUAAAAEdGhpcwUAAAAJREFQUFVQS0VZAwkBAAAACWlzRGVmaW5lZAAAAAEFAAAACWRBcHBVcE9wdAkBAAAAB2V4dHJhY3QAAAABBQAAAAlkQXBwVXBPcHQHAQAAABFtb25pdG9yTWF4QmFsYW5jZQAAAAAEAAAADW1heEJhbGFuY2VPcHQJAAQaAAAAAgUAAAAEdGhpcwUAAAANTUFYQkFMQU5DRUtFWQQAAAAKbWF4QmFsYW5jZQMJAQAAAAlpc0RlZmluZWQAAAABBQAAAA1tYXhCYWxhbmNlT3B0CQEAAAAHZXh0cmFjdAAAAAEFAAAADW1heEJhbGFuY2VPcHQAAAAAAAAAAAAEAAAAC2N1cnJCYWxhbmNlCQEAAAAMd2F2ZXNCYWxhbmNlAAAAAQUAAAAEdGhpcwMJAABmAAAAAgUAAAALY3VyckJhbGFuY2UFAAAACm1heEJhbGFuY2UFAAAAC2N1cnJCYWxhbmNlBAAAAARkaWZmCQAAZQAAAAIFAAAACm1heEJhbGFuY2UFAAAAC2N1cnJCYWxhbmNlAwkAAGYAAAACBQAAAARkaWZmBQAAAA5NQVhCQUxBTkNFRElGRgkAAAIAAAABAgAAABpkQXBwIGlzIHRlbXBvcmFyeSBkaXNhYmxlZAUAAAAKbWF4QmFsYW5jZQAAAAMAAAABaQEAAAAGZEFwcFVwAAAAAQAAAAZkQXBwVXADCQEAAAACIT0AAAACCAUAAAABaQAAAAZjYWxsZXIFAAAABlNFUlZFUgkAAAIAAAABAgAAACdPbmx5IFNlcnZlciBjYW4gbWFuYWdlIGRBcHBVcCBhdHRyaWJ1dGUDCQAAAAAAAAIJAQAAAAhJc0RBcHBVcAAAAAAFAAAABmRBcHBVcAkAAAIAAAABAgAAACpkQXBwVXAgbXVzdCBiZSBkaWZmZXJlbnQgd2l0aCBhY3R1YWwgdmFsdWUJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAACURBUFBVUEtFWQUAAAAGZEFwcFVwBQAAAANuaWwAAAABaQEAAAADYmV0AAAAAQAAAAxwbGF5ZXJDaG9pY2UEAAAABmdhbWVJZAkAAlgAAAABCAUAAAABaQAAAA10cmFuc2FjdGlvbklkAwkBAAAAASEAAAABCQEAAAAISXNEQXBwVXAAAAAACQAAAgAAAAECAAAAGURBcHAgaXMgdW5kZXIgbWFpbnRlbmFuY2UDCQEAAAAJaXNEZWZpbmVkAAAAAQkABB0AAAACBQAAAAR0aGlzBQAAAAZnYW1lSWQJAAACAAAAAQkAASwAAAACCQABLAAAAAICAAAACUJldCBmb3I6IAUAAAAGZ2FtZUlkAgAAABIgd2FzIGFscmVhZHkgbWFkZS4EAAAAA3BtdAkBAAAAB2V4dHJhY3QAAAABCAUAAAABaQAAAAdwYXltZW50BAAAAA1iZXROb3RJbldhdmVzCQEAAAAJaXNEZWZpbmVkAAAAAQgFAAAAA3BtdAAAAAdhc3NldElkBAAAAAZ3aW5BbXQJAQAAABpWYWxpZGF0ZUJldEFuZERlZmluZVdpbkFtdAAAAAIIBQAAAANwbXQAAAAGYW1vdW50BQAAAAxwbGF5ZXJDaG9pY2UEAAAACHR4SWRVc2VkCQEAAAAJaXNEZWZpbmVkAAAAAQkABB0AAAACBQAAAAR0aGlzBQAAAAZnYW1lSWQDBQAAAA1iZXROb3RJbldhdmVzCQAAAgAAAAECAAAAG0JldCBhbW91bnQgbXVzdCBiZSBpbiBXYXZlcwQAAAAOcGxheWVyUHViS2V5NTgJAAJYAAAAAQgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5BAAAAAtnYW1lRGF0YVN0cgkBAAAAEUZvcm1hdEdhbWVEYXRhU3RyAAAABgUAAAAOU1RBVEVTVUJNSVRURUQFAAAADHBsYXllckNob2ljZQUAAAAOcGxheWVyUHViS2V5NTgFAAAABmhlaWdodAUAAAAGd2luQW10AgAAAAAJAQAAAAxTY3JpcHRSZXN1bHQAAAACCQEAAAAIV3JpdGVTZXQAAAABCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAA5SRVNFUlZBVElPTktFWQkBAAAAHlZhbGlkYXRlQW5kSW5jcmVhc2VSZXNlcnZlZEFtdAAAAAEFAAAABndpbkFtdAkABEwAAAACCQEAAAAMaW5jcmVtZW50SW50AAAAAQUAAAAPR0FNRVNDT1VOVEVSS0VZCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAA1NQVhCQUxBTkNFS0VZCQEAAAARbW9uaXRvck1heEJhbGFuY2UAAAAACQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAAZnYW1lSWQFAAAAC2dhbWVEYXRhU3RyBQAAAANuaWwJAQAAAAtUcmFuc2ZlclNldAAAAAEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAAGU0VSVkVSBQAAAApDT01NSVNTSU9OBQAAAAR1bml0BQAAAANuaWwAAAABaQEAAAAId2l0aGRyYXcAAAACAAAABmdhbWVJZAAAAAdyc2FTaWduBAAAAAxnYW1lRGF0YUxpc3QJAQAAABNFeHRyYWN0R2FtZURhdGFMaXN0AAAAAQUAAAAGZ2FtZUlkBAAAAAlnYW1lU3RhdGUJAAGRAAAAAgUAAAAMZ2FtZURhdGFMaXN0BQAAAAxJZHhHYW1lU3RhdGUEAAAADHBsYXllckNob2ljZQkAAZEAAAACBQAAAAxnYW1lRGF0YUxpc3QFAAAAD0lkeFBsYXllckNob2ljZQQAAAANc3RhcnRlZEhlaWdodAkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAADGdhbWVEYXRhTGlzdAUAAAAQSWR4U3RhcnRlZEhlaWdodAQAAAAGd2luQW10CQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAMZ2FtZURhdGFMaXN0BQAAAAlJZHhXaW5BbXQEAAAADnBsYXllclB1YktleTU4CQABkQAAAAIFAAAADGdhbWVEYXRhTGlzdAUAAAARSWR4UGxheWVyUHViS2V5NTgEAAAADXBsYXllckFkZHJlc3MJAQAAABRhZGRyZXNzRnJvbVB1YmxpY0tleQAAAAEJAAJZAAAAAQUAAAAOcGxheWVyUHViS2V5NTgEAAAADHdpbkJ5VGltZW91dAkAAGYAAAACCQAAZQAAAAIFAAAABmhlaWdodAUAAAANc3RhcnRlZEhlaWdodAUAAAATUkFORE9SQUNMRVRJTUVGUkFNRQQAAAARZGVjcmVhc2VkUmVzZXJ2ZXMJAQAAABNEZWNyZWFzZVJlc2VydmVkQW10AAAAAgUAAAAGZ2FtZUlkBQAAAAZ3aW5BbXQDCQEAAAACIT0AAAACBQAAAAlnYW1lU3RhdGUFAAAADlNUQVRFU1VCTUlUVEVECQAAAgAAAAECAAAAJEludmFsaWQgZ2FtZSBzdGF0ZSBmb3IgcGFzc2VkIGdhbWVJZAMFAAAADHdpbkJ5VGltZW91dAQAAAAHcmFuZFN0cgkAAS8AAAACBQAAAAxwbGF5ZXJDaG9pY2UAAAAAAAAAAAEEAAAADm5ld0dhbWVEYXRhU3RyCQEAAAARRm9ybWF0R2FtZURhdGFTdHIAAAAGBQAAAAhTVEFURVdPTgUAAAAMcGxheWVyQ2hvaWNlBQAAAA5wbGF5ZXJQdWJLZXk1OAUAAAANc3RhcnRlZEhlaWdodAUAAAAGd2luQW10BQAAAAdyYW5kU3RyCQEAAAAMV2luU2NyaXB0U2V0AAAABgUAAAAGZ2FtZUlkBQAAAA1wbGF5ZXJBZGRyZXNzBQAAAAZ3aW5BbXQFAAAADm5ld0dhbWVEYXRhU3RyBQAAAAx3aW5CeVRpbWVvdXQFAAAAEWRlY3JlYXNlZFJlc2VydmVzBAAAAAdyYW5kU3RyCQEAAAAJUmFuZFRvU3RyAAAAAQkBAAAAD0dlbmVyYXRlUmFuZEludAAAAAIFAAAABmdhbWVJZAUAAAAHcnNhU2lnbgMJAQAAAAIhPQAAAAIIBQAAAAFpAAAABmNhbGxlcgUAAAAGU0VSVkVSCQAAAgAAAAECAAAAK1JlZ3VsYXIgd2l0aGRyYXcgY2FuIGJlIGRvbmUgYnkgc2VydmVyIG9ubHkDCQEAAAALSXNQbGF5ZXJXaW4AAAACBQAAAAxwbGF5ZXJDaG9pY2UFAAAAB3JhbmRTdHIEAAAADm5ld0dhbWVEYXRhU3RyCQEAAAARRm9ybWF0R2FtZURhdGFTdHIAAAAGBQAAAAhTVEFURVdPTgUAAAAMcGxheWVyQ2hvaWNlBQAAAA5wbGF5ZXJQdWJLZXk1OAUAAAANc3RhcnRlZEhlaWdodAUAAAAGd2luQW10BQAAAAdyYW5kU3RyCQEAAAAMV2luU2NyaXB0U2V0AAAABgUAAAAGZ2FtZUlkBQAAAA1wbGF5ZXJBZGRyZXNzBQAAAAZ3aW5BbXQFAAAADm5ld0dhbWVEYXRhU3RyBQAAAAx3aW5CeVRpbWVvdXQFAAAAEWRlY3JlYXNlZFJlc2VydmVzBAAAAA5uZXdHYW1lRGF0YVN0cgkBAAAAEUZvcm1hdEdhbWVEYXRhU3RyAAAABgUAAAAJU1RBVEVMT1NUBQAAAAxwbGF5ZXJDaG9pY2UFAAAADnBsYXllclB1YktleTU4BQAAAA1zdGFydGVkSGVpZ2h0BQAAAAZ3aW5BbXQFAAAAB3JhbmRTdHIJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAABmdhbWVJZAUAAAAObmV3R2FtZURhdGFTdHIJAARMAAAAAgUAAAARZGVjcmVhc2VkUmVzZXJ2ZXMFAAAAA25pbAAAAAEAAAACdHgBAAAABnZlcmlmeQAAAAADCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAAgFAAAAAnR4AAAAD3NlbmRlclB1YmxpY0tleQQAAAAHJG1hdGNoMAUAAAACdHgDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAE1RyYW5zZmVyVHJhbnNhY3Rpb24EAAAAA3R0eAUAAAAHJG1hdGNoMAkAAGcAAAACCQAAZQAAAAIJAQAAAAx3YXZlc0JhbGFuY2UAAAABBQAAAAR0aGlzCAUAAAADdHR4AAAABmFtb3VudAkBAAAAEkV4dHJhY3RSZXNlcnZlZEFtdAAAAAADCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAFFNldFNjcmlwdFRyYW5zYWN0aW9uBAAAAANzdHgFAAAAByRtYXRjaDADCQAAAAAAAAIJAQAAAAhJc0RBcHBVcAAAAAAHCQAAAAAAAAIJAQAAABJFeHRyYWN0UmVzZXJ2ZWRBbXQAAAAAAAAAAAAAAAAABwcHlo1jbw==", "chainId": 84, "height": 942100, "spentComplexity": 0 } View: original | compacted Prev: B5sh5eCzMdCK9paWDLCYPuA5K58YRVhyZedKNwx1fbiW Next: none Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 3 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+let WAVELET = ((100 * 1000) * 1000)
5+
6+let COMMISSION = ((5 * WAVELET) / 1000)
7+
48 let RSAPUBLIC = fromBase64String("base64:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmpuXcI/o4pIB5ywv9DOOGapTBUwRVlM/6+H6hFelOXtkrwY/YItmPxEDpz7rAerQPQe9tDPEaAv/GnlEztybOFXgu9DzDe8YoMRD1vakgoAcogmbY58QD6KMj5HkoVj/yTNIc9szj5qhIlrAdmb3KLL6hQU7y8+Jj69BWVPsaQgkspSdeYtb1tHQc7t95n7OZ56r2A7G3+bQf6nSMkPkAhIrEpbCm58oiGBczdTd/LqFSVotZsbL7Yh6SHLfnHeD+QgcfJrnam8OHMGJEJTRXjILeHGjlRCP8oVpioHry1S2xPx5sVzIm2MM+CzYenAGlo0j26atBhiULoTulwD3pQIDAQAB")
59
610 let SERVER = addressFromStringValue("3NCiG28LmWyTigWG13E5QnvdHBsZFYXSS2j")
711
812 let RANDORACLETIMEFRAME = 4320
913
10-let WAVELET = ((100 * 1000) * 1000)
11-
12-let COMMISSION = ((5 * WAVELET) / 1000)
14+let MAXBALANCEDIFF = 100000000
1315
1416 let BET1 = (1 * WAVELET)
1517
3335
3436 let RATE5 = 11400
3537
38+let RATES = [RATE1, RATE2, RATE3, RATE4, RATE5]
39+
40+let BETS = [BET1, BET2, BET4, BET8, BET14]
41+
3642 let IdxGameState = 0
3743
3844 let IdxPlayerChoice = 1
4955
5056 let GAMESCOUNTERKEY = "$GAME_NUM"
5157
58+let DAPPUPKEY = "$DAPP_UP"
59+
60+let MAXBALANCEKEY = "$MAX_BALANCE"
61+
5262 let STATESUBMITTED = "SUBMITTED"
5363
5464 let STATEWON = "WON"
5565
5666 let STATELOST = "LOST"
5767
58-func IncrementGameNum () = {
59- let gameNum = match getInteger(this, GAMESCOUNTERKEY) {
60- case num: Int =>
61- num
62- case _ =>
63- 0
64- }
65- (gameNum + 1)
66- }
68+func getIntOr (key,default) = if (isDefined(getInteger(this, key)))
69+ then getIntegerValue(this, key)
70+ else default
71+
72+
73+func setInt (key,value) = DataEntry(key, value)
74+
75+
76+func incrementInt (key) = setInt(key, (getIntOr(key, -1) + 1))
6777
6878
6979 func ExtractReservedAmt () = match getInteger(this, RESERVATIONKEY) {
102112 then true
103113 else (betAmt == (BET14 + COMMISSION))
104114 if (betAmtValid)
105- then {
115+ then throw("Bet amount is not in range")
116+ else {
106117 let dicesCount = size(playerChoice)
107118 let bet = (betAmt - COMMISSION)
108119 if ((dicesCount == 1))
117128 then ((bet * RATE5) / RATEMULT)
118129 else throw("Invalid dices count in player's choice")
119130 }
120- else throw("Bet amount is not in range")
121131 }
122132
123133
151161
152162 func IsPlayerWin (playerChoice,randStr) = {
153163 let s = size(playerChoice)
154- if (if (if (if (if (if ((s >= 1))
164+ if (if (if (if (if ((s >= 1))
155165 then (take(drop(playerChoice, 0), 1) == randStr)
156166 else false)
157167 then true
167177 then (take(drop(playerChoice, 3), 1) == randStr)
168178 else false)
169179 then true
170- else if ((s >= 5))
180+ else if ((s == 5))
171181 then (take(drop(playerChoice, 4), 1) == randStr)
172- else false)
173- then true
174- else if ((s >= 6))
175- then (take(drop(playerChoice, 5), 1) == randStr)
176182 else false
177183 }
178184
253259 }
254260
255261
262+func IsDAppUp () = {
263+ let dAppUpOpt = getBoolean(this, DAPPUPKEY)
264+ if (isDefined(dAppUpOpt))
265+ then extract(dAppUpOpt)
266+ else false
267+ }
268+
269+
270+func monitorMaxBalance () = {
271+ let maxBalanceOpt = getInteger(this, MAXBALANCEKEY)
272+ let maxBalance = if (isDefined(maxBalanceOpt))
273+ then extract(maxBalanceOpt)
274+ else 0
275+ let currBalance = wavesBalance(this)
276+ if ((currBalance > maxBalance))
277+ then currBalance
278+ else {
279+ let diff = (maxBalance - currBalance)
280+ if ((diff > MAXBALANCEDIFF))
281+ then throw("dApp is temporary disabled")
282+ else maxBalance
283+ }
284+ }
285+
286+
287+@Callable(i)
288+func dAppUp (dAppUp) = if ((i.caller != SERVER))
289+ then throw("Only Server can manage dAppUp attribute")
290+ else if ((IsDAppUp() == dAppUp))
291+ then throw("dAppUp must be different with actual value")
292+ else WriteSet([DataEntry(DAPPUPKEY, dAppUp)])
293+
294+
295+
256296 @Callable(i)
257297 func bet (playerChoice) = {
258- let newGameNum = IncrementGameNum()
259298 let gameId = toBase58String(i.transactionId)
260- let pmt = extract(i.payment)
261- let betNotInWaves = isDefined(pmt.assetId)
262- let feeNotInWaves = isDefined(pmt.assetId)
263- let winAmt = ValidateBetAndDefineWinAmt(pmt.amount, playerChoice)
264- let txIdUsed = isDefined(getString(this, gameId))
265- if (betNotInWaves)
266- then throw("Bet amount must be in Waves")
267- else if (feeNotInWaves)
268- then throw("Transaction's fee must be in Waves")
269- else if (txIdUsed)
270- then throw("Passed txId had been used before. Game aborted.")
271- else {
272- let playerPubKey58 = toBase58String(i.callerPublicKey)
273- let gameDataStr = FormatGameDataStr(STATESUBMITTED, playerChoice, playerPubKey58, height, winAmt, "")
274- ScriptResult(WriteSet([DataEntry(RESERVATIONKEY, ValidateAndIncreaseReservedAmt(winAmt)), DataEntry(GAMESCOUNTERKEY, newGameNum), DataEntry(gameId, gameDataStr)]), TransferSet([ScriptTransfer(SERVER, COMMISSION, unit)]))
275- }
299+ if (!(IsDAppUp()))
300+ then throw("DApp is under maintenance")
301+ else if (isDefined(getString(this, gameId)))
302+ then throw((("Bet for: " + gameId) + " was already made."))
303+ else {
304+ let pmt = extract(i.payment)
305+ let betNotInWaves = isDefined(pmt.assetId)
306+ let winAmt = ValidateBetAndDefineWinAmt(pmt.amount, playerChoice)
307+ let txIdUsed = isDefined(getString(this, gameId))
308+ if (betNotInWaves)
309+ then throw("Bet amount must be in Waves")
310+ else {
311+ let playerPubKey58 = toBase58String(i.callerPublicKey)
312+ let gameDataStr = FormatGameDataStr(STATESUBMITTED, playerChoice, playerPubKey58, height, winAmt, "")
313+ ScriptResult(WriteSet([DataEntry(RESERVATIONKEY, ValidateAndIncreaseReservedAmt(winAmt)), incrementInt(GAMESCOUNTERKEY), DataEntry(MAXBALANCEKEY, monitorMaxBalance()), DataEntry(gameId, gameDataStr)]), TransferSet([ScriptTransfer(SERVER, COMMISSION, unit)]))
314+ }
315+ }
276316 }
277317
278318
298338 }
299339 else {
300340 let randStr = RandToStr(GenerateRandInt(gameId, rsaSign))
301- if (IsPlayerWin(playerChoice, randStr))
302- then {
303- let newGameDataStr = FormatGameDataStr(STATEWON, playerChoice, playerPubKey58, startedHeight, winAmt, randStr)
304- WinScriptSet(gameId, playerAddress, winAmt, newGameDataStr, winByTimeout, decreasedReserves)
305- }
306- else {
307- let newGameDataStr = FormatGameDataStr(STATELOST, playerChoice, playerPubKey58, startedHeight, winAmt, randStr)
308- WriteSet([DataEntry(gameId, newGameDataStr), decreasedReserves])
309- }
341+ if ((i.caller != SERVER))
342+ then throw("Regular withdraw can be done by server only")
343+ else if (IsPlayerWin(playerChoice, randStr))
344+ then {
345+ let newGameDataStr = FormatGameDataStr(STATEWON, playerChoice, playerPubKey58, startedHeight, winAmt, randStr)
346+ WinScriptSet(gameId, playerAddress, winAmt, newGameDataStr, winByTimeout, decreasedReserves)
347+ }
348+ else {
349+ let newGameDataStr = FormatGameDataStr(STATELOST, playerChoice, playerPubKey58, startedHeight, winAmt, randStr)
350+ WriteSet([DataEntry(gameId, newGameDataStr), decreasedReserves])
351+ }
310352 }
311353 }
312354
317359 case ttx: TransferTransaction =>
318360 ((wavesBalance(this) - ttx.amount) >= ExtractReservedAmt())
319361 case stx: SetScriptTransaction =>
320- true
362+ if ((IsDAppUp() == false))
363+ then (ExtractReservedAmt() == 0)
364+ else false
321365 case _ =>
322366 false
323367 }
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 3 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+let WAVELET = ((100 * 1000) * 1000)
5+
6+let COMMISSION = ((5 * WAVELET) / 1000)
7+
48 let RSAPUBLIC = fromBase64String("base64:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmpuXcI/o4pIB5ywv9DOOGapTBUwRVlM/6+H6hFelOXtkrwY/YItmPxEDpz7rAerQPQe9tDPEaAv/GnlEztybOFXgu9DzDe8YoMRD1vakgoAcogmbY58QD6KMj5HkoVj/yTNIc9szj5qhIlrAdmb3KLL6hQU7y8+Jj69BWVPsaQgkspSdeYtb1tHQc7t95n7OZ56r2A7G3+bQf6nSMkPkAhIrEpbCm58oiGBczdTd/LqFSVotZsbL7Yh6SHLfnHeD+QgcfJrnam8OHMGJEJTRXjILeHGjlRCP8oVpioHry1S2xPx5sVzIm2MM+CzYenAGlo0j26atBhiULoTulwD3pQIDAQAB")
59
610 let SERVER = addressFromStringValue("3NCiG28LmWyTigWG13E5QnvdHBsZFYXSS2j")
711
812 let RANDORACLETIMEFRAME = 4320
913
10-let WAVELET = ((100 * 1000) * 1000)
11-
12-let COMMISSION = ((5 * WAVELET) / 1000)
14+let MAXBALANCEDIFF = 100000000
1315
1416 let BET1 = (1 * WAVELET)
1517
1618 let BET2 = (2 * WAVELET)
1719
1820 let BET4 = (4 * WAVELET)
1921
2022 let BET8 = (8 * WAVELET)
2123
2224 let BET14 = (14 * WAVELET)
2325
2426 let RATEMULT = 10000
2527
2628 let RATE1 = 39655
2729
2830 let RATE2 = 24600
2931
3032 let RATE3 = 19000
3133
3234 let RATE4 = 14200
3335
3436 let RATE5 = 11400
3537
38+let RATES = [RATE1, RATE2, RATE3, RATE4, RATE5]
39+
40+let BETS = [BET1, BET2, BET4, BET8, BET14]
41+
3642 let IdxGameState = 0
3743
3844 let IdxPlayerChoice = 1
3945
4046 let IdxPlayerPubKey58 = 2
4147
4248 let IdxStartedHeight = 3
4349
4450 let IdxWinAmt = 4
4551
4652 let IdxRandOrEmpty = 5
4753
4854 let RESERVATIONKEY = "$RESERVED_AMOUNT"
4955
5056 let GAMESCOUNTERKEY = "$GAME_NUM"
5157
58+let DAPPUPKEY = "$DAPP_UP"
59+
60+let MAXBALANCEKEY = "$MAX_BALANCE"
61+
5262 let STATESUBMITTED = "SUBMITTED"
5363
5464 let STATEWON = "WON"
5565
5666 let STATELOST = "LOST"
5767
58-func IncrementGameNum () = {
59- let gameNum = match getInteger(this, GAMESCOUNTERKEY) {
60- case num: Int =>
61- num
62- case _ =>
63- 0
64- }
65- (gameNum + 1)
66- }
68+func getIntOr (key,default) = if (isDefined(getInteger(this, key)))
69+ then getIntegerValue(this, key)
70+ else default
71+
72+
73+func setInt (key,value) = DataEntry(key, value)
74+
75+
76+func incrementInt (key) = setInt(key, (getIntOr(key, -1) + 1))
6777
6878
6979 func ExtractReservedAmt () = match getInteger(this, RESERVATIONKEY) {
7080 case a: Int =>
7181 a
7282 case _ =>
7383 0
7484 }
7585
7686
7787 func ValidateAndIncreaseReservedAmt (winAmt) = {
7888 let newReservedAmount = (ExtractReservedAmt() + winAmt)
7989 let balance = wavesBalance(this)
8090 if ((newReservedAmount > balance))
8191 then throw("Insufficient funds on Dice Roller account. Transaction was rejected for your safety.")
8292 else newReservedAmount
8393 }
8494
8595
8696 func DecreaseReservedAmt (gameId,winAmt) = {
8797 let newReservedAmount = (ExtractReservedAmt() - winAmt)
8898 if ((0 > newReservedAmount))
8999 then throw("Invalid Dice Roller account state - reserved amount is less than 0")
90100 else DataEntry(RESERVATIONKEY, newReservedAmount)
91101 }
92102
93103
94104 func ValidateBetAndDefineWinAmt (betAmt,playerChoice) = {
95105 let betAmtValid = if (if (if (if ((betAmt == (BET1 + COMMISSION)))
96106 then true
97107 else (betAmt == (BET2 + COMMISSION)))
98108 then true
99109 else (betAmt == (BET4 + COMMISSION)))
100110 then true
101111 else (betAmt == (BET8 + COMMISSION)))
102112 then true
103113 else (betAmt == (BET14 + COMMISSION))
104114 if (betAmtValid)
105- then {
115+ then throw("Bet amount is not in range")
116+ else {
106117 let dicesCount = size(playerChoice)
107118 let bet = (betAmt - COMMISSION)
108119 if ((dicesCount == 1))
109120 then ((bet * RATE1) / RATEMULT)
110121 else if ((dicesCount == 2))
111122 then ((bet * RATE2) / RATEMULT)
112123 else if ((dicesCount == 3))
113124 then ((bet * RATE3) / RATEMULT)
114125 else if ((dicesCount == 4))
115126 then ((bet * RATE4) / RATEMULT)
116127 else if ((dicesCount == 5))
117128 then ((bet * RATE5) / RATEMULT)
118129 else throw("Invalid dices count in player's choice")
119130 }
120- else throw("Bet amount is not in range")
121131 }
122132
123133
124134 func RandToStr (r) = if ((r == 0))
125135 then "1"
126136 else if ((r == 1))
127137 then "2"
128138 else if ((r == 2))
129139 then "3"
130140 else if ((r == 3))
131141 then "4"
132142 else if ((r == 4))
133143 then "5"
134144 else if ((r == 5))
135145 then "6"
136146 else throw(("Unsupported r parameter passed: expected=[0,...,5] actual=" + toString(r)))
137147
138148
139149 func GenerateRandInt (gameId,rsaSign) = {
140150 let rsaSigValid = rsaVerify(SHA256, toBytes(gameId), rsaSign, RSAPUBLIC)
141151 if (rsaSigValid)
142152 then {
143153 let rand = (toInt(sha256(rsaSign)) % 6)
144154 if ((0 > rand))
145155 then (-1 * rand)
146156 else rand
147157 }
148158 else throw("Invalid RSA signature")
149159 }
150160
151161
152162 func IsPlayerWin (playerChoice,randStr) = {
153163 let s = size(playerChoice)
154- if (if (if (if (if (if ((s >= 1))
164+ if (if (if (if (if ((s >= 1))
155165 then (take(drop(playerChoice, 0), 1) == randStr)
156166 else false)
157167 then true
158168 else if ((s >= 2))
159169 then (take(drop(playerChoice, 1), 1) == randStr)
160170 else false)
161171 then true
162172 else if ((s >= 3))
163173 then (take(drop(playerChoice, 2), 1) == randStr)
164174 else false)
165175 then true
166176 else if ((s >= 4))
167177 then (take(drop(playerChoice, 3), 1) == randStr)
168178 else false)
169179 then true
170- else if ((s >= 5))
180+ else if ((s == 5))
171181 then (take(drop(playerChoice, 4), 1) == randStr)
172- else false)
173- then true
174- else if ((s >= 6))
175- then (take(drop(playerChoice, 5), 1) == randStr)
176182 else false
177183 }
178184
179185
180186 func FormatGameDataParam (p) = {
181187 let s = size(p)
182188 if ((s == 0))
183189 then throw("Parameter size must be greater then 0")
184190 else if ((s > 99))
185191 then throw("Parameter size must be less then 100")
186192 else if ((10 > s))
187193 then (("0" + toString(s)) + p)
188194 else (toString(s) + p)
189195 }
190196
191197
192198 func FormatGameDataStr (gameState,playerChoice,playerPubKey58,startedHeight,winAmt,randOrEmpty) = {
193199 let fullStateStr = ((((((((FormatGameDataParam(gameState) + "_") + FormatGameDataParam(playerChoice)) + "_") + FormatGameDataParam(playerPubKey58)) + "_") + FormatGameDataParam(toString(startedHeight))) + "_") + FormatGameDataParam(toString(winAmt)))
194200 if ((randOrEmpty == ""))
195201 then fullStateStr
196202 else ((fullStateStr + "_") + FormatGameDataParam(randOrEmpty))
197203 }
198204
199205
200206 func RemoveUnderscoreIfPresent (remaining) = if ((size(remaining) > 0))
201207 then drop(remaining, 1)
202208 else remaining
203209
204210
205211 func ParseNextAttribute (remaining) = {
206212 let s = size(remaining)
207213 if ((s > 0))
208214 then {
209215 let nn = parseIntValue(take(remaining, 2))
210216 let v = take(drop(remaining, 2), nn)
211217 let tmpRemaining = drop(remaining, (nn + 2))
212218 let remainingState = RemoveUnderscoreIfPresent(tmpRemaining)
213219 [v, remainingState]
214220 }
215221 else throw("Empty string was passed into parseNextAttribute func")
216222 }
217223
218224
219225 func ParseGameRawDataStr (rawStateStr) = {
220226 let gameState = ParseNextAttribute(rawStateStr)
221227 let playerChoice = ParseNextAttribute(gameState[1])
222228 let playerPubKey58 = ParseNextAttribute(playerChoice[1])
223229 let startedHeight = ParseNextAttribute(playerPubKey58[1])
224230 let winAmt = ParseNextAttribute(startedHeight[1])
225231 [gameState[0], playerChoice[0], playerPubKey58[0], startedHeight[0], winAmt[0]]
226232 }
227233
228234
229235 func ExtractGameDataList (gameId) = {
230236 let rawDataStr = match getString(this, gameId) {
231237 case str: String =>
232238 str
233239 case _ =>
234240 throw(("Couldn't find game by " + gameId))
235241 }
236242 ParseGameRawDataStr(rawDataStr)
237243 }
238244
239245
240246 func WinScriptSet (gameId,playerAddress,winAmt,newGameDataStr,winByTimeout,decreasedReserves) = {
241247 let wSetCommonData = [decreasedReserves]
242248 let tSetCommonData = [ScriptTransfer(playerAddress, winAmt, unit)]
243249 if (winByTimeout)
244250 then {
245251 let newGameDataStrAdjusted = ((newGameDataStr + "_") + FormatGameDataParam("TIMEOUT"))
246252 let gameData = DataEntry(gameId, newGameDataStrAdjusted)
247253 ScriptResult(WriteSet(gameData :: wSetCommonData), TransferSet(tSetCommonData))
248254 }
249255 else {
250256 let gameData = DataEntry(gameId, newGameDataStr)
251257 ScriptResult(WriteSet(gameData :: wSetCommonData), TransferSet(tSetCommonData))
252258 }
253259 }
254260
255261
262+func IsDAppUp () = {
263+ let dAppUpOpt = getBoolean(this, DAPPUPKEY)
264+ if (isDefined(dAppUpOpt))
265+ then extract(dAppUpOpt)
266+ else false
267+ }
268+
269+
270+func monitorMaxBalance () = {
271+ let maxBalanceOpt = getInteger(this, MAXBALANCEKEY)
272+ let maxBalance = if (isDefined(maxBalanceOpt))
273+ then extract(maxBalanceOpt)
274+ else 0
275+ let currBalance = wavesBalance(this)
276+ if ((currBalance > maxBalance))
277+ then currBalance
278+ else {
279+ let diff = (maxBalance - currBalance)
280+ if ((diff > MAXBALANCEDIFF))
281+ then throw("dApp is temporary disabled")
282+ else maxBalance
283+ }
284+ }
285+
286+
287+@Callable(i)
288+func dAppUp (dAppUp) = if ((i.caller != SERVER))
289+ then throw("Only Server can manage dAppUp attribute")
290+ else if ((IsDAppUp() == dAppUp))
291+ then throw("dAppUp must be different with actual value")
292+ else WriteSet([DataEntry(DAPPUPKEY, dAppUp)])
293+
294+
295+
256296 @Callable(i)
257297 func bet (playerChoice) = {
258- let newGameNum = IncrementGameNum()
259298 let gameId = toBase58String(i.transactionId)
260- let pmt = extract(i.payment)
261- let betNotInWaves = isDefined(pmt.assetId)
262- let feeNotInWaves = isDefined(pmt.assetId)
263- let winAmt = ValidateBetAndDefineWinAmt(pmt.amount, playerChoice)
264- let txIdUsed = isDefined(getString(this, gameId))
265- if (betNotInWaves)
266- then throw("Bet amount must be in Waves")
267- else if (feeNotInWaves)
268- then throw("Transaction's fee must be in Waves")
269- else if (txIdUsed)
270- then throw("Passed txId had been used before. Game aborted.")
271- else {
272- let playerPubKey58 = toBase58String(i.callerPublicKey)
273- let gameDataStr = FormatGameDataStr(STATESUBMITTED, playerChoice, playerPubKey58, height, winAmt, "")
274- ScriptResult(WriteSet([DataEntry(RESERVATIONKEY, ValidateAndIncreaseReservedAmt(winAmt)), DataEntry(GAMESCOUNTERKEY, newGameNum), DataEntry(gameId, gameDataStr)]), TransferSet([ScriptTransfer(SERVER, COMMISSION, unit)]))
275- }
299+ if (!(IsDAppUp()))
300+ then throw("DApp is under maintenance")
301+ else if (isDefined(getString(this, gameId)))
302+ then throw((("Bet for: " + gameId) + " was already made."))
303+ else {
304+ let pmt = extract(i.payment)
305+ let betNotInWaves = isDefined(pmt.assetId)
306+ let winAmt = ValidateBetAndDefineWinAmt(pmt.amount, playerChoice)
307+ let txIdUsed = isDefined(getString(this, gameId))
308+ if (betNotInWaves)
309+ then throw("Bet amount must be in Waves")
310+ else {
311+ let playerPubKey58 = toBase58String(i.callerPublicKey)
312+ let gameDataStr = FormatGameDataStr(STATESUBMITTED, playerChoice, playerPubKey58, height, winAmt, "")
313+ ScriptResult(WriteSet([DataEntry(RESERVATIONKEY, ValidateAndIncreaseReservedAmt(winAmt)), incrementInt(GAMESCOUNTERKEY), DataEntry(MAXBALANCEKEY, monitorMaxBalance()), DataEntry(gameId, gameDataStr)]), TransferSet([ScriptTransfer(SERVER, COMMISSION, unit)]))
314+ }
315+ }
276316 }
277317
278318
279319
280320 @Callable(i)
281321 func withdraw (gameId,rsaSign) = {
282322 let gameDataList = ExtractGameDataList(gameId)
283323 let gameState = gameDataList[IdxGameState]
284324 let playerChoice = gameDataList[IdxPlayerChoice]
285325 let startedHeight = parseIntValue(gameDataList[IdxStartedHeight])
286326 let winAmt = parseIntValue(gameDataList[IdxWinAmt])
287327 let playerPubKey58 = gameDataList[IdxPlayerPubKey58]
288328 let playerAddress = addressFromPublicKey(fromBase58String(playerPubKey58))
289329 let winByTimeout = ((height - startedHeight) > RANDORACLETIMEFRAME)
290330 let decreasedReserves = DecreaseReservedAmt(gameId, winAmt)
291331 if ((gameState != STATESUBMITTED))
292332 then throw("Invalid game state for passed gameId")
293333 else if (winByTimeout)
294334 then {
295335 let randStr = take(playerChoice, 1)
296336 let newGameDataStr = FormatGameDataStr(STATEWON, playerChoice, playerPubKey58, startedHeight, winAmt, randStr)
297337 WinScriptSet(gameId, playerAddress, winAmt, newGameDataStr, winByTimeout, decreasedReserves)
298338 }
299339 else {
300340 let randStr = RandToStr(GenerateRandInt(gameId, rsaSign))
301- if (IsPlayerWin(playerChoice, randStr))
302- then {
303- let newGameDataStr = FormatGameDataStr(STATEWON, playerChoice, playerPubKey58, startedHeight, winAmt, randStr)
304- WinScriptSet(gameId, playerAddress, winAmt, newGameDataStr, winByTimeout, decreasedReserves)
305- }
306- else {
307- let newGameDataStr = FormatGameDataStr(STATELOST, playerChoice, playerPubKey58, startedHeight, winAmt, randStr)
308- WriteSet([DataEntry(gameId, newGameDataStr), decreasedReserves])
309- }
341+ if ((i.caller != SERVER))
342+ then throw("Regular withdraw can be done by server only")
343+ else if (IsPlayerWin(playerChoice, randStr))
344+ then {
345+ let newGameDataStr = FormatGameDataStr(STATEWON, playerChoice, playerPubKey58, startedHeight, winAmt, randStr)
346+ WinScriptSet(gameId, playerAddress, winAmt, newGameDataStr, winByTimeout, decreasedReserves)
347+ }
348+ else {
349+ let newGameDataStr = FormatGameDataStr(STATELOST, playerChoice, playerPubKey58, startedHeight, winAmt, randStr)
350+ WriteSet([DataEntry(gameId, newGameDataStr), decreasedReserves])
351+ }
310352 }
311353 }
312354
313355
314356 @Verifier(tx)
315357 func verify () = if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey))
316358 then match tx {
317359 case ttx: TransferTransaction =>
318360 ((wavesBalance(this) - ttx.amount) >= ExtractReservedAmt())
319361 case stx: SetScriptTransaction =>
320- true
362+ if ((IsDAppUp() == false))
363+ then (ExtractReservedAmt() == 0)
364+ else false
321365 case _ =>
322366 false
323367 }
324368 else false
325369

github/deemru/w8io/3ef1775 
164.66 ms