tx · 6vYJqpd2jaTMbX9Je6K8FFHPceyRrGrt3GLUbrg1Ah1Z 3PAETTtuW7aSiyKtn9GuML3RgtV1xdq1mQW: -0.02300000 Waves 2024.04.17 20:18 [4133016] smart account 3PAETTtuW7aSiyKtn9GuML3RgtV1xdq1mQW > SELF 0.00000000 Waves
{ "type": 13, "id": "6vYJqpd2jaTMbX9Je6K8FFHPceyRrGrt3GLUbrg1Ah1Z", "fee": 2300000, "feeAssetId": null, "timestamp": 1713374285049, "version": 2, "chainId": 87, "sender": "3PAETTtuW7aSiyKtn9GuML3RgtV1xdq1mQW", "senderPublicKey": "DSNxHVyf38CbPoz2oSJ1b4FWqRvqFsAphCzdtrPeWPHa", "proofs": [ "2mPTDx2ga39ZywY9GoEuhmn9MhCYfZJU584Hk1wTYAzmv9jnViHiCyVnTvyENTXDzKi8FpaMB3P6qMNxfaRQW9ap" ], "script": "base64:AAIFAAAAAAAAADEIAhIDCgEIEgMKAQgSBAoCCAgSBQoDCAgBEgMKAQgSBQoDCAQEEgMKAQgSABIDCgEIAAAANwAAAAAFU2NhbGUAAAAAAAX14QABAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgAAAAdhZGRyZXNzAAAAA2tleQQAAAAHJG1hdGNoMAkABB0AAAACBQAAAAdhZGRyZXNzBQAAAANrZXkDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABlN0cmluZwQAAAABYQUAAAAHJG1hdGNoMAUAAAABYQIAAAAAAQAAAAx0cnlHZXRTdHJpbmcAAAABAAAAA2tleQkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgUAAAAEdGhpcwUAAAADa2V5AQAAABxzdGF0aWNLZXlfcmVmQ29udHJhY3RBZGRyZXNzAAAAAAIAAAAZc3RhdGljX3JlZkNvbnRyYWN0QWRkcmVzcwAAAAAVa2V5R2xvYmFsTGFzdEludGVyZXN0AgAAABlnbG9iYWxfbGFzdENoZWNrX2ludGVyZXN0AQAAABdzdGF0aWNLZXlfb3JhY2xlQWRkcmVzcwAAAAACAAAAFHN0YXRpY19vcmFjbGVBZGRyZXNzAQAAABRzdGF0aWNLZXlfZWdnQXNzZXRJZAAAAAACAAAAEXN0YXRpY19lZ2dBc3NldElkAQAAABpzdGF0aWNLZXlfaW5jdWJhdG9yQWRkcmVzcwAAAAACAAAAF3N0YXRpY19pbmN1YmF0b3JBZGRyZXNzAQAAABhzdGF0aWNLZXlfYnJlZWRlckFkZHJlc3MAAAAAAgAAABVzdGF0aWNfYnJlZWRlckFkZHJlc3MBAAAAG3N0YXRpY0tleV9hY2NCb29zdGVyQWRkcmVzcwAAAAACAAAAGHN0YXRpY19hY2NCb29zdGVyQWRkcmVzcwEAAAAYc3RhdGljS2V5X2NvdXBvbnNBZGRyZXNzAAAAAAIAAAAVc3RhdGljX2NvdXBvbnNBZGRyZXNzAQAAABVzdGF0aWNLZXlfYnVybkFkZHJlc3MAAAAAAgAAABJzdGF0aWNfYnVybkFkZHJlc3MBAAAAEnN0YXRpY0tleV9leHRyYUZlZQAAAAACAAAAD3N0YXRpY19leHRyYUZlZQEAAAAXc3RhdGljS2V5X2ZlZUFnZ3JlZ2F0b3IAAAAAAgAAABRzdGF0aWNfZmVlQWdncmVnYXRvcgAAAAAPa2V5R2xvYmFsRWFybmVkAgAAAA9nbG9iYWxfZWFybmluZ3MBAAAAEnN0YXRpY0tleV9wZXJjaEZlZQAAAAACAAAAD3N0YXRpY19wZXJjaEZlZQEAAAAYc3RhdGljS2V5X3JlYmlydGhBZGRyZXNzAAAAAAIAAAAVc3RhdGljX3JlYmlydGhBZGRyZXNzAQAAAB5zdGF0aWNLZXlfdHVydGxlUmViaXJ0aEFkZHJlc3MAAAAAAgAAABtzdGF0aWNfdHVydGxlUmViaXJ0aEFkZHJlc3MBAAAAFnN0YXRpY0tleV9pdGVtc0FkZHJlc3MAAAAAAgAAABNzdGF0aWNfaXRlbXNBZGRyZXNzAQAAAA50b3RhbFN0YWtlZEtleQAAAAACAAAADHRvdGFsX3N0YWtlZAEAAAAfc3RhdGljS2V5X3Byb3h5U3Rha2luZ0NvbnRyYWN0cwAAAAACAAAAHHN0YXRpY19wcm94eVN0YWtpbmdDb250cmFjdHMBAAAACWdldE9yYWNsZQAAAAAJAQAAAAdBZGRyZXNzAAAAAQkAAlkAAAABCQEAAAAMdHJ5R2V0U3RyaW5nAAAAAQkBAAAAF3N0YXRpY0tleV9vcmFjbGVBZGRyZXNzAAAAAAEAAAARZ2V0UmViaXJ0aEFkZHJlc3MAAAAACQEAAAAHQWRkcmVzcwAAAAEJAAJZAAAAAQkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgkBAAAACWdldE9yYWNsZQAAAAAJAQAAABhzdGF0aWNLZXlfcmViaXJ0aEFkZHJlc3MAAAAAAQAAAA1nZXRFZ2dBc3NldElkAAAAAAkAAlkAAAABCQEAAAAUdHJ5R2V0U3RyaW5nRXh0ZXJuYWwAAAACCQEAAAAJZ2V0T3JhY2xlAAAAAAkBAAAAFHN0YXRpY0tleV9lZ2dBc3NldElkAAAAAAEAAAATZ2V0SW5jdWJhdG9yQWRkcmVzcwAAAAAJAQAAAAdBZGRyZXNzAAAAAQkAAlkAAAABCQEAAAAUdHJ5R2V0U3RyaW5nRXh0ZXJuYWwAAAACCQEAAAAJZ2V0T3JhY2xlAAAAAAkBAAAAGnN0YXRpY0tleV9pbmN1YmF0b3JBZGRyZXNzAAAAAAEAAAARZ2V0QnJlZWRlckFkZHJlc3MAAAAACQEAAAAHQWRkcmVzcwAAAAEJAAJZAAAAAQkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgkBAAAACWdldE9yYWNsZQAAAAAJAQAAABhzdGF0aWNLZXlfYnJlZWRlckFkZHJlc3MAAAAAAQAAABRnZXRBY2NCb29zdGVyQWRkcmVzcwAAAAAJAQAAAAdBZGRyZXNzAAAAAQkAAlkAAAABCQEAAAAUdHJ5R2V0U3RyaW5nRXh0ZXJuYWwAAAACCQEAAAAJZ2V0T3JhY2xlAAAAAAkBAAAAG3N0YXRpY0tleV9hY2NCb29zdGVyQWRkcmVzcwAAAAABAAAAEWdldENvdXBvbnNBZGRyZXNzAAAAAAkBAAAAB0FkZHJlc3MAAAABCQACWQAAAAEJAQAAABR0cnlHZXRTdHJpbmdFeHRlcm5hbAAAAAIJAQAAAAlnZXRPcmFjbGUAAAAACQEAAAAYc3RhdGljS2V5X2NvdXBvbnNBZGRyZXNzAAAAAAEAAAAOZ2V0QnVybkFkZHJlc3MAAAAACQEAAAAHQWRkcmVzcwAAAAEJAAJZAAAAAQkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgkBAAAACWdldE9yYWNsZQAAAAAJAQAAABVzdGF0aWNLZXlfYnVybkFkZHJlc3MAAAAAAQAAABBnZXRGZWVBZ2dyZWdhdG9yAAAAAAkBAAAAB0FkZHJlc3MAAAABCQACWQAAAAEJAQAAABR0cnlHZXRTdHJpbmdFeHRlcm5hbAAAAAIJAQAAAAlnZXRPcmFjbGUAAAAACQEAAAAXc3RhdGljS2V5X2ZlZUFnZ3JlZ2F0b3IAAAAAAQAAABVnZXRSZWZDb250cmFjdEFkZHJlc3MAAAAACQEAAAAHQWRkcmVzcwAAAAEJAAJZAAAAAQkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgkBAAAACWdldE9yYWNsZQAAAAAJAQAAABxzdGF0aWNLZXlfcmVmQ29udHJhY3RBZGRyZXNzAAAAAAEAAAAXZ2V0VHVydGxlUmViaXJ0aEFkZHJlc3MAAAAACQEAAAAHQWRkcmVzcwAAAAEJAAJZAAAAAQkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgkBAAAACWdldE9yYWNsZQAAAAAJAQAAAB5zdGF0aWNLZXlfdHVydGxlUmViaXJ0aEFkZHJlc3MAAAAAAQAAAA9nZXRJdGVtc0FkZHJlc3MAAAAACQEAAAAHQWRkcmVzcwAAAAEJAAJZAAAAAQkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgkBAAAACWdldE9yYWNsZQAAAAAJAQAAABZzdGF0aWNLZXlfaXRlbXNBZGRyZXNzAAAAAAEAAAAPZ2V0UHJveHlTdGFraW5nAAAAAAkBAAAAFHRyeUdldFN0cmluZ0V4dGVybmFsAAAAAgkBAAAACWdldE9yYWNsZQAAAAAJAQAAAB9zdGF0aWNLZXlfcHJveHlTdGFraW5nQ29udHJhY3RzAAAAAAEAAAAUa2V5TGFzdENoZWNrSW50ZXJlc3QAAAACAAAAB2FkZHJlc3MAAAAFYXNzZXQJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAB19hc3NldF8FAAAABWFzc2V0AgAAABJfbGFzdENoZWNrSW50ZXJlc3QBAAAAEWFzc2V0RmFybWluZ1Bvd2VyAAAAAgAAAAdhZGRyZXNzAAAABWFzc2V0CQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAAAdfYXNzZXRfBQAAAAVhc3NldAIAAAANX2Zhcm1pbmdQb3dlcgEAAAAQcmV3YXJkQ2xhaW1lZEtleQAAAAIAAAAHYWRkcmVzcwAAAAVhc3NldAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgUAAAAHYWRkcmVzcwIAAAAHX2Fzc2V0XwUAAAAFYXNzZXQCAAAACF9jbGFpbWVkAQAAABJ0b3RhbFN0YWtlZFVzZXJLZXkAAAABAAAAB2FkZHJlc3MJAAEsAAAAAgIAAAANdG90YWxfc3Rha2VkXwUAAAAHYWRkcmVzcwAAAAANUmVmZXJlclJld2FyZAAAAAAAAAAABQEAAAAWY2hlY2tBZGRpdGlvbmFsUGF5bWVudAAAAAEAAAAHcGF5bWVudAMJAQAAAAlpc0RlZmluZWQAAAABCAUAAAAHcGF5bWVudAAAAAdhc3Nl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cml0eQEAAAASdXBkYXRlRmFybWluZ1Bvd2VyAAAAAgAAAAdhZGRyZXNzAAAABWFzc2V0BAAAAAt0b3RhbFN0YWtlZAkBAAAADXRyeUdldEludGVnZXIAAAABCQEAAAAOdG90YWxTdGFrZWRLZXkAAAAABAAAAA90b3RhbFN0YWtlZFVzZXIJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQkBAAAAEnRvdGFsU3Rha2VkVXNlcktleQAAAAEFAAAAB2FkZHJlc3MEAAAACWN1cnJlbnRGUAkBAAAADXRyeUdldEludGVnZXIAAAABCQEAAAARYXNzZXRGYXJtaW5nUG93ZXIAAAACBQAAAAdhZGRyZXNzBQAAAAVhc3NldAQAAAAFbmV3RlAJAQAAAAphc0ludFR1cGxlAAAAAQkAA/wAAAAEBQAAAAR0aGlzAgAAABJjYWxjdWxhdGVGYXJtUG93ZXIJAARMAAAAAgUAAAAFYXNzZXQFAAAAA25pbAUAAAADbmlsAwkBAAAAAiE9AAAAAgUAAAAJY3VycmVudEZQAAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAOdG90YWxTdGFrZWRLZXkAAAAACQAAZAAAAAIJAABlAAAAAgUAAAALdG90YWxTdGFrZWQFAAAACWN1cnJlbnRGUAgFAAAABW5ld0ZQAAAAAl8xCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAASdG90YWxTdGFrZWRVc2VyS2V5AAAAAQUAAAAHYWRkcmVzcwkAAGQAAAACCQAAZQAAAAIFAAAAD3RvdGFsU3Rha2VkVXNlcgUAAAAJY3VycmVudEZQCAUAAAAFbmV3RlAAAAACXzEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABFhc3NldEZhcm1pbmdQb3dlcgAAAAIFAAAAB2FkZHJlc3MFAAAABWFzc2V0CAUAAAAFbmV3RlAAAAACXzEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAD0RFQlVHX2N1cnJlbnRGUAUAAAAJY3VycmVudEZQCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAAtERUJVR19uZXdGUAgFAAAABW5ld0ZQAAAAAl8xBQAAAANuaWwFAAAAA25pbAEAAAASY2xhaW1TdGFraW5nUmVzdWx0AAAAAwAAAAdhZGRyZXNzAAAABWFzc2V0AAAABnJlY2FsYwQAAAAPY3VycmVudEludGVyZXN0CQEAAAANdHJ5R2V0SW50ZWdlcgAAAAEFAAAAFWtleUdsb2JhbExhc3RJbnRlcmVzdAQAAAARbGFzdENoZWNrSW50ZXJlc3QJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQkBAAAAFGtleUxhc3RDaGVja0ludGVyZXN0AAAAAgUAAAAHYWRkcmVzcwUAAAAFYXNzZXQEAAAADHN0YWtlZEFtb3VudAkBAAAADXRyeUdldEludGVnZXIAAAABCQEAAAARYXNzZXRGYXJtaW5nUG93ZXIAAAACBQAAAAdhZGRyZXNzBQAAAAVhc3NldAQAAAAIZnBVcGRhdGUDBQAAAAZyZWNhbGMJAQAAABJ1cGRhdGVGYXJtaW5nUG93ZXIAAAACBQAAAAdhZGRyZXNzBQAAAAVhc3NldAUAAAADbmlsAwkAAAAAAAACBQAAAAhmcFVwZGF0ZQUAAAAIZnBVcGRhdGUEAAAABnJld2FyZAMJAABmAAAAAgUAAAARbGFzdENoZWNrSW50ZXJlc3QAAAAAAAAAAAAJAABrAAAAAwkAAGUAAAACBQAAAA9jdXJyZW50SW50ZXJlc3QFAAAAEWxhc3RDaGVja0ludGVyZXN0BQAAAAxzdGFrZWRBbW91bnQFAAAABVNjYWxlAAAAAAAAAAAACQAFFAAAAAIJAAROAAAAAgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCQEAAAAHQWRkcmVzcwAAAAEJAAJZAAAAAQUAAAAHYWRkcmVzcwUAAAAGcmV3YXJkCQEAAAANZ2V0RWdnQXNzZXRJZAAAAAAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABRrZXlMYXN0Q2hlY2tJbnRlcmVzdAAAAAIFAAAAB2FkZHJlc3MFAAAABWFzc2V0BQAAAA9jdXJyZW50SW50ZXJlc3QJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABByZXdhcmRDbGFpbWVkS2V5AAAAAgUAAAAHYWRkcmVzcwUAAAAFYXNzZXQJAABkAAAAAgkBAAAADXRyeUdldEludGVnZXIAAAABCQEAAAAQcmV3YXJkQ2xhaW1lZEtleQAAAAIFAAAAB2FkZHJlc3MFAAAABWFzc2V0BQAAAAZyZXdhcmQFAAAAA25pbAUAAAAIZnBVcGRhdGUFAAAABnJld2FyZAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAAAACWFzQm9vbGVhbgAAAAEAAAAFdmFsdWUEAAAAByRtYXRjaDAFAAAABXZhbHVlAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAdCb29sZWFuBAAAAAdib29sZWFuBQAAAAckbWF0Y2gwBQAAAAdib29sZWFuCQAAAgAAAAECAAAAIkZBQjogd3JvbmcgdHlwZSwgZXhwZWN0ZWQ6IEJvb2xlYW4BAAAAE2NhbGN1bGF0ZVBlcmNoUHJpY2UAAAABAAAAB2FkZHJlc3MEAAAAEWhhc0FydGVmYWN0U3Rha2VkCQEAAAAUdHJ5R2V0U3RyaW5nRXh0ZXJuYWwAAAACCQEAAAAUZ2V0QWNjQm9vc3RlckFkZHJlc3MAAAAACQABLAAAAAIJAAEsAAAAAgIAAAALQVJULVhNSVNUTF8FAAAAB2FkZHJlc3MCAAAABl9vd25lcgQAAAAKcGVyY2hQcmljZQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgkBAAAACWdldE9yYWNsZQAAAAAJAQAAABJzdGF0aWNLZXlfcGVyY2hGZWUAAAAAAwkAAAAAAAACBQAAABFoYXNBcnRlZmFjdFN0YWtlZAIAAAAABQAAAApwZXJjaFByaWNlCQAAaAAAAAIJAABpAAAAAgUAAAAKcGVyY2hQcmljZQAAAAAAAAAACgAAAAAAAAAACQEAAAAQaXNQcm94eVN0YWtpbmdTYwAAAAEAAAAHYWRkcmVzcwQAAAAQYWxsb3dlZENvbnRyYWN0cwkBAAAAD2dldFByb3h5U3Rha2luZwAAAAAEAAAAFGFsbG93ZWRDb250cmFjdHNMaXN0CQAEtQAAAAIFAAAAEGFsbG93ZWRDb250cmFjdHMCAAAAATsJAQAAAAIhPQAAAAIJAARPAAAAAgUAAAAUYWxsb3dlZENvbnRyYWN0c0xpc3QFAAAAB2FkZHJlc3MFAAAABHVuaXQA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cmF0ZVBlcmNoZXMAAAABAAAAB2FkZHJlc3MEAAAACm9sZEZhcm1pbmcJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEJAQAAABR0cnlHZXRTdHJpbmdFeHRlcm5hbAAAAAIJAQAAAAlnZXRPcmFjbGUAAAAAAgAAABVzdGF0aWNfZmFybWluZ0FkZHJlc3MKAQAAABd0cnlHZXRJbnRlZ2VyT2xkRmFybWluZwAAAAEAAAADa2V5BAAAAAckbWF0Y2gwCQAEGgAAAAIFAAAACm9sZEZhcm1pbmcFAAAAA2tleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAFiBQAAAAckbWF0Y2gwBQAAAAFiAAAAAAAAAAAABAAAAAxwZXJjaEFtb3VudEIJAQAAABd0cnlHZXRJbnRlZ2VyT2xkRmFybWluZwAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAATX3BlcmNoZXNBdmFpbGFibGVfQgQAAAAMcGVyY2hBbW91bnRSCQEAAAAXdHJ5R2V0SW50ZWdlck9sZEZhcm1pbmcAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAE19wZXJjaGVzQXZhaWxhYmxlX1IEAAAADHBlcmNoQW1vdW50RwkBAAAAF3RyeUdldEludGVnZXJPbGRGYXJtaW5nAAAAAQkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAABNfcGVyY2hlc0F2YWlsYWJsZV9HBAAAAAxwZXJjaEFtb3VudFkJAQAAABd0cnlHZXRJbnRlZ2VyT2xkRmFybWluZwAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwUAAAAHYWRkcmVzcwIAAAATX3BlcmNoZXNBdmFpbGFibGVfWQQAAAAScGVyY2hBbW91bnRCSW52b2tlCQAD/AAAAAQFAAAABHRoaXMCAAAADGFkZEZyZWVQZXJjaAkABEwAAAACBQAAAAdhZGRyZXNzCQAETAAAAAICAAAAAUIJAARMAAAAAgUAAAAMcGVyY2hBbW91bnRCBQAAAANuaWwFAAAAA25pbAQAAAAScGVyY2hBbW91bnRSSW52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", "height": 4133016, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 2AuCXttd91WxsqvrxXRWLmSX17ymvWagemYTQ7Zcw4H8 Next: B41BtyqVQJRVEVfKnNSqX17thSsfg4kKXLxRUdyymEQd Diff:
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | - | let perchPrice = (100 * 1000000) | |
5 | - | ||
6 | - | let scale = 10000 | |
7 | - | ||
8 | - | let scale2 = 1000000 | |
4 | + | let Scale = 100000000 | |
9 | 5 | ||
10 | 6 | func tryGetStringExternal (address,key) = match getString(address, key) { | |
11 | 7 | case a: String => | |
17 | 13 | ||
18 | 14 | func tryGetString (key) = tryGetStringExternal(this, key) | |
19 | 15 | ||
16 | + | ||
17 | + | func staticKey_refContractAddress () = "static_refContractAddress" | |
18 | + | ||
19 | + | ||
20 | + | let keyGlobalLastInterest = "global_lastCheck_interest" | |
20 | 21 | ||
21 | 22 | func staticKey_oracleAddress () = "static_oracleAddress" | |
22 | 23 | ||
30 | 31 | func staticKey_breederAddress () = "static_breederAddress" | |
31 | 32 | ||
32 | 33 | ||
33 | - | func staticKey_itemsAddress () = "static_itemsAddress" | |
34 | - | ||
35 | - | ||
36 | - | func staticKey_metaRaceAddress () = "static_metaRaceAddress" | |
37 | - | ||
38 | - | ||
39 | 34 | func staticKey_accBoosterAddress () = "static_accBoosterAddress" | |
40 | 35 | ||
41 | 36 | ||
42 | - | func staticKey_ | |
37 | + | func staticKey_couponsAddress () = "static_couponsAddress" | |
43 | 38 | ||
44 | 39 | ||
45 | - | func staticKey_maintenance () = "static_maintenance" | |
46 | - | ||
47 | - | ||
48 | - | func staticKey_cfMasterAddress () = "static_cfMasterAddress" | |
40 | + | func staticKey_burnAddress () = "static_burnAddress" | |
49 | 41 | ||
50 | 42 | ||
51 | 43 | func staticKey_extraFee () = "static_extraFee" | |
54 | 46 | func staticKey_feeAggregator () = "static_feeAggregator" | |
55 | 47 | ||
56 | 48 | ||
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" | |
67 | + | ||
68 | + | ||
57 | 69 | func getOracle () = Address(fromBase58String(tryGetString(staticKey_oracleAddress()))) | |
70 | + | ||
71 | + | ||
72 | + | func getRebirthAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_rebirthAddress()))) | |
58 | 73 | ||
59 | 74 | ||
60 | 75 | func getEggAssetId () = fromBase58String(tryGetStringExternal(getOracle(), staticKey_eggAssetId())) | |
66 | 81 | func getBreederAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_breederAddress()))) | |
67 | 82 | ||
68 | 83 | ||
69 | - | func | |
84 | + | func getAccBoosterAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_accBoosterAddress()))) | |
70 | 85 | ||
71 | 86 | ||
72 | - | func | |
87 | + | func getCouponsAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_couponsAddress()))) | |
73 | 88 | ||
74 | 89 | ||
75 | - | func getAccBoosterAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_accBoosterAddress()))) | |
90 | + | func getBurnAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_burnAddress()))) | |
91 | + | ||
92 | + | ||
93 | + | func getFeeAggregator () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_feeAggregator()))) | |
94 | + | ||
95 | + | ||
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()))) | |
76 | 103 | ||
77 | 104 | ||
78 | 105 | func getProxyStaking () = tryGetStringExternal(getOracle(), staticKey_proxyStakingContracts()) | |
79 | 106 | ||
80 | 107 | ||
81 | - | func | |
108 | + | func keyLastCheckInterest (address,asset) = (((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest") | |
82 | 109 | ||
83 | 110 | ||
84 | - | func | |
111 | + | func assetFarmingPower (address,asset) = (((("address_" + address) + "_asset_") + asset) + "_farmingPower") | |
85 | 112 | ||
86 | 113 | ||
87 | - | func getFeeAggregator () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_feeAggregator()))) | |
114 | + | func rewardClaimedKey (address,asset) = (((address + "_asset_") + asset) + "_claimed") | |
115 | + | ||
116 | + | ||
117 | + | func totalStakedUserKey (address) = ("total_staked_" + address) | |
88 | 118 | ||
89 | 119 | ||
90 | 120 | let RefererReward = 5 | |
99 | 129 | } | |
100 | 130 | ||
101 | 131 | ||
102 | - | func getRewardPerBlock () = 0 | |
103 | - | ||
104 | - | ||
105 | - | func isLocked () = if ((getMaintenance() != "")) | |
106 | - | then throw(getMaintenance()) | |
107 | - | else 0 | |
108 | - | ||
109 | - | ||
110 | 132 | func tryGetInteger (key) = match getInteger(this, key) { | |
111 | 133 | case b: Int => | |
112 | 134 | b | |
113 | 135 | case _ => | |
114 | 136 | 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") | |
115 | 171 | } | |
116 | 172 | ||
117 | 173 | ||
145 | 201 | } | |
146 | 202 | ||
147 | 203 | ||
148 | - | func asString (value) = match value { | |
149 | - | case string: String => | |
150 | - | string | |
151 | - | case _ => | |
152 | - | throw("FAS: wrong type, expected: String") | |
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 | 216 | ||
155 | 217 | ||
156 | - | func asInt (value) = match value { | |
157 | - | case int: Int => | |
158 | - | int | |
159 | - | case _ => | |
160 | - | throw("FAI: wrong type, expected: Int") | |
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 | 245 | ||
163 | 246 | ||
164 | 247 | func asBoolean (value) = match value { | |
169 | 252 | } | |
170 | 253 | ||
171 | 254 | ||
172 | - | func getAssetFarmingPower (assetId,address) = if (if ((value(assetInfo(assetId)).issuer == getBreederAddress())) | |
173 | - | then true | |
174 | - | else (value(assetInfo(assetId)).issuer == getIncubatorAddress())) | |
175 | - | then { | |
176 | - | let farmBoost = asInt(invoke(getItemsAddress(), "calculateFarmingPowerBoost", [toBase58String(assetId), address], nil)) | |
177 | - | if ((farmBoost == farmBoost)) | |
178 | - | then { | |
179 | - | let assetName = value(assetInfo(assetId)).name | |
180 | - | let isJackpot = (takeRight(value(assetName), 1) == "U") | |
181 | - | let farmGen = if (isJackpot) | |
182 | - | then "" | |
183 | - | else asString(invoke(getBreederAddress(), "getGenFromName", [assetName], nil)) | |
184 | - | if ((farmGen == farmGen)) | |
185 | - | then { | |
186 | - | let rarity = if (isJackpot) | |
187 | - | then 100 | |
188 | - | else { | |
189 | - | let generation = take(takeRight(assetName, 2), 1) | |
190 | - | getAssetRarity(farmGen, generation) | |
191 | - | } | |
192 | - | let totalFarmingPower = (rarity + fraction(rarity, farmBoost, 100)) | |
193 | - | $Tuple2(farmGen, totalFarmingPower) | |
194 | - | } | |
195 | - | else throw("Strict value is not equal to itself.") | |
196 | - | } | |
197 | - | else throw("Strict value is not equal to itself.") | |
198 | - | } | |
199 | - | else throw("not valid NFT") | |
200 | - | ||
201 | - | ||
202 | - | func getLastKnownAssetFarmingPower (address,assetId) = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_farmingPower")) | |
203 | - | ||
204 | - | ||
205 | - | func calcInterest (previousInterest,previousInterestHeight,totalFarmingPower) = (previousInterest + (((scale * getRewardPerBlock()) * (height - previousInterestHeight)) / totalFarmingPower)) | |
206 | - | ||
207 | - | ||
208 | - | func getCurrentInterest () = if ((tryGetInteger("total_farmingPower") > 0)) | |
209 | - | then { | |
210 | - | let previousInterest = tryGetInteger("total_lastCheckInterest") | |
211 | - | let previousInterestHeight = tryGetInteger("total_lastCheckInterestHeight") | |
212 | - | let totalFarmingPower = tryGetInteger("total_farmingPower") | |
213 | - | calcInterest(previousInterest, previousInterestHeight, totalFarmingPower) | |
214 | - | } | |
215 | - | else if ((tryGetInteger("total_startHeight") != 0)) | |
216 | - | then tryGetInteger("total_lastCheckInterest") | |
217 | - | else throw("farming is not launched, yet") | |
218 | - | ||
219 | - | ||
220 | - | func calcAssetRewardDelta (address,assetId,assetFarmingPower) = { | |
221 | - | let lastCheckAssetInterest = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_lastCheckInterest")) | |
222 | - | let currentInterest = getCurrentInterest() | |
223 | - | (assetFarmingPower * (currentInterest - lastCheckAssetInterest)) | |
224 | - | } | |
225 | - | ||
226 | - | ||
227 | - | func addAssetIdToGenEntry (assetId,assetGen) = { | |
228 | - | let currentValue = tryGetString((("assets_" + assetGen) + "_locked")) | |
229 | - | if ((currentValue == "")) | |
230 | - | then assetId | |
231 | - | else ((currentValue + ",") + assetId) | |
232 | - | } | |
233 | - | ||
234 | - | ||
235 | - | func getStakeResult (address,assetId,assetFarmingPower,unstaker) = { | |
236 | - | let asset = toBase58String(assetId) | |
237 | - | [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)] | |
238 | - | } | |
239 | - | ||
240 | - | ||
241 | - | func getUnstakeResult (address,assetId,color,caller,realCaller,claimEggs) = { | |
242 | - | let locked = isLocked() | |
243 | - | if ((locked == locked)) | |
244 | - | then { | |
245 | - | let asset = toBase58String(assetId) | |
246 | - | let unstaker = tryGetString((((("address_" + address) + "_asset_") + asset) + "_unstaker")) | |
247 | - | if (if ((unstaker != "")) | |
248 | - | then (unstaker != realCaller) | |
249 | - | else false) | |
250 | - | then throw("FUN: It seems duck was staked throuh a dapp, not directly, please unstake through dapp!") | |
251 | - | else { | |
252 | - | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
253 | - | if (!((assetFarmingPower > 0))) | |
254 | - | then throw("FGU: Asset farming power not bigger then 0") | |
255 | - | else { | |
256 | - | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
257 | - | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
258 | - | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
259 | - | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
260 | - | let isWithoutPerch = tryGetBoolean((((("address_" + address) + "_asset_") + asset) + "_without_perch")) | |
261 | - | let rewardAfterSickNess = reward | |
262 | - | let appendPerches = if (isWithoutPerch) | |
263 | - | then [DeleteEntry((((("address_" + address) + "_asset_") + asset) + "_without_perch"))] | |
264 | - | else [IntegerEntry(((("address_" + address) + "_perchesAvailable_") + color), (tryGetInteger(((("address_" + address) + "_perchesAvailable_") + color)) + 1))] | |
265 | - | let sendTx = if (claimEggs) | |
266 | - | then $Tuple2([ScriptTransfer(caller, (rewardAfterSickNess * 1000000), getEggAssetId())], (rewardAfterSickNess * 1000000)) | |
267 | - | else $Tuple2(nil, 0) | |
268 | - | $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) | |
269 | - | } | |
270 | - | } | |
271 | - | } | |
272 | - | else throw("Strict value is not equal to itself.") | |
273 | - | } | |
274 | - | ||
275 | - | ||
276 | 255 | func calculatePerchPrice (address) = { | |
277 | 256 | let hasArtefactStaked = tryGetStringExternal(getAccBoosterAddress(), (("ART-XMISTL_" + address) + "_owner")) | |
257 | + | let perchPrice = getIntegerValue(getOracle(), staticKey_perchFee()) | |
278 | 258 | if ((hasArtefactStaked == "")) | |
279 | 259 | then perchPrice | |
280 | 260 | else ((perchPrice / 10) * 9) | |
288 | 268 | } | |
289 | 269 | ||
290 | 270 | ||
291 | - | func unstakeNFTInternal (asset,i,claimEgg) = { | |
292 | - | let assetId = fromBase58String(asset) | |
293 | - | let realCaller = toString(i.caller) | |
294 | - | let address = if (isProxyStakingSc(toString(i.caller))) | |
295 | - | then toString(i.originCaller) | |
296 | - | else realCaller | |
297 | - | let color = takeRight(value(assetInfo(assetId)).name, 1) | |
298 | - | if ((color == "U")) | |
299 | - | then throw("FUN: use another function to unstake Jackpot NFT") | |
300 | - | else { | |
301 | - | let result = getUnstakeResult(address, assetId, color, i.caller, realCaller, claimEgg) | |
302 | - | result | |
271 | + | @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) | |
303 | 299 | } | |
304 | - | } | |
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 | + | } | |
305 | 318 | ||
306 | - | ||
307 | - | func unstakeJackpotInternal (asset,i,claimEgg) = { | |
308 | - | let assetId = fromBase58String(asset) | |
309 | - | let realCaller = toString(i.caller) | |
310 | - | let address = if (isProxyStakingSc(toString(i.caller))) | |
311 | - | then toString(i.originCaller) | |
312 | - | else realCaller | |
313 | - | let color = tryGetString((((("address_" + address) + "_asset_") + asset) + "_perchColor")) | |
314 | - | if ((takeRight(value(value(assetInfo(assetId)).name), 1) != "U")) | |
315 | - | then throw("jackpot only") | |
316 | - | else { | |
317 | - | let result = getUnstakeResult(address, assetId, color, i.caller, realCaller, claimEgg) | |
318 | - | result | |
319 | - | } | |
320 | - | } | |
321 | - | ||
322 | - | ||
323 | - | func getBool (key) = match getBoolean(this, key) { | |
324 | - | case b: Boolean => | |
325 | - | b | |
326 | - | case _ => | |
327 | - | false | |
328 | - | } | |
329 | - | ||
330 | - | ||
331 | - | func isTestEnv () = getBool("TESTENV") | |
332 | 319 | ||
333 | 320 | ||
334 | 321 | @Callable(i) | |
339 | 326 | ||
340 | 327 | ||
341 | 328 | @Callable(i) | |
342 | - | func init () = if ((i.caller != this)) | |
343 | - | then throw("FI: admin only") | |
344 | - | else [IntegerEntry("total_startHeight", height)] | |
345 | - | ||
346 | - | ||
347 | - | ||
348 | - | @Callable(i) | |
349 | - | func buyPerch (colorI,refererAddress) = throw("FBN: function is disabled, migration to new sc ongoing") | |
350 | - | ||
351 | - | ||
352 | - | ||
353 | - | @Callable(i) | |
354 | - | func addFreePerch (address,color) = throw("FBN: function is disabled, migration to new sc ongoing") | |
355 | - | ||
356 | - | ||
357 | - | ||
358 | - | @Callable(i) | |
359 | - | func stakeNFT () = throw("FBN: function is disabled, migration to new sc ongoing") | |
360 | - | ||
361 | - | ||
362 | - | ||
363 | - | @Callable(i) | |
364 | - | func stakeNFTWithoutPerch () = throw("FBN: function is disabled, migration to new sc ongoing") | |
365 | - | ||
366 | - | ||
367 | - | ||
368 | - | @Callable(i) | |
369 | - | func unstakeNFT (asset) = { | |
370 | - | let validPayment = if ((i.caller == getMetaraceAddress())) | |
371 | - | then nil | |
372 | - | else checkAdditionalPayment(i.payments[0]) | |
329 | + | func buyPerch (colorI,refererAddress) = { | |
330 | + | let validPayment = checkAdditionalPayment(i.payments[0]) | |
373 | 331 | if ((validPayment == validPayment)) | |
374 | 332 | then { | |
375 | - | let result = unstakeNFTInternal(asset, i, true) | |
376 | - | $Tuple2((result._1 ++ validPayment), result._2) | |
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 | + | } | |
377 | 375 | } | |
378 | 376 | else throw("Strict value is not equal to itself.") | |
379 | 377 | } | |
381 | 379 | ||
382 | 380 | ||
383 | 381 | @Callable(i) | |
384 | - | func unstakeNFTWithoutClaim (asset) = unstakeNFTInternal(asset, i, false) | |
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 | + | } | |
385 | 395 | ||
386 | 396 | ||
387 | 397 | ||
388 | 398 | @Callable(i) | |
389 | - | func stakeJackpot (color) = throw("FBN: function is disabled, migration to new sc ongoing") | |
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 | + | } | |
390 | 419 | ||
391 | 420 | ||
392 | 421 | ||
393 | 422 | @Callable(i) | |
394 | - | func unstakeJackpot (asset) = { | |
395 | - | let validPayment = checkAdditionalPayment(i.payments[0]) | |
396 | - | if ((validPayment == validPayment)) | |
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)) | |
397 | 479 | then { | |
398 | - | let result = unstakeJackpotInternal(asset, i, true) | |
399 | - | $Tuple2((result._1 ++ validPayment), result._2) | |
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.") | |
400 | 504 | } | |
401 | 505 | else throw("Strict value is not equal to itself.") | |
402 | 506 | } | |
404 | 508 | ||
405 | 509 | ||
406 | 510 | @Callable(i) | |
407 | - | func unstakeJackpotWithoutClaimEgg (asset) = unstakeJackpotInternal(asset, i, false) | |
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 | + | } | |
408 | 520 | ||
409 | 521 | ||
410 | 522 | ||
411 | 523 | @Callable(i) | |
412 | - | func claimReward (asset) = { | |
413 | - | let locked = isLocked() | |
414 | - | if ((locked == locked)) | |
415 | - | then { | |
416 | - | let validPayment = if ((i.originCaller == getCfMasterAddress())) | |
417 | - | then nil | |
418 | - | else checkAdditionalPayment(i.payments[0]) | |
419 | - | if ((validPayment == validPayment)) | |
420 | - | then { | |
421 | - | let address = if ((i.originCaller == getCfMasterAddress())) | |
422 | - | then toString(i.caller) | |
423 | - | else toString(i.originCaller) | |
424 | - | let assetId = fromBase58String(asset) | |
425 | - | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
426 | - | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
427 | - | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
428 | - | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
429 | - | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
430 | - | if ((0 >= reward)) | |
431 | - | then throw("FCR: you have no EGGs to withdraw") | |
432 | - | 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)) | |
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) | |
433 | 534 | } | |
434 | - | else throw("Strict value is not equal to itself.") | |
435 | - | } | |
436 | 535 | else throw("Strict value is not equal to itself.") | |
437 | 536 | } | |
438 | 537 |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | - | let perchPrice = (100 * 1000000) | |
5 | - | ||
6 | - | let scale = 10000 | |
7 | - | ||
8 | - | let scale2 = 1000000 | |
4 | + | let Scale = 100000000 | |
9 | 5 | ||
10 | 6 | func tryGetStringExternal (address,key) = match getString(address, key) { | |
11 | 7 | case a: String => | |
12 | 8 | a | |
13 | 9 | case _ => | |
14 | 10 | "" | |
15 | 11 | } | |
16 | 12 | ||
17 | 13 | ||
18 | 14 | func tryGetString (key) = tryGetStringExternal(this, key) | |
19 | 15 | ||
16 | + | ||
17 | + | func staticKey_refContractAddress () = "static_refContractAddress" | |
18 | + | ||
19 | + | ||
20 | + | let keyGlobalLastInterest = "global_lastCheck_interest" | |
20 | 21 | ||
21 | 22 | func staticKey_oracleAddress () = "static_oracleAddress" | |
22 | 23 | ||
23 | 24 | ||
24 | 25 | func staticKey_eggAssetId () = "static_eggAssetId" | |
25 | 26 | ||
26 | 27 | ||
27 | 28 | func staticKey_incubatorAddress () = "static_incubatorAddress" | |
28 | 29 | ||
29 | 30 | ||
30 | 31 | func staticKey_breederAddress () = "static_breederAddress" | |
31 | 32 | ||
32 | 33 | ||
33 | - | func staticKey_itemsAddress () = "static_itemsAddress" | |
34 | - | ||
35 | - | ||
36 | - | func staticKey_metaRaceAddress () = "static_metaRaceAddress" | |
37 | - | ||
38 | - | ||
39 | 34 | func staticKey_accBoosterAddress () = "static_accBoosterAddress" | |
40 | 35 | ||
41 | 36 | ||
42 | - | func staticKey_ | |
37 | + | func staticKey_couponsAddress () = "static_couponsAddress" | |
43 | 38 | ||
44 | 39 | ||
45 | - | func staticKey_maintenance () = "static_maintenance" | |
46 | - | ||
47 | - | ||
48 | - | func staticKey_cfMasterAddress () = "static_cfMasterAddress" | |
40 | + | func staticKey_burnAddress () = "static_burnAddress" | |
49 | 41 | ||
50 | 42 | ||
51 | 43 | func staticKey_extraFee () = "static_extraFee" | |
52 | 44 | ||
53 | 45 | ||
54 | 46 | func staticKey_feeAggregator () = "static_feeAggregator" | |
55 | 47 | ||
56 | 48 | ||
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" | |
67 | + | ||
68 | + | ||
57 | 69 | func getOracle () = Address(fromBase58String(tryGetString(staticKey_oracleAddress()))) | |
70 | + | ||
71 | + | ||
72 | + | func getRebirthAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_rebirthAddress()))) | |
58 | 73 | ||
59 | 74 | ||
60 | 75 | func getEggAssetId () = fromBase58String(tryGetStringExternal(getOracle(), staticKey_eggAssetId())) | |
61 | 76 | ||
62 | 77 | ||
63 | 78 | func getIncubatorAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_incubatorAddress()))) | |
64 | 79 | ||
65 | 80 | ||
66 | 81 | func getBreederAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_breederAddress()))) | |
67 | 82 | ||
68 | 83 | ||
69 | - | func | |
84 | + | func getAccBoosterAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_accBoosterAddress()))) | |
70 | 85 | ||
71 | 86 | ||
72 | - | func | |
87 | + | func getCouponsAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_couponsAddress()))) | |
73 | 88 | ||
74 | 89 | ||
75 | - | func getAccBoosterAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_accBoosterAddress()))) | |
90 | + | func getBurnAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_burnAddress()))) | |
91 | + | ||
92 | + | ||
93 | + | func getFeeAggregator () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_feeAggregator()))) | |
94 | + | ||
95 | + | ||
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()))) | |
76 | 103 | ||
77 | 104 | ||
78 | 105 | func getProxyStaking () = tryGetStringExternal(getOracle(), staticKey_proxyStakingContracts()) | |
79 | 106 | ||
80 | 107 | ||
81 | - | func | |
108 | + | func keyLastCheckInterest (address,asset) = (((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest") | |
82 | 109 | ||
83 | 110 | ||
84 | - | func | |
111 | + | func assetFarmingPower (address,asset) = (((("address_" + address) + "_asset_") + asset) + "_farmingPower") | |
85 | 112 | ||
86 | 113 | ||
87 | - | func getFeeAggregator () = Address(fromBase58String(tryGetStringExternal(getOracle(), staticKey_feeAggregator()))) | |
114 | + | func rewardClaimedKey (address,asset) = (((address + "_asset_") + asset) + "_claimed") | |
115 | + | ||
116 | + | ||
117 | + | func totalStakedUserKey (address) = ("total_staked_" + address) | |
88 | 118 | ||
89 | 119 | ||
90 | 120 | let RefererReward = 5 | |
91 | 121 | ||
92 | 122 | func checkAdditionalPayment (payment) = if (isDefined(payment.assetId)) | |
93 | 123 | then throw("FCAP: Please attach waves") | |
94 | 124 | else { | |
95 | 125 | let feeAmount = getIntegerValue(getOracle(), staticKey_extraFee()) | |
96 | 126 | if ((payment.amount != feeAmount)) | |
97 | 127 | then throw((("FCAP: Please attach exactly " + toString(feeAmount)) + " amount of wavelets")) | |
98 | 128 | else [ScriptTransfer(getFeeAggregator(), feeAmount, unit)] | |
99 | 129 | } | |
100 | 130 | ||
101 | 131 | ||
102 | - | func getRewardPerBlock () = 0 | |
103 | - | ||
104 | - | ||
105 | - | func isLocked () = if ((getMaintenance() != "")) | |
106 | - | then throw(getMaintenance()) | |
107 | - | else 0 | |
108 | - | ||
109 | - | ||
110 | 132 | func tryGetInteger (key) = match getInteger(this, key) { | |
111 | 133 | case b: Int => | |
112 | 134 | b | |
113 | 135 | case _ => | |
114 | 136 | 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") | |
115 | 171 | } | |
116 | 172 | ||
117 | 173 | ||
118 | 174 | func tryGetBoolean (key) = match getBoolean(this, key) { | |
119 | 175 | case b: Boolean => | |
120 | 176 | b | |
121 | 177 | case _ => | |
122 | 178 | false | |
123 | 179 | } | |
124 | 180 | ||
125 | 181 | ||
126 | 182 | func tryGetBooleanExternal (address,key) = match getBoolean(address, key) { | |
127 | 183 | case b: Boolean => | |
128 | 184 | b | |
129 | 185 | case _ => | |
130 | 186 | false | |
131 | 187 | } | |
132 | 188 | ||
133 | 189 | ||
134 | 190 | func getAssetOrigin (generation) = if ((generation == "G")) | |
135 | 191 | then getIncubatorAddress() | |
136 | 192 | else getBreederAddress() | |
137 | 193 | ||
138 | 194 | ||
139 | 195 | func getAssetRarity (genotype,generation) = { | |
140 | 196 | let quantity = valueOrErrorMessage(getInteger(getAssetOrigin(generation), (("stats_" + genotype) + "_quantity")), (("stats_" + genotype) + "_quantity not found")) | |
141 | 197 | let power = pow((10000 / quantity), 4, 5, 1, 2, FLOOR) | |
142 | 198 | if ((power > 0)) | |
143 | 199 | then power | |
144 | 200 | else 2 | |
145 | 201 | } | |
146 | 202 | ||
147 | 203 | ||
148 | - | func asString (value) = match value { | |
149 | - | case string: String => | |
150 | - | string | |
151 | - | case _ => | |
152 | - | throw("FAS: wrong type, expected: String") | |
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 | 216 | ||
155 | 217 | ||
156 | - | func asInt (value) = match value { | |
157 | - | case int: Int => | |
158 | - | int | |
159 | - | case _ => | |
160 | - | throw("FAI: wrong type, expected: Int") | |
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 | 245 | ||
163 | 246 | ||
164 | 247 | func asBoolean (value) = match value { | |
165 | 248 | case boolean: Boolean => | |
166 | 249 | boolean | |
167 | 250 | case _ => | |
168 | 251 | throw("FAB: wrong type, expected: Boolean") | |
169 | 252 | } | |
170 | 253 | ||
171 | 254 | ||
172 | - | func getAssetFarmingPower (assetId,address) = if (if ((value(assetInfo(assetId)).issuer == getBreederAddress())) | |
173 | - | then true | |
174 | - | else (value(assetInfo(assetId)).issuer == getIncubatorAddress())) | |
175 | - | then { | |
176 | - | let farmBoost = asInt(invoke(getItemsAddress(), "calculateFarmingPowerBoost", [toBase58String(assetId), address], nil)) | |
177 | - | if ((farmBoost == farmBoost)) | |
178 | - | then { | |
179 | - | let assetName = value(assetInfo(assetId)).name | |
180 | - | let isJackpot = (takeRight(value(assetName), 1) == "U") | |
181 | - | let farmGen = if (isJackpot) | |
182 | - | then "" | |
183 | - | else asString(invoke(getBreederAddress(), "getGenFromName", [assetName], nil)) | |
184 | - | if ((farmGen == farmGen)) | |
185 | - | then { | |
186 | - | let rarity = if (isJackpot) | |
187 | - | then 100 | |
188 | - | else { | |
189 | - | let generation = take(takeRight(assetName, 2), 1) | |
190 | - | getAssetRarity(farmGen, generation) | |
191 | - | } | |
192 | - | let totalFarmingPower = (rarity + fraction(rarity, farmBoost, 100)) | |
193 | - | $Tuple2(farmGen, totalFarmingPower) | |
194 | - | } | |
195 | - | else throw("Strict value is not equal to itself.") | |
196 | - | } | |
197 | - | else throw("Strict value is not equal to itself.") | |
198 | - | } | |
199 | - | else throw("not valid NFT") | |
200 | - | ||
201 | - | ||
202 | - | func getLastKnownAssetFarmingPower (address,assetId) = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_farmingPower")) | |
203 | - | ||
204 | - | ||
205 | - | func calcInterest (previousInterest,previousInterestHeight,totalFarmingPower) = (previousInterest + (((scale * getRewardPerBlock()) * (height - previousInterestHeight)) / totalFarmingPower)) | |
206 | - | ||
207 | - | ||
208 | - | func getCurrentInterest () = if ((tryGetInteger("total_farmingPower") > 0)) | |
209 | - | then { | |
210 | - | let previousInterest = tryGetInteger("total_lastCheckInterest") | |
211 | - | let previousInterestHeight = tryGetInteger("total_lastCheckInterestHeight") | |
212 | - | let totalFarmingPower = tryGetInteger("total_farmingPower") | |
213 | - | calcInterest(previousInterest, previousInterestHeight, totalFarmingPower) | |
214 | - | } | |
215 | - | else if ((tryGetInteger("total_startHeight") != 0)) | |
216 | - | then tryGetInteger("total_lastCheckInterest") | |
217 | - | else throw("farming is not launched, yet") | |
218 | - | ||
219 | - | ||
220 | - | func calcAssetRewardDelta (address,assetId,assetFarmingPower) = { | |
221 | - | let lastCheckAssetInterest = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_lastCheckInterest")) | |
222 | - | let currentInterest = getCurrentInterest() | |
223 | - | (assetFarmingPower * (currentInterest - lastCheckAssetInterest)) | |
224 | - | } | |
225 | - | ||
226 | - | ||
227 | - | func addAssetIdToGenEntry (assetId,assetGen) = { | |
228 | - | let currentValue = tryGetString((("assets_" + assetGen) + "_locked")) | |
229 | - | if ((currentValue == "")) | |
230 | - | then assetId | |
231 | - | else ((currentValue + ",") + assetId) | |
232 | - | } | |
233 | - | ||
234 | - | ||
235 | - | func getStakeResult (address,assetId,assetFarmingPower,unstaker) = { | |
236 | - | let asset = toBase58String(assetId) | |
237 | - | [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)] | |
238 | - | } | |
239 | - | ||
240 | - | ||
241 | - | func getUnstakeResult (address,assetId,color,caller,realCaller,claimEggs) = { | |
242 | - | let locked = isLocked() | |
243 | - | if ((locked == locked)) | |
244 | - | then { | |
245 | - | let asset = toBase58String(assetId) | |
246 | - | let unstaker = tryGetString((((("address_" + address) + "_asset_") + asset) + "_unstaker")) | |
247 | - | if (if ((unstaker != "")) | |
248 | - | then (unstaker != realCaller) | |
249 | - | else false) | |
250 | - | then throw("FUN: It seems duck was staked throuh a dapp, not directly, please unstake through dapp!") | |
251 | - | else { | |
252 | - | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
253 | - | if (!((assetFarmingPower > 0))) | |
254 | - | then throw("FGU: Asset farming power not bigger then 0") | |
255 | - | else { | |
256 | - | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
257 | - | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
258 | - | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
259 | - | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
260 | - | let isWithoutPerch = tryGetBoolean((((("address_" + address) + "_asset_") + asset) + "_without_perch")) | |
261 | - | let rewardAfterSickNess = reward | |
262 | - | let appendPerches = if (isWithoutPerch) | |
263 | - | then [DeleteEntry((((("address_" + address) + "_asset_") + asset) + "_without_perch"))] | |
264 | - | else [IntegerEntry(((("address_" + address) + "_perchesAvailable_") + color), (tryGetInteger(((("address_" + address) + "_perchesAvailable_") + color)) + 1))] | |
265 | - | let sendTx = if (claimEggs) | |
266 | - | then $Tuple2([ScriptTransfer(caller, (rewardAfterSickNess * 1000000), getEggAssetId())], (rewardAfterSickNess * 1000000)) | |
267 | - | else $Tuple2(nil, 0) | |
268 | - | $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) | |
269 | - | } | |
270 | - | } | |
271 | - | } | |
272 | - | else throw("Strict value is not equal to itself.") | |
273 | - | } | |
274 | - | ||
275 | - | ||
276 | 255 | func calculatePerchPrice (address) = { | |
277 | 256 | let hasArtefactStaked = tryGetStringExternal(getAccBoosterAddress(), (("ART-XMISTL_" + address) + "_owner")) | |
257 | + | let perchPrice = getIntegerValue(getOracle(), staticKey_perchFee()) | |
278 | 258 | if ((hasArtefactStaked == "")) | |
279 | 259 | then perchPrice | |
280 | 260 | else ((perchPrice / 10) * 9) | |
281 | 261 | } | |
282 | 262 | ||
283 | 263 | ||
284 | 264 | func isProxyStakingSc (address) = { | |
285 | 265 | let allowedContracts = getProxyStaking() | |
286 | 266 | let allowedContractsList = split(allowedContracts, ";") | |
287 | 267 | (indexOf(allowedContractsList, address) != unit) | |
288 | 268 | } | |
289 | 269 | ||
290 | 270 | ||
291 | - | func unstakeNFTInternal (asset,i,claimEgg) = { | |
292 | - | let assetId = fromBase58String(asset) | |
293 | - | let realCaller = toString(i.caller) | |
294 | - | let address = if (isProxyStakingSc(toString(i.caller))) | |
295 | - | then toString(i.originCaller) | |
296 | - | else realCaller | |
297 | - | let color = takeRight(value(assetInfo(assetId)).name, 1) | |
298 | - | if ((color == "U")) | |
299 | - | then throw("FUN: use another function to unstake Jackpot NFT") | |
300 | - | else { | |
301 | - | let result = getUnstakeResult(address, assetId, color, i.caller, realCaller, claimEgg) | |
302 | - | result | |
271 | + | @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) | |
303 | 299 | } | |
304 | - | } | |
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 | + | } | |
305 | 318 | ||
306 | - | ||
307 | - | func unstakeJackpotInternal (asset,i,claimEgg) = { | |
308 | - | let assetId = fromBase58String(asset) | |
309 | - | let realCaller = toString(i.caller) | |
310 | - | let address = if (isProxyStakingSc(toString(i.caller))) | |
311 | - | then toString(i.originCaller) | |
312 | - | else realCaller | |
313 | - | let color = tryGetString((((("address_" + address) + "_asset_") + asset) + "_perchColor")) | |
314 | - | if ((takeRight(value(value(assetInfo(assetId)).name), 1) != "U")) | |
315 | - | then throw("jackpot only") | |
316 | - | else { | |
317 | - | let result = getUnstakeResult(address, assetId, color, i.caller, realCaller, claimEgg) | |
318 | - | result | |
319 | - | } | |
320 | - | } | |
321 | - | ||
322 | - | ||
323 | - | func getBool (key) = match getBoolean(this, key) { | |
324 | - | case b: Boolean => | |
325 | - | b | |
326 | - | case _ => | |
327 | - | false | |
328 | - | } | |
329 | - | ||
330 | - | ||
331 | - | func isTestEnv () = getBool("TESTENV") | |
332 | 319 | ||
333 | 320 | ||
334 | 321 | @Callable(i) | |
335 | 322 | func configureOracle (oracle) = if ((i.caller != this)) | |
336 | 323 | then throw("FCO: admin only") | |
337 | 324 | else [StringEntry(staticKey_oracleAddress(), oracle)] | |
338 | 325 | ||
339 | 326 | ||
340 | 327 | ||
341 | 328 | @Callable(i) | |
342 | - | func init () = if ((i.caller != this)) | |
343 | - | then throw("FI: admin only") | |
344 | - | else [IntegerEntry("total_startHeight", height)] | |
345 | - | ||
346 | - | ||
347 | - | ||
348 | - | @Callable(i) | |
349 | - | func buyPerch (colorI,refererAddress) = throw("FBN: function is disabled, migration to new sc ongoing") | |
350 | - | ||
351 | - | ||
352 | - | ||
353 | - | @Callable(i) | |
354 | - | func addFreePerch (address,color) = throw("FBN: function is disabled, migration to new sc ongoing") | |
355 | - | ||
356 | - | ||
357 | - | ||
358 | - | @Callable(i) | |
359 | - | func stakeNFT () = throw("FBN: function is disabled, migration to new sc ongoing") | |
360 | - | ||
361 | - | ||
362 | - | ||
363 | - | @Callable(i) | |
364 | - | func stakeNFTWithoutPerch () = throw("FBN: function is disabled, migration to new sc ongoing") | |
365 | - | ||
366 | - | ||
367 | - | ||
368 | - | @Callable(i) | |
369 | - | func unstakeNFT (asset) = { | |
370 | - | let validPayment = if ((i.caller == getMetaraceAddress())) | |
371 | - | then nil | |
372 | - | else checkAdditionalPayment(i.payments[0]) | |
329 | + | func buyPerch (colorI,refererAddress) = { | |
330 | + | let validPayment = checkAdditionalPayment(i.payments[0]) | |
373 | 331 | if ((validPayment == validPayment)) | |
374 | 332 | then { | |
375 | - | let result = unstakeNFTInternal(asset, i, true) | |
376 | - | $Tuple2((result._1 ++ validPayment), result._2) | |
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 | + | } | |
377 | 375 | } | |
378 | 376 | else throw("Strict value is not equal to itself.") | |
379 | 377 | } | |
380 | 378 | ||
381 | 379 | ||
382 | 380 | ||
383 | 381 | @Callable(i) | |
384 | - | func unstakeNFTWithoutClaim (asset) = unstakeNFTInternal(asset, i, false) | |
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 | + | } | |
385 | 395 | ||
386 | 396 | ||
387 | 397 | ||
388 | 398 | @Callable(i) | |
389 | - | func stakeJackpot (color) = throw("FBN: function is disabled, migration to new sc ongoing") | |
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 | + | } | |
390 | 419 | ||
391 | 420 | ||
392 | 421 | ||
393 | 422 | @Callable(i) | |
394 | - | func unstakeJackpot (asset) = { | |
395 | - | let validPayment = checkAdditionalPayment(i.payments[0]) | |
396 | - | if ((validPayment == validPayment)) | |
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)) | |
397 | 479 | then { | |
398 | - | let result = unstakeJackpotInternal(asset, i, true) | |
399 | - | $Tuple2((result._1 ++ validPayment), result._2) | |
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.") | |
400 | 504 | } | |
401 | 505 | else throw("Strict value is not equal to itself.") | |
402 | 506 | } | |
403 | 507 | ||
404 | 508 | ||
405 | 509 | ||
406 | 510 | @Callable(i) | |
407 | - | func unstakeJackpotWithoutClaimEgg (asset) = unstakeJackpotInternal(asset, i, false) | |
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 | + | } | |
408 | 520 | ||
409 | 521 | ||
410 | 522 | ||
411 | 523 | @Callable(i) | |
412 | - | func claimReward (asset) = { | |
413 | - | let locked = isLocked() | |
414 | - | if ((locked == locked)) | |
415 | - | then { | |
416 | - | let validPayment = if ((i.originCaller == getCfMasterAddress())) | |
417 | - | then nil | |
418 | - | else checkAdditionalPayment(i.payments[0]) | |
419 | - | if ((validPayment == validPayment)) | |
420 | - | then { | |
421 | - | let address = if ((i.originCaller == getCfMasterAddress())) | |
422 | - | then toString(i.caller) | |
423 | - | else toString(i.originCaller) | |
424 | - | let assetId = fromBase58String(asset) | |
425 | - | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
426 | - | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
427 | - | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
428 | - | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
429 | - | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
430 | - | if ((0 >= reward)) | |
431 | - | then throw("FCR: you have no EGGs to withdraw") | |
432 | - | 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)) | |
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) | |
433 | 534 | } | |
434 | - | else throw("Strict value is not equal to itself.") | |
435 | - | } | |
436 | 535 | else throw("Strict value is not equal to itself.") | |
437 | 536 | } | |
438 | 537 | ||
439 | 538 |
github/deemru/w8io/3ef1775 88.56 ms ◑