tx · 682BY9XahuoqUCbYtWY8CR4LahuGXA3q6P7pdLQEjN6N 3N49shcErzZepEy7HDR1fjAce8humpL7QiH: -0.01500000 Waves 2023.02.22 14:08 [2460774] smart account 3N49shcErzZepEy7HDR1fjAce8humpL7QiH > SELF 0.00000000 Waves
{ "type": 13, "id": "682BY9XahuoqUCbYtWY8CR4LahuGXA3q6P7pdLQEjN6N", "fee": 1500000, "feeAssetId": null, "timestamp": 1677064035945, "version": 2, "chainId": 84, "sender": "3N49shcErzZepEy7HDR1fjAce8humpL7QiH", "senderPublicKey": "9frGdXQHcSntKXRWwZ4YJZWnnKREWwYH4cEzMVQwcwYj", "proofs": [ "4D9NbWPs62zSyb4xjC4sxK6MdBEpYWV11gfEbSGbALVohpVkypiVPT1rkLqP2E8g6X6UUgsc6F4wRy3KsueXw7FG" ], "script": "base64:BgItCAISBAoCCAgSABIECgIICBIAEgASBAoCCAgSBQoDCAgBEgMKAQgSAwoBCBIAKwEQd3JpdGVDb25zdFN0cmluZwIDa2V5BXZhbHVlAwkBASEBCQEJaXNEZWZpbmVkAQkAnQgCBQR0aGlzBQNrZXkJAQtTdHJpbmdFbnRyeQIFA2tleQUFdmFsdWUJAAIBCQCsAgICFWFscmVhZHkgaW5pdGlhbGl6ZWQ6IAUDa2V5AQ13cml0ZUNvbnN0SW50AgNrZXkFdmFsdWUDCQEBIQEJAQlpc0RlZmluZWQBCQCaCAIFBHRoaXMFA2tleQkBDEludGVnZXJFbnRyeQIFA2tleQUFdmFsdWUJAAIBCQCsAgICFWFscmVhZHkgaW5pdGlhbGl6ZWQ6IAUDa2V5AQh3cml0ZUludAIDa2V5BXZhbHVlAwkAZgIAAAUFdmFsdWUJAAIBCQCsAgIJAKwCAgkArAICAhd3cml0aW5nIG5lZ2F0aXZlIHZhbHVlIAkApAMBBQV2YWx1ZQIJIGZvciBrZXkgBQNrZXkJAQxJbnRlZ2VyRW50cnkCBQNrZXkFBXZhbHVlAQhjaGFuZ2VCeQIDa2V5BXZhbHVlCQEId3JpdGVJbnQCBQNrZXkJAGQCCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFA2tleQAABQV2YWx1ZQALY29uZmlnU3RvcmUCBmNvbmZpZwANY29uZmlnQWRkcmVzcwkBEUBleHRyTmF0aXZlKDEwNjIpAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwULY29uZmlnU3RvcmUAFHZlc3RpbmdDb25maWdBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzAg12ZXN0aW5nQ29uZmlnABJtYXliZU9yYWNsZUFkZHJlc3MEByRtYXRjaDAJAJ0IAgUNY29uZmlnQWRkcmVzcwIOb3JhY2xlX2FkZHJlc3MDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwCQCmCAEFAXMFBHVuaXQABkhFSUdIVAUGaGVpZ2h0AQlvcEFsbG93ZWQBAm9wBAckbWF0Y2gwCQD8BwQFDWNvbmZpZ0FkZHJlc3MCCW9wQWxsb3dlZAkAzAgCAgR1c2RuCQDMCAIFAm9wBQNuaWwFA25pbAMJAAECBQckbWF0Y2gwAgdCb29sZWFuBAFiBQckbWF0Y2gwAwUBYgYJAAIBAgtub3QgYWxsb3dlZAkAAgECIW9wQWxsb3dlZDogdW5leHBlY3RlZCByZXN1bHQgdHlwZQEIbWFpbk9ubHkBAWkDCQEIY29udGFpbnMCCQERQGV4dHJOYXRpdmUoMTA1MykCBQ1jb25maWdBZGRyZXNzAgRtYWluCQClCAEIBQFpBmNhbGxlcgYJAAIBAhBvbmx5IG1haW4gY2FuIGRvAQd0aHJvd0lmAgljb25kaXRpb24FZXJyb3IDBQljb25kaXRpb24JAAIBBQVlcnJvcgYABHVzZG4JARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMCBHVzZG4BF2FkZHJlc3NUb3RhbFN0b3JlTGVnYWN5AQdhZGRyZXNzCQCsAgIFB2FkZHJlc3MCBV91c2RuARFhZGRyZXNzVG90YWxTdG9yZQEHYWRkcmVzcwkArAICBQdhZGRyZXNzAgVfVVNETgETdmVzdGluZ0NsYWltZWRTdG9yZQEHYWRkcmVzcwkArAICBQdhZGRyZXNzAghfY2xhaW1lZAESY29udmVydGVkVG9McFN0b3JlAQdhZGRyZXNzCQCsAgIFB2FkZHJlc3MCEF9jb252ZXJ0ZWRfdG9fbHABEXZlc3RpbmdTdGFydFN0b3JlAQdhZGRyZXNzCQCsAgIFB2FkZHJlc3MCDl92ZXN0aW5nX3N0YXJ0ARd2ZXN0aW5nTGFzdENsYWltZWRTdG9yZQEHYWRkcmVzcwkArAICBQdhZGRyZXNzAhVfdmVzdGluZ19sYXN0X2NsYWltZWQBFnZlc3RpbmdEYWlseVNwZWVkU3RvcmUBB2FkZHJlc3MJAKwCAgUHYWRkcmVzcwIUX3Zlc3RpbmdfZGFpbHlfc3BlZWQBDGFzSW50M1N0cmluZwEFdmFsdWUEByRtYXRjaDAFBXZhbHVlAwkAAQIFByRtYXRjaDACFyhJbnQsIEludCwgSW50LCBTdHJpbmcpBAdpbnQzc3RyBQckbWF0Y2gwBQdpbnQzc3RyCQACAQItd3JvbmcgdHlwZSwgZXhwZWN0ZWQ6IChJbnQsIEludCwgSW50LCBTdHJpbmcpAA50b3RhbFVTRE5TdG9yZQIKdG90YWxfdXNkbgALdG90YWxWZXN0ZWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUOdG90YWxVU0ROU3RvcmUAAAAVc3BlZWRDb2VmZmljaWVudFN0b3JlAhl2ZXN0aW5nX3NwZWVkX2NvZWZmaWNpZW50ABBzcGVlZENvZWZmaWNpZW50CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMCGXZlc3Rpbmdfc3BlZWRfY29lZmZpY2llbnQAZAARdG90YWxTdGFraW5nU3RvcmUCEnRvdGFsX3N0YWtpbmdfdXNkbgEXdXNlckNsYWltZWRSZXdhcmRzU3RvcmUBB2FkZHJlc3MJAKwCAgUHYWRkcmVzcwIVX2NsYWltZWRfc3Rha2luZ191c2RuARN1c2VyU3Rha2luZ0FkalN0b3JlAQdhZGRyZXNzCQCsAgIFB2FkZHJlc3MCBF9hZGoAI0xJTkVBUl9WRVNUSU5HX0RFRkFVTFRfU1RBUlRfSEVJR0hUAOGQ1wEAF0xJTkVBUl9WRVNUSU5HX01BWF9EQVlTCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMCF2xpbmVhcl92ZXN0aW5nX21heF9kYXlzAPQDARJ1c2VyVmVzdGluZ0JhbGFuY2UBB2FkZHJlc3MEF2xlZ2FjeVRvdGFsVmVzdGluZ1ZhbHVlCQELdmFsdWVPckVsc2UCCQCfCAEJARdhZGRyZXNzVG90YWxTdG9yZUxlZ2FjeQEFB2FkZHJlc3MAAAQMdG90YWxWZXN0aW5nCQBlAgkAZQIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEWFkZHJlc3NUb3RhbFN0b3JlAQUHYWRkcmVzcwUXbGVnYWN5VG90YWxWZXN0aW5nVmFsdWUJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBE3Zlc3RpbmdDbGFpbWVkU3RvcmUBBQdhZGRyZXNzAAAJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEmNvbnZlcnRlZFRvTHBTdG9yZQEFB2FkZHJlc3MAAAQHJG1hdGNoMAkAmggCBQR0aGlzCQEXdmVzdGluZ0xhc3RDbGFpbWVkU3RvcmUBBQdhZGRyZXNzAwkAAQIFByRtYXRjaDACA0ludAQRbGFzdENsYWltZWRIZWlnaHQFByRtYXRjaDAEEnVzZXJTcGVlZFBlckRheVJhdwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEJARZ2ZXN0aW5nRGFpbHlTcGVlZFN0b3JlAQUHYWRkcmVzcwkArAICAg1ubyBzcGVlZCBmb3IgBQdhZGRyZXNzBAZwZXJEYXkJAGsDBRJ1c2VyU3BlZWRQZXJEYXlSYXcFEHNwZWVkQ29lZmZpY2llbnQAZAQIdW5sb2NrZWQJAGsDBQZwZXJEYXkJAGUCBQZIRUlHSFQFEWxhc3RDbGFpbWVkSGVpZ2h0AKALCQCVCgMFDHRvdGFsVmVzdGluZwkAlwMBCQDMCAIFCHVubG9ja2VkCQDMCAIFDHRvdGFsVmVzdGluZwUDbmlsBQZwZXJEYXkEByRtYXRjaDEJAJ8IAQkBEXZlc3RpbmdTdGFydFN0b3JlAQUHYWRkcmVzcwMJAAECBQckbWF0Y2gxAgNJbnQEDnZlc3RpbmdSZXN0YXJ0BSNMSU5FQVJfVkVTVElOR19ERUZBVUxUX1NUQVJUX0hFSUdIVAQGcGVyRGF5CQBrAwkAaQIFC3RvdGFsVmVzdGVkBRdMSU5FQVJfVkVTVElOR19NQVhfREFZUwUQc3BlZWRDb2VmZmljaWVudABkBAh1bmxvY2tlZAkAawMFBnBlckRheQkAZQIFBkhFSUdIVAUOdmVzdGluZ1Jlc3RhcnQAoAsJAJUKAwUMdG90YWxWZXN0aW5nCQCXAwEJAMwIAgUIdW5sb2NrZWQJAMwIAgUMdG90YWxWZXN0aW5nBQNuaWwFBnBlckRheQkAlQoDAAAAAAAAAQp1c2VyVmVzdGVkAQdhZGRyZXNzBAskdDA0NTE2NDU4NgkBEnVzZXJWZXN0aW5nQmFsYW5jZQEFB2FkZHJlc3MEDHRvdGFsVmVzdGluZwgFCyR0MDQ1MTY0NTg2Al8xBAxhdmFpbGFibGVOb3cIBQskdDA0NTE2NDU4NgJfMgQGcGVyRGF5CAULJHQwNDUxNjQ1ODYCXzMFDHRvdGFsVmVzdGluZwEQdXNlclRvdGFsUmV3YXJkcwEHYWRkcmVzcwQMdG90YWxSZXdhcmRzCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFEXRvdGFsU3Rha2luZ1N0b3JlAAAEDnVzZXJTdGFraW5nQWRqCQELdmFsdWVPckVsc2UCCQCfCAEJARN1c2VyU3Rha2luZ0FkalN0b3JlAQUHYWRkcmVzcwAAAwkAAAIFC3RvdGFsVmVzdGVkAAAFDnVzZXJTdGFraW5nQWRqCQBkAgkAawMFDHRvdGFsUmV3YXJkcwkBCnVzZXJWZXN0ZWQBBQdhZGRyZXNzBQt0b3RhbFZlc3RlZAUOdXNlclN0YWtpbmdBZGoBG3VzZXJTdGFraW5nUmV3YXJkc0F2YWlsYWJsZQEHYWRkcmVzcwQSdXNlckNsYWltZWRSZXdhcmRzCQELdmFsdWVPckVsc2UCCQCfCAEJARd1c2VyQ2xhaW1lZFJld2FyZHNTdG9yZQEFB2FkZHJlc3MAAAQUdXNlckF2YWlsYWJsZVJld2FyZHMJAGUCCQEQdXNlclRvdGFsUmV3YXJkcwEFB2FkZHJlc3MFEnVzZXJDbGFpbWVkUmV3YXJkcwMJAGYCAAAFFHVzZXJBdmFpbGFibGVSZXdhcmRzAAAFFHVzZXJBdmFpbGFibGVSZXdhcmRzARB1cGRhdGVSZXdhcmREYXRhAgdhZGRyZXNzCnVzZXJDaGFuZ2UECXByZXZUb3RhbAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQ50b3RhbFVTRE5TdG9yZQAABBBwcmV2U3Rha2luZ1RvdGFsCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFEXRvdGFsU3Rha2luZ1N0b3JlAAAEEnByZXZVc2VyU3Rha2luZ0FkagkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQETdXNlclN0YWtpbmdBZGpTdG9yZQEFB2FkZHJlc3MAAAQIbmV3VG90YWwJAGQCBQlwcmV2VG90YWwFCnVzZXJDaGFuZ2UEFW5ld1N0YWtpbmdSZXdhcmRUb3RhbAMJAAACBQlwcmV2VG90YWwAAAUQcHJldlN0YWtpbmdUb3RhbAkAawMFEHByZXZTdGFraW5nVG90YWwFCG5ld1RvdGFsBQlwcmV2VG90YWwEEG5ld1VzZXJSZXdhcmRBZGoDCQAAAgUIbmV3VG90YWwAAAkAZAIFEnByZXZVc2VyU3Rha2luZ0FkagUQcHJldlN0YWtpbmdUb3RhbAkAZQIFEnByZXZVc2VyU3Rha2luZ0FkagkAawMFFW5ld1N0YWtpbmdSZXdhcmRUb3RhbAUKdXNlckNoYW5nZQUIbmV3VG90YWwJAMwIAgkBDEludGVnZXJFbnRyeQIFEXRvdGFsU3Rha2luZ1N0b3JlBRVuZXdTdGFraW5nUmV3YXJkVG90YWwJAMwIAgkBDEludGVnZXJFbnRyeQIJARN1c2VyU3Rha2luZ0FkalN0b3JlAQUHYWRkcmVzcwUQbmV3VXNlclJld2FyZEFkagUDbmlsAA5zdGFraW5nQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ1jb25maWdBZGRyZXNzCQCsAgICD3N0YWtpbmdfY29uZmlnXwkApQgBBQR0aGlzCQCsAgICF25vIHN0YWtpbmcgYWRkcmVzcyBmb3IgCQClCAEFBHRoaXMJAKwCAgIYYmFkIHN0YWtpbmcgYWRkcmVzcyBmb3IgCQClCAEFBHRoaXMADnN0YWtpbmdFbmFibGVkCQELdmFsdWVPckVsc2UCCQCbCAIFDWNvbmZpZ0FkZHJlc3MJAKwCAgIQc3Rha2luZ19lbmFibGVkXwkApQgBBQR0aGlzBwELc3luY1N0YWtpbmcBDWtlZXBBdEJhbGFuY2UEDWFjdHVhbEJhbGFuY2UJAPAHAgUEdGhpcwkA2QQBBQR1c2RuBA1zdGFraW5nQWN0aW9uAwkAAAIFDWFjdHVhbEJhbGFuY2UFDWtlZXBBdEJhbGFuY2UFA25pbAMJAQEhAQUOc3Rha2luZ0VuYWJsZWQFA25pbAMJAGYCBQ1hY3R1YWxCYWxhbmNlBQ1rZWVwQXRCYWxhbmNlCQD8BwQFDnN0YWtpbmdBZGRyZXNzAgNwdXQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkA2QQBBQR1c2RuCQBlAgUNYWN0dWFsQmFsYW5jZQUNa2VlcEF0QmFsYW5jZQUDbmlsCQD8BwQFDnN0YWtpbmdBZGRyZXNzAgNnZXQJAMwIAgkAZQIFDWtlZXBBdEJhbGFuY2UFDWFjdHVhbEJhbGFuY2UFA25pbAUDbmlsAwkAAAIFDXN0YWtpbmdBY3Rpb24FDXN0YWtpbmdBY3Rpb24FA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEKYWR2aXNlVXNlcgEHYWRkcmVzcwQLJHQwNzA3OTcxNDkJARJ1c2VyVmVzdGluZ0JhbGFuY2UBBQdhZGRyZXNzBAx0b3RhbFZlc3RpbmcIBQskdDA3MDc5NzE0OQJfMQQMYXZhaWxhYmxlTm93CAULJHQwNzA3OTcxNDkCXzIEBnBlckRheQgFCyR0MDcwNzk3MTQ5Al8zCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIRbWFya2V0c19hZGRyZXNzOiAFB2FkZHJlc3MCGCwgbWFya2V0c190b3RhbFZlc3Rpbmc6IAkApAMBBQx0b3RhbFZlc3RpbmcCFiwgbWFya2V0c19hdmFpbGFibGVOb3cJAKQDAQUMYXZhaWxhYmxlTm93AhAsIG1hcmtldHNfcGVyRGF5CQCkAwEFBnBlckRheQIXLCBtYXJrZXRzX3N0YXJ0SGVpZ2h0OiACATACFiwgbWFya2V0c19kYWlseUxpbWl0OiACATACGCwgbWFya2V0c19jbGFpbWVkVG9kYXk6IAIBMAIaLCBtYXJrZXRzX2F2YWlsYWJsZVRvZGF5OiACATACIiwgbWFya2V0c19nbG9iYWxseUF2YWlsYWJsZVRvZGF5OiACATACGiwgbWFya2V0c19tYXhUb3RhbFBlckRheTogAgEwAhQsIG1hcmtldHNfc2xvdEJ1c3k6IAIBMAIhLCBtYXJrZXRzX3N0YWtpbmdfcmV3YXJkc190b3RhbDogCQCkAwEJARB1c2VyVG90YWxSZXdhcmRzAQUHYWRkcmVzcwIjLCBtYXJrZXRzX3N0YWtpbmdfcmV3YXJkc19jbGFpbWVkOiAJAKQDAQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEXdXNlckNsYWltZWRSZXdhcmRzU3RvcmUBBQdhZGRyZXNzAAACGSwgbWFya2V0c19jb252ZXJ0ZWRUb0xQOiACATACFiwgbWFya2V0c192ZXN0blN0YXRlOiACBmxpbmVhcgEWd2l0aGRyYXdWZXN0ZWRJbnRlcm5hbAIHYWRkcmVzcwJ0bwQGY2hlY2tzCQEJb3BBbGxvd2VkAQIbbGlxdWlkYW9fYWxsX3dpdGhkcmF3VmVzdGVkAwkAAAIFBmNoZWNrcwUGY2hlY2tzBAskdDA4MTM5ODIwOQkBEnVzZXJWZXN0aW5nQmFsYW5jZQEFB2FkZHJlc3MEDHRvdGFsVmVzdGluZwgFCyR0MDgxMzk4MjA5Al8xBAxhdmFpbGFibGVOb3cIBQskdDA4MTM5ODIwOQJfMgQGcGVyRGF5CAULJHQwODEzOTgyMDkCXzMDCQBnAgAABQxhdmFpbGFibGVOb3cJAAIBAhFub3RoaW5nIGF2YWlsYWJsZQkAlAoCCQDOCAIJAM4IAgkBC3N5bmNTdGFraW5nAQUMYXZhaWxhYmxlTm93CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAnRvBQxhdmFpbGFibGVOb3cJANkEAQUEdXNkbgkAzAgCCQEId3JpdGVJbnQCCQERYWRkcmVzc1RvdGFsU3RvcmUBBQdhZGRyZXNzCQBlAgUMdG90YWxWZXN0aW5nBQxhdmFpbGFibGVOb3cJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBE3Zlc3RpbmdDbGFpbWVkU3RvcmUBBQdhZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJARJjb252ZXJ0ZWRUb0xwU3RvcmUBBQdhZGRyZXNzCQDMCAIJAQhjaGFuZ2VCeQIFDnRvdGFsVVNETlN0b3JlCQEBLQEFDGF2YWlsYWJsZU5vdwUDbmlsAwkBCWlzRGVmaW5lZAEJARZ2ZXN0aW5nRGFpbHlTcGVlZFN0b3JlAQUHYWRkcmVzcwkAzAgCCQEId3JpdGVJbnQCCQEXdmVzdGluZ0xhc3RDbGFpbWVkU3RvcmUBBQdhZGRyZXNzBQZIRUlHSFQFA25pbAkAzggCCQDMCAIJAQh3cml0ZUludAIJARd2ZXN0aW5nTGFzdENsYWltZWRTdG9yZQEFB2FkZHJlc3MFBkhFSUdIVAkAzAgCCQEId3JpdGVJbnQCCQEWdmVzdGluZ0RhaWx5U3BlZWRTdG9yZQEFB2FkZHJlc3MJAGkCBQx0b3RhbFZlc3RpbmcFF0xJTkVBUl9WRVNUSU5HX01BWF9EQVlTBQNuaWwJARB1cGRhdGVSZXdhcmREYXRhAgUHYWRkcmVzcwkBAS0BBQxhdmFpbGFibGVOb3cFDGF2YWlsYWJsZU5vdwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEdcGFydGlhbFdpdGhkcmF3VmVzdGVkSW50ZXJuYWwDB2FkZHJlc3MCdG8DYW10BAZjaGVja3MJAQlvcEFsbG93ZWQBAh9saXF1aWRhb19hbGxfd2l0aGRyYXdWZXN0ZWRBc0xQAwkAAAIFBmNoZWNrcwUGY2hlY2tzBAskdDA5Mjc2OTM0NgkBEnVzZXJWZXN0aW5nQmFsYW5jZQEFB2FkZHJlc3MEDHRvdGFsVmVzdGluZwgFCyR0MDkyNzY5MzQ2Al8xBAxhdmFpbGFibGVOb3cIBQskdDA5Mjc2OTM0NgJfMgQGcGVyRGF5CAULJHQwOTI3NjkzNDYCXzMDCQBmAgUDYW10BQx0b3RhbFZlc3RpbmcJAAIBAhJ0b28gbXVjaCByZXF1ZXN0ZWQJAJQKAgkAzggCCQDOCAIJAQtzeW5jU3Rha2luZwEFA2FtdAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBBQJ0bwUDYW10CQDZBAEFBHVzZG4JAMwIAgkBCHdyaXRlSW50AgkBEWFkZHJlc3NUb3RhbFN0b3JlAQUHYWRkcmVzcwkAZQIFDHRvdGFsVmVzdGluZwUDYW10CQDMCAIJAQtEZWxldGVFbnRyeQEJARN2ZXN0aW5nQ2xhaW1lZFN0b3JlAQUHYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQESY29udmVydGVkVG9McFN0b3JlAQUHYWRkcmVzcwkAzAgCCQEId3JpdGVJbnQCCQEXdmVzdGluZ0xhc3RDbGFpbWVkU3RvcmUBBQdhZGRyZXNzBQZIRUlHSFQJAMwIAgkBCHdyaXRlSW50AgkBFnZlc3RpbmdEYWlseVNwZWVkU3RvcmUBBQdhZGRyZXNzCQBpAgkAZQIFDHRvdGFsVmVzdGluZwUDYW10BRdMSU5FQVJfVkVTVElOR19NQVhfREFZUwkAzAgCCQEIY2hhbmdlQnkCBQ50b3RhbFVTRE5TdG9yZQkBAS0BBQNhbXQFA25pbAkBEHVwZGF0ZVJld2FyZERhdGECBQdhZGRyZXNzCQEBLQEFA2FtdAUDYW10CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuABFzdGFraW5nU3RhcnRTdG9yZQINc3Rha2luZ0hlaWdodAEMZW5zdXJlU3Rha2VkAAkAZgIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBRFzdGFraW5nU3RhcnRTdG9yZQIlbmVlZCB0byBzdGFrZSBhbGwgZXhpc3RpbmcgdXNkbiBmaXJzdAAACgFpAQRpbml0AgRjb25mA25JZAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECEm9ubHkgc2VsZiBjYW4gaW5pdAkAzAgCCQEQd3JpdGVDb25zdFN0cmluZwIFC2NvbmZpZ1N0b3JlBQRjb25mCQDMCAIJARB3cml0ZUNvbnN0U3RyaW5nAgIEdXNkbgUDbklkBQNuaWwBaQEOd2l0aGRyYXdWZXN0ZWQABAFjCQEMZW5zdXJlU3Rha2VkAAMJAAACBQFjBQFjBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgkBFndpdGhkcmF3VmVzdGVkSW50ZXJuYWwCBQdhZGRyZXNzBQdhZGRyZXNzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBE3dpdGhkcmF3VmVzdGVkRm9yVG8CA2FjYwJ0bwQGY2hlY2tzAwkBCG1haW5Pbmx5AQUBaQkBDGVuc3VyZVN0YWtlZAAHAwkAAAIFBmNoZWNrcwUGY2hlY2tzCQEWd2l0aGRyYXdWZXN0ZWRJbnRlcm5hbAIFA2FjYwUCdG8JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMY2xhaW1SZXdhcmRzAAQBYwMJAQxlbnN1cmVTdGFrZWQACQEJb3BBbGxvd2VkAQIZbGlxdWlkYW9fYWxsX2NsYWltUmV3YXJkcwcDCQAAAgUBYwUBYwQHYWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEB3Jld2FyZHMJARt1c2VyU3Rha2luZ1Jld2FyZHNBdmFpbGFibGUBBQdhZGRyZXNzAwkAZwIAAAUHcmV3YXJkcwkAAgECEG5vdGhpbmcgdG8gY2xhaW0JAM4IAgkBC3N5bmNTdGFraW5nAQUHcmV3YXJkcwkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBBQdhZGRyZXNzBQdyZXdhcmRzCQDZBAEFBHVzZG4JAMwIAgkBCGNoYW5nZUJ5AgkBF3VzZXJDbGFpbWVkUmV3YXJkc1N0b3JlAQUHYWRkcmVzcwUHcmV3YXJkcwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCmFkZFJld2FyZHMABAFjCQEMZW5zdXJlU3Rha2VkAAMJAAACBQFjBQFjAwkBAiE9AgkA2AQBCQEFdmFsdWUBCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQFBHVzZG4JAAIBAglVU0ROIG9ubHkJAM4IAgkBC3N5bmNTdGFraW5nAQAACQDMCAIJAQhjaGFuZ2VCeQIFEXRvdGFsU3Rha2luZ1N0b3JlCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBFndpdGhkcmF3QWxsVmVzdGVkRm9yVG8CB2FkZHJlc3MCdG8EBmNoZWNrcwMDCQEIbWFpbk9ubHkBBQFpCQEJb3BBbGxvd2VkAQIhbGlxdWlkYW9fYWxsX3dpdGhkcmF3VmVzdGVkQXNTdXJmBwkBDGVuc3VyZVN0YWtlZAAHAwkAAAIFBmNoZWNrcwUGY2hlY2tzBA0kdDAxMTYxMDExNjgwCQESdXNlclZlc3RpbmdCYWxhbmNlAQUHYWRkcmVzcwQMdG90YWxWZXN0aW5nCAUNJHQwMTE2MTAxMTY4MAJfMQQMYXZhaWxhYmxlTm93CAUNJHQwMTE2MTAxMTY4MAJfMgQGcGVyRGF5CAUNJHQwMTE2MTAxMTY4MAJfMwMJAGcCAAAFDGF2YWlsYWJsZU5vdwkAAgECEm5vIHZlc3RpbmcgZW5hYmxlZAkAlAoCCQDOCAIJAM4IAgkBC3N5bmNTdGFraW5nAQUMYXZhaWxhYmxlTm93CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAnRvBQx0b3RhbFZlc3RpbmcJANkEAQUEdXNkbgkAzAgCCQELRGVsZXRlRW50cnkBCQERYWRkcmVzc1RvdGFsU3RvcmUBBQdhZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJARdhZGRyZXNzVG90YWxTdG9yZUxlZ2FjeQEFB2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBEXZlc3RpbmdTdGFydFN0b3JlAQUHYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQETdmVzdGluZ0NsYWltZWRTdG9yZQEFB2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBEmNvbnZlcnRlZFRvTHBTdG9yZQEFB2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFnZlc3RpbmdEYWlseVNwZWVkU3RvcmUBBQdhZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJARd2ZXN0aW5nTGFzdENsYWltZWRTdG9yZQEFB2FkZHJlc3MJAMwIAgkBCGNoYW5nZUJ5AgUOdG90YWxVU0ROU3RvcmUJAQEtAQUMdG90YWxWZXN0aW5nBQNuaWwJARB1cGRhdGVSZXdhcmREYXRhAgUHYWRkcmVzcwkBAS0BBQx0b3RhbFZlc3RpbmcFDHRvdGFsVmVzdGluZwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARpwYXJ0aWFsV2l0aGRyYXdWZXN0ZWRGb3JUbwMDYWNjAnRvA2FtdAQHY2hlY2tzMAkBCG1haW5Pbmx5AQUBaQMJAAACBQdjaGVja3MwBQdjaGVja3MwCQEdcGFydGlhbFdpdGhkcmF3VmVzdGVkSW50ZXJuYWwDBQNhY2MFAnRvBQNhbXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEKYWNjb3VudEZvcgEHYWRkcmVzcwQIYXR0YWNoZWQJAJEDAggFAWkIcGF5bWVudHMAAAQGY2hlY2tzAwMDCQEIbWFpbk9ubHkBBQFpCQEJb3BBbGxvd2VkAQIRbGlxdWlkYW9fYWxsX21vdmUHCQEMZW5zdXJlU3Rha2VkAAcJAQd0aHJvd0lmAgkBAiE9AgkA2AQBCQEFdmFsdWUBCAUIYXR0YWNoZWQHYXNzZXRJZAUEdXNkbgIVdXNkbiBtdXN0IGJlIGF0dGFjaGVkBwMJAAACBQZjaGVja3MFBmNoZWNrcwQNJHQwMTI4MDYxMjg3NgkBEnVzZXJWZXN0aW5nQmFsYW5jZQEFB2FkZHJlc3MEDHRvdGFsVmVzdGluZwgFDSR0MDEyODA2MTI4NzYCXzEEDGF2YWlsYWJsZU5vdwgFDSR0MDEyODA2MTI4NzYCXzIEBnBlckRheQgFDSR0MDEyODA2MTI4NzYCXzMJAM4IAgkAzggCCQELc3luY1N0YWtpbmcBAAAJAMwIAgkBCHdyaXRlSW50AgkBEWFkZHJlc3NUb3RhbFN0b3JlAQUHYWRkcmVzcwkAZAIFDHRvdGFsVmVzdGluZwgFCGF0dGFjaGVkBmFtb3VudAkAzAgCCQELRGVsZXRlRW50cnkBCQETdmVzdGluZ0NsYWltZWRTdG9yZQEFB2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBEmNvbnZlcnRlZFRvTHBTdG9yZQEFB2FkZHJlc3MJAMwIAgkBCHdyaXRlSW50AgkBF3Zlc3RpbmdMYXN0Q2xhaW1lZFN0b3JlAQUHYWRkcmVzcwUGSEVJR0hUCQDMCAIJAQh3cml0ZUludAIJARZ2ZXN0aW5nRGFpbHlTcGVlZFN0b3JlAQUHYWRkcmVzcwkAaQIJAGQCBQx0b3RhbFZlc3RpbmcIBQhhdHRhY2hlZAZhbW91bnQFF0xJTkVBUl9WRVNUSU5HX01BWF9EQVlTCQDMCAIJAQhjaGFuZ2VCeQIFDnRvdGFsVVNETlN0b3JlCAUIYXR0YWNoZWQGYW1vdW50BQNuaWwJARB1cGRhdGVSZXdhcmREYXRhAgUHYWRkcmVzcwgFCGF0dGFjaGVkBmFtb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQdhZHZpc2VVAQNhY2MJAJQKAgUDbmlsCQEKYWR2aXNlVXNlcgEFA2FjYwFpAQVzdGFrZQAKAQVhc0ludAEFdmFsdWUEByRtYXRjaDAFBXZhbHVlAwkAAQIFByRtYXRjaDACA0ludAQDaW50BQckbWF0Y2gwBQNpbnQJAAIBAgR2YToxBA1hY3R1YWxCYWxhbmNlCQDwBwIFBHRoaXMJANkEAQUEdXNkbgMJAQEhAQUOc3Rha2luZ0VuYWJsZWQJAAIBAhNzdGFraW5nIG5vdCBlbmFibGVkAwkBCWlzRGVmaW5lZAEJAJoIAgUEdGhpcwURc3Rha2luZ1N0YXJ0U3RvcmUJAAIBAg5hbHJlYWR5IHN0YWtlZAQDaW52CQD8BwQFDnN0YWtpbmdBZGRyZXNzAgNwdXQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkA2QQBBQR1c2RuBQ1hY3R1YWxCYWxhbmNlBQNuaWwDCQAAAgUDaW52BQNpbnYEBnN0YWtlZAkBBWFzSW50AQkA/AcEBQ5zdGFraW5nQWRkcmVzcwIEaW5mbwUDbmlsBQNuaWwDCQAAAgUGc3Rha2VkBQZzdGFrZWQJAMwIAgkBDEludGVnZXJFbnRyeQIFDnRvdGFsVVNETlN0b3JlBQZzdGFrZWQJAMwIAgkBDEludGVnZXJFbnRyeQIFEXN0YWtpbmdTdGFydFN0b3JlBQZIRUlHSFQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECdHgBBnZlcmlmeQAEBEJBU0UA6AcEC3F1b3J1bVJhdGlvCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUNY29uZmlnQWRkcmVzcwIVcHJvcG9zYWxfcXVvcnVtX3JhdGlvAiJwcm9wb3NhbFF1b3J1bVJhdGlvIGlzIG5vdCBkZWZpbmVkBAtwYXNzZWRSYXRpbwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFDWNvbmZpZ0FkZHJlc3MCFXByb3Bvc2FsX3Bhc3NlZF9yYXRpbwIlcHJvcG9zYWxUaHJlc2hvbGRSYXRpbyBpcyBub3QgZGVmaW5lZAQOZ1ZpcmVzQ29udHJhY3QJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUNY29uZmlnQWRkcmVzcwISZGl2aWRlbmRzX2NvbnRyYWN0AhVubyBkaXZpZGVuZHNfY29udHJhY3QCGmludmFsaWQgZGl2aWRlbmRzX2NvbnRyYWN0BA52b3RpbmdDb250cmFjdAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ1jb25maWdBZGRyZXNzAg92b3RpbmdfY29udHJhY3QCEm5vIHZvdGluZ19jb250cmFjdAIXaW52YWxpZCB2b3RpbmdfY29udHJhY3QEAmlkCQDYBAEIBQJ0eAJpZAQIdm90ZXNZZXMJAQt2YWx1ZU9yRWxzZQIJAJoIAgUOdm90aW5nQ29udHJhY3QJAKwCAgINcHJvcG9zYWxfeWVzXwUCaWQAAAQHdm90ZXNObwkBC3ZhbHVlT3JFbHNlAgkAmggCBQ52b3RpbmdDb250cmFjdAkArAICAgxwcm9wb3NhbF9ub18FAmlkAAAEDnByb3Bvc2FsSGVpZ2h0CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUOdm90aW5nQ29udHJhY3QJAKwCAgIQcHJvcG9zYWxfaGVpZ2h0XwUCaWQCF3Byb3Bvc2FsIG5vdCByZWdpc3RlcmVkBAphcHBseVN0YXJ0CQELdmFsdWVPckVsc2UCCQCaCAIFDnZvdGluZ0NvbnRyYWN0CQCsAgICFHByb3Bvc2FsX2FwcGx5c3RhcnRfBQJpZAAABAhhcHBseUVuZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ52b3RpbmdDb250cmFjdAkArAICAhJwcm9wb3NhbF9hcHBseWVuZF8FAmlkAAAEC3RvdGFsR1ZpcmVzCQELdmFsdWVPckVsc2UCCQCaCAIFDnZvdGluZ0NvbnRyYWN0CQCsAgICEHByb3Bvc2FsX2d2aXJlc18FAmlkAAAEB2VuYWJsZWQJAQt2YWx1ZU9yRWxzZQIJAJsIAgUNY29uZmlnQWRkcmVzcwIdb3BfZ292ZXJuYW5jZV9hcHBseV90eF9wYXVzZWQHBAd2b3RlWWVzBQh2b3Rlc1llcwQGdm90ZU5vBQd2b3Rlc05vBAp0b3RhbFZvdGVzCQBkAgUHdm90ZVllcwUGdm90ZU5vBAloYXNRdW9ydW0JAGcCCQBpAgkAaAIFCnRvdGFsVm90ZXMFBEJBU0UFC3RvdGFsR1ZpcmVzBQtxdW9ydW1SYXRpbwQJaGFzUGFzc2VkCQBnAgkAaQIJAGgCBQd2b3RlWWVzBQRCQVNFBQp0b3RhbFZvdGVzBQtwYXNzZWRSYXRpbwQIdG9vRWFybHkJAGcCBQphcHBseVN0YXJ0BQZIRUlHSFQEB3Rvb0xhdGUJAGcCBQZIRUlHSFQFCGFwcGx5RW5kBAl0aW1lRGVidWcJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIRcHJvcG9zYWxIZWlnaHQgPSAJAKQDAQUOcHJvcG9zYWxIZWlnaHQCDywgYXBwbHlTdGFydCA9IAkApAMBBQphcHBseVN0YXJ0Ag0sIGFwcGx5RW5kID0gCQCkAwEFCGFwcGx5RW5kAgssIEhFSUdIVCA9IAkApAMBBQZIRUlHSFQECGJ5Vm90aW5nAwkBASEBBQdlbmFibGVkCQACAQIrdHggYXBwbGljYXRpb24gdGhyb3cgZ292ZXJuYW5jZSBub3QgZW5hYmxlZAMFCHRvb0Vhcmx5CQACAQkArAICAi5wcm9wb3NhbCBjYW4ndCBiZSBleGVjdXRlZCBhcyBpdCdzIHRvbyBlYXJseTogBQl0aW1lRGVidWcDBQd0b29MYXRlCQACAQkArAICAixwcm9wb3NhbCBjYW4ndCBiZSBleGVjdXRlZCBhcyBpdCdzIHRvbyBsYXRlOgUJdGltZURlYnVnAwkBASEBBQloYXNRdW9ydW0JAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAgtubyBxdW9ydW06IAIMdG90YWxWb3RlczogCQCkAwEFCnRvdGFsVm90ZXMCDywgdG90YWxHVmlyZXM6IAkApAMBBQt0b3RhbEdWaXJlcwIPLCBxdW9ydW1SYXRpbzogCQCkAwEFC3F1b3J1bVJhdGlvAwkBASEBBQloYXNQYXNzZWQJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhdubyB0aHJlc2hvbGQgYWNoaWV2ZWQ6IAIJdm90ZVllczogCQCkAwEFB3ZvdGVZZXMCCiwgdm90ZU5vOiAJAKQDAQUGdm90ZU5vAg8sIHBhc3NlZFJhdGlvOiAJAKQDAQULcGFzc2VkUmF0aW8GAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tleQYFCGJ5Vm90aW5n3P+TjA==", "height": 2460774, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 3QWXjmidDNhAh46ZsgFJja4WrNgqGGi1B1p5ABmVCTqG Next: none Full:
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | - | func cfee (inv) = if ((500001 >= inv.fee)) | |
5 | - | then (inv.feeAssetId == unit) | |
6 | - | else false | |
4 | + | func writeConstString (key,value) = if (!(isDefined(getString(this, key)))) | |
5 | + | then StringEntry(key, value) | |
6 | + | else throw(("already initialized: " + key)) | |
7 | + | ||
8 | + | ||
9 | + | func writeConstInt (key,value) = if (!(isDefined(getInteger(this, key)))) | |
10 | + | then IntegerEntry(key, value) | |
11 | + | else throw(("already initialized: " + key)) | |
12 | + | ||
13 | + | ||
14 | + | func writeInt (key,value) = if ((0 > value)) | |
15 | + | then throw(((("writing negative value " + toString(value)) + " for key ") + key)) | |
16 | + | else IntegerEntry(key, value) | |
17 | + | ||
18 | + | ||
19 | + | func changeBy (key,value) = writeInt(key, (valueOrElse(getInteger(this, key), 0) + value)) | |
20 | + | ||
21 | + | ||
22 | + | let configStore = "config" | |
23 | + | ||
24 | + | let configAddress = addressFromStringValue(getStringValue(this, configStore)) | |
25 | + | ||
26 | + | let vestingConfigAddress = addressFromStringValue(getStringValue(this, "vestingConfig")) | |
27 | + | ||
28 | + | let maybeOracleAddress = match getString(configAddress, "oracle_address") { | |
29 | + | case s: String => | |
30 | + | addressFromString(s) | |
31 | + | case _ => | |
32 | + | unit | |
33 | + | } | |
34 | + | ||
35 | + | let HEIGHT = height | |
36 | + | ||
37 | + | func opAllowed (op) = match invoke(configAddress, "opAllowed", ["usdn", op], nil) { | |
38 | + | case b: Boolean => | |
39 | + | if (b) | |
40 | + | then true | |
41 | + | else throw("not allowed") | |
42 | + | case _ => | |
43 | + | throw("opAllowed: unexpected result type") | |
44 | + | } | |
45 | + | ||
46 | + | ||
47 | + | func mainOnly (i) = if (contains(getStringValue(configAddress, "main"), toString(i.caller))) | |
48 | + | then true | |
49 | + | else throw("only main can do") | |
50 | + | ||
51 | + | ||
52 | + | func throwIf (condition,error) = if (condition) | |
53 | + | then throw(error) | |
54 | + | else true | |
55 | + | ||
56 | + | ||
57 | + | let usdn = getStringValue(this, "usdn") | |
58 | + | ||
59 | + | func addressTotalStoreLegacy (address) = (address + "_usdn") | |
60 | + | ||
61 | + | ||
62 | + | func addressTotalStore (address) = (address + "_USDN") | |
63 | + | ||
64 | + | ||
65 | + | func vestingClaimedStore (address) = (address + "_claimed") | |
66 | + | ||
67 | + | ||
68 | + | func convertedToLpStore (address) = (address + "_converted_to_lp") | |
69 | + | ||
70 | + | ||
71 | + | func vestingStartStore (address) = (address + "_vesting_start") | |
72 | + | ||
73 | + | ||
74 | + | func vestingLastClaimedStore (address) = (address + "_vesting_last_claimed") | |
75 | + | ||
76 | + | ||
77 | + | func vestingDailySpeedStore (address) = (address + "_vesting_daily_speed") | |
78 | + | ||
79 | + | ||
80 | + | func asInt3String (value) = match value { | |
81 | + | case int3str: (Int, Int, Int, String) => | |
82 | + | int3str | |
83 | + | case _ => | |
84 | + | throw("wrong type, expected: (Int, Int, Int, String)") | |
85 | + | } | |
86 | + | ||
87 | + | ||
88 | + | let totalUSDNStore = "total_usdn" | |
89 | + | ||
90 | + | let totalVested = valueOrElse(getInteger(this, totalUSDNStore), 0) | |
91 | + | ||
92 | + | let speedCoefficientStore = "vesting_speed_coefficient" | |
93 | + | ||
94 | + | let speedCoefficient = valueOrElse(getInteger(this, "vesting_speed_coefficient"), 100) | |
95 | + | ||
96 | + | let totalStakingStore = "total_staking_usdn" | |
97 | + | ||
98 | + | func userClaimedRewardsStore (address) = (address + "_claimed_staking_usdn") | |
99 | + | ||
100 | + | ||
101 | + | func userStakingAdjStore (address) = (address + "_adj") | |
102 | + | ||
103 | + | ||
104 | + | let LINEAR_VESTING_DEFAULT_START_HEIGHT = 3524705 | |
105 | + | ||
106 | + | let LINEAR_VESTING_MAX_DAYS = valueOrElse(getInteger(this, "linear_vesting_max_days"), 500) | |
107 | + | ||
108 | + | func userVestingBalance (address) = { | |
109 | + | let legacyTotalVestingValue = valueOrElse(getInteger(addressTotalStoreLegacy(address)), 0) | |
110 | + | let totalVesting = ((valueOrElse(getInteger(addressTotalStore(address)), legacyTotalVestingValue) - valueOrElse(getInteger(vestingClaimedStore(address)), 0)) - valueOrElse(getInteger(convertedToLpStore(address)), 0)) | |
111 | + | match getInteger(this, vestingLastClaimedStore(address)) { | |
112 | + | case lastClaimedHeight: Int => | |
113 | + | let userSpeedPerDayRaw = valueOrErrorMessage(getInteger(vestingDailySpeedStore(address)), ("no speed for " + address)) | |
114 | + | let perDay = fraction(userSpeedPerDayRaw, speedCoefficient, 100) | |
115 | + | let unlocked = fraction(perDay, (HEIGHT - lastClaimedHeight), 1440) | |
116 | + | $Tuple3(totalVesting, min([unlocked, totalVesting]), perDay) | |
117 | + | case _ => | |
118 | + | match getInteger(vestingStartStore(address)) { | |
119 | + | case _: Int => | |
120 | + | let vestingRestart = LINEAR_VESTING_DEFAULT_START_HEIGHT | |
121 | + | let perDay = fraction((totalVested / LINEAR_VESTING_MAX_DAYS), speedCoefficient, 100) | |
122 | + | let unlocked = fraction(perDay, (HEIGHT - vestingRestart), 1440) | |
123 | + | $Tuple3(totalVesting, min([unlocked, totalVesting]), perDay) | |
124 | + | case _ => | |
125 | + | $Tuple3(0, 0, 0) | |
126 | + | } | |
127 | + | } | |
128 | + | } | |
129 | + | ||
130 | + | ||
131 | + | func userVested (address) = { | |
132 | + | let $t045164586 = userVestingBalance(address) | |
133 | + | let totalVesting = $t045164586._1 | |
134 | + | let availableNow = $t045164586._2 | |
135 | + | let perDay = $t045164586._3 | |
136 | + | totalVesting | |
137 | + | } | |
138 | + | ||
139 | + | ||
140 | + | func userTotalRewards (address) = { | |
141 | + | let totalRewards = valueOrElse(getInteger(this, totalStakingStore), 0) | |
142 | + | let userStakingAdj = valueOrElse(getInteger(userStakingAdjStore(address)), 0) | |
143 | + | if ((totalVested == 0)) | |
144 | + | then userStakingAdj | |
145 | + | else (fraction(totalRewards, userVested(address), totalVested) + userStakingAdj) | |
146 | + | } | |
147 | + | ||
148 | + | ||
149 | + | func userStakingRewardsAvailable (address) = { | |
150 | + | let userClaimedRewards = valueOrElse(getInteger(userClaimedRewardsStore(address)), 0) | |
151 | + | let userAvailableRewards = (userTotalRewards(address) - userClaimedRewards) | |
152 | + | if ((0 > userAvailableRewards)) | |
153 | + | then 0 | |
154 | + | else userAvailableRewards | |
155 | + | } | |
156 | + | ||
157 | + | ||
158 | + | func updateRewardData (address,userChange) = { | |
159 | + | let prevTotal = valueOrElse(getInteger(this, totalUSDNStore), 0) | |
160 | + | let prevStakingTotal = valueOrElse(getInteger(this, totalStakingStore), 0) | |
161 | + | let prevUserStakingAdj = valueOrElse(getInteger(this, userStakingAdjStore(address)), 0) | |
162 | + | let newTotal = (prevTotal + userChange) | |
163 | + | let newStakingRewardTotal = if ((prevTotal == 0)) | |
164 | + | then prevStakingTotal | |
165 | + | else fraction(prevStakingTotal, newTotal, prevTotal) | |
166 | + | let newUserRewardAdj = if ((newTotal == 0)) | |
167 | + | then (prevUserStakingAdj + prevStakingTotal) | |
168 | + | else (prevUserStakingAdj - fraction(newStakingRewardTotal, userChange, newTotal)) | |
169 | + | [IntegerEntry(totalStakingStore, newStakingRewardTotal), IntegerEntry(userStakingAdjStore(address), newUserRewardAdj)] | |
170 | + | } | |
171 | + | ||
172 | + | ||
173 | + | let stakingAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, ("staking_config_" + toString(this))), ("no staking address for " + toString(this)))), ("bad staking address for " + toString(this))) | |
174 | + | ||
175 | + | let stakingEnabled = valueOrElse(getBoolean(configAddress, ("staking_enabled_" + toString(this))), false) | |
176 | + | ||
177 | + | func syncStaking (keepAtBalance) = { | |
178 | + | let actualBalance = assetBalance(this, fromBase58String(usdn)) | |
179 | + | let stakingAction = if ((actualBalance == keepAtBalance)) | |
180 | + | then nil | |
181 | + | else if (!(stakingEnabled)) | |
182 | + | then nil | |
183 | + | else if ((actualBalance > keepAtBalance)) | |
184 | + | then invoke(stakingAddress, "put", nil, [AttachedPayment(fromBase58String(usdn), (actualBalance - keepAtBalance))]) | |
185 | + | else invoke(stakingAddress, "get", [(keepAtBalance - actualBalance)], nil) | |
186 | + | if ((stakingAction == stakingAction)) | |
187 | + | then nil | |
188 | + | else throw("Strict value is not equal to itself.") | |
189 | + | } | |
190 | + | ||
191 | + | ||
192 | + | func adviseUser (address) = { | |
193 | + | let $t070797149 = userVestingBalance(address) | |
194 | + | let totalVesting = $t070797149._1 | |
195 | + | let availableNow = $t070797149._2 | |
196 | + | let perDay = $t070797149._3 | |
197 | + | ((((((((((((((((((((((((((((("markets_address: " + address) + ", markets_totalVesting: ") + toString(totalVesting)) + ", markets_availableNow") + toString(availableNow)) + ", markets_perDay") + toString(perDay)) + ", markets_startHeight: ") + "0") + ", markets_dailyLimit: ") + "0") + ", markets_claimedToday: ") + "0") + ", markets_availableToday: ") + "0") + ", markets_globallyAvailableToday: ") + "0") + ", markets_maxTotalPerDay: ") + "0") + ", markets_slotBusy: ") + "0") + ", markets_staking_rewards_total: ") + toString(userTotalRewards(address))) + ", markets_staking_rewards_claimed: ") + toString(valueOrElse(getInteger(userClaimedRewardsStore(address)), 0))) + ", markets_convertedToLP: ") + "0") + ", markets_vestnState: ") + "linear") | |
198 | + | } | |
199 | + | ||
200 | + | ||
201 | + | func withdrawVestedInternal (address,to) = { | |
202 | + | let checks = opAllowed("liquidao_all_withdrawVested") | |
203 | + | if ((checks == checks)) | |
204 | + | then { | |
205 | + | let $t081398209 = userVestingBalance(address) | |
206 | + | let totalVesting = $t081398209._1 | |
207 | + | let availableNow = $t081398209._2 | |
208 | + | let perDay = $t081398209._3 | |
209 | + | if ((0 >= availableNow)) | |
210 | + | then throw("nothing available") | |
211 | + | else $Tuple2(((syncStaking(availableNow) ++ [ScriptTransfer(addressFromStringValue(to), availableNow, fromBase58String(usdn)), writeInt(addressTotalStore(address), (totalVesting - availableNow)), DeleteEntry(vestingClaimedStore(address)), DeleteEntry(convertedToLpStore(address)), changeBy(totalUSDNStore, -(availableNow))]) ++ (if (isDefined(vestingDailySpeedStore(address))) | |
212 | + | then [writeInt(vestingLastClaimedStore(address), HEIGHT)] | |
213 | + | else ([writeInt(vestingLastClaimedStore(address), HEIGHT), writeInt(vestingDailySpeedStore(address), (totalVesting / LINEAR_VESTING_MAX_DAYS))] ++ updateRewardData(address, -(availableNow))))), availableNow) | |
214 | + | } | |
215 | + | else throw("Strict value is not equal to itself.") | |
216 | + | } | |
217 | + | ||
218 | + | ||
219 | + | func partialWithdrawVestedInternal (address,to,amt) = { | |
220 | + | let checks = opAllowed("liquidao_all_withdrawVestedAsLP") | |
221 | + | if ((checks == checks)) | |
222 | + | then { | |
223 | + | let $t092769346 = userVestingBalance(address) | |
224 | + | let totalVesting = $t092769346._1 | |
225 | + | let availableNow = $t092769346._2 | |
226 | + | let perDay = $t092769346._3 | |
227 | + | if ((amt > totalVesting)) | |
228 | + | then throw("too much requested") | |
229 | + | else $Tuple2(((syncStaking(amt) ++ [ScriptTransfer(addressFromStringValue(to), amt, fromBase58String(usdn)), writeInt(addressTotalStore(address), (totalVesting - amt)), DeleteEntry(vestingClaimedStore(address)), DeleteEntry(convertedToLpStore(address)), writeInt(vestingLastClaimedStore(address), HEIGHT), writeInt(vestingDailySpeedStore(address), ((totalVesting - amt) / LINEAR_VESTING_MAX_DAYS)), changeBy(totalUSDNStore, -(amt))]) ++ updateRewardData(address, -(amt))), amt) | |
230 | + | } | |
231 | + | else throw("Strict value is not equal to itself.") | |
232 | + | } | |
233 | + | ||
234 | + | ||
235 | + | let stakingStartStore = "stakingHeight" | |
236 | + | ||
237 | + | func ensureStaked () = (valueOrErrorMessage(getInteger(this, stakingStartStore), "need to stake all existing usdn first") > 0) | |
7 | 238 | ||
8 | 239 | ||
9 | 240 | @Callable(i) | |
10 | - | func call () = [IntegerEntry("int", 10)] | |
241 | + | func init (conf,nId) = if ((i.caller != this)) | |
242 | + | then throw("only self can init") | |
243 | + | else [writeConstString(configStore, conf), writeConstString("usdn", nId)] | |
244 | + | ||
245 | + | ||
246 | + | ||
247 | + | @Callable(i) | |
248 | + | func withdrawVested () = { | |
249 | + | let c = ensureStaked() | |
250 | + | if ((c == c)) | |
251 | + | then { | |
252 | + | let address = toString(i.caller) | |
253 | + | withdrawVestedInternal(address, address) | |
254 | + | } | |
255 | + | else throw("Strict value is not equal to itself.") | |
256 | + | } | |
257 | + | ||
258 | + | ||
259 | + | ||
260 | + | @Callable(i) | |
261 | + | func withdrawVestedForTo (acc,to) = { | |
262 | + | let checks = if (mainOnly(i)) | |
263 | + | then ensureStaked() | |
264 | + | else false | |
265 | + | if ((checks == checks)) | |
266 | + | then withdrawVestedInternal(acc, to) | |
267 | + | else throw("Strict value is not equal to itself.") | |
268 | + | } | |
269 | + | ||
270 | + | ||
271 | + | ||
272 | + | @Callable(i) | |
273 | + | func claimRewards () = { | |
274 | + | let c = if (ensureStaked()) | |
275 | + | then opAllowed("liquidao_all_claimRewards") | |
276 | + | else false | |
277 | + | if ((c == c)) | |
278 | + | then { | |
279 | + | let address = toString(i.caller) | |
280 | + | let rewards = userStakingRewardsAvailable(address) | |
281 | + | if ((0 >= rewards)) | |
282 | + | then throw("nothing to claim") | |
283 | + | else (syncStaking(rewards) ++ [ScriptTransfer(addressFromStringValue(address), rewards, fromBase58String(usdn)), changeBy(userClaimedRewardsStore(address), rewards)]) | |
284 | + | } | |
285 | + | else throw("Strict value is not equal to itself.") | |
286 | + | } | |
287 | + | ||
288 | + | ||
289 | + | ||
290 | + | @Callable(i) | |
291 | + | func addRewards () = { | |
292 | + | let c = ensureStaked() | |
293 | + | if ((c == c)) | |
294 | + | then if ((toBase58String(value(i.payments[0].assetId)) != usdn)) | |
295 | + | then throw("USDN only") | |
296 | + | else (syncStaking(0) ++ [changeBy(totalStakingStore, i.payments[0].amount)]) | |
297 | + | else throw("Strict value is not equal to itself.") | |
298 | + | } | |
299 | + | ||
300 | + | ||
301 | + | ||
302 | + | @Callable(i) | |
303 | + | func withdrawAllVestedForTo (address,to) = { | |
304 | + | let checks = if (if (mainOnly(i)) | |
305 | + | then opAllowed("liquidao_all_withdrawVestedAsSurf") | |
306 | + | else false) | |
307 | + | then ensureStaked() | |
308 | + | else false | |
309 | + | if ((checks == checks)) | |
310 | + | then { | |
311 | + | let $t01161011680 = userVestingBalance(address) | |
312 | + | let totalVesting = $t01161011680._1 | |
313 | + | let availableNow = $t01161011680._2 | |
314 | + | let perDay = $t01161011680._3 | |
315 | + | if ((0 >= availableNow)) | |
316 | + | then throw("no vesting enabled") | |
317 | + | else $Tuple2(((syncStaking(availableNow) ++ [ScriptTransfer(addressFromStringValue(to), totalVesting, fromBase58String(usdn)), DeleteEntry(addressTotalStore(address)), DeleteEntry(addressTotalStoreLegacy(address)), DeleteEntry(vestingStartStore(address)), DeleteEntry(vestingClaimedStore(address)), DeleteEntry(convertedToLpStore(address)), DeleteEntry(vestingDailySpeedStore(address)), DeleteEntry(vestingLastClaimedStore(address)), changeBy(totalUSDNStore, -(totalVesting))]) ++ updateRewardData(address, -(totalVesting))), totalVesting) | |
318 | + | } | |
319 | + | else throw("Strict value is not equal to itself.") | |
320 | + | } | |
321 | + | ||
322 | + | ||
323 | + | ||
324 | + | @Callable(i) | |
325 | + | func partialWithdrawVestedForTo (acc,to,amt) = { | |
326 | + | let checks0 = mainOnly(i) | |
327 | + | if ((checks0 == checks0)) | |
328 | + | then partialWithdrawVestedInternal(acc, to, amt) | |
329 | + | else throw("Strict value is not equal to itself.") | |
330 | + | } | |
331 | + | ||
332 | + | ||
333 | + | ||
334 | + | @Callable(i) | |
335 | + | func accountFor (address) = { | |
336 | + | let attached = i.payments[0] | |
337 | + | let checks = if (if (if (mainOnly(i)) | |
338 | + | then opAllowed("liquidao_all_move") | |
339 | + | else false) | |
340 | + | then ensureStaked() | |
341 | + | else false) | |
342 | + | then throwIf((toBase58String(value(attached.assetId)) != usdn), "usdn must be attached") | |
343 | + | else false | |
344 | + | if ((checks == checks)) | |
345 | + | then { | |
346 | + | let $t01280612876 = userVestingBalance(address) | |
347 | + | let totalVesting = $t01280612876._1 | |
348 | + | let availableNow = $t01280612876._2 | |
349 | + | let perDay = $t01280612876._3 | |
350 | + | ((syncStaking(0) ++ [writeInt(addressTotalStore(address), (totalVesting + attached.amount)), DeleteEntry(vestingClaimedStore(address)), DeleteEntry(convertedToLpStore(address)), writeInt(vestingLastClaimedStore(address), HEIGHT), writeInt(vestingDailySpeedStore(address), ((totalVesting + attached.amount) / LINEAR_VESTING_MAX_DAYS)), changeBy(totalUSDNStore, attached.amount)]) ++ updateRewardData(address, attached.amount)) | |
351 | + | } | |
352 | + | else throw("Strict value is not equal to itself.") | |
353 | + | } | |
354 | + | ||
355 | + | ||
356 | + | ||
357 | + | @Callable(i) | |
358 | + | func adviseU (acc) = $Tuple2(nil, adviseUser(acc)) | |
359 | + | ||
360 | + | ||
361 | + | ||
362 | + | @Callable(i) | |
363 | + | func stake () = { | |
364 | + | func asInt (value) = match value { | |
365 | + | case int: Int => | |
366 | + | int | |
367 | + | case _ => | |
368 | + | throw("va:1") | |
369 | + | } | |
370 | + | ||
371 | + | let actualBalance = assetBalance(this, fromBase58String(usdn)) | |
372 | + | if (!(stakingEnabled)) | |
373 | + | then throw("staking not enabled") | |
374 | + | else if (isDefined(getInteger(this, stakingStartStore))) | |
375 | + | then throw("already staked") | |
376 | + | else { | |
377 | + | let inv = invoke(stakingAddress, "put", nil, [AttachedPayment(fromBase58String(usdn), actualBalance)]) | |
378 | + | if ((inv == inv)) | |
379 | + | then { | |
380 | + | let staked = asInt(invoke(stakingAddress, "info", nil, nil)) | |
381 | + | if ((staked == staked)) | |
382 | + | then [IntegerEntry(totalUSDNStore, staked), IntegerEntry(stakingStartStore, HEIGHT)] | |
383 | + | else throw("Strict value is not equal to itself.") | |
384 | + | } | |
385 | + | else throw("Strict value is not equal to itself.") | |
386 | + | } | |
387 | + | } | |
11 | 388 | ||
12 | 389 | ||
13 | 390 | @Verifier(tx) | |
14 | - | func verify () = match tx { | |
15 | - | case inv: InvokeScriptTransaction => | |
16 | - | if (if ((addressFromRecipient(inv.dApp) == this)) | |
17 | - | then cfee(inv) | |
18 | - | else false) | |
19 | - | then true | |
20 | - | else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
21 | - | case _ => | |
22 | - | sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
23 | - | } | |
391 | + | func verify () = { | |
392 | + | let BASE = 1000 | |
393 | + | let quorumRatio = valueOrErrorMessage(getInteger(configAddress, "proposal_quorum_ratio"), "proposalQuorumRatio is not defined") | |
394 | + | let passedRatio = valueOrErrorMessage(getInteger(configAddress, "proposal_passed_ratio"), "proposalThresholdRatio is not defined") | |
395 | + | let gViresContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "dividends_contract"), "no dividends_contract")), "invalid dividends_contract") | |
396 | + | let votingContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "voting_contract"), "no voting_contract")), "invalid voting_contract") | |
397 | + | let id = toBase58String(tx.id) | |
398 | + | let votesYes = valueOrElse(getInteger(votingContract, ("proposal_yes_" + id)), 0) | |
399 | + | let votesNo = valueOrElse(getInteger(votingContract, ("proposal_no_" + id)), 0) | |
400 | + | let proposalHeight = valueOrErrorMessage(getInteger(votingContract, ("proposal_height_" + id)), "proposal not registered") | |
401 | + | let applyStart = valueOrElse(getInteger(votingContract, ("proposal_applystart_" + id)), 0) | |
402 | + | let applyEnd = valueOrElse(getInteger(votingContract, ("proposal_applyend_" + id)), 0) | |
403 | + | let totalGVires = valueOrElse(getInteger(votingContract, ("proposal_gvires_" + id)), 0) | |
404 | + | let enabled = valueOrElse(getBoolean(configAddress, "op_governance_apply_tx_paused"), false) | |
405 | + | let voteYes = votesYes | |
406 | + | let voteNo = votesNo | |
407 | + | let totalVotes = (voteYes + voteNo) | |
408 | + | let hasQuorum = (((totalVotes * BASE) / totalGVires) >= quorumRatio) | |
409 | + | let hasPassed = (((voteYes * BASE) / totalVotes) >= passedRatio) | |
410 | + | let tooEarly = (applyStart >= HEIGHT) | |
411 | + | let tooLate = (HEIGHT >= applyEnd) | |
412 | + | let timeDebug = ((((((("proposalHeight = " + toString(proposalHeight)) + ", applyStart = ") + toString(applyStart)) + ", applyEnd = ") + toString(applyEnd)) + ", HEIGHT = ") + toString(HEIGHT)) | |
413 | + | let byVoting = if (!(enabled)) | |
414 | + | then throw("tx application throw governance not enabled") | |
415 | + | else if (tooEarly) | |
416 | + | then throw(("proposal can't be executed as it's too early: " + timeDebug)) | |
417 | + | else if (tooLate) | |
418 | + | then throw(("proposal can't be executed as it's too late:" + timeDebug)) | |
419 | + | else if (!(hasQuorum)) | |
420 | + | then throw((((((("no quorum: " + "totalVotes: ") + toString(totalVotes)) + ", totalGVires: ") + toString(totalGVires)) + ", quorumRatio: ") + toString(quorumRatio))) | |
421 | + | else if (!(hasPassed)) | |
422 | + | then throw((((((("no threshold achieved: " + "voteYes: ") + toString(voteYes)) + ", voteNo: ") + toString(voteNo)) + ", passedRatio: ") + toString(passedRatio))) | |
423 | + | else true | |
424 | + | if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)) | |
425 | + | then true | |
426 | + | else byVoting | |
427 | + | } | |
24 | 428 |
github/deemru/w8io/169f3d6 42.72 ms ◑