tx · CePWAsvbqcM4ypm1268t74p7MsF7Bo5GFNqxSfGUZCej 3NADcxHXbecCheinqFbvhDjfzZhsMFZJUuH: -0.03700000 Waves 2022.11.28 14:22 [2336885] smart account 3NADcxHXbecCheinqFbvhDjfzZhsMFZJUuH > SELF 0.00000000 Waves
{ "type": 13, "id": "CePWAsvbqcM4ypm1268t74p7MsF7Bo5GFNqxSfGUZCej", "fee": 3700000, "feeAssetId": null, "timestamp": 1669634598015, "version": 2, "chainId": 84, "sender": "3NADcxHXbecCheinqFbvhDjfzZhsMFZJUuH", "senderPublicKey": "DKfzQgvVdTqPHgGbdZptWYA8G5xVfmSMAwL3UnhwQmdy", "proofs": [ "2Rw7p4gTGkNiqaoL5aY6aj8ndaih57dENX44XsGJX65TegRnz7FPexJvkoKfjoPUpEB2AJQbguwM7BDKAcPv6vTP" ], "script": "base64:BgImCAISAwoBCBIAEgMKAQESABIAEgMKAQESAwoBARIDCgEIEgMKAQg5AA1rX3RvdGFsU3VwcGx5Ag1rX3RvdGFsU3VwcGx5AA9rX2xvY2tlZEJhbGFuY2UCD2tfbG9ja2VkQmFsYW5jZQANa19mcmVlQmFsYW5jZQINa19mcmVlQmFsYW5jZQAGa19yYXRlAgZrX3JhdGUACWtfYmFsYW5jZQIJa19iYWxhbmNlAA5rX2F2ZXJhZ2VfcmF0ZQIOa19hdmVyYWdlX3JhdGUAEGtfd2l0aGRyYXdfbGltaXQCEGtfd2l0aGRyYXdfbGltaXQAFGtfbGFzdF93aXRoZHJhd19kYXRlAhRrX2xhc3Rfd2l0aGRyYXdfZGF0ZQAUa193aXRoZHJhd19pbl9wZXJpb2QCFGtfd2l0aGRyYXdfaW5fcGVyaW9kAA1rX2luaXRpYWxpemVkAg1rX2luaXRpYWxpemVkABRrX2Nvb3JkaW5hdG9yQWRkcmVzcwIUa19jb29yZGluYXRvckFkZHJlc3MABWtfYW1tAgVrX2FtbQANa19xdW90ZV9hc3NldAINa19xdW90ZV9hc3NldAASa19hZG1pbl9wdWJsaWNfa2V5AhJrX2FkbWluX3B1YmxpY19rZXkAD2tfYWRtaW5fYWRkcmVzcwIPa19hZG1pbl9hZGRyZXNzABFrX21hbmFnZXJfYWRkcmVzcwIRa19tYW5hZ2VyX2FkZHJlc3MBDnRvQ29tcG9zaXRlS2V5AgRfa2V5CF9hZGRyZXNzCQCsAgIJAKwCAgUEX2tleQIBXwUIX2FkZHJlc3MBC2Nvb3JkaW5hdG9yAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFFGtfY29vcmRpbmF0b3JBZGRyZXNzAhNDb29yZGluYXRvciBub3Qgc2V0AQtpc1doaXRlbGlzdAEIX2FkZHJlc3MJAQt2YWx1ZU9yRWxzZQIJAJsIAgkBC2Nvb3JkaW5hdG9yAAkBDnRvQ29tcG9zaXRlS2V5AgUFa19hbW0FCF9hZGRyZXNzBwEOYWRtaW5QdWJsaWNLZXkACQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEmtfYWRtaW5fcHVibGljX2tleQEMYWRtaW5BZGRyZXNzAAkApggBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgkBC2Nvb3JkaW5hdG9yAAUPa19hZG1pbl9hZGRyZXNzAhVBZG1pbiBhZGRyZXNzIG5vdCBzZXQBCnF1b3RlQXNzZXQACQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFDWtfcXVvdGVfYXNzZXQBDm1hbmFnZXJBZGRyZXNzAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEWtfbWFuYWdlcl9hZGRyZXNzAg9NYW5hZ2VyIG5vdCBzZXQADERFQ0lNQUxfVU5JVAkAaAIAAQkAaAIJAGgCCQBoAgkAaAIJAGgCCQBoAgkAaAIACgAKAAoACgAKAAoACgAKAAhEVVJBVElPTgkAaAIJAGgCADwAPAAYAApOT19BRERSRVNTAgAACU5PX1NUQUtFUgAAARB1c2RuRnJvbURlY2ltYWxzAQdfYW1vdW50CQBpAgUHX2Ftb3VudABkAQ51c2RuVG9EZWNpbWFscwEHX2Ftb3VudAkAaAIFB19hbW91bnQAZAEEZGl2ZAICX3gCX3kJAG4EBQJfeAUMREVDSU1BTF9VTklUBQJfeQUISEFMRkVWRU4BBG11bGQCAl94Al95CQBuBAUCX3gFAl95BQxERUNJTUFMX1VOSVQFCEhBTEZFVkVOAQNhYnMBAl94AwkAZgIFAl94AAAFAl94CQEBLQEFAl94AQRtaW52AgJfeAJfeQMJAGYCBQJfeAUCX3kFAl95BQJfeAAPV0lUSERSQVdfUEVSSU9ECQBoAgCAowUA6AcAE1dJVEhEUkFXX1BFUl9QRVJJT0QJAQRkaXZkAgkAaAIAAQUMREVDSU1BTF9VTklUCQBoAgAEBQxERUNJTUFMX1VOSVQBA2ludAEBawkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBHRoaXMFAWsJAKwCAgINbm8gdmFsdWUgZm9yIAUBawEEaW50MAEBawkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQFrAAABBGludDEBAWsJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUBawUMREVDSU1BTF9VTklUAQt0b3RhbFN1cHBseQAJAQRpbnQwAQUNa190b3RhbFN1cHBseQEEcmF0ZQAJAQRpbnQxAQUGa19yYXRlAQliYWxhbmNlT2YBB19zdGFrZXIJAQRpbnQwAQkBDnRvQ29tcG9zaXRlS2V5AgUJa19iYWxhbmNlBQdfc3Rha2VyAQthdmVyYWdlUmF0ZQEHX3N0YWtlcgkBBGludDABCQEOdG9Db21wb3NpdGVLZXkCBQ5rX2F2ZXJhZ2VfcmF0ZQUHX3N0YWtlcgENd2l0aGRyYXdMaW1pdAEHX3N0YWtlcgkBBGludDABCQEOdG9Db21wb3NpdGVLZXkCBRBrX3dpdGhkcmF3X2xpbWl0BQdfc3Rha2VyARF3aXRoZHJhd25JblBlcmlvZAEHX3N0YWtlcgkBBGludDABCQEOdG9Db21wb3NpdGVLZXkCBRRrX3dpdGhkcmF3X2luX3BlcmlvZAUHX3N0YWtlcgERbGFzdFdpdGhkcmF3bkRhdGUBB19zdGFrZXIJAQRpbnQwAQkBDnRvQ29tcG9zaXRlS2V5AgUUa19sYXN0X3dpdGhkcmF3X2RhdGUFB19zdGFrZXIBC2ZyZWVCYWxhbmNlAAkBBGludDABBQ1rX2ZyZWVCYWxhbmNlAQ1sb2NrZWRCYWxhbmNlAAkBBGludDABBQ9rX2xvY2tlZEJhbGFuY2UBC2luaXRpYWxpemVkAAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzBQ1rX2luaXRpYWxpemVkBwEUZ2V0V2l0aGRyYXdMaW1pdExlZnQBB19zdGFrZXIEC2N1cnJlbnREYXRlCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQQbGFzdFdpdGhkcmF3RGF0ZQkBEWxhc3RXaXRoZHJhd25EYXRlAQUHX3N0YWtlcgQLJHQwNDMyNzQ1OTEDCQBmAgkAZQIFC2N1cnJlbnREYXRlBRBsYXN0V2l0aGRyYXdEYXRlBQ9XSVRIRFJBV19QRVJJT0QJAJQKAgULY3VycmVudERhdGUJAQ13aXRoZHJhd0xpbWl0AQUHX3N0YWtlcgkAlAoCBRBsYXN0V2l0aGRyYXdEYXRlCQBlAgkBDXdpdGhkcmF3TGltaXQBBQdfc3Rha2VyCQERd2l0aGRyYXduSW5QZXJpb2QBBQdfc3Rha2VyBBRuZXdMYXN0V2l0aGRyYXduRGF0ZQgFCyR0MDQzMjc0NTkxAl8xBBF3aXRoZHJhd0xpbWl0TGVmdAgFCyR0MDQzMjc0NTkxAl8yCQCUCgIFFG5ld0xhc3RXaXRoZHJhd25EYXRlBRF3aXRoZHJhd0xpbWl0TGVmdAERdXBkYXRlVXNlckJhbGFuY2UCBV91c2VyB19jaGFuZ2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFCWtfYmFsYW5jZQUFX3VzZXIJAGQCCQEJYmFsYW5jZU9mAQUFX3VzZXIFB19jaGFuZ2UFA25pbAEUc2V0VXNlcldpdGhkcmF3TGltaXQCBV91c2VyBV9yYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBRBrX3dpdGhkcmF3X2xpbWl0BQVfdXNlcgUFX3JhdGUFA25pbAESc2V0VXNlckF2ZXJhZ2VSYXRlAgVfdXNlcgVfcmF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUOa19hdmVyYWdlX3JhdGUFBV91c2VyBQVfcmF0ZQUDbmlsARF1cGRhdGVGcmVlQmFsYW5jZQEHX2NoYW5nZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUNa19mcmVlQmFsYW5jZQkAZAIJAQtmcmVlQmFsYW5jZQAFB19jaGFuZ2UFA25pbAETdXBkYXRlTG9ja2VkQmFsYW5jZQEHX2NoYW5nZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUPa19sb2NrZWRCYWxhbmNlCQBkAgkBDWxvY2tlZEJhbGFuY2UABQdfY2hhbmdlBQNuaWwBEXVwZGF0ZVRvdGFsU3VwcGx5AQdfY2hhbmdlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ1rX3RvdGFsU3VwcGx5CQBkAgkBC3RvdGFsU3VwcGx5AAUHX2NoYW5nZQUDbmlsAQp1cGRhdGVSYXRlAQVfcmF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUGa19yYXRlBQVfcmF0ZQUDbmlsARVzZXRVc2VyV2l0aGRyYXdQYXJhbXMDBV91c2VyEV9sYXN0V2l0aGRyYXdEYXRlCl93aXRoZHJhd24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFFGtfbGFzdF93aXRoZHJhd19kYXRlBQVfdXNlcgURX2xhc3RXaXRoZHJhd0RhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFFGtfd2l0aGRyYXdfaW5fcGVyaW9kBQVfdXNlcgUKX3dpdGhkcmF3bgUDbmlsCQFpAQppbml0aWFsaXplAQxfY29vcmRpbmF0b3IDCQELaW5pdGlhbGl6ZWQACQACAQITQWxyZWFkeSBpbml0aWFsaXplZAkAzAgCCQELU3RyaW5nRW50cnkCBRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwUMX2Nvb3JkaW5hdG9yCQDMCAIJAQxCb29sZWFuRW50cnkCBQ1rX2luaXRpYWxpemVkBgUDbmlsAWkBBXN0YWtlAAQHX3N0YWtlcgkApQgBCAUBaQZjYWxsZXIEB19hbW91bnQJAQ51c2RuVG9EZWNpbWFscwEICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50AwMJAQIhPQIICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAkBCnF1b3RlQXNzZXQABgkBASEBCQELaW5pdGlhbGl6ZWQACQACAQIVSW52YWxpZCBjYWxsIHRvIHN0YWtlBAtjdXJyZW50UmF0ZQkBBHJhdGUABA9wcmV2QXZlcmFnZVJhdGUJAQthdmVyYWdlUmF0ZQEFB19zdGFrZXIEB3ZBbW91bnQJAQRkaXZkAgUHX2Ftb3VudAULY3VycmVudFJhdGUEDm5ld0F2ZXJhZ2VSYXRlCQEEZGl2ZAIJAGQCCQEEbXVsZAIFB3ZBbW91bnQFC2N1cnJlbnRSYXRlCQEEbXVsZAIJAQliYWxhbmNlT2YBBQdfc3Rha2VyBQ9wcmV2QXZlcmFnZVJhdGUJAGQCBQtjdXJyZW50UmF0ZQUPcHJldkF2ZXJhZ2VSYXRlBA9uZXdUb3RhbEJhbGFuY2UJAGQCBQd2QW1vdW50CQEJYmFsYW5jZU9mAQUHX3N0YWtlcgQQbmV3V2l0aGRyYXdMaW1pdAkBBG11bGQCBQ9uZXdUb3RhbEJhbGFuY2UFE1dJVEhEUkFXX1BFUl9QRVJJT0QEBXN0YWtlCQD8BwQJAQ5tYW5hZ2VyQWRkcmVzcwACB2RlcG9zaXQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQACQEQdXNkbkZyb21EZWNpbWFscwEFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UJAM4IAgkAzggCCQDOCAIJAM4IAgkBEXVwZGF0ZUZyZWVCYWxhbmNlAQUHX2Ftb3VudAkBEXVwZGF0ZVVzZXJCYWxhbmNlAgUHX3N0YWtlcgUHdkFtb3VudAkBEnNldFVzZXJBdmVyYWdlUmF0ZQIFB19zdGFrZXIFDm5ld0F2ZXJhZ2VSYXRlCQEUc2V0VXNlcldpdGhkcmF3TGltaXQCBQdfc3Rha2VyBRBuZXdXaXRoZHJhd0xpbWl0CQERdXBkYXRlVG90YWxTdXBwbHkBBQd2QW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBB3VuU3Rha2UBB19hbW91bnQEB19zdGFrZXIJAKUIAQgFAWkGY2FsbGVyBBJhbW91bnRPZlF1b3RlQXNzZXQJAQ51c2RuVG9EZWNpbWFscwEFB19hbW91bnQDAwkBAiE9AggFAWkIcGF5bWVudHMFA25pbAYJAQEhAQkBC2luaXRpYWxpemVkAAkAAgECF0ludmFsaWQgY2FsbCB0byB1blN0YWtlBAskdDA3NjA0Nzc0NQkBFGdldFdpdGhkcmF3TGltaXRMZWZ0AQUHX3N0YWtlcgQUbmV3TGFzdFdpdGhkcmF3bkRhdGUIBQskdDA3NjA0Nzc0NQJfMQQRd2l0aGRyYXdMaW1pdExlZnQIBQskdDA3NjA0Nzc0NQJfMgQHdkFtb3VudAkBBGRpdmQCBRJhbW91bnRPZlF1b3RlQXNzZXQJAQRyYXRlAAMJAGYCBQd2QW1vdW50BRF3aXRoZHJhd0xpbWl0TGVmdAkAAgECLEludmFsaWQgY2FsbCB0byB1blN0YWtlOiB3aXRoZHJhdyBvdmVyIGxpbWl0BBRuZXdXaXRoZHJhd25JblBlcmlvZAkAZAIJARF3aXRoZHJhd25JblBlcmlvZAEFB19zdGFrZXIFB3ZBbW91bnQDCQBmAgUSYW1vdW50T2ZRdW90ZUFzc2V0CQELZnJlZUJhbGFuY2UACQACAQIoSW52YWxpZCBjYWxsIHRvIHVuU3Rha2U6IGJhbGFuY2UgdG9vIGxvdwQHdW5zdGFrZQkA/AcECQEObWFuYWdlckFkZHJlc3MAAgh3aXRoZHJhdwkAzAgCCQDYBAEJAQpxdW90ZUFzc2V0AAkAzAgCCQEQdXNkbkZyb21EZWNpbWFscwEFEmFtb3VudE9mUXVvdGVBc3NldAUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQkAzggCCQDOCAIJAM4IAgkAzggCCQERdXBkYXRlRnJlZUJhbGFuY2UBCQEBLQEFEmFtb3VudE9mUXVvdGVBc3NldAkBEXVwZGF0ZVVzZXJCYWxhbmNlAgUHX3N0YWtlcgkBAS0BBQd2QW1vdW50CQERdXBkYXRlVG90YWxTdXBwbHkBCQEBLQEFB3ZBbW91bnQJARVzZXRVc2VyV2l0aGRyYXdQYXJhbXMDBQdfc3Rha2VyBRRuZXdMYXN0V2l0aGRyYXduRGF0ZQUUbmV3V2l0aGRyYXduSW5QZXJpb2QJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyCQEQdXNkbkZyb21EZWNpbWFscwEFEmFtb3VudE9mUXVvdGVBc3NldAkBCnF1b3RlQXNzZXQABQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEHYWRkRnJlZQAEB19hbW91bnQJAQ51c2RuVG9EZWNpbWFscwEICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50AwMDCQECIT0CCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQJAQpxdW90ZUFzc2V0AAYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQEhAQMJAQtpc1doaXRlbGlzdAEJAKUIAQgFAWkGY2FsbGVyBgkAAAIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhZJbnZhbGlkIGFkZEZyZWUgcGFyYW1zBAduZXdSYXRlAwkAZgIJAQt0b3RhbFN1cHBseQAAAAkBBGRpdmQCCQBkAgkBC2ZyZWVCYWxhbmNlAAUHX2Ftb3VudAkBC3RvdGFsU3VwcGx5AAUMREVDSU1BTF9VTklUBAd1bnN0YWtlCQD8BwQJAQ5tYW5hZ2VyQWRkcmVzcwACB2RlcG9zaXQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQACQEQdXNkbkZyb21EZWNpbWFscwEFB19hbW91bnQFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlCQDOCAIJARF1cGRhdGVGcmVlQmFsYW5jZQEFB19hbW91bnQJAQp1cGRhdGVSYXRlAQUHbmV3UmF0ZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQlhZGRMb2NrZWQABAdfYW1vdW50CQEOdXNkblRvRGVjaW1hbHMBCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAMDAwkBAiE9AggJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkCQEKcXVvdGVBc3NldAAGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEBIQEDCQELaXNXaGl0ZWxpc3QBCQClCAEIBQFpBmNhbGxlcgYJAAACCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIYSW52YWxpZCBhZGRMb2NrZWQgcGFyYW1zBAd1bnN0YWtlCQD8BwQJAQ5tYW5hZ2VyQWRkcmVzcwACB2RlcG9zaXQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnF1b3RlQXNzZXQACQEQdXNkbkZyb21EZWNpbWFscwEFB19hbW91bnQFA25pbAMJAAACBQd1bnN0YWtlBQd1bnN0YWtlCQETdXBkYXRlTG9ja2VkQmFsYW5jZQEFB19hbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEVZXhjaGFuZ2VGcmVlQW5kTG9ja2VkAQdfYW1vdW50AwMJAQEhAQkBC2luaXRpYWxpemVkAAYJAQEhAQMJAQtpc1doaXRlbGlzdAEJAKUIAQgFAWkGY2FsbGVyBgkAAAIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAiRJbnZhbGlkIGV4Y2hhbmdlRnJlZUFuZExvY2tlZCBwYXJhbXMEEmFtb3VudE9mUXVvdGVBc3NldAkBDnVzZG5Ub0RlY2ltYWxzAQUHX2Ftb3VudAQHbmV3UmF0ZQMJAGYCCQELdG90YWxTdXBwbHkAAAAJAQRkaXZkAgkAZQIJAQtmcmVlQmFsYW5jZQAFEmFtb3VudE9mUXVvdGVBc3NldAkBC3RvdGFsU3VwcGx5AAUMREVDSU1BTF9VTklUCQDOCAIJAM4IAgkBE3VwZGF0ZUxvY2tlZEJhbGFuY2UBBRJhbW91bnRPZlF1b3RlQXNzZXQJARF1cGRhdGVGcmVlQmFsYW5jZQEJAQEtAQUSYW1vdW50T2ZRdW90ZUFzc2V0CQEKdXBkYXRlUmF0ZQEFB25ld1JhdGUBaQEOd2l0aGRyYXdMb2NrZWQBB19hbW91bnQDAwMJAQEhAQkBC2luaXRpYWxpemVkAAYJAGcCAAAFB19hbW91bnQGCQEBIQEJAQtpc1doaXRlbGlzdAEJAKUIAQgFAWkGY2FsbGVyCQACAQIdSW52YWxpZCB3aXRoZHJhd0xvY2tlZCBwYXJhbXMEEmFtb3VudE9mUXVvdGVBc3NldAkBDnVzZG5Ub0RlY2ltYWxzAQUHX2Ftb3VudAQHdW5zdGFrZQkA/AcECQEObWFuYWdlckFkZHJlc3MAAgh3aXRoZHJhdwkAzAgCCQDYBAEJAQpxdW90ZUFzc2V0AAkAzAgCCQEQdXNkbkZyb21EZWNpbWFscwEFEmFtb3VudE9mUXVvdGVBc3NldAUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQkAzggCCQETdXBkYXRlTG9ja2VkQmFsYW5jZQEJAQEtAQUSYW1vdW50T2ZRdW90ZUFzc2V0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgkBEHVzZG5Gcm9tRGVjaW1hbHMBBRJhbW91bnRPZlF1b3RlQXNzZXQJAQpxdW90ZUFzc2V0AAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBC3ZpZXdfcmV3YXJkAQdfc3Rha2VyBAdiYWxhbmNlCQEJYmFsYW5jZU9mAQUHX3N0YWtlcgQPZGVwb3NpdGVkQW1vdW50CQEEbXVsZAIJAQthdmVyYWdlUmF0ZQEFB19zdGFrZXIFB2JhbGFuY2UEDWN1cnJlbnRBbW91bnQJAQRtdWxkAgkBBHJhdGUABQdiYWxhbmNlBAZlYXJuZWQJAGUCBQ1jdXJyZW50QW1vdW50BQ9kZXBvc2l0ZWRBbW91bnQJAAIBCQCkAwEFBmVhcm5lZAFpARJ2aWV3X3dpdGhkcmF3TGltaXQBB19zdGFrZXIEEXdpdGhkcmF3TGltaXRMZWZ0CAkBFGdldFdpdGhkcmF3TGltaXRMZWZ0AQUHX3N0YWtlcgJfMgQLbGltaXRJblVzZG4JARB1c2RuRnJvbURlY2ltYWxzAQkBBG11bGQCBRF3aXRoZHJhd0xpbWl0TGVmdAkBBHJhdGUACQACAQkApAMBBQtsaW1pdEluVXNkbgECdHgBBnZlcmlmeQAJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAJAQ5hZG1pblB1YmxpY0tleQDc5+Ho", "height": 2336885, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: A23uyJcPFbSeJSK1YvxF1druv295S4vMd9oPuLYTUvMJ Next: 7Sn8aJWrWUwG7L5o8ps4qXkCqXcDXAsBujNT1dxt1J8j Diff:
Old | New | Differences | |
---|---|---|---|
13 | 13 | ||
14 | 14 | let k_average_rate = "k_average_rate" | |
15 | 15 | ||
16 | - | let k_withdraw_rate = "k_withdraw_rate" | |
16 | + | let k_withdraw_limit = "k_withdraw_limit" | |
17 | + | ||
18 | + | let k_last_withdraw_date = "k_last_withdraw_date" | |
19 | + | ||
20 | + | let k_withdraw_in_period = "k_withdraw_in_period" | |
17 | 21 | ||
18 | 22 | let k_initialized = "k_initialized" | |
19 | 23 | ||
80 | 84 | else _x | |
81 | 85 | ||
82 | 86 | ||
87 | + | let WITHDRAW_PERIOD = (86400 * 1000) | |
88 | + | ||
89 | + | let WITHDRAW_PER_PERIOD = divd((1 * DECIMAL_UNIT), (4 * DECIMAL_UNIT)) | |
90 | + | ||
83 | 91 | func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k)) | |
84 | 92 | ||
85 | 93 | ||
101 | 109 | func averageRate (_staker) = int0(toCompositeKey(k_average_rate, _staker)) | |
102 | 110 | ||
103 | 111 | ||
112 | + | func withdrawLimit (_staker) = int0(toCompositeKey(k_withdraw_limit, _staker)) | |
113 | + | ||
114 | + | ||
115 | + | func withdrawnInPeriod (_staker) = int0(toCompositeKey(k_withdraw_in_period, _staker)) | |
116 | + | ||
117 | + | ||
118 | + | func lastWithdrawnDate (_staker) = int0(toCompositeKey(k_last_withdraw_date, _staker)) | |
119 | + | ||
120 | + | ||
104 | 121 | func freeBalance () = int0(k_freeBalance) | |
105 | 122 | ||
106 | 123 | ||
110 | 127 | func initialized () = valueOrElse(getBoolean(this, k_initialized), false) | |
111 | 128 | ||
112 | 129 | ||
130 | + | func getWithdrawLimitLeft (_staker) = { | |
131 | + | let currentDate = lastBlock.timestamp | |
132 | + | let lastWithdrawDate = lastWithdrawnDate(_staker) | |
133 | + | let $t043274591 = if (((currentDate - lastWithdrawDate) > WITHDRAW_PERIOD)) | |
134 | + | then $Tuple2(currentDate, withdrawLimit(_staker)) | |
135 | + | else $Tuple2(lastWithdrawDate, (withdrawLimit(_staker) - withdrawnInPeriod(_staker))) | |
136 | + | let newLastWithdrawnDate = $t043274591._1 | |
137 | + | let withdrawLimitLeft = $t043274591._2 | |
138 | + | $Tuple2(newLastWithdrawnDate, withdrawLimitLeft) | |
139 | + | } | |
140 | + | ||
141 | + | ||
113 | 142 | func updateUserBalance (_user,_change) = [IntegerEntry(toCompositeKey(k_balance, _user), (balanceOf(_user) + _change))] | |
114 | 143 | ||
115 | 144 | ||
116 | - | func updateUserAverageRate (_user,_rate) = [IntegerEntry(toCompositeKey(k_average_rate, _user), _rate)] | |
145 | + | func setUserWithdrawLimit (_user,_rate) = [IntegerEntry(toCompositeKey(k_withdraw_limit, _user), _rate)] | |
146 | + | ||
147 | + | ||
148 | + | func setUserAverageRate (_user,_rate) = [IntegerEntry(toCompositeKey(k_average_rate, _user), _rate)] | |
117 | 149 | ||
118 | 150 | ||
119 | 151 | func updateFreeBalance (_change) = [IntegerEntry(k_freeBalance, (freeBalance() + _change))] | |
128 | 160 | func updateRate (_rate) = [IntegerEntry(k_rate, _rate)] | |
129 | 161 | ||
130 | 162 | ||
163 | + | func setUserWithdrawParams (_user,_lastWithdrawDate,_withdrawn) = [IntegerEntry(toCompositeKey(k_last_withdraw_date, _user), _lastWithdrawDate), IntegerEntry(toCompositeKey(k_withdraw_in_period, _user), _withdrawn)] | |
164 | + | ||
165 | + | ||
131 | 166 | @Callable(i) | |
132 | 167 | func initialize (_coordinator) = if (initialized()) | |
133 | 168 | then throw("Already initialized") | |
138 | 173 | @Callable(i) | |
139 | 174 | func stake () = { | |
140 | 175 | let _staker = toString(i.caller) | |
141 | - | let _amount = i.payments[0].amount | |
176 | + | let _amount = usdnToDecimals(i.payments[0].amount) | |
142 | 177 | if (if ((i.payments[0].assetId != quoteAsset())) | |
143 | 178 | then true | |
144 | 179 | else !(initialized())) | |
146 | 181 | else { | |
147 | 182 | let currentRate = rate() | |
148 | 183 | let prevAverageRate = averageRate(_staker) | |
149 | - | let vAmount = divd( | |
184 | + | let vAmount = divd(_amount, currentRate) | |
150 | 185 | let newAverageRate = divd((muld(vAmount, currentRate) + muld(balanceOf(_staker), prevAverageRate)), (currentRate + prevAverageRate)) | |
151 | - | let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), _amount)]) | |
152 | - | if ((unstake == unstake)) | |
153 | - | then (((updateFreeBalance(_amount) ++ updateUserBalance(_staker, vAmount)) ++ updateUserAverageRate(_staker, newAverageRate)) ++ updateTotalSupply(vAmount)) | |
186 | + | let newTotalBalance = (vAmount + balanceOf(_staker)) | |
187 | + | let newWithdrawLimit = muld(newTotalBalance, WITHDRAW_PER_PERIOD) | |
188 | + | let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))]) | |
189 | + | if ((stake == stake)) | |
190 | + | then ((((updateFreeBalance(_amount) ++ updateUserBalance(_staker, vAmount)) ++ setUserAverageRate(_staker, newAverageRate)) ++ setUserWithdrawLimit(_staker, newWithdrawLimit)) ++ updateTotalSupply(vAmount)) | |
154 | 191 | else throw("Strict value is not equal to itself.") | |
155 | 192 | } | |
156 | 193 | } | |
158 | 195 | ||
159 | 196 | ||
160 | 197 | @Callable(i) | |
161 | - | func unStake (_ | |
198 | + | func unStake (_amount) = { | |
162 | 199 | let _staker = toString(i.caller) | |
163 | - | if (if (if ((_vAmount > balanceOf(_staker))) | |
164 | - | then true | |
165 | - | else (i.payments != nil)) | |
200 | + | let amountOfQuoteAsset = usdnToDecimals(_amount) | |
201 | + | if (if ((i.payments != nil)) | |
166 | 202 | then true | |
167 | 203 | else !(initialized())) | |
168 | 204 | then throw("Invalid call to unStake") | |
169 | 205 | else { | |
170 | - | let amountOfQuoteAsset = muld(_vAmount, rate()) | |
171 | - | if ((freeBalance() > amountOfQuoteAsset)) | |
172 | - | then throw("Balance to low") | |
206 | + | let $t076047745 = getWithdrawLimitLeft(_staker) | |
207 | + | let newLastWithdrawnDate = $t076047745._1 | |
208 | + | let withdrawLimitLeft = $t076047745._2 | |
209 | + | let vAmount = divd(amountOfQuoteAsset, rate()) | |
210 | + | if ((vAmount > withdrawLimitLeft)) | |
211 | + | then throw("Invalid call to unStake: withdraw over limit") | |
173 | 212 | else { | |
174 | - | let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), usdnFromDecimals(amountOfQuoteAsset)], nil) | |
175 | - | if ((unstake == unstake)) | |
176 | - | then (((updateFreeBalance(-(amountOfQuoteAsset)) ++ updateUserBalance(_staker, -(_vAmount))) ++ updateTotalSupply(-(_vAmount))) ++ [ScriptTransfer(i.caller, usdnFromDecimals(amountOfQuoteAsset), quoteAsset())]) | |
177 | - | else throw("Strict value is not equal to itself.") | |
213 | + | let newWithdrawnInPeriod = (withdrawnInPeriod(_staker) + vAmount) | |
214 | + | if ((amountOfQuoteAsset > freeBalance())) | |
215 | + | then throw("Invalid call to unStake: balance too low") | |
216 | + | else { | |
217 | + | let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), usdnFromDecimals(amountOfQuoteAsset)], nil) | |
218 | + | if ((unstake == unstake)) | |
219 | + | then ((((updateFreeBalance(-(amountOfQuoteAsset)) ++ updateUserBalance(_staker, -(vAmount))) ++ updateTotalSupply(-(vAmount))) ++ setUserWithdrawParams(_staker, newLastWithdrawnDate, newWithdrawnInPeriod)) ++ [ScriptTransfer(i.caller, usdnFromDecimals(amountOfQuoteAsset), quoteAsset())]) | |
220 | + | else throw("Strict value is not equal to itself.") | |
221 | + | } | |
178 | 222 | } | |
179 | 223 | } | |
180 | 224 | } | |
183 | 227 | ||
184 | 228 | @Callable(i) | |
185 | 229 | func addFree () = { | |
186 | - | let _amount = i.payments[0].amount | |
230 | + | let _amount = usdnToDecimals(i.payments[0].amount) | |
187 | 231 | if (if (if ((i.payments[0].assetId != quoteAsset())) | |
188 | 232 | then true | |
189 | 233 | else !(initialized())) | |
193 | 237 | else (i.caller == adminAddress()))) | |
194 | 238 | then throw("Invalid addFree params") | |
195 | 239 | else { | |
196 | - | let amountOfQuoteAsset = usdnToDecimals(_amount) | |
197 | 240 | let newRate = if ((totalSupply() > 0)) | |
198 | - | then divd((freeBalance() + | |
241 | + | then divd((freeBalance() + _amount), totalSupply()) | |
199 | 242 | else DECIMAL_UNIT | |
200 | - | let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), _amount)]) | |
243 | + | let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))]) | |
201 | 244 | if ((unstake == unstake)) | |
202 | - | then (updateFreeBalance( | |
245 | + | then (updateFreeBalance(_amount) ++ updateRate(newRate)) | |
203 | 246 | else throw("Strict value is not equal to itself.") | |
204 | 247 | } | |
205 | 248 | } | |
208 | 251 | ||
209 | 252 | @Callable(i) | |
210 | 253 | func addLocked () = { | |
211 | - | let _amount = i.payments[0].amount | |
254 | + | let _amount = usdnToDecimals(i.payments[0].amount) | |
212 | 255 | if (if (if ((i.payments[0].assetId != quoteAsset())) | |
213 | 256 | then true | |
214 | 257 | else !(initialized())) | |
218 | 261 | else (i.caller == adminAddress()))) | |
219 | 262 | then throw("Invalid addLocked params") | |
220 | 263 | else { | |
221 | - | let amountOfQuoteAsset = usdnToDecimals(_amount) | |
222 | - | let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), _amount)]) | |
264 | + | let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))]) | |
223 | 265 | if ((unstake == unstake)) | |
224 | - | then updateLockedBalance( | |
266 | + | then updateLockedBalance(_amount) | |
225 | 267 | else throw("Strict value is not equal to itself.") | |
226 | 268 | } | |
227 | 269 | } | |
254 | 296 | then throw("Invalid withdrawLocked params") | |
255 | 297 | else { | |
256 | 298 | let amountOfQuoteAsset = usdnToDecimals(_amount) | |
257 | - | let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), | |
299 | + | let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), usdnFromDecimals(amountOfQuoteAsset)], nil) | |
258 | 300 | if ((unstake == unstake)) | |
259 | - | then (updateLockedBalance(-(amountOfQuoteAsset)) ++ [ScriptTransfer(i.caller, | |
301 | + | then (updateLockedBalance(-(amountOfQuoteAsset)) ++ [ScriptTransfer(i.caller, usdnFromDecimals(amountOfQuoteAsset), quoteAsset())]) | |
260 | 302 | else throw("Strict value is not equal to itself.") | |
261 | 303 | } | |
262 | 304 | ||
263 | 305 | ||
264 | 306 | ||
265 | 307 | @Callable(i) | |
266 | - | func view_reward (_ | |
267 | - | let balance = balanceOf(_ | |
268 | - | let depositedAmount = muld(averageRate(_ | |
308 | + | func view_reward (_staker) = { | |
309 | + | let balance = balanceOf(_staker) | |
310 | + | let depositedAmount = muld(averageRate(_staker), balance) | |
269 | 311 | let currentAmount = muld(rate(), balance) | |
270 | 312 | let earned = (currentAmount - depositedAmount) | |
271 | 313 | throw(toString(earned)) | |
314 | + | } | |
315 | + | ||
316 | + | ||
317 | + | ||
318 | + | @Callable(i) | |
319 | + | func view_withdrawLimit (_staker) = { | |
320 | + | let withdrawLimitLeft = getWithdrawLimitLeft(_staker)._2 | |
321 | + | let limitInUsdn = usdnFromDecimals(muld(withdrawLimitLeft, rate())) | |
322 | + | throw(toString(limitInUsdn)) | |
272 | 323 | } | |
273 | 324 | ||
274 | 325 |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let k_totalSupply = "k_totalSupply" | |
5 | 5 | ||
6 | 6 | let k_lockedBalance = "k_lockedBalance" | |
7 | 7 | ||
8 | 8 | let k_freeBalance = "k_freeBalance" | |
9 | 9 | ||
10 | 10 | let k_rate = "k_rate" | |
11 | 11 | ||
12 | 12 | let k_balance = "k_balance" | |
13 | 13 | ||
14 | 14 | let k_average_rate = "k_average_rate" | |
15 | 15 | ||
16 | - | let k_withdraw_rate = "k_withdraw_rate" | |
16 | + | let k_withdraw_limit = "k_withdraw_limit" | |
17 | + | ||
18 | + | let k_last_withdraw_date = "k_last_withdraw_date" | |
19 | + | ||
20 | + | let k_withdraw_in_period = "k_withdraw_in_period" | |
17 | 21 | ||
18 | 22 | let k_initialized = "k_initialized" | |
19 | 23 | ||
20 | 24 | let k_coordinatorAddress = "k_coordinatorAddress" | |
21 | 25 | ||
22 | 26 | let k_amm = "k_amm" | |
23 | 27 | ||
24 | 28 | let k_quote_asset = "k_quote_asset" | |
25 | 29 | ||
26 | 30 | let k_admin_public_key = "k_admin_public_key" | |
27 | 31 | ||
28 | 32 | let k_admin_address = "k_admin_address" | |
29 | 33 | ||
30 | 34 | let k_manager_address = "k_manager_address" | |
31 | 35 | ||
32 | 36 | func toCompositeKey (_key,_address) = ((_key + "_") + _address) | |
33 | 37 | ||
34 | 38 | ||
35 | 39 | func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set") | |
36 | 40 | ||
37 | 41 | ||
38 | 42 | func isWhitelist (_address) = valueOrElse(getBoolean(coordinator(), toCompositeKey(k_amm, _address)), false) | |
39 | 43 | ||
40 | 44 | ||
41 | 45 | func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key)) | |
42 | 46 | ||
43 | 47 | ||
44 | 48 | func adminAddress () = addressFromString(valueOrErrorMessage(getString(coordinator(), k_admin_address), "Admin address not set")) | |
45 | 49 | ||
46 | 50 | ||
47 | 51 | func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset)) | |
48 | 52 | ||
49 | 53 | ||
50 | 54 | func managerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_manager_address)), "Manager not set") | |
51 | 55 | ||
52 | 56 | ||
53 | 57 | let DECIMAL_UNIT = (1 * (((((((10 * 10) * 10) * 10) * 10) * 10) * 10) * 10)) | |
54 | 58 | ||
55 | 59 | let DURATION = ((60 * 60) * 24) | |
56 | 60 | ||
57 | 61 | let NO_ADDRESS = "" | |
58 | 62 | ||
59 | 63 | let NO_STAKER = 0 | |
60 | 64 | ||
61 | 65 | func usdnFromDecimals (_amount) = (_amount / 100) | |
62 | 66 | ||
63 | 67 | ||
64 | 68 | func usdnToDecimals (_amount) = (_amount * 100) | |
65 | 69 | ||
66 | 70 | ||
67 | 71 | func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN) | |
68 | 72 | ||
69 | 73 | ||
70 | 74 | func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN) | |
71 | 75 | ||
72 | 76 | ||
73 | 77 | func abs (_x) = if ((_x > 0)) | |
74 | 78 | then _x | |
75 | 79 | else -(_x) | |
76 | 80 | ||
77 | 81 | ||
78 | 82 | func minv (_x,_y) = if ((_x > _y)) | |
79 | 83 | then _y | |
80 | 84 | else _x | |
81 | 85 | ||
82 | 86 | ||
87 | + | let WITHDRAW_PERIOD = (86400 * 1000) | |
88 | + | ||
89 | + | let WITHDRAW_PER_PERIOD = divd((1 * DECIMAL_UNIT), (4 * DECIMAL_UNIT)) | |
90 | + | ||
83 | 91 | func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k)) | |
84 | 92 | ||
85 | 93 | ||
86 | 94 | func int0 (k) = valueOrElse(getInteger(this, k), 0) | |
87 | 95 | ||
88 | 96 | ||
89 | 97 | func int1 (k) = valueOrElse(getInteger(this, k), DECIMAL_UNIT) | |
90 | 98 | ||
91 | 99 | ||
92 | 100 | func totalSupply () = int0(k_totalSupply) | |
93 | 101 | ||
94 | 102 | ||
95 | 103 | func rate () = int1(k_rate) | |
96 | 104 | ||
97 | 105 | ||
98 | 106 | func balanceOf (_staker) = int0(toCompositeKey(k_balance, _staker)) | |
99 | 107 | ||
100 | 108 | ||
101 | 109 | func averageRate (_staker) = int0(toCompositeKey(k_average_rate, _staker)) | |
102 | 110 | ||
103 | 111 | ||
112 | + | func withdrawLimit (_staker) = int0(toCompositeKey(k_withdraw_limit, _staker)) | |
113 | + | ||
114 | + | ||
115 | + | func withdrawnInPeriod (_staker) = int0(toCompositeKey(k_withdraw_in_period, _staker)) | |
116 | + | ||
117 | + | ||
118 | + | func lastWithdrawnDate (_staker) = int0(toCompositeKey(k_last_withdraw_date, _staker)) | |
119 | + | ||
120 | + | ||
104 | 121 | func freeBalance () = int0(k_freeBalance) | |
105 | 122 | ||
106 | 123 | ||
107 | 124 | func lockedBalance () = int0(k_lockedBalance) | |
108 | 125 | ||
109 | 126 | ||
110 | 127 | func initialized () = valueOrElse(getBoolean(this, k_initialized), false) | |
111 | 128 | ||
112 | 129 | ||
130 | + | func getWithdrawLimitLeft (_staker) = { | |
131 | + | let currentDate = lastBlock.timestamp | |
132 | + | let lastWithdrawDate = lastWithdrawnDate(_staker) | |
133 | + | let $t043274591 = if (((currentDate - lastWithdrawDate) > WITHDRAW_PERIOD)) | |
134 | + | then $Tuple2(currentDate, withdrawLimit(_staker)) | |
135 | + | else $Tuple2(lastWithdrawDate, (withdrawLimit(_staker) - withdrawnInPeriod(_staker))) | |
136 | + | let newLastWithdrawnDate = $t043274591._1 | |
137 | + | let withdrawLimitLeft = $t043274591._2 | |
138 | + | $Tuple2(newLastWithdrawnDate, withdrawLimitLeft) | |
139 | + | } | |
140 | + | ||
141 | + | ||
113 | 142 | func updateUserBalance (_user,_change) = [IntegerEntry(toCompositeKey(k_balance, _user), (balanceOf(_user) + _change))] | |
114 | 143 | ||
115 | 144 | ||
116 | - | func updateUserAverageRate (_user,_rate) = [IntegerEntry(toCompositeKey(k_average_rate, _user), _rate)] | |
145 | + | func setUserWithdrawLimit (_user,_rate) = [IntegerEntry(toCompositeKey(k_withdraw_limit, _user), _rate)] | |
146 | + | ||
147 | + | ||
148 | + | func setUserAverageRate (_user,_rate) = [IntegerEntry(toCompositeKey(k_average_rate, _user), _rate)] | |
117 | 149 | ||
118 | 150 | ||
119 | 151 | func updateFreeBalance (_change) = [IntegerEntry(k_freeBalance, (freeBalance() + _change))] | |
120 | 152 | ||
121 | 153 | ||
122 | 154 | func updateLockedBalance (_change) = [IntegerEntry(k_lockedBalance, (lockedBalance() + _change))] | |
123 | 155 | ||
124 | 156 | ||
125 | 157 | func updateTotalSupply (_change) = [IntegerEntry(k_totalSupply, (totalSupply() + _change))] | |
126 | 158 | ||
127 | 159 | ||
128 | 160 | func updateRate (_rate) = [IntegerEntry(k_rate, _rate)] | |
129 | 161 | ||
130 | 162 | ||
163 | + | func setUserWithdrawParams (_user,_lastWithdrawDate,_withdrawn) = [IntegerEntry(toCompositeKey(k_last_withdraw_date, _user), _lastWithdrawDate), IntegerEntry(toCompositeKey(k_withdraw_in_period, _user), _withdrawn)] | |
164 | + | ||
165 | + | ||
131 | 166 | @Callable(i) | |
132 | 167 | func initialize (_coordinator) = if (initialized()) | |
133 | 168 | then throw("Already initialized") | |
134 | 169 | else [StringEntry(k_coordinatorAddress, _coordinator), BooleanEntry(k_initialized, true)] | |
135 | 170 | ||
136 | 171 | ||
137 | 172 | ||
138 | 173 | @Callable(i) | |
139 | 174 | func stake () = { | |
140 | 175 | let _staker = toString(i.caller) | |
141 | - | let _amount = i.payments[0].amount | |
176 | + | let _amount = usdnToDecimals(i.payments[0].amount) | |
142 | 177 | if (if ((i.payments[0].assetId != quoteAsset())) | |
143 | 178 | then true | |
144 | 179 | else !(initialized())) | |
145 | 180 | then throw("Invalid call to stake") | |
146 | 181 | else { | |
147 | 182 | let currentRate = rate() | |
148 | 183 | let prevAverageRate = averageRate(_staker) | |
149 | - | let vAmount = divd( | |
184 | + | let vAmount = divd(_amount, currentRate) | |
150 | 185 | let newAverageRate = divd((muld(vAmount, currentRate) + muld(balanceOf(_staker), prevAverageRate)), (currentRate + prevAverageRate)) | |
151 | - | let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), _amount)]) | |
152 | - | if ((unstake == unstake)) | |
153 | - | then (((updateFreeBalance(_amount) ++ updateUserBalance(_staker, vAmount)) ++ updateUserAverageRate(_staker, newAverageRate)) ++ updateTotalSupply(vAmount)) | |
186 | + | let newTotalBalance = (vAmount + balanceOf(_staker)) | |
187 | + | let newWithdrawLimit = muld(newTotalBalance, WITHDRAW_PER_PERIOD) | |
188 | + | let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))]) | |
189 | + | if ((stake == stake)) | |
190 | + | then ((((updateFreeBalance(_amount) ++ updateUserBalance(_staker, vAmount)) ++ setUserAverageRate(_staker, newAverageRate)) ++ setUserWithdrawLimit(_staker, newWithdrawLimit)) ++ updateTotalSupply(vAmount)) | |
154 | 191 | else throw("Strict value is not equal to itself.") | |
155 | 192 | } | |
156 | 193 | } | |
157 | 194 | ||
158 | 195 | ||
159 | 196 | ||
160 | 197 | @Callable(i) | |
161 | - | func unStake (_ | |
198 | + | func unStake (_amount) = { | |
162 | 199 | let _staker = toString(i.caller) | |
163 | - | if (if (if ((_vAmount > balanceOf(_staker))) | |
164 | - | then true | |
165 | - | else (i.payments != nil)) | |
200 | + | let amountOfQuoteAsset = usdnToDecimals(_amount) | |
201 | + | if (if ((i.payments != nil)) | |
166 | 202 | then true | |
167 | 203 | else !(initialized())) | |
168 | 204 | then throw("Invalid call to unStake") | |
169 | 205 | else { | |
170 | - | let amountOfQuoteAsset = muld(_vAmount, rate()) | |
171 | - | if ((freeBalance() > amountOfQuoteAsset)) | |
172 | - | then throw("Balance to low") | |
206 | + | let $t076047745 = getWithdrawLimitLeft(_staker) | |
207 | + | let newLastWithdrawnDate = $t076047745._1 | |
208 | + | let withdrawLimitLeft = $t076047745._2 | |
209 | + | let vAmount = divd(amountOfQuoteAsset, rate()) | |
210 | + | if ((vAmount > withdrawLimitLeft)) | |
211 | + | then throw("Invalid call to unStake: withdraw over limit") | |
173 | 212 | else { | |
174 | - | let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), usdnFromDecimals(amountOfQuoteAsset)], nil) | |
175 | - | if ((unstake == unstake)) | |
176 | - | then (((updateFreeBalance(-(amountOfQuoteAsset)) ++ updateUserBalance(_staker, -(_vAmount))) ++ updateTotalSupply(-(_vAmount))) ++ [ScriptTransfer(i.caller, usdnFromDecimals(amountOfQuoteAsset), quoteAsset())]) | |
177 | - | else throw("Strict value is not equal to itself.") | |
213 | + | let newWithdrawnInPeriod = (withdrawnInPeriod(_staker) + vAmount) | |
214 | + | if ((amountOfQuoteAsset > freeBalance())) | |
215 | + | then throw("Invalid call to unStake: balance too low") | |
216 | + | else { | |
217 | + | let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), usdnFromDecimals(amountOfQuoteAsset)], nil) | |
218 | + | if ((unstake == unstake)) | |
219 | + | then ((((updateFreeBalance(-(amountOfQuoteAsset)) ++ updateUserBalance(_staker, -(vAmount))) ++ updateTotalSupply(-(vAmount))) ++ setUserWithdrawParams(_staker, newLastWithdrawnDate, newWithdrawnInPeriod)) ++ [ScriptTransfer(i.caller, usdnFromDecimals(amountOfQuoteAsset), quoteAsset())]) | |
220 | + | else throw("Strict value is not equal to itself.") | |
221 | + | } | |
178 | 222 | } | |
179 | 223 | } | |
180 | 224 | } | |
181 | 225 | ||
182 | 226 | ||
183 | 227 | ||
184 | 228 | @Callable(i) | |
185 | 229 | func addFree () = { | |
186 | - | let _amount = i.payments[0].amount | |
230 | + | let _amount = usdnToDecimals(i.payments[0].amount) | |
187 | 231 | if (if (if ((i.payments[0].assetId != quoteAsset())) | |
188 | 232 | then true | |
189 | 233 | else !(initialized())) | |
190 | 234 | then true | |
191 | 235 | else !(if (isWhitelist(toString(i.caller))) | |
192 | 236 | then true | |
193 | 237 | else (i.caller == adminAddress()))) | |
194 | 238 | then throw("Invalid addFree params") | |
195 | 239 | else { | |
196 | - | let amountOfQuoteAsset = usdnToDecimals(_amount) | |
197 | 240 | let newRate = if ((totalSupply() > 0)) | |
198 | - | then divd((freeBalance() + | |
241 | + | then divd((freeBalance() + _amount), totalSupply()) | |
199 | 242 | else DECIMAL_UNIT | |
200 | - | let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), _amount)]) | |
243 | + | let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))]) | |
201 | 244 | if ((unstake == unstake)) | |
202 | - | then (updateFreeBalance( | |
245 | + | then (updateFreeBalance(_amount) ++ updateRate(newRate)) | |
203 | 246 | else throw("Strict value is not equal to itself.") | |
204 | 247 | } | |
205 | 248 | } | |
206 | 249 | ||
207 | 250 | ||
208 | 251 | ||
209 | 252 | @Callable(i) | |
210 | 253 | func addLocked () = { | |
211 | - | let _amount = i.payments[0].amount | |
254 | + | let _amount = usdnToDecimals(i.payments[0].amount) | |
212 | 255 | if (if (if ((i.payments[0].assetId != quoteAsset())) | |
213 | 256 | then true | |
214 | 257 | else !(initialized())) | |
215 | 258 | then true | |
216 | 259 | else !(if (isWhitelist(toString(i.caller))) | |
217 | 260 | then true | |
218 | 261 | else (i.caller == adminAddress()))) | |
219 | 262 | then throw("Invalid addLocked params") | |
220 | 263 | else { | |
221 | - | let amountOfQuoteAsset = usdnToDecimals(_amount) | |
222 | - | let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), _amount)]) | |
264 | + | let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))]) | |
223 | 265 | if ((unstake == unstake)) | |
224 | - | then updateLockedBalance( | |
266 | + | then updateLockedBalance(_amount) | |
225 | 267 | else throw("Strict value is not equal to itself.") | |
226 | 268 | } | |
227 | 269 | } | |
228 | 270 | ||
229 | 271 | ||
230 | 272 | ||
231 | 273 | @Callable(i) | |
232 | 274 | func exchangeFreeAndLocked (_amount) = if (if (!(initialized())) | |
233 | 275 | then true | |
234 | 276 | else !(if (isWhitelist(toString(i.caller))) | |
235 | 277 | then true | |
236 | 278 | else (i.caller == adminAddress()))) | |
237 | 279 | then throw("Invalid exchangeFreeAndLocked params") | |
238 | 280 | else { | |
239 | 281 | let amountOfQuoteAsset = usdnToDecimals(_amount) | |
240 | 282 | let newRate = if ((totalSupply() > 0)) | |
241 | 283 | then divd((freeBalance() - amountOfQuoteAsset), totalSupply()) | |
242 | 284 | else DECIMAL_UNIT | |
243 | 285 | ((updateLockedBalance(amountOfQuoteAsset) ++ updateFreeBalance(-(amountOfQuoteAsset))) ++ updateRate(newRate)) | |
244 | 286 | } | |
245 | 287 | ||
246 | 288 | ||
247 | 289 | ||
248 | 290 | @Callable(i) | |
249 | 291 | func withdrawLocked (_amount) = if (if (if (!(initialized())) | |
250 | 292 | then true | |
251 | 293 | else (0 >= _amount)) | |
252 | 294 | then true | |
253 | 295 | else !(isWhitelist(toString(i.caller)))) | |
254 | 296 | then throw("Invalid withdrawLocked params") | |
255 | 297 | else { | |
256 | 298 | let amountOfQuoteAsset = usdnToDecimals(_amount) | |
257 | - | let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), | |
299 | + | let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), usdnFromDecimals(amountOfQuoteAsset)], nil) | |
258 | 300 | if ((unstake == unstake)) | |
259 | - | then (updateLockedBalance(-(amountOfQuoteAsset)) ++ [ScriptTransfer(i.caller, | |
301 | + | then (updateLockedBalance(-(amountOfQuoteAsset)) ++ [ScriptTransfer(i.caller, usdnFromDecimals(amountOfQuoteAsset), quoteAsset())]) | |
260 | 302 | else throw("Strict value is not equal to itself.") | |
261 | 303 | } | |
262 | 304 | ||
263 | 305 | ||
264 | 306 | ||
265 | 307 | @Callable(i) | |
266 | - | func view_reward (_ | |
267 | - | let balance = balanceOf(_ | |
268 | - | let depositedAmount = muld(averageRate(_ | |
308 | + | func view_reward (_staker) = { | |
309 | + | let balance = balanceOf(_staker) | |
310 | + | let depositedAmount = muld(averageRate(_staker), balance) | |
269 | 311 | let currentAmount = muld(rate(), balance) | |
270 | 312 | let earned = (currentAmount - depositedAmount) | |
271 | 313 | throw(toString(earned)) | |
314 | + | } | |
315 | + | ||
316 | + | ||
317 | + | ||
318 | + | @Callable(i) | |
319 | + | func view_withdrawLimit (_staker) = { | |
320 | + | let withdrawLimitLeft = getWithdrawLimitLeft(_staker)._2 | |
321 | + | let limitInUsdn = usdnFromDecimals(muld(withdrawLimitLeft, rate())) | |
322 | + | throw(toString(limitInUsdn)) | |
272 | 323 | } | |
273 | 324 | ||
274 | 325 | ||
275 | 326 | @Verifier(tx) | |
276 | 327 | func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey()) | |
277 | 328 |
github/deemru/w8io/169f3d6 54.36 ms ◑