tx · 82mzXussvGY3hQ9jBr3aEkBt1ABcjUYEpxADx4r1fm4Q

3MsGji5z9nkRgi7QUd9TgnViDoDJwUPht9n:  -0.05000000 Waves

2023.07.12 15:24 [2662676] smart account 3MsGji5z9nkRgi7QUd9TgnViDoDJwUPht9n > SELF 0.00000000 Waves

{ "type": 13, "id": "82mzXussvGY3hQ9jBr3aEkBt1ABcjUYEpxADx4r1fm4Q", "fee": 5000000, "feeAssetId": null, "timestamp": 1689164703083, "version": 2, "chainId": 84, "sender": "3MsGji5z9nkRgi7QUd9TgnViDoDJwUPht9n", "senderPublicKey": "22ybxrUfke8vvVQss84AhBXq6DeHBFvSXHU6bwt6McQS", "proofs": [ "SpVmgz36hSJHBxJQozhbuqpq8or9zsrPmWBb3EqxkxFbzkJPjraeBzpPq7EVkMqSNCcpwR8Uz5oqUDcaRvacARm" ], "script": "base64:BgLzFQgCEgMKAQgSBAoCCAgSAwoBCBIDCgEIEgASABIAEgMKAQESBAoCCAESAwoBCBIDCgEIIgNTRVAiCVBSRUNJU0lPTiIDREFZIgRZRUFSIghJTkZJTklUWSIQTUlOX0FNT1VOVF9ERUxUQSIRTElRVUlEQVRJT05fQk9OVVMiFE1BWF9MSVFVSURBVElPTl9QQVJUIg1TVEFCSUxJVFlfRkVFIgdFTkFCTEVEIghESVNBQkxFRCINSWR4VmF1bHRDb3VudCISSWR4VmF1bHRFYXN0QW1vdW50IhFJZHhWYXVsdFRpbWVzdGFtcCIPSWR4U3RhYmlsaXR5RmVlIg9JZHhMYXN0RnJhY3Rpb24iBGRpdnAiAl94IgJfeSIEbXVscCIIY29udjZ0bzgiAl92Ighjb252OHRvNiIEam9pbiICYXIiDmtleUluaXRpYWxpemVkIhVrZXlDb29yZGluYXRvckFkZHJlc3MiEmtleVZlcmlmaWVyQWRkcmVzcyIQa2V5TWludGVyQWRkcmVzcyISa2V5VHJlYXN1cnlBZGRyZXNzIgxrZXlFYXN0QXNzZXQiDWtleVZhdWx0QXNzZXQiB2FkZHJlc3MiBWFzc2V0IgxrZXlWYXVsdERhdGEiE2tleUxpcXVpZGF0aW9uQm9udXMiD2tleVN0YWJpbGl0eUZlZSIRa2V5TWluQW1vdW50RGVsdGEiCWtleVNpZ25lZCIIX2FkZHJlc3MiBV90eElkIhFrZXlQcm90b2NvbEFjdGl2ZSINaXNJbml0aWFsaXplZCIPbXVzdEluaXRpYWxpemVkIhJtdXN0Tm90SW5pdGlhbGl6ZWQiCG11c3RTZWxmIgFpIgtjb29yZGluYXRvciIIdmVyaWZpZXIiByRtYXRjaDAiAXMiCmdldEFkZHJlc3MiA2tleSIDZXJyIhBnZXRNaW50ZXJBZGRyZXNzIhJnZXRUcmVhc3VyeUFkZHJlc3MiDWlzTm90VHJlYXN1cnkiEWdldE1pbkFtb3VudERlbHRhIhNnZXRMaXF1aWRhdGlvbkJvbnVzIg9nZXRTdGFiaWxpdHlGZWUiD2dldEVhc3RBc3NldFN0ciIMZ2V0RWFzdEFzc2V0Ighpc0FjdGl2ZSIKbXVzdEFjdGl2ZSIRbXVzdE5vdFZhdWx0T3duZXIiEm11c3RIYXZlT25lUGF5bWVudCIRbXVzdEhhdmVOb1BheW1lbnQiDWhhc09uZVBheW1lbnQiCmlzUG9zaXRpdmUiBm51bWJlciINaXNOb3ROZWdhdGl2ZSILZ2V0U3VidmF1bHQiEGlzU3VidmF1bHRFeGlzdHMiDmdldEFzc2V0U3RyaW5nIgFwIgdhc3NldElkIhRnZXRBc3NldElkRnJvbVN0cmluZyIHaXNBc3NldCINY2hlY2tpbmdBc3NldCICYnYiBG5hbWUiByRtYXRjaDEiDHBheW1lbnRBc3NldCIMY2hlY2tBZGRyZXNzIhZnZXRDdXJyZW50VGltZXN0YW1wU2VjIg5JZHhBc3NldFN0YXR1cyISSWR4QXNzZXRDb250cmFjdElkIghrZXlBc3NldCIJX2Fzc2V0U3RyIg5rZXlWYXVsdEFzc2V0cyIYa2V5Q3VtdWxhdGl2ZUZlZUZyYWN0aW9uIhZrZXlGcmFjdGlvbkxhc3RVcGRhdGVkIhNnZXRBc3NldENvbnRyYWN0U3RyIgZfYXNzZXQiEGdldEFzc2V0Q29udHJhY3QiC2NvbnRyYWN0U3RyIgtjb250cmFjdEFyciIKY29udHJhY3RJZCIOZ2V0VmF1bHRBc3NldHMiDGdldFZhdWx0RGF0YSIFdmF1bHQiBWNvdW50IgplYXN0QW1vdW50Igl0aW1lc3RhbXAiEGxhc3RTdGFiaWxpdHlGZWUiDGxhc3RGcmFjdGlvbiIKYXNzZXRFeGlzdCIYZ2V0Q3VtdWxhdGl2ZUZlZUZyYWN0aW9uIhZnZXRGcmFjdGlvbkxhc3RVcGRhdGVkIglpc0VuYWJsZWQiCGFzc2V0Q2ZnIghhc3NldEFyciINaXNWYXVsdEV4aXN0cyIWZ2V0Q3VycmVudFN0YWJpbGl0eUZlZSILX2Vhc3RBbW91bnQiEV9sYXN0U3RhYmlsaXR5RmVlIg1fbGFzdEZyYWN0aW9uIglkYXRhQXNzZXQiB19zdGF0dXMiC3VwZGF0ZVZhdWx0IghfcGFpZEZlZSINJHQwMTM2MjYxMzcxNyINbmV3RWFzdEFtb3VudCIIbmV3Q291bnQiD25ld1N0YWJpbGl0eUZlZSINYWRkVmF1bHRBc3NldCIGYXNzZXRzIhNfY29vcmRpbmF0b3JBZGRyZXNzIgZjaGVja3MiDF9jb250cmFjdFN0ciIFZGVsdGEiDWZyYWN0aW9uRGVsdGEiFWN1bXVsYXRpdmVGZWVGcmFjdGlvbiIHcGF5bWVudCIIYXNzZXRTdHIiEGRvVXBkYXRlRnJhY3Rpb24iBGVycjEiCGNvbnRyYWN0Ig0kdDAxNjk3MzE3MDczIgFAIgZlYXN0RXEiCmFzc2V0VmF1bHQiDHVwZGF0ZWRWYXVsdCIGbWludGVyIgtkb0lzc3VlRWFzdCIJZWFzdEFzc2V0IhF2YXVsdEFzc2V0QWN0aW9ucyIRdXBkYXRlZFZhdWx0QXNzZXQiB19hbW91bnQiDSR0MDE4ODU2MTg5NzIiA2ZlZSICbHIiAmJyIgV1c2RFcSINZWFzdEF2YWlsYWJsZSIEZXJyMiINJHQwMTk5OTYyMDExMiINJHQwMjAxMTYyMTEyNCINdG90YWxFYXN0T3dlZCIBayIKZWFzdFRvQnVybiIMZWFzdFRvUGF5RmVlIgRlcnIzIg90cmVhc3VyeUFkZHJlc3MiC2Vhc3RBY3Rpb25zIgxhc3NldEFjdGlvbnMiDSR0MDIxMjE5MjEzNTIiC2Nsb3NlZFVzZEVxIgxjbG9zZWRFYXN0RXEiCW5ld0Vhc3RFcSISb3ZlcmNvbGxhdGVyYWxpemVkIgRlMWUyIgRlMmUxIhltYXhMaXF1aWRhdGVBbW91bnRBbGxvd2VkIg0kdDAyMjgzNDIyOTg1IhNhdmdMaXF1aWRhdGlvblJhdGlvIhNjdXJyZW50QmFja2luZ1JhdGlvIg9wYXltZW50QW1vdW50RDgiEGxpcXVpZGF0aW9uQ29lZmYiF2xpcXVpZGF0aW9uRWFzdEFtb3VudEQ4IhBsaXF1aWRhdGlvblJhdGlvIhFsaXF1aWRhdG9yQWRkcmVzcyIPbGlxdWlkYXRlQXNzZXRzIgNhY2MiBG5leHQiBWNoZWNrIgF2Ig0kdDAyMzgwMTIzOTUzIhBsaXF1aWRhdGVkRWFzdEVxIgdhY3Rpb25zIg0kdDAyNDMwMTI0Mzg4IgIkbCICJHMiBSRhY2MwIgUkZjBfMSICJGEiAiRpIgUkZjBfMiISdmF1bHRBc3NldHNBY3Rpb25zIglwb3N0Q2hlY2siCG5ld1VzZEVxIgR1MWUyIgR1MmUxIgRlcnI0Igx2YXVsdEFjdGlvbnMiBmV4aXN0cyIOY291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AAIBAi1Qcm90b2NvbCBpcyBkaXNhYmxlZC4gUGxlYXNlIGNvbnRhY3Qgc3VwcG9ydC4FBHVuaXQBAmFtAgFVAUcDCQAAAgkA2AQBCAgFAVUGY2FsbGVyBWJ5dGVzBQFHCQACAQIcU2VsZiBpbnZvY2F0aW9uIG5vdCBhbGxvd2VkLgUEdW5pdAECYW4BAVUDCQECIT0CCQCQAwEIBQFVCHBheW1lbnRzAAEJAAIBAhZNdXN0IGhhdmUgb25lIHBheW1lbnQuBQR1bml0AQJhbwEBVQMJAQIhPQIJAJADAQgFAVUIcGF5bWVudHMAAAkAAgECE05vIHBheW1lbnQgYWxsb3dlZC4FBHVuaXQBAmFwAQFVCQAAAgkAkAMBCAUBVQhwYXltZW50cwABAQJhcQECYXIDCQBnAgAABQJhcgkAAgECHUF0dHJpYnV0ZSBzaG91bGQgYmUgcG9zaXRpdmUuBQR1bml0AQJhcwECYXIDCQBmAgAABQJhcgkAAgECJUF0dHJpYnV0ZSBzaG91bGQgYmUgcG9zaXRpdmUgb3IgemVyby4FBHVuaXQBAmF0AgFHAUgJAKIIAQkBAUYCBQFHBQFIAQJhdQIBRwFICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAQJhdAIFAUcFAUgCEFZhdWx0IG5vdCBleGlzdHMBAmF2AQJhdwQBWAgFAmF3B2Fzc2V0SWQDCQABAgUBWAIKQnl0ZVZlY3RvcgQCYXgFAVgJANgEAQUCYXgDCQABAgUBWAIEVW5pdAIFV0FWRVMJAAIBAgtNYXRjaCBlcnJvcgECYXkBAmF4AwkAAAIFAmF4AgVXQVZFUwUEdW5pdAkA2QQBBQJheAECYXoCAmF3AmFBBAJheAQBWAUCYUEDCQABAgUBWAIKQnl0ZVZlY3RvcgQCYUIFAVgFAmFCAwkAAQIFAVgCBlN0cmluZwQBWQUBWAkBAmF5AQUBWQMJAAECBQFYAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IEAVgFAmF4AwkAAQIFAVgCCkJ5dGVWZWN0b3IEAmFCBQFYBAJhQwQCYUQJAOwHAQUCYUIDCQABAgUCYUQCBUFzc2V0BAFIBQJhRAgFAUgEbmFtZQMJAAECBQJhRAIEVW5pdAkAAgEJAKwCAgIRQ2FuJ3QgZmluZCBhc3NldCAJANgEAQUCYUIJAAIBAgtNYXRjaCBlcnJvcgQCYWIJAAIBCQCsAgICHkF0dGFjaGVkIHBheW1lbnQgYXNzZXQgaXMgbm90IAUCYUMEAmFECAUCYXcHYXNzZXRJZAMJAAECBQJhRAIKQnl0ZVZlY3RvcgQCYUUFAmFEAwkBAiE9AgUCYUUFAmF4BQJhYgUEdW5pdAMJAAECBQJhRAIEVW5pdAUCYWIJAAIBAgtNYXRjaCBlcnJvcgMJAAECBQFYAgRVbml0AwkBAiE9AggFAmF3B2Fzc2V0SWQFBHVuaXQJAAIBAiNBdHRhY2hlZCBwYXltZW50IGFzc2V0IGlzIG5vdCBXQVZFUwUEdW5pdAkAAgECC01hdGNoIGVycm9yAQJhRgEBTgQBWAkApggBBQFOAwkAAQIFAVgCB0FkZHJlc3MEAUcFAVgGAwkAAQIFAVgCBFVuaXQJAAIBAg9JbnZhbGlkIGFkZHJlc3MJAAIBAgtNYXRjaCBlcnJvcgECYUcACQBpAggFCWxhc3RCbG9jawl0aW1lc3RhbXAA6AcAAmFIAAEAAmFJAAIBAmFKAQJhSwkBAXgBCQDMCAICBCVzJXMJAMwIAgIFYXNzZXQJAMwIAgUCYUsFA25pbAECYUwBAU4JAQF4AQkAzAgCAgQlcyVzCQDMCAICC3ZhdWx0QXNzZXRzCQDMCAIFAU4FA25pbAECYU0ACQEBeAEJAMwIAgICJXMJAMwIAgIVY3VtdWxhdGl2ZUZlZUZyYWN0aW9uBQNuaWwBAmFOAAkBAXgBCQDMCAICAiVzCQDMCAICE2ZyYWN0aW9uTGFzdFVwZGF0ZWQFA25pbAECYU8BAmFQCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBAmFKAQUCYVACDVVua25vd24gYXNzZXQBAmFRAQJhUAQCYVIJAQJhTwEFAmFQBAJhUwkAtQkCBQJhUgUBYQQCYVQJAJEDAgUCYVMFAmFJCQERQGV4dHJOYXRpdmUoMTA2MikBBQJhVAECYVUBAU4EAVgJAKIIAQkBAmFMAQUBTgMJAAECBQFYAgZTdHJpbmcEAVkFAVgJALUJAgUBWQUBYQMJAAECBQFYAgRVbml0BQNuaWwJAAIBAgtNYXRjaCBlcnJvcgECYVYBAU4EAmFXBAFYCQCiCAEJAQFJAQUBTgMJAAECBQFYAgZTdHJpbmcEAVkFAVgJALUJAgUBWQUBYQMJAAECBQFYAgRVbml0CQDMCAICCiVkJWQlZCVkJWQJAMwIAgIBMAkAzAgCAgEwCQDMCAIJAKQDAQkBAmFHAAkAzAgCAgEwCQDMCAICATAFA25pbAkAAgECC01hdGNoIGVycm9yBAJhWAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmFXBQFsBAJhWQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmFXBQFtBAJhWgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmFXBQFuBAJiYQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmFXBQFvBAJiYgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmFXBQFwCQCXCgUFAmFZBQJiYQUCYmIFAmFaBQJhWAECYmMBAmFLBAFYCQCiCAEJAQJhSgEFAmFLAwkAAQIFAVgCBlN0cmluZwQBWQUBWAYDCQABAgUBWAIEVW5pdAcJAAIBAgtNYXRjaCBlcnJvcgECYmQACQELdmFsdWVPckVsc2UCCQCfCAEJAQJhTQAAAAECYmUACQELdmFsdWVPckVsc2UCCQCfCAEJAQJhTgAJAQJhRwABAmJmAQJhSwQCYmcJARFAZXh0ck5hdGl2ZSgxMDU4KQEJAQJhSgEFAmFLBAJiaAkAtQkCBQJiZwUBYQMJAQIhPQIJAJEDAgUCYmgFAmFIBQFqCQACAQkArAICCQCsAgICBkFzc2V0IAUCYUsCDyBpcyBub3QgZW5hYmxlZAUEdW5pdAECYmkBAU4DCQAAAgkAkAMBCQECYVUBBQFOAAAJAAIBAhJWYXVsdCBpcyBub3QgZXhpc3QFBHVuaXQBAmJqAwJiawJibAJibQkAZAIFAmJsCQEBdAIFAmJrCQBlAgkBAmJkAAUCYm0BAmJuAgJibwFOCQC5CQIJAMwIAgIEJXMlcwkAzAgCBQJibwkAzAgCBQFOBQNuaWwFAWEBAmJwAwFOAmJrAmJxBAJicgkBAmFWAQUBTgQCYVkIBQJicgJfMQQCYmEIBQJicgJfMgQCYmIIBQJicgJfMwQCYVoIBQJicgJfNAQCYVgIBQJicgJfNQQCYnMJAGQCBQJhWQUCYmsEAmJ0CQBkAgUCYVgAAQMJAGYCAAAFAmJzCQACAQIlU29tZXRoaW5nIHdlbnQgd3JvbmcuIENvbnRhY3Qgc3VwcG9ydAQCYnUJAGUCCQECYmoDBQJhWQUCYmEFAmJiBQJicQkAuQkCCQDMCAICCiVkJWQlZCVkJWQJAMwIAgkApAMBBQJidAkAzAgCCQCkAwEFAmJzCQDMCAIJAKQDAQkBAmFHAAkAzAgCCQCkAwEFAmJ1CQDMCAIJAKQDAQkBAmJkAAUDbmlsBQFhAQJidgIBTgJhSwQCYncJAQJhVQEFAU4DCQEPY29udGFpbnNFbGVtZW50AgUCYncFAmFLCQACAQIUQXNzZXQgYWxyZWFkeSBleGlzdHMJALkJAgkAzQgCBQJidwUCYUsFAWELAVUBCmluaXRpYWxpemUBAmJ4BAJieQkAzAgCCQEBVAEFAVUJAMwIAgkBAVMACQDMCAIJAQJhRgEFAmJ4BQNuaWwDCQAAAgUCYnkFAmJ5CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFBAAUCYngJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAQF6AAYFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFVAQhhZGRBc3NldAICYUsCYnoEAmJ5CQDMCAIJAQFSAAkAzAgCCQEBVAEFAVUFA25pbAMJAAACBQJieQUCYnkDCQEBIQEJAQJhRgEFAmJ6CQACAQIUQWRkcmVzcyBpcyBub3QgdmFsaWQDCQECYmMBBQJhSwkAAgECFEFzc2V0IGlzIGFscmVhZHkgc2V0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhSgEFAmFLCQECYm4CBQFqBQJiegUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAVUBDGRpc2FibGVBc3NldAECYUsEAmJ5CQDMCAIJAQFSAAkAzAgCCQEBVAEFAVUFA25pbAMJAAACBQJieQUCYnkEAmJoCQC1CQIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQECYUoBBQJhSwINVW5rbm93biBhc3NldAUBYQkAzAgCCQELU3RyaW5nRW50cnkCCQECYUoBBQJhSwkBAmJuAgUBawkAkQMCBQJiaAUCYUkFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFVAQtlbmFibGVBc3NldAECYUsEAmJ5CQDMCAIJAQFSAAkAzAgCCQEBVAEFAVUFA25pbAMJAAACBQJieQUCYnkEAmJoCQC1CQIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQECYUoBBQJhSwINVW5rbm93biBhc3NldAUBYQkAzAgCCQELU3RyaW5nRW50cnkCCQECYUoBBQJhSwkBAmJuAgUBagkAkQMCBQJiaAUCYUkFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFVAQ51cGRhdGVGcmFjdGlvbgAEAmJBCQBlAgkBAmFHAAkBAmJlAAQCYkIJAQF0AgkBAXECBQJiQQUBZAkBAmFoAAQCYkMJAGQCCQECYmQABQJiQgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAmFNAAUCYkMJAMwIAgkBDEludGVnZXJFbnRyeQIJAQJhTgAJAQJhRwAFA25pbAFVAQRtaW50AAQCYkQJAJEDAggFAVUIcGF5bWVudHMAAAQCYkUJAQJhdgEFAmJEBAFHCQDYBAEICAUBVQZjYWxsZXIFYnl0ZXMEAmJ5CQDMCAIJAQJhbAAJAMwIAgkBAmFuAQUBVQkAzAgCCQECYmYBBQJiRQUDbmlsAwkAAAIFAmJ5BQJieQQCYkYJAPwHBAUEdGhpcwIOdXBkYXRlRnJhY3Rpb24FA25pbAUDbmlsAwkAAAIFAmJGBQJiRgQCYkcJAAIBAilVbmFibGUgdG8gcHJvY2VlZC4gVG9vIGZldyBhc3NldHMgdG8gbWludAMJAGYCCQECYWYACAUCYkQGYW1vdW50BQJiRwQCYkgJAQJhUQEFAmJFBAJiSQoAAmJKCQD8BwQFAmJIAgRtaW50CQDMCAIFAUcFA25pbAgFAVUIcGF5bWVudHMDCQABAgUCYkoCDShTdHJpbmcsIEludCkFAmJKCQACAQkArAICCQADAQUCYkoCIiBjb3VsZG4ndCBiZSBjYXN0IHRvIChTdHJpbmcsIEludCkDCQAAAgUCYkkFAmJJBAJiSwgFAmJJAl8yBAJiTAgFAmJJAl8xBAJhWQkBAXcBBQJiSwQCYk0JAQJicAMFAUcFAmFZAAAEAmJOCQECYWMABAJiTwkA/AcEBQJiTgIFaXNzdWUJAMwIAgUCYVkFA25pbAUDbmlsAwkAAAIFAmJPBQJiTwQCYncJAQJhVQEFAUcEAmJQCQECYWoABAJiUQMJAQEhAQkBD2NvbnRhaW5zRWxlbWVudAIFAmJ3BQJiRQkAzAgCCQELU3RyaW5nRW50cnkCCQECYUwBBQFHCQECYnYCBQFHBQJiRQUDbmlsBQNuaWwJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCCQEBSQEFAUcFAmJNCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFGAgUBRwUCYkUFAmJMCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFVBmNhbGxlcgUCYVkFAmJQBQNuaWwFAmJRCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAVUBBnN1cHBseQAEAmJECQCRAwIIBQFVCHBheW1lbnRzAAAEAUcJANgEAQgIBQFVBmNhbGxlcgVieXRlcwQBSAkBAmF2AQkAkQMCCAUBVQhwYXltZW50cwAABAJieQkAzAgCCQECYWwACQDMCAIJAQJhbgEFAVUJAMwIAgkBAmF1AgUBRwUBSAkAzAgCCQECYmYBBQFIBQNuaWwDCQAAAgUCYnkFAmJ5BAJiRgkA/AcEBQR0aGlzAg51cGRhdGVGcmFjdGlvbgUDbmlsBQNuaWwDCQAAAgUCYkYFAmJGBAJiRwkAAgECK1VuYWJsZSB0byBwcm9jZWVkLiBUb28gZmV3IGFzc2V0cyB0byBzdXBwbHkDCQBmAgkBAmFmAAgFAmJEBmFtb3VudAUCYkcEAmJICQECYVEBBQFIBAJiUgoAAmJKCQD8BwQFAmJIAgZzdXBwbHkJAMwIAgUBRwUDbmlsCAUBVQhwYXltZW50cwMJAAECBQJiSgIGU3RyaW5nBQJiSgkAAgEJAKwCAgkAAwEFAmJKAhsgY291bGRuJ3QgYmUgY2FzdCB0byBTdHJpbmcDCQAAAgUCYlIFAmJSCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFGAgUBRwUBSAUCYlIFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFVAQdyZWlzc3VlAQJiUwQBRwkA2AQBCAgFAVUGY2FsbGVyBWJ5dGVzBAJieQkAzAgCCQECYWwACQDMCAIJAQJhcQEFAmJTCQDMCAIJAQJhbwEFAVUJAMwIAgkBAmJpAQUBRwUDbmlsAwkAAAIFAmJ5BQJieQQCYkYJAPwHBAUEdGhpcwIOdXBkYXRlRnJhY3Rpb24FA25pbAUDbmlsAwkAAAIFAmJGBQJiRgQCYkcJAAIBAipVbmFibGUgdG8gcHJvY2VlZC4gVG9vIGZldyBFQVNUIHRvIHJlaXNzdWUDCQBmAgkBAmFmAAUCYlMFAmJHBAJhWQgJAQJhVgEFAUcCXzEEAmJUCgACYkoJAPwHBAUEdGhpcwIMZ2V0VmF1bHRJbmZvCQDMCAIFAUcFA25pbAUDbmlsAwkAAQIFAmJKAhkoSW50LCBJbnQsIEludCwgSW50LCBJbnQpBQJiSgkAAgEJAKwCAgkAAwEFAmJKAi4gY291bGRuJ3QgYmUgY2FzdCB0byAoSW50LCBJbnQsIEludCwgSW50LCBJbnQpAwkAAAIFAmJUBQJiVAQCYlUIBQJiVAJfNQQCYlYIBQJiVAJfNAQCYlcIBQJiVAJfMwQCYksIBQJiVAJfMgQCYlgIBQJiVAJfMQQCYlkJAGUCCQEBdwEFAmJLBQJhWQQCYloJAAIBCQCsAgIJAKwCAgIYVW5hYmxlIHRvIHJlaXNzdWUuIE9ubHkgCQCkAwEFAmJZAhAgRUFTVCBhdmFpbGFibGUuAwkAZgIFAmJTBQJiWQUCYloEAmJNCQECYnADBQFHBQJiUwAABAJiTgkBAmFjAAQCYk8JAPwHBAUCYk4CBWlzc3VlCQDMCAIFAmJTBQNuaWwFA25pbAMJAAACBQJiTwUCYk8EAmJQCQECYWoACQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFJAQUBRwUCYk0JAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAVUGY2FsbGVyBQJiUwUCYlAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFVAQVjbG9zZQICYVACYlMEAUcJANgEAQgIBQFVBmNhbGxlcgVieXRlcwQCYlAJAQJhagAEAmJ5CQDMCAIJAQJhbAAJAMwIAgkBAmFzAQUCYlMJAMwIAgkBAmJpAQUBRwkAzAgCAwkBAmFwAQUBVQkBAmF6AgkAkQMCCAUBVQhwYXltZW50cwAABQJiUAkBAmFvAQUBVQkAzAgCAwkAZgIFAmJTAAAJAMwIAgkBAmF1AgUBRwUCYVAFA25pbAUEdW5pdAUDbmlsAwkAAAIFAmJ5BQJieQQCYkYJAPwHBAUEdGhpcwIOdXBkYXRlRnJhY3Rpb24FA25pbAUDbmlsAwkAAAIFAmJGBQJiRgQCYVkICQECYVYBBQFHAl8xBAJjYQoAAmJKCQD8BwQFBHRoaXMCDGdldFZhdWx0SW5mbwkAzAgCBQFHBQNuaWwFA25pbAMJAAECBQJiSgIZKEludCwgSW50LCBJbnQsIEludCwgSW50KQUCYkoJAAIBCQCsAgIJAAMBBQJiSgIuIGNvdWxkbid0IGJlIGNhc3QgdG8gKEludCwgSW50LCBJbnQsIEludCwgSW50KQMJAAACBQJjYQUCY2EEAmJVCAUCY2ECXzUEAmJWCAUCY2ECXzQEAmJXCAUCY2ECXzMEAmJLCAUCY2ECXzIEAmJYCAUCY2ECXzEEAmNiAwkBAmFwAQUBVQQCYkQJAJEDAggFAVUIcGF5bWVudHMAAAQCY2MJAGQCBQJhWQUCYlUEAmNkCQEBcQIFAmFZBQJjYwQCY2UJAQF0AggFAmJEBmFtb3VudAUCY2QEAmNmCQBlAggFAmJEBmFtb3VudAUCY2UEAmJHCQACAQI+VW5hYmxlIHRvIHByb2NlZWQuIFBheW1lbnQgaXMgYmlnZ2VyIHRoYW4gb3dlZCBhbW91bnQgb2YgZWFzdC4DCQBmAggFAmJEBmFtb3VudAUCY2MFAmJHBAJiWgkAAgECKVVuYWJsZSB0byBwcm9jZWVkLiBUb28gbXVjaCBFQVNUIHRvIGJ1cm4uAwkAZgIFAmNlBQJhWQUCYloEAmNnCQACAQIoVW5hYmxlIHRvIHByb2NlZWQuIFRvbyBmZXcgRUFTVCB0byBidXJuLgMJAGYCCQECYWYABQJjZQUCY2cEAmJNCQECYnADBQFHCQEBLQEFAmNlBQJjZgQCY2gJAQJhZAAJAJQKAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQJjaAUCY2YFAmJQCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQFJAQUBRwUCYk0JAMwIAgkBBEJ1cm4CBQJiUAUCY2UFA25pbAUCY2UJAJQKAgUDbmlsAAAEAmNpCAUCY2ICXzEEAmNlCAUCY2ICXzIEAmNqAwkAZgIFAmJTAAAEAmJICQECYVEBBQJhUAQCY2sKAAJiSgkA/AcEBQJiSAIFY2xvc2UJAMwIAgUBRwkAzAgCBQJiUwUDbmlsBQNuaWwDCQABAgUCYkoCEihTdHJpbmcsIEludCwgSW50KQUCYkoJAAIBCQCsAgIJAAMBBQJiSgInIGNvdWxkbid0IGJlIGNhc3QgdG8gKFN0cmluZywgSW50LCBJbnQpAwkAAAIFAmNrBQJjawQCY2wIBQJjawJfMwQCY20IBQJjawJfMgQCYlIIBQJjawJfMQQCY24JAGUCBQJiSwUCY20EAmJzCQBlAgUCYVkFAmNlBAJjbwkAZgIFAmJLCQEBdQEFAmFZBAJiRwkAAgECK1VuYWJsZSB0byBwcm9jZWVkLiBUb28gZmV3IGFzc2V0cyB0byBjbG9zZS4DCQBmAgkBAmFmAAUCYlMFAmJHBAJiWgkAAgECRFVuYWJsZSB0byBwcm9jZWVkLiBUb28gbXVjaCBhc3NldHMgdG8gY2xvc2UgZm9yIHRoYXQgYW1vdW50IG9mIEVBU1QuAwMFAmNvCQBmAgkBAXUBBQJicwUCY24HBQJiWgQCY2cJAAIBAkVVbmFibGUgdG8gcHJvY2VlZC4gVmF1bHQgaGVhbHRoIGFmdGVyIGNsb3NlIG11c3QgYmUgbW9yZSB0aGFuIGJlZm9yZS4EAmNwCQC5AgIJALYCAQUCYksJALYCAQUCYnMEAmNxCQC5AgIJALYCAQUCY24JALYCAQUCYVkDAwkBASEBBQJjbwkAvwICBQJjcAUCY3EHBQJjZwkAzAgCCQELU3RyaW5nRW50cnkCCQEBRgIFAUcFAmFQBQJiUgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwJAM4IAgUCY2kFAmNqCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAVUBCWxpcXVpZGF0ZQEBTgQCYkQJAJEDAggFAVUIcGF5bWVudHMAAAQCYlAJAQJhagAEAmJ5CQDMCAIJAQJhbAAJAMwIAgkBAmFuAQUBVQkAzAgCCQECYW0CBQFVBQFOCQDMCAIJAQJhegIFAmJEBQJiUAkAzAgCCQECYmkBBQFOBQNuaWwDCQAAAgUCYnkFAmJ5BAJiRgkA/AcEBQR0aGlzAg51cGRhdGVGcmFjdGlvbgUDbmlsBQNuaWwDCQAAAgUCYkYFAmJGBAJhWQgJAQJhVgEFAU4CXzEEAmNyCQEBdAIFAmFZBQFoBAJiRwkAAgECQlVuYWJsZSB0byBwcm9jZWVkLiBQYXltZW50IGFtb3VudCBpcyBiaWdnZXIgdGhhbiA1MCUgb2YgdGhlIHZhdWx0LgMJAGYCCAUCYkQGYW1vdW50BQJjcgUCYkcEAmNzCgACYkoJAPwHBAUEdGhpcwIMZ2V0VmF1bHRJbmZvCQDMCAIFAU4FA25pbAUDbmlsAwkAAQIFAmJKAhkoSW50LCBJbnQsIEludCwgSW50LCBJbnQpBQJiSgkAAgEJAKwCAgkAAwEFAmJKAi4gY291bGRuJ3QgYmUgY2FzdCB0byAoSW50LCBJbnQsIEludCwgSW50LCBJbnQpAwkAAAIFAmNzBQJjcwQCYlUIBQJjcwJfNQQCY3QIBQJjcwJfNAQCY3UIBQJjcwJfMwQCYksIBQJjcwJfMgQCYlgIBQJjcwJfMQQCYloJAAIBAipVbmFibGUgdG8gcHJvY2VlZC4gVmF1bHQgaGVhbHRoIGlzIG5vcm1hbC4DCQBmAgUCY3UFAmN0BQJiWgQCY3YJAQF1AQgFAmJEBmFtb3VudAQCY3cJAGQCBQFiCQECYWcABAJjeAkBAXQCBQJjdgUCY3cEAmN5CQEBcQIFAmN4BQJiWAQCY2gJAQJhZAAEAmN6CQDYBAEICAUBVQZjYWxsZXIFYnl0ZXMKAQJjQQICY0ICY0MEAVgFAmNDAwkAAQIFAVgCBlN0cmluZwQBSAUBWAQCY0QJAQJiZgEFAUgDCQAAAgUCY0QFAmNEBAJhVwkBAmF0AgUBTgUBSAQCYUQFAmFXAwkAAQIFAmFEAgZTdHJpbmcEAmNFBQJhRAQCYkgJAQJhUQEFAUgEAmNGCgACYkoJAPwHBAUCYkgCCWxpcXVpZGF0ZQkAzAgCBQJjegkAzAgCBQFOCQDMCAIFAmN5BQNuaWwFA25pbAMJAAECBQJiSgINKFN0cmluZywgSW50KQUCYkoJAAIBCQCsAgIJAAMBBQJiSgIiIGNvdWxkbid0IGJlIGNhc3QgdG8gKFN0cmluZywgSW50KQMJAAACBQJjRgUCY0YEAmNHCAUCY0YCXzIEAmJSCAUCY0YCXzEEAmF4CQECYXkBBQFIBAJjSAkAzAgCCQELU3RyaW5nRW50cnkCCQEBRgIFAU4FAUgFAmJSBQNuaWwJAJQKAgkAzggCCAUCY0ICXzEFAmNICQBkAggFAmNCAl8yBQJjRwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgMJAAECBQJhRAIEVW5pdAUCY0IJAAIBAgtNYXRjaCBlcnJvcgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgMJAAECBQFYAgRVbml0BQJjQgkAAgECC01hdGNoIGVycm9yBAJidwkBAmFVAQUBTgQCY0kKAAJjSgUCYncKAAJjSwkAkAMBBQJjSgoAAmNMCQCUCgIFA25pbAAACgECY00CAmNOAmNPAwkAZwIFAmNPBQJjSwUCY04JAQJjQQIFAmNOCQCRAwIFAmNKBQJjTwoBAmNQAgJjTgJjTwMJAGcCBQJjTwUCY0sFAmNOCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQJjUAIJAQJjTQIJAQJjTQIJAQJjTQIJAQJjTQIJAQJjTQIJAQJjTQIJAQJjTQIJAQJjTQIJAQJjTQIJAQJjTQIFAmNMAAAAAQACAAMABAAFAAYABwAIAAkACgQCY1EIBQJjSQJfMQQCY0cIBQJjSQJfMgQCYk0JAQJicAMFAU4JAQEtAQgFAmJEBmFtb3VudAAABAJjUgMJAQJhZQEFAVUEAmNTCQBlAgUCYlgFAmN4BAJjbgkAZQIFAmJLBQJjRwQCYnMJAGUCBQJhWQgFAmJEBmFtb3VudAQCY2cJAAIBAkFVbmFibGUgdG8gcHJvY2VlZC4gQlIgYWZ0ZXIgbGlxdWlkYXRpb24gbXVzdCBiZSBtb3JlIHRoYW4gYmVmb3JlLgQCY1QJALkCAgkAtgIBBQJiWAkAtgIBBQJicwQCY1UJALkCAgkAtgIBBQJjUwkAtgIBBQJhWQMJAL8CAgUCY1QFAmNVBQJjZwQCY1YJAAIBAkBVbmFibGUgdG8gcHJvY2VlZC4gVmF1bHQgaGVhbHRoIGlzIGFib3ZlIDEwMCUgYWZ0ZXIgbGlxdWlkYXRpb24uAwkAZgIFAmNuCQEBdQEFAmJzBQJjVgUEdW5pdAUEdW5pdAMJAAACBQJjUgUCY1IEAmNXCQDMCAIJAQRCdXJuAgUCYlAIBQJiRAZhbW91bnQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAUkBBQFOBQJiTQUDbmlsCQDOCAIFAmNXBQJjUQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFVAQxnZXRWYXVsdEluZm8BAU4EAmNYCQECYmkBBQFOAwkAAAIFAmNYBQJjWAQCYkYJAPwHBAUEdGhpcwIOdXBkYXRlRnJhY3Rpb24FA25pbAUDbmlsAwkAAAIFAmJGBQJiRgQCYncJAQJhVQEFAU4KAQJjWQICY0ICY0MEAVgFAmNDAwkAAQIFAVgCBlN0cmluZwQBSAUBWAQCYkgJAQJhUQEFAUgEAmNaCgACYkoJAPwHBAUCYkgCD2dldFN1YnZhdWx0SW5mbwkAzAgCBQFOBQNuaWwFA25pbAMJAAECBQJiSgIPKEludCwgSW50LCBJbnQpBQJiSgkAAgEJAKwCAgkAAwEFAmJKAiQgY291bGRuJ3QgYmUgY2FzdCB0byAoSW50LCBJbnQsIEludCkDCQAAAgUCY1oFAmNaBAJkYQgFAmNaAl8zBAJiSwgFAmNaAl8yBAJiWAgFAmNaAl8xCQCVCgMJAGQCCAUCY0ICXzEFAmJYCQBkAggFAmNCAl8yBQJiSwkAZAIIBQJjQgJfMwUCZGEJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4DCQABAgUBWAIEVW5pdAUCY0IJAAIBAgtNYXRjaCBlcnJvcgQCZGIKAAJjSgUCYncKAAJjSwkAkAMBBQJjSgoAAmNMCQCVCgMAAAAAAAAKAQJjTQICY04CY08DCQBnAgUCY08FAmNLBQJjTgkBAmNZAgUCY04JAJEDAgUCY0oFAmNPCgECY1ACAmNOAmNPAwkAZwIFAmNPBQJjSwUCY04JAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBAmNQAgkBAmNNAgkBAmNNAgkBAmNNAgkBAmNNAgkBAmNNAgkBAmNNAgkBAmNNAgkBAmNNAgkBAmNNAgkBAmNNAgUCY0wAAAABAAIAAwAEAAUABgAHAAgACQAKBAJiWAgFAmRiAl8xBAJiSwgFAmRiAl8yBAJkYQgFAmRiAl8zBAJjdAkBAXECBQJkYQUCYlgEAmRjCQECYVYBBQFOBAJhWQgFAmRjAl8xBAJiYQgFAmRjAl8yBAJiYggFAmRjAl8zBAJkZAkBAXUBBQJhWQQCY3UDCQBmAgUCZGQAAAkBAXECBQJiWAUCZGQFAWUEAmRlCQECYmoDBQJhWQUCYmEFAmJiCQCUCgIFA25pbAkAlwoFBQJiWAUCYksFAmN1BQJjdAUCZGUJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAmRmAQJkZwAEAVgJAQFXAAMJAAECBQFYAgZTdHJpbmcEAUcFAVgJAQt2YWx1ZU9yRWxzZQIJAJsIAgkBEUBleHRyTmF0aXZlKDEwNjIpAQUBRwkBAU0CCQClCAEFBHRoaXMJANgEAQgFAmRmAmlkBwkA9AMDCAUCZGYJYm9keUJ5dGVzCQCRAwIIBQJkZgZwcm9vZnMAAAgFAmRmD3NlbmRlclB1YmxpY0tleSdfFqo=", "height": 2662676, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let SEP = "__"
5+
6+let PRECISION = 1000000000000
7+
8+let DAY = ((60 * 60) * 24)
9+
10+let YEAR = (DAY * 365)
11+
12+let INFINITY = 9223372036854775807
13+
14+let MIN_AMOUNT_DELTA = 1000
15+
16+let LIQUIDATION_BONUS = ((PRECISION / 100) * 5)
17+
18+let MAX_LIQUIDATION_PART = ((PRECISION / 100) * 50)
19+
20+let STABILITY_FEE = (PRECISION / 100)
21+
22+let ENABLED = "ENABLED"
23+
24+let DISABLED = "DISABLED"
25+
26+let IdxVaultCount = 1
27+
28+let IdxVaultEastAmount = 2
29+
30+let IdxVaultTimestamp = 3
31+
32+let IdxStabilityFee = 4
33+
34+let IdxLastFraction = 5
35+
36+func divp (_x,_y) = fraction(_x, PRECISION, _y, HALFEVEN)
37+
38+
39+func mulp (_x,_y) = fraction(_x, _y, PRECISION, HALFEVEN)
40+
41+
42+func conv6to8 (_v) = (_v * 100)
43+
44+
45+func conv8to6 (_v) = (_v / 100)
46+
47+
48+func join (ar) = makeString(ar, SEP)
49+
50+
51+func keyInitialized () = join(["%s", "initialized"])
52+
53+
54+func keyCoordinatorAddress () = join(["%s", "coordinatorAddress"])
55+
56+
57+func keyVerifierAddress () = join(["%s", "verifierAddress"])
58+
59+
60+func keyMinterAddress () = join(["%s", "minterAddress"])
61+
62+
63+func keyTreasuryAddress () = join(["%s", "treasuryAddress"])
64+
65+
66+func keyEastAsset () = join(["%s", "eastAsset"])
67+
68+
69+func keyVaultAsset (address,asset) = join(["%s%s%s", "vault", address, asset])
70+
71+
72+func keyVaultData (address) = join(["%s%s", "vault", address])
73+
74+
75+func keyLiquidationBonus () = join(["%s", "liquidationBonus"])
76+
77+
78+func keyStabilityFee () = join(["%s", "stabilityFee"])
79+
80+
81+func keyMinAmountDelta () = join(["%s", "minAmountDelta"])
82+
83+
84+func keySigned (_address,_txId) = join(["%s%s%s", "signed", _address, _txId])
85+
86+
87+func keyProtocolActive () = join(["%s", "protocolActive"])
88+
89+
90+func isInitialized () = valueOrElse(getBoolean(this, keyInitialized()), false)
91+
92+
93+func mustInitialized () = if (!(isInitialized()))
94+ then throw("Not initialized")
95+ else unit
96+
97+
98+func mustNotInitialized () = if (isInitialized())
99+ then throw("Already initialized")
100+ else unit
101+
102+
103+func mustSelf (i) = if ((i.caller != this))
104+ then throw("Only self invocation allowed.")
105+ else unit
106+
107+
108+func coordinator () = addressFromStringValue(valueOrErrorMessage(getString(keyCoordinatorAddress()), "Coordinator is not set"))
109+
110+
111+func verifier () = match getString(keyCoordinatorAddress()) {
112+ case s: String =>
113+ getString(addressFromStringValue(s), keyVerifierAddress())
114+ case _: Unit =>
115+ unit
116+ case _ =>
117+ throw("Match error")
118+}
119+
120+
121+func getAddress (key,err) = addressFromStringValue(valueOrErrorMessage(getString(coordinator(), key), err))
122+
123+
124+func getMinterAddress () = getAddress(keyMinterAddress(), "Minter is not set")
125+
126+
127+func getTreasuryAddress () = getAddress(keyTreasuryAddress(), "Treasury is not set")
128+
129+
130+func isNotTreasury (i) = (i.caller != getTreasuryAddress())
131+
132+
133+func getMinAmountDelta () = valueOrElse(getInteger(coordinator(), keyMinAmountDelta()), MIN_AMOUNT_DELTA)
134+
135+
136+func getLiquidationBonus () = valueOrElse(getInteger(coordinator(), keyLiquidationBonus()), LIQUIDATION_BONUS)
137+
138+
139+func getStabilityFee () = valueOrElse(getInteger(coordinator(), keyStabilityFee()), STABILITY_FEE)
140+
141+
142+func getEastAssetStr () = valueOrErrorMessage(getString(coordinator(), keyEastAsset()), "East asset is not set")
143+
144+
145+func getEastAsset () = fromBase58String(getEastAssetStr())
146+
147+
148+func isActive () = valueOrElse(getBoolean(coordinator(), keyProtocolActive()), false)
149+
150+
151+func mustActive () = if (if (!(isActive()))
152+ then true
153+ else !(isInitialized()))
154+ then throw("Protocol is disabled. Please contact support.")
155+ else unit
156+
157+
158+func mustNotVaultOwner (i,address) = if ((toBase58String(i.caller.bytes) == address))
159+ then throw("Self invocation not allowed.")
160+ else unit
161+
162+
163+func mustHaveOnePayment (i) = if ((size(i.payments) != 1))
164+ then throw("Must have one payment.")
165+ else unit
166+
167+
168+func mustHaveNoPayment (i) = if ((size(i.payments) != 0))
169+ then throw("No payment allowed.")
170+ else unit
171+
172+
173+func hasOnePayment (i) = (size(i.payments) == 1)
174+
175+
176+func isPositive (number) = if ((0 >= number))
177+ then throw("Attribute should be positive.")
178+ else unit
179+
180+
181+func isNotNegative (number) = if ((0 > number))
182+ then throw("Attribute should be positive or zero.")
183+ else unit
184+
185+
186+func getSubvault (address,asset) = getString(keyVaultAsset(address, asset))
187+
188+
189+func isSubvaultExists (address,asset) = valueOrErrorMessage(getSubvault(address, asset), "Vault not exists")
190+
191+
192+func getAssetString (p) = match p.assetId {
193+ case assetId: ByteVector =>
194+ toBase58String(assetId)
195+ case _: Unit =>
196+ "WAVES"
197+ case _ =>
198+ throw("Match error")
199+}
200+
201+
202+func getAssetIdFromString (assetId) = if ((assetId == "WAVES"))
203+ then unit
204+ else fromBase58String(assetId)
205+
206+
207+func isAsset (p,checkingAsset) = {
208+ let assetId = match checkingAsset {
209+ case bv: ByteVector =>
210+ bv
211+ case s: String =>
212+ getAssetIdFromString(s)
213+ case _: Unit =>
214+ unit
215+ case _ =>
216+ throw("Match error")
217+ }
218+ match assetId {
219+ case bv: ByteVector =>
220+ let name = match assetInfo(bv) {
221+ case asset: Asset =>
222+ asset.name
223+ case _: Unit =>
224+ throw(("Can't find asset " + toBase58String(bv)))
225+ case _ =>
226+ throw("Match error")
227+ }
228+ let err = throw(("Attached payment asset is not " + name))
229+ match p.assetId {
230+ case paymentAsset: ByteVector =>
231+ if ((paymentAsset != assetId))
232+ then err
233+ else unit
234+ case _: Unit =>
235+ err
236+ case _ =>
237+ throw("Match error")
238+ }
239+ case _: Unit =>
240+ if ((p.assetId != unit))
241+ then throw("Attached payment asset is not WAVES")
242+ else unit
243+ case _ =>
244+ throw("Match error")
245+ }
246+ }
247+
248+
249+func checkAddress (_address) = match addressFromString(_address) {
250+ case address: Address =>
251+ true
252+ case _: Unit =>
253+ throw("Invalid address")
254+ case _ =>
255+ throw("Match error")
256+}
257+
258+
259+func getCurrentTimestampSec () = (lastBlock.timestamp / 1000)
260+
261+
262+let IdxAssetStatus = 1
263+
264+let IdxAssetContractId = 2
265+
266+func keyAsset (_assetStr) = join(["%s%s", "asset", _assetStr])
267+
268+
269+func keyVaultAssets (_address) = join(["%s%s", "vaultAssets", _address])
270+
271+
272+func keyCumulativeFeeFraction () = join(["%s", "cumulativeFeeFraction"])
273+
274+
275+func keyFractionLastUpdated () = join(["%s", "fractionLastUpdated"])
276+
277+
278+func getAssetContractStr (_asset) = valueOrErrorMessage(getString(keyAsset(_asset)), "Unknown asset")
279+
280+
281+func getAssetContract (_asset) = {
282+ let contractStr = getAssetContractStr(_asset)
283+ let contractArr = split(contractStr, SEP)
284+ let contractId = contractArr[IdxAssetContractId]
285+ addressFromStringValue(contractId)
286+ }
287+
288+
289+func getVaultAssets (_address) = match getString(keyVaultAssets(_address)) {
290+ case s: String =>
291+ split(s, SEP)
292+ case _: Unit =>
293+ nil
294+ case _ =>
295+ throw("Match error")
296+}
297+
298+
299+func getVaultData (_address) = {
300+ let vault = match getString(keyVaultData(_address)) {
301+ case s: String =>
302+ split(s, SEP)
303+ case _: Unit =>
304+["%d%d%d%d%d", "0", "0", toString(getCurrentTimestampSec()), "0", "0"]
305+ case _ =>
306+ throw("Match error")
307+ }
308+ let count = parseIntValue(vault[IdxVaultCount])
309+ let eastAmount = parseIntValue(vault[IdxVaultEastAmount])
310+ let timestamp = parseIntValue(vault[IdxVaultTimestamp])
311+ let lastStabilityFee = parseIntValue(vault[IdxStabilityFee])
312+ let lastFraction = parseIntValue(vault[IdxLastFraction])
313+ $Tuple5(eastAmount, lastStabilityFee, lastFraction, timestamp, count)
314+ }
315+
316+
317+func assetExist (_assetStr) = match getString(keyAsset(_assetStr)) {
318+ case s: String =>
319+ true
320+ case _: Unit =>
321+ false
322+ case _ =>
323+ throw("Match error")
324+}
325+
326+
327+func getCumulativeFeeFraction () = valueOrElse(getInteger(keyCumulativeFeeFraction()), 0)
328+
329+
330+func getFractionLastUpdated () = valueOrElse(getInteger(keyFractionLastUpdated()), getCurrentTimestampSec())
331+
332+
333+func isEnabled (_assetStr) = {
334+ let assetCfg = getStringValue(keyAsset(_assetStr))
335+ let assetArr = split(assetCfg, SEP)
336+ if ((assetArr[IdxAssetStatus] != ENABLED))
337+ then throw((("Asset " + _assetStr) + " is not enabled"))
338+ else unit
339+ }
340+
341+
342+func isVaultExists (_address) = if ((size(getVaultAssets(_address)) == 0))
343+ then throw("Vault is not exist")
344+ else unit
345+
346+
347+func getCurrentStabilityFee (_eastAmount,_lastStabilityFee,_lastFraction) = (_lastStabilityFee + mulp(_eastAmount, (getCumulativeFeeFraction() - _lastFraction)))
348+
349+
350+func dataAsset (_status,_address) = makeString(["%s%s", _status, _address], SEP)
351+
352+
353+func updateVault (_address,_eastAmount,_paidFee) = {
354+ let $t01362613717 = getVaultData(_address)
355+ let eastAmount = $t01362613717._1
356+ let lastStabilityFee = $t01362613717._2
357+ let lastFraction = $t01362613717._3
358+ let timestamp = $t01362613717._4
359+ let count = $t01362613717._5
360+ let newEastAmount = (eastAmount + _eastAmount)
361+ let newCount = (count + 1)
362+ if ((0 > newEastAmount))
363+ then throw("Something went wrong. Contact support")
364+ else {
365+ let newStabilityFee = (getCurrentStabilityFee(eastAmount, lastStabilityFee, lastFraction) - _paidFee)
366+ makeString(["%d%d%d%d%d", toString(newCount), toString(newEastAmount), toString(getCurrentTimestampSec()), toString(newStabilityFee), toString(getCumulativeFeeFraction())], SEP)
367+ }
368+ }
369+
370+
371+func addVaultAsset (_address,_assetStr) = {
372+ let assets = getVaultAssets(_address)
373+ if (containsElement(assets, _assetStr))
374+ then throw("Asset already exists")
375+ else makeString((assets :+ _assetStr), SEP)
376+ }
377+
378+
379+@Callable(i)
380+func initialize (_coordinatorAddress) = {
381+ let checks = [mustSelf(i), mustNotInitialized(), checkAddress(_coordinatorAddress)]
382+ if ((checks == checks))
383+ then [StringEntry(keyCoordinatorAddress(), _coordinatorAddress), BooleanEntry(keyInitialized(), true)]
384+ else throw("Strict value is not equal to itself.")
385+ }
386+
387+
388+
389+@Callable(i)
390+func addAsset (_assetStr,_contractStr) = {
391+ let checks = [mustInitialized(), mustSelf(i)]
392+ if ((checks == checks))
393+ then if (!(checkAddress(_contractStr)))
394+ then throw("Address is not valid")
395+ else if (assetExist(_assetStr))
396+ then throw("Asset is already set")
397+ else [StringEntry(keyAsset(_assetStr), dataAsset(ENABLED, _contractStr))]
398+ else throw("Strict value is not equal to itself.")
399+ }
400+
401+
402+
403+@Callable(i)
404+func disableAsset (_assetStr) = {
405+ let checks = [mustInitialized(), mustSelf(i)]
406+ if ((checks == checks))
407+ then {
408+ let assetArr = split(valueOrErrorMessage(getString(keyAsset(_assetStr)), "Unknown asset"), SEP)
409+[StringEntry(keyAsset(_assetStr), dataAsset(DISABLED, assetArr[IdxAssetContractId]))]
410+ }
411+ else throw("Strict value is not equal to itself.")
412+ }
413+
414+
415+
416+@Callable(i)
417+func enableAsset (_assetStr) = {
418+ let checks = [mustInitialized(), mustSelf(i)]
419+ if ((checks == checks))
420+ then {
421+ let assetArr = split(valueOrErrorMessage(getString(keyAsset(_assetStr)), "Unknown asset"), SEP)
422+[StringEntry(keyAsset(_assetStr), dataAsset(ENABLED, assetArr[IdxAssetContractId]))]
423+ }
424+ else throw("Strict value is not equal to itself.")
425+ }
426+
427+
428+
429+@Callable(i)
430+func updateFraction () = {
431+ let delta = (getCurrentTimestampSec() - getFractionLastUpdated())
432+ let fractionDelta = mulp(divp(delta, YEAR), getStabilityFee())
433+ let cumulativeFeeFraction = (getCumulativeFeeFraction() + fractionDelta)
434+[IntegerEntry(keyCumulativeFeeFraction(), cumulativeFeeFraction), IntegerEntry(keyFractionLastUpdated(), getCurrentTimestampSec())]
435+ }
436+
437+
438+
439+@Callable(i)
440+func mint () = {
441+ let payment = i.payments[0]
442+ let assetStr = getAssetString(payment)
443+ let address = toBase58String(i.caller.bytes)
444+ let checks = [mustActive(), mustHaveOnePayment(i), isEnabled(assetStr)]
445+ if ((checks == checks))
446+ then {
447+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
448+ if ((doUpdateFraction == doUpdateFraction))
449+ then {
450+ let err1 = throw("Unable to proceed. Too few assets to mint")
451+ if ((getMinAmountDelta() > payment.amount))
452+ then err1
453+ else {
454+ let contract = getAssetContract(assetStr)
455+ let $t01697317073 = {
456+ let @ = invoke(contract, "mint", [address], i.payments)
457+ if ($isInstanceOf(@, "(String, Int)"))
458+ then @
459+ else throw(($getType(@) + " couldn't be cast to (String, Int)"))
460+ }
461+ if (($t01697317073 == $t01697317073))
462+ then {
463+ let eastEq = $t01697317073._2
464+ let assetVault = $t01697317073._1
465+ let eastAmount = conv8to6(eastEq)
466+ let updatedVault = updateVault(address, eastAmount, 0)
467+ let minter = getMinterAddress()
468+ let doIssueEast = invoke(minter, "issue", [eastAmount], nil)
469+ if ((doIssueEast == doIssueEast))
470+ then {
471+ let assets = getVaultAssets(address)
472+ let eastAsset = getEastAsset()
473+ let vaultAssetActions = if (!(containsElement(assets, assetStr)))
474+ then [StringEntry(keyVaultAssets(address), addVaultAsset(address, assetStr))]
475+ else nil
476+ ([StringEntry(keyVaultData(address), updatedVault), StringEntry(keyVaultAsset(address, assetStr), assetVault), ScriptTransfer(i.caller, eastAmount, eastAsset)] ++ vaultAssetActions)
477+ }
478+ else throw("Strict value is not equal to itself.")
479+ }
480+ else throw("Strict value is not equal to itself.")
481+ }
482+ }
483+ else throw("Strict value is not equal to itself.")
484+ }
485+ else throw("Strict value is not equal to itself.")
486+ }
487+
488+
489+
490+@Callable(i)
491+func supply () = {
492+ let payment = i.payments[0]
493+ let address = toBase58String(i.caller.bytes)
494+ let asset = getAssetString(i.payments[0])
495+ let checks = [mustActive(), mustHaveOnePayment(i), isSubvaultExists(address, asset), isEnabled(asset)]
496+ if ((checks == checks))
497+ then {
498+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
499+ if ((doUpdateFraction == doUpdateFraction))
500+ then {
501+ let err1 = throw("Unable to proceed. Too few assets to supply")
502+ if ((getMinAmountDelta() > payment.amount))
503+ then err1
504+ else {
505+ let contract = getAssetContract(asset)
506+ let updatedVaultAsset = {
507+ let @ = invoke(contract, "supply", [address], i.payments)
508+ if ($isInstanceOf(@, "String"))
509+ then @
510+ else throw(($getType(@) + " couldn't be cast to String"))
511+ }
512+ if ((updatedVaultAsset == updatedVaultAsset))
513+ then [StringEntry(keyVaultAsset(address, asset), updatedVaultAsset)]
514+ else throw("Strict value is not equal to itself.")
515+ }
516+ }
517+ else throw("Strict value is not equal to itself.")
518+ }
519+ else throw("Strict value is not equal to itself.")
520+ }
521+
522+
523+
524+@Callable(i)
525+func reissue (_amount) = {
526+ let address = toBase58String(i.caller.bytes)
527+ let checks = [mustActive(), isPositive(_amount), mustHaveNoPayment(i), isVaultExists(address)]
528+ if ((checks == checks))
529+ then {
530+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
531+ if ((doUpdateFraction == doUpdateFraction))
532+ then {
533+ let err1 = throw("Unable to proceed. Too few EAST to reissue")
534+ if ((getMinAmountDelta() > _amount))
535+ then err1
536+ else {
537+ let eastAmount = getVaultData(address)._1
538+ let $t01885618972 = {
539+ let @ = invoke(this, "getVaultInfo", [address], nil)
540+ if ($isInstanceOf(@, "(Int, Int, Int, Int, Int)"))
541+ then @
542+ else throw(($getType(@) + " couldn't be cast to (Int, Int, Int, Int, Int)"))
543+ }
544+ if (($t01885618972 == $t01885618972))
545+ then {
546+ let fee = $t01885618972._5
547+ let lr = $t01885618972._4
548+ let br = $t01885618972._3
549+ let eastEq = $t01885618972._2
550+ let usdEq = $t01885618972._1
551+ let eastAvailable = (conv8to6(eastEq) - eastAmount)
552+ let err2 = throw((("Unable to reissue. Only " + toString(eastAvailable)) + " EAST available."))
553+ if ((_amount > eastAvailable))
554+ then err2
555+ else {
556+ let updatedVault = updateVault(address, _amount, 0)
557+ let minter = getMinterAddress()
558+ let doIssueEast = invoke(minter, "issue", [_amount], nil)
559+ if ((doIssueEast == doIssueEast))
560+ then {
561+ let eastAsset = getEastAsset()
562+[StringEntry(keyVaultData(address), updatedVault), ScriptTransfer(i.caller, _amount, eastAsset)]
563+ }
564+ else throw("Strict value is not equal to itself.")
565+ }
566+ }
567+ else throw("Strict value is not equal to itself.")
568+ }
569+ }
570+ else throw("Strict value is not equal to itself.")
571+ }
572+ else throw("Strict value is not equal to itself.")
573+ }
574+
575+
576+
577+@Callable(i)
578+func close (_asset,_amount) = {
579+ let address = toBase58String(i.caller.bytes)
580+ let eastAsset = getEastAsset()
581+ let checks = [mustActive(), isNotNegative(_amount), isVaultExists(address), if (hasOnePayment(i))
582+ then isAsset(i.payments[0], eastAsset)
583+ else mustHaveNoPayment(i), if ((_amount > 0))
584+ then [isSubvaultExists(address, _asset)]
585+ else unit]
586+ if ((checks == checks))
587+ then {
588+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
589+ if ((doUpdateFraction == doUpdateFraction))
590+ then {
591+ let eastAmount = getVaultData(address)._1
592+ let $t01999620112 = {
593+ let @ = invoke(this, "getVaultInfo", [address], nil)
594+ if ($isInstanceOf(@, "(Int, Int, Int, Int, Int)"))
595+ then @
596+ else throw(($getType(@) + " couldn't be cast to (Int, Int, Int, Int, Int)"))
597+ }
598+ if (($t01999620112 == $t01999620112))
599+ then {
600+ let fee = $t01999620112._5
601+ let lr = $t01999620112._4
602+ let br = $t01999620112._3
603+ let eastEq = $t01999620112._2
604+ let usdEq = $t01999620112._1
605+ let $t02011621124 = if (hasOnePayment(i))
606+ then {
607+ let payment = i.payments[0]
608+ let totalEastOwed = (eastAmount + fee)
609+ let k = divp(eastAmount, totalEastOwed)
610+ let eastToBurn = mulp(payment.amount, k)
611+ let eastToPayFee = (payment.amount - eastToBurn)
612+ let err1 = throw("Unable to proceed. Payment is bigger than owed amount of east.")
613+ if ((payment.amount > totalEastOwed))
614+ then err1
615+ else {
616+ let err2 = throw("Unable to proceed. Too much EAST to burn.")
617+ if ((eastToBurn > eastAmount))
618+ then err2
619+ else {
620+ let err3 = throw("Unable to proceed. Too few EAST to burn.")
621+ if ((getMinAmountDelta() > eastToBurn))
622+ then err3
623+ else {
624+ let updatedVault = updateVault(address, -(eastToBurn), eastToPayFee)
625+ let treasuryAddress = getTreasuryAddress()
626+ $Tuple2([ScriptTransfer(treasuryAddress, eastToPayFee, eastAsset), StringEntry(keyVaultData(address), updatedVault), Burn(eastAsset, eastToBurn)], eastToBurn)
627+ }
628+ }
629+ }
630+ }
631+ else $Tuple2(nil, 0)
632+ let eastActions = $t02011621124._1
633+ let eastToBurn = $t02011621124._2
634+ let assetActions = if ((_amount > 0))
635+ then {
636+ let contract = getAssetContract(_asset)
637+ let $t02121921352 = {
638+ let @ = invoke(contract, "close", [address, _amount], nil)
639+ if ($isInstanceOf(@, "(String, Int, Int)"))
640+ then @
641+ else throw(($getType(@) + " couldn't be cast to (String, Int, Int)"))
642+ }
643+ if (($t02121921352 == $t02121921352))
644+ then {
645+ let closedUsdEq = $t02121921352._3
646+ let closedEastEq = $t02121921352._2
647+ let updatedVaultAsset = $t02121921352._1
648+ let newEastEq = (eastEq - closedEastEq)
649+ let newEastAmount = (eastAmount - eastToBurn)
650+ let overcollateralized = (eastEq > conv6to8(eastAmount))
651+ let err1 = throw("Unable to proceed. Too few assets to close.")
652+ if ((getMinAmountDelta() > _amount))
653+ then err1
654+ else {
655+ let err2 = throw("Unable to proceed. Too much assets to close for that amount of EAST.")
656+ if (if (overcollateralized)
657+ then (conv6to8(newEastAmount) > newEastEq)
658+ else false)
659+ then err2
660+ else {
661+ let err3 = throw("Unable to proceed. Vault health after close must be more than before.")
662+ let e1e2 = (toBigInt(eastEq) * toBigInt(newEastAmount))
663+ let e2e1 = (toBigInt(newEastEq) * toBigInt(eastAmount))
664+ if (if (!(overcollateralized))
665+ then (e1e2 > e2e1)
666+ else false)
667+ then err3
668+ else [StringEntry(keyVaultAsset(address, _asset), updatedVaultAsset)]
669+ }
670+ }
671+ }
672+ else throw("Strict value is not equal to itself.")
673+ }
674+ else nil
675+ (eastActions ++ assetActions)
676+ }
677+ else throw("Strict value is not equal to itself.")
678+ }
679+ else throw("Strict value is not equal to itself.")
680+ }
681+ else throw("Strict value is not equal to itself.")
682+ }
683+
684+
685+
686+@Callable(i)
687+func liquidate (_address) = {
688+ let payment = i.payments[0]
689+ let eastAsset = getEastAsset()
690+ let checks = [mustActive(), mustHaveOnePayment(i), mustNotVaultOwner(i, _address), isAsset(payment, eastAsset), isVaultExists(_address)]
691+ if ((checks == checks))
692+ then {
693+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
694+ if ((doUpdateFraction == doUpdateFraction))
695+ then {
696+ let eastAmount = getVaultData(_address)._1
697+ let maxLiquidateAmountAllowed = mulp(eastAmount, MAX_LIQUIDATION_PART)
698+ let err1 = throw("Unable to proceed. Payment amount is bigger than 50% of the vault.")
699+ if ((payment.amount > maxLiquidateAmountAllowed))
700+ then err1
701+ else {
702+ let $t02283422985 = {
703+ let @ = invoke(this, "getVaultInfo", [_address], nil)
704+ if ($isInstanceOf(@, "(Int, Int, Int, Int, Int)"))
705+ then @
706+ else throw(($getType(@) + " couldn't be cast to (Int, Int, Int, Int, Int)"))
707+ }
708+ if (($t02283422985 == $t02283422985))
709+ then {
710+ let fee = $t02283422985._5
711+ let avgLiquidationRatio = $t02283422985._4
712+ let currentBackingRatio = $t02283422985._3
713+ let eastEq = $t02283422985._2
714+ let usdEq = $t02283422985._1
715+ let err2 = throw("Unable to proceed. Vault health is normal.")
716+ if ((currentBackingRatio > avgLiquidationRatio))
717+ then err2
718+ else {
719+ let paymentAmountD8 = conv6to8(payment.amount)
720+ let liquidationCoeff = (PRECISION + getLiquidationBonus())
721+ let liquidationEastAmountD8 = mulp(paymentAmountD8, liquidationCoeff)
722+ let liquidationRatio = divp(liquidationEastAmountD8, usdEq)
723+ let treasuryAddress = getTreasuryAddress()
724+ let liquidatorAddress = toBase58String(i.caller.bytes)
725+ func liquidateAssets (acc,next) = match next {
726+ case asset: String =>
727+ let check = isEnabled(asset)
728+ if ((check == check))
729+ then {
730+ let vault = getSubvault(_address, asset)
731+ match vault {
732+ case v: String =>
733+ let contract = getAssetContract(asset)
734+ let $t02380123953 = {
735+ let @ = invoke(contract, "liquidate", [liquidatorAddress, _address, liquidationRatio], nil)
736+ if ($isInstanceOf(@, "(String, Int)"))
737+ then @
738+ else throw(($getType(@) + " couldn't be cast to (String, Int)"))
739+ }
740+ if (($t02380123953 == $t02380123953))
741+ then {
742+ let liquidatedEastEq = $t02380123953._2
743+ let updatedVaultAsset = $t02380123953._1
744+ let assetId = getAssetIdFromString(asset)
745+ let actions = [StringEntry(keyVaultAsset(_address, asset), updatedVaultAsset)]
746+ $Tuple2((acc._1 ++ actions), (acc._2 + liquidatedEastEq))
747+ }
748+ else throw("Strict value is not equal to itself.")
749+ case _: Unit =>
750+ acc
751+ case _ =>
752+ throw("Match error")
753+ }
754+ }
755+ else throw("Strict value is not equal to itself.")
756+ case _: Unit =>
757+ acc
758+ case _ =>
759+ throw("Match error")
760+ }
761+
762+ let assets = getVaultAssets(_address)
763+ let $t02430124388 = {
764+ let $l = assets
765+ let $s = size($l)
766+ let $acc0 = $Tuple2(nil, 0)
767+ func $f0_1 ($a,$i) = if (($i >= $s))
768+ then $a
769+ else liquidateAssets($a, $l[$i])
770+
771+ func $f0_2 ($a,$i) = if (($i >= $s))
772+ then $a
773+ else throw("List size exceeds 10")
774+
775+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
776+ }
777+ let vaultAssetsActions = $t02430124388._1
778+ let liquidatedEastEq = $t02430124388._2
779+ let updatedVault = updateVault(_address, -(payment.amount), 0)
780+ let postCheck = if (isNotTreasury(i))
781+ then {
782+ let newUsdEq = (usdEq - liquidationEastAmountD8)
783+ let newEastEq = (eastEq - liquidatedEastEq)
784+ let newEastAmount = (eastAmount - payment.amount)
785+ let err3 = throw("Unable to proceed. BR after liquidation must be more than before.")
786+ let u1e2 = (toBigInt(usdEq) * toBigInt(newEastAmount))
787+ let u2e1 = (toBigInt(newUsdEq) * toBigInt(eastAmount))
788+ if ((u1e2 > u2e1))
789+ then err3
790+ else {
791+ let err4 = throw("Unable to proceed. Vault health is above 100% after liquidation.")
792+ if ((newEastEq > conv6to8(newEastAmount)))
793+ then err4
794+ else unit
795+ }
796+ }
797+ else unit
798+ if ((postCheck == postCheck))
799+ then {
800+ let vaultActions = [Burn(eastAsset, payment.amount), StringEntry(keyVaultData(_address), updatedVault)]
801+ (vaultActions ++ vaultAssetsActions)
802+ }
803+ else throw("Strict value is not equal to itself.")
804+ }
805+ }
806+ else throw("Strict value is not equal to itself.")
807+ }
808+ }
809+ else throw("Strict value is not equal to itself.")
810+ }
811+ else throw("Strict value is not equal to itself.")
812+ }
813+
814+
815+
816+@Callable(i)
817+func getVaultInfo (_address) = {
818+ let exists = isVaultExists(_address)
819+ if ((exists == exists))
820+ then {
821+ let doUpdateFraction = invoke(this, "updateFraction", nil, nil)
822+ if ((doUpdateFraction == doUpdateFraction))
823+ then {
824+ let assets = getVaultAssets(_address)
825+ func countSubvaults (acc,next) = match next {
826+ case asset: String =>
827+ let contract = getAssetContract(asset)
828+ let $t02561425726 = {
829+ let @ = invoke(contract, "getSubvaultInfo", [_address], nil)
830+ if ($isInstanceOf(@, "(Int, Int, Int)"))
831+ then @
832+ else throw(($getType(@) + " couldn't be cast to (Int, Int, Int)"))
833+ }
834+ if (($t02561425726 == $t02561425726))
835+ then {
836+ let threshold = $t02561425726._3
837+ let eastEq = $t02561425726._2
838+ let usdEq = $t02561425726._1
839+ $Tuple3((acc._1 + usdEq), (acc._2 + eastEq), (acc._3 + threshold))
840+ }
841+ else throw("Strict value is not equal to itself.")
842+ case _: Unit =>
843+ acc
844+ case _ =>
845+ throw("Match error")
846+ }
847+
848+ let $t02583625912 = {
849+ let $l = assets
850+ let $s = size($l)
851+ let $acc0 = $Tuple3(0, 0, 0)
852+ func $f0_1 ($a,$i) = if (($i >= $s))
853+ then $a
854+ else countSubvaults($a, $l[$i])
855+
856+ func $f0_2 ($a,$i) = if (($i >= $s))
857+ then $a
858+ else throw("List size exceeds 10")
859+
860+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
861+ }
862+ let usdEq = $t02583625912._1
863+ let eastEq = $t02583625912._2
864+ let threshold = $t02583625912._3
865+ let avgLiquidationRatio = divp(threshold, usdEq)
866+ let $t02596726040 = getVaultData(_address)
867+ let eastAmount = $t02596726040._1
868+ let lastStabilityFee = $t02596726040._2
869+ let lastFraction = $t02596726040._3
870+ let eastAmountD8 = conv6to8(eastAmount)
871+ let currentBackingRatio = if ((eastAmountD8 > 0))
872+ then divp(usdEq, eastAmountD8)
873+ else INFINITY
874+ let stabilityFee = getCurrentStabilityFee(eastAmount, lastStabilityFee, lastFraction)
875+ $Tuple2(nil, $Tuple5(usdEq, eastEq, currentBackingRatio, avgLiquidationRatio, stabilityFee))
876+ }
877+ else throw("Strict value is not equal to itself.")
878+ }
879+ else throw("Strict value is not equal to itself.")
880+ }
881+
882+
883+@Verifier(tx)
884+func verify () = match verifier() {
885+ case address: String =>
886+ valueOrElse(getBoolean(addressFromStringValue(address), keySigned(toString(this), toBase58String(tx.id))), false)
887+ case _ =>
888+ sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
889+}
890+

github/deemru/w8io/026f985 
41.93 ms