2022.08.08 11:05 [3240724] smart account 3P8w8NXZUtYdCA13tHbDY5sW4mC27ZFJgG3 > SELF 0.00000000 Waves

{ "type": 13, "id": "24XWyrzVBWBFbvMCBpUzntzxhT7R5zqdh2HJ47vNwbY4", "fee": 3100000, "feeAssetId": null, "timestamp": 1659947840872, "version": 1, "sender": "3P8w8NXZUtYdCA13tHbDY5sW4mC27ZFJgG3", "senderPublicKey": "6uKJV5r5qjqG9uVK4Q24W7zG5KZtGtKXz3NWRMwfZbB7", "proofs": [ "", "4wrRczJMTYP2AN7wjM5S5sRA3HPsRbaWX3dG8uFVeLTvGqxFfjMRCHq5jEuLsfCkxpQ1zq36D1q2uubcijVysVFM", "", "2qXSgvFyEunu3g4XgFJ8PwG6z9ksT12YZNBErReHaWKvKXUFdHMbRvbeo4YSV6xz2z3c2rCNPHgBRRFkskzUNeun" ], "script": "base64:AAIFAAAAAAAAACkIAhIHCgUICAEBCBIAEgMKAQESABIAEgASAwoBCBIECgIIARIECgIIAQAAAEgAAAAAC3JldmlzaW9uTnVtAgAAAChjYmQwYmRjOGJiYmE5MWRiNjQwNjZiMTZhODQ5MTNhNGM5NjVlMjNlAAAAAAlzZXBhcmF0b3ICAAAAAl9fAAAAAANTRVACAAAAAl9fAAAAAAVNVUxUNgAAAAAAAA9CQAAAAAAFTVVMVDgAAAAAAAX14QAAAAAABk1VTFRYNgkAATYAAAABBQAAAAVNVUxUNgAAAAAGTVVMVFg4CQABNgAAAAEFAAAABU1VTFQ4AAAAAAdNVUxUWDE4CQABNgAAAAEADeC2s6dkAAAAAAAACldBVkVTSURTVFICAAAABVdBVkVTAAAAAAdXQVZFU0lECQACWQAAAAEFAAAACldBVkVTSURTVFIAAAAAGUlkeENvbnRyb2xDZmdOZXV0cmlub0RhcHAAAAAAAAAAAAEAAAAAGElkeENvbnRyb2xDZmdBdWN0aW9uRGFwcAAAAAAAAAAAAgAAAAAUSWR4Q29udHJvbENmZ1JwZERhcHAAAAAAAAAAAAMAAAAAFUlkeENvbnRyb2xDZmdNYXRoRGFwcAAAAAAAAAAABAAAAAAcSWR4Q29udHJvbENmZ0xpcXVpZGF0aW9uRGFwcAAAAAAAAAAABQAAAAAVSWR4Q29udHJvbENmZ1Jlc3REYXBwAAAAAAAAAAAGAAAAAB1JZHhDb250cm9sQ2ZnTm9kZVJlZ2lzdHJ5RGFwcAAAAAAAAAAABwAAAAAcSWR4Q29udHJvbENmZ05zYnRTdGFraW5nRGFwcAAAAAAAAAAACAAAAAAZSWR4Q29udHJvbENmZ01lZGlhdG9yRGFwcAAAAAAAAAAACQEAAAAPZ2V0U3RyaW5nT3JGYWlsAAAAAgAAAAdhZGRyZXNzAAAAA2tleQkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAAB2FkZHJlc3MFAAAAA2tleQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAptYW5kYXRvcnkgCQAEJQAAAAEFAAAAB2FkZHJlc3MCAAAAAS4FAAAAA2tleQIAAAAPIGlzIG5vdCBkZWZpbmVkAQAAABFrZXlDb250cm9sQWRkcmVzcwAAAAACAAAAHCVzJXNfX2NvbmZpZ19fY29udHJvbEFkZHJlc3MBAAAADWtleUNvbnRyb2xDZmcAAAAAAgAAABElc19fY29udHJvbENvbmZpZwEAAAAUcmVhZENvbnRyb2xDZmdPckZhaWwAAAABAAAAB2NvbnRyb2wJAAS1AAAAAgkBAAAAD2dldFN0cmluZ09yRmFpbAAAAAIFAAAAB2NvbnRyb2wJAQAAAA1rZXlDb250cm9sQ2ZnAAAAAAUAAAADU0VQAQAAABhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwAAAACAAAACmNvbnRyb2xDZmcAAAADaWR4CQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQmAAAAAQkAAZEAAAACBQAAAApjb250cm9sQ2ZnBQAAAANpZHgJAAEsAAAAAgIAAAAtQ29udHJvbCBjZmcgZG9lc24ndCBjb250YWluIGFkZHJlc3MgYXQgaW5kZXggCQABpAAAAAEFAAAAA2lkeAAAAAAPY29udHJvbENvbnRyYWN0CQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABCQEAAAALdmFsdWVPckVsc2UAAAACCQAEHQAAAAIFAAAABHRoaXMJAQAAABFrZXlDb250cm9sQWRkcmVzcwAAAAACAAAAIzNQNUJmZDU4UFBmTnZCTTJIeThRZmJjRHFNZU50emc3S2ZQAAAAAApjb250cm9sQ2ZnCQEAAAAUcmVhZENvbnRyb2xDZmdPckZhaWwAAAABBQAAAA9jb250cm9sQ29udHJhY3QAAAAADG1hdGhDb250cmFjdAkBAAAAGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAAAAAIFAAAACmNvbnRyb2xDZmcFAAAAFUlkeENvbnRyb2xDZmdNYXRoRGFwcAAAAAAQbmV1dHJpbm9Db250cmFjdAkBAAAAGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAAAAAIFAAAACmNvbnRyb2xDZmcFAAAAGUlkeENvbnRyb2xDZmdOZXV0cmlub0RhcHAAAAAAD2F1Y3Rpb25Db250cmFjdAkBAAAAGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAAAAAIFAAAACmNvbnRyb2xDZmcFAAAAGElkeENvbnRyb2xDZmdBdWN0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YXRvcgEAAAASSGlzdG9yeVJlY29yZEVudHJ5AAAABwAAAAR0eXBlAAAAC3VzZXJBZGRyZXNzAAAABHR4SWQAAAAJb2xkQW1vdW50AAAACG9sZFN0YXJ0AAAACW5ld0Ftb3VudAAAAAhuZXdTdGFydAkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEGtleUhpc3RvcnlSZWNvcmQAAAADBQAAAAR0eXBlBQAAAAt1c2VyQWRkcmVzcwUAAAAEdHhJZAkBAAAAE2Zvcm1hdEhpc3RvcnlSZWNvcmQAAAAEBQAAAAlvbGRBbW91bnQFAAAACG9sZFN0YXJ0BQAAAAluZXdBbW91bnQFAAAACG5ld1N0YXJ0AQAAABFDbGFpbUhpc3RvcnlFbnRyeQAAAAMAAAALdXNlckFkZHJlc3MAAAAEdHhJZAAAAA5jbGFpbWVkUmV3YXJkcwkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEGtleUhpc3RvcnlSZWNvcmQAAAADAgAAAAVjbGFpbQUAAAALdXNlckFkZHJlc3MFAAAABHR4SWQJAQAAABhmb3JtYXRDbGFpbUhpc3RvcnlSZWNvcmQAAAACCQAEJQAAAAEFAAAAC3VzZXJBZGRyZXNzBQAAAA5jbGFpbWVkUmV3YXJkcwEAAAALU3RhdHNSZXN1bHQAAAADAAAADnRvdGFsTG9ja2VkSW5jAAAADGxvY2tDb3VudEluYwAAAA11c2Vyc0NvdW50SW5jBAAAAApsb2Nrc0NvdW50CQEAAAAMZ2V0SW50T3JaZXJvAAAAAQkBAAAAEmtleVN0YXRzTG9ja3NDb3VudAAAAAAEAAAACnVzZXJzQ291bnQJAQAAAAxnZXRJbnRPclplcm8AAAABCQEAAAASa2V5U3RhdHNVc2Vyc0NvdW50AAAAAAQAAAALdG90YWxBbW91bnQJAQAAAAxnZXRJbnRPclplcm8AAAABCQEAAAAXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQAAAAABAAAAA50b3RhbEFtb3VudE5ldwkAAGQAAAACBQAAAAt0b3RhbEFtb3VudAUAAAAOdG90YWxMb2NrZWRJbmMJAAUVAAAAAwkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAEmtleVN0YXRzTG9ja3NDb3VudAAAAAAJAABkAAAAAgUAAAAKbG9ja3NDb3VudAUAAAAMbG9ja0NvdW50SW5jCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAASa2V5U3RhdHNVc2Vyc0NvdW50AAAAAAkAAGQAAAACBQAAAAp1c2Vyc0NvdW50BQAAAA11c2Vyc0NvdW50SW5jCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQAAAAABQAAAA50b3RhbEFtb3VudE5ldwUAAAADbmlsBQAAAAt0b3RhbEFtb3VudAUAAAAOdG90YWxBbW91bnROZXcBAAAAD0xvY2tQYXJhbXNFbnRyeQAAAAMAAAALdXNlckFkZHJlc3MAAAAGYW1vdW50AAAABXN0YXJ0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAWa2V5TG9ja1BhcmFtVXNlckFtb3VudAAAAAEFAAAAC3VzZXJBZGRyZXNzBQAAAAZhbW91bnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABZrZXlMb2NrUGFyYW1TdGFydEJsb2NrAAAAAQUAAAALdXNlckFkZHJlc3MFAAAABXN0YXJ0BQAAAANuaWwBAAAAD2dldFBhcmFtc09yRmFpbAAAAAAJAAUVAAAAAwkAAlkAAAABCQEAAAARQGV4dHJOYXRpdmUoMTA1MykAAAACBQAAABBuZXV0cmlub0NvbnRyYWN0CQEAAAAMa2V5Qm9uZEFzc2V0AAAAAAkBAAAADGdldEludE9yRmFpbAAAAAEJAQAAABBrZXlNaW5Mb2NrQW1vdW50AAAAAAkBAAAADGdldEludE9yRmFpbAAAAAEJAQAAAAtrZXlIYWxmTGlmZQAAAAABAAAADGlzQWN0aXZlVXNlcgAAAAEAAAALdXNlckFkZHJlc3MJAABmAAAAAgkBAAAADGdldEludE9yRWxzZQAAAAIJAQAAABZrZXlMb2NrUGFyYW1Vc2VyQW1vdW50AAAAAQUAAAALdXNlckFkZHJlc3MAAAAAAAAAAAAAAAAAAAAAAAABAAAAE2dldFVzZXJQYXJhbXNPclVuaXQAAAABAAAAC3VzZXJBZGRyZXNzAwkBAAAADGlzQWN0aXZlVXNlcgAAAAEFAAAAC3VzZXJBZGRyZXNzCQAFFQAAAAMHCQEAAAAMZ2V0SW50T3JGYWlsAAAAAQkBAAAAFmtleUxvY2tQYXJhbVVzZXJBbW91bnQAAAABBQAAAAt1c2VyQWRkcmVzcwkBAAAADGdldEludE9yRmFpbAAAAAEJAQAAABZrZXlMb2NrUGFyYW1TdGFydEJsb2NrAAAAAQUAAAALdXNlckFkZHJlc3MFAAAABHVuaXQBAAAAE2dldFVzZXJQYXJhbXNPckZhaWwAAAABAAAAC3VzZXJBZGRyZXNzCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAQAAABNnZXRVc2VyUGFyYW1zT3JVbml0AAAAAQUAAAALdXNlckFkZHJlc3MJAAEsAAAAAgkAASwAAAACAgAAAAVVc2VyIAkABCUAAAABBQAAAAt1c2VyQWRkcmVzcwIAAAAPIGlzIG5vdCBkZWZpbmVkAAAAABJzdXBwb3J0ZWRBc3NldHNTdHIJAQAAAAxnZXRTdHJPckVsc2UAAAACCQEAAAAYa2V5U3VwcG9ydGVkUmV3YXJkQXNzZXRzAAAAAAIAAAAAAAAAABNzdXBwb3J0ZWRBc3NldHNMaXN0CQAEtQAAAAIFAAAAEnN1cHBvcnRlZEFzc2V0c1N0cgIAAAABXwEAAAAKY2FsY1Jld2FyZAAAAAUAAAALdXNlckFkZHJlc3MAAAAHYXNzZXRJZAAAAA1zdGFrZWRBbW91bnRYAAAADmRlcG9zaXROdW1Vc2VyAAAADmRlcG9zaXROdW1MYXN0BAAAABdyZXdhcmRQZXJOc2J0U3VtTGFzdEtFWQkBAAAAFWtleVJld2FyZFBlck5zYnRTdW1BdAAAAAIFAAAADmRlcG9zaXROdW1MYXN0BQAAAAdhc3NldElkBAAAAApzdW1MYXN0WDE4CQABpwAAAAEJAQAAAAxnZXRTdHJPckVsc2UAAAACCQEAAAAVa2V5UmV3YXJkUGVyTnNidFN1bUF0AAAAAgUAAAAOZGVwb3NpdE51bUxhc3QFAAAAB2Fzc2V0SWQCAAAAATAEAAAACnN1bVVzZXJYMTgJAAGnAAAAAQkBAAAADGdldFN0ck9yRWxzZQAAAAIJAQAAABVrZXlSZXdhcmRQZXJOc2J0U3VtQXQAAAACBQAAAA5kZXBvc2l0TnVtVXNlcgUAAAAHYXNzZXRJZAIAAAABMAQAAAARcmV3YXJkRHluYW1pY1BhcnQJAAGgAAAAAQkAATwAAAADCQABOAAAAAIFAAAACnN1bUxhc3RYMTgFAAAACnN1bVVzZXJYMTgFAAAADXN0YWtlZEFtb3VudFgFAAAAB01VTFRYMTgEAAAAE3Jld2FyZENhY2hlZFBhcnRLRVkJAQAAAAlrZXlSZXdhcmQAAAACBQAAAAt1c2VyQWRkcmVzcwUAAAAHYXNzZXRJZAQAAAAQcmV3YXJkQ2FjaGVkUGFydAkBAAAADGdldEludE9yRWxzZQAAAAIFAAAAE3Jld2FyZENhY2hlZFBhcnRLRVkAAAAAAAAAAAAJAAUWAAAABAkAAGQAAAACBQAAABByZXdhcmRDYWNoZWRQYXJ0BQAAABFyZXdhcmREeW5hbWljUGFydAUAAAAQcmV3YXJkQ2FjaGVkUGFydAUAAAARcmV3YXJkRHluYW1pY1BhcnQFAAAAE3Jld2FyZENhY2hlZFBhcnRLRVkBAAAADVJld2FyZEVudHJpZXMAAAADAAAACWlzTmV3VXNlcgAAAAt1c2VyQWRkcmVzcwAAAAxzdGFrZWRBbW91bnQEAAAADXN0YWtlZEFtb3VudFgJAAE2AAAAAQUAAAAMc3Rha2VkQW1vdW50BAAAABt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkJAQAAABtrZXlVc2VyUmV3YXJkRnJvbURlcG9zaXROdW0AAAABBQAAAAt1c2VyQWRkcmVzcwQAAAAOZGVwb3NpdE51bVVzZXIJAQAAAAxnZXRJbnRPckVsc2UAAAACBQAAABt1c2VyUmV3YXJkRnJvbURlcG9zaXROdW1LRVkA//////////8EAAAADmRlcG9zaXROdW1MYXN0CQEAAAAMZ2V0SW50T3JFbHNlAAAAAgkBAAAAEWtleURlcG9zaXROdW1MYXN0AAAAAAD//////////woBAAAAG2ZvckVhY2hBc3NldENhY2hlVXNlclJld2FyZAAAAAIAAAAFYWNjdW0AAAAFYXNzZXQEAAAACyR0MDg0NTA4NTg1CQEAAAAKY2FsY1Jld2FyZAAAAAUFAAAAC3VzZXJBZGRyZXNzBQAAAAVhc3NldAUAAAANc3Rha2VkQW1vdW50WAUAAAAO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AAAAAgAAAAt1c2VyQWRkcmVzcwAAAAFpBAAAAA51c2VyQWRkcmVzc1N0cgkABCUAAAABBQAAAAt1c2VyQWRkcmVzcwMJAABmAAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAkAAAIAAAABAgAAABlwYXltZW50cyBhcmUgbm90IGFjY2VwdGVkBAAAAA0kdDAxMTUyOTExNjM0CQEAAAALdmFsdWVPckVsc2UAAAACCQEAAAATZ2V0VXNlclBhcmFtc09yVW5pdAAAAAEFAAAAC3VzZXJBZGRyZXNzCQAFFQAAAAMGAAAAAAAAAAAAAAAAAAAAAAAABAAAAAlpc05ld1VzZXIIBQAAAA0kdDAxMTUyOTExNjM0AAAAAl8xBAAAAAxzdGFrZWRBbW91bnQIBQAAAA0kdDAxMTUyOTExNjM0AAAAAl8yBAAAAAxzdGFraW5nU3RhcnQIBQAAAA0kdDAxMTUyOTExNjM0AAAAAl8zBAAAAA1zdGFrZWRBbW91bnRYCQABNgAAAAEFAAAADHN0YWtlZEFtb3VudAQAAAAbdXNlclJld2FyZEZyb21EZXBvc2l0TnVtS0VZCQEAAAAba2V5VXNlclJld2FyZEZyb21EZXBvc2l0TnVtAAAAAQUAAAAOdXNlckFkZHJlc3NTdHIEAAAADmRlcG9zaXROdW1Vc2VyCQEAAAAMZ2V0SW50T3JFbHNlAAAAAgUAAAAbdXNlclJld2FyZEZyb21EZXBvc2l0TnVtS0VZAP//////////BAAAAA5kZXBvc2l0TnVtTGFzdAkBAAAADGdldEludE9yRWxzZQAAAAIJAQAAABFrZXlEZXBvc2l0TnVtTGFzdAAAAAAA//////////8KAQAAAB9mb3JFYWNoQXNzZXRDYWxjVW5jbGFpbWVkUmV3YXJkAAAAAgAAAAVhY2N1bQAAAAVhc3NldAQAAAANJHQwMTIwMDUxMjE0MwkBAAAACmNhbGNSZXdhcmQAAAAFBQAAAA51c2VyQWRkcmVzc1N0cgUAAAAFYXNzZXQFAAAADXN0YWtlZEFtb3VudFgFAAAADmRlcG9zaXROdW1Vc2VyBQAAAA5kZXBvc2l0TnVtTGFzdAQAAAALcmV3YXJkVG90YWwIBQAAAA0kdDAxMjAwNTEyMTQzAAAAAl8xBAAA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QnlBc3NldFJlc3VsdAAAAAAAAAAAAQAAAAkAAAABaQEAAAALY29uc3RydWN0b3IAAAAFAAAAF25ldXRyaW5vQ29udHJhY3RBZGRyZXNzAAAAE21hdGhDb250cmFjdEFkZHJlc3MAAAANbWluTG9ja0Ftb3VudAAAAAhoYWxmTGlmZQAAABVzdXBwb3J0ZWRSZXdhcmRBc3NldHMDCQEAAAACIT0AAAACCAUAAAABaQAAAAZjYWxsZXIFAAAABHRoaXMJAAACAAAAAQIAAAARUGVybWlzc2lvbiBkZW5pZWQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAGmtleU5ldXRyaW5vQ29udHJhY3RBZGRyZXNzAAAAAAUAAAAXbmV1dHJpbm9Db250cmFjdEFkZHJlc3MJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAFmtleU1hdGhDb250cmFjdEFkZHJlc3MAAAAABQAAABNtYXRoQ29udHJhY3RBZGRyZXNzCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAQa2V5TWluTG9ja0Ftb3VudAAAAAAFAAAADW1pbkxvY2tBbW91bnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAAAtrZXlIYWxmTGlmZQAAAAAFAAAACGhhbGZMaWZlCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABhrZXlTdXBwb3J0ZWRSZXdhcmRBc3NldHMAAAAABQAAABVzdXBwb3J0ZWRSZXdhcmRBc3NldHMFAAAAA25pbAAAAAFpAQAAAAVzdGFrZQAAAAAEAAAADSR0MDEzNjM4MTM3MDAJAQAAAA9nZXRQYXJhbXNPckZhaWwAAAAABAAAAAtib25kQXNzZXRJZAgFAAAADSR0MDEzNjM4MTM3MDAAAAACXzEEAAAADW1pbkxvY2tBbW91bnQIBQAAAA0kdDAxMzYzODEzNzAwAAAAAl8yBAAAAAhoYWxmTGlmZQgFAAAADSR0MDEzNjM4MTM3MDAAAAACXzMDCQEAAAACIT0AAAACCQABkAAAAAEIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAABCQAAAgAAAAECAAAAFUludmFsaWQgcGF5bWVudHMgc2l6ZQQAAAAHcGF5bWVudAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAQAAAAGYW1vdW50CAUAAAAHcGF5bWVudAAAAAZhbW91bnQEAAAAE2ludmFsaWRBc3NldE1lc3NhZ2UJAAEsAAAAAgkAASwAAAACAgAAAA9JbnZhbGlkIGFzc2V0LiAJAAJYAAAAAQUAAAALYm9uZEFzc2V0SWQCAAAADCBpcyBleHBlY3RlZAQAAAAHYXNzZXRJZAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCAUAAAAHcGF5bWVudAAAAAdhc3NldElkBQAAABNpbnZhbGlkQXNzZXRNZXNzYWdlAwkBAAAAAiE9AAAAAgUAAAAHYXNzZXRJZAUAAAALYm9uZEFzc2V0SWQJAAACAAAAAQUAAAATaW52YWxpZEFzc2V0TWVzc2FnZQQAAAALdXNlckFkZHJlc3MIBQAAAAFpAAAABmNhbGxlcgQAAAAOdXNlckFkZHJlc3NTdHIJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAAA0kdDAxNDI0MjE0MzQ5CQEAAAALdmFsdWVPckVsc2UAAAACCQEAAAATZ2V0VXNlclBhcmFtc09yVW5pdAAAAAEFAAAAC3VzZXJBZGRyZXNzCQAFFQAAAAMGAAAAAAAAAAAAAP//////////BAAAAAlpc05ld1VzZXIIBQAAAA0kdDAxNDI0MjE0MzQ5AAAAAl8xBAAAAApsb2NrQW1vdW50CAUAAAANJHQwMTQyNDIxNDM0OQAAAAJfMgQAAAAPbG9ja1N0YXJ0SGVpZ2h0CAUAAAANJHQwMTQyNDIxNDM0OQAAAAJfMwQAAAAMbWVyZ2VkQW1vdW50AwUAAAAJaXNOZXdVc2VyBQAAAAZhbW91bnQJAABkAAAAAgUAAAAGYW1vdW50BQAAAApsb2NrQW1vdW50BAAAABFtZXJnZWRTdGFydEhlaWdodAMFAAAACWlzTmV3VXNlcgUAAAAGaGVpZ2h0CQEAAAAFYXNJbnQAAAABCQAD/AAAAAQFAAAADG1hdGhDb250cmFjdAIAAAATbWVyZ2VTdGFrZXNSRUFET05MWQkABEwAAAACBQAAAAZhbW91bnQJAARMAAAAAgUAAAAGaGVpZ2h0CQAETAAAAAIFAAAACmxvY2tBbW91bnQJAARMAAAAAgUAAAAPbG9ja1N0YXJ0SGVpZ2h0CQAETAAAAAIFAAAACGhhbGZMaWZlBQAAAANuaWwFAAAAA25pbAMJAABmAAAAAgUAAAANbWluTG9ja0Ftb3VudAUAAAAMbWVyZ2VkQW1vdW50CQAAAgAAAAEJAAEsAAAAAgIAAAATTWluIGxvY2sgYW1vdW50IGlzIAkAAaQAAAABBQAAAA1taW5Mb2NrQW1vdW50BAAAAA0kdDAxNDcxMDE0ODEyCQEAAAALU3RhdHNSZXN1bHQAAAADBQAAAAZhbW91bnQAAAAAAAAAAAEDBQAAAAlpc05ld1VzZXIAAAAAAAAAAAEAAAAAAAAAAAAEAAAADHN0YXRzRW50cmllcwgFAAAADSR0MDE0NzEwMTQ4MTIAAAACXzEEAAAAC3RvdGFsU3Rha2VkCAUAAAANJHQwMTQ3MTAxNDgxMgAAAAJfMgQAAAAOdG90YWxTdGFrZWROZXcIBQAAAA0kdDAxNDcxMDE0ODEyAAAAAl8zCQAETgAAAAIJAAROAAAAAgkABE4AAAACCQAETAAAAAIJAQAAABJIaXN0b3J5UmVjb3JkRW50cnkAAAAHAgAAAAVzdGFrZQUAAAALdXNlckFkZHJlc3MIBQAAAAFpAAAADXRyYW5zYWN0aW9uSWQFAAAACmxvY2tBbW91bnQFAAAAD2xvY2tTdGFydEhlaWdodAUAAAAMbWVyZ2VkQW1vdW50BQAAABFtZXJnZWRTdGFydEhlaWdodAUAAAADbmlsCQEAAAANUmV3YXJkRW50cmllcwAAAAMFAAAACWlzTmV3VXNlcgUAAAAOdXNlckFkZHJlc3NTdHIFAAAACmxvY2tBbW91bnQJAQAAAA9Mb2NrUGFyYW1zRW50cnkAAAADBQAAAAt1c2VyQWRkcmVzcwUAAAAMbWVyZ2VkQW1vdW50BQAAABFtZXJnZWRTdGFydEhlaWdodAUAAAAMc3RhdHNFbnRyaWVzAAAAAWkBAAAAB3Vuc3Rha2UAAAABAAAABmFtb3VudAMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAJAAACAAAAAQIAAAAjdW5zdGFrZSBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnQEAAAAC3Vz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AAAAAAAABAAAAAZhbW91bnQIBQAAAANwbXQAAAAGYW1vdW50BAAAAApwbXRBc3NldElkCQEAAAALdmFsdWVPckVsc2UAAAACCAUAAAADcG10AAAAB2Fzc2V0SWQFAAAAB1dBVkVTSUQEAAAADXBtdEFzc2V0SWRTdHIJAAJYAAAAAQUAAAAKcG10QXNzZXRJZAQAAAAIcG10TXVsdFgDCQAAAAAAAAIFAAAACnBtdEFzc2V0SWQFAAAAB1dBVkVTSUQFAAAABk1VTFRYOAUAAAAGTVVMVFg2BAAAAAdhbW91bnRYCQABNgAAAAEFAAAABmFtb3VudAQAAAALdG90YWxTdGFrZWQJAQAAAAxnZXRJbnRPckVsc2UAAAACCQEAAAAXa2V5TG9ja1BhcmFtVG90YWxBbW91bnQAAAAAAAAAAAAAAAAABAAAAAx0b3RhbFN0YWtlZFgJAAE2AAAAAQUAAAALdG90YWxTdGFrZWQDCQAAZgAAAAIAAAAAAAAAAAAFAAAAC3RvdGFsU3Rha2VkCQAAAgAAAAECAAAAG1RPRE86IGNhc2UgaXMgbm90IHN1cHBvcnRlZAMJAAAAAAAAAgUAAAALdG90YWxTdGFrZWQAAAAAAAAAAAAJAQAAACJJbmNyZW1lbnROb3REaXN0cmlidXRlZFJld2FyZEVudHJ5AAAAAgUAAAANcG10QXNzZXRJZFN0cgUAAAAGYW1vdW50BAAAABByZXdhcmRQZXJOc2J0WDE4CQABPAAAAAMFAAAAB2Ftb3VudFgFAAAAB01VTFRYMTgFAAAADHRvdGFsU3Rha2VkWAQAAAARZGVwb3NpdE51bUxhc3RLRVkJAQAAABFrZXlEZXBvc2l0TnVtTGFzdAAAAAAEAAAADmRlcG9zaXROdW1MYXN0CQEAAAAMZ2V0SW50T3JFbHNlAAAAAgUAAAARZGVwb3NpdE51bUxhc3RLRVkA//////////8EAAAADWRlcG9zaXROdW1OZXcJAABkAAAAAgUAAAAOZGVwb3NpdE51bUxhc3QAAAAAAAAAAAEDCQEAAAABIQAAAAEJAQAAAAhjb250YWlucwAAAAIFAAAAEnN1cHBvcnRlZEFzc2V0c1N0cgUAAAANcG10QXNzZXRJZFN0cgkAAAIAAAABCQABLAAAAAIJAAEsAAAAAgUAAAASc3VwcG9y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bAQAAAALdXNlckFkZHJlc3MJAQAAAA90b0FkZHJlc3NPckZhaWwAAAABBQAAAA51c2VyQWRkcmVzc1N0cgQAAAANJHQwMjA4NDkyMDk1MwkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkBAAAAE2dldFVzZXJQYXJhbXNPclVuaXQAAAABBQAAAAt1c2VyQWRkcmVzcwkABRUAAAADBgAAAAAAAAAAAAAAAAAAAAAAAAQAAAAJaXNOZXdVc2VyCAUAAAANJHQwMjA4NDkyMDk1MwAAAAJfMQQAAAALdXNlck5zYnRBbXQIBQAAAA0kdDAyMDg0OTIwOTUzAAAAAl8yBAAAAAxzdGFraW5nU3RhcnQIBQAAAA0kdDAyMDg0OTIwOTUzAAAAAl8zCQAFFAAAAAIFAAAAA25pbAkABEwAAAACBQAAAAt1c2VyTnNidEFtdAkABEwAAAACBQAAAAx0b3RhbE5zYnRBbXQJAARMAAAAAgUAAAAMc3Rha2luZ1N0YXJ0BQAAAANuaWwAAAABAAAAAnR4AQAAAAZ2ZXJpZnkAAAAABAAAABNwdWJLZXlBZG1pbnNMaXN0U3RyCQAEuQAAAAIJAARMAAAAAgIAAAAsR0pkTFNhTGl2NUs3eHVlamFjOG1jUmNIb3lvM2RQckVTcnZrdEczYTZNQVIJAARMAAAAAgIAAAAsRVl3Wm1VUmQ1S0thUVJCanNWYTZnOERQaXNGb1M2U292Ukp0RmlMNWdNSFUJAARMAAAAAgIAAAAsRHRtQWZ1RGRDckhLOHNwZEFlQVl6cTZNc1plZ2VEOWduc3JwdVRSa0NiVkEJAARMAAAAAgIAAAAsNVdSWEZTandjVGJOZktjSnM4WnFYbVNTV1lzU1ZKVXRNdk1xWmo1aEg0TmMFAAAAA25pbAUAAAADU0VQBAAAABBwdWJLZXlBZG1pbnNMaXN0CQAEtQAAAAIJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQdAAAAAgUAAAAPY29udHJvbENvbnRyYWN0AgAAAAwlc19fbXVsdGlzaWcFAAAAE3B1YktleUFkbWluc0xpc3RTdHIFAAAAA1NFUAQAAAAFY291bnQJAABkAAAAAgkAAGQAAAACCQAAZAAAAAIDCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAAkAAlkAAAABCQABkQAAAAIFAAAAEHB1YktleUFkbWluc0xpc3QAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAADCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAQkAAlkAAAABCQABkQAAAAIFAAAAEHB1YktleUFkbWluc0xpc3QAAAAAAAAAAAEAAAAAAAAAAAEAAAAAAAAAAAADCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAgkAAlkAAAABCQABkQAAAAIFAAAAEHB1YktleUFkbWluc0xpc3QAAAAAAAAAAAIAAAAAAAAAAAEAAAAAAAAAAAADCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAwkAAlkAAAABCQABkQAAAAIFAAAAEHB1YktleUFkbWluc0xpc3QAAAAAAAAAAAMAAAAAAAAAAAIAAAAAAAAAAAAJAABnAAAAAgUAAAAFY291bnQAAAAAAAAAAAM0bKA6", "chainId": 87, "height": 3240724, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 7NDg2qJaEmtDnrgaqnPDCZd9D97yrsXjbkeT1jhpUbDr Next: G4ZV5HPmVK7hK96j9CKhNKREiKJVQ3oRkVAhxAs6q2tV Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let revisionNum = "b3ff7472a1d54a9f0c8f6d6665c4458c36a31e48"
4+let revisionNum = "cbd0bdc8bbba91db64066b16a84913a4c965e23e"
55
66 let separator = "__"
77
2121
2222 let WAVESID = fromBase58String(WAVESIDSTR)
2323
24-func keyBondAsset () = "bond_asset_id"
24+let IdxControlCfgNeutrinoDapp = 1
25+
26+let IdxControlCfgAuctionDapp = 2
27+
28+let IdxControlCfgRpdDapp = 3
29+
30+let IdxControlCfgMathDapp = 4
31+
32+let IdxControlCfgLiquidationDapp = 5
33+
34+let IdxControlCfgRestDapp = 6
35+
36+let IdxControlCfgNodeRegistryDapp = 7
37+
38+let IdxControlCfgNsbtStakingDapp = 8
39+
40+let IdxControlCfgMediatorDapp = 9
41+
42+func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (((("mandatory " + toString(address)) + ".") + key) + " is not defined"))
2543
2644
27-func keyAuctionContractAddress () = "auction_contract"
45+func keyControlAddress () = "%s%s__config__controlAddress"
46+
47+
48+func keyControlCfg () = "%s__controlConfig"
49+
50+
51+func readControlCfgOrFail (control) = split(getStringOrFail(control, keyControlCfg()), SEP)
52+
53+
54+func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
55+
56+
57+let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP"))
58+
59+let controlCfg = readControlCfgOrFail(controlContract)
60+
61+let mathContract = getContractAddressOrFail(controlCfg, IdxControlCfgMathDapp)
62+
63+let neutrinoContract = getContractAddressOrFail(controlCfg, IdxControlCfgNeutrinoDapp)
64+
65+let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
66+
67+func keyBondAsset () = "bond_asset_id"
2868
2969
3070 func keyNeutrinoContractAddress () = "%s__neutrinoContractAddress"
96136 func getStrOrElse (key,defaultVal) = valueOrElse(getString(this, key), defaultVal)
97137
98138
99-func getStringOrFail (key) = valueOrErrorMessage(getString(this, key), (("Mandatory this." + key) + " is not defined"))
100-
101-
102139 func toAddressOrFail (addressStr) = valueOrErrorMessage(addressFromString(addressStr), ("couldn't parse passed addressStr=" + addressStr))
103140
104141
139176 func LockParamsEntry (userAddress,amount,start) = [IntegerEntry(keyLockParamUserAmount(userAddress), amount), IntegerEntry(keyLockParamStartBlock(userAddress), start)]
140177
141178
142-func getParamsOrFail () = {
143- let neutrinoContract = addressFromStringValue(getStringOrFail(keyNeutrinoContractAddress()))
144- $Tuple4(fromBase58String(getStringValue(neutrinoContract, keyAuctionContractAddress())), fromBase58String(getStringValue(neutrinoContract, keyBondAsset())), getIntOrFail(keyMinLockAmount()), getIntOrFail(keyHalfLife()))
145- }
179+func getParamsOrFail () = $Tuple3(fromBase58String(getStringValue(neutrinoContract, keyBondAsset())), getIntOrFail(keyMinLockAmount()), getIntOrFail(keyHalfLife()))
146180
147181
148182 func isActiveUser (userAddress) = (getIntOrElse(keyLockParamUserAmount(userAddress), 0) > 0)
177211 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
178212 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
179213 func forEachAssetCacheUserReward (accum,asset) = {
180- let $t074167551 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
181- let rewardTotal = $t074167551._1
182- let cached = $t074167551._2
183- let dynamic = $t074167551._3
184- let rewardCachedPartKEY = $t074167551._4
214+ let $t084508585 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
215+ let rewardTotal = $t084508585._1
216+ let cached = $t084508585._2
217+ let dynamic = $t084508585._3
218+ let rewardCachedPartKEY = $t084508585._4
185219 (accum :+ IntegerEntry(rewardCachedPartKEY, rewardTotal))
186220 }
187221
194228 else false)
195229 then throw("invalid depositNumLast and depositNumUser state")
196230 else if (if ((depositNumLast > -1))
197- then (depositNumUser == -1)
231+ then (depositNumUser >= -1)
198232 else false)
199233 then if (isNewUser)
200234 then [IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)]
212246
213247 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
214248 } :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast))
215- else if (if ((depositNumLast > -1))
216- then (depositNumUser > -1)
217- else false)
218- then if (isNewUser)
219- then [IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)]
220- else ({
221- let $l = supportedAssetsList
222- let $s = size($l)
223- let $acc0 = nil
224- func $f0_1 ($a,$i) = if (($i >= $s))
225- then $a
226- else forEachAssetCacheUserReward($a, $l[$i])
227-
228- func $f0_2 ($a,$i) = if (($i >= $s))
229- then $a
230- else throw("List size exceeds 10")
231-
232- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
233- } :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast))
234- else throw(((("uncovered condition: depositNumLast=" + toString(depositNumLast)) + " depositNumUser=") + toString(depositNumUser)))
249+ else throw(((("uncovered condition: depositNumLast=" + toString(depositNumLast)) + " depositNumUser=") + toString(depositNumUser)))
235250 }
236251
237252
242257 }
243258
244259
245-let ContolContractKey = "control_contract"
260+func commonClaim (userAddress,i) = {
261+ let userAddressStr = toString(userAddress)
262+ if ((size(i.payments) > 0))
263+ then throw("payments are not accepted")
264+ else {
265+ let $t01152911634 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
266+ let isNewUser = $t01152911634._1
267+ let stakedAmount = $t01152911634._2
268+ let stakingStart = $t01152911634._3
269+ let stakedAmountX = toBigInt(stakedAmount)
270+ let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
271+ let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
272+ let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
273+ func forEachAssetCalcUnclaimedReward (accum,asset) = {
274+ let $t01200512143 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
275+ let rewardTotal = $t01200512143._1
276+ let cached = $t01200512143._2
277+ let dynamic = $t01200512143._3
278+ let rewardCachedPartKEY = $t01200512143._4
279+ let claimedKEY = keyClaimed(userAddressStr, asset)
280+ let $t01220312240 = accum
281+ let data = $t01220312240._1
282+ let claimedAmtByAsset = $t01220312240._2
283+ let newPart = makeString([asset, toString(rewardTotal)], ":")
284+ let claimedAmtByAssetNew = makeString([claimedAmtByAsset, newPart], "_")
285+ if ((0 >= rewardTotal))
286+ then $Tuple2(data, claimedAmtByAssetNew)
287+ else $Tuple2((((data :+ ScriptTransfer(userAddress, rewardTotal, toAssetVect(asset))) :+ IntegerEntry(claimedKEY, (valueOrElse(getInteger(claimedKEY), 0) + rewardTotal))) :+ IntegerEntry(rewardCachedPartKEY, 0)), claimedAmtByAssetNew)
288+ }
246289
247-let neutrinoContract = addressFromStringValue(getStringOrFail(keyNeutrinoContractAddress()))
290+ let $t01270012814 = {
291+ let $l = supportedAssetsList
292+ let $s = size($l)
293+ let $acc0 = $Tuple2(nil, "")
294+ func $f0_1 ($a,$i) = if (($i >= $s))
295+ then $a
296+ else forEachAssetCalcUnclaimedReward($a, $l[$i])
248297
249-let controlContract = addressFromStringValue(getStringValue(neutrinoContract, ContolContractKey))
298+ func $f0_2 ($a,$i) = if (($i >= $s))
299+ then $a
300+ else throw("List size exceeds 10")
301+
302+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
303+ }
304+ let transfers = $t01270012814._1
305+ let claimedAmtByAssetResult = $t01270012814._2
306+ if ((0 >= size(transfers)))
307+ then nil
308+ else ((transfers :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)) :+ ClaimHistoryEntry(userAddress, i.transactionId, drop(claimedAmtByAssetResult, 1)))
309+ }
310+ }
311+
250312
251313 @Callable(i)
252314 func constructor (neutrinoContractAddress,mathContractAddress,minLockAmount,halfLife,supportedRewardAssets) = if ((i.caller != this))
257319
258320 @Callable(i)
259321 func stake () = {
260- let $t01144211521 = getParamsOrFail()
261- let auctionContract = $t01144211521._1
262- let bondAssetId = $t01144211521._2
263- let minLockAmount = $t01144211521._3
264- let halfLife = $t01144211521._4
322+ let $t01363813700 = getParamsOrFail()
323+ let bondAssetId = $t01363813700._1
324+ let minLockAmount = $t01363813700._2
325+ let halfLife = $t01363813700._3
265326 if ((size(i.payments) != 1))
266327 then throw("Invalid payments size")
267328 else {
274335 else {
275336 let userAddress = i.caller
276337 let userAddressStr = toString(i.caller)
277- let $t01206312170 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, -1))
278- let isNewUser = $t01206312170._1
279- let lockAmount = $t01206312170._2
280- let lockStartHeight = $t01206312170._3
338+ let $t01424214349 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, -1))
339+ let isNewUser = $t01424214349._1
340+ let lockAmount = $t01424214349._2
341+ let lockStartHeight = $t01424214349._3
281342 let mergedAmount = if (isNewUser)
282343 then amount
283344 else (amount + lockAmount)
284345 let mergedStartHeight = if (isNewUser)
285346 then height
286- else {
287- let mathContract = addressFromStringValue(getStringOrFail(keyMathContractAddress()))
288- asInt(invoke(mathContract, "mergeStakesREADONLY", [amount, height, lockAmount, lockStartHeight, halfLife], nil))
289- }
347+ else asInt(invoke(mathContract, "mergeStakesREADONLY", [amount, height, lockAmount, lockStartHeight, halfLife], nil))
290348 if ((minLockAmount > mergedAmount))
291349 then throw(("Min lock amount is " + toString(minLockAmount)))
292350 else {
293- let $t01262012722 = StatsResult(amount, 1, if (isNewUser)
351+ let $t01471014812 = StatsResult(amount, 1, if (isNewUser)
294352 then 1
295353 else 0)
296- let statsEntries = $t01262012722._1
297- let totalStaked = $t01262012722._2
298- let totalStakedNew = $t01262012722._3
354+ let statsEntries = $t01471014812._1
355+ let totalStaked = $t01471014812._2
356+ let totalStakedNew = $t01471014812._3
299357 ((([HistoryRecordEntry("stake", userAddress, i.transactionId, lockAmount, lockStartHeight, mergedAmount, mergedStartHeight)] ++ RewardEntries(isNewUser, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, mergedAmount, mergedStartHeight)) ++ statsEntries)
300358 }
301359 }
310368 else {
311369 let userAddress = i.caller
312370 let userAddressStr = toString(userAddress)
313- let $t01320813286 = getParamsOrFail()
314- let auctionAddress = $t01320813286._1
315- let bondAssetId = $t01320813286._2
316- let minLockAmount = $t01320813286._3
317- let halfLife = $t01320813286._4
318- let $t01328913363 = getUserParamsOrFail(userAddress)
319- let isNewUser = $t01328913363._1
320- let lockAmount = $t01328913363._2
321- let lockStart = $t01328913363._3
371+ let $t01529815360 = getParamsOrFail()
372+ let bondAssetId = $t01529815360._1
373+ let minLockAmount = $t01529815360._2
374+ let halfLife = $t01529815360._3
375+ let $t01536315437 = getUserParamsOrFail(userAddress)
376+ let isNewUser = $t01536315437._1
377+ let lockAmount = $t01536315437._2
378+ let lockStart = $t01536315437._3
322379 if ((0 >= lockAmount))
323380 then throw("Nothing to unstake")
324381 else if ((amount > lockAmount))
325382 then throw(((("Requested " + toString(amount)) + ", but staked only ") + toString(lockAmount)))
326383 else {
327- let mathContract = addressFromStringValue(getStringOrFail(keyMathContractAddress()))
328384 let comissionAmount = asInt(invoke(mathContract, "getUnstakeComissionAmountREADONLY", [amount, lockStart, halfLife], nil))
329- let $t01376413918 = StatsResult(-(amount), if ((amount == lockAmount))
385+ let $t01575115905 = StatsResult(-(amount), if ((amount == lockAmount))
330386 then -1
331387 else 0, if ((amount == lockAmount))
332388 then -1
333389 else 0)
334- let statsEntries = $t01376413918._1
335- let totalStaked = $t01376413918._2
336- let totalStakedNew = $t01376413918._3
337- ((([ScriptTransfer(userAddress, (amount - comissionAmount), bondAssetId), ScriptTransfer(Address(auctionAddress), comissionAmount, bondAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, lockAmount, lockStart, (lockAmount - amount), lockStart)] ++ RewardEntries(false, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, (lockAmount - amount), lockStart)) ++ statsEntries)
390+ let statsEntries = $t01575115905._1
391+ let totalStaked = $t01575115905._2
392+ let totalStakedNew = $t01575115905._3
393+ ((([ScriptTransfer(userAddress, (amount - comissionAmount), bondAssetId), ScriptTransfer(auctionContract, comissionAmount, bondAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, lockAmount, lockStart, (lockAmount - amount), lockStart)] ++ RewardEntries(false, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, (lockAmount - amount), lockStart)) ++ statsEntries)
338394 }
339395 }
340396
395451
396452
397453 @Callable(i)
398-func claimRewards () = {
399- let userAddress = i.caller
400- let userAddressStr = toString(userAddress)
401- if ((size(i.payments) > 0))
402- then throw("payments are not accepted")
403- else {
404- let $t01617416279 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
405- let isNewUser = $t01617416279._1
406- let stakedAmount = $t01617416279._2
407- let stakingStart = $t01617416279._3
408- let stakedAmountX = toBigInt(stakedAmount)
409- let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
410- let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
411- let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
412- func forEachAssetCalcUnclaimedReward (accum,asset) = {
413- let $t01665016788 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
414- let rewardTotal = $t01665016788._1
415- let cached = $t01665016788._2
416- let dynamic = $t01665016788._3
417- let rewardCachedPartKEY = $t01665016788._4
418- let claimedKEY = keyClaimed(userAddressStr, asset)
419- let $t01684816885 = accum
420- let data = $t01684816885._1
421- let claimedAmtByAsset = $t01684816885._2
422- let newPart = makeString([asset, toString(rewardTotal)], ":")
423- let claimedAmtByAssetNew = makeString([claimedAmtByAsset, newPart], "_")
424- if ((0 >= rewardTotal))
425- then $Tuple2(data, claimedAmtByAssetNew)
426- else $Tuple2((((data :+ ScriptTransfer(userAddress, rewardTotal, toAssetVect(asset))) :+ IntegerEntry(claimedKEY, (valueOrElse(getInteger(claimedKEY), 0) + rewardTotal))) :+ IntegerEntry(rewardCachedPartKEY, 0)), claimedAmtByAssetNew)
427- }
454+func claimRewards () = commonClaim(i.caller, i)
428455
429- let $t01734517459 = {
430- let $l = supportedAssetsList
431- let $s = size($l)
432- let $acc0 = $Tuple2(nil, "")
433- func $f0_1 ($a,$i) = if (($i >= $s))
434- then $a
435- else forEachAssetCalcUnclaimedReward($a, $l[$i])
436456
437- func $f0_2 ($a,$i) = if (($i >= $s))
438- then $a
439- else throw("List size exceeds 10")
440457
441- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
442- }
443- let transfers = $t01734517459._1
444- let claimedAmtByAssetResult = $t01734517459._2
445- if ((0 >= size(transfers)))
446- then throw("nothing to claim")
447- else ((transfers :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)) :+ ClaimHistoryEntry(userAddress, i.transactionId, drop(claimedAmtByAssetResult, 1)))
448- }
449- }
458+@Callable(i)
459+func claimRewardsByOriginCaller () = commonClaim(i.originCaller, i)
450460
451461
452462
471481 }
472482 else {
473483 let userAddress = addressFromStringValue(userAddressStr)
474- let $t01811818223 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
475- let isNewUser = $t01811818223._1
476- let stakedAmount = $t01811818223._2
477- let stakingStart = $t01811818223._3
484+ let $t01858118686 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
485+ let isNewUser = $t01858118686._1
486+ let stakedAmount = $t01858118686._2
487+ let stakingStart = $t01858118686._3
478488 let stakedAmountX = toBigInt(stakedAmount)
479489 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
480490 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
481491 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
482492 func forEachAssetCalcUnclaimedReward (accum,asset) = {
483- let $t01856918707 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
484- let rewardTotal = $t01856918707._1
485- let cached = $t01856918707._2
486- let dynamic = $t01856918707._3
487- let rewardCachedPartKEY = $t01856918707._4
493+ let $t01903219170 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
494+ let rewardTotal = $t01903219170._1
495+ let cached = $t01903219170._2
496+ let dynamic = $t01903219170._3
497+ let rewardCachedPartKEY = $t01903219170._4
488498 let claimed = valueOrElse(getInteger(keyClaimed(userAddressStr, asset)), 0)
489499 ((accum + makeString([asset, toString(rewardTotal), toString(claimed)], ":")) + "_")
490500 }
508518
509519
510520 @Callable(i)
511-func nsbtStakingSYSREADONLY (userAddressStr) = {
521+func nsbtUnstakingSYSREADONLY (userAddressStrOrEmpty,unstakeAmtP) = {
522+ let resultArray = if ((userAddressStrOrEmpty == ""))
523+ then [0, 0, 0, 0]
524+ else {
525+ let userAddress = addressFromStringValue(userAddressStrOrEmpty)
526+ let cfgDATA = getParamsOrFail()
527+ let nsbtAssetId = cfgDATA._1
528+ let minLockAmount = cfgDATA._2
529+ let halfLife = cfgDATA._3
530+ let userDATA = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
531+ let isNewUser = userDATA._1
532+ let stakedAmount = userDATA._2
533+ let lockStart = userDATA._3
534+ let unstakeAmt = if ((unstakeAmtP > stakedAmount))
535+ then stakedAmount
536+ else unstakeAmtP
537+ let stakedAmountNEW = (stakedAmount - unstakeAmt)
538+ let comissionAmount = if ((unstakeAmt == 0))
539+ then 0
540+ else asInt(invoke(mathContract, "getUnstakeComissionAmountREADONLY", [unstakeAmt, lockStart, halfLife], nil))
541+ let receiveAmount = (unstakeAmt - comissionAmount)
542+[stakedAmount, stakedAmountNEW, receiveAmount, comissionAmount]
543+ }
544+ $Tuple2(nil, resultArray)
545+ }
546+
547+
548+
549+@Callable(i)
550+func nsbtStakingSYSREADONLY (userAddressStr,nsbtDiff) = {
512551 let totalNsbtAmt = getIntOrElse(keyLockParamTotalAmount(), 0)
513552 if ((userAddressStr == ""))
514553 then $Tuple2(nil, [0, totalNsbtAmt, 0])
515554 else {
516555 let userAddress = toAddressOrFail(userAddressStr)
517- let $t01931119415 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
518- let isNewUser = $t01931119415._1
519- let userNsbtAmt = $t01931119415._2
520- let stakingStart = $t01931119415._3
556+ let $t02084920953 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
557+ let isNewUser = $t02084920953._1
558+ let userNsbtAmt = $t02084920953._2
559+ let stakingStart = $t02084920953._3
521560 $Tuple2(nil, [userNsbtAmt, totalNsbtAmt, stakingStart])
522561 }
523562 }
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let revisionNum = "b3ff7472a1d54a9f0c8f6d6665c4458c36a31e48"
4+let revisionNum = "cbd0bdc8bbba91db64066b16a84913a4c965e23e"
55
66 let separator = "__"
77
88 let SEP = "__"
99
1010 let MULT6 = 1000000
1111
1212 let MULT8 = 100000000
1313
1414 let MULTX6 = toBigInt(MULT6)
1515
1616 let MULTX8 = toBigInt(MULT8)
1717
1818 let MULTX18 = toBigInt(1000000000000000000)
1919
2020 let WAVESIDSTR = "WAVES"
2121
2222 let WAVESID = fromBase58String(WAVESIDSTR)
2323
24-func keyBondAsset () = "bond_asset_id"
24+let IdxControlCfgNeutrinoDapp = 1
25+
26+let IdxControlCfgAuctionDapp = 2
27+
28+let IdxControlCfgRpdDapp = 3
29+
30+let IdxControlCfgMathDapp = 4
31+
32+let IdxControlCfgLiquidationDapp = 5
33+
34+let IdxControlCfgRestDapp = 6
35+
36+let IdxControlCfgNodeRegistryDapp = 7
37+
38+let IdxControlCfgNsbtStakingDapp = 8
39+
40+let IdxControlCfgMediatorDapp = 9
41+
42+func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), (((("mandatory " + toString(address)) + ".") + key) + " is not defined"))
2543
2644
27-func keyAuctionContractAddress () = "auction_contract"
45+func keyControlAddress () = "%s%s__config__controlAddress"
46+
47+
48+func keyControlCfg () = "%s__controlConfig"
49+
50+
51+func readControlCfgOrFail (control) = split(getStringOrFail(control, keyControlCfg()), SEP)
52+
53+
54+func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
55+
56+
57+let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP"))
58+
59+let controlCfg = readControlCfgOrFail(controlContract)
60+
61+let mathContract = getContractAddressOrFail(controlCfg, IdxControlCfgMathDapp)
62+
63+let neutrinoContract = getContractAddressOrFail(controlCfg, IdxControlCfgNeutrinoDapp)
64+
65+let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
66+
67+func keyBondAsset () = "bond_asset_id"
2868
2969
3070 func keyNeutrinoContractAddress () = "%s__neutrinoContractAddress"
3171
3272
3373 func keyMathContractAddress () = "%s__mathContract"
3474
3575
3676 func keyMinLockAmount () = "%s__minLockAmount"
3777
3878
3979 func keyHalfLife () = "%s__halfLife"
4080
4181
4282 func keyLockParamUserAmount (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "amount"], separator)
4383
4484
4585 func keyLockParamStartBlock (userAddress) = makeString(["%s%s%s", "paramByUser", toString(userAddress), "start"], separator)
4686
4787
4888 func keyHistoryRecord (type,userAddress,txId) = makeString(["%s%s%s%s", "history", type, toString(userAddress), toBase58String(txId)], separator)
4989
5090
5191 func keyLockParamTotalAmount () = makeString(["%s%s", "stats", "activeTotalLocked"], separator)
5292
5393
5494 func keyStatsLocksCount () = makeString(["%s%s", "stats", "locksCount"], separator)
5595
5696
5797 func keyStatsUsersCount () = makeString(["%s%s", "stats", "activeUsersCount"], separator)
5898
5999
60100 func keyNextPeriod () = "%s__nextPeriod"
61101
62102
63103 func keySupportedRewardAssets () = "supportedRewardAssets"
64104
65105
66106 func keyDepositNumLast () = makeString(["%s%s%s", "dep", "lastNum"], separator)
67107
68108
69109 func keyUserRewardFromDepositNum (userAddress) = makeString(["%s%s%s", "userRwdFromDepNum", userAddress], separator)
70110
71111
72112 func keyRewardPerNsbtSumAt (depositNum,tkn) = makeString(["%s%d", "rwdPerNsbtSumByDepNum", toString(depositNum), tkn], separator)
73113
74114
75115 func keyReward (userAddress,tkn) = makeString(["%s%s%s", "rwd", userAddress, tkn], separator)
76116
77117
78118 func keyClaimed (userAddress,tkn) = makeString(["%s%s%s", "clm", userAddress, tkn], separator)
79119
80120
81121 func keyNotDistributedReward (tkn) = makeString(["%s%s", "notDistributed", tkn], separator)
82122
83123
84124 func toX18 (origVal,origMult) = fraction(toBigInt(origVal), MULTX18, origMult)
85125
86126
87127 func getIntOrZero (key) = valueOrElse(getInteger(this, key), 0)
88128
89129
90130 func getIntOrElse (key,defaultVal) = valueOrElse(getInteger(this, key), defaultVal)
91131
92132
93133 func getIntOrFail (key) = valueOrErrorMessage(getInteger(this, key), (("Mandatory this." + key) + " is not defined"))
94134
95135
96136 func getStrOrElse (key,defaultVal) = valueOrElse(getString(this, key), defaultVal)
97137
98138
99-func getStringOrFail (key) = valueOrErrorMessage(getString(this, key), (("Mandatory this." + key) + " is not defined"))
100-
101-
102139 func toAddressOrFail (addressStr) = valueOrErrorMessage(addressFromString(addressStr), ("couldn't parse passed addressStr=" + addressStr))
103140
104141
105142 func toAssetVect (assetStr) = if ((assetStr == WAVESIDSTR))
106143 then unit
107144 else fromBase58String(assetStr)
108145
109146
110147 func asInt (val) = match val {
111148 case valInt: Int =>
112149 valInt
113150 case _ =>
114151 throw("fail to cast into Int")
115152 }
116153
117154
118155 func formatHistoryRecord (oldAmount,oldStart,newAmount,newStart) = makeString(["%d%d%d%d%d%d", toString(lastBlock.height), toString(lastBlock.timestamp), toString(oldAmount), toString(oldStart), toString(newAmount), toString(newStart)], separator)
119156
120157
121158 func formatClaimHistoryRecord (user,claimedRewards) = makeString(["%s%d%d%s", user, toString(lastBlock.height), toString(lastBlock.timestamp), claimedRewards], separator)
122159
123160
124161 func HistoryRecordEntry (type,userAddress,txId,oldAmount,oldStart,newAmount,newStart) = StringEntry(keyHistoryRecord(type, userAddress, txId), formatHistoryRecord(oldAmount, oldStart, newAmount, newStart))
125162
126163
127164 func ClaimHistoryEntry (userAddress,txId,claimedRewards) = StringEntry(keyHistoryRecord("claim", userAddress, txId), formatClaimHistoryRecord(toString(userAddress), claimedRewards))
128165
129166
130167 func StatsResult (totalLockedInc,lockCountInc,usersCountInc) = {
131168 let locksCount = getIntOrZero(keyStatsLocksCount())
132169 let usersCount = getIntOrZero(keyStatsUsersCount())
133170 let totalAmount = getIntOrZero(keyLockParamTotalAmount())
134171 let totalAmountNew = (totalAmount + totalLockedInc)
135172 $Tuple3([IntegerEntry(keyStatsLocksCount(), (locksCount + lockCountInc)), IntegerEntry(keyStatsUsersCount(), (usersCount + usersCountInc)), IntegerEntry(keyLockParamTotalAmount(), totalAmountNew)], totalAmount, totalAmountNew)
136173 }
137174
138175
139176 func LockParamsEntry (userAddress,amount,start) = [IntegerEntry(keyLockParamUserAmount(userAddress), amount), IntegerEntry(keyLockParamStartBlock(userAddress), start)]
140177
141178
142-func getParamsOrFail () = {
143- let neutrinoContract = addressFromStringValue(getStringOrFail(keyNeutrinoContractAddress()))
144- $Tuple4(fromBase58String(getStringValue(neutrinoContract, keyAuctionContractAddress())), fromBase58String(getStringValue(neutrinoContract, keyBondAsset())), getIntOrFail(keyMinLockAmount()), getIntOrFail(keyHalfLife()))
145- }
179+func getParamsOrFail () = $Tuple3(fromBase58String(getStringValue(neutrinoContract, keyBondAsset())), getIntOrFail(keyMinLockAmount()), getIntOrFail(keyHalfLife()))
146180
147181
148182 func isActiveUser (userAddress) = (getIntOrElse(keyLockParamUserAmount(userAddress), 0) > 0)
149183
150184
151185 func getUserParamsOrUnit (userAddress) = if (isActiveUser(userAddress))
152186 then $Tuple3(false, getIntOrFail(keyLockParamUserAmount(userAddress)), getIntOrFail(keyLockParamStartBlock(userAddress)))
153187 else unit
154188
155189
156190 func getUserParamsOrFail (userAddress) = valueOrErrorMessage(getUserParamsOrUnit(userAddress), (("User " + toString(userAddress)) + " is not defined"))
157191
158192
159193 let supportedAssetsStr = getStrOrElse(keySupportedRewardAssets(), "")
160194
161195 let supportedAssetsList = split(supportedAssetsStr, "_")
162196
163197 func calcReward (userAddress,assetId,stakedAmountX,depositNumUser,depositNumLast) = {
164198 let rewardPerNsbtSumLastKEY = keyRewardPerNsbtSumAt(depositNumLast, assetId)
165199 let sumLastX18 = parseBigIntValue(getStrOrElse(keyRewardPerNsbtSumAt(depositNumLast, assetId), "0"))
166200 let sumUserX18 = parseBigIntValue(getStrOrElse(keyRewardPerNsbtSumAt(depositNumUser, assetId), "0"))
167201 let rewardDynamicPart = toInt(fraction((sumLastX18 - sumUserX18), stakedAmountX, MULTX18))
168202 let rewardCachedPartKEY = keyReward(userAddress, assetId)
169203 let rewardCachedPart = getIntOrElse(rewardCachedPartKEY, 0)
170204 $Tuple4((rewardCachedPart + rewardDynamicPart), rewardCachedPart, rewardDynamicPart, rewardCachedPartKEY)
171205 }
172206
173207
174208 func RewardEntries (isNewUser,userAddress,stakedAmount) = {
175209 let stakedAmountX = toBigInt(stakedAmount)
176210 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddress)
177211 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
178212 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
179213 func forEachAssetCacheUserReward (accum,asset) = {
180- let $t074167551 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
181- let rewardTotal = $t074167551._1
182- let cached = $t074167551._2
183- let dynamic = $t074167551._3
184- let rewardCachedPartKEY = $t074167551._4
214+ let $t084508585 = calcReward(userAddress, asset, stakedAmountX, depositNumUser, depositNumLast)
215+ let rewardTotal = $t084508585._1
216+ let cached = $t084508585._2
217+ let dynamic = $t084508585._3
218+ let rewardCachedPartKEY = $t084508585._4
185219 (accum :+ IntegerEntry(rewardCachedPartKEY, rewardTotal))
186220 }
187221
188222 if (if ((depositNumLast == -1))
189223 then (depositNumUser == -1)
190224 else false)
191225 then nil
192226 else if (if ((depositNumLast == -1))
193227 then (depositNumUser > -1)
194228 else false)
195229 then throw("invalid depositNumLast and depositNumUser state")
196230 else if (if ((depositNumLast > -1))
197- then (depositNumUser == -1)
231+ then (depositNumUser >= -1)
198232 else false)
199233 then if (isNewUser)
200234 then [IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)]
201235 else ({
202236 let $l = supportedAssetsList
203237 let $s = size($l)
204238 let $acc0 = nil
205239 func $f0_1 ($a,$i) = if (($i >= $s))
206240 then $a
207241 else forEachAssetCacheUserReward($a, $l[$i])
208242
209243 func $f0_2 ($a,$i) = if (($i >= $s))
210244 then $a
211245 else throw("List size exceeds 10")
212246
213247 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
214248 } :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast))
215- else if (if ((depositNumLast > -1))
216- then (depositNumUser > -1)
217- else false)
218- then if (isNewUser)
219- then [IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)]
220- else ({
221- let $l = supportedAssetsList
222- let $s = size($l)
223- let $acc0 = nil
224- func $f0_1 ($a,$i) = if (($i >= $s))
225- then $a
226- else forEachAssetCacheUserReward($a, $l[$i])
227-
228- func $f0_2 ($a,$i) = if (($i >= $s))
229- then $a
230- else throw("List size exceeds 10")
231-
232- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
233- } :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast))
234- else throw(((("uncovered condition: depositNumLast=" + toString(depositNumLast)) + " depositNumUser=") + toString(depositNumUser)))
249+ else throw(((("uncovered condition: depositNumLast=" + toString(depositNumLast)) + " depositNumUser=") + toString(depositNumUser)))
235250 }
236251
237252
238253 func IncrementNotDistributedRewardEntry (tkn,amountInc) = {
239254 let notDistributedRewardKEY = keyNotDistributedReward(tkn)
240255 let notDistributedReward = getIntOrElse(notDistributedRewardKEY, 0)
241256 [IntegerEntry(notDistributedRewardKEY, (notDistributedReward + amountInc))]
242257 }
243258
244259
245-let ContolContractKey = "control_contract"
260+func commonClaim (userAddress,i) = {
261+ let userAddressStr = toString(userAddress)
262+ if ((size(i.payments) > 0))
263+ then throw("payments are not accepted")
264+ else {
265+ let $t01152911634 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
266+ let isNewUser = $t01152911634._1
267+ let stakedAmount = $t01152911634._2
268+ let stakingStart = $t01152911634._3
269+ let stakedAmountX = toBigInt(stakedAmount)
270+ let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
271+ let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
272+ let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
273+ func forEachAssetCalcUnclaimedReward (accum,asset) = {
274+ let $t01200512143 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
275+ let rewardTotal = $t01200512143._1
276+ let cached = $t01200512143._2
277+ let dynamic = $t01200512143._3
278+ let rewardCachedPartKEY = $t01200512143._4
279+ let claimedKEY = keyClaimed(userAddressStr, asset)
280+ let $t01220312240 = accum
281+ let data = $t01220312240._1
282+ let claimedAmtByAsset = $t01220312240._2
283+ let newPart = makeString([asset, toString(rewardTotal)], ":")
284+ let claimedAmtByAssetNew = makeString([claimedAmtByAsset, newPart], "_")
285+ if ((0 >= rewardTotal))
286+ then $Tuple2(data, claimedAmtByAssetNew)
287+ else $Tuple2((((data :+ ScriptTransfer(userAddress, rewardTotal, toAssetVect(asset))) :+ IntegerEntry(claimedKEY, (valueOrElse(getInteger(claimedKEY), 0) + rewardTotal))) :+ IntegerEntry(rewardCachedPartKEY, 0)), claimedAmtByAssetNew)
288+ }
246289
247-let neutrinoContract = addressFromStringValue(getStringOrFail(keyNeutrinoContractAddress()))
290+ let $t01270012814 = {
291+ let $l = supportedAssetsList
292+ let $s = size($l)
293+ let $acc0 = $Tuple2(nil, "")
294+ func $f0_1 ($a,$i) = if (($i >= $s))
295+ then $a
296+ else forEachAssetCalcUnclaimedReward($a, $l[$i])
248297
249-let controlContract = addressFromStringValue(getStringValue(neutrinoContract, ContolContractKey))
298+ func $f0_2 ($a,$i) = if (($i >= $s))
299+ then $a
300+ else throw("List size exceeds 10")
301+
302+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
303+ }
304+ let transfers = $t01270012814._1
305+ let claimedAmtByAssetResult = $t01270012814._2
306+ if ((0 >= size(transfers)))
307+ then nil
308+ else ((transfers :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)) :+ ClaimHistoryEntry(userAddress, i.transactionId, drop(claimedAmtByAssetResult, 1)))
309+ }
310+ }
311+
250312
251313 @Callable(i)
252314 func constructor (neutrinoContractAddress,mathContractAddress,minLockAmount,halfLife,supportedRewardAssets) = if ((i.caller != this))
253315 then throw("Permission denied")
254316 else [StringEntry(keyNeutrinoContractAddress(), neutrinoContractAddress), StringEntry(keyMathContractAddress(), mathContractAddress), IntegerEntry(keyMinLockAmount(), minLockAmount), IntegerEntry(keyHalfLife(), halfLife), StringEntry(keySupportedRewardAssets(), supportedRewardAssets)]
255317
256318
257319
258320 @Callable(i)
259321 func stake () = {
260- let $t01144211521 = getParamsOrFail()
261- let auctionContract = $t01144211521._1
262- let bondAssetId = $t01144211521._2
263- let minLockAmount = $t01144211521._3
264- let halfLife = $t01144211521._4
322+ let $t01363813700 = getParamsOrFail()
323+ let bondAssetId = $t01363813700._1
324+ let minLockAmount = $t01363813700._2
325+ let halfLife = $t01363813700._3
265326 if ((size(i.payments) != 1))
266327 then throw("Invalid payments size")
267328 else {
268329 let payment = i.payments[0]
269330 let amount = payment.amount
270331 let invalidAssetMessage = (("Invalid asset. " + toBase58String(bondAssetId)) + " is expected")
271332 let assetId = valueOrErrorMessage(payment.assetId, invalidAssetMessage)
272333 if ((assetId != bondAssetId))
273334 then throw(invalidAssetMessage)
274335 else {
275336 let userAddress = i.caller
276337 let userAddressStr = toString(i.caller)
277- let $t01206312170 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, -1))
278- let isNewUser = $t01206312170._1
279- let lockAmount = $t01206312170._2
280- let lockStartHeight = $t01206312170._3
338+ let $t01424214349 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, -1))
339+ let isNewUser = $t01424214349._1
340+ let lockAmount = $t01424214349._2
341+ let lockStartHeight = $t01424214349._3
281342 let mergedAmount = if (isNewUser)
282343 then amount
283344 else (amount + lockAmount)
284345 let mergedStartHeight = if (isNewUser)
285346 then height
286- else {
287- let mathContract = addressFromStringValue(getStringOrFail(keyMathContractAddress()))
288- asInt(invoke(mathContract, "mergeStakesREADONLY", [amount, height, lockAmount, lockStartHeight, halfLife], nil))
289- }
347+ else asInt(invoke(mathContract, "mergeStakesREADONLY", [amount, height, lockAmount, lockStartHeight, halfLife], nil))
290348 if ((minLockAmount > mergedAmount))
291349 then throw(("Min lock amount is " + toString(minLockAmount)))
292350 else {
293- let $t01262012722 = StatsResult(amount, 1, if (isNewUser)
351+ let $t01471014812 = StatsResult(amount, 1, if (isNewUser)
294352 then 1
295353 else 0)
296- let statsEntries = $t01262012722._1
297- let totalStaked = $t01262012722._2
298- let totalStakedNew = $t01262012722._3
354+ let statsEntries = $t01471014812._1
355+ let totalStaked = $t01471014812._2
356+ let totalStakedNew = $t01471014812._3
299357 ((([HistoryRecordEntry("stake", userAddress, i.transactionId, lockAmount, lockStartHeight, mergedAmount, mergedStartHeight)] ++ RewardEntries(isNewUser, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, mergedAmount, mergedStartHeight)) ++ statsEntries)
300358 }
301359 }
302360 }
303361 }
304362
305363
306364
307365 @Callable(i)
308366 func unstake (amount) = if ((size(i.payments) != 0))
309367 then throw("unstake doesn't require any payment")
310368 else {
311369 let userAddress = i.caller
312370 let userAddressStr = toString(userAddress)
313- let $t01320813286 = getParamsOrFail()
314- let auctionAddress = $t01320813286._1
315- let bondAssetId = $t01320813286._2
316- let minLockAmount = $t01320813286._3
317- let halfLife = $t01320813286._4
318- let $t01328913363 = getUserParamsOrFail(userAddress)
319- let isNewUser = $t01328913363._1
320- let lockAmount = $t01328913363._2
321- let lockStart = $t01328913363._3
371+ let $t01529815360 = getParamsOrFail()
372+ let bondAssetId = $t01529815360._1
373+ let minLockAmount = $t01529815360._2
374+ let halfLife = $t01529815360._3
375+ let $t01536315437 = getUserParamsOrFail(userAddress)
376+ let isNewUser = $t01536315437._1
377+ let lockAmount = $t01536315437._2
378+ let lockStart = $t01536315437._3
322379 if ((0 >= lockAmount))
323380 then throw("Nothing to unstake")
324381 else if ((amount > lockAmount))
325382 then throw(((("Requested " + toString(amount)) + ", but staked only ") + toString(lockAmount)))
326383 else {
327- let mathContract = addressFromStringValue(getStringOrFail(keyMathContractAddress()))
328384 let comissionAmount = asInt(invoke(mathContract, "getUnstakeComissionAmountREADONLY", [amount, lockStart, halfLife], nil))
329- let $t01376413918 = StatsResult(-(amount), if ((amount == lockAmount))
385+ let $t01575115905 = StatsResult(-(amount), if ((amount == lockAmount))
330386 then -1
331387 else 0, if ((amount == lockAmount))
332388 then -1
333389 else 0)
334- let statsEntries = $t01376413918._1
335- let totalStaked = $t01376413918._2
336- let totalStakedNew = $t01376413918._3
337- ((([ScriptTransfer(userAddress, (amount - comissionAmount), bondAssetId), ScriptTransfer(Address(auctionAddress), comissionAmount, bondAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, lockAmount, lockStart, (lockAmount - amount), lockStart)] ++ RewardEntries(false, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, (lockAmount - amount), lockStart)) ++ statsEntries)
390+ let statsEntries = $t01575115905._1
391+ let totalStaked = $t01575115905._2
392+ let totalStakedNew = $t01575115905._3
393+ ((([ScriptTransfer(userAddress, (amount - comissionAmount), bondAssetId), ScriptTransfer(auctionContract, comissionAmount, bondAssetId), HistoryRecordEntry("unstake", userAddress, i.transactionId, lockAmount, lockStart, (lockAmount - amount), lockStart)] ++ RewardEntries(false, userAddressStr, lockAmount)) ++ LockParamsEntry(userAddress, (lockAmount - amount), lockStart)) ++ statsEntries)
338394 }
339395 }
340396
341397
342398
343399 @Callable(i)
344400 func deposit () = if ((size(i.payments) != 1))
345401 then throw("exact 1 payment is allowed only")
346402 else {
347403 let pmt = i.payments[0]
348404 let amount = pmt.amount
349405 let pmtAssetId = valueOrElse(pmt.assetId, WAVESID)
350406 let pmtAssetIdStr = toBase58String(pmtAssetId)
351407 let pmtMultX = if ((pmtAssetId == WAVESID))
352408 then MULTX8
353409 else MULTX6
354410 let amountX = toBigInt(amount)
355411 let totalStaked = getIntOrElse(keyLockParamTotalAmount(), 0)
356412 let totalStakedX = toBigInt(totalStaked)
357413 if ((0 > totalStaked))
358414 then throw("TODO: case is not supported")
359415 else if ((totalStaked == 0))
360416 then IncrementNotDistributedRewardEntry(pmtAssetIdStr, amount)
361417 else {
362418 let rewardPerNsbtX18 = fraction(amountX, MULTX18, totalStakedX)
363419 let depositNumLastKEY = keyDepositNumLast()
364420 let depositNumLast = getIntOrElse(depositNumLastKEY, -1)
365421 let depositNumNew = (depositNumLast + 1)
366422 if (!(contains(supportedAssetsStr, pmtAssetIdStr)))
367423 then throw(((supportedAssetsStr + " doesn't contain ") + pmtAssetIdStr))
368424 else {
369425 func refreshRewardPerNsbtSUM (accum,nextAsset) = {
370426 let rewardPerNsbtSumNewKEY = keyRewardPerNsbtSumAt(depositNumNew, nextAsset)
371427 let sumLastStr = getStrOrElse(keyRewardPerNsbtSumAt(depositNumLast, nextAsset), "0")
372428 (accum :+ (if ((nextAsset == pmtAssetIdStr))
373429 then StringEntry(rewardPerNsbtSumNewKEY, toString((parseBigIntValue(sumLastStr) + rewardPerNsbtX18)))
374430 else StringEntry(rewardPerNsbtSumNewKEY, sumLastStr)))
375431 }
376432
377433 ({
378434 let $l = supportedAssetsList
379435 let $s = size($l)
380436 let $acc0 = nil
381437 func $f0_1 ($a,$i) = if (($i >= $s))
382438 then $a
383439 else refreshRewardPerNsbtSUM($a, $l[$i])
384440
385441 func $f0_2 ($a,$i) = if (($i >= $s))
386442 then $a
387443 else throw("List size exceeds 10")
388444
389445 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
390446 } :+ IntegerEntry(depositNumLastKEY, depositNumNew))
391447 }
392448 }
393449 }
394450
395451
396452
397453 @Callable(i)
398-func claimRewards () = {
399- let userAddress = i.caller
400- let userAddressStr = toString(userAddress)
401- if ((size(i.payments) > 0))
402- then throw("payments are not accepted")
403- else {
404- let $t01617416279 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
405- let isNewUser = $t01617416279._1
406- let stakedAmount = $t01617416279._2
407- let stakingStart = $t01617416279._3
408- let stakedAmountX = toBigInt(stakedAmount)
409- let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
410- let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
411- let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
412- func forEachAssetCalcUnclaimedReward (accum,asset) = {
413- let $t01665016788 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
414- let rewardTotal = $t01665016788._1
415- let cached = $t01665016788._2
416- let dynamic = $t01665016788._3
417- let rewardCachedPartKEY = $t01665016788._4
418- let claimedKEY = keyClaimed(userAddressStr, asset)
419- let $t01684816885 = accum
420- let data = $t01684816885._1
421- let claimedAmtByAsset = $t01684816885._2
422- let newPart = makeString([asset, toString(rewardTotal)], ":")
423- let claimedAmtByAssetNew = makeString([claimedAmtByAsset, newPart], "_")
424- if ((0 >= rewardTotal))
425- then $Tuple2(data, claimedAmtByAssetNew)
426- else $Tuple2((((data :+ ScriptTransfer(userAddress, rewardTotal, toAssetVect(asset))) :+ IntegerEntry(claimedKEY, (valueOrElse(getInteger(claimedKEY), 0) + rewardTotal))) :+ IntegerEntry(rewardCachedPartKEY, 0)), claimedAmtByAssetNew)
427- }
454+func claimRewards () = commonClaim(i.caller, i)
428455
429- let $t01734517459 = {
430- let $l = supportedAssetsList
431- let $s = size($l)
432- let $acc0 = $Tuple2(nil, "")
433- func $f0_1 ($a,$i) = if (($i >= $s))
434- then $a
435- else forEachAssetCalcUnclaimedReward($a, $l[$i])
436456
437- func $f0_2 ($a,$i) = if (($i >= $s))
438- then $a
439- else throw("List size exceeds 10")
440457
441- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
442- }
443- let transfers = $t01734517459._1
444- let claimedAmtByAssetResult = $t01734517459._2
445- if ((0 >= size(transfers)))
446- then throw("nothing to claim")
447- else ((transfers :+ IntegerEntry(userRewardFromDepositNumKEY, depositNumLast)) :+ ClaimHistoryEntry(userAddress, i.transactionId, drop(claimedAmtByAssetResult, 1)))
448- }
449- }
458+@Callable(i)
459+func claimRewardsByOriginCaller () = commonClaim(i.originCaller, i)
450460
451461
452462
453463 @Callable(i)
454464 func unclaimedRewardsREADONLY (userAddressStr) = {
455465 func forEachAssetZeroReward (accum,asset) = ((accum + makeString([asset, "0", "0"], ":")) + "_")
456466
457467 let unclaimedRewardStr = if ((userAddressStr == ""))
458468 then {
459469 let $l = supportedAssetsList
460470 let $s = size($l)
461471 let $acc0 = ""
462472 func $f0_1 ($a,$i) = if (($i >= $s))
463473 then $a
464474 else forEachAssetZeroReward($a, $l[$i])
465475
466476 func $f0_2 ($a,$i) = if (($i >= $s))
467477 then $a
468478 else throw("List size exceeds 10")
469479
470480 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
471481 }
472482 else {
473483 let userAddress = addressFromStringValue(userAddressStr)
474- let $t01811818223 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
475- let isNewUser = $t01811818223._1
476- let stakedAmount = $t01811818223._2
477- let stakingStart = $t01811818223._3
484+ let $t01858118686 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
485+ let isNewUser = $t01858118686._1
486+ let stakedAmount = $t01858118686._2
487+ let stakingStart = $t01858118686._3
478488 let stakedAmountX = toBigInt(stakedAmount)
479489 let userRewardFromDepositNumKEY = keyUserRewardFromDepositNum(userAddressStr)
480490 let depositNumUser = getIntOrElse(userRewardFromDepositNumKEY, -1)
481491 let depositNumLast = getIntOrElse(keyDepositNumLast(), -1)
482492 func forEachAssetCalcUnclaimedReward (accum,asset) = {
483- let $t01856918707 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
484- let rewardTotal = $t01856918707._1
485- let cached = $t01856918707._2
486- let dynamic = $t01856918707._3
487- let rewardCachedPartKEY = $t01856918707._4
493+ let $t01903219170 = calcReward(userAddressStr, asset, stakedAmountX, depositNumUser, depositNumLast)
494+ let rewardTotal = $t01903219170._1
495+ let cached = $t01903219170._2
496+ let dynamic = $t01903219170._3
497+ let rewardCachedPartKEY = $t01903219170._4
488498 let claimed = valueOrElse(getInteger(keyClaimed(userAddressStr, asset)), 0)
489499 ((accum + makeString([asset, toString(rewardTotal), toString(claimed)], ":")) + "_")
490500 }
491501
492502 let $l = supportedAssetsList
493503 let $s = size($l)
494504 let $acc0 = ""
495505 func $f0_1 ($a,$i) = if (($i >= $s))
496506 then $a
497507 else forEachAssetCalcUnclaimedReward($a, $l[$i])
498508
499509 func $f0_2 ($a,$i) = if (($i >= $s))
500510 then $a
501511 else throw("List size exceeds 10")
502512
503513 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
504514 }
505515 $Tuple2(nil, dropRight(unclaimedRewardStr, 1))
506516 }
507517
508518
509519
510520 @Callable(i)
511-func nsbtStakingSYSREADONLY (userAddressStr) = {
521+func nsbtUnstakingSYSREADONLY (userAddressStrOrEmpty,unstakeAmtP) = {
522+ let resultArray = if ((userAddressStrOrEmpty == ""))
523+ then [0, 0, 0, 0]
524+ else {
525+ let userAddress = addressFromStringValue(userAddressStrOrEmpty)
526+ let cfgDATA = getParamsOrFail()
527+ let nsbtAssetId = cfgDATA._1
528+ let minLockAmount = cfgDATA._2
529+ let halfLife = cfgDATA._3
530+ let userDATA = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
531+ let isNewUser = userDATA._1
532+ let stakedAmount = userDATA._2
533+ let lockStart = userDATA._3
534+ let unstakeAmt = if ((unstakeAmtP > stakedAmount))
535+ then stakedAmount
536+ else unstakeAmtP
537+ let stakedAmountNEW = (stakedAmount - unstakeAmt)
538+ let comissionAmount = if ((unstakeAmt == 0))
539+ then 0
540+ else asInt(invoke(mathContract, "getUnstakeComissionAmountREADONLY", [unstakeAmt, lockStart, halfLife], nil))
541+ let receiveAmount = (unstakeAmt - comissionAmount)
542+[stakedAmount, stakedAmountNEW, receiveAmount, comissionAmount]
543+ }
544+ $Tuple2(nil, resultArray)
545+ }
546+
547+
548+
549+@Callable(i)
550+func nsbtStakingSYSREADONLY (userAddressStr,nsbtDiff) = {
512551 let totalNsbtAmt = getIntOrElse(keyLockParamTotalAmount(), 0)
513552 if ((userAddressStr == ""))
514553 then $Tuple2(nil, [0, totalNsbtAmt, 0])
515554 else {
516555 let userAddress = toAddressOrFail(userAddressStr)
517- let $t01931119415 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
518- let isNewUser = $t01931119415._1
519- let userNsbtAmt = $t01931119415._2
520- let stakingStart = $t01931119415._3
556+ let $t02084920953 = valueOrElse(getUserParamsOrUnit(userAddress), $Tuple3(true, 0, 0))
557+ let isNewUser = $t02084920953._1
558+ let userNsbtAmt = $t02084920953._2
559+ let stakingStart = $t02084920953._3
521560 $Tuple2(nil, [userNsbtAmt, totalNsbtAmt, stakingStart])
522561 }
523562 }
524563
525564
526565 @Verifier(tx)
527566 func verify () = {
528567 let pubKeyAdminsListStr = makeString(["GJdLSaLiv5K7xuejac8mcRcHoyo3dPrESrvktG3a6MAR", "EYwZmURd5KKaQRBjsVa6g8DPisFoS6SovRJtFiL5gMHU", "DtmAfuDdCrHK8spdAeAYzq6MsZegeD9gnsrpuTRkCbVA", "5WRXFSjwcTbNfKcJs8ZqXmSSWYsSVJUtMvMqZj5hH4Nc"], SEP)
529568 let pubKeyAdminsList = split(valueOrElse(getString(controlContract, "%s__multisig"), pubKeyAdminsListStr), SEP)
530569 let count = ((((if (sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(pubKeyAdminsList[0])))
531570 then 1
532571 else 0) + (if (sigVerify(tx.bodyBytes, tx.proofs[1], fromBase58String(pubKeyAdminsList[1])))
533572 then 1
534573 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[2], fromBase58String(pubKeyAdminsList[2])))
535574 then 1
536575 else 0)) + (if (sigVerify(tx.bodyBytes, tx.proofs[3], fromBase58String(pubKeyAdminsList[3])))
537576 then 2
538577 else 0))
539578 (count >= 3)
540579 }
541580

github/deemru/w8io/786bc32 
104.43 ms