tx · B41BtyqVQJRVEVfKnNSqX17thSsfg4kKXLxRUdyymEQd 3PAETTtuW7aSiyKtn9GuML3RgtV1xdq1mQW: -0.01800000 Waves 2024.04.17 20:18 [4133016] smart account 3PAETTtuW7aSiyKtn9GuML3RgtV1xdq1mQW > SELF 0.00000000 Waves
{ "type": 13, "id": "B41BtyqVQJRVEVfKnNSqX17thSsfg4kKXLxRUdyymEQd", "fee": 1800000, "feeAssetId": null, "timestamp": 1713374303640, "version": 2, "chainId": 87, "sender": "3PAETTtuW7aSiyKtn9GuML3RgtV1xdq1mQW", "senderPublicKey": "DSNxHVyf38CbPoz2oSJ1b4FWqRvqFsAphCzdtrPeWPHa", "proofs": [ "2wFVKmc4t9xG8JLfJYwdifJzCSWEry1sPgnsRtUVhMDmiRaghefADKSX5fjbimE6txMaz932rZS4ZiQKsP5wKxhK" ], "script": "base64:AAIFAAAAAAAAADwIAhIDCgEIEgMKAQgSABIECgIICBIECgIICBIAEgASAwoBCBIDCgEIEgMKAQgSAwoBCBIDCgEIEgMKAQgAAAA4AAAAAApwZXJjaFByaWNlCQAAaAAAAAIAAAAAAAAAAGQAAAAAAAAPQkAAAAAABXNjYWxlAAAAAAAAACcQAAAAAAZzY2FsZTIAAAAAAAAPQkABAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgAAAAdhZGRyZXNzAAAAA2tleQQAAAAHJG1hdGNoMAkABB0AAAACBQAAAAdhZGRyZXNzBQAAAANrZXkDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABlN0cmluZwQAAAABYQUAAAAHJG1hdGNoMAUAAAABYQIAAAAAAQAAAAx0cnlHZXRTdHJpbmcAAAABAAAAA2tleQkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgUAAAAEdGhpcwUAAAADa2V5AQAAABdzdGF0aWNLZXlfb3JhY2xlQWRkcmVzcwAAAAACAAAAFHN0YXRpY19vcmFjbGVBZGRyZXNzAQAAABRzdGF0aWNLZXlfZWdnQXNzZXRJZAAAAAACAAAAEXN0YXRpY19lZ2dBc3NldElkAQAAABpzdGF0aWNLZXlfaW5jdWJhdG9yQWRkcmVzcwAAAAACAAAAF3N0YXRpY19pbmN1YmF0b3JBZGRyZXNzAQAAABhzdGF0aWNLZXlfYnJlZWRlckFkZHJlc3MAAAAAAgAAABVzdGF0aWNfYnJlZWRlckFkZHJlc3MBAAAAFnN0YXRpY0tleV9pdGVtc0FkZHJlc3MAAAAAAgAAABNzdGF0aWNfaXRlbXNBZGRyZXNzAQAAABlzdGF0aWNLZXlfbWV0YVJhY2VBZGRyZXNzAAAAAAIAAAAWc3RhdGljX21ldGFSYWNlQWRkcmVzcwEAAAAbc3RhdGljS2V5X2FjY0Jvb3N0ZXJBZGRyZXNzAAAAAAIAAAAYc3RhdGljX2FjY0Jvb3N0ZXJBZGRyZXNzAQAAAB9zdGF0aWNLZXlfcHJveHlTdGFraW5nQ29udHJhY3RzAAAAAAIAAAAcc3RhdGljX3Byb3h5U3Rha2luZ0NvbnRyYWN0cwEAAAAVc3RhdGljS2V5X21haW50ZW5hbmNlAAAAAAIAAAASc3RhdGljX21haW50ZW5hbmNlAQAAABlzdGF0aWNLZXlfY2ZNYXN0ZXJBZGRyZXNzAAAAAAIAAAAWc3RhdGljX2NmTWFzdGVyQWRkcmVzcwEAAAASc3RhdGljS2V5X2V4dHJhRmVlAAAAAAIAAAAPc3RhdGljX2V4dHJhRmVlAQAAABdzdGF0aWNLZXlfZmVlQWdncmVnYXRvcgAAAAACAAAAFHN0YXRpY19mZWVBZ2dyZWdhdG9yAQAAABRzdGF0aWNLZXlfZmFybWluZ05ldwAAAAACAAAAGHN0YXRpY19mYXJtaW5nQWRkcmVzc05ldwEAAAAJZ2V0T3JhY2xlAAAAAAkBAAAAB0FkZHJlc3MAAAABCQACWQAAAAEJAQAAAAx0cnlHZXRTdHJpbmcAAAABCQEAAAAXc3RhdGljS2V5X29yYWNsZUFkZHJlc3MAAAAAAQAAAA1nZXRFZ2dBc3NldElkAAAAAAkAAlkAAAABCQEAAAAUdHJ5R2V0U3RyaW5nRXh0ZXJuYWwAAAACCQEAAAAJZ2V0T3JhY2xlAAAAAAkBAAAAFHN0YXRpY0tleV9lZ2dBc3NldElkAAAAAAEAAAATZ2V0SW5jdWJhdG9yQWRkcmVzcwAAAAAJAQAAAAdBZGRyZXNzAAAAAQkAAlkAAAABCQEAAAAUdHJ5R2V0U3RyaW5nRXh0ZXJuYWwAAAACCQEAAAAJZ2V0T3JhY2xlAAAAAAkBAAAAGnN0YXRpY0tleV9pbmN1YmF0b3JBZGRyZXNzAAAAAAEAAAARZ2V0QnJlZWRlckFkZHJlc3MAAAAACQEAAAAHQWRkcmVzcwAAAAEJAAJZAAAAAQkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgkBAAAACWdldE9yYWNsZQAAAAAJAQAAABhzdGF0aWNLZXlfYnJlZWRlckFkZHJlc3MAAAAAAQAAAA9nZXRJdGVtc0FkZHJlc3MAAAAACQEAAAAHQWRkcmVzcwAAAAEJAAJZAAAAAQkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgkBAAAACWdldE9yYWNsZQAAAAAJAQAAABZzdGF0aWNLZXlfaXRlbXNBZGRyZXNzAAAAAAEAAAASZ2V0TWV0YXJhY2VBZGRyZXNzAAAAAAkBAAAAB0FkZHJlc3MAAAABCQACWQAAAAEJAQAAABR0cnlHZXRTdHJpbmdFeHRlcm5hbAAAAAIJAQAAAAlnZXRPcmFjbGUAAAAACQEAAAAZc3RhdGljS2V5X21ldGFSYWNlQWRkcmVzcwAAAAABAAAAFGdldEFjY0Jvb3N0ZXJBZGRyZXNzAAAAAAkBAAAAB0FkZHJlc3MAAAABCQACWQAAAAEJAQAAABR0cnlHZXRTdHJpbmdFeHRlcm5hbAAAAAIJAQAAAAlnZXRPcmFjbGUAAAAACQEAAAAbc3RhdGljS2V5X2FjY0Jvb3N0ZXJBZGRyZXNzAAAAAAEAAAAPZ2V0UHJveHlTdGFraW5nAAAAAAkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgkBAAAACWdldE9yYWNsZQAAAAAJAQAAAB9zdGF0aWNLZXlfcHJveHlTdGFraW5nQ29udHJhY3RzAAAAAAEAAAAOZ2V0TWFpbnRlbmFuY2UAAAAACQEAAAAUdHJ5R2V0U3RyaW5nRXh0ZXJuYWwAAAACCQEAAAAJZ2V0T3JhY2xlAAAAAAkBAAAAFXN0YXRpY0tleV9tYWludGVuYW5jZQAAAAABAAAAEmdldENmTWFzdGVyQWRkcmVzcwAAAAAJAQAAAAdBZGRyZXNzAAAAAQkAAlkAAAABCQEAAAAUdHJ5R2V0U3RyaW5nRXh0ZXJuYWwAAAACCQEAAAAJZ2V0T3JhY2xlAAAAAAkBAAAAGXN0YXRpY0tleV9jZk1hc3RlckFkZHJlc3MAAAAAAQAAABBnZXRGZWVBZ2dyZWdhdG9yAAAAAAkBAAAAB0FkZHJlc3MAAAABCQACWQAAAAEJAQAAABR0cnlHZXRTdHJpbmdFeHRlcm5hbAAAAAIJAQAAAAlnZXRPcmFjbGUAAAAACQEAAAAXc3RhdGljS2V5X2ZlZUFnZ3JlZ2F0b3IAAAAAAQAAABRnZXROZXdGYXJtaW5nQWRkcmVzcwAAAAAJAQAAAAdBZGRyZXNzAAAAAQkAAlkAAAABCQEAAAAUdHJ5R2V0U3RyaW5nRXh0ZXJuYWwAAAACCQEAAAAJZ2V0T3JhY2xlAAAAAAkBAAAAFHN0YXRpY0tleV9mYXJtaW5nTmV3AAAAAAAAAAANUmVmZXJlclJld2FyZAAAAAAAAAAABQEAAAAWY2hlY2tBZGRpdGlvbmFsUGF5bWVudAAAAAEA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dAAAAAAAAAAAZAQAAAAKZ2VuZXJhdGlvbgkAAS8AAAACCQEAAAAJdGFrZVJpZ2h0AAAAAgUAAAAJYXNzZXROYW1lAAAAAAAAAAACAAAAAAAAAAABCQEAAAAOZ2V0QXNzZXRSYXJpdHkAAAACBQAAAAdmYXJtR2VuBQAAAApnZW5lcmF0aW9uBAAAABF0b3RhbEZhcm1pbmdQb3dlcgkAAGQAAAACBQAAAAZyYXJpdHkJAABrAAAAAwUAAAAGcmFyaXR5BQAAAAlmYXJtQm9vc3QAAAAAAAAAAGQJAAUUAAAAAgUAAAAHZmFybUdlbgUAAAARdG90YWxGYXJtaW5nUG93ZXIJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAAA1ub3QgdmFsaWQgTkZUAQAAAB1nZXRMYXN0S25vd25Bc3NldEZhcm1pbmdQb3dlcgAAAAIAAAAHYWRkcmVzcwAAAAdhc3NldElkCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAB19hc3NldF8FAAAAB2Fzc2V0SWQCAAAADV9mYXJtaW5nUG93ZXIBAAAADGNhbGNJbnRlcmVzdAAAAAMAAAAQcHJldmlvdXNJbnRlcmVzdAAAABZwcmV2aW91c0ludGVyZXN0SGVpZ2h0AAAAEXRvdGFsRmFybWluZ1Bvd2VyCQAAZAAAAAIFAAAAEHByZXZpb3VzSW50ZXJlc3QJAABpAAAAAgkAAGgAAAACCQAAaAAAAAIFAAAABXNjYWxlCQEAAAARZ2V0UmV3YXJkUGVyQmxvY2sAAAAACQAAZQAAAAIFAAAABmhlaWdodAUAAAAWcHJldmlvdXNJbnRlcmVzdEhlaWdodAUAAAARdG90YWxGYXJtaW5nUG93ZXIBAAAAEmdldEN1cnJlbnRJbnRlcmVzdAAAAAADCQAAZgAAAAIJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQIAAAASdG90YWxfZmFybWluZ1Bvd2VyAAAAAAAAAAAABAAAABBwcmV2aW91c0ludGVyZXN0CQEAAAANdHJ5R2V0SW50ZWdlcgAAAAECAAAAF3RvdGFsX2xhc3RDaGVja0ludGVyZXN0BAAAABZwcmV2aW91c0ludGVyZXN0SGVpZ2h0CQEAAAANdHJ5R2V0SW50ZWdlcgAAAAECAAAAHXRvdGFsX2xhc3RDaGVja0ludGVyZXN0SGVpZ2h0BAAAABF0b3RhbEZhcm1pbmdQb3dlcgkBAAAADXRyeUdldEludGVnZXIAAAABAgAAABJ0b3RhbF9mYXJtaW5nUG93ZXIJAQAAAAxjYWxjSW50ZXJlc3QAAAADBQAAABBwcmV2aW91c0ludGVyZXN0BQAAABZwcmV2aW91c0ludGVyZXN0SGVpZ2h0BQAAABF0b3RhbEZhcm1pbmdQb3dlcgMJAQAAAAIhPQAAAAIJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQIAAAARdG90YWxfc3RhcnRIZWlnaHQAAAAAAAAAAAAJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQIAAAAXdG90YWxfbGFzdENoZWNrSW50ZXJlc3QJAAACAAAAAQIAAAAcZmFybWluZyBpcyBub3QgbGF1bmNoZWQsIHlldAEAAAAUY2FsY0Fzc2V0UmV3YXJkRGVsdGEAAAADAAAAB2FkZHJlc3MAAAAHYXNzZXRJZAAAABFhc3NldEZhcm1pbmdQb3dlcgQAAAAWbGFzdENoZWNrQXNzZXRJbnRlcmVzdAkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAAAdfYXNzZXRfBQAAAAdhc3NldElkAgAAABJfbGFzdENoZWNrSW50ZXJlc3QEAAAAD2N1cnJlbnRJbnRlcmVzdAkBAAAAEmdldEN1cnJlbnRJbnRlcmVzdAAAAAAJAABoAAAAAgUAAAARYXNzZXRGYXJtaW5nUG93ZXIJAABlAAAAAgUAAAAPY3VycmVudEludGVyZXN0BQAAABZsYXN0Q2hlY2tBc3NldEludGVyZXN0AQAAABRhZGRBc3NldElkVG9HZW5FbnRyeQAAAAIAAAAHYXNzZXRJZAAAAAhhc3NldEdlbgQAAAAMY3VycmVudFZhbHVlCQEAAAAMdHJ5R2V0U3RyaW5nAAAAAQkAASwAAAACCQABLAAAAAICAAAAB2Fzc2V0c18FAAAACGFzc2V0R2VuAgAAAAdfbG9ja2VkAwkAAAAAAAACBQAAAAxjdXJyZW50VmFsdWUCAAAAAAUAAAAHYXNzZXRJZAkAASwAAAACCQABLAAAAAIFAAAADGN1cnJlbnRWYWx1ZQIAAAABLAUAAAAHYXNzZXRJZAEAAAAOZ2V0U3Rha2VSZXN1bHQAAAAEAAAAB2FkZHJlc3MAAAAHYXNzZXRJZAAAABFhc3NldEZhcm1pbmdQb3dlcgAAAAh1bnN0YWtlcgQAAAAFYXNzZXQJAAJYAAAAAQUAAAAHYXNzZXRJZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAASdG90YWxfZmFybWluZ1Bvd2VyCQAAZAAAAAIJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQIAAAASdG90YWxfZmFybWluZ1Bvd2VyBQAAABFhc3NldEZhcm1pbmdQb3dlcgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAAXdG90YWxfbGFzdENoZWNrSW50ZXJlc3QJAQAAABJnZXRDdXJyZW50SW50ZXJlc3QAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAB10b3RhbF9sYXN0Q2hlY2tJbnRlcmVzdEhlaWdodAUAAAAGaGVpZ2h0CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAZhc3NldF8FAAAABWFzc2V0AgAAAAZfb3duZXIFAAAAB2FkZHJlc3MJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAB19hc3NldF8FAAAABWFzc2V0AgAAAA1fZmFybWluZ1Bvd2VyBQAAABFhc3NldEZhcm1pbmdQb3dlcgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAAHX2Fzc2V0XwUAAAAFYXNzZXQCAAAAEl9sYXN0Q2hlY2tJbnRlcmVzdAkBAAAAEmdldEN1cnJlbnRJbnRlcmVzdAAAAAAJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAAHX2Fzc2V0XwUAAAAFYXNzZXQCAAAACV91bnN0YWtlcgUAAAAIdW5zdGFrZXIFAAAAA25pbAEAAAAQZ2V0VW5zdGFrZVJlc3VsdAAAAAYAAAAHYWRkcmVzcwAAAAdhc3NldElkAAAABWNvbG9yAAAABmNhbGxlcgAAAApyZWFsQ2FsbGVyAAAACWNsYWltRWdncwQAAAAGbG9ja2VkCQEAAAAIaXNMb2NrZWQAAAAAAwkAAAAAAAACBQAAAAZsb2NrZWQFAAAABmxvY2tlZAQAAAAFYXNzZXQJAAJYAAAAAQUAAAAHYXNzZXRJZAQAAAAIdW5zdGFrZXIJAQAAAAx0cnlHZXRTdHJpbmcAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAAAdfYXNzZXRfBQAAAAVhc3NldAIAAAAJX3Vuc3Rha2VyAwMJAQAAAAIhPQAAAAIFAAAACHVuc3Rha2VyAgAAAAAJAQAAAAIhPQAAAAIFAAAACHVuc3Rha2VyBQAAAApyZWFsQ2FsbGVyBwkAAAIAAAABAgAAAFdGVU46IEl0IHNlZW1zIGR1Y2sgd2FzIHN0YWtlZCB0aHJvdWggYSBkYXBwLCBub3QgZGlyZWN0bHksIHBsZWFzZSB1bnN0YWtlIHRocm91Z2ggZGFwcCEEAAAAEWFzc2V0RmFybWluZ1Bvd2VyCQEAAAAdZ2V0TGFzdEtub3duQXNzZXRGYXJtaW5nUG93ZXIAAAACBQAAAAdhZGRyZXNzBQAAAAVhc3NldAMJAQAAAAEhAAAAAQkAAGYAAAACBQAAABFhc3NldEZhcm1pbmdQb3dlcgAAAAAAAAAAAAkAAAIAAAABAgAAACpGR1U6IEFzc2V0IGZhcm1pbmcgcG93ZXIgbm90IGJpZ2dlciB0aGVuIDAEAAAAEGFzc2V0UmV3YXJkRGVsdGEJAQAAABRjYWxjQXNzZXRSZXdhcmREZWx0YQAAAAMFAAAAB2FkZHJlc3MFAAAABWFzc2V0BQAAABFhc3NldEZhcm1pbmdQb3dlcgQAAAAMZmFybWVkQW1vdW50CQAAZAAAAAIFAAAAEGFzc2V0UmV3YXJkRGVsdGEJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAAHX2Fzc2V0XwUAAAAFYXNzZXQCAAAAFl9sYXN0Q2hlY2tGYXJtZWRBbW91bnQEAAAAD3dpdGhkcmF3bkFtb3VudAkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAAAdfYXNzZXRfBQAAAAVhc3NldAIAAAAQX3dpdGhkcmF3bkFtb3VudAQAAAAGcmV3YXJkCQAAaQAAAAIJAABlAAAAAgUAAAAMZmFybWVkQW1vdW50BQAAAA93aXRoZHJhd25BbW91bnQJAABoAAAAAgUAAAAFc2NhbGUAAAAAAAAAAGQEAAAADmlzV2l0aG91dFBlcmNoCQEAAAANdHJ5R2V0Qm9vbGVhbgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAB19hc3NldF8FAAAABWFzc2V0AgAAAA5fd2l0aG91dF9wZXJjaAQAAAATcmV3YXJkQWZ0ZXJTaWNrTmVzcwUAAAAGcmV3YXJkBAAAAA1hcHBlbmRQZXJjaGVzAwUAAAAOaXNXaXRob3V0UGVyY2gJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAAHX2Fzc2V0XwUAAAAFYXNzZXQCAAAADl93aXRob3V0X3BlcmNoBQAAAANuaWwJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAABJfcGVyY2hlc0F2YWlsYWJsZV8FAAAABWNvbG9yCQAAZAAAAAIJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAEl9wZXJjaGVzQXZhaWxhYmxlXwUAAAAFY29sb3IAAAAAAAAAAAEFAAAAA25pbAQAAAAGc2VuZFR4AwUAAAAJY2xhaW1FZ2dzCQAFFAAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAAGY2FsbGVyCQAAaAAAAAIFAAAAE3Jld2FyZEFmdGVyU2lja05lc3MAAAAAAAAPQkAJAQAAAA1nZXRFZ2dBc3NldElkAAAAAAUAAAADbmlsCQAAaAAAAAIFAAAAE3Jld2FyZEFmdGVyU2lja05lc3MAAAAAAAAPQkAJAAUUAAAAAgUAAAADbmlsAAAAAAAAAAAACQAFFAAAAAIJAAROAAAAAgkABE4AAAACCQAETgAAAAIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAEnRvdGFsX2Zhcm1pbmdQb3dlcgkAAGUAAAACCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAECAAAAEnRvdGFsX2Zhcm1pbmdQb3dlcgUAAAARYXNzZXRGYXJtaW5nUG93ZXIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAF3RvdGFsX2xhc3RDaGVja0ludGVyZXN0CQEAAAASZ2V0Q3VycmVudEludGVyZXN0AAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAAddG90YWxfbGFzdENoZWNrSW50ZXJlc3RIZWlnaHQFAAAABmhlaWdodAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAGYXNzZXRfBQAAAAVhc3NldAIAAAAGX293bmVyCQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAB19hc3NldF8FAAAABWFzc2V0AgAAAAlfdW5zdGFrZXIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAB19hc3NldF8FAAAABWFzc2V0AgAAAA1fZmFybWluZ1Bvd2VyAAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAAAdfYXNzZXRfBQAAAAVhc3NldAIAAAASX2xhc3RDaGVja0ludGVyZXN0CQEAAAASZ2V0Q3VycmVudEludGVyZXN0AAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAAHX2Fzc2V0XwUAAAAFYXNzZXQCAAAAEF93aXRoZHJhd25BbW91bnQJAABkAAAAAgUAAAAPd2l0aGRyYXduQW1vdW50CQAAaAAAAAIFAAAAE3Jld2FyZEFmdGVyU2lja05lc3MFAAAABnNjYWxlMgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAAHX2Fzc2V0XwUAAAAFYXNzZXQCAAAAFl9sYXN0Q2hlY2tGYXJtZWRBbW91bnQJAABkAAAAAgkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAAAdfYXNzZXRfBQAAAAVhc3NldAIAAAAWX2xhc3RDaGVja0Zhcm1lZEFtb3VudAUAAAAQYXNzZXRSZXdhcmREZWx0YQUAAAADbmlsBQAAAA1hcHBlbmRQZXJjaGVzCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMFAAAABmNhbGxlcgAAAAAAAAAAAQUAAAAHYXNzZXRJZAUAAAADbmlsCAUAAAAGc2VuZFR4AAAAAl8xCAUAAAAGc2VuZFR4AAAAAl8yCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEAAAATY2FsY3VsYXRlUGVyY2hQcmljZQAAAAEAAAAHYWRkcmVzcwQAAAARaGFzQXJ0ZWZhY3RTdGFrZWQJAQAAABR0cnlHZXRTdHJpbmdFeHRlcm5hbAAAAAIJAQAAABRnZXRBY2NCb29zdGVyQWRkcmVzcwAAAAAJAAEsAAAAAgkAASwAAAACAgAAAAtBUlQtWE1JU1RMXwUAAAAHYWRkcmVzcwIAAAAGX293bmVyAwkAAAAAAAACBQAAABFoYXNBcnRlZmFjdFN0YWtlZAIAAAAABQAAAApwZXJjaFByaWNlCQAAaAAAAAIJAABpAAAAAgUAAAAKcGVyY2hQcmljZQAAAAAAAAAACgAAAAAAAAAACQEAAAAQaXNQcm94eVN0YWtpbmdTYwAAAAEAAAAHYWRkcmVzcwQAAAAQYWxsb3dlZENvbnRyYWN0cwkBAAAAD2dldFByb3h5U3Rha2luZwAAAAAEAAAAFGFsbG93ZWRDb250cmFjdHNMaXN0CQAEtQAAAAIFAAAAEGFsbG93ZWRDb250cmFjdHMCAAAAATsJAQAAAAIhPQAAAAIJAARPAAAAAgUAAAAUYWxsb3dlZENvbnRyYWN0c0xpc3QFAAAAB2FkZHJlc3MFAAAABHVuaXQBAAAAEnVuc3Rha2VORlRJbnRlcm5hbAAAAAMAAAAFYXNzZXQAAAABaQAAAAhjbGFpbUVnZwQAAAAHYXNzZXRJZAkAAlkAAAABBQAAAAVhc3NldAQAAAAKcmVhbENhbGxlcgkABCUAAAABCAUAAAABaQAAAAZjYWxsZXIEAAAAB2FkZHJlc3MDCQEAAAAQaXNQcm94eVN0YWtpbmdTYwAAAAEJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyCQAEJQAAAAEIBQAAAAFpAAAADG9yaWdpbkNhbGxlcgUAAAAKcmVhbENhbGxlcgQAAAAFY29sb3IJAQAAAAl0YWtlUmlnaHQAAAACCAkBAAAABXZhbHVlAAAAAQkAA+wAAAABBQAAAAdhc3NldElkAAAABG5hbWUAAAAAAAAAAAEDCQAAAAAAAAIFAAAABWNvbG9yAgAAAAFVCQAAAgAAAAECAAAAMEZVTjogdXNlIGFub3RoZXIgZnVuY3Rpb24gdG8gdW5zdGFrZSBKYWNrcG90IE5GVAQAAAAGcmVzdWx0CQEAAAAQZ2V0VW5zdGFrZVJlc3VsdAAAAAYFAAAAB2FkZHJlc3MFAAAAB2Fzc2V0SWQFAAAABWNvbG9yCAUAAAABaQAAAAZjYWxsZXIFAAAACnJlYWxDYWxsZXIFAAAACGNsYWltRWdnBQAAAAZyZXN1bHQBAAAAFnVuc3Rha2VKYWNrcG90SW50ZXJuYWwAAAADAAAABWFzc2V0AAAAAWkAAAAIY2xhaW1FZ2cEAAAAB2Fzc2V0SWQJAAJZAAAAAQUAAAAFYXNzZXQEAAAACnJlYWxDYWxsZXIJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAAAdhZGRyZXNzAwkBAAAAEGlzUHJveHlTdGFraW5nU2MAAAABCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgkABCUAAAABCAUAAAABaQAAAAxvcmlnaW5DYWxsZXIFAAAACnJlYWxDYWxsZXIEAAAABWNvbG9yCQEAAAAMdHJ5R2V0U3RyaW5nAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAAHX2Fzc2V0XwUAAAAFYXNzZXQCAAAAC19wZXJjaENvbG9yAwkBAAAAAiE9AAAAAgkBAAAACXRha2VSaWdodAAAAAIJAQAAAAV2YWx1ZQAAAAEICQEAAAAFdmFsdWUAAAABCQAD7AAAAAEFAAAAB2Fzc2V0SWQAAAAEbmFtZQAAAAAAAAAAAQIAAAABVQkAAAIAAAABAgAAAAxqYWNrcG90IG9ubHkEAAAABnJlc3VsdAkBAAAAEGdldFVuc3Rha2VSZXN1bHQAAAAGBQAAAAdhZGRyZXNzBQAAAAdhc3NldElkBQAAAAVjb2xvcggFAAAAAWkAAAAGY2FsbGVyBQAAAApyZWFsQ2FsbGVyBQAAAAhjbGFpbUVnZwUAAAAGcmVzdWx0AQAAAAdnZXRCb29sAAAAAQAAAANrZXkEAAAAByRtYXRjaDAJAAQbAAAAAgUAAAAEdGhpcwUAAAADa2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAdCb29sZWFuBAAAAAFiBQAAAAckbWF0Y2gwBQAAAAFiBwEAAAAJaXNUZXN0RW52AAAAAAkBAAAAB2dldEJvb2wAAAABAgAAAAdURVNURU5WAAAADQAAAAFpAQAAAA1yZW1vdmVQZXJjaGVzAAAAAQAAAAdhZGRyZXNzAwkBAAAAAiE9AAAAAggFAAAAAWkAAAAGY2FsbGVyCQEAAAAUZ2V0TmV3RmFybWluZ0FkZHJlc3MAAAAACQAAAgAAAAECAAAAD0ZSUDogYWRtaW4gb25seQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAABNfcGVyY2hlc0F2YWlsYWJsZV9SAAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAE19wZXJjaGVzQXZhaWxhYmxlX0cAAAAAAAAAAAAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAATX3BlcmNoZXNBdmFpbGFibGVfQgAAAAAAAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAABNfcGVyY2hlc0F2YWlsYWJsZV9VAAAAAAAAAAAABQAAAANuaWwAAAABaQEAAAAPY29uZmlndXJlT3JhY2xlAAAAAQAAAAZvcmFjbGUDCQEAAAACIT0AAAACCAUAAAABaQAAAAZjYWxsZXIFAAAABHRoaXMJAAACAAAAAQIAAAAPRkNPOiBhZG1pbiBvbmx5CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABdzdGF0aWNLZXlfb3JhY2xlQWRkcmVzcwAAAAAFAAAABm9yYWNsZQUAAAADbmlsAAAAAWkBAAAABGluaXQAAAAAAwkBAAAAAiE9AAAAAggFAAAAAWkAAAAGY2FsbGVyBQAAAAR0aGlzCQAAAgAAAAECAAAADkZJOiBhZG1pbiBvbmx5CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAABF0b3RhbF9zdGFydEhlaWdodAUAAAAGaGVpZ2h0BQAAAANuaWwAAAABaQEAAAAIYnV5UGVyY2gAAAACAAAABmNvbG9ySQAAAA5yZWZlcmVyQWRkcmVzcwkAAAIAAAABAgAAADZGQk46IGZ1bmN0aW9uIGlzIGRpc2FibGVkLCBtaWdyYXRpb24gdG8gbmV3IHNjIG9uZ29pbmcAAAABaQEAAAAMYWRkRnJlZVBlcmNoAAAAAgAAAAdhZGRyZXNzAAAABWNvbG9yCQAAAgAAAAECAAAANkZCTjogZnVuY3Rpb24gaXMgZGlzYWJsZWQsIG1pZ3JhdGlvbiB0byBuZXcgc2Mgb25nb2luZwAAAAFpAQAAAAhzdGFrZU5GVAAAAAAJAAACAAAAAQIAAAA2RkJOOiBmdW5jdGlvbiBpcyBkaXNhYmxlZCwgbWlncmF0aW9uIHRvIG5ldyBzYyBvbmdvaW5nAAAAAWkBAAAAFHN0YWtlTkZUV2l0aG91dFBlcmNoAAAAAAkAAAIAAAABAgAAADZGQk46IGZ1bmN0aW9uIGlzIGRpc2FibGVkLCBtaWdyYXRpb24gdG8gbmV3IHNjIG9uZ29pbmcAAAABaQEAAAAKdW5zdGFrZU5GVAAAAAEAAAAFYXNzZXQEAAAADHZhbGlkUGF5bWVudAMJAAAAAAAAAggFAAAAAWkAAAAGY2FsbGVyCQEAAAASZ2V0TWV0YXJhY2VBZGRyZXNzAAAAAAUAAAADbmlsCQEAAAAWY2hlY2tBZGRpdGlvbmFsUGF5bWVudAAAAAEJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAADCQAAAAAAAAIFAAAADHZhbGlkUGF5bWVudAUAAAAMdmFsaWRQYXltZW50BAAAAAZyZXN1bHQJAQAAABJ1bnN0YWtlTkZUSW50ZXJuYWwAAAADBQAAAAVhc3NldAUAAAABaQYJAAUUAAAAAgkABE4AAAACCAUAAAAGcmVzdWx0AAAAAl8xBQAAAAx2YWxpZFBheW1lbnQIBQAAAAZyZXN1bHQAAAACXzIJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAAFnVuc3Rha2VORlRXaXRob3V0Q2xhaW0AAAABAAAABWFzc2V0CQEAAAASdW5zdGFrZU5GVEludGVybmFsAAAAAwUAAAAFYXNzZXQFAAAAAWkHAAAAAWkBAAAADHN0YWtlSmFja3BvdAAAAAEAAAAFY29sb3IJAAACAAAAAQIAAAA2RkJOOiBmdW5jdGlvbiBpcyBkaXNhYmxlZCwgbWlncmF0aW9uIHRvIG5ldyBzYyBvbmdvaW5nAAAAAWkBAAAADnVuc3Rha2VKYWNrcG90AAAAAQAAAAVhc3NldAQAAAAMdmFsaWRQYXltZW50CQEAAAAWY2hlY2tBZGRpdGlvbmFsUGF5bWVudAAAAAEJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAADCQAAAAAAAAIFAAAADHZhbGlkUGF5bWVudAUAAAAMdmFsaWRQYXltZW50BAAAAAZyZXN1bHQJAQAAABZ1bnN0YWtlSmFja3BvdEludGVybmFsAAAAAwUAAAAFYXNzZXQFAAAAAWkGCQAFFAAAAAIJAAROAAAAAggFAAAABnJlc3VsdAAAAAJfMQUAAAAMdmFsaWRQYXltZW50CAUAAAAGcmVzdWx0AAAAAl8yCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAB11bnN0YWtlSmFja3BvdFdpdGhvdXRDbGFpbUVnZwAAAAEAAAAFYXNzZXQJAQAAABZ1bnN0YWtlSmFja3BvdEludGVybmFsAAAAAwUAAAAFYXNzZXQFAAAAAWkHAAAAAWkBAAAAC2NsYWltUmV3YXJkAAAAAQAAAAVhc3NldAQAAAAGbG9ja2VkCQEAAAAIaXNMb2NrZWQAAAAAAwkAAAAAAAACBQAAAAZsb2NrZWQFAAAABmxvY2tlZAQAAAAMdmFsaWRQYXltZW50AwkAAAAAAAACCAUAAAABaQAAAAxvcmlnaW5DYWxsZXIJAQAAABJnZXRDZk1hc3RlckFkZHJlc3MAAAAABQAAAANuaWwJAQAAABZjaGVja0FkZGl0aW9uYWxQYXltZW50AAAAAQkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAMJAAAAAAAAAgUAAAAMdmFsaWRQYXltZW50BQAAAAx2YWxpZFBheW1lbnQEAAAAB2FkZHJlc3MDCQAAAAAAAAIIBQAAAAFpAAAADG9yaWdpbkNhbGxlcgkBAAAAEmdldENmTWFzdGVyQWRkcmVzcwAAAAAJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyCQAEJQAAAAEIBQAAAAFpAAAADG9yaWdpbkNhbGxlcgQAAAAHYXNzZXRJZAkAAlkAAAABBQAAAAVhc3NldAQAAAARYXNzZXRGYXJtaW5nUG93ZXIJAQAAAB1nZXRMYXN0S25vd25Bc3NldEZhcm1pbmdQb3dlcgAAAAIFAAAAB2FkZHJlc3MFAAAABWFzc2V0BAAAABBhc3NldFJld2FyZERlbHRhCQEAAAAUY2FsY0Fzc2V0UmV3YXJkRGVsdGEAAAADBQAAAAdhZGRyZXNzBQAAAAVhc3NldAUAAAARYXNzZXRGYXJtaW5nUG93ZXIEAAAADGZhcm1lZEFtb3VudAkAAGQAAAACBQAAABBhc3NldFJld2FyZERlbHRhCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAB19hc3NldF8FAAAABWFzc2V0AgAAABZfbGFzdENoZWNrRmFybWVkQW1vdW50BAAAAA93aXRoZHJhd25BbW91bnQJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAAHX2Fzc2V0XwUAAAAFYXNzZXQCAAAAEF93aXRoZHJhd25BbW91bnQEAAAABnJld2FyZAkAAGkAAAACCQAAZQAAAAIFAAAADGZhcm1lZEFtb3VudAUAAAAPd2l0aGRyYXduQW1vdW50CQAAaAAAAAIFAAAABXNjYWxlAAAAAAAAAABkAwkAAGcAAAACAAAAAAAAAAAABQAAAAZyZXdhcmQJAAACAAAAAQIAAAAhRkNSOiB5b3UgaGF2ZSBubyBFR0dzIHRvIHdpdGhkcmF3CQAFFAAAAAIJAAROAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAAHX2Fzc2V0XwUAAAAFYXNzZXQCAAAAEF93aXRoZHJhd25BbW91bnQJAABkAAAAAgkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAAAdfYXNzZXRfBQAAAAVhc3NldAIAAAAQX3dpdGhkcmF3bkFtb3VudAkAAGgAAAACBQAAAAZyZXdhcmQFAAAABnNjYWxlMgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEJAAJZAAAAAQUAAAAHYWRkcmVzcwkAAGgAAAACBQAAAAZyZXdhcmQAAAAAAAAPQkAJAQAAAA1nZXRFZ2dBc3NldElkAAAAAAUAAAADbmlsBQAAAAx2YWxpZFBheW1lbnQJAABoAAAAAgUAAAAGcmV3YXJkAAAAAAAAD0JACQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAAA3h0tbg==", "height": 4133016, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 6vYJqpd2jaTMbX9Je6K8FFHPceyRrGrt3GLUbrg1Ah1Z Next: DV2KsVzPZGpDCzbPqxYyEQmzs4oxp3FeSWWQ3Ktwu6xM Diff:
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | - | let Scale = 100000000 | |
4 | + | let perchPrice = (100 * 1000000) | |
5 | + | ||
6 | + | let scale = 10000 | |
7 | + | ||
8 | + | let scale2 = 1000000 | |
5 | 9 | ||
6 | 10 | func tryGetStringExternal (address,key) = match getString(address, key) { | |
7 | 11 | case a: String => | |
13 | 17 | ||
14 | 18 | func tryGetString (key) = tryGetStringExternal(this, key) | |
15 | 19 | ||
16 | - | ||
17 | - | func staticKey_refContractAddress () = "static_refContractAddress" | |
18 | - | ||
19 | - | ||
20 | - | let keyGlobalLastInterest = "global_lastCheck_interest" | |
21 | 20 | ||
22 | 21 | func staticKey_oracleAddress () = "static_oracleAddress" | |
23 | 22 | ||
31 | 30 | func staticKey_breederAddress () = "static_breederAddress" | |
32 | 31 | ||
33 | 32 | ||
33 | + | func staticKey_itemsAddress () = "static_itemsAddress" | |
34 | + | ||
35 | + | ||
36 | + | func staticKey_metaRaceAddress () = "static_metaRaceAddress" | |
37 | + | ||
38 | + | ||
34 | 39 | func staticKey_accBoosterAddress () = "static_accBoosterAddress" | |
35 | 40 | ||
36 | 41 | ||
37 | - | func staticKey_ | |
42 | + | func staticKey_proxyStakingContracts () = "static_proxyStakingContracts" | |
38 | 43 | ||
39 | 44 | ||
40 | - | func staticKey_burnAddress () = "static_burnAddress" | |
45 | + | func staticKey_maintenance () = "static_maintenance" | |
46 | + | ||
47 | + | ||
48 | + | func staticKey_cfMasterAddress () = "static_cfMasterAddress" | |
41 | 49 | ||
42 | 50 | ||
43 | 51 | func staticKey_extraFee () = "static_extraFee" | |
46 | 54 | func staticKey_feeAggregator () = "static_feeAggregator" | |
47 | 55 | ||
48 | 56 | ||
49 | - | let keyGlobalEarned = "global_earnings" | |
50 | - | ||
51 | - | func staticKey_perchFee () = "static_perchFee" | |
52 | - | ||
53 | - | ||
54 | - | func staticKey_rebirthAddress () = "static_rebirthAddress" | |
55 | - | ||
56 | - | ||
57 | - | func staticKey_turtleRebirthAddress () = "static_turtleRebirthAddress" | |
58 | - | ||
59 | - | ||
60 | - | func staticKey_itemsAddress () = "static_itemsAddress" | |
61 | - | ||
62 | - | ||
63 | - | func totalStakedKey () = "total_staked" | |
64 | - | ||
65 | - | ||
66 | - | func staticKey_proxyStakingContracts () = "static_proxyStakingContracts" | |
57 | + | func staticKey_farmingNew () = "static_farmingAddressNew" | |
67 | 58 | ||
68 | 59 | ||
69 | 60 | func getOracle () = Address(fromBase58String(tryGetString(staticKey_oracleAddress()))) | |
70 | - | ||
71 | - | ||
72 | - | func getRebirthAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_rebirthAddress()))) | |
73 | 61 | ||
74 | 62 | ||
75 | 63 | func getEggAssetId () = fromBase58String(tryGetStringExternal(getOracle(), staticKey_eggAssetId())) | |
81 | 69 | func getBreederAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_breederAddress()))) | |
82 | 70 | ||
83 | 71 | ||
72 | + | func getItemsAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_itemsAddress()))) | |
73 | + | ||
74 | + | ||
75 | + | func getMetaraceAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_metaRaceAddress()))) | |
76 | + | ||
77 | + | ||
84 | 78 | func getAccBoosterAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_accBoosterAddress()))) | |
85 | 79 | ||
86 | 80 | ||
87 | - | func | |
81 | + | func getProxyStaking () = tryGetStringExternal(getOracle(), staticKey_proxyStakingContracts()) | |
88 | 82 | ||
89 | 83 | ||
90 | - | func getBurnAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_burnAddress()))) | |
84 | + | func getMaintenance () = tryGetStringExternal(getOracle(), staticKey_maintenance()) | |
85 | + | ||
86 | + | ||
87 | + | func getCfMasterAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_cfMasterAddress()))) | |
91 | 88 | ||
92 | 89 | ||
93 | 90 | func getFeeAggregator () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_feeAggregator()))) | |
94 | 91 | ||
95 | 92 | ||
96 | - | func getRefContractAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_refContractAddress()))) | |
97 | - | ||
98 | - | ||
99 | - | func getTurtleRebirthAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_turtleRebirthAddress()))) | |
100 | - | ||
101 | - | ||
102 | - | func getItemsAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_itemsAddress()))) | |
103 | - | ||
104 | - | ||
105 | - | func getProxyStaking () = tryGetStringExternal(getOracle(), staticKey_proxyStakingContracts()) | |
106 | - | ||
107 | - | ||
108 | - | func keyLastCheckInterest (address,asset) = (((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest") | |
109 | - | ||
110 | - | ||
111 | - | func assetFarmingPower (address,asset) = (((("address_" + address) + "_asset_") + asset) + "_farmingPower") | |
112 | - | ||
113 | - | ||
114 | - | func rewardClaimedKey (address,asset) = (((address + "_asset_") + asset) + "_claimed") | |
115 | - | ||
116 | - | ||
117 | - | func totalStakedUserKey (address) = ("total_staked_" + address) | |
93 | + | func getNewFarmingAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_farmingNew()))) | |
118 | 94 | ||
119 | 95 | ||
120 | 96 | let RefererReward = 5 | |
129 | 105 | } | |
130 | 106 | ||
131 | 107 | ||
108 | + | func getRewardPerBlock () = 0 | |
109 | + | ||
110 | + | ||
111 | + | func isLocked () = if ((getMaintenance() != "")) | |
112 | + | then throw(getMaintenance()) | |
113 | + | else 0 | |
114 | + | ||
115 | + | ||
132 | 116 | func tryGetInteger (key) = match getInteger(this, key) { | |
133 | 117 | case b: Int => | |
134 | 118 | b | |
135 | 119 | case _ => | |
136 | 120 | 0 | |
137 | - | } | |
138 | - | ||
139 | - | ||
140 | - | func asInt (value) = match value { | |
141 | - | case int: Int => | |
142 | - | int | |
143 | - | case _ => | |
144 | - | throw("FAI: wrong type, expected: Int") | |
145 | - | } | |
146 | - | ||
147 | - | ||
148 | - | func asIntTuple (value) = match value { | |
149 | - | case int: (Int, Int) => | |
150 | - | int | |
151 | - | case _ => | |
152 | - | throw("FAI: wrong type, expected: (Int,Int)") | |
153 | - | } | |
154 | - | ||
155 | - | ||
156 | - | func handleStakingTopUp (amount) = { | |
157 | - | let currentInterest = tryGetInteger(keyGlobalLastInterest) | |
158 | - | let totalStakedAmount = tryGetInteger(totalStakedKey()) | |
159 | - | let interestDelta = if ((totalStakedAmount > 0)) | |
160 | - | then fraction(amount, Scale, totalStakedAmount) | |
161 | - | else 0 | |
162 | - | [IntegerEntry(keyGlobalEarned, (tryGetInteger(keyGlobalEarned) + amount)), IntegerEntry(keyGlobalLastInterest, (currentInterest + interestDelta))] | |
163 | - | } | |
164 | - | ||
165 | - | ||
166 | - | func asString (value) = match value { | |
167 | - | case string: String => | |
168 | - | string | |
169 | - | case _ => | |
170 | - | throw("FAS: wrong type, expected: String") | |
171 | 121 | } | |
172 | 122 | ||
173 | 123 | ||
201 | 151 | } | |
202 | 152 | ||
203 | 153 | ||
204 | - | func getAssetRarityComplete (isJackpot,assetName) = { | |
205 | - | let rarity = if (isJackpot) | |
206 | - | then 100 | |
207 | - | else { | |
208 | - | let generation = take(takeRight(assetName, 2), 1) | |
209 | - | let farmGen = asString(invoke(getBreederAddress(), "getGenFromName", [assetName], nil)) | |
210 | - | if ((farmGen == farmGen)) | |
211 | - | then getAssetRarity(farmGen, generation) | |
212 | - | else throw("Strict value is not equal to itself.") | |
213 | - | } | |
214 | - | rarity | |
215 | - | } | |
154 | + | func asString (value) = match value { | |
155 | + | case string: String => | |
156 | + | string | |
157 | + | case _ => | |
158 | + | throw("FAS: wrong type, expected: String") | |
159 | + | } | |
216 | 160 | ||
217 | 161 | ||
218 | - | func updateFarmingPower (address,asset) = { | |
219 | - | let totalStaked = tryGetInteger(totalStakedKey()) | |
220 | - | let totalStakedUser = tryGetInteger(totalStakedUserKey(address)) | |
221 | - | let currentFP = tryGetInteger(assetFarmingPower(address, asset)) | |
222 | - | let newFP = asIntTuple(invoke(this, "calculateFarmPower", [asset], nil)) | |
223 | - | if ((currentFP != 0)) | |
224 | - | then [IntegerEntry(totalStakedKey(), ((totalStaked - currentFP) + newFP._1)), IntegerEntry(totalStakedUserKey(address), ((totalStakedUser - currentFP) + newFP._1)), IntegerEntry(assetFarmingPower(address, asset), newFP._1), IntegerEntry("DEBUG_currentFP", currentFP), IntegerEntry("DEBUG_newFP", newFP._1)] | |
225 | - | else nil | |
226 | - | } | |
227 | - | ||
228 | - | ||
229 | - | func claimStakingResult (address,asset,recalc) = { | |
230 | - | let currentInterest = tryGetInteger(keyGlobalLastInterest) | |
231 | - | let lastCheckInterest = tryGetInteger(keyLastCheckInterest(address, asset)) | |
232 | - | let stakedAmount = tryGetInteger(assetFarmingPower(address, asset)) | |
233 | - | let fpUpdate = if (recalc) | |
234 | - | then updateFarmingPower(address, asset) | |
235 | - | else nil | |
236 | - | if ((fpUpdate == fpUpdate)) | |
237 | - | then { | |
238 | - | let reward = if ((lastCheckInterest > 0)) | |
239 | - | then fraction((currentInterest - lastCheckInterest), stakedAmount, Scale) | |
240 | - | else 0 | |
241 | - | $Tuple2(([ScriptTransfer(Address(fromBase58String(address)), reward, getEggAssetId()), IntegerEntry(keyLastCheckInterest(address, asset), currentInterest), IntegerEntry(rewardClaimedKey(address, asset), (tryGetInteger(rewardClaimedKey(address, asset)) + reward))] ++ fpUpdate), reward) | |
242 | - | } | |
243 | - | else throw("Strict value is not equal to itself.") | |
244 | - | } | |
162 | + | func asInt (value) = match value { | |
163 | + | case int: Int => | |
164 | + | int | |
165 | + | case _ => | |
166 | + | throw("FAI: wrong type, expected: Int") | |
167 | + | } | |
245 | 168 | ||
246 | 169 | ||
247 | 170 | func asBoolean (value) = match value { | |
252 | 175 | } | |
253 | 176 | ||
254 | 177 | ||
178 | + | func getAssetFarmingPower (assetId,address) = if (if ((value(assetInfo(assetId)).issuer == getBreederAddress())) | |
179 | + | then true | |
180 | + | else (value(assetInfo(assetId)).issuer == getIncubatorAddress())) | |
181 | + | then { | |
182 | + | let farmBoost = asInt(invoke(getItemsAddress(), "calculateFarmingPowerBoost", [toBase58String(assetId), address], nil)) | |
183 | + | if ((farmBoost == farmBoost)) | |
184 | + | then { | |
185 | + | let assetName = value(assetInfo(assetId)).name | |
186 | + | let isJackpot = (takeRight(value(assetName), 1) == "U") | |
187 | + | let farmGen = if (isJackpot) | |
188 | + | then "" | |
189 | + | else asString(invoke(getBreederAddress(), "getGenFromName", [assetName], nil)) | |
190 | + | if ((farmGen == farmGen)) | |
191 | + | then { | |
192 | + | let rarity = if (isJackpot) | |
193 | + | then 100 | |
194 | + | else { | |
195 | + | let generation = take(takeRight(assetName, 2), 1) | |
196 | + | getAssetRarity(farmGen, generation) | |
197 | + | } | |
198 | + | let totalFarmingPower = (rarity + fraction(rarity, farmBoost, 100)) | |
199 | + | $Tuple2(farmGen, totalFarmingPower) | |
200 | + | } | |
201 | + | else throw("Strict value is not equal to itself.") | |
202 | + | } | |
203 | + | else throw("Strict value is not equal to itself.") | |
204 | + | } | |
205 | + | else throw("not valid NFT") | |
206 | + | ||
207 | + | ||
208 | + | func getLastKnownAssetFarmingPower (address,assetId) = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_farmingPower")) | |
209 | + | ||
210 | + | ||
211 | + | func calcInterest (previousInterest,previousInterestHeight,totalFarmingPower) = (previousInterest + (((scale * getRewardPerBlock()) * (height - previousInterestHeight)) / totalFarmingPower)) | |
212 | + | ||
213 | + | ||
214 | + | func getCurrentInterest () = if ((tryGetInteger("total_farmingPower") > 0)) | |
215 | + | then { | |
216 | + | let previousInterest = tryGetInteger("total_lastCheckInterest") | |
217 | + | let previousInterestHeight = tryGetInteger("total_lastCheckInterestHeight") | |
218 | + | let totalFarmingPower = tryGetInteger("total_farmingPower") | |
219 | + | calcInterest(previousInterest, previousInterestHeight, totalFarmingPower) | |
220 | + | } | |
221 | + | else if ((tryGetInteger("total_startHeight") != 0)) | |
222 | + | then tryGetInteger("total_lastCheckInterest") | |
223 | + | else throw("farming is not launched, yet") | |
224 | + | ||
225 | + | ||
226 | + | func calcAssetRewardDelta (address,assetId,assetFarmingPower) = { | |
227 | + | let lastCheckAssetInterest = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_lastCheckInterest")) | |
228 | + | let currentInterest = getCurrentInterest() | |
229 | + | (assetFarmingPower * (currentInterest - lastCheckAssetInterest)) | |
230 | + | } | |
231 | + | ||
232 | + | ||
233 | + | func addAssetIdToGenEntry (assetId,assetGen) = { | |
234 | + | let currentValue = tryGetString((("assets_" + assetGen) + "_locked")) | |
235 | + | if ((currentValue == "")) | |
236 | + | then assetId | |
237 | + | else ((currentValue + ",") + assetId) | |
238 | + | } | |
239 | + | ||
240 | + | ||
241 | + | func getStakeResult (address,assetId,assetFarmingPower,unstaker) = { | |
242 | + | let asset = toBase58String(assetId) | |
243 | + | [IntegerEntry("total_farmingPower", (tryGetInteger("total_farmingPower") + assetFarmingPower)), IntegerEntry("total_lastCheckInterest", getCurrentInterest()), IntegerEntry("total_lastCheckInterestHeight", height), StringEntry((("asset_" + asset) + "_owner"), address), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_farmingPower"), assetFarmingPower), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest"), getCurrentInterest()), StringEntry((((("address_" + address) + "_asset_") + asset) + "_unstaker"), unstaker)] | |
244 | + | } | |
245 | + | ||
246 | + | ||
247 | + | func getUnstakeResult (address,assetId,color,caller,realCaller,claimEggs) = { | |
248 | + | let locked = isLocked() | |
249 | + | if ((locked == locked)) | |
250 | + | then { | |
251 | + | let asset = toBase58String(assetId) | |
252 | + | let unstaker = tryGetString((((("address_" + address) + "_asset_") + asset) + "_unstaker")) | |
253 | + | if (if ((unstaker != "")) | |
254 | + | then (unstaker != realCaller) | |
255 | + | else false) | |
256 | + | then throw("FUN: It seems duck was staked throuh a dapp, not directly, please unstake through dapp!") | |
257 | + | else { | |
258 | + | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
259 | + | if (!((assetFarmingPower > 0))) | |
260 | + | then throw("FGU: Asset farming power not bigger then 0") | |
261 | + | else { | |
262 | + | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
263 | + | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
264 | + | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
265 | + | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
266 | + | let isWithoutPerch = tryGetBoolean((((("address_" + address) + "_asset_") + asset) + "_without_perch")) | |
267 | + | let rewardAfterSickNess = reward | |
268 | + | let appendPerches = if (isWithoutPerch) | |
269 | + | then [DeleteEntry((((("address_" + address) + "_asset_") + asset) + "_without_perch"))] | |
270 | + | else [IntegerEntry(((("address_" + address) + "_perchesAvailable_") + color), (tryGetInteger(((("address_" + address) + "_perchesAvailable_") + color)) + 1))] | |
271 | + | let sendTx = if (claimEggs) | |
272 | + | then $Tuple2([ScriptTransfer(caller, (rewardAfterSickNess * 1000000), getEggAssetId())], (rewardAfterSickNess * 1000000)) | |
273 | + | else $Tuple2(nil, 0) | |
274 | + | $Tuple2(((([IntegerEntry("total_farmingPower", (tryGetInteger("total_farmingPower") - assetFarmingPower)), IntegerEntry("total_lastCheckInterest", getCurrentInterest()), IntegerEntry("total_lastCheckInterestHeight", height), DeleteEntry((("asset_" + asset) + "_owner")), DeleteEntry((((("address_" + address) + "_asset_") + asset) + "_unstaker")), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_farmingPower"), 0), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest"), getCurrentInterest()), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount"), (withdrawnAmount + (rewardAfterSickNess * scale2))), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"), (tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount")) + assetRewardDelta))] ++ appendPerches) ++ [ScriptTransfer(caller, 1, assetId)]) ++ sendTx._1), sendTx._2) | |
275 | + | } | |
276 | + | } | |
277 | + | } | |
278 | + | else throw("Strict value is not equal to itself.") | |
279 | + | } | |
280 | + | ||
281 | + | ||
255 | 282 | func calculatePerchPrice (address) = { | |
256 | 283 | let hasArtefactStaked = tryGetStringExternal(getAccBoosterAddress(), (("ART-XMISTL_" + address) + "_owner")) | |
257 | - | let perchPrice = getIntegerValue(getOracle(), staticKey_perchFee()) | |
258 | 284 | if ((hasArtefactStaked == "")) | |
259 | 285 | then perchPrice | |
260 | 286 | else ((perchPrice / 10) * 9) | |
268 | 294 | } | |
269 | 295 | ||
270 | 296 | ||
297 | + | func unstakeNFTInternal (asset,i,claimEgg) = { | |
298 | + | let assetId = fromBase58String(asset) | |
299 | + | let realCaller = toString(i.caller) | |
300 | + | let address = if (isProxyStakingSc(toString(i.caller))) | |
301 | + | then toString(i.originCaller) | |
302 | + | else realCaller | |
303 | + | let color = takeRight(value(assetInfo(assetId)).name, 1) | |
304 | + | if ((color == "U")) | |
305 | + | then throw("FUN: use another function to unstake Jackpot NFT") | |
306 | + | else { | |
307 | + | let result = getUnstakeResult(address, assetId, color, i.caller, realCaller, claimEgg) | |
308 | + | result | |
309 | + | } | |
310 | + | } | |
311 | + | ||
312 | + | ||
313 | + | func unstakeJackpotInternal (asset,i,claimEgg) = { | |
314 | + | let assetId = fromBase58String(asset) | |
315 | + | let realCaller = toString(i.caller) | |
316 | + | let address = if (isProxyStakingSc(toString(i.caller))) | |
317 | + | then toString(i.originCaller) | |
318 | + | else realCaller | |
319 | + | let color = tryGetString((((("address_" + address) + "_asset_") + asset) + "_perchColor")) | |
320 | + | if ((takeRight(value(value(assetInfo(assetId)).name), 1) != "U")) | |
321 | + | then throw("jackpot only") | |
322 | + | else { | |
323 | + | let result = getUnstakeResult(address, assetId, color, i.caller, realCaller, claimEgg) | |
324 | + | result | |
325 | + | } | |
326 | + | } | |
327 | + | ||
328 | + | ||
329 | + | func getBool (key) = match getBoolean(this, key) { | |
330 | + | case b: Boolean => | |
331 | + | b | |
332 | + | case _ => | |
333 | + | false | |
334 | + | } | |
335 | + | ||
336 | + | ||
337 | + | func isTestEnv () = getBool("TESTENV") | |
338 | + | ||
339 | + | ||
271 | 340 | @Callable(i) | |
272 | - | func calculateFarmPower (assetId) = if (!(if ((value(assetInfo(fromBase58String(assetId))).issuer == getBreederAddress())) | |
273 | - | then true | |
274 | - | else (value(assetInfo(fromBase58String(assetId))).issuer == getIncubatorAddress()))) | |
275 | - | then throw("This does not seem like a valid Duck!") | |
276 | - | else { | |
277 | - | let assetName = value(assetInfo(fromBase58String(assetId))).name | |
278 | - | let gen = takeRight(assetName, 1) | |
279 | - | let isJackpot = (takeRight(assetName, 1) == "U") | |
280 | - | let rarity = getAssetRarityComplete(isJackpot, assetName) | |
281 | - | let genotype = split(dropRight(drop(assetName, 5), 3), "") | |
282 | - | func uniqueArrayFilter (accum,nextGen) = if (!(containsElement(accum, nextGen))) | |
283 | - | then (accum :+ nextGen) | |
284 | - | else accum | |
285 | - | ||
286 | - | let uniqueList = { | |
287 | - | let $l = genotype | |
288 | - | let $s = size($l) | |
289 | - | let $acc0 = nil | |
290 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
291 | - | then $a | |
292 | - | else uniqueArrayFilter($a, $l[$i]) | |
293 | - | ||
294 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
295 | - | then $a | |
296 | - | else throw("List size exceeds 8") | |
297 | - | ||
298 | - | $f0_2($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) | |
299 | - | } | |
300 | - | let totalGenes = if ((gen == "U")) | |
301 | - | then 8 | |
302 | - | else size(uniqueList) | |
303 | - | let power = pow(15, 1, totalGenes, 0, 2, DOWN) | |
304 | - | let multiplier = (((height - 3750000) * 100) / (((60 * 24) * 30) * 3)) | |
305 | - | let basePower = tryGetInteger((assetId + "_basePower")) | |
306 | - | let finalPower = if ((basePower > 0)) | |
307 | - | then basePower | |
308 | - | else ((power * multiplier) / 100) | |
309 | - | let finalPowerRarity = ((finalPower * rarity) / 100) | |
310 | - | let farmBoost = asInt(invoke(getItemsAddress(), "calculateFarmingPowerBoost", [assetId, toString(i.originCaller)], nil)) | |
311 | - | if ((farmBoost == farmBoost)) | |
312 | - | then { | |
313 | - | let finalPowerRarityBoost = (finalPowerRarity + ((finalPowerRarity * farmBoost) / 100)) | |
314 | - | $Tuple2([IntegerEntry(("DEBUG_" + assetName), finalPower), IntegerEntry(("DEBUG_RARITY" + assetName), rarity), IntegerEntry(("DEBUG_FPRARITY_" + assetName), finalPowerRarity), IntegerEntry(("DEBUG_FARMBOOST_" + assetName), farmBoost), IntegerEntry(("DEBUG_FPRARITYBOOST_" + assetName), finalPowerRarityBoost), IntegerEntry(("DEBUG_POWER_" + assetName), power), IntegerEntry(("DEBUG_BASEPOWER_" + assetName), basePower), IntegerEntry(("DEBUG_COEFFICIENT_" + assetName), multiplier), IntegerEntry(("DEBUG_BOOST_" + assetName), farmBoost)], $Tuple2(finalPowerRarityBoost, finalPower)) | |
315 | - | } | |
316 | - | else throw("Strict value is not equal to itself.") | |
317 | - | } | |
341 | + | func removePerches (address) = if ((i.caller != getNewFarmingAddress())) | |
342 | + | then throw("FRP: admin only") | |
343 | + | else [IntegerEntry((("address_" + address) + "_perchesAvailable_R"), 0), IntegerEntry((("address_" + address) + "_perchesAvailable_G"), 0), IntegerEntry((("address_" + address) + "_perchesAvailable_B"), 0), IntegerEntry((("address_" + address) + "_perchesAvailable_U"), 0)] | |
318 | 344 | ||
319 | 345 | ||
320 | 346 | ||
326 | 352 | ||
327 | 353 | ||
328 | 354 | @Callable(i) | |
329 | - | func buyPerch (colorI,refererAddress) = { | |
330 | - | let validPayment = checkAdditionalPayment(i.payments[0]) | |
355 | + | func init () = if ((i.caller != this)) | |
356 | + | then throw("FI: admin only") | |
357 | + | else [IntegerEntry("total_startHeight", height)] | |
358 | + | ||
359 | + | ||
360 | + | ||
361 | + | @Callable(i) | |
362 | + | func buyPerch (colorI,refererAddress) = throw("FBN: function is disabled, migration to new sc ongoing") | |
363 | + | ||
364 | + | ||
365 | + | ||
366 | + | @Callable(i) | |
367 | + | func addFreePerch (address,color) = throw("FBN: function is disabled, migration to new sc ongoing") | |
368 | + | ||
369 | + | ||
370 | + | ||
371 | + | @Callable(i) | |
372 | + | func stakeNFT () = throw("FBN: function is disabled, migration to new sc ongoing") | |
373 | + | ||
374 | + | ||
375 | + | ||
376 | + | @Callable(i) | |
377 | + | func stakeNFTWithoutPerch () = throw("FBN: function is disabled, migration to new sc ongoing") | |
378 | + | ||
379 | + | ||
380 | + | ||
381 | + | @Callable(i) | |
382 | + | func unstakeNFT (asset) = { | |
383 | + | let validPayment = if ((i.caller == getMetaraceAddress())) | |
384 | + | then nil | |
385 | + | else checkAdditionalPayment(i.payments[0]) | |
331 | 386 | if ((validPayment == validPayment)) | |
332 | 387 | then { | |
333 | - | let color = if ((colorI == "U")) | |
334 | - | then "B" | |
335 | - | else colorI | |
336 | - | if ((0 > value(indexOf(["B", "R", "G", "Y"], color)))) | |
337 | - | then throw("you need to set color properly") | |
338 | - | else { | |
339 | - | let exactPrice = calculatePerchPrice(toString(i.caller)) | |
340 | - | let leftToPay = if ((i.originCaller == i.caller)) | |
341 | - | then { | |
342 | - | let amountPaidByCoupons = asInt(invoke(getCouponsAddress(), "useCoupons", [exactPrice], nil)) | |
343 | - | if ((amountPaidByCoupons == amountPaidByCoupons)) | |
344 | - | then (exactPrice - amountPaidByCoupons) | |
345 | - | else throw("Strict value is not equal to itself.") | |
346 | - | } | |
347 | - | else exactPrice | |
348 | - | let firstPayment = if ((size(i.payments) == 2)) | |
349 | - | then value(i.payments[1]) | |
350 | - | else value(i.payments[0]) | |
351 | - | if ((firstPayment.assetId != getEggAssetId())) | |
352 | - | then throw(("FBP: You can attach only EGG tokens with the following asset id: " + toBase58String(getEggAssetId()))) | |
353 | - | else if ((firstPayment.amount != leftToPay)) | |
354 | - | then throw(((("FBP: To buy a perch you currently need the following amount of EGGlets: " + toString(leftToPay)) + " ") + toString(i.caller))) | |
355 | - | else { | |
356 | - | let refererRewardForPerch = fraction(leftToPay, 5, 100) | |
357 | - | let refCall = asBoolean(invoke(getRefContractAddress(), "refPayment", [refererAddress], [AttachedPayment(getEggAssetId(), refererRewardForPerch)])) | |
358 | - | if ((refCall == refCall)) | |
359 | - | then { | |
360 | - | let toBurn = if (refCall) | |
361 | - | then (leftToPay - refererRewardForPerch) | |
362 | - | else leftToPay | |
363 | - | let burnCall = invoke(getBurnAddress(), "burnAttachedPayments", nil, [AttachedPayment(getEggAssetId(), toBurn)]) | |
364 | - | if ((burnCall == burnCall)) | |
365 | - | then { | |
366 | - | let perchAmountKey = ((("address_" + toString(i.caller)) + "_perchesAvailable_") + color) | |
367 | - | let perchAmount = tryGetInteger(perchAmountKey) | |
368 | - | ([IntegerEntry(perchAmountKey, (perchAmount + 1))] ++ validPayment) | |
369 | - | } | |
370 | - | else throw("Strict value is not equal to itself.") | |
371 | - | } | |
372 | - | else throw("Strict value is not equal to itself.") | |
373 | - | } | |
374 | - | } | |
388 | + | let result = unstakeNFTInternal(asset, i, true) | |
389 | + | $Tuple2((result._1 ++ validPayment), result._2) | |
375 | 390 | } | |
376 | 391 | else throw("Strict value is not equal to itself.") | |
377 | 392 | } | |
379 | 394 | ||
380 | 395 | ||
381 | 396 | @Callable(i) | |
382 | - | func addFreePerch (address,color,amount) = if ((0 > value(indexOf(["B", "R", "G", "Y"], color)))) | |
383 | - | then throw("you need to set color properly") | |
384 | - | else if (if (if ((i.caller != getRebirthAddress())) | |
385 | - | then (i.caller != getTurtleRebirthAddress()) | |
386 | - | else false) | |
387 | - | then (i.caller != this) | |
388 | - | else false) | |
389 | - | then throw("rebirth and admin only") | |
390 | - | else { | |
391 | - | let perchAmountKey = ((("address_" + address) + "_perchesAvailable_") + color) | |
392 | - | let perchAmount = tryGetInteger(perchAmountKey) | |
393 | - | $Tuple2([IntegerEntry(perchAmountKey, (perchAmount + amount))], "") | |
394 | - | } | |
397 | + | func unstakeNFTWithoutClaim (asset) = unstakeNFTInternal(asset, i, false) | |
395 | 398 | ||
396 | 399 | ||
397 | 400 | ||
398 | 401 | @Callable(i) | |
399 | - | func migratePerches (address) = { | |
400 | - | let oldFarming = addressFromStringValue(tryGetStringExternal(getOracle(), "static_farmingAddress")) | |
401 | - | func tryGetIntegerOldFarming (key) = match getInteger(oldFarming, key) { | |
402 | - | case b: Int => | |
403 | - | b | |
404 | - | case _ => | |
405 | - | 0 | |
406 | - | } | |
407 | - | ||
408 | - | let perchAmountB = tryGetIntegerOldFarming((("address_" + address) + "_perchesAvailable_B")) | |
409 | - | let perchAmountR = tryGetIntegerOldFarming((("address_" + address) + "_perchesAvailable_R")) | |
410 | - | let perchAmountG = tryGetIntegerOldFarming((("address_" + address) + "_perchesAvailable_G")) | |
411 | - | let perchAmountY = tryGetIntegerOldFarming((("address_" + address) + "_perchesAvailable_Y")) | |
412 | - | let perchAmountBInvoke = invoke(this, "addFreePerch", [address, "B", perchAmountB], nil) | |
413 | - | let perchAmountRInvoke = invoke(this, "addFreePerch", [address, "R", perchAmountR], nil) | |
414 | - | let perchAmountGInvoke = invoke(this, "addFreePerch", [address, "G", perchAmountG], nil) | |
415 | - | let perchAmountYInvoke = invoke(this, "addFreePerch", [address, "Y", perchAmountY], nil) | |
416 | - | let invokePerchesDelete = invoke(oldFarming, "removePerches", [address], nil) | |
417 | - | nil | |
418 | - | } | |
402 | + | func stakeJackpot (color) = throw("FBN: function is disabled, migration to new sc ongoing") | |
419 | 403 | ||
420 | 404 | ||
421 | 405 | ||
422 | 406 | @Callable(i) | |
423 | - | func stakeNFT (jColor,usePerchOrigin,stakeWithoutPerch) = if (true) | |
424 | - | then throw("Staking is disabled") | |
425 | - | else if (if (stakeWithoutPerch) | |
426 | - | then !(isProxyStakingSc(toString(i.caller))) | |
427 | - | else false) | |
428 | - | then throw("You can't stake without a perch") | |
429 | - | else { | |
430 | - | let validPayment = checkAdditionalPayment(i.payments[0]) | |
431 | - | if ((validPayment == validPayment)) | |
432 | - | then { | |
433 | - | let pmt = value(i.payments[1]) | |
434 | - | let assetId = value(pmt.assetId) | |
435 | - | let assetName = value(value(assetInfo(assetId)).name) | |
436 | - | let isJackpot = (takeRight(assetName, 1) == "U") | |
437 | - | let address = toString(i.caller) | |
438 | - | let perchAddress = if (usePerchOrigin) | |
439 | - | then toString(i.originCaller) | |
440 | - | else address | |
441 | - | let rarity = getAssetRarityComplete(isJackpot, assetName) | |
442 | - | let perches = if (stakeWithoutPerch) | |
443 | - | then nil | |
444 | - | else { | |
445 | - | let color = if (isJackpot) | |
446 | - | then jColor | |
447 | - | else takeRight(assetName, 1) | |
448 | - | let availablePerches = tryGetInteger(((("address_" + perchAddress) + "_perchesAvailable_") + color)) | |
449 | - | if ((0 >= availablePerches)) | |
450 | - | then throw(("no perches available for the color " + color)) | |
451 | - | else [IntegerEntry(((("address_" + perchAddress) + "_perchesAvailable_") + color), (availablePerches - 1)), StringEntry((((("address_" + address) + "_asset_") + toBase58String(assetId)) + "_perchColor"), color)] | |
452 | - | } | |
453 | - | if ((perches == perches)) | |
454 | - | then if ((pmt.amount != 1)) | |
455 | - | then throw("NFT is not attached") | |
456 | - | else { | |
457 | - | let farmingPower = asIntTuple(invoke(this, "calculateFarmPower", [toBase58String(assetId)], nil)) | |
458 | - | if ((farmingPower == farmingPower)) | |
459 | - | then { | |
460 | - | let result = claimStakingResult(address, toBase58String(assetId), false) | |
461 | - | if ((result == result)) | |
462 | - | then ((([IntegerEntry(totalStakedKey(), (tryGetInteger(totalStakedKey()) + farmingPower._1)), IntegerEntry(totalStakedUserKey(address), (tryGetInteger(totalStakedUserKey(address)) + farmingPower._1)), StringEntry((toBase58String(assetId) + "_owner"), address), BooleanEntry((toBase58String(assetId) + "_use_origin"), usePerchOrigin), StringEntry((toBase58String(assetId) + "_original_caller"), toString(i.originCaller)), IntegerEntry(assetFarmingPower(address, toBase58String(assetId)), farmingPower._1), IntegerEntry((toBase58String(assetId) + "_basePower"), farmingPower._2), BooleanEntry((toBase58String(assetId) + "_without_perch"), stakeWithoutPerch)] ++ validPayment) ++ perches) ++ result._1) | |
463 | - | else throw("Strict value is not equal to itself.") | |
464 | - | } | |
465 | - | else throw("Strict value is not equal to itself.") | |
466 | - | } | |
467 | - | else throw("Strict value is not equal to itself.") | |
468 | - | } | |
469 | - | else throw("Strict value is not equal to itself.") | |
470 | - | } | |
471 | - | ||
472 | - | ||
473 | - | ||
474 | - | @Callable(i) | |
475 | - | func unstakeNFT (asset) = { | |
476 | - | let address = toString(i.caller) | |
477 | - | let result = claimStakingResult(address, asset, false) | |
478 | - | if ((result == result)) | |
407 | + | func unstakeJackpot (asset) = { | |
408 | + | let validPayment = checkAdditionalPayment(i.payments[0]) | |
409 | + | if ((validPayment == validPayment)) | |
479 | 410 | then { | |
480 | - | let validPayment = checkAdditionalPayment(i.payments[0]) | |
481 | - | if ((validPayment == validPayment)) | |
482 | - | then { | |
483 | - | let color = tryGetString((((("address_" + address) + "_asset_") + asset) + "_perchColor")) | |
484 | - | let withoutPerch = tryGetBoolean((asset + "_without_perch")) | |
485 | - | let perches = if (withoutPerch) | |
486 | - | then nil | |
487 | - | else { | |
488 | - | let usePerchOrigin = tryGetBoolean((asset + "_use_origin")) | |
489 | - | let perchOwner = if (usePerchOrigin) | |
490 | - | then toString(i.originCaller) | |
491 | - | else address | |
492 | - | [IntegerEntry(((("address_" + address) + "_perchesAvailable_") + color), (tryGetInteger(((("address_" + address) + "_perchesAvailable_") + color)) + 1))] | |
493 | - | } | |
494 | - | if ((perches == perches)) | |
495 | - | then { | |
496 | - | let assetFP = tryGetInteger(assetFarmingPower(address, asset)) | |
497 | - | if ((assetFP == assetFP)) | |
498 | - | then $Tuple2(((([IntegerEntry(totalStakedKey(), (tryGetInteger(totalStakedKey()) - assetFP)), IntegerEntry(totalStakedUserKey(address), (tryGetInteger(totalStakedUserKey(address)) - assetFP)), DeleteEntry((asset + "_owner")), DeleteEntry(assetFarmingPower(address, asset)), DeleteEntry((((("address_" + address) + "_asset_") + asset) + "_perchColor")), DeleteEntry((asset + "_original_caller")), DeleteEntry((asset + "_use_origin")), DeleteEntry((asset + "_without_perch")), ScriptTransfer(Address(fromBase58String(address)), 1, fromBase58String(asset))] ++ validPayment) ++ perches) ++ result._1), result._2) | |
499 | - | else throw("Strict value is not equal to itself.") | |
500 | - | } | |
501 | - | else throw("Strict value is not equal to itself.") | |
502 | - | } | |
503 | - | else throw("Strict value is not equal to itself.") | |
411 | + | let result = unstakeJackpotInternal(asset, i, true) | |
412 | + | $Tuple2((result._1 ++ validPayment), result._2) | |
504 | 413 | } | |
505 | 414 | else throw("Strict value is not equal to itself.") | |
506 | 415 | } | |
508 | 417 | ||
509 | 418 | ||
510 | 419 | @Callable(i) | |
511 | - | func topUpReward () = { | |
512 | - | let firstPayment = value(i.payments[0]) | |
513 | - | if ((firstPayment.assetId != getEggAssetId())) | |
514 | - | then throw(("FBP: You can attach only EGG tokens with the following asset id: " + toBase58String(getEggAssetId()))) | |
515 | - | else { | |
516 | - | let resHandleStaking = handleStakingTopUp(firstPayment.amount) | |
517 | - | $Tuple2(resHandleStaking, true) | |
518 | - | } | |
519 | - | } | |
420 | + | func unstakeJackpotWithoutClaimEgg (asset) = unstakeJackpotInternal(asset, i, false) | |
520 | 421 | ||
521 | 422 | ||
522 | 423 | ||
523 | 424 | @Callable(i) | |
524 | - | func claimReward (assetId) = { | |
525 | - | let validPayment = checkAdditionalPayment(i.payments[0]) | |
526 | - | if ((validPayment == validPayment)) | |
527 | - | then if ((tryGetString((assetId + "_owner")) != toString(i.caller))) | |
528 | - | then throw("You don't own this duck!!") | |
529 | - | else if ((size(i.payments) > 1)) | |
530 | - | then throw("Please don't add extra payments") | |
531 | - | else { | |
532 | - | let result = claimStakingResult(toString(i.caller), assetId, true) | |
533 | - | $Tuple2((validPayment ++ result._1), result._2) | |
425 | + | func claimReward (asset) = { | |
426 | + | let locked = isLocked() | |
427 | + | if ((locked == locked)) | |
428 | + | then { | |
429 | + | let validPayment = if ((i.originCaller == getCfMasterAddress())) | |
430 | + | then nil | |
431 | + | else checkAdditionalPayment(i.payments[0]) | |
432 | + | if ((validPayment == validPayment)) | |
433 | + | then { | |
434 | + | let address = if ((i.originCaller == getCfMasterAddress())) | |
435 | + | then toString(i.caller) | |
436 | + | else toString(i.originCaller) | |
437 | + | let assetId = fromBase58String(asset) | |
438 | + | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
439 | + | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
440 | + | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
441 | + | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
442 | + | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
443 | + | if ((0 >= reward)) | |
444 | + | then throw("FCR: you have no EGGs to withdraw") | |
445 | + | else $Tuple2(([IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount"), (tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) + (reward * scale2))), ScriptTransfer(Address(fromBase58String(address)), (reward * 1000000), getEggAssetId())] ++ validPayment), (reward * 1000000)) | |
534 | 446 | } | |
447 | + | else throw("Strict value is not equal to itself.") | |
448 | + | } | |
535 | 449 | else throw("Strict value is not equal to itself.") | |
536 | 450 | } | |
537 | 451 |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | - | let Scale = 100000000 | |
4 | + | let perchPrice = (100 * 1000000) | |
5 | + | ||
6 | + | let scale = 10000 | |
7 | + | ||
8 | + | let scale2 = 1000000 | |
5 | 9 | ||
6 | 10 | func tryGetStringExternal (address,key) = match getString(address, key) { | |
7 | 11 | case a: String => | |
8 | 12 | a | |
9 | 13 | case _ => | |
10 | 14 | "" | |
11 | 15 | } | |
12 | 16 | ||
13 | 17 | ||
14 | 18 | func tryGetString (key) = tryGetStringExternal(this, key) | |
15 | 19 | ||
16 | - | ||
17 | - | func staticKey_refContractAddress () = "static_refContractAddress" | |
18 | - | ||
19 | - | ||
20 | - | let keyGlobalLastInterest = "global_lastCheck_interest" | |
21 | 20 | ||
22 | 21 | func staticKey_oracleAddress () = "static_oracleAddress" | |
23 | 22 | ||
24 | 23 | ||
25 | 24 | func staticKey_eggAssetId () = "static_eggAssetId" | |
26 | 25 | ||
27 | 26 | ||
28 | 27 | func staticKey_incubatorAddress () = "static_incubatorAddress" | |
29 | 28 | ||
30 | 29 | ||
31 | 30 | func staticKey_breederAddress () = "static_breederAddress" | |
32 | 31 | ||
33 | 32 | ||
33 | + | func staticKey_itemsAddress () = "static_itemsAddress" | |
34 | + | ||
35 | + | ||
36 | + | func staticKey_metaRaceAddress () = "static_metaRaceAddress" | |
37 | + | ||
38 | + | ||
34 | 39 | func staticKey_accBoosterAddress () = "static_accBoosterAddress" | |
35 | 40 | ||
36 | 41 | ||
37 | - | func staticKey_ | |
42 | + | func staticKey_proxyStakingContracts () = "static_proxyStakingContracts" | |
38 | 43 | ||
39 | 44 | ||
40 | - | func staticKey_burnAddress () = "static_burnAddress" | |
45 | + | func staticKey_maintenance () = "static_maintenance" | |
46 | + | ||
47 | + | ||
48 | + | func staticKey_cfMasterAddress () = "static_cfMasterAddress" | |
41 | 49 | ||
42 | 50 | ||
43 | 51 | func staticKey_extraFee () = "static_extraFee" | |
44 | 52 | ||
45 | 53 | ||
46 | 54 | func staticKey_feeAggregator () = "static_feeAggregator" | |
47 | 55 | ||
48 | 56 | ||
49 | - | let keyGlobalEarned = "global_earnings" | |
50 | - | ||
51 | - | func staticKey_perchFee () = "static_perchFee" | |
52 | - | ||
53 | - | ||
54 | - | func staticKey_rebirthAddress () = "static_rebirthAddress" | |
55 | - | ||
56 | - | ||
57 | - | func staticKey_turtleRebirthAddress () = "static_turtleRebirthAddress" | |
58 | - | ||
59 | - | ||
60 | - | func staticKey_itemsAddress () = "static_itemsAddress" | |
61 | - | ||
62 | - | ||
63 | - | func totalStakedKey () = "total_staked" | |
64 | - | ||
65 | - | ||
66 | - | func staticKey_proxyStakingContracts () = "static_proxyStakingContracts" | |
57 | + | func staticKey_farmingNew () = "static_farmingAddressNew" | |
67 | 58 | ||
68 | 59 | ||
69 | 60 | func getOracle () = Address(fromBase58String(tryGetString(staticKey_oracleAddress()))) | |
70 | - | ||
71 | - | ||
72 | - | func getRebirthAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_rebirthAddress()))) | |
73 | 61 | ||
74 | 62 | ||
75 | 63 | func getEggAssetId () = fromBase58String(tryGetStringExternal(getOracle(), staticKey_eggAssetId())) | |
76 | 64 | ||
77 | 65 | ||
78 | 66 | func getIncubatorAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_incubatorAddress()))) | |
79 | 67 | ||
80 | 68 | ||
81 | 69 | func getBreederAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_breederAddress()))) | |
82 | 70 | ||
83 | 71 | ||
72 | + | func getItemsAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_itemsAddress()))) | |
73 | + | ||
74 | + | ||
75 | + | func getMetaraceAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_metaRaceAddress()))) | |
76 | + | ||
77 | + | ||
84 | 78 | func getAccBoosterAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_accBoosterAddress()))) | |
85 | 79 | ||
86 | 80 | ||
87 | - | func | |
81 | + | func getProxyStaking () = tryGetStringExternal(getOracle(), staticKey_proxyStakingContracts()) | |
88 | 82 | ||
89 | 83 | ||
90 | - | func getBurnAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_burnAddress()))) | |
84 | + | func getMaintenance () = tryGetStringExternal(getOracle(), staticKey_maintenance()) | |
85 | + | ||
86 | + | ||
87 | + | func getCfMasterAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_cfMasterAddress()))) | |
91 | 88 | ||
92 | 89 | ||
93 | 90 | func getFeeAggregator () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_feeAggregator()))) | |
94 | 91 | ||
95 | 92 | ||
96 | - | func getRefContractAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_refContractAddress()))) | |
97 | - | ||
98 | - | ||
99 | - | func getTurtleRebirthAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_turtleRebirthAddress()))) | |
100 | - | ||
101 | - | ||
102 | - | func getItemsAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_itemsAddress()))) | |
103 | - | ||
104 | - | ||
105 | - | func getProxyStaking () = tryGetStringExternal(getOracle(), staticKey_proxyStakingContracts()) | |
106 | - | ||
107 | - | ||
108 | - | func keyLastCheckInterest (address,asset) = (((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest") | |
109 | - | ||
110 | - | ||
111 | - | func assetFarmingPower (address,asset) = (((("address_" + address) + "_asset_") + asset) + "_farmingPower") | |
112 | - | ||
113 | - | ||
114 | - | func rewardClaimedKey (address,asset) = (((address + "_asset_") + asset) + "_claimed") | |
115 | - | ||
116 | - | ||
117 | - | func totalStakedUserKey (address) = ("total_staked_" + address) | |
93 | + | func getNewFarmingAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_farmingNew()))) | |
118 | 94 | ||
119 | 95 | ||
120 | 96 | let RefererReward = 5 | |
121 | 97 | ||
122 | 98 | func checkAdditionalPayment (payment) = if (isDefined(payment.assetId)) | |
123 | 99 | then throw("FCAP: Please attach waves") | |
124 | 100 | else { | |
125 | 101 | let feeAmount = getIntegerValue(getOracle(), staticKey_extraFee()) | |
126 | 102 | if ((payment.amount != feeAmount)) | |
127 | 103 | then throw((("FCAP: Please attach exactly " + toString(feeAmount)) + " amount of wavelets")) | |
128 | 104 | else [ScriptTransfer(getFeeAggregator(), feeAmount, unit)] | |
129 | 105 | } | |
130 | 106 | ||
131 | 107 | ||
108 | + | func getRewardPerBlock () = 0 | |
109 | + | ||
110 | + | ||
111 | + | func isLocked () = if ((getMaintenance() != "")) | |
112 | + | then throw(getMaintenance()) | |
113 | + | else 0 | |
114 | + | ||
115 | + | ||
132 | 116 | func tryGetInteger (key) = match getInteger(this, key) { | |
133 | 117 | case b: Int => | |
134 | 118 | b | |
135 | 119 | case _ => | |
136 | 120 | 0 | |
137 | - | } | |
138 | - | ||
139 | - | ||
140 | - | func asInt (value) = match value { | |
141 | - | case int: Int => | |
142 | - | int | |
143 | - | case _ => | |
144 | - | throw("FAI: wrong type, expected: Int") | |
145 | - | } | |
146 | - | ||
147 | - | ||
148 | - | func asIntTuple (value) = match value { | |
149 | - | case int: (Int, Int) => | |
150 | - | int | |
151 | - | case _ => | |
152 | - | throw("FAI: wrong type, expected: (Int,Int)") | |
153 | - | } | |
154 | - | ||
155 | - | ||
156 | - | func handleStakingTopUp (amount) = { | |
157 | - | let currentInterest = tryGetInteger(keyGlobalLastInterest) | |
158 | - | let totalStakedAmount = tryGetInteger(totalStakedKey()) | |
159 | - | let interestDelta = if ((totalStakedAmount > 0)) | |
160 | - | then fraction(amount, Scale, totalStakedAmount) | |
161 | - | else 0 | |
162 | - | [IntegerEntry(keyGlobalEarned, (tryGetInteger(keyGlobalEarned) + amount)), IntegerEntry(keyGlobalLastInterest, (currentInterest + interestDelta))] | |
163 | - | } | |
164 | - | ||
165 | - | ||
166 | - | func asString (value) = match value { | |
167 | - | case string: String => | |
168 | - | string | |
169 | - | case _ => | |
170 | - | throw("FAS: wrong type, expected: String") | |
171 | 121 | } | |
172 | 122 | ||
173 | 123 | ||
174 | 124 | func tryGetBoolean (key) = match getBoolean(this, key) { | |
175 | 125 | case b: Boolean => | |
176 | 126 | b | |
177 | 127 | case _ => | |
178 | 128 | false | |
179 | 129 | } | |
180 | 130 | ||
181 | 131 | ||
182 | 132 | func tryGetBooleanExternal (address,key) = match getBoolean(address, key) { | |
183 | 133 | case b: Boolean => | |
184 | 134 | b | |
185 | 135 | case _ => | |
186 | 136 | false | |
187 | 137 | } | |
188 | 138 | ||
189 | 139 | ||
190 | 140 | func getAssetOrigin (generation) = if ((generation == "G")) | |
191 | 141 | then getIncubatorAddress() | |
192 | 142 | else getBreederAddress() | |
193 | 143 | ||
194 | 144 | ||
195 | 145 | func getAssetRarity (genotype,generation) = { | |
196 | 146 | let quantity = valueOrErrorMessage(getInteger(getAssetOrigin(generation), (("stats_" + genotype) + "_quantity")), (("stats_" + genotype) + "_quantity not found")) | |
197 | 147 | let power = pow((10000 / quantity), 4, 5, 1, 2, FLOOR) | |
198 | 148 | if ((power > 0)) | |
199 | 149 | then power | |
200 | 150 | else 2 | |
201 | 151 | } | |
202 | 152 | ||
203 | 153 | ||
204 | - | func getAssetRarityComplete (isJackpot,assetName) = { | |
205 | - | let rarity = if (isJackpot) | |
206 | - | then 100 | |
207 | - | else { | |
208 | - | let generation = take(takeRight(assetName, 2), 1) | |
209 | - | let farmGen = asString(invoke(getBreederAddress(), "getGenFromName", [assetName], nil)) | |
210 | - | if ((farmGen == farmGen)) | |
211 | - | then getAssetRarity(farmGen, generation) | |
212 | - | else throw("Strict value is not equal to itself.") | |
213 | - | } | |
214 | - | rarity | |
215 | - | } | |
154 | + | func asString (value) = match value { | |
155 | + | case string: String => | |
156 | + | string | |
157 | + | case _ => | |
158 | + | throw("FAS: wrong type, expected: String") | |
159 | + | } | |
216 | 160 | ||
217 | 161 | ||
218 | - | func updateFarmingPower (address,asset) = { | |
219 | - | let totalStaked = tryGetInteger(totalStakedKey()) | |
220 | - | let totalStakedUser = tryGetInteger(totalStakedUserKey(address)) | |
221 | - | let currentFP = tryGetInteger(assetFarmingPower(address, asset)) | |
222 | - | let newFP = asIntTuple(invoke(this, "calculateFarmPower", [asset], nil)) | |
223 | - | if ((currentFP != 0)) | |
224 | - | then [IntegerEntry(totalStakedKey(), ((totalStaked - currentFP) + newFP._1)), IntegerEntry(totalStakedUserKey(address), ((totalStakedUser - currentFP) + newFP._1)), IntegerEntry(assetFarmingPower(address, asset), newFP._1), IntegerEntry("DEBUG_currentFP", currentFP), IntegerEntry("DEBUG_newFP", newFP._1)] | |
225 | - | else nil | |
226 | - | } | |
227 | - | ||
228 | - | ||
229 | - | func claimStakingResult (address,asset,recalc) = { | |
230 | - | let currentInterest = tryGetInteger(keyGlobalLastInterest) | |
231 | - | let lastCheckInterest = tryGetInteger(keyLastCheckInterest(address, asset)) | |
232 | - | let stakedAmount = tryGetInteger(assetFarmingPower(address, asset)) | |
233 | - | let fpUpdate = if (recalc) | |
234 | - | then updateFarmingPower(address, asset) | |
235 | - | else nil | |
236 | - | if ((fpUpdate == fpUpdate)) | |
237 | - | then { | |
238 | - | let reward = if ((lastCheckInterest > 0)) | |
239 | - | then fraction((currentInterest - lastCheckInterest), stakedAmount, Scale) | |
240 | - | else 0 | |
241 | - | $Tuple2(([ScriptTransfer(Address(fromBase58String(address)), reward, getEggAssetId()), IntegerEntry(keyLastCheckInterest(address, asset), currentInterest), IntegerEntry(rewardClaimedKey(address, asset), (tryGetInteger(rewardClaimedKey(address, asset)) + reward))] ++ fpUpdate), reward) | |
242 | - | } | |
243 | - | else throw("Strict value is not equal to itself.") | |
244 | - | } | |
162 | + | func asInt (value) = match value { | |
163 | + | case int: Int => | |
164 | + | int | |
165 | + | case _ => | |
166 | + | throw("FAI: wrong type, expected: Int") | |
167 | + | } | |
245 | 168 | ||
246 | 169 | ||
247 | 170 | func asBoolean (value) = match value { | |
248 | 171 | case boolean: Boolean => | |
249 | 172 | boolean | |
250 | 173 | case _ => | |
251 | 174 | throw("FAB: wrong type, expected: Boolean") | |
252 | 175 | } | |
253 | 176 | ||
254 | 177 | ||
178 | + | func getAssetFarmingPower (assetId,address) = if (if ((value(assetInfo(assetId)).issuer == getBreederAddress())) | |
179 | + | then true | |
180 | + | else (value(assetInfo(assetId)).issuer == getIncubatorAddress())) | |
181 | + | then { | |
182 | + | let farmBoost = asInt(invoke(getItemsAddress(), "calculateFarmingPowerBoost", [toBase58String(assetId), address], nil)) | |
183 | + | if ((farmBoost == farmBoost)) | |
184 | + | then { | |
185 | + | let assetName = value(assetInfo(assetId)).name | |
186 | + | let isJackpot = (takeRight(value(assetName), 1) == "U") | |
187 | + | let farmGen = if (isJackpot) | |
188 | + | then "" | |
189 | + | else asString(invoke(getBreederAddress(), "getGenFromName", [assetName], nil)) | |
190 | + | if ((farmGen == farmGen)) | |
191 | + | then { | |
192 | + | let rarity = if (isJackpot) | |
193 | + | then 100 | |
194 | + | else { | |
195 | + | let generation = take(takeRight(assetName, 2), 1) | |
196 | + | getAssetRarity(farmGen, generation) | |
197 | + | } | |
198 | + | let totalFarmingPower = (rarity + fraction(rarity, farmBoost, 100)) | |
199 | + | $Tuple2(farmGen, totalFarmingPower) | |
200 | + | } | |
201 | + | else throw("Strict value is not equal to itself.") | |
202 | + | } | |
203 | + | else throw("Strict value is not equal to itself.") | |
204 | + | } | |
205 | + | else throw("not valid NFT") | |
206 | + | ||
207 | + | ||
208 | + | func getLastKnownAssetFarmingPower (address,assetId) = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_farmingPower")) | |
209 | + | ||
210 | + | ||
211 | + | func calcInterest (previousInterest,previousInterestHeight,totalFarmingPower) = (previousInterest + (((scale * getRewardPerBlock()) * (height - previousInterestHeight)) / totalFarmingPower)) | |
212 | + | ||
213 | + | ||
214 | + | func getCurrentInterest () = if ((tryGetInteger("total_farmingPower") > 0)) | |
215 | + | then { | |
216 | + | let previousInterest = tryGetInteger("total_lastCheckInterest") | |
217 | + | let previousInterestHeight = tryGetInteger("total_lastCheckInterestHeight") | |
218 | + | let totalFarmingPower = tryGetInteger("total_farmingPower") | |
219 | + | calcInterest(previousInterest, previousInterestHeight, totalFarmingPower) | |
220 | + | } | |
221 | + | else if ((tryGetInteger("total_startHeight") != 0)) | |
222 | + | then tryGetInteger("total_lastCheckInterest") | |
223 | + | else throw("farming is not launched, yet") | |
224 | + | ||
225 | + | ||
226 | + | func calcAssetRewardDelta (address,assetId,assetFarmingPower) = { | |
227 | + | let lastCheckAssetInterest = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_lastCheckInterest")) | |
228 | + | let currentInterest = getCurrentInterest() | |
229 | + | (assetFarmingPower * (currentInterest - lastCheckAssetInterest)) | |
230 | + | } | |
231 | + | ||
232 | + | ||
233 | + | func addAssetIdToGenEntry (assetId,assetGen) = { | |
234 | + | let currentValue = tryGetString((("assets_" + assetGen) + "_locked")) | |
235 | + | if ((currentValue == "")) | |
236 | + | then assetId | |
237 | + | else ((currentValue + ",") + assetId) | |
238 | + | } | |
239 | + | ||
240 | + | ||
241 | + | func getStakeResult (address,assetId,assetFarmingPower,unstaker) = { | |
242 | + | let asset = toBase58String(assetId) | |
243 | + | [IntegerEntry("total_farmingPower", (tryGetInteger("total_farmingPower") + assetFarmingPower)), IntegerEntry("total_lastCheckInterest", getCurrentInterest()), IntegerEntry("total_lastCheckInterestHeight", height), StringEntry((("asset_" + asset) + "_owner"), address), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_farmingPower"), assetFarmingPower), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest"), getCurrentInterest()), StringEntry((((("address_" + address) + "_asset_") + asset) + "_unstaker"), unstaker)] | |
244 | + | } | |
245 | + | ||
246 | + | ||
247 | + | func getUnstakeResult (address,assetId,color,caller,realCaller,claimEggs) = { | |
248 | + | let locked = isLocked() | |
249 | + | if ((locked == locked)) | |
250 | + | then { | |
251 | + | let asset = toBase58String(assetId) | |
252 | + | let unstaker = tryGetString((((("address_" + address) + "_asset_") + asset) + "_unstaker")) | |
253 | + | if (if ((unstaker != "")) | |
254 | + | then (unstaker != realCaller) | |
255 | + | else false) | |
256 | + | then throw("FUN: It seems duck was staked throuh a dapp, not directly, please unstake through dapp!") | |
257 | + | else { | |
258 | + | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
259 | + | if (!((assetFarmingPower > 0))) | |
260 | + | then throw("FGU: Asset farming power not bigger then 0") | |
261 | + | else { | |
262 | + | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
263 | + | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
264 | + | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
265 | + | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
266 | + | let isWithoutPerch = tryGetBoolean((((("address_" + address) + "_asset_") + asset) + "_without_perch")) | |
267 | + | let rewardAfterSickNess = reward | |
268 | + | let appendPerches = if (isWithoutPerch) | |
269 | + | then [DeleteEntry((((("address_" + address) + "_asset_") + asset) + "_without_perch"))] | |
270 | + | else [IntegerEntry(((("address_" + address) + "_perchesAvailable_") + color), (tryGetInteger(((("address_" + address) + "_perchesAvailable_") + color)) + 1))] | |
271 | + | let sendTx = if (claimEggs) | |
272 | + | then $Tuple2([ScriptTransfer(caller, (rewardAfterSickNess * 1000000), getEggAssetId())], (rewardAfterSickNess * 1000000)) | |
273 | + | else $Tuple2(nil, 0) | |
274 | + | $Tuple2(((([IntegerEntry("total_farmingPower", (tryGetInteger("total_farmingPower") - assetFarmingPower)), IntegerEntry("total_lastCheckInterest", getCurrentInterest()), IntegerEntry("total_lastCheckInterestHeight", height), DeleteEntry((("asset_" + asset) + "_owner")), DeleteEntry((((("address_" + address) + "_asset_") + asset) + "_unstaker")), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_farmingPower"), 0), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest"), getCurrentInterest()), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount"), (withdrawnAmount + (rewardAfterSickNess * scale2))), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"), (tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount")) + assetRewardDelta))] ++ appendPerches) ++ [ScriptTransfer(caller, 1, assetId)]) ++ sendTx._1), sendTx._2) | |
275 | + | } | |
276 | + | } | |
277 | + | } | |
278 | + | else throw("Strict value is not equal to itself.") | |
279 | + | } | |
280 | + | ||
281 | + | ||
255 | 282 | func calculatePerchPrice (address) = { | |
256 | 283 | let hasArtefactStaked = tryGetStringExternal(getAccBoosterAddress(), (("ART-XMISTL_" + address) + "_owner")) | |
257 | - | let perchPrice = getIntegerValue(getOracle(), staticKey_perchFee()) | |
258 | 284 | if ((hasArtefactStaked == "")) | |
259 | 285 | then perchPrice | |
260 | 286 | else ((perchPrice / 10) * 9) | |
261 | 287 | } | |
262 | 288 | ||
263 | 289 | ||
264 | 290 | func isProxyStakingSc (address) = { | |
265 | 291 | let allowedContracts = getProxyStaking() | |
266 | 292 | let allowedContractsList = split(allowedContracts, ";") | |
267 | 293 | (indexOf(allowedContractsList, address) != unit) | |
268 | 294 | } | |
269 | 295 | ||
270 | 296 | ||
297 | + | func unstakeNFTInternal (asset,i,claimEgg) = { | |
298 | + | let assetId = fromBase58String(asset) | |
299 | + | let realCaller = toString(i.caller) | |
300 | + | let address = if (isProxyStakingSc(toString(i.caller))) | |
301 | + | then toString(i.originCaller) | |
302 | + | else realCaller | |
303 | + | let color = takeRight(value(assetInfo(assetId)).name, 1) | |
304 | + | if ((color == "U")) | |
305 | + | then throw("FUN: use another function to unstake Jackpot NFT") | |
306 | + | else { | |
307 | + | let result = getUnstakeResult(address, assetId, color, i.caller, realCaller, claimEgg) | |
308 | + | result | |
309 | + | } | |
310 | + | } | |
311 | + | ||
312 | + | ||
313 | + | func unstakeJackpotInternal (asset,i,claimEgg) = { | |
314 | + | let assetId = fromBase58String(asset) | |
315 | + | let realCaller = toString(i.caller) | |
316 | + | let address = if (isProxyStakingSc(toString(i.caller))) | |
317 | + | then toString(i.originCaller) | |
318 | + | else realCaller | |
319 | + | let color = tryGetString((((("address_" + address) + "_asset_") + asset) + "_perchColor")) | |
320 | + | if ((takeRight(value(value(assetInfo(assetId)).name), 1) != "U")) | |
321 | + | then throw("jackpot only") | |
322 | + | else { | |
323 | + | let result = getUnstakeResult(address, assetId, color, i.caller, realCaller, claimEgg) | |
324 | + | result | |
325 | + | } | |
326 | + | } | |
327 | + | ||
328 | + | ||
329 | + | func getBool (key) = match getBoolean(this, key) { | |
330 | + | case b: Boolean => | |
331 | + | b | |
332 | + | case _ => | |
333 | + | false | |
334 | + | } | |
335 | + | ||
336 | + | ||
337 | + | func isTestEnv () = getBool("TESTENV") | |
338 | + | ||
339 | + | ||
271 | 340 | @Callable(i) | |
272 | - | func calculateFarmPower (assetId) = if (!(if ((value(assetInfo(fromBase58String(assetId))).issuer == getBreederAddress())) | |
273 | - | then true | |
274 | - | else (value(assetInfo(fromBase58String(assetId))).issuer == getIncubatorAddress()))) | |
275 | - | then throw("This does not seem like a valid Duck!") | |
276 | - | else { | |
277 | - | let assetName = value(assetInfo(fromBase58String(assetId))).name | |
278 | - | let gen = takeRight(assetName, 1) | |
279 | - | let isJackpot = (takeRight(assetName, 1) == "U") | |
280 | - | let rarity = getAssetRarityComplete(isJackpot, assetName) | |
281 | - | let genotype = split(dropRight(drop(assetName, 5), 3), "") | |
282 | - | func uniqueArrayFilter (accum,nextGen) = if (!(containsElement(accum, nextGen))) | |
283 | - | then (accum :+ nextGen) | |
284 | - | else accum | |
285 | - | ||
286 | - | let uniqueList = { | |
287 | - | let $l = genotype | |
288 | - | let $s = size($l) | |
289 | - | let $acc0 = nil | |
290 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
291 | - | then $a | |
292 | - | else uniqueArrayFilter($a, $l[$i]) | |
293 | - | ||
294 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
295 | - | then $a | |
296 | - | else throw("List size exceeds 8") | |
297 | - | ||
298 | - | $f0_2($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) | |
299 | - | } | |
300 | - | let totalGenes = if ((gen == "U")) | |
301 | - | then 8 | |
302 | - | else size(uniqueList) | |
303 | - | let power = pow(15, 1, totalGenes, 0, 2, DOWN) | |
304 | - | let multiplier = (((height - 3750000) * 100) / (((60 * 24) * 30) * 3)) | |
305 | - | let basePower = tryGetInteger((assetId + "_basePower")) | |
306 | - | let finalPower = if ((basePower > 0)) | |
307 | - | then basePower | |
308 | - | else ((power * multiplier) / 100) | |
309 | - | let finalPowerRarity = ((finalPower * rarity) / 100) | |
310 | - | let farmBoost = asInt(invoke(getItemsAddress(), "calculateFarmingPowerBoost", [assetId, toString(i.originCaller)], nil)) | |
311 | - | if ((farmBoost == farmBoost)) | |
312 | - | then { | |
313 | - | let finalPowerRarityBoost = (finalPowerRarity + ((finalPowerRarity * farmBoost) / 100)) | |
314 | - | $Tuple2([IntegerEntry(("DEBUG_" + assetName), finalPower), IntegerEntry(("DEBUG_RARITY" + assetName), rarity), IntegerEntry(("DEBUG_FPRARITY_" + assetName), finalPowerRarity), IntegerEntry(("DEBUG_FARMBOOST_" + assetName), farmBoost), IntegerEntry(("DEBUG_FPRARITYBOOST_" + assetName), finalPowerRarityBoost), IntegerEntry(("DEBUG_POWER_" + assetName), power), IntegerEntry(("DEBUG_BASEPOWER_" + assetName), basePower), IntegerEntry(("DEBUG_COEFFICIENT_" + assetName), multiplier), IntegerEntry(("DEBUG_BOOST_" + assetName), farmBoost)], $Tuple2(finalPowerRarityBoost, finalPower)) | |
315 | - | } | |
316 | - | else throw("Strict value is not equal to itself.") | |
317 | - | } | |
341 | + | func removePerches (address) = if ((i.caller != getNewFarmingAddress())) | |
342 | + | then throw("FRP: admin only") | |
343 | + | else [IntegerEntry((("address_" + address) + "_perchesAvailable_R"), 0), IntegerEntry((("address_" + address) + "_perchesAvailable_G"), 0), IntegerEntry((("address_" + address) + "_perchesAvailable_B"), 0), IntegerEntry((("address_" + address) + "_perchesAvailable_U"), 0)] | |
318 | 344 | ||
319 | 345 | ||
320 | 346 | ||
321 | 347 | @Callable(i) | |
322 | 348 | func configureOracle (oracle) = if ((i.caller != this)) | |
323 | 349 | then throw("FCO: admin only") | |
324 | 350 | else [StringEntry(staticKey_oracleAddress(), oracle)] | |
325 | 351 | ||
326 | 352 | ||
327 | 353 | ||
328 | 354 | @Callable(i) | |
329 | - | func buyPerch (colorI,refererAddress) = { | |
330 | - | let validPayment = checkAdditionalPayment(i.payments[0]) | |
355 | + | func init () = if ((i.caller != this)) | |
356 | + | then throw("FI: admin only") | |
357 | + | else [IntegerEntry("total_startHeight", height)] | |
358 | + | ||
359 | + | ||
360 | + | ||
361 | + | @Callable(i) | |
362 | + | func buyPerch (colorI,refererAddress) = throw("FBN: function is disabled, migration to new sc ongoing") | |
363 | + | ||
364 | + | ||
365 | + | ||
366 | + | @Callable(i) | |
367 | + | func addFreePerch (address,color) = throw("FBN: function is disabled, migration to new sc ongoing") | |
368 | + | ||
369 | + | ||
370 | + | ||
371 | + | @Callable(i) | |
372 | + | func stakeNFT () = throw("FBN: function is disabled, migration to new sc ongoing") | |
373 | + | ||
374 | + | ||
375 | + | ||
376 | + | @Callable(i) | |
377 | + | func stakeNFTWithoutPerch () = throw("FBN: function is disabled, migration to new sc ongoing") | |
378 | + | ||
379 | + | ||
380 | + | ||
381 | + | @Callable(i) | |
382 | + | func unstakeNFT (asset) = { | |
383 | + | let validPayment = if ((i.caller == getMetaraceAddress())) | |
384 | + | then nil | |
385 | + | else checkAdditionalPayment(i.payments[0]) | |
331 | 386 | if ((validPayment == validPayment)) | |
332 | 387 | then { | |
333 | - | let color = if ((colorI == "U")) | |
334 | - | then "B" | |
335 | - | else colorI | |
336 | - | if ((0 > value(indexOf(["B", "R", "G", "Y"], color)))) | |
337 | - | then throw("you need to set color properly") | |
338 | - | else { | |
339 | - | let exactPrice = calculatePerchPrice(toString(i.caller)) | |
340 | - | let leftToPay = if ((i.originCaller == i.caller)) | |
341 | - | then { | |
342 | - | let amountPaidByCoupons = asInt(invoke(getCouponsAddress(), "useCoupons", [exactPrice], nil)) | |
343 | - | if ((amountPaidByCoupons == amountPaidByCoupons)) | |
344 | - | then (exactPrice - amountPaidByCoupons) | |
345 | - | else throw("Strict value is not equal to itself.") | |
346 | - | } | |
347 | - | else exactPrice | |
348 | - | let firstPayment = if ((size(i.payments) == 2)) | |
349 | - | then value(i.payments[1]) | |
350 | - | else value(i.payments[0]) | |
351 | - | if ((firstPayment.assetId != getEggAssetId())) | |
352 | - | then throw(("FBP: You can attach only EGG tokens with the following asset id: " + toBase58String(getEggAssetId()))) | |
353 | - | else if ((firstPayment.amount != leftToPay)) | |
354 | - | then throw(((("FBP: To buy a perch you currently need the following amount of EGGlets: " + toString(leftToPay)) + " ") + toString(i.caller))) | |
355 | - | else { | |
356 | - | let refererRewardForPerch = fraction(leftToPay, 5, 100) | |
357 | - | let refCall = asBoolean(invoke(getRefContractAddress(), "refPayment", [refererAddress], [AttachedPayment(getEggAssetId(), refererRewardForPerch)])) | |
358 | - | if ((refCall == refCall)) | |
359 | - | then { | |
360 | - | let toBurn = if (refCall) | |
361 | - | then (leftToPay - refererRewardForPerch) | |
362 | - | else leftToPay | |
363 | - | let burnCall = invoke(getBurnAddress(), "burnAttachedPayments", nil, [AttachedPayment(getEggAssetId(), toBurn)]) | |
364 | - | if ((burnCall == burnCall)) | |
365 | - | then { | |
366 | - | let perchAmountKey = ((("address_" + toString(i.caller)) + "_perchesAvailable_") + color) | |
367 | - | let perchAmount = tryGetInteger(perchAmountKey) | |
368 | - | ([IntegerEntry(perchAmountKey, (perchAmount + 1))] ++ validPayment) | |
369 | - | } | |
370 | - | else throw("Strict value is not equal to itself.") | |
371 | - | } | |
372 | - | else throw("Strict value is not equal to itself.") | |
373 | - | } | |
374 | - | } | |
388 | + | let result = unstakeNFTInternal(asset, i, true) | |
389 | + | $Tuple2((result._1 ++ validPayment), result._2) | |
375 | 390 | } | |
376 | 391 | else throw("Strict value is not equal to itself.") | |
377 | 392 | } | |
378 | 393 | ||
379 | 394 | ||
380 | 395 | ||
381 | 396 | @Callable(i) | |
382 | - | func addFreePerch (address,color,amount) = if ((0 > value(indexOf(["B", "R", "G", "Y"], color)))) | |
383 | - | then throw("you need to set color properly") | |
384 | - | else if (if (if ((i.caller != getRebirthAddress())) | |
385 | - | then (i.caller != getTurtleRebirthAddress()) | |
386 | - | else false) | |
387 | - | then (i.caller != this) | |
388 | - | else false) | |
389 | - | then throw("rebirth and admin only") | |
390 | - | else { | |
391 | - | let perchAmountKey = ((("address_" + address) + "_perchesAvailable_") + color) | |
392 | - | let perchAmount = tryGetInteger(perchAmountKey) | |
393 | - | $Tuple2([IntegerEntry(perchAmountKey, (perchAmount + amount))], "") | |
394 | - | } | |
397 | + | func unstakeNFTWithoutClaim (asset) = unstakeNFTInternal(asset, i, false) | |
395 | 398 | ||
396 | 399 | ||
397 | 400 | ||
398 | 401 | @Callable(i) | |
399 | - | func migratePerches (address) = { | |
400 | - | let oldFarming = addressFromStringValue(tryGetStringExternal(getOracle(), "static_farmingAddress")) | |
401 | - | func tryGetIntegerOldFarming (key) = match getInteger(oldFarming, key) { | |
402 | - | case b: Int => | |
403 | - | b | |
404 | - | case _ => | |
405 | - | 0 | |
406 | - | } | |
407 | - | ||
408 | - | let perchAmountB = tryGetIntegerOldFarming((("address_" + address) + "_perchesAvailable_B")) | |
409 | - | let perchAmountR = tryGetIntegerOldFarming((("address_" + address) + "_perchesAvailable_R")) | |
410 | - | let perchAmountG = tryGetIntegerOldFarming((("address_" + address) + "_perchesAvailable_G")) | |
411 | - | let perchAmountY = tryGetIntegerOldFarming((("address_" + address) + "_perchesAvailable_Y")) | |
412 | - | let perchAmountBInvoke = invoke(this, "addFreePerch", [address, "B", perchAmountB], nil) | |
413 | - | let perchAmountRInvoke = invoke(this, "addFreePerch", [address, "R", perchAmountR], nil) | |
414 | - | let perchAmountGInvoke = invoke(this, "addFreePerch", [address, "G", perchAmountG], nil) | |
415 | - | let perchAmountYInvoke = invoke(this, "addFreePerch", [address, "Y", perchAmountY], nil) | |
416 | - | let invokePerchesDelete = invoke(oldFarming, "removePerches", [address], nil) | |
417 | - | nil | |
418 | - | } | |
402 | + | func stakeJackpot (color) = throw("FBN: function is disabled, migration to new sc ongoing") | |
419 | 403 | ||
420 | 404 | ||
421 | 405 | ||
422 | 406 | @Callable(i) | |
423 | - | func stakeNFT (jColor,usePerchOrigin,stakeWithoutPerch) = if (true) | |
424 | - | then throw("Staking is disabled") | |
425 | - | else if (if (stakeWithoutPerch) | |
426 | - | then !(isProxyStakingSc(toString(i.caller))) | |
427 | - | else false) | |
428 | - | then throw("You can't stake without a perch") | |
429 | - | else { | |
430 | - | let validPayment = checkAdditionalPayment(i.payments[0]) | |
431 | - | if ((validPayment == validPayment)) | |
432 | - | then { | |
433 | - | let pmt = value(i.payments[1]) | |
434 | - | let assetId = value(pmt.assetId) | |
435 | - | let assetName = value(value(assetInfo(assetId)).name) | |
436 | - | let isJackpot = (takeRight(assetName, 1) == "U") | |
437 | - | let address = toString(i.caller) | |
438 | - | let perchAddress = if (usePerchOrigin) | |
439 | - | then toString(i.originCaller) | |
440 | - | else address | |
441 | - | let rarity = getAssetRarityComplete(isJackpot, assetName) | |
442 | - | let perches = if (stakeWithoutPerch) | |
443 | - | then nil | |
444 | - | else { | |
445 | - | let color = if (isJackpot) | |
446 | - | then jColor | |
447 | - | else takeRight(assetName, 1) | |
448 | - | let availablePerches = tryGetInteger(((("address_" + perchAddress) + "_perchesAvailable_") + color)) | |
449 | - | if ((0 >= availablePerches)) | |
450 | - | then throw(("no perches available for the color " + color)) | |
451 | - | else [IntegerEntry(((("address_" + perchAddress) + "_perchesAvailable_") + color), (availablePerches - 1)), StringEntry((((("address_" + address) + "_asset_") + toBase58String(assetId)) + "_perchColor"), color)] | |
452 | - | } | |
453 | - | if ((perches == perches)) | |
454 | - | then if ((pmt.amount != 1)) | |
455 | - | then throw("NFT is not attached") | |
456 | - | else { | |
457 | - | let farmingPower = asIntTuple(invoke(this, "calculateFarmPower", [toBase58String(assetId)], nil)) | |
458 | - | if ((farmingPower == farmingPower)) | |
459 | - | then { | |
460 | - | let result = claimStakingResult(address, toBase58String(assetId), false) | |
461 | - | if ((result == result)) | |
462 | - | then ((([IntegerEntry(totalStakedKey(), (tryGetInteger(totalStakedKey()) + farmingPower._1)), IntegerEntry(totalStakedUserKey(address), (tryGetInteger(totalStakedUserKey(address)) + farmingPower._1)), StringEntry((toBase58String(assetId) + "_owner"), address), BooleanEntry((toBase58String(assetId) + "_use_origin"), usePerchOrigin), StringEntry((toBase58String(assetId) + "_original_caller"), toString(i.originCaller)), IntegerEntry(assetFarmingPower(address, toBase58String(assetId)), farmingPower._1), IntegerEntry((toBase58String(assetId) + "_basePower"), farmingPower._2), BooleanEntry((toBase58String(assetId) + "_without_perch"), stakeWithoutPerch)] ++ validPayment) ++ perches) ++ result._1) | |
463 | - | else throw("Strict value is not equal to itself.") | |
464 | - | } | |
465 | - | else throw("Strict value is not equal to itself.") | |
466 | - | } | |
467 | - | else throw("Strict value is not equal to itself.") | |
468 | - | } | |
469 | - | else throw("Strict value is not equal to itself.") | |
470 | - | } | |
471 | - | ||
472 | - | ||
473 | - | ||
474 | - | @Callable(i) | |
475 | - | func unstakeNFT (asset) = { | |
476 | - | let address = toString(i.caller) | |
477 | - | let result = claimStakingResult(address, asset, false) | |
478 | - | if ((result == result)) | |
407 | + | func unstakeJackpot (asset) = { | |
408 | + | let validPayment = checkAdditionalPayment(i.payments[0]) | |
409 | + | if ((validPayment == validPayment)) | |
479 | 410 | then { | |
480 | - | let validPayment = checkAdditionalPayment(i.payments[0]) | |
481 | - | if ((validPayment == validPayment)) | |
482 | - | then { | |
483 | - | let color = tryGetString((((("address_" + address) + "_asset_") + asset) + "_perchColor")) | |
484 | - | let withoutPerch = tryGetBoolean((asset + "_without_perch")) | |
485 | - | let perches = if (withoutPerch) | |
486 | - | then nil | |
487 | - | else { | |
488 | - | let usePerchOrigin = tryGetBoolean((asset + "_use_origin")) | |
489 | - | let perchOwner = if (usePerchOrigin) | |
490 | - | then toString(i.originCaller) | |
491 | - | else address | |
492 | - | [IntegerEntry(((("address_" + address) + "_perchesAvailable_") + color), (tryGetInteger(((("address_" + address) + "_perchesAvailable_") + color)) + 1))] | |
493 | - | } | |
494 | - | if ((perches == perches)) | |
495 | - | then { | |
496 | - | let assetFP = tryGetInteger(assetFarmingPower(address, asset)) | |
497 | - | if ((assetFP == assetFP)) | |
498 | - | then $Tuple2(((([IntegerEntry(totalStakedKey(), (tryGetInteger(totalStakedKey()) - assetFP)), IntegerEntry(totalStakedUserKey(address), (tryGetInteger(totalStakedUserKey(address)) - assetFP)), DeleteEntry((asset + "_owner")), DeleteEntry(assetFarmingPower(address, asset)), DeleteEntry((((("address_" + address) + "_asset_") + asset) + "_perchColor")), DeleteEntry((asset + "_original_caller")), DeleteEntry((asset + "_use_origin")), DeleteEntry((asset + "_without_perch")), ScriptTransfer(Address(fromBase58String(address)), 1, fromBase58String(asset))] ++ validPayment) ++ perches) ++ result._1), result._2) | |
499 | - | else throw("Strict value is not equal to itself.") | |
500 | - | } | |
501 | - | else throw("Strict value is not equal to itself.") | |
502 | - | } | |
503 | - | else throw("Strict value is not equal to itself.") | |
411 | + | let result = unstakeJackpotInternal(asset, i, true) | |
412 | + | $Tuple2((result._1 ++ validPayment), result._2) | |
504 | 413 | } | |
505 | 414 | else throw("Strict value is not equal to itself.") | |
506 | 415 | } | |
507 | 416 | ||
508 | 417 | ||
509 | 418 | ||
510 | 419 | @Callable(i) | |
511 | - | func topUpReward () = { | |
512 | - | let firstPayment = value(i.payments[0]) | |
513 | - | if ((firstPayment.assetId != getEggAssetId())) | |
514 | - | then throw(("FBP: You can attach only EGG tokens with the following asset id: " + toBase58String(getEggAssetId()))) | |
515 | - | else { | |
516 | - | let resHandleStaking = handleStakingTopUp(firstPayment.amount) | |
517 | - | $Tuple2(resHandleStaking, true) | |
518 | - | } | |
519 | - | } | |
420 | + | func unstakeJackpotWithoutClaimEgg (asset) = unstakeJackpotInternal(asset, i, false) | |
520 | 421 | ||
521 | 422 | ||
522 | 423 | ||
523 | 424 | @Callable(i) | |
524 | - | func claimReward (assetId) = { | |
525 | - | let validPayment = checkAdditionalPayment(i.payments[0]) | |
526 | - | if ((validPayment == validPayment)) | |
527 | - | then if ((tryGetString((assetId + "_owner")) != toString(i.caller))) | |
528 | - | then throw("You don't own this duck!!") | |
529 | - | else if ((size(i.payments) > 1)) | |
530 | - | then throw("Please don't add extra payments") | |
531 | - | else { | |
532 | - | let result = claimStakingResult(toString(i.caller), assetId, true) | |
533 | - | $Tuple2((validPayment ++ result._1), result._2) | |
425 | + | func claimReward (asset) = { | |
426 | + | let locked = isLocked() | |
427 | + | if ((locked == locked)) | |
428 | + | then { | |
429 | + | let validPayment = if ((i.originCaller == getCfMasterAddress())) | |
430 | + | then nil | |
431 | + | else checkAdditionalPayment(i.payments[0]) | |
432 | + | if ((validPayment == validPayment)) | |
433 | + | then { | |
434 | + | let address = if ((i.originCaller == getCfMasterAddress())) | |
435 | + | then toString(i.caller) | |
436 | + | else toString(i.originCaller) | |
437 | + | let assetId = fromBase58String(asset) | |
438 | + | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
439 | + | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
440 | + | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
441 | + | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
442 | + | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
443 | + | if ((0 >= reward)) | |
444 | + | then throw("FCR: you have no EGGs to withdraw") | |
445 | + | else $Tuple2(([IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount"), (tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) + (reward * scale2))), ScriptTransfer(Address(fromBase58String(address)), (reward * 1000000), getEggAssetId())] ++ validPayment), (reward * 1000000)) | |
534 | 446 | } | |
447 | + | else throw("Strict value is not equal to itself.") | |
448 | + | } | |
535 | 449 | else throw("Strict value is not equal to itself.") | |
536 | 450 | } | |
537 | 451 | ||
538 | 452 |
github/deemru/w8io/6500d08 103.86 ms ◑