tx · 57ua4u22SQs3cUXMUhy785myJZiou6kKvwHSKr7FQKxb

3NBG2Nuz2cjtG8wWcKLBGZ1bBpveU56gp77:  -0.04000000 Waves

2021.09.05 03:17 [1689008] smart account 3NBG2Nuz2cjtG8wWcKLBGZ1bBpveU56gp77 > SELF 0.00000000 Waves

{ "type": 13, "id": "57ua4u22SQs3cUXMUhy785myJZiou6kKvwHSKr7FQKxb", "fee": 4000000, "feeAssetId": null, "timestamp": 1630801088173, "version": 2, "chainId": 84, "sender": "3NBG2Nuz2cjtG8wWcKLBGZ1bBpveU56gp77", "senderPublicKey": "B565vUqaobfDQJcgjUnNdsSqnqWfRsAQDBb1JeciPWtP", "proofs": [ "pPPahyD4onHjy4ezpvuxy5ANKy5R4mqptm7nm4icPEMMxhkph6m5ZoRsGNMyqZUt6qHvbjdMLJcxLYX2R3a9jW6" ], "script": "base64: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VG9rZW5TdXBwbHkJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkABBoAAAACBQAAAAR0aGlzAgAAAAxkVG9rZW5TdXBwbHkCAAAAHU5vIGtleSBkVG9rZW5TdXBwbHkgd2FzIGZvdW5kAAAAAA5kVG9rZW5EZWNpbWFscwkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEGgAAAAIFAAAABHRoaXMCAAAADmRUb2tlbkRlY2ltYWxzAgAAAB9ObyBrZXkgZFRva2VuRGVjaW1hbHMgd2FzIGZvdW5kAAAAAAhkVG9rZW5JZAkBAAAAE3ZhbHVlT3JFcnJvck1lc3NhZ2UAAAACCQAEHQAAAAIFAAAABHRoaXMCAAAACGRUb2tlbklkAgAAABlObyBrZXkgZFRva2VuSWQgd2FzIGZvdW5kAAAAAApkVG9rZW5OYW1lCQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwIAAAAKZFRva2VuTmFtZQIAAAAbTm8ga2V5IGRUb2tlbk5hbWUgd2FzIGZvdW5kAAAAAAxzdG9yZWRIZWlnaHQJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQaAAAAAgUAAAAEdGhpcwIAAAAMc3RvcmVkSGVpZ2h0BQAAAAZoZWlnaHQAAAAAC3N0b3JlZEluZGV4CQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMCAAAAC3N0b3JlZEluZGV4AAAjhvJvwQAAAQAAAA5pc0FkbWluQWRkcmVzcwAAAAEAAAAHYWRkcmVzcwMJAAAAAAAAAgkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAAFYWRtaW4FAAAAB2FkZHJlc3MGBwEAAAANaXNXYXZldHJvbGxlcgAAAAEAAAAHYWRkcmVzcwMJAAAAAAAAAgkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQUAAAALd2F2ZXRyb2xsZXIFAAAAB2FkZHJlc3MGBwEAAAATaXNBY2NlcHRhYmxlQXNzZXRJZAAAAAEAAAAHYXNzZXRJZAMJAAAAAAAAAgUAAAAHYXNzZXRJZAUAAAAKYXNzZXRJZFN1YgYHAQAAAAt3cml0ZVN0cmluZwAAAAIAAAADa2V5AAAAC3N0cmluZ1ZhbHVlCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAANrZXkFAAAAC3N0cmluZ1ZhbHVlAQAAAAx3cml0ZUludGVnZXIAAAACAAAAA2tleQAAAAxpbnRlZ2VyVmFsdWUJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAANrZXkFAAAADGludGVnZXJWYWx1ZQEAAAARdXNlcmxvY2tlZEJhbGFuY2UAAAABAAAAC3VzZXJBZGRyZXNzCQEAAAALdmFsdWVPckVsc2UAAAACCQAEGgAAAAIFAAAABHRoaXMJAAEsAAAAAgUAAAALdXNlckFkZHJlc3MCAAAAB19sb2NrZWQAAAAAAAAAAAAAAAAAC3V0aWxpemF0aW9uAwkAAGYAAAACBQAAAAt0b3RhbFN1cHBseQAAAAAAAAAAAAkAAGsAAAADBQAAAAt0b3RhbEJvcnJvdwUAAAAKYmFzZUZhY3RvcgUAAAALdG90YWxTdXBwbHkAAAAAAAAAAAAAAAAAA2FwcgQAAAAIbWluVmFsdWUJAARMAAAAAgUAAAALdXRpbGl6YXRpb24JAARMAAAAAgUAAAAEa2luawUAAAADbmlsBAAAAAxtaW5WYWx1ZUl0ZW0JAAGXAAAAAQUAAAAIbWluVmFsdWUEAAAACG1heFZhbHVlCQAETAAAAAIAAAAAAAAAAAAJAARMAAAAAgkAAGUAAAACBQAAAAt1dGlsaXphdGlvbgUAAAAEa2luawUAAAADbmlsBAAAAAxtYXhWYWx1ZUl0ZW0JAAGWAAAAAQUAAAAIbWF4VmFsdWUJAABkAAAAAgkAAGQAAAACCQAAawAAAAMFAAAACm11bHRpcGxpZXIFAAAADG1pblZhbHVlSXRlbQUAAAAKYmFzZUZhY3RvcgkAAGsAAAADBQAAAA5qdW1wTXVsdGlwbGllcgUAAAAMbWF4VmFsdWVJdGVtBQAAAApiYXNlRmFjdG9yBQAAAAhiYXNlUmF0ZQAAAAADYXB5CQAAawAAAAMJAABrAAAAAwUAAAADYXByBQAAAAt1dGlsaXphdGlvbgUAAAAKYmFzZUZhY3RvcgkAAGUAAAACBQAAAApiYXNlRmFjdG9yBQAAAA1yZXNlcnZlRmFjdG9yBQAAAApiYXNlRmFjdG9yAAAAABJib3Jyb3dSYXRlUGVyQmxvY2sJAABrAAAAAwUAAAADYXByBQAAAAliYXNlSW5kZXgJAABoAAAAAgUAAAANYmxvY2tzUGVyWWVhcgUAAAAKYmFzZUZhY3RvcgAAAAALZGVsdGFCbG9ja3MJAABlAAAAAgUAAAAGaGVpZ2h0BQAAAAxzdG9yZWRIZWlnaHQAAAAADGN1cnJlbnRJbmRleAkBAAAACGZyYWN0aW9uAAAABAUAAAALc3RvcmVkSW5kZXgJAABkAAAAAgUAAAAJYmFzZUluZGV4CQAAaAAAAAIFAAAAEmJvcnJvd1JhdGVQZXJCbG9jawUAAAALZGVsdGFCbG9ja3MFAAAACWJhc2VJbmRleAUAAAAHQ0VJTElORwAAAAASY3VycmVudFRvdGFsQm9ycm93CQAAawAAAAMFAAAAC3RvdGFsQm9ycm93BQAAAAxjdXJyZW50SW5kZXgFAAAAC3N0b3JlZEluZGV4AAAAABFjb2xsZWN0ZWRJbnRlcmVzdAkAAGsAAAADBQAAAAt0b3RhbEJvcnJvdwkAAGgAAAACBQAAABJib3Jyb3dSYXRlUGVyQmxvY2sFAAAAC2RlbHRhQmxvY2tzBQAAAAliYXNlSW5kZXgAAAAAEmN1cnJlbnRUb3RhbFN1cHBseQkAAGQAAAACBQAAAAt0b3RhbFN1cHBseQkAAGsAAAADCQAAZQAAAAIFAAAACmJhc2VGYWN0b3IFAAAADXJlc2VydmVGYWN0b3IFAAAAEWNvbGxlY3RlZEludGVyZXN0BQAAAApiYXNlRmFjdG9yAAAAAA5jdXJyZW50UmVzZXJ2ZQkAAGQAAAACBQAAAAx0b3RhbFJlc2VydmUJAABrAAAAAwUAAAANcmVzZXJ2ZUZhY3RvcgUAAAARY29sbGVjdGVkSW50ZXJlc3QFAAAACmJhc2VGYWN0b3IAAAAADGV4Y2hhbmdlUmF0ZQMJAABmAAAAAgUAAAAMZFRva2VuU3VwcGx5AAAAAAAAAAAABAAAAAhleHBvbmVudAkAAGQAAAACCQAAZQAAAAIAAAAAAAAAABIFAAAADmRUb2tlbkRlY2ltYWxzBQAAAA1hc3NldERlY2ltYWxzBAAAAAhtYW50aXNzYQkAAGwAAAAGAAAAAAAAAAAKAAAAAAAAAAAABQAAAAhleHBvbmVudAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAHQ0VJTElORwkAAGsAAAADBQAAABJjdXJyZW50VG90YWxTdXBwbHkFAAAACG1hbnRpc3NhBQAAAAxkVG9rZW5TdXBwbHkFAAAAEGJhc2VFeGNoYW5nZVJhdGUBAAAAEGNhbGNEVG9rZW5BbW91bnQAAAABAAAAC2Fzc2V0QW1vdW50BAAAAAhleHBvbmVudAkAAGQAAAACCQAAZQAAAAIAAAAAAAAAABIFAAAADmRUb2tlbkRlY2ltYWxzBQAAAA1hc3NldERlY2ltYWxzBAAAAAhtYW50aXNzYQkAAGwAAAAGAAAAAAAAAAAKAAAAAAAAAAAABQAAAAhleHBvbmVudAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAHQ0VJTElORwkAAGsAAAADBQAAAAthc3NldEFtb3VudAUAAAAIbWFudGlzc2EFAAAADGV4Y2hhbmdlUmF0ZQEAAAAPY2FsY0Fzc2V0QW1vdW50AAAAAQAAAAxkVG9rZW5BbW91bnQEAAAACGV4cG9uZW50CQAAZAAAAAIJAABlAAAAAgAAAAAAAAAAEgUAAAAOZFRva2VuRGVjaW1hbHMFAAAADWFzc2V0RGVjaW1hbHMEAAAACG1hbnRpc3NhCQAAbAAAAAYAAAAAAAAAAAoAAAAAAAAAAAAFAAAACGV4cG9uZW50AAAAAAAAAAAAAAAAAAAAAAAABQAAAAdDRUlMSU5HCQAAawAAAAMFAAAADGRUb2tlbkFtb3VudAUAAAAMZXhjaGFuZ2VSYXRlBQAAAAhtYW50aXNzYQEAAAAUZ2V0Q3VycmVudFVzZXJCb3Jyb3cAAAABAAAABHVzZXIEAAAADHN0b3JlZEJvcnJvdwkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAEdGhpcwkAASwAAAACBQAAAAR1c2VyAgAAAAdfYm9ycm93AAAAAAAAAAAABAAAABFzdG9yZWRCb3Jyb3dJbmRleAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAEdGhpcwkAASwAAAACBQAAAAR1c2VyAgAAAAZfaW5kZXgAAAAAAAAAAAADCQAAZgAAAAIFAAAAEXN0b3JlZEJvcnJvd0luZGV4AAAAAAAAAAAACQAAawAAAAMFAAAADHN0b3JlZEJvcnJvdwUAAAAMY3VycmVudEluZGV4BQAAABFzdG9yZWRCb3Jyb3dJbmRleAAAAAAAAAAAAAAAAAcAAAABaQEAAAAWZ2V0VXNlckhlYWx0aFBhcmFtZXRlcgAAAAUAAAAEdXNlcgAAABBjb2xsYXRlcmFsQW1vdW50AAAADGNvbGxhdGVyYWxJZAAAAA1uZXdEZWJ0QW1vdW50AAAACW5ld0RlYnRJZAMJAQAAAA1pc1dhdmV0cm9sbGVyAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAAAp1c2VyTG9ja2VkCQEAAAALdmFsdWVPckVsc2UAAAACCQEAAAARQGV4dHJOYXRpdmUoMTA1MCkAAAACBQAAAAR0aGlzCQABLAAAAAIFAAAABHVzZXICAAAAB19sb2NrZWQAAAAAAAAAAAAEAAAAFHVzZXJEVG9rZW5Db2xsYXRlcmFsAwkAAAAAAAACBQAAAAhkVG9rZW5JZAUAAAAMY29sbGF0ZXJhbElkCQAAZQAAAAIFAAAACnVzZXJMb2NrZWQFAAAAEGNvbGxhdGVyYWxBbW91bnQFAAAACnVzZXJMb2NrZWQEAAAAEWN1cnJlbnRVc2VyQm9ycm93AwkAAAAAAAACBQAAAAluZXdEZWJ0SWQFAAAACmFzc2V0SWRTdWIJAABkAAAAAgkBAAAAFGdldEN1cnJlbnRVc2VyQm9ycm93AAAAAQUAAAAEdXNlcgUAAAANbmV3RGVidEFtb3VudAkBAAAAFGdldEN1cnJlbnRVc2VyQm9ycm93AAAAAQUAAAAEdXNlcgQAAAAOdXNlckNvbGxhdGVyYWwJAQAAAA9jYWxjQXNzZXRBbW91bnQAAAABBQAAABR1c2VyRFRva2VuQ29sbGF0ZXJhbAQAAAAKYXNzZXRQcmljZQkAA/wAAAAECQEAAAARQGV4dHJOYXRpdmUoMTA2MikAAAABBQAAAAZvcmFjbGUCAAAACGdldFByaWNlCQAETAAAAAIFAAAACmFzc2V0SWRTdWIFAAAAA25pbAUAAAADbmlsBAAAAAckbWF0Y2gwBQAAAAphc3NldFByaWNlAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAAAXQFAAAAByRtYXRjaDAEAAAAD2NvbGxhdGVyYWxWYWx1ZQkAAGsAAAADBQAAABBjb2xsYXRlcmFsRmFjdG9yBQAAAA51c2VyQ29sbGF0ZXJhbAUAAAAKYmFzZUZhY3RvcgQAAAAIbWFudGlzc2EJAABsAAAABgAAAAAAAAAACgAAAAAAAAAAAAUAAAANYXNzZXREZWNpbWFscwAAAAAAAAAAAAAAAAAAAAAAAAUAAAAHQ0VJTElORwQAAAAJYkNTdW1tYW5kCQAAawAAAAMFAAAAD2NvbGxhdGVyYWxWYWx1ZQUAAAABdAUAAAAIbWFudGlzc2EEAAAAC2JvcnJvd0luVVNECQAAawAAAAMFAAAAEWN1cnJlbnRVc2VyQm9ycm93BQAAAAF0BQAAAAhtYW50aXNzYQQAAAAKYkNVU3VtbWFuZAkAAGsAAAADBQAAAAtib3Jyb3dJblVTRAUAAAAKYmFzZUZhY3RvcgUAAAAUbGlxdWlkYXRpb25UaHJlc2hvbGQJAAUUAAAAAgUAAAADbmlsCQAFFAAAAAIFAAAACWJDU3VtbWFuZAUAAAAKYkNVU3VtbWFuZAkAAAIAAAABAgAAABFJbmNvcnJlY3QgcHJpY2luZwkAAAIAAAABAgAAADBBZGRyZXNzIGRvZXMgbm90IG1hdGNoIHdpdGggd2F2ZXRyb2xsZXIgYWRkcmVzcyEAAAABaQEAAAAHZGVwb3NpdAAAAAIAAAAEdXNlcgAAAAxpc0NvbGxhdGVyYWwDCQEAAAANaXNXYXZldHJvbGxlcgAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAAPdXNlclRva2VuQW1vdW50CQEAAAAQY2FsY0RUb2tlbkFtb3VudAAAAAEICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAQAAAATY3VycmVudERUb2tlblN1cHBseQkAAGQAAAACBQAAAAxkVG9rZW5TdXBwbHkFAAAAD3VzZXJUb2tlbkFtb3VudAMFAAAADGlzQ29sbGF0ZXJhbAQAAAARbG9ja2VkVXNlckJhbGFuY2UJAABkAAAAAgkBAAAAEXVzZXJsb2NrZWRCYWxhbmNlAAAAAQUAAAAEdXNlcgUAAAAPdXNlclRva2VuQW1vdW50CQAFFAAAAAIJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAIJAAEsAAAAAgUAAAAEdXNlcgIAAAAHX2xvY2tlZAUAAAARbG9ja2VkVXNlckJhbGFuY2UJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAICAAAADGRUb2tlblN1cHBseQUAAAATY3VycmVudERUb2tlblN1cHBseQkABEwAAAACCQEAAAAMd3JpdGVJbnRlZ2VyAAAAAgIAAAALdG90YWxCb3Jyb3cFAAAAEmN1cnJlbnRUb3RhbEJvcnJvdwkABEwAAAACCQEAAAAMd3JpdGVJbnRlZ2VyAAAAAgIAAAALdG90YWxTdXBwbHkJAABkAAAAAgUAAAASY3VycmVudFRvdGFsU3VwcGx5CAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAZhbW91bnQJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAICAAAADHRvdGFsUmVzZXJ2ZQUAAAAOY3VycmVudFJlc2VydmUJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAICAAAAC3N0b3JlZEluZGV4BQAAAAxjdXJyZW50SW5kZXgJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAICAAAADHN0b3JlZEhlaWdodAUAAAAGaGVpZ2h0CQAETAAAAAIJAQAAAAdSZWlzc3VlAAAAAwkAAlkAAAABBQAAAAhkVG9rZW5JZAUAAAAPdXNlclRva2VuQW1vdW50BgUAAAADbmlsCQABLAAAAAIJAAEsAAAAAgkAAaQAAAABCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAZhbW91bnQFAAAACmRUb2tlbk5hbWUCAAAAGHdlcmUgc3VjY2Vzc2Z1bGx5IGxvY2tlZAkABRQAAAACCQAETAAAAAIJAQAAAAx3cml0ZUludGVnZXIAAAACAgAAAAxkVG9rZW5TdXBwbHkFAAAAE2N1cnJlbnREVG9rZW5TdXBwbHkJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAICAAAAC3RvdGFsQm9ycm93BQAAABJjdXJyZW50VG90YWxCb3Jyb3cJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAICAAAAC3RvdGFsU3VwcGx5CQAAZAAAAAIFAAAAEmN1cnJlbnRUb3RhbFN1cHBseQgJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50CQAETAAAAAIJAQAAAAx3cml0ZUludGVnZXIAAAACAgAAAAx0b3RhbFJlc2VydmUFAAAADmN1cnJlbnRSZXNlcnZlCQAETAAAAAIJAQAAAAx3cml0ZUludGVnZXIAAAACAgAAAAtzdG9yZWRJbmRleAUAAAAMY3VycmVudEluZGV4CQAETAAAAAIJAQAAAAx3cml0ZUludGVnZXIAAAACAgAAAAxzdG9yZWRIZWlnaHQFAAAABmhlaWdodAkABEwAAAACCQEAAAAHUmVpc3N1ZQAAAAMJAAJZAAAAAQUAAAAIZFRva2VuSWQFAAAAD3VzZXJUb2tlbkFtb3VudAYJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAA91c2VyVG9rZW5BbW91bnQJAAJZAAAAAQUAAAAIZFRva2VuSWQFAAAAA25pbAUAAAAPdXNlclRva2VuQW1vdW50CQAAAgAAAAECAAAAMEFkZHJlc3MgZG9lcyBub3QgbWF0Y2ggd2l0aCB3YXZldHJvbGxlciBhZGRyZXNzIQAAAAFpAQAAAAh3aXRoZHJhdwAAAAEAAAAEdXNlcgMJAQAAAA1pc1dhdmV0cm9sbGVyAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAABJhdmFpbGFibGVMaXF1aWRpdHkJAABlAAAAAgUAAAASY3VycmVudFRvdGFsU3VwcGx5BQAAABJjdXJyZW50VG90YWxCb3Jyb3cEAAAAFHJlcXVlc3RlZEFzc2V0QW1vdW50CQEAAAAPY2FsY0Fzc2V0QW1vdW50AAAAAQgJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50AwkAAGcAAAACBQAAABJhdmFpbGFibGVMaXF1aWRpdHkFAAAAFHJlcXVlc3RlZEFzc2V0QW1vdW50CQAFFAAAAAIJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAICAAAADGRUb2tlblN1cHBseQkAAGUAAAACBQAAAAxkVG9rZW5TdXBwbHkICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAkABEwAAAACCQEAAAAMd3JpdGVJbnRlZ2VyAAAAAgIAAAALdG90YWxCb3Jyb3cFAAAAEmN1cnJlbnRUb3RhbEJvcnJvdwkABEwAAAACCQEAAAAMd3JpdGVJbnRlZ2VyAAAAAgIAAAALdG90YWxTdXBwbHkJAABlAAAAAgUAAAASY3VycmVudFRvdGFsU3VwcGx5BQAAABRyZXF1ZXN0ZWRBc3NldEFtb3VudAkABEwAAAACCQEAAAAMd3JpdGVJbnRlZ2VyAAAAAgIAAAAMdG90YWxSZXNlcnZlBQAAAA5jdXJyZW50UmVzZXJ2ZQkABEwAAAACCQEAAAAMd3JpdGVJbnRlZ2VyAAAAAgIAAAALc3RvcmVkSW5kZXgFAAAADGN1cnJlbnRJbmRleAkABEwAAAACCQEAAAAMd3JpdGVJbnRlZ2VyAAAAAgIAAAAMc3RvcmVkSGVpZ2h0BQAAAAZoZWlnaHQJAARMAAAAAgkBAAAABEJ1cm4AAAACCQACWQAAAAEFAAAACGRUb2tlbklkCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAZhbW91bnQJAARMAAAAAgMJAAAAAAAAAgUAAAAKYXNzZXRJZFN1YgIAAAAFV0FWRVMJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAUcmVxdWVzdGVkQXNzZXRBbW91bnQFAAAABHVuaXQJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAUcmVxdWVzdGVkQXNzZXRBbW91bnQJAAJZAAAAAQUAAAAKYXNzZXRJZFN1YgUAAAADbmlsBQAAABRyZXF1ZXN0ZWRBc3NldEFtb3VudAkAAAIAAAABAgAAACFQb29sIGxpcXVpZGl0eSBpcyBub3Qgc3VmZmljaWVudCEJAAACAAAAAQIAAAAwQWRkcmVzcyBkb2VzIG5vdCBtYXRjaCB3aXRoIHdhdmV0cm9sbGVyIGFkZHJlc3MhAAAAAWkBAAAAEGxvY2tBc0NvbGxhdGVyYWwAAAABAAAABHVzZXIDCQEAAAANaXNXYXZldHJvbGxlcgAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAAQbmV3TG9ja2VkQmFsYW5jZQkAAGQAAAACCQEAAAARdXNlcmxvY2tlZEJhbGFuY2UAAAABBQAAAAR1c2VyCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAZhbW91bnQJAAUUAAAAAgkABEwAAAACCQEAAAAMd3JpdGVJbnRlZ2VyAAAAAgkAASwAAAACBQAAAAR1c2VyAgAAAAdfbG9ja2VkBQAAABBuZXdMb2NrZWRCYWxhbmNlCQAETAAAAAIJAQAAAAx3cml0ZUludGVnZXIAAAACAgAAAAt0b3RhbEJvcnJvdwUAAAASY3VycmVudFRvdGFsQm9ycm93CQAETAAAAAIJAQAAAAx3cml0ZUludGVnZXIAAAACAgAAAAt0b3RhbFN1cHBseQUAAAASY3VycmVudFRvdGFsU3VwcGx5CQAETAAAAAIJAQAAAAx3cml0ZUludGVnZXIAAAACAgAAAAx0b3RhbFJlc2VydmUFAAAADmN1cnJlbnRSZXNlcnZlCQAETAAAAAIJAQAAAAx3cml0ZUludGVnZXIAAAACAgAAAAtzdG9yZWRJbmRleAUAAAAMY3VycmVudEluZGV4CQAETAAAAAIJAQAAAAx3cml0ZUludGVnZXIAAAACAgAAAAxzdG9yZWRIZWlnaHQFAAAABmhlaWdodAUAAAADbmlsCQABLAAAAAIJAAEsAAAAAgkAAaQAAAABCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAZhbW91bnQFAAAACmRUb2tlbk5hbWUCAAAAGHdlcmUgc3VjY2Vzc2Z1bGx5IGxvY2tlZAkAAAIAAAABAgAAADBBZGRyZXNzIGRvZXMgbm90IG1hdGNoIHdpdGggd2F2ZXRyb2xsZXIgYWRkcmVzcyEAAAABaQEAAAAGYm9ycm93AAAAAgAAAAR1c2VyAAAABmFtb3VudAMJAQAAAA1pc1dhdmV0cm9sbGVyAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAABFjdXJyZW50VXNlckJvcnJvdwkBAAAAFGdldEN1cnJlbnRVc2VyQm9ycm93AAAAAQUAAAAEdXNlcgkABRQAAAACCQAETAAAAAIJAQAAAAx3cml0ZUludGVnZXIAAAACCQABLAAAAAIFAAAABHVzZXICAAAAB19ib3Jyb3cJAABkAAAAAgUAAAARY3VycmVudFVzZXJCb3Jyb3cFAAAABmFtb3VudAkABEwAAAACCQEAAAAMd3JpdGVJbnRlZ2VyAAAAAgkAASwAAAACBQAAAAR1c2VyAgAAAAZfaW5kZXgFAAAADGN1cnJlbnRJbmRleAkABEwAAAACCQEAAAAMd3JpdGVJbnRlZ2VyAAAAAgIAAAALdG90YWxCb3Jyb3cJAABkAAAAAgUAAAASY3VycmVudFRvdGFsQm9ycm93BQAAAAZhbW91bnQJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAICAAAAC3RvdGFsU3VwcGx5BQAAABJjdXJyZW50VG90YWxTdXBwbHkJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAICAAAADHRvdGFsUmVzZXJ2ZQUAAAAOY3VycmVudFJlc2VydmUJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAICAAAAC3N0b3JlZEluZGV4BQAAAAxjdXJyZW50SW5kZXgJAARMAAAAAgkBAAAADHdyaXRlSW50ZWdlcgAAAAICAAAADHN0b3JlZEhlaWdodAUAAAAGaGVpZ2h0CQAETAAAAAIDCQAAAAAAAAIFAAAACmFzc2V0SWRTdWICAAAABVdBVkVTCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAABmFtb3VudAUAAAAEdW5pdAkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAZhbW91bnQJAAJZAAAAAQUAAAAKYXNzZXRJZFN1YgUAAAADbmlsBQAAAAZhbW91bnQJAAACAAAAAQIAAAAwQWRkcmVzcyBkb2VzIG5vdCBtYXRjaCB3aXRoIHdhdmV0cm9sbGVyIGFkZHJlc3MhAAAAAWkBAAAABXNldHVwAAAABQAAAANhSWQAAAAJY29uZmlnQWRkAAAAEGJhc2VFeGNoYW5nZVJhdGUAAAAJdG9rZW5OYW1lAAAAEHRva2VuRGVzY3JpcHRpb24DCQEAAAABIQAAAAEJAQAAAAlpc0RlZmluZWQAAAABCQAEHQAAAAIFAAAABHRoaXMCAAAADWNvbmZpZ0FkZHJlc3MEAAAABWFzc2V0CQAEQgAAAAUFAAAACXRva2VuTmFtZQUAAAAQdG9rZW5EZXNjcmlwdGlvbgAAAAAAAAAAAAAAAAAAAAAACAYEAAAAB3Rva2VuSWQJAAQ4AAAAAQUAAAAFYXNzZXQJAARMAAAAAgUAAAAFYXNzZXQJAARMAAAAAgkBAAAAC3dyaXRlU3RyaW5nAAAAAgIAAAAHYXNzZXRJZAUAAAADYUlkCQAETAAAAAIJAQAAAAt3cml0ZVN0cmluZwAAAAICAAAADWNvbmZpZ0FkZHJlc3MFAAAACWNvbmZpZ0FkZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAALdG90YWxCb3Jyb3cAAAAAAAAAAAAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAC3RvdGFsU3VwcGx5AAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAAx0b3RhbFJlc2VydmUAAAAAAAAAAAAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAC3N0b3JlZEluZGV4BQAAAAliYXNlSW5kZXgJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAADHN0b3JlZEhlaWdodAUAAAAGaGVpZ2h0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAABBiYXNlRXhjaGFuZ2VSYXRlBQAAABBiYXNlRXhjaGFuZ2VSYXRlCQAETAAAAAIJAQAAAAt3cml0ZVN0cmluZwAAAAICAAAACmRUb2tlbk5hbWUFAAAACXRva2VuTmFtZQkABEwAAAACCQEAAAALd3JpdGVTdHJpbmcAAAACAgAAAAhkVG9rZW5JZAkAAlgAAAABBQAAAAd0b2tlbklkCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAA5kVG9rZW5EZWNpbWFscwAAAAAAAAAACAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAAMZFRva2VuU3VwcGx5AAAAAAAAAAAABQAAAANuaWwJAAACAAAAAQIAAAATUG9vbCBhbHJlYWR5IHNldHVwIQAAAAFpAQAAAAp3cml0ZUVudHJ5AAAAAgAAAARuYW1lAAAABGRhdGEJAARMAAAAAgkBAAAAC3dyaXRlU3RyaW5nAAAAAgUAAAAEbmFtZQUAAAAEZGF0YQUAAAADbmlsAAAAAQAAAAJ0eAEAAAAGdmVyaWZ5AAAAAAkAAfQAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAAIBQAAAAJ0eAAAAA9zZW5kZXJQdWJsaWNLZXmXR2Rb", "height": 1689008, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 7F3oKDBJhPxdGDuBUd7oxcez4FMhv9kRn53FCmBGSJro Next: 4RmBzkMWBjMjMfri39gtEaZty3UR5SQWFDLsvEaq8Kep Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let config = valueOrElse(getStringValue(this, "config"), "")
4+let baseFactor = 1000
55
6-let admin = valueOrElse(getStringValue(addressFromStringValue(config), "admin"), "")
6+let baseIndex = 10000000000000000
77
8-let pools = valueOrElse(getStringValue(this, "pools"), "")
8+let blocksPerYear = 525600
99
10-func isAdmin (callerAddress) = if ((callerAddress == addressFromStringValue(admin)))
10+let config = valueOrElse(getString(this, "configAddress"), "")
11+
12+let admin = valueOrElse(getString(addressFromStringValue(config), "admin"), "")
13+
14+let wavetroller = valueOrElse(getString(addressFromStringValue(config), "wavetroller"), "")
15+
16+let oracle = valueOrElse(getString(addressFromStringValue(config), "oracle"), "")
17+
18+let assetIdSub = valueOrErrorMessage(getString(this, "assetId"), "No assetId could be found in data storage!")
19+
20+let assetDecimals = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_Decimals")), (("No key " + (assetIdSub + "_Decimals")) + " was found"))
21+
22+let multiplier = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_Multiplier")), (("No key " + (assetIdSub + "_Multiplier")) + " was found"))
23+
24+let kink = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_Kink")), (("No key " + (assetIdSub + "_Kink")) + " was found"))
25+
26+let jumpMultiplier = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_JumpMultiplier")), (("No key " + (assetIdSub + "_JumpMultiplier")) + " was found"))
27+
28+let baseRate = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_BaseRate")), (("No key " + (assetIdSub + "_BaseRate")) + " was found"))
29+
30+let baseExchangeRate = valueOrErrorMessage(getInteger(this, "baseExchangeRate"), "No key baseExchangeRate was found")
31+
32+let collateralFactor = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_CollateralFactor")), (("No key " + (assetIdSub + "_CollateralFactor")) + " was found"))
33+
34+let liquidationThreshold = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_Threshold")), (("No key " + (assetIdSub + "_Threshold")) + " was found"))
35+
36+let reserveFactor = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_ReserveFactor")), (("No key " + (assetIdSub + "_ReserveFactor")) + " was found"))
37+
38+let totalBorrow = valueOrElse(getInteger(this, "totalBorrow"), 0)
39+
40+let totalSupply = valueOrElse(getInteger(this, "totalSupply"), 0)
41+
42+let totalReserve = valueOrElse(getInteger(this, "totalReserve"), 0)
43+
44+let dTokenSupply = valueOrErrorMessage(getInteger(this, "dTokenSupply"), "No key dTokenSupply was found")
45+
46+let dTokenDecimals = valueOrErrorMessage(getInteger(this, "dTokenDecimals"), "No key dTokenDecimals was found")
47+
48+let dTokenId = valueOrErrorMessage(getString(this, "dTokenId"), "No key dTokenId was found")
49+
50+let dTokenName = valueOrErrorMessage(getString(this, "dTokenName"), "No key dTokenName was found")
51+
52+let storedHeight = valueOrElse(getInteger(this, "storedHeight"), height)
53+
54+let storedIndex = valueOrElse(getInteger(this, "storedIndex"), 10000000000000000)
55+
56+func isAdminAddress (address) = if ((addressFromStringValue(admin) == address))
1157 then true
1258 else false
1359
1460
15-func checkPool (poolAdd) = if (contains(pools, poolAdd))
61+func isWavetroller (address) = if ((addressFromStringValue(wavetroller) == address))
62+ then true
63+ else false
64+
65+
66+func isAcceptableAssetId (assetId) = if ((assetId == assetIdSub))
1667 then true
1768 else false
1869
2374 func writeInteger (key,integerValue) = IntegerEntry(key, integerValue)
2475
2576
26-func checkPoolLiquidity (poolAddress,amount) = {
27- let totalSupply = getIntegerValue(addressFromStringValue(poolAddress), "totalSupply")
28- let totalBorrow = getIntegerValue(addressFromStringValue(poolAddress), "totalBorrow")
29- let availableLiquidity = (totalSupply - totalBorrow)
30- if ((availableLiquidity >= amount))
31- then true
32- else false
77+func userlockedBalance (userAddress) = valueOrElse(getInteger(this, (userAddress + "_locked")), 0)
78+
79+
80+let utilization = if ((totalSupply > 0))
81+ then fraction(totalBorrow, baseFactor, totalSupply)
82+ else 0
83+
84+let apr = {
85+ let minValue = [utilization, kink]
86+ let minValueItem = min(minValue)
87+ let maxValue = [0, (utilization - kink)]
88+ let maxValueItem = max(maxValue)
89+ ((fraction(multiplier, minValueItem, baseFactor) + fraction(jumpMultiplier, maxValueItem, baseFactor)) + baseRate)
90+ }
91+
92+let apy = fraction(fraction(apr, utilization, baseFactor), (baseFactor - reserveFactor), baseFactor)
93+
94+let borrowRatePerBlock = fraction(apr, baseIndex, (blocksPerYear * baseFactor))
95+
96+let deltaBlocks = (height - storedHeight)
97+
98+let currentIndex = fraction(storedIndex, (baseIndex + (borrowRatePerBlock * deltaBlocks)), baseIndex, CEILING)
99+
100+let currentTotalBorrow = fraction(totalBorrow, currentIndex, storedIndex)
101+
102+let collectedInterest = fraction(totalBorrow, (borrowRatePerBlock * deltaBlocks), baseIndex)
103+
104+let currentTotalSupply = (totalSupply + fraction((baseFactor - reserveFactor), collectedInterest, baseFactor))
105+
106+let currentReserve = (totalReserve + fraction(reserveFactor, collectedInterest, baseFactor))
107+
108+let exchangeRate = if ((dTokenSupply > 0))
109+ then {
110+ let exponent = ((18 - dTokenDecimals) + assetDecimals)
111+ let mantissa = pow(10, 0, exponent, 0, 0, CEILING)
112+ fraction(currentTotalSupply, mantissa, dTokenSupply)
113+ }
114+ else baseExchangeRate
115+
116+func calcDTokenAmount (assetAmount) = {
117+ let exponent = ((18 - dTokenDecimals) + assetDecimals)
118+ let mantissa = pow(10, 0, exponent, 0, 0, CEILING)
119+ fraction(assetAmount, mantissa, exchangeRate)
33120 }
34121
35122
36-func getHealthParameter (user,poolAddress,newDebtAmount,newDebtId,collateralAmount,collateralId) = {
37- let result = invoke(addressFromStringValue(poolAddress), "getUserHealthParameter", [user, collateralAmount, collateralId, newDebtAmount, newDebtId], nil)
38- match result {
39- case t: (Int, Int) =>
40- t
41- case _ =>
42- $Tuple2(0, 0)
43- }
123+func calcAssetAmount (dTokenAmount) = {
124+ let exponent = ((18 - dTokenDecimals) + assetDecimals)
125+ let mantissa = pow(10, 0, exponent, 0, 0, CEILING)
126+ fraction(dTokenAmount, exchangeRate, mantissa)
44127 }
45128
46129
47-func calcHealthFactor (borrowCapacity,borrowCapacityUsed) = fraction((borrowCapacity - borrowCapacityUsed), 1000, borrowCapacity)
48-
49-
50-func calcBorrowCBorrowCU (user,newDebtAmount,newDebtId,collateralAmount,collateralId) = {
51- let poolList = split(pools, ";")
52- let listSize = size(poolList)
53- func foldPools (accum,next) = {
54- let healthParams = getHealthParameter(user, next, newDebtAmount, newDebtId, collateralAmount, collateralId)
55- match healthParams {
56- case t: (Int, Int) =>
57- $Tuple2((accum._1 + healthParams._1), (accum._2 + healthParams._1))
58- case e =>
59- throw("Test")
60- }
61- }
62-
63- let $list22852319 = poolList
64- let $size22852319 = size($list22852319)
65- let $acc022852319 = $Tuple2(0, 0)
66- if (($size22852319 == 0))
67- then $acc022852319
68- else {
69- let $acc122852319 = foldPools($acc022852319, $list22852319[0])
70- if (($size22852319 == 1))
71- then $acc122852319
72- else {
73- let $acc222852319 = foldPools($acc122852319, $list22852319[1])
74- if (($size22852319 == 2))
75- then $acc222852319
76- else {
77- let $acc322852319 = foldPools($acc222852319, $list22852319[2])
78- throw("List size exceed 2")
79- }
80- }
81- }
82- }
83-
84-
85-func checkUserHealth (user,newDebtAmount,newDebtId,collateralAmount,collateralId) = {
86- let bcBcu = calcBorrowCBorrowCU(user, newDebtAmount, newDebtId, collateralAmount, collateralId)
87- let userHealth = calcHealthFactor(bcBcu._1, bcBcu._2)
88- if ((userHealth >= 0))
89- then true
90- else false
130+func getCurrentUserBorrow (user) = {
131+ let storedBorrow = valueOrElse(getIntegerValue(this, (user + "_borrow")), 0)
132+ let storedBorrowIndex = valueOrElse(getIntegerValue(this, (user + "_index")), 0)
133+ if ((storedBorrowIndex > 0))
134+ then fraction(storedBorrow, currentIndex, storedBorrowIndex)
135+ else 0
91136 }
92137
93138
94139 @Callable(i)
95-func borrowFrom (poolAddress,assetId,amount) = if (checkPool(poolAddress))
140+func getUserHealthParameter (user,collateralAmount,collateralId,newDebtAmount,newDebtId) = if (isWavetroller(i.caller))
96141 then {
97- let poolAsset = getStringValue(addressFromStringValue(poolAddress), "assetId")
98- if ((poolAsset == assetId))
99- then if (checkPoolLiquidity(poolAddress, amount))
100- then {
101- let user = toBase58String(i.caller.bytes)
102- if (checkUserHealth(user, amount, assetId, 0, ""))
103- then nil
104- else throw("Borrow exceeds user health!")
105- }
106- else throw("Pool liquidity is not sufficient!")
107- else throw("AssetIds does not match")
142+ let userLocked = valueOrElse(getIntegerValue(this, (user + "_locked")), 0)
143+ let userDTokenCollateral = if ((dTokenId == collateralId))
144+ then (userLocked - collateralAmount)
145+ else userLocked
146+ let currentUserBorrow = if ((newDebtId == assetIdSub))
147+ then (getCurrentUserBorrow(user) + newDebtAmount)
148+ else getCurrentUserBorrow(user)
149+ let userCollateral = calcAssetAmount(userDTokenCollateral)
150+ let assetPrice = invoke(addressFromStringValue(oracle), "getPrice", [assetIdSub], nil)
151+ match assetPrice {
152+ case t: Int =>
153+ let collateralValue = fraction(collateralFactor, userCollateral, baseFactor)
154+ let mantissa = pow(10, 0, assetDecimals, 0, 0, CEILING)
155+ let bCSummand = fraction(collateralValue, t, mantissa)
156+ let borrowInUSD = fraction(currentUserBorrow, t, mantissa)
157+ let bCUSummand = fraction(borrowInUSD, baseFactor, liquidationThreshold)
158+ $Tuple2(nil, $Tuple2(bCSummand, bCUSummand))
159+ case _ =>
160+ throw("Incorrect pricing")
108161 }
109- else throw("Pool address not found!")
162+ }
163+ else throw("Address does not match with wavetroller address!")
110164
111165
112166
113167 @Callable(i)
114-func setup (configAddress,pools) = if (if (!(isDefined(getString(this, "config"))))
115- then !(isDefined(getString(this, "pools")))
116- else false)
117- then [writeString("config", configAddress), writeString("pools", makeString(pools, ";"))]
118- else throw("Admin and config address already definied!")
168+func deposit (user,isCollateral) = if (isWavetroller(i.caller))
169+ then {
170+ let userTokenAmount = calcDTokenAmount(i.payments[0].amount)
171+ let currentDTokenSupply = (dTokenSupply + userTokenAmount)
172+ if (isCollateral)
173+ then {
174+ let lockedUserBalance = (userlockedBalance(user) + userTokenAmount)
175+ $Tuple2([writeInteger((user + "_locked"), lockedUserBalance), writeInteger("dTokenSupply", currentDTokenSupply), writeInteger("totalBorrow", currentTotalBorrow), writeInteger("totalSupply", (currentTotalSupply + i.payments[0].amount)), writeInteger("totalReserve", currentReserve), writeInteger("storedIndex", currentIndex), writeInteger("storedHeight", height), Reissue(fromBase58String(dTokenId), userTokenAmount, true)], ((toString(i.payments[0].amount) + dTokenName) + "were successfully locked"))
176+ }
177+ else $Tuple2([writeInteger("dTokenSupply", currentDTokenSupply), writeInteger("totalBorrow", currentTotalBorrow), writeInteger("totalSupply", (currentTotalSupply + i.payments[0].amount)), writeInteger("totalReserve", currentReserve), writeInteger("storedIndex", currentIndex), writeInteger("storedHeight", height), Reissue(fromBase58String(dTokenId), userTokenAmount, true), ScriptTransfer(i.caller, userTokenAmount, fromBase58String(dTokenId))], userTokenAmount)
178+ }
179+ else throw("Address does not match with wavetroller address!")
119180
120181
121182
122183 @Callable(i)
123-func addPool (poolAddress) = if (isAdmin(i.caller))
184+func withdraw (user) = if (isWavetroller(i.caller))
124185 then {
125- let poolList = split(pools, ";")
126- if ((containsElement(poolList, poolAddress) == false))
127- then {
128- let newPools = (poolList :+ poolAddress)
129-[writeString("pools", makeString(newPools, ";"))]
130- }
131- else throw("Pool already exists!")
186+ let availableLiquidity = (currentTotalSupply - currentTotalBorrow)
187+ let requestedAssetAmount = calcAssetAmount(i.payments[0].amount)
188+ if ((availableLiquidity >= requestedAssetAmount))
189+ then $Tuple2([writeInteger("dTokenSupply", (dTokenSupply - i.payments[0].amount)), writeInteger("totalBorrow", currentTotalBorrow), writeInteger("totalSupply", (currentTotalSupply - requestedAssetAmount)), writeInteger("totalReserve", currentReserve), writeInteger("storedIndex", currentIndex), writeInteger("storedHeight", height), Burn(fromBase58String(dTokenId), i.payments[0].amount), if ((assetIdSub == "WAVES"))
190+ then ScriptTransfer(i.caller, requestedAssetAmount, unit)
191+ else ScriptTransfer(i.caller, requestedAssetAmount, fromBase58String(assetIdSub))], requestedAssetAmount)
192+ else throw("Pool liquidity is not sufficient!")
132193 }
133- else throw("Address does not match with admin address!")
194+ else throw("Address does not match with wavetroller address!")
134195
135196
136197
137198 @Callable(i)
138-func updateConfig (configAddress) = if (isAdmin(i.caller))
139- then [writeString("config", configAddress)]
140- else throw("Address does not match with admin address!")
199+func lockAsCollateral (user) = if (isWavetroller(i.caller))
200+ then {
201+ let newLockedBalance = (userlockedBalance(user) + i.payments[0].amount)
202+ $Tuple2([writeInteger((user + "_locked"), newLockedBalance), writeInteger("totalBorrow", currentTotalBorrow), writeInteger("totalSupply", currentTotalSupply), writeInteger("totalReserve", currentReserve), writeInteger("storedIndex", currentIndex), writeInteger("storedHeight", height)], ((toString(i.payments[0].amount) + dTokenName) + "were successfully locked"))
203+ }
204+ else throw("Address does not match with wavetroller address!")
141205
142206
143207
144208 @Callable(i)
145-func depositAt (poolAddress,isCollateral) = if (checkPool(poolAddress))
146- then if ((size(i.payments) > 0))
147- then {
148- let user = toBase58String(i.caller.bytes)
149- let tokenAmount = invoke(addressFromStringValue(poolAddress), "deposit", [user, isCollateral], i.payments)
150- if ((tokenAmount == tokenAmount))
151- then {
152- let tokenId = getStringValue(addressFromStringValue(poolAddress), "dTokenId")
153- match tokenAmount {
154- case t: Int =>
155-[ScriptTransfer(i.caller, t, fromBase58String(tokenId))]
156- case t: String =>
157- nil
158- case _ =>
159- throw("Incorrect invoke result!")
160- }
161- }
162- else throw("Strict value is not equal to itself.")
163- }
164- else throw("No payment attached!")
165- else throw("Pool address not found!")
209+func borrow (user,amount) = if (isWavetroller(i.caller))
210+ then {
211+ let currentUserBorrow = getCurrentUserBorrow(user)
212+ $Tuple2([writeInteger((user + "_borrow"), (currentUserBorrow + amount)), writeInteger((user + "_index"), currentIndex), writeInteger("totalBorrow", (currentTotalBorrow + amount)), writeInteger("totalSupply", currentTotalSupply), writeInteger("totalReserve", currentReserve), writeInteger("storedIndex", currentIndex), writeInteger("storedHeight", height), if ((assetIdSub == "WAVES"))
213+ then ScriptTransfer(i.caller, amount, unit)
214+ else ScriptTransfer(i.caller, amount, fromBase58String(assetIdSub))], amount)
215+ }
216+ else throw("Address does not match with wavetroller address!")
166217
167218
168219
169220 @Callable(i)
170-func withdrawFrom (poolAddress) = if (checkPool(poolAddress))
221+func setup (aId,configAdd,baseExchangeRate,tokenName,tokenDescription) = if (!(isDefined(getString(this, "configAddress"))))
171222 then {
172- let dTokenId = getStringValue(addressFromStringValue(poolAddress), "dTokenId")
173- if ((fromBase58String(dTokenId) == i.payments[0].assetId))
174- then if ((size(i.payments) > 0))
175- then {
176- let user = toBase58String(i.caller.bytes)
177- let tokenAmount = invoke(addressFromStringValue(poolAddress), "withdraw", [user], i.payments)
178- if ((tokenAmount == tokenAmount))
179- then {
180- let tokenId = getStringValue(addressFromStringValue(poolAddress), "assetId")
181- match tokenAmount {
182- case t: Int =>
183- if ((tokenId == "WAVES"))
184- then [ScriptTransfer(i.caller, t, unit)]
185- else [ScriptTransfer(i.caller, t, fromBase58String(tokenId))]
186- case t: String =>
187- nil
188- case _ =>
189- throw("Incorrect invoke result!")
190- }
191- }
192- else throw("Strict value is not equal to itself.")
193- }
194- else throw("No payment attached!")
195- else throw("AssetIds does not match")
223+ let asset = Issue(tokenName, tokenDescription, 0, 8, true)
224+ let tokenId = calculateAssetId(asset)
225+[asset, writeString("assetId", aId), writeString("configAddress", configAdd), IntegerEntry("totalBorrow", 0), IntegerEntry("totalSupply", 0), IntegerEntry("totalReserve", 0), IntegerEntry("storedIndex", baseIndex), IntegerEntry("storedHeight", height), IntegerEntry("baseExchangeRate", baseExchangeRate), writeString("dTokenName", tokenName), writeString("dTokenId", toBase58String(tokenId)), IntegerEntry("dTokenDecimals", 8), IntegerEntry("dTokenSupply", 0)]
196226 }
197- else throw("Pool address not found!")
227+ else throw("Pool already setup!")
198228
199229
200230
201231 @Callable(i)
202-func lockAsCollateralAt (poolAddress) = if (checkPool(poolAddress))
203- then {
204- let dTokenId = getStringValue(addressFromStringValue(poolAddress), "dTokenId")
205- if ((fromBase58String(dTokenId) == i.payments[0].assetId))
206- then if ((size(i.payments) > 0))
207- then {
208- let user = toBase58String(i.caller.bytes)
209- let msg = invoke(addressFromStringValue(poolAddress), "lockAsCollateral", [user], i.payments)
210- if ((msg == msg))
211- then match msg {
212- case t: String =>
213- nil
214- case _ =>
215- throw("Incorrect invoke result!")
216- }
217- else throw("Strict value is not equal to itself.")
218- }
219- else throw("No payment attached!")
220- else throw("AssetIds does not match")
221- }
222- else throw("Pool address not found!")
232+func writeEntry (name,data) = [writeString(name, data)]
223233
234+
235+@Verifier(tx)
236+func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
224237
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let config = valueOrElse(getStringValue(this, "config"), "")
4+let baseFactor = 1000
55
6-let admin = valueOrElse(getStringValue(addressFromStringValue(config), "admin"), "")
6+let baseIndex = 10000000000000000
77
8-let pools = valueOrElse(getStringValue(this, "pools"), "")
8+let blocksPerYear = 525600
99
10-func isAdmin (callerAddress) = if ((callerAddress == addressFromStringValue(admin)))
10+let config = valueOrElse(getString(this, "configAddress"), "")
11+
12+let admin = valueOrElse(getString(addressFromStringValue(config), "admin"), "")
13+
14+let wavetroller = valueOrElse(getString(addressFromStringValue(config), "wavetroller"), "")
15+
16+let oracle = valueOrElse(getString(addressFromStringValue(config), "oracle"), "")
17+
18+let assetIdSub = valueOrErrorMessage(getString(this, "assetId"), "No assetId could be found in data storage!")
19+
20+let assetDecimals = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_Decimals")), (("No key " + (assetIdSub + "_Decimals")) + " was found"))
21+
22+let multiplier = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_Multiplier")), (("No key " + (assetIdSub + "_Multiplier")) + " was found"))
23+
24+let kink = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_Kink")), (("No key " + (assetIdSub + "_Kink")) + " was found"))
25+
26+let jumpMultiplier = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_JumpMultiplier")), (("No key " + (assetIdSub + "_JumpMultiplier")) + " was found"))
27+
28+let baseRate = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_BaseRate")), (("No key " + (assetIdSub + "_BaseRate")) + " was found"))
29+
30+let baseExchangeRate = valueOrErrorMessage(getInteger(this, "baseExchangeRate"), "No key baseExchangeRate was found")
31+
32+let collateralFactor = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_CollateralFactor")), (("No key " + (assetIdSub + "_CollateralFactor")) + " was found"))
33+
34+let liquidationThreshold = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_Threshold")), (("No key " + (assetIdSub + "_Threshold")) + " was found"))
35+
36+let reserveFactor = valueOrErrorMessage(getInteger(addressFromStringValue(config), (assetIdSub + "_ReserveFactor")), (("No key " + (assetIdSub + "_ReserveFactor")) + " was found"))
37+
38+let totalBorrow = valueOrElse(getInteger(this, "totalBorrow"), 0)
39+
40+let totalSupply = valueOrElse(getInteger(this, "totalSupply"), 0)
41+
42+let totalReserve = valueOrElse(getInteger(this, "totalReserve"), 0)
43+
44+let dTokenSupply = valueOrErrorMessage(getInteger(this, "dTokenSupply"), "No key dTokenSupply was found")
45+
46+let dTokenDecimals = valueOrErrorMessage(getInteger(this, "dTokenDecimals"), "No key dTokenDecimals was found")
47+
48+let dTokenId = valueOrErrorMessage(getString(this, "dTokenId"), "No key dTokenId was found")
49+
50+let dTokenName = valueOrErrorMessage(getString(this, "dTokenName"), "No key dTokenName was found")
51+
52+let storedHeight = valueOrElse(getInteger(this, "storedHeight"), height)
53+
54+let storedIndex = valueOrElse(getInteger(this, "storedIndex"), 10000000000000000)
55+
56+func isAdminAddress (address) = if ((addressFromStringValue(admin) == address))
1157 then true
1258 else false
1359
1460
15-func checkPool (poolAdd) = if (contains(pools, poolAdd))
61+func isWavetroller (address) = if ((addressFromStringValue(wavetroller) == address))
62+ then true
63+ else false
64+
65+
66+func isAcceptableAssetId (assetId) = if ((assetId == assetIdSub))
1667 then true
1768 else false
1869
1970
2071 func writeString (key,stringValue) = StringEntry(key, stringValue)
2172
2273
2374 func writeInteger (key,integerValue) = IntegerEntry(key, integerValue)
2475
2576
26-func checkPoolLiquidity (poolAddress,amount) = {
27- let totalSupply = getIntegerValue(addressFromStringValue(poolAddress), "totalSupply")
28- let totalBorrow = getIntegerValue(addressFromStringValue(poolAddress), "totalBorrow")
29- let availableLiquidity = (totalSupply - totalBorrow)
30- if ((availableLiquidity >= amount))
31- then true
32- else false
77+func userlockedBalance (userAddress) = valueOrElse(getInteger(this, (userAddress + "_locked")), 0)
78+
79+
80+let utilization = if ((totalSupply > 0))
81+ then fraction(totalBorrow, baseFactor, totalSupply)
82+ else 0
83+
84+let apr = {
85+ let minValue = [utilization, kink]
86+ let minValueItem = min(minValue)
87+ let maxValue = [0, (utilization - kink)]
88+ let maxValueItem = max(maxValue)
89+ ((fraction(multiplier, minValueItem, baseFactor) + fraction(jumpMultiplier, maxValueItem, baseFactor)) + baseRate)
90+ }
91+
92+let apy = fraction(fraction(apr, utilization, baseFactor), (baseFactor - reserveFactor), baseFactor)
93+
94+let borrowRatePerBlock = fraction(apr, baseIndex, (blocksPerYear * baseFactor))
95+
96+let deltaBlocks = (height - storedHeight)
97+
98+let currentIndex = fraction(storedIndex, (baseIndex + (borrowRatePerBlock * deltaBlocks)), baseIndex, CEILING)
99+
100+let currentTotalBorrow = fraction(totalBorrow, currentIndex, storedIndex)
101+
102+let collectedInterest = fraction(totalBorrow, (borrowRatePerBlock * deltaBlocks), baseIndex)
103+
104+let currentTotalSupply = (totalSupply + fraction((baseFactor - reserveFactor), collectedInterest, baseFactor))
105+
106+let currentReserve = (totalReserve + fraction(reserveFactor, collectedInterest, baseFactor))
107+
108+let exchangeRate = if ((dTokenSupply > 0))
109+ then {
110+ let exponent = ((18 - dTokenDecimals) + assetDecimals)
111+ let mantissa = pow(10, 0, exponent, 0, 0, CEILING)
112+ fraction(currentTotalSupply, mantissa, dTokenSupply)
113+ }
114+ else baseExchangeRate
115+
116+func calcDTokenAmount (assetAmount) = {
117+ let exponent = ((18 - dTokenDecimals) + assetDecimals)
118+ let mantissa = pow(10, 0, exponent, 0, 0, CEILING)
119+ fraction(assetAmount, mantissa, exchangeRate)
33120 }
34121
35122
36-func getHealthParameter (user,poolAddress,newDebtAmount,newDebtId,collateralAmount,collateralId) = {
37- let result = invoke(addressFromStringValue(poolAddress), "getUserHealthParameter", [user, collateralAmount, collateralId, newDebtAmount, newDebtId], nil)
38- match result {
39- case t: (Int, Int) =>
40- t
41- case _ =>
42- $Tuple2(0, 0)
43- }
123+func calcAssetAmount (dTokenAmount) = {
124+ let exponent = ((18 - dTokenDecimals) + assetDecimals)
125+ let mantissa = pow(10, 0, exponent, 0, 0, CEILING)
126+ fraction(dTokenAmount, exchangeRate, mantissa)
44127 }
45128
46129
47-func calcHealthFactor (borrowCapacity,borrowCapacityUsed) = fraction((borrowCapacity - borrowCapacityUsed), 1000, borrowCapacity)
48-
49-
50-func calcBorrowCBorrowCU (user,newDebtAmount,newDebtId,collateralAmount,collateralId) = {
51- let poolList = split(pools, ";")
52- let listSize = size(poolList)
53- func foldPools (accum,next) = {
54- let healthParams = getHealthParameter(user, next, newDebtAmount, newDebtId, collateralAmount, collateralId)
55- match healthParams {
56- case t: (Int, Int) =>
57- $Tuple2((accum._1 + healthParams._1), (accum._2 + healthParams._1))
58- case e =>
59- throw("Test")
60- }
61- }
62-
63- let $list22852319 = poolList
64- let $size22852319 = size($list22852319)
65- let $acc022852319 = $Tuple2(0, 0)
66- if (($size22852319 == 0))
67- then $acc022852319
68- else {
69- let $acc122852319 = foldPools($acc022852319, $list22852319[0])
70- if (($size22852319 == 1))
71- then $acc122852319
72- else {
73- let $acc222852319 = foldPools($acc122852319, $list22852319[1])
74- if (($size22852319 == 2))
75- then $acc222852319
76- else {
77- let $acc322852319 = foldPools($acc222852319, $list22852319[2])
78- throw("List size exceed 2")
79- }
80- }
81- }
82- }
83-
84-
85-func checkUserHealth (user,newDebtAmount,newDebtId,collateralAmount,collateralId) = {
86- let bcBcu = calcBorrowCBorrowCU(user, newDebtAmount, newDebtId, collateralAmount, collateralId)
87- let userHealth = calcHealthFactor(bcBcu._1, bcBcu._2)
88- if ((userHealth >= 0))
89- then true
90- else false
130+func getCurrentUserBorrow (user) = {
131+ let storedBorrow = valueOrElse(getIntegerValue(this, (user + "_borrow")), 0)
132+ let storedBorrowIndex = valueOrElse(getIntegerValue(this, (user + "_index")), 0)
133+ if ((storedBorrowIndex > 0))
134+ then fraction(storedBorrow, currentIndex, storedBorrowIndex)
135+ else 0
91136 }
92137
93138
94139 @Callable(i)
95-func borrowFrom (poolAddress,assetId,amount) = if (checkPool(poolAddress))
140+func getUserHealthParameter (user,collateralAmount,collateralId,newDebtAmount,newDebtId) = if (isWavetroller(i.caller))
96141 then {
97- let poolAsset = getStringValue(addressFromStringValue(poolAddress), "assetId")
98- if ((poolAsset == assetId))
99- then if (checkPoolLiquidity(poolAddress, amount))
100- then {
101- let user = toBase58String(i.caller.bytes)
102- if (checkUserHealth(user, amount, assetId, 0, ""))
103- then nil
104- else throw("Borrow exceeds user health!")
105- }
106- else throw("Pool liquidity is not sufficient!")
107- else throw("AssetIds does not match")
142+ let userLocked = valueOrElse(getIntegerValue(this, (user + "_locked")), 0)
143+ let userDTokenCollateral = if ((dTokenId == collateralId))
144+ then (userLocked - collateralAmount)
145+ else userLocked
146+ let currentUserBorrow = if ((newDebtId == assetIdSub))
147+ then (getCurrentUserBorrow(user) + newDebtAmount)
148+ else getCurrentUserBorrow(user)
149+ let userCollateral = calcAssetAmount(userDTokenCollateral)
150+ let assetPrice = invoke(addressFromStringValue(oracle), "getPrice", [assetIdSub], nil)
151+ match assetPrice {
152+ case t: Int =>
153+ let collateralValue = fraction(collateralFactor, userCollateral, baseFactor)
154+ let mantissa = pow(10, 0, assetDecimals, 0, 0, CEILING)
155+ let bCSummand = fraction(collateralValue, t, mantissa)
156+ let borrowInUSD = fraction(currentUserBorrow, t, mantissa)
157+ let bCUSummand = fraction(borrowInUSD, baseFactor, liquidationThreshold)
158+ $Tuple2(nil, $Tuple2(bCSummand, bCUSummand))
159+ case _ =>
160+ throw("Incorrect pricing")
108161 }
109- else throw("Pool address not found!")
162+ }
163+ else throw("Address does not match with wavetroller address!")
110164
111165
112166
113167 @Callable(i)
114-func setup (configAddress,pools) = if (if (!(isDefined(getString(this, "config"))))
115- then !(isDefined(getString(this, "pools")))
116- else false)
117- then [writeString("config", configAddress), writeString("pools", makeString(pools, ";"))]
118- else throw("Admin and config address already definied!")
168+func deposit (user,isCollateral) = if (isWavetroller(i.caller))
169+ then {
170+ let userTokenAmount = calcDTokenAmount(i.payments[0].amount)
171+ let currentDTokenSupply = (dTokenSupply + userTokenAmount)
172+ if (isCollateral)
173+ then {
174+ let lockedUserBalance = (userlockedBalance(user) + userTokenAmount)
175+ $Tuple2([writeInteger((user + "_locked"), lockedUserBalance), writeInteger("dTokenSupply", currentDTokenSupply), writeInteger("totalBorrow", currentTotalBorrow), writeInteger("totalSupply", (currentTotalSupply + i.payments[0].amount)), writeInteger("totalReserve", currentReserve), writeInteger("storedIndex", currentIndex), writeInteger("storedHeight", height), Reissue(fromBase58String(dTokenId), userTokenAmount, true)], ((toString(i.payments[0].amount) + dTokenName) + "were successfully locked"))
176+ }
177+ else $Tuple2([writeInteger("dTokenSupply", currentDTokenSupply), writeInteger("totalBorrow", currentTotalBorrow), writeInteger("totalSupply", (currentTotalSupply + i.payments[0].amount)), writeInteger("totalReserve", currentReserve), writeInteger("storedIndex", currentIndex), writeInteger("storedHeight", height), Reissue(fromBase58String(dTokenId), userTokenAmount, true), ScriptTransfer(i.caller, userTokenAmount, fromBase58String(dTokenId))], userTokenAmount)
178+ }
179+ else throw("Address does not match with wavetroller address!")
119180
120181
121182
122183 @Callable(i)
123-func addPool (poolAddress) = if (isAdmin(i.caller))
184+func withdraw (user) = if (isWavetroller(i.caller))
124185 then {
125- let poolList = split(pools, ";")
126- if ((containsElement(poolList, poolAddress) == false))
127- then {
128- let newPools = (poolList :+ poolAddress)
129-[writeString("pools", makeString(newPools, ";"))]
130- }
131- else throw("Pool already exists!")
186+ let availableLiquidity = (currentTotalSupply - currentTotalBorrow)
187+ let requestedAssetAmount = calcAssetAmount(i.payments[0].amount)
188+ if ((availableLiquidity >= requestedAssetAmount))
189+ then $Tuple2([writeInteger("dTokenSupply", (dTokenSupply - i.payments[0].amount)), writeInteger("totalBorrow", currentTotalBorrow), writeInteger("totalSupply", (currentTotalSupply - requestedAssetAmount)), writeInteger("totalReserve", currentReserve), writeInteger("storedIndex", currentIndex), writeInteger("storedHeight", height), Burn(fromBase58String(dTokenId), i.payments[0].amount), if ((assetIdSub == "WAVES"))
190+ then ScriptTransfer(i.caller, requestedAssetAmount, unit)
191+ else ScriptTransfer(i.caller, requestedAssetAmount, fromBase58String(assetIdSub))], requestedAssetAmount)
192+ else throw("Pool liquidity is not sufficient!")
132193 }
133- else throw("Address does not match with admin address!")
194+ else throw("Address does not match with wavetroller address!")
134195
135196
136197
137198 @Callable(i)
138-func updateConfig (configAddress) = if (isAdmin(i.caller))
139- then [writeString("config", configAddress)]
140- else throw("Address does not match with admin address!")
199+func lockAsCollateral (user) = if (isWavetroller(i.caller))
200+ then {
201+ let newLockedBalance = (userlockedBalance(user) + i.payments[0].amount)
202+ $Tuple2([writeInteger((user + "_locked"), newLockedBalance), writeInteger("totalBorrow", currentTotalBorrow), writeInteger("totalSupply", currentTotalSupply), writeInteger("totalReserve", currentReserve), writeInteger("storedIndex", currentIndex), writeInteger("storedHeight", height)], ((toString(i.payments[0].amount) + dTokenName) + "were successfully locked"))
203+ }
204+ else throw("Address does not match with wavetroller address!")
141205
142206
143207
144208 @Callable(i)
145-func depositAt (poolAddress,isCollateral) = if (checkPool(poolAddress))
146- then if ((size(i.payments) > 0))
147- then {
148- let user = toBase58String(i.caller.bytes)
149- let tokenAmount = invoke(addressFromStringValue(poolAddress), "deposit", [user, isCollateral], i.payments)
150- if ((tokenAmount == tokenAmount))
151- then {
152- let tokenId = getStringValue(addressFromStringValue(poolAddress), "dTokenId")
153- match tokenAmount {
154- case t: Int =>
155-[ScriptTransfer(i.caller, t, fromBase58String(tokenId))]
156- case t: String =>
157- nil
158- case _ =>
159- throw("Incorrect invoke result!")
160- }
161- }
162- else throw("Strict value is not equal to itself.")
163- }
164- else throw("No payment attached!")
165- else throw("Pool address not found!")
209+func borrow (user,amount) = if (isWavetroller(i.caller))
210+ then {
211+ let currentUserBorrow = getCurrentUserBorrow(user)
212+ $Tuple2([writeInteger((user + "_borrow"), (currentUserBorrow + amount)), writeInteger((user + "_index"), currentIndex), writeInteger("totalBorrow", (currentTotalBorrow + amount)), writeInteger("totalSupply", currentTotalSupply), writeInteger("totalReserve", currentReserve), writeInteger("storedIndex", currentIndex), writeInteger("storedHeight", height), if ((assetIdSub == "WAVES"))
213+ then ScriptTransfer(i.caller, amount, unit)
214+ else ScriptTransfer(i.caller, amount, fromBase58String(assetIdSub))], amount)
215+ }
216+ else throw("Address does not match with wavetroller address!")
166217
167218
168219
169220 @Callable(i)
170-func withdrawFrom (poolAddress) = if (checkPool(poolAddress))
221+func setup (aId,configAdd,baseExchangeRate,tokenName,tokenDescription) = if (!(isDefined(getString(this, "configAddress"))))
171222 then {
172- let dTokenId = getStringValue(addressFromStringValue(poolAddress), "dTokenId")
173- if ((fromBase58String(dTokenId) == i.payments[0].assetId))
174- then if ((size(i.payments) > 0))
175- then {
176- let user = toBase58String(i.caller.bytes)
177- let tokenAmount = invoke(addressFromStringValue(poolAddress), "withdraw", [user], i.payments)
178- if ((tokenAmount == tokenAmount))
179- then {
180- let tokenId = getStringValue(addressFromStringValue(poolAddress), "assetId")
181- match tokenAmount {
182- case t: Int =>
183- if ((tokenId == "WAVES"))
184- then [ScriptTransfer(i.caller, t, unit)]
185- else [ScriptTransfer(i.caller, t, fromBase58String(tokenId))]
186- case t: String =>
187- nil
188- case _ =>
189- throw("Incorrect invoke result!")
190- }
191- }
192- else throw("Strict value is not equal to itself.")
193- }
194- else throw("No payment attached!")
195- else throw("AssetIds does not match")
223+ let asset = Issue(tokenName, tokenDescription, 0, 8, true)
224+ let tokenId = calculateAssetId(asset)
225+[asset, writeString("assetId", aId), writeString("configAddress", configAdd), IntegerEntry("totalBorrow", 0), IntegerEntry("totalSupply", 0), IntegerEntry("totalReserve", 0), IntegerEntry("storedIndex", baseIndex), IntegerEntry("storedHeight", height), IntegerEntry("baseExchangeRate", baseExchangeRate), writeString("dTokenName", tokenName), writeString("dTokenId", toBase58String(tokenId)), IntegerEntry("dTokenDecimals", 8), IntegerEntry("dTokenSupply", 0)]
196226 }
197- else throw("Pool address not found!")
227+ else throw("Pool already setup!")
198228
199229
200230
201231 @Callable(i)
202-func lockAsCollateralAt (poolAddress) = if (checkPool(poolAddress))
203- then {
204- let dTokenId = getStringValue(addressFromStringValue(poolAddress), "dTokenId")
205- if ((fromBase58String(dTokenId) == i.payments[0].assetId))
206- then if ((size(i.payments) > 0))
207- then {
208- let user = toBase58String(i.caller.bytes)
209- let msg = invoke(addressFromStringValue(poolAddress), "lockAsCollateral", [user], i.payments)
210- if ((msg == msg))
211- then match msg {
212- case t: String =>
213- nil
214- case _ =>
215- throw("Incorrect invoke result!")
216- }
217- else throw("Strict value is not equal to itself.")
218- }
219- else throw("No payment attached!")
220- else throw("AssetIds does not match")
221- }
222- else throw("Pool address not found!")
232+func writeEntry (name,data) = [writeString(name, data)]
223233
234+
235+@Verifier(tx)
236+func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
224237

github/deemru/w8io/169f3d6 
49.40 ms