tx · 93JCaHiMe8d3iUnAkzqD2ThmDqzwA16MmdTgZY851yti

3NBynfbXC2KastUxhukcMUaE58K9cBdB9UY:  -0.02500000 Waves

2023.01.20 08:39 [2412864] smart account 3NBynfbXC2KastUxhukcMUaE58K9cBdB9UY > SELF 0.00000000 Waves

{ "type": 13, "id": "93JCaHiMe8d3iUnAkzqD2ThmDqzwA16MmdTgZY851yti", "fee": 2500000, "feeAssetId": null, "timestamp": 1674193257572, "version": 2, "chainId": 84, "sender": "3NBynfbXC2KastUxhukcMUaE58K9cBdB9UY", "senderPublicKey": "J9DCtJJxJBWZdtDR12BA1U94Q3cZzMi4R6k5hYkAzmzC", "proofs": [ "3oWDb6DZwdSCwrqdqhNF3iEu1zm3VoDGkz6a2QCHMWhFW7iXFrceb8PzTopHVVCqtFmuVZvFMs613VjK7bA2AGQd" ], "script": "base64:BgJfCAISBAoCCAgSEAoOCAgICAgICAgICAgIAQgSDwoNCAgICAgICAgICAgBCBIGCgQICAgIEgQKAggIEggKBggBAQgBCBIECgIICBIECgIICBIGCgQICAgIEgYKBAgICAhOAAdWRVJTSU9OAgYxLjEuMTABDmdldFN0cmluZ0J5S2V5AQNrZXkJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUDa2V5AgAACHVuaXRUZXN0BwAJb3JhY2xlRmVlCQEFdmFsdWUBCQCmCAEJAQ5nZXRTdHJpbmdCeUtleQECD2NvbmZfb3JhY2xlX2ZlZQAIc2lnbkRhcHAJAQV2YWx1ZQEJAKYIAQkBDmdldFN0cmluZ0J5S2V5AQIRY29uZl9zaWdud2ViX2RhcHAAC2ZlZVJlY2VpdmVyCQEOZ2V0U3RyaW5nQnlLZXkBAhFjb25mX2ZlZV9yZWNlaXZlcgAIdXNlckRhcHADBQh1bml0VGVzdAkBBXZhbHVlAQkApggBAiMzTXQ0UkdNRXlqU1dZQW9jVFBxZDU1d2RIUVFCM1BVMlVDbQkBBXZhbHVlAQkApggBCQEOZ2V0U3RyaW5nQnlLZXkBAg9jb25mX3VzZXJzX2RhcHAADXdoaXRlbGlzdERhcHAJAQV2YWx1ZQEJAKYIAQkBDmdldFN0cmluZ0J5S2V5AQITY29uZl93aGl0ZWxpc3RfZGFwcAALc2lnbkFzc2V0SWQJANkEAQkBDmdldFN0cmluZ0J5S2V5AQIYY29uZl9hY2NlcHRlZF9hc3NldF9TSUdOAAt1c2RuQXNzZXRJZAkA2QQBCQEOZ2V0U3RyaW5nQnlLZXkBAhhjb25mX2FjY2VwdGVkX2Fzc2V0X1VTRE4AC3VzZHRBc3NldElkCQDZBAEJAQ5nZXRTdHJpbmdCeUtleQECGGNvbmZfYWNjZXB0ZWRfYXNzZXRfVVNEVAAMd2F2ZXNBc3NldElkAQAABWNocmlzCQEOZ2V0U3RyaW5nQnlLZXkBAgxjb25mX2FkbWluXzEBGWdldEludGVnZXJCeUtleUZyb21PcmFjbGUBA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFCW9yYWNsZUZlZQUDa2V5Ah9JbnRlZ2VyIHVuZGVmaW5lIG9yIDAgaW4gb3JhY2xlAQ9nZXRJbnRlZ2VyQnlLZXkBA2tleQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQNrZXkAAAEOY2hlY2tXaGl0ZWxpc3QBA2tleQkBC3ZhbHVlT3JFbHNlAgkAmggCBQ13aGl0ZWxpc3REYXBwBQNrZXkAAAEPZ2V0Qm9vbGVhbkJ5S2V5AQNrZXkJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUDa2V5BwAHc2lnbkN1dAAHAAt1c2RuV2F2ZUN1dAAKAA5kZWZhdWx0TGljZW5jZQkBDmdldFN0cmluZ0J5S2V5AQIUY29uZl9kZWZhdWx0X2xpY2VuY2UAEmRlZmF1bHRIYXNoTGljZW5jZQkBDmdldFN0cmluZ0J5S2V5AQIZY29uZl9kZWZhdWx0X2xpY2VuY2VfaGFzaAALZGFwcFJ1bm5pbmcJAQt2YWx1ZU9yRWxzZQIJAJsIAgUIdXNlckRhcHACFGNvbmZfZGFwcF9pc19ydW5uaW5nBgAObWFpbnRlbmFuY2VNU0cJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUIdXNlckRhcHACFGNvbmZfbWFpbnRlbmFuY2VfbXNnAgAADXVzZXJTdXNwZW5kZWQCCVNVU1BFTkRFRAALdXNlclJlbW92ZWQCB1JFTU9WRUQAEHVzZXJVbnJlZ2lzdGVyZWQCDFVOUkVHSVNURVJFRAALdXNlckFsbG93ZWQCB0FMTE9XRUQAGWN1cnJlbnRDZXJ0aWZpY2F0aW9uUHJpY2UJARlnZXRJbnRlZ2VyQnlLZXlGcm9tT3JhY2xlAQkArAICAhJjZXJ0aWZpY2F0aW9uX2ZlZV8JANgEAQULc2lnbkFzc2V0SWQBE2dldEFydHdvcmtSb3lhbHRpZXMBA2tleQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQNrZXkA6AcBFGNoZWNrU2lnbkNlcnRpZmljYXRlAwZzaWduSUQFT3duZXIKc2hhMjU2SGFzaAQHJG1hdGNoMAkAnQgCBQhzaWduRGFwcAkArAICCQCsAgIJAKwCAgIIZGF0YV9mY18FBnNpZ25JRAIBXwUFT3duZXIDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFhBQckbWF0Y2gwAwkBCGNvbnRhaW5zAgUBYQUKc2hhMjU2SGFzaAYHBwELdmFsaWRhdGVDSUQBA2NpZAMJAQhjb250YWlucwIFA2NpZAIBLwMDCQBmAgBMCQCxAgEFA2NpZAkAAAIJALECAQkAkQMCCQC1CQIFA2NpZAIBLwAAADsHCQBmAgAQCQCxAgEJAJEDAgkAtQkCBQNjaWQCAS8AAQcHAQx2YWxpZGF0ZUhhc2gBBGhhc2gJAAACCQCxAgEFBGhhc2gAQAENa2V5VXNlclN0YXR1cwEGY2FsbGVyCQCsAgICDHVzZXJfc3RhdHVzXwUGY2FsbGVyAQdrZXlEYXRlAgZjYWxsZXIFYXJ0SWQJAKwCAgkArAICCQCsAgICCWFydF9kYXRlXwUFYXJ0SWQCAV8FBmNhbGxlcgEHa2V5TmFtZQIGY2FsbGVyBWFydElkCQCsAgIJAKwCAgkArAICAglhcnRfbmFtZV8FBWFydElkAgFfBQZjYWxsZXIBB2tleURlc2MCBmNhbGxlcgVhcnRJZAkArAICCQCsAgIJAKwCAgIJYXJ0X2Rlc2NfBQVhcnRJZAIBXwUGY2FsbGVyAQ1rZXlEaXNwbGF5Q2lkAgZjYWxsZXIFYXJ0SWQJAKwCAgkArAICCQCsAgICEGFydF9kaXNwbGF5X2NpZF8FBWFydElkAgFfBQZjYWxsZXIBDWtleUV4cG9ydEhhc2gCBmNhbGxlcgVhcnRJZAkArAICCQCsAgIJAKwCAgIQYXJ0X2V4cG9ydF9oYXNoXwUFYXJ0SWQCAV8FBmNhbGxlcgEMa2V5RXhwb3J0Q2lkAgZjYWxsZXIFYXJ0SWQJAKwCAgkArAICCQCsAgICD2FydF9leHBvcnRfY2lkXwUFYXJ0SWQCAV8FBmNhbGxlcgEKa2V5TWF4TWludAIGY2FsbGVyBWFydElkCQCsAgIJAKwCAgkArAICAgxhcnRfbWF4bWludF8FBWFydElkAgFfBQZjYWxsZXIBCWtleVNpZ25JRAIGY2FsbGVyBWFydElkCQCsAgIJAKwCAgkArAICAgthcnRfc2lnbmlkXwUFYXJ0SWQCAV8FBmNhbGxlcgEJa2V5SXNzdWVkAgZjYWxsZXIFYXJ0SWQJAKwCAgkArAICCQCsAgICC2FydF9pc3N1ZWRfBQVhcnRJZAIBXwUGY2FsbGVyAQlrZXlPblNhbGUCBmNhbGxlcgVhcnRJZAkArAICCQCsAgIJAKwCAgILYXJ0X29uc2FsZV8FBWFydElkAgFfBQZjYWxsZXIBDmtleUxpY2VuY2VIYXNoAgZjYWxsZXIFYXJ0SWQJAKwCAgkArAICCQCsAgICEWFydF9saWNlbmNlX2hhc2hfBQVhcnRJZAIBXwUGY2FsbGVyAQ1rZXlMaWNlbmNlQ2lkAgZjYWxsZXIFYXJ0SWQJAKwCAgkArAICCQCsAgICEGFydF9saWNlbmNlX2NpZF8FBWFydElkAgFfBQZjYWxsZXIBB2tleVRhZ3MCBmNhbGxlcgVhcnRJZAkArAICCQCsAgIJAKwCAgIJYXJ0X3RhZ3NfBQVhcnRJZAIBXwUGY2FsbGVyAQdrZXlUeXBlAgZjYWxsZXIFYXJ0SWQJAKwCAgkArAICCQCsAgICCWFydF90eXBlXwUFYXJ0SWQCAV8FBmNhbGxlcgEHa2V5Tm90ZQIGY2FsbGVyBWFydElkCQCsAgIJAKwCAgkArAICAglhcnRfbm90ZV8FBWFydElkAgFfBQZjYWxsZXIBCmtleUNyYXdsZXICBmNhbGxlcgVhcnRJZAkArAICCQCsAgIJAKwCAgIQYXJ0X2NyYXdsZXJfY2lkXwUFYXJ0SWQCAV8FBmNhbGxlcgEMa2V5Um95YWx0aWVzAgZjYWxsZXIFYXJ0SWQJAKwCAgkArAICCQCsAgICDmFydF9yb3lhbHRpZXNfBQVhcnRJZAIBXwUGY2FsbGVyAQhrZXlQcmljZQIGY2FsbGVyBWFydElkCQCsAgIJAKwCAgkArAICAgphcnRfcHJpY2VfBQVhcnRJZAIBXwUGY2FsbGVyAQprZXlFbmRTYWxlAgZjYWxsZXIFYXJ0SWQJAKwCAgkArAICCQCsAgICDGFydF9lbmRzYWxlXwUFYXJ0SWQCAV8FBmNhbGxlcgESa2V5QXNzZXRJZEFjY2VwdGVkAgZjYWxsZXIFYXJ0SWQJAKwCAgkArAICCQCsAgICEmFydF9hc3NldEFjY2VwdGVkXwUFYXJ0SWQCAV8FBmNhbGxlcgEHa2V5RmxhZwIGY2FsbGVyBWFydElkCQCsAgIJAKwCAgkArAICAglhcnRfZmxhZ18FBWFydElkAgFfBQZjYWxsZXIBEmtleUFydGlzdEFnZW50QWRkcgEKYXJ0aXN0QWRkcgkArAICAg1hcnRpc3RfYWdlbnRfBQphcnRpc3RBZGRyAQ9rZXlQcmltYXJ5U2hhcmUBCmFydGlzdEFkZHIJAKwCAgIVYXJ0aXN0X2FnZW50X3ByaW1hcnlfBQphcnRpc3RBZGRyARFrZXlIYXNoQnlUeGlkQWRkcgIGY2FsbGVyBHR4aWQJAKwCAgkArAICCQCsAgICE2dldF9oYXNoYnl0eGlkYWRkcl8FBHR4aWQCAV8FBmNhbGxlcgEOa2V5T3duZXJCeUhhc2gBCnNoYTI1Nkhhc2gJAKwCAgISZ2V0X293bmVyX2J5X2hhc2hfBQpzaGEyNTZIYXNoAQ1rZXlpZEJ5U2lnbmlkAgZjYWxsZXIGc2lnbklkCQCsAgIJAKwCAgkArAICAhJnZXRfYXJ0aWRieXNpZ25pZF8FBnNpZ25JZAIBXwUGY2FsbGVyARJrZXlUeGlkQnlIYXNoT3duZXICCnNoYTI1Nkhhc2gGY2FsbGVyCQCsAgICF2dldF90eGlkX2J5X2hhc2hfb3duZXJfCQDYBAEJANQWAQkAmwMBCQCsAgIFCnNoYTI1Nkhhc2gFBmNhbGxlcgEOdmFsaWRhdGVBbGxDSUQDCmNpZERpc3BsYXkJY2lkRXhwb3J0CmNpZExpY2VuY2UDCQEBIQEJAQt2YWxpZGF0ZUNJRAEFCmNpZERpc3BsYXkJAAIBAhFXcm9uZyBEaXNwbGF5IENJRAMJAQEhAQkBC3ZhbGlkYXRlQ0lEAQUJY2lkRXhwb3J0CQACAQIQV3JvbmcgRXhwb3J0IENJRAMDCQECIT0CBQpjaWRMaWNlbmNlAgAJAQEhAQkBC3ZhbGlkYXRlQ0lEAQUKY2lkTGljZW5jZQcJAAIBAhFXcm9uZyBMaWNlbmNlIENJRAYBD3ZhbGlkYXRlQWxsSGFzaAIMc2hhMjU2RXhwb3J0DXNoYTI1NkxpY2VuY2UDCQEBIQEJAQx2YWxpZGF0ZUhhc2gBBQxzaGEyNTZFeHBvcnQJAAIBAhhFeHBvcnQgSGFzaCA2NCBjaGFyLiBtYXgDCQEBIQEJAQx2YWxpZGF0ZUhhc2gBBQ1zaGEyNTZMaWNlbmNlCQACAQIZTGljZW5jZSBIYXNoIDY0IGNoYXIuIG1heAYBDnZhbGlkYXRlU3RyaW5nAgNzdHIDbWF4AwkAAAIJALECAQUDc3RyAAAJAAIBAhhGaWVsZCBjYW5ub3QgYmUgaXMgZW1wdHkDCQBmAgkAsQIBBQNzdHIFA21heAkAAgEJAKwCAgUDc3RyAgwgaXMgdG9vIGxvbmcGAQx2YWxpZGF0ZVVzZXIBBmNhbGxlcgQKdXNlclN0YXR1cwkBC3ZhbHVlT3JFbHNlAgkAnQgCBQh1c2VyRGFwcAkBDWtleVVzZXJTdGF0dXMBBQZjYWxsZXIFEHVzZXJVbnJlZ2lzdGVyZWQDAwkAAAIFCnVzZXJTdGF0dXMFEHVzZXJVbnJlZ2lzdGVyZWQGCQAAAgUKdXNlclN0YXR1cwULdXNlckFsbG93ZWQCLlJlZ2lzdGVyIHRoaXMgYWNjb3VudCBmaXJzdCB3aXRoICJBY2NvdW50IiB0YWIDCQAAAgUKdXNlclN0YXR1cwUNdXNlclN1c3BlbmRlZAIRQWNjb3VudCBzdXNwZW5kZWQDCQAAAgUKdXNlclN0YXR1cwULdXNlclJlbW92ZWQCD0FjY291bnQgcmVtb3ZlZAIAAQpzZXRMSWNlbmNlAgpjaWRMaWNlbmNlDXNoYTI1NkxpY2VuY2UEA2NpZAMJAAACCQCxAgEFCmNpZExpY2VuY2UAAAUOZGVmYXVsdExpY2VuY2UFCmNpZExpY2VuY2UEBGhhc2gDCQAAAgkAsQIBBQ1zaGEyNTZMaWNlbmNlAAAFEmRlZmF1bHRIYXNoTGljZW5jZQUNc2hhMjU2TGljZW5jZQkAlAoCBQNjaWQFBGhhc2gBE3ZhbGlkYXRlQXJ0d29ya0RhdGEKBmNhbGxlcgpjaWREaXNwbGF5CWNpZEV4cG9ydApsaWNlbmNlQ0lEDHNoYTI1NkV4cG9ydAtsaWNlbmNlSGFzaARuYW1lC2Rlc2NyaXB0aW9uBHRhZ3MJcm95YWx0aWVzBAljaGVja1VzZXIJAQx2YWxpZGF0ZVVzZXIBBQZjYWxsZXIDCQECIT0CBQljaGVja1VzZXICAAkAAgEFCWNoZWNrVXNlcgMJAAACCQCxAgEFCmNpZERpc3BsYXkAAAkAAgECG0Rpc3BsYXkgQ0lEIGNhbm5vdCBiZSBlbXB0eQMJAQEhAQkBDnZhbGlkYXRlQWxsQ0lEAwUKY2lkRGlzcGxheQUJY2lkRXhwb3J0BQpsaWNlbmNlQ0lECQACAQIQUHJvYmxlbSB3aXRoIENJRAMJAQEhAQkBD3ZhbGlkYXRlQWxsSGFzaAIFDHNoYTI1NkV4cG9ydAULbGljZW5jZUhhc2gJAAIBAhNQcm9ibGVtIHdpdGggSGFzaGVzAwkBASEBCQEOdmFsaWRhdGVTdHJpbmcCBQRuYW1lAGQJAAIBAhIxMDAgQ2hhci4gbWF4IG5hbWUDCQEBIQEJAQ52YWxpZGF0ZVN0cmluZwIFC2Rlc2NyaXB0aW9uAOgHCQACAQIaMTAwMCBDaGFyLiBtYXggZGVzY3JpcHRpb24DAwkAZgIAAAUJcm95YWx0aWVzBgkAZgIFCXJveWFsdGllcwDoBwkAAgECM1JveWFsdGllcyBjYW5ub3QgYmUgbGVzcyB0aGFuIDAlIG9yIGhpZ2hlciB0aGFuIDEwJQMJAGYCCQCQAwEJALUJAgUEdGFncwIBLAAFCQACAQILNSB0YWdzIG1heC4CAAEJaXNQYXltZW50AQFpAwkAAAIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECE05vIHBheW1lbnQgYXR0YWNoZWQEB3BheW1lbnQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAQGYW1vdW50CQEFdmFsdWUBCAUHcGF5bWVudAZhbW91bnQJAJQKAgUHcGF5bWVudAUGYW1vdW50AQ92YWxpZGF0ZVBheW1lbnQBAWkECyR0MDg5MDc4OTQzCQEJaXNQYXltZW50AQUBaQQHcGF5bWVudAgFCyR0MDg5MDc4OTQzAl8xBAZhbW91bnQIBQskdDA4OTA3ODk0MwJfMgQHYXNzZXRJZAMDCQEJaXNEZWZpbmVkAQgFB3BheW1lbnQHYXNzZXRJZAkAAAIIBQdwYXltZW50B2Fzc2V0SWQFC3NpZ25Bc3NldElkBwgFB3BheW1lbnQHYXNzZXRJZAkAAgECK09ubHkgU0lHTiB0b2tlbiBhY2NlcHRlZCBhcyB0cmFuc2FjdGlvbiBmZWUDCQECIT0CBQZhbW91bnQFGWN1cnJlbnRDZXJ0aWZpY2F0aW9uUHJpY2UJAAIBCQCsAgICGVBheW1lbnQgYW1vdW50IHNob3VsZCBiZSAJAKQDAQUZY3VycmVudENlcnRpZmljYXRpb25QcmljZQkAlAoCBQZhbW91bnQFB2Fzc2V0SWQBC2lzQXJ0TWludGVkAglhZGRyVG9Vc2UFYXJ0SWQEByRtYXRjaDAJAJoIAgUEdGhpcwkBCWtleUlzc3VlZAIFCWFkZHJUb1VzZQUFYXJ0SWQDCQABAgUHJG1hdGNoMAIDSW50BAFiBQckbWF0Y2gwAwkBAiE9AgUBYgAABgcHARR2YWxpZGF0ZVByaWNlQXNzZXRJZAMBaQxwcmljZUFzc2V0SWQMYXJ0d29ya1ByaWNlBAskdDA5NTMxOTU2NwkBCWlzUGF5bWVudAEFAWkEB3BheW1lbnQIBQskdDA5NTMxOTU2NwJfMQQGYW1vdW50CAULJHQwOTUzMTk1NjcCXzIEB2Fzc2V0SWQDCQEBIQEJAQlpc0RlZmluZWQBCAUHcGF5bWVudAdhc3NldElkBQR1bml0AwMJAGYCCQCxAgEFDHByaWNlQXNzZXRJZAAACQAAAgkA2AQBCQEFdmFsdWUBCAUHcGF5bWVudAdhc3NldElkBQxwcmljZUFzc2V0SWQHCAUHcGF5bWVudAdhc3NldElkCQACAQIOV3JvbmcgYXNzZXQgaWQDAwkAAAIFB2Fzc2V0SWQFBHVuaXQJAQIhPQIFDHByaWNlQXNzZXRJZAIABwkAAgECDldyb25nIGFzc2V0IGlkAwkBAiE9AgUMYXJ0d29ya1ByaWNlBQZhbW91bnQJAAIBAhNQYXltZW50IGRvbid0IG1hdGNoCQCUCgIFBmFtb3VudAUHYXNzZXRJZAEQYWNjZXB0ZWRBc3NldElkcwEHYXNzZXRJZAMDAwMDCQECIT0CBQdhc3NldElkCQDYBAEFC3NpZ25Bc3NldElkCQECIT0CBQdhc3NldElkCQDYBAEFDHdhdmVzQXNzZXRJZAcJAQIhPQIFB2Fzc2V0SWQCBVdBVkVTBwkBAiE9AgUHYXNzZXRJZAkA2AQBBQt1c2RuQXNzZXRJZAcJAQIhPQIFB2Fzc2V0SWQJANgEAQULdXNkdEFzc2V0SWQHCQACAQImT25seSBTSUdOLCBVU0ROLFVTRFQgb3IgV0FWRVMgYWNjZXB0ZWQGAQ92YWxpZGF0ZU1pblNlbGwCB2Fzc2V0SWQFcHJpY2UEDG1pblNlbGxXYXZlcwMFCHVuaXRUZXN0AAoJARlnZXRJbnRlZ2VyQnlLZXlGcm9tT3JhY2xlAQIOd2F2ZXNfbWluX3NlbGwEC21pblNlbGxVc2RuAMCEPQQLbWluU2VsbFNpZ24DBQh1bml0VGVzdAABCQBoAgUZY3VycmVudENlcnRpZmljYXRpb25QcmljZQACAwMDAwMDCQAAAgUHYXNzZXRJZAkA2AQBBQt1c2RuQXNzZXRJZAkAZgIFC21pblNlbGxVc2RuBQVwcmljZQcJAQIhPQIFBXByaWNlAAAHBgMDCQAAAgUHYXNzZXRJZAkA2AQBBQt1c2R0QXNzZXRJZAkAZgIFC21pblNlbGxVc2RuBQVwcmljZQcJAQIhPQIFBXByaWNlAAAHBgMDCQAAAgUHYXNzZXRJZAkA2AQBBQtzaWduQXNzZXRJZAkAZgIFC21pblNlbGxTaWduBQVwcmljZQcJAQIhPQIFBXByaWNlAAAHBgMDAwkAAAIFB2Fzc2V0SWQJANgEAQUMd2F2ZXNBc3NldElkBgkAAAIFB2Fzc2V0SWQCBVdBVkVTCQBmAgUMbWluU2VsbFdhdmVzBQVwcmljZQcJAQIhPQIFBXByaWNlAAAHCQACAQIYV3JvbmcgbWluaW11bSBzZWxsIHByaWNlBgENZ2V0QmlkQXNzZXRJZAEHYXNzZXRJZAMJAAACBQdhc3NldElkAgVXQVZFUwUEdW5pdAkA2QQBBQdhc3NldElkARZnZXRQcmljZUFzc2V0SWRGcm9tQmlkAQpiaWREYXRhS2V5BAdiaWREYXRhCQEOZ2V0U3RyaW5nQnlLZXkBCQCsAgIFCmJpZERhdGFLZXkCBV9PUEVOAwkAAAIFB2JpZERhdGECAAkAAgECDUJpZCBub3QgZm91bmQECmJpZERhdGFBcnIJALUJAgUHYmlkRGF0YQIBXwQJYmlkQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUKYmlkRGF0YUFycgABBApiaWRBc3NldElkCQENZ2V0QmlkQXNzZXRJZAEJAJEDAgUKYmlkRGF0YUFycgAAAwkAZwIAAAUJYmlkQW1vdW50CQACAQIMV3JvbmcgYW1vdW50CQCUCgIFCWJpZEFtb3VudAUKYmlkQXNzZXRJZAEVaWRDYWxsZXJEYXRlU3BvbnNvcmVkAgFpBnB1YktleQMJAQEhAQULZGFwcFJ1bm5pbmcJAAIBBQ5tYWludGVuYW5jZU1TRwQLaXNTcG9uc29yZWQJAQt2YWx1ZU9yRWxzZQIJAQ5jaGVja1doaXRlbGlzdAEJAKwCAgkApQgBCQCnCAEJANkEAQUGcHViS2V5AglfZnJlZV90eHMAAAQGY2FsbGVyAwMDCQAAAgkA2AQBCAgFAWkGY2FsbGVyBWJ5dGVzCQClCAEFBHRoaXMJAAACCQCQAwEIBQFpCHBheW1lbnRzAAAHCQBmAgULaXNTcG9uc29yZWQAAAcJAKUIAQkApwgBCQDZBAEFBnB1YktleQkA2AQBCAgFAWkGY2FsbGVyBWJ5dGVzBBNnZXRfc3BvbnNvcmVkX3dhdmVzAwkBAiE9AgUGcHViS2V5AgAJAPwHBAUNd2hpdGVsaXN0RGFwcAIJdXNlRnJlZVR4CQDMCAIJAKUIAQkApwgBCQDZBAEFBnB1YktleQUDbmlsBQNuaWwFBHVuaXQDCQAAAgUTZ2V0X3Nwb25zb3JlZF93YXZlcwUTZ2V0X3Nwb25zb3JlZF93YXZlcwkAlgoECQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQFBmNhbGxlcggFCWxhc3RCbG9jawl0aW1lc3RhbXAJAGYCBQtpc1Nwb25zb3JlZAAACQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQxpZENhbGxlckRhdGUBAWkDCQEBIQEFC2RhcHBSdW5uaW5nCQACAQUObWFpbnRlbmFuY2VNU0cJAJUKAwkA2AQBCAUBaQ10cmFuc2FjdGlvbklkCQDYBAEICAUBaQZjYWxsZXIFYnl0ZXMIBQlsYXN0QmxvY2sJdGltZXN0YW1wAQdidXlNaW50BQFpBWFydElkBmlzc3VlcgViaWRJZAhiaWRPd25lcgQNJHQwMTI5MTkxMjk3OAkBDGlkQ2FsbGVyRGF0ZQEFAWkEAmlkCAUNJHQwMTI5MTkxMjk3OAJfMQQGY2FsbGVyCAUNJHQwMTI5MTkxMjk3OAJfMgQEZGF0ZQgFDSR0MDEyOTE5MTI5NzgCXzMEBWlzQmlkAwMDCQAAAgUGY2FsbGVyBQZpc3N1ZXIJAQIhPQIFCGJpZE93bmVyAgAHCQECIT0CBQViaWRJZAIABwYHBAhibG9ja0VuZAkBD2dldEludGVnZXJCeUtleQEJAQprZXlFbmRTYWxlAgUGY2FsbGVyBQVhcnRJZAMDAwkBAiE9AgUIYmxvY2tFbmQAAAkAZwIFBmhlaWdodAUIYmxvY2tFbmQHCQEBIQEFBWlzQmlkBwkAAgECC1NhbGUgZW5kZWQuBA5jYWxsZXJJc0lzc3VlcgkAAAIFBmNhbGxlcgUGaXNzdWVyBAh0b3RhbE5GVAkBD2dldEludGVnZXJCeUtleQECEHRvdGFsX25mdF9pc3N1ZWQEBnNpZ25JRAkBDmdldFN0cmluZ0J5S2V5AQkBCWtleVNpZ25JRAIFBmlzc3VlcgUFYXJ0SWQEC2FydHdvcmtOYW1lCQEOZ2V0U3RyaW5nQnlLZXkBCQEHa2V5TmFtZQIFBmlzc3VlcgUFYXJ0SWQDCQAAAgULYXJ0d29ya05hbWUCAAkAAgECEUFydCBkb2Vzbid0IGV4aXN0BAhpc09uU2FsZQkBD2dldEJvb2xlYW5CeUtleQEJAQlrZXlPblNhbGUCBQZpc3N1ZXIFBWFydElkBAphbW91bnRTb2xkCQEPZ2V0SW50ZWdlckJ5S2V5AQkBCWtleUlzc3VlZAIFBmlzc3VlcgUFYXJ0SWQEDGFydHdvcmtQcmljZQMFDmNhbGxlcklzSXNzdWVyCQBoAgUZY3VycmVudENlcnRpZmljYXRpb25QcmljZQACCQEPZ2V0SW50ZWdlckJ5S2V5AQkBCGtleVByaWNlAgUGaXNzdWVyBQVhcnRJZAQMcHJpY2VBc3NldElkAwUOY2FsbGVySXNJc3N1ZXIJANgEAQULc2lnbkFzc2V0SWQJAQ5nZXRTdHJpbmdCeUtleQEJARJrZXlBc3NldElkQWNjZXB0ZWQCBQZpc3N1ZXIFBWFydElkBAptYXhDYW5TZWxsCQEPZ2V0SW50ZWdlckJ5S2V5AQkBCmtleU1heE1pbnQCBQZpc3N1ZXIFBWFydElkAwMDCQEBIQEFBWlzQmlkCQEBIQEFDmNhbGxlcklzSXNzdWVyBwMDCQBnAgAABQxhcnR3b3JrUHJpY2UGCQEBIQEFCGlzT25TYWxlBgkAZwIAAAUKbWF4Q2FuU2VsbAcJAAIBAhBBcnQgbm90IGZvciBzYWxlAwMDCQEBIQEFBWlzQmlkBQ5jYWxsZXJJc0lzc3VlcgcJAGcCAAAFCm1heENhblNlbGwHCQACAQIUTWF4IGlzc3VhYmxlIG5vdCBzZXQECWNoZWNrVXNlcgkBDHZhbGlkYXRlVXNlcgEFBmlzc3VlcgMDBQVpc0JpZAkBAiE9AgUJY2hlY2tVc2VyAgAHCQACAQUJY2hlY2tVc2VyBApiaWREYXRhS2V5CQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICBGJpZF8FBWFydElkAgFfBQZpc3N1ZXICAV8FCGJpZE93bmVyAgFfBQViaWRJZAQNJHQwMTQ2ODExNDg0OAMFBWlzQmlkCQEWZ2V0UHJpY2VBc3NldElkRnJvbUJpZAEFCmJpZERhdGFLZXkJARR2YWxpZGF0ZVByaWNlQXNzZXRJZAMFAWkFDHByaWNlQXNzZXRJZAUMYXJ0d29ya1ByaWNlBAZhbW91bnQIBQ0kdDAxNDY4MTE0ODQ4Al8xBAdhc3NldElkCAUNJHQwMTQ2ODExNDg0OAJfMgQFYWdlbnQJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUIdXNlckRhcHAJARJrZXlBcnRpc3RBZ2VudEFkZHIBBQZpc3N1ZXIFC2ZlZVJlY2VpdmVyBAphZ2VudFNoYXJlCQELdmFsdWVPckVsc2UCCQCaCAIFCHVzZXJEYXBwCQEPa2V5UHJpbWFyeVNoYXJlAQUGaXNzdWVyAAAEDWlzV2hpdGVsaXN0ZWQJAQ5jaGVja1doaXRlbGlzdAEFBmlzc3VlcgQDY3V0AwkAZgIFDWlzV2hpdGVsaXN0ZWQFBmhlaWdodAAAAwkAAAIFB2Fzc2V0SWQFC3NpZ25Bc3NldElkBQdzaWduQ3V0BQt1c2RuV2F2ZUN1dAQNYW1vdW50Rm9yU2lnbgkAawMFBmFtb3VudAUDY3V0AGQEDmFtb3VudEZvckFnZW50AwMDCQECIT0CBQVhZ2VudAULZmVlUmVjZWl2ZXIJAGYCBQphZ2VudFNoYXJlAAAHCQBmAgUGaGVpZ2h0BQ1pc1doaXRlbGlzdGVkBwkAawMFBmFtb3VudAUKYWdlbnRTaGFyZQBkAAAEEGFtb3VudEZvckNyZWF0b3IJAGUCBQZhbW91bnQFDWFtb3VudEZvclNpZ24DCQAAAgUKYW1vdW50U29sZAUKbWF4Q2FuU2VsbAkAAgECDEFydCBzb2xkIG91dAQNbmV3QW1vdW50U29sZAkAZAIFCmFtb3VudFNvbGQAAQQJaXNzdWVNZXRhCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIJQ3JlYXRvcjogBQZpc3N1ZXICCiwKIEFydElEOiAFBWFydElkAgssCiBTaWduSUQ6IAUGc2lnbklEAhEsCiBBcnR3b3JrIG5hbWU6IAULYXJ0d29ya05hbWUCCiwKIElzc3VlOiAJAKQDAQUNbmV3QW1vdW50U29sZAIBLwkApAMBBQptYXhDYW5TZWxsBAhpc3N1ZU5GVAkAwggFCQCsAgICA1NBXwkApAMBCQBkAgUIdG90YWxORlQAAQUJaXNzdWVNZXRhAAEAAAcEBWlkTkZUCQC4CAEFCGlzc3VlTkZUBApzZWxsU3RhdHVzAwMJAAACBQ1uZXdBbW91bnRTb2xkBQptYXhDYW5TZWxsBgkBASEBBQhpc09uU2FsZQcGBApyZWNlaXZlTkZUAwMDCQAAAgUGY2FsbGVyBQZpc3N1ZXIJAQIhPQIFCGJpZE93bmVyAgAHCQECIT0CBQViaWRJZAIABwkBEUBleHRyTmF0aXZlKDEwNjIpAQUIYmlkT3duZXIIBQFpBmNhbGxlcgQKYXNzZXRJZEJpZAMJAQEhAQkBCWlzRGVmaW5lZAEFB2Fzc2V0SWQCBVdBVkVTCQDYBAEJAQV2YWx1ZQEFB2Fzc2V0SWQEB2JpZERhdGEJAQ5nZXRTdHJpbmdCeUtleQEJAKwCAgUKYmlkRGF0YUtleQIFX09QRU4ECWJpZERlbE9sZAkBC0RlbGV0ZUVudHJ5AQkArAICBQpiaWREYXRhS2V5AgVfT1BFTgQJYmlkVXBkYXRlCQELU3RyaW5nRW50cnkCCQCsAgIFCmJpZERhdGFLZXkCB19DTE9TRUQJAKwCAgkArAICBQdiaWREYXRhAgFfCQCkAwEFBGRhdGUEB3NvbGRLZXkJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIJYXJ0X3NvbGRfCQCkAwEFDW5ld0Ftb3VudFNvbGQCBF9vZl8JAKQDAQUKbWF4Q2FuU2VsbAIBXwUFYXJ0SWQCAV8FBmlzc3VlcgQJc29sZFZhbHVlAwkBASEBBQVpc0JpZAkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICBQZjYWxsZXICAV8JAKQDAQUEZGF0ZQIBXwUCaWQCAV8JAKQDAQUMYXJ0d29ya1ByaWNlAgFfBQxwcmljZUFzc2V0SWQCAV8JANgEAQUFaWRORlQJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBBQpyZWNlaXZlTkZUAgFfCQCkAwEFBGRhdGUCAV8FAmlkAgFfCQCkAwEFBmFtb3VudAIBXwUKYXNzZXRJZEJpZAIBXwkA2AQBBQVpZE5GVAQIc29sZERhdGEJAQtTdHJpbmdFbnRyeQIFB3NvbGRLZXkFCXNvbGRWYWx1ZQQLY29tbWlzc2lvbnMDCQECIT0CBQ5hbW91bnRGb3JBZ2VudAAACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJAQdBZGRyZXNzAQkA2QQBBQtmZWVSZWNlaXZlcgkAZQIFDWFtb3VudEZvclNpZ24FDmFtb3VudEZvckFnZW50BQdhc3NldElkCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJAQdBZGRyZXNzAQkA2QQBBQVhZ2VudAUOYW1vdW50Rm9yQWdlbnQFB2Fzc2V0SWQFA25pbAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEHQWRkcmVzcwEJANkEAQULZmVlUmVjZWl2ZXIFDWFtb3VudEZvclNpZ24FB2Fzc2V0SWQFA25pbAQGYnV5UmVzCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQlrZXlJc3N1ZWQCBQZpc3N1ZXIFBWFydElkBQ1uZXdBbW91bnRTb2xkCQDMCAIJAQtTdHJpbmdFbnRyeQIJAKwCAgIEbmZ0XwkA2AQBBQVpZE5GVAUHc29sZEtleQkAzAgCCQEMSW50ZWdlckVudHJ5AgIQdG90YWxfbmZ0X2lzc3VlZAkAZAIFCHRvdGFsTkZUAAEJAMwIAgkBDEludGVnZXJFbnRyeQIJAQprZXlFbmRTYWxlAgUGaXNzdWVyBQVhcnRJZAAACQDMCAIJAQxCb29sZWFuRW50cnkCCQEJa2V5T25TYWxlAgUGaXNzdWVyBQVhcnRJZAUKc2VsbFN0YXR1cwkAzAgCBQhpc3N1ZU5GVAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEHQWRkcmVzcwEJANkEAQUGaXNzdWVyBRBhbW91bnRGb3JDcmVhdG9yBQdhc3NldElkCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFCnJlY2VpdmVORlQAAQUFaWRORlQFA25pbAULY29tbWlzc2lvbnMDBQVpc0JpZAkAzAgCBQhzb2xkRGF0YQkAzAgCBQliaWRVcGRhdGUJAMwIAgUJYmlkRGVsT2xkBQZidXlSZXMJAMwIAgUIc29sZERhdGEFBmJ1eVJlcwEIYXNTdHJpbmcBAmJ2BAckbWF0Y2gwBQJidgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEA2J2MAUHJG1hdGNoMAUDYnYwCQACAQIkU3BvbnNvcmVkIFB1YmxpYyBLZXkgU3RyaW5nIGV4cGVjdGVkCgZpbnZva2UBB3NldENvbmYCA2tleQN2YWwEBmNhbGxlcgkApQgBCAUGaW52b2tlBmNhbGxlcgMJAQ9jb250YWluc0VsZW1lbnQCCQDMCAIFBWNocmlzCQDMCAIJAKUIAQUEdGhpcwUDbmlsBQZjYWxsZXIDCQEIY29udGFpbnMCBQNrZXkCBWNvbmZfCQDMCAIJAQtTdHJpbmdFbnRyeQIFA2tleQUDdmFsBQNuaWwJAAIBAiBFbnRyaWVzIHN0YXJ0aW5nIHdpdGggY29uZl8gb25seQkAAgECIllvdSBhcmUgbm90IGFsbG93ZWQgdG8gY2hhbmdlIHRoaXMBaQEKYWRkQXJ0d29yaw4Kc2hhMjU2SGFzaAZzaWduSUQEbmFtZQtkZXNjcmlwdGlvbgR0YWdzBHR5cGUKY2lkRGlzcGxheQxzaGEyNTZFeHBvcnQJY2lkRXhwb3J0DXNoYTI1NkxpY2VuY2UKY2lkTGljZW5jZQdjcmF3bGVyCXJveWFsdGllcwZwdWJLZXkEDSR0MDE4ODgxMTg5NTQJARVpZENhbGxlckRhdGVTcG9uc29yZWQCBQFpBQZwdWJLZXkEBWFydElkCAUNJHQwMTg4ODExODk1NAJfMQQGY2FsbGVyCAUNJHQwMTg4ODExODk1NAJfMgQEZGF0ZQgFDSR0MDE4ODgxMTg5NTQCXzMEC2lzU3BvbnNvcmVkCAUNJHQwMTg4ODExODk1NAJfNAMJAQEhAQkBDHZhbGlkYXRlSGFzaAEFCnNoYTI1Nkhhc2gJAAIBAiRIYXNoIHNob3VsZCBiZSA2NCBjaGFyYWN0ZXJzIG1heGltdW0EDSR0MDE5MDU1MTkxMjQJAQpzZXRMSWNlbmNlAgUKY2lkTGljZW5jZQUNc2hhMjU2TGljZW5jZQQKbGljZW5jZUNJRAgFDSR0MDE5MDU1MTkxMjQCXzEEC2xpY2VuY2VIYXNoCAUNJHQwMTkwNTUxOTEyNAJfMgQPdmFsaWRhdGVBcnR3b3JrCQETdmFsaWRhdGVBcnR3b3JrRGF0YQoFBmNhbGxlcgUKY2lkRGlzcGxheQUJY2lkRXhwb3J0BQpsaWNlbmNlQ0lEBQxzaGEyNTZFeHBvcnQFC2xpY2VuY2VIYXNoBQRuYW1lBQtkZXNjcmlwdGlvbgUEdGFncwUJcm95YWx0aWVzAwkBAiE9AgUPdmFsaWRhdGVBcnR3b3JrAgAJAAIBAhVTb21ldGhpbmcgd2VudCB3cm9uZyEEEHdoaXRlbGlzdGVkX2Ryb3AJAGYCCQEOY2hlY2tXaGl0ZWxpc3QBCQCsAgIFBmNhbGxlcgILX2ZyZWVfZHJvcHMAAAQNJHQwMTk0MjMxOTUwNwMFEHdoaXRlbGlzdGVkX2Ryb3AJAJQKAgAABQZzaWduSUQJAQ92YWxpZGF0ZVBheW1lbnQBBQFpBAZhbW91bnQIBQ0kdDAxOTQyMzE5NTA3Al8xBAdhc3NldElkCAUNJHQwMTk0MjMxOTUwNwJfMgMJAQEhAQkBCWlzRGVmaW5lZAEFBmFtb3VudAkAAgECFFNvbWV0aGluZyB3ZW50IHdyb25nBAplbnRyeUV4aXN0CQEOZ2V0U3RyaW5nQnlLZXkBCQESa2V5VHhpZEJ5SGFzaE93bmVyAgUKc2hhMjU2SGFzaAUGY2FsbGVyAwkBAiE9AgUKZW50cnlFeGlzdAIACQACAQIUWW91IGFscmVhZHkgYWRkZWQgaXQECWhhc2hFeGlzdAkBDmdldFN0cmluZ0J5S2V5AQkBDmtleU93bmVyQnlIYXNoAQUKc2hhMjU2SGFzaAMJAQIhPQIFCWhhc2hFeGlzdAIACQACAQIXSGFzaCBhbHJlYWR5IHJlZ2lzdGVyZWQED2lzU2lnbkNlcnRpZmllZAkBFGNoZWNrU2lnbkNlcnRpZmljYXRlAwUGc2lnbklEBQZjYWxsZXIFCnNoYTI1Nkhhc2gDCQEBIQEFD2lzU2lnbkNlcnRpZmllZAkAAgECLFNpZ24gQ2VydGlmaWNhdGUgbm90IGZvdW5kIGZvciB0aGlzIGFkZHJlc3MuBBdkZWNyZWFzZV93aGl0ZWxpc3RfZHJvcAMFEHdoaXRlbGlzdGVkX2Ryb3AJAPwHBAUNd2hpdGVsaXN0RGFwcAILdXNlRnJlZURyb3AJAMwIAgUGY2FsbGVyBQNuaWwFA25pbAUEdW5pdAMJAAACBRdkZWNyZWFzZV93aGl0ZWxpc3RfZHJvcAUXZGVjcmVhc2Vfd2hpdGVsaXN0X2Ryb3AECnR4VG9DYWxsZXIDBQtpc1Nwb25zb3JlZAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEHQWRkcmVzcwEJANkEAQUGY2FsbGVyAAAFBHVuaXQFA25pbAUDbmlsCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDmtleU93bmVyQnlIYXNoAQUKc2hhMjU2SGFzaAUGY2FsbGVyCQDMCAIJAQtTdHJpbmdFbnRyeQIJARJrZXlUeGlkQnlIYXNoT3duZXICBQpzaGEyNTZIYXNoBQZjYWxsZXIFBWFydElkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEHa2V5RGF0ZQIFBmNhbGxlcgUFYXJ0SWQFBGRhdGUJAMwIAgkBC1N0cmluZ0VudHJ5AgkBB2tleU5hbWUCBQZjYWxsZXIFBWFydElkBQRuYW1lCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQdrZXlEZXNjAgUGY2FsbGVyBQVhcnRJZAULZGVzY3JpcHRpb24JAMwIAgkBC1N0cmluZ0VudHJ5AgkBDWtleURpc3BsYXlDaWQCBQZjYWxsZXIFBWFydElkBQpjaWREaXNwbGF5CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxrZXlFeHBvcnRDaWQCBQZjYWxsZXIFBWFydElkBQljaWRFeHBvcnQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDWtleUV4cG9ydEhhc2gCBQZjYWxsZXIFBWFydElkBQxzaGEyNTZFeHBvcnQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDmtleUxpY2VuY2VIYXNoAgUGY2FsbGVyBQVhcnRJZAULbGljZW5jZUhhc2gJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDWtleUxpY2VuY2VDaWQCBQZjYWxsZXIFBWFydElkBQpsaWNlbmNlQ0lECQDMCAIJAQtTdHJpbmdFbnRyeQIJAQdrZXlUeXBlAgUGY2FsbGVyBQVhcnRJZAUEdHlwZQkAzAgCCQELU3RyaW5nRW50cnkCCQEHa2V5VGFncwIFBmNhbGxlcgUFYXJ0SWQFBHRhZ3MJAMwIAgkBDEludGVnZXJFbnRyeQIJAQprZXlNYXhNaW50AgUGY2FsbGVyBQVhcnRJZAAACQDMCAIJAQtTdHJpbmdFbnRyeQIJAQlrZXlTaWduSUQCBQZjYWxsZXIFBWFydElkBQZzaWduSUQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQlrZXlJc3N1ZWQCBQZjYWxsZXIFBWFydElkAAAJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAQlrZXlPblNhbGUCBQZjYWxsZXIFBWFydElkBwkAzAgCCQELU3RyaW5nRW50cnkCCQENa2V5aWRCeVNpZ25pZAIFBmNhbGxlcgUGc2lnbklEBQVhcnRJZAkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5SGFzaEJ5VHhpZEFkZHICBQZjYWxsZXIFBWFydElkBQpzaGEyNTZIYXNoCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQprZXlDcmF3bGVyAgUGY2FsbGVyBQVhcnRJZAUHY3Jhd2xlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDGtleVJveWFsdGllcwIFBmNhbGxlcgUFYXJ0SWQFCXJveWFsdGllcwkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEHQWRkcmVzcwEJANkEAQULZmVlUmVjZWl2ZXIFBmFtb3VudAULc2lnbkFzc2V0SWQFA25pbAUKdHhUb0NhbGxlcgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ11cGRhdGVBcnR3b3JrDQR0eGlkBG5hbWULZGVzY3JpcHRpb24EdGFncwR0eXBlCmNpZERpc3BsYXkMc2hhMjU2RXhwb3J0CWNpZEV4cG9ydA1zaGEyNTZMaWNlbmNlCmNpZExpY2VuY2UHY3Jhd2xlcglyb3lhbHRpZXMGcHViS2V5AwkBASEBBQtkYXBwUnVubmluZwkAAgEFDm1haW50ZW5hbmNlTVNHBA0kdDAyMjU0MTIyNjExCQEVaWRDYWxsZXJEYXRlU3BvbnNvcmVkAgUBaQUGcHViS2V5BAJpZAgFDSR0MDIyNTQxMjI2MTECXzEEBmNhbGxlcggFDSR0MDIyNTQxMjI2MTECXzIEBGRhdGUIBQ0kdDAyMjU0MTIyNjExAl8zBAtpc1Nwb25zb3JlZAgFDSR0MDIyNTQxMjI2MTECXzQEDSR0MDIyNjIxMjI2OTAJAQpzZXRMSWNlbmNlAgUKY2lkTGljZW5jZQUNc2hhMjU2TGljZW5jZQQKbGljZW5jZUNJRAgFDSR0MDIyNjIxMjI2OTACXzEEC2xpY2VuY2VIYXNoCAUNJHQwMjI2MjEyMjY5MAJfMgQPdmFsaWRhdGVBcnR3b3JrCQETdmFsaWRhdGVBcnR3b3JrRGF0YQoFBmNhbGxlcgUKY2lkRGlzcGxheQUJY2lkRXhwb3J0BQpsaWNlbmNlQ0lEBQxzaGEyNTZFeHBvcnQFC2xpY2VuY2VIYXNoBQRuYW1lBQtkZXNjcmlwdGlvbgUEdGFncwUJcm95YWx0aWVzAwkBAiE9AgUPdmFsaWRhdGVBcnR3b3JrAgAJAAIBAhVTb21ldGhpbmcgd2VudCB3cm9uZyEECmVudHJ5RXhpc3QJAQ5nZXRTdHJpbmdCeUtleQEJAQdrZXlOYW1lAgUGY2FsbGVyBQR0eGlkAwkAAAIFCmVudHJ5RXhpc3QCAAkAAgECD0VudHJ5IG5vdCBmb3VuZAQEZmxhZwkBDmdldFN0cmluZ0J5S2V5AQkBB2tleUZsYWcCBQZjYWxsZXIFBHR4aWQDCQAAAgUEZmxhZwIHSUxMRUdBTAkAAgECHUNhbm5vdCB1cGRhdGUgSUxMRUdBTCBhcnR3b3JrAwkBASEBCQELaXNBcnRNaW50ZWQCBQZjYWxsZXIFBHR4aWQECnR4VG9DYWxsZXIDBQtpc1Nwb25zb3JlZAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEHQWRkcmVzcwEJANkEAQUGY2FsbGVyAAAFBHVuaXQFA25pbAUDbmlsCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBB2tleU5hbWUCBQZjYWxsZXIFBHR4aWQFBG5hbWUJAMwIAgkBC1N0cmluZ0VudHJ5AgkBB2tleURlc2MCBQZjYWxsZXIFBHR4aWQFC2Rlc2NyaXB0aW9uCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ1rZXlEaXNwbGF5Q2lkAgUGY2FsbGVyBQR0eGlkBQpjaWREaXNwbGF5CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxrZXlFeHBvcnRDaWQCBQZjYWxsZXIFBHR4aWQFCWNpZEV4cG9ydAkAzAgCCQELU3RyaW5nRW50cnkCCQENa2V5RXhwb3J0SGFzaAIFBmNhbGxlcgUEdHhpZAUMc2hhMjU2RXhwb3J0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ1rZXlMaWNlbmNlQ2lkAgUGY2FsbGVyBQR0eGlkBQpsaWNlbmNlQ0lECQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ5rZXlMaWNlbmNlSGFzaAIFBmNhbGxlcgUEdHhpZAULbGljZW5jZUhhc2gJAMwIAgkBC1N0cmluZ0VudHJ5AgkBB2tleVRhZ3MCBQZjYWxsZXIFBHR4aWQFBHRhZ3MJAMwIAgkBC1N0cmluZ0VudHJ5AgkBB2tleVR5cGUCBQZjYWxsZXIFBHR4aWQFBHR5cGUJAMwIAgkBC1N0cmluZ0VudHJ5AgkBCmtleUNyYXdsZXICBQZjYWxsZXIFBHR4aWQFB2NyYXdsZXIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQxrZXlSb3lhbHRpZXMCBQZjYWxsZXIFBHR4aWQFCXJveWFsdGllcwUDbmlsBQp0eFRvQ2FsbGVyCQACAQIOQWxyZWFkeSBtaW50ZWQBaQELZmxhZ0FydHdvcmsEBWFydElkBGFkZHIEZmxhZwRub3RlBA0kdDAyNDMxNzI0MzUxCQEMaWRDYWxsZXJEYXRlAQUBaQQCaWQIBQ0kdDAyNDMxNzI0MzUxAl8xBAZjYWxsZXIIBQ0kdDAyNDMxNzI0MzUxAl8yAwkBD2NvbnRhaW5zRWxlbWVudAIJAMwIAgUFY2hyaXMJAMwIAgkApQgBBQR0aGlzBQNuaWwFBmNhbGxlcgMJAQ9jb250YWluc0VsZW1lbnQCCQDMCAICB0NPTlNFTlQJAMwIAgIACQDMCAICD0NIQU5HRV9SRVFVSVJFRAkAzAgCAgdGTEFHR0VECQDMCAICB0lMTEVHQUwFA25pbAUEZmxhZwkAzAgCCQELU3RyaW5nRW50cnkCCQEHa2V5RmxhZwIFBGFkZHIFBWFydElkBQRmbGFnCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQdrZXlOb3RlAgUEYWRkcgUFYXJ0SWQFBG5vdGUFA25pbAkAAgEJAKwCAgIOVW5rbm93IHN0YXR1cyAFBGZsYWcJAAIBAhNZb3UgYXJlIG5vdCBhbGxvd2VkAWkBDWRlbGV0ZUFydHdvcmsCBWFydElkBGFkZHIEDSR0MDI0Nzg3MjQ4MjEJAQxpZENhbGxlckRhdGUBBQFpBAJpZAgFDSR0MDI0Nzg3MjQ4MjECXzEEBmNhbGxlcggFDSR0MDI0Nzg3MjQ4MjECXzIECWFkZHJUb1VzZQMJAQ9jb250YWluc0VsZW1lbnQCCQDMCAIFBWNocmlzCQDMCAIJAKUIAQUEdGhpcwUDbmlsBQZjYWxsZXIFBGFkZHIFBmNhbGxlcgQKZW50cnlFeGlzdAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQEOZ2V0U3RyaW5nQnlLZXkBCQEHa2V5TmFtZQIFCWFkZHJUb1VzZQUFYXJ0SWQCIE5vIGFydCBtYXRjaGluZyBmb3IgdGhpcyBhZGRyZXNzAwkAAAIFCmVudHJ5RXhpc3QCAAkAAgECIE5vIGFydCBtYXRjaGluZyBmb3IgdGhpcyBhZGRyZXNzBApzaGEyNTZIYXNoCQEOZ2V0U3RyaW5nQnlLZXkBCQERa2V5SGFzaEJ5VHhpZEFkZHICBQlhZGRyVG9Vc2UFBWFydElkAwkAAAIFCnNoYTI1Nkhhc2gCAAkAAgECJU5vIGFydCBoYXNoIG1hdGNoaW5nIGZvciB0aGlzIGFkZHJlc3MEBnNpZ25JRAkBDmdldFN0cmluZ0J5S2V5AQkBCWtleVNpZ25JRAIFCWFkZHJUb1VzZQUFYXJ0SWQDCQAAAgUGc2lnbklEAgAJAAIBAhNObyBTSUdOIElEIG1hdGNoaW5nBAxkYXRhVG9EZWxldGUJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBB2tleURhdGUCBQlhZGRyVG9Vc2UFBWFydElkCQDMCAIJAQtEZWxldGVFbnRyeQEJAQdrZXlOYW1lAgUJYWRkclRvVXNlBQVhcnRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEHa2V5RGVzYwIFCWFkZHJUb1VzZQUFYXJ0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBDWtleURpc3BsYXlDaWQCBQlhZGRyVG9Vc2UFBWFydElkCQDMCAIJAQtEZWxldGVFbnRyeQEJAQxrZXlFeHBvcnRDaWQCBQlhZGRyVG9Vc2UFBWFydElkCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ1rZXlFeHBvcnRIYXNoAgUJYWRkclRvVXNlBQVhcnRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEOa2V5TGljZW5jZUhhc2gCBQlhZGRyVG9Vc2UFBWFydElkCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ1rZXlMaWNlbmNlQ2lkAgUJYWRkclRvVXNlBQVhcnRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEHa2V5VHlwZQIFCWFkZHJUb1VzZQUFYXJ0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBB2tleVRhZ3MCBQlhZGRyVG9Vc2UFBWFydElkCQDMCAIJAQtEZWxldGVFbnRyeQEJAQprZXlNYXhNaW50AgUJYWRkclRvVXNlBQVhcnRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEJa2V5U2lnbklEAgUJYWRkclRvVXNlBQVhcnRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEJa2V5SXNzdWVkAgUJYWRkclRvVXNlBQVhcnRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEJa2V5T25TYWxlAgUJYWRkclRvVXNlBQVhcnRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEHa2V5RmxhZwIFCWFkZHJUb1VzZQUFYXJ0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBCGtleVByaWNlAgUJYWRkclRvVXNlBQVhcnRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQESa2V5QXNzZXRJZEFjY2VwdGVkAgUJYWRkclRvVXNlBQVhcnRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEOa2V5T3duZXJCeUhhc2gBBQpzaGEyNTZIYXNoCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ1rZXlpZEJ5U2lnbmlkAgUJYWRkclRvVXNlBQZzaWduSUQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBEmtleVR4aWRCeUhhc2hPd25lcgIFCnNoYTI1Nkhhc2gFCWFkZHJUb1VzZQkAzAgCCQELRGVsZXRlRW50cnkBCQEKa2V5RW5kU2FsZQIFCWFkZHJUb1VzZQUFYXJ0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBB2tleU5vdGUCBQlhZGRyVG9Vc2UFBWFydElkCQDMCAIJAQtEZWxldGVFbnRyeQEJAQprZXlDcmF3bGVyAgUJYWRkclRvVXNlBQVhcnRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEMa2V5Um95YWx0aWVzAgUJYWRkclRvVXNlBQVhcnRJZAUDbmlsAwkBASEBCQELaXNBcnRNaW50ZWQCBQlhZGRyVG9Vc2UFBWFydElkAwkBASEBBQtkYXBwUnVubmluZwkAAgEFDm1haW50ZW5hbmNlTVNHBQxkYXRhVG9EZWxldGUDCQEPY29udGFpbnNFbGVtZW50AgkAzAgCBQVjaHJpcwkAzAgCCQClCAEFBHRoaXMFA25pbAUGY2FsbGVyBQxkYXRhVG9EZWxldGUJAAIBAihBcnQgYWxyZWFkeSBtaW50ZWQsIHlvdSBjYW5ub3QgZGVsZXRlIGl0AWkBC3NlbGxBcnR3b3JrBgVhcnRJZAVwcmljZQdtYXhNaW50B2Fzc2V0SWQIYmxvY2tFbmQGcHViS2V5BA0kdDAyNzY1NzI3NzI3CQEVaWRDYWxsZXJEYXRlU3BvbnNvcmVkAgUBaQUGcHViS2V5BAJpZAgFDSR0MDI3NjU3Mjc3MjcCXzEEBmNhbGxlcggFDSR0MDI3NjU3Mjc3MjcCXzIEBGRhdGUIBQ0kdDAyNzY1NzI3NzI3Al8zBAtpc1Nwb25zb3JlZAgFDSR0MDI3NjU3Mjc3MjcCXzQEC2FydHdvcmtOYW1lCQEOZ2V0U3RyaW5nQnlLZXkBCQEHa2V5TmFtZQIFBmNhbGxlcgUFYXJ0SWQDCQAAAgULYXJ0d29ya05hbWUCAAkAAgECI1RoaXMgYXJ0IGRvZXNuJ3QgbWF0Y2ggeW91ciBhY2NvdW50BARmbGFnCQEOZ2V0U3RyaW5nQnlLZXkBCQEHa2V5RmxhZwIFBmNhbGxlcgUFYXJ0SWQDCQEPY29udGFpbnNFbGVtZW50AgkAzAgCAg9DSEFOR0VfUkVRVUlSRUQJAMwIAgIHRkxBR0dFRAkAzAgCAgdJTExFR0FMBQNuaWwFBGZsYWcJAAIBAg9GbGFnZ2VkIGFydHdvcmsEBmJpZE5icgkBD2dldEludGVnZXJCeUtleQEJAKwCAgISY3VycmVudF9iaWRhbW91bnRfBQVhcnRJZAMJAGYCAAAFCGJsb2NrRW5kCQACAQIMTmVnYXRpdmUgZW5kAwMJAGYCBQhibG9ja0VuZAAAAwkBAiE9AgUHbWF4TWludAABBgkBAiE9AgUFcHJpY2UAAAcJAAIBAjpUaW1lZCBvZmZlciBvbmx5IGFsbG93ZWQgZm9yIHVuaXF1ZSBlZGl0aW9uIGFuZCBvZmZlciBvbmx5BApiYXNlSGVpZ2h0AwkAAAIFCGJsb2NrRW5kAAAAAAUGaGVpZ2h0AwkBASEBCQEQYWNjZXB0ZWRBc3NldElkcwEFB2Fzc2V0SWQJAAIBAhVTb21ldGhpbmcgd2VudCB3cm9uZyEDCQEBIQEJAQ92YWxpZGF0ZU1pblNlbGwCBQdhc3NldElkBQVwcmljZQkAAgECFVNvbWV0aGluZyB3ZW50IHdyb25nIQQJY2hlY2tVc2VyCQEMdmFsaWRhdGVVc2VyAQUGY2FsbGVyAwkBAiE9AgUJY2hlY2tVc2VyAgAJAAIBBQljaGVja1VzZXIECmFtb3VudFNvbGQJAQ9nZXRJbnRlZ2VyQnlLZXkBCQEJa2V5SXNzdWVkAgUGY2FsbGVyBQVhcnRJZAQKbWF4Q2FuU2VsbAkBD2dldEludGVnZXJCeUtleQEJAQprZXlNYXhNaW50AgUGY2FsbGVyBQVhcnRJZAMJAGYCBQdtYXhNaW50AGQJAAIBAhwxMDAgZWRpdGlvbnMgbWF4IHBlciBhcnR3b3JrAwMJAQIhPQIFCmFtb3VudFNvbGQAAAkAAAIFCmFtb3VudFNvbGQFCm1heENhblNlbGwHCQACAQIUTWF4IGVkaXRpb24gcmVhY2hlZC4DAwkAZgIFCmFtb3VudFNvbGQAAAkBAiE9AgUKbWF4Q2FuU2VsbAUHbWF4TWludAcJAAIBAiZDYW5ub3QgY2hhbmdlIG1heGltdW0gaXNzdWFibGUgYW55bW9yZQMDCQBmAgUGYmlkTmJyAAAJAQIhPQIFCm1heENhblNlbGwFB21heE1pbnQHCQACAQIxQ2Fubm90IGNoYW5nZSBtYXhpbXVtIGlzc3VhYmxlIHdpdGggYWN0aXZlIG9yZGVycwQKc2VsbFN0YXR1cwMDCQBmAgUFcHJpY2UAAAkAZgIFB21heE1pbnQAAAcGBwQKdHhUb0NhbGxlcgMFC2lzU3BvbnNvcmVkCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJAQdBZGRyZXNzAQkA2QQBBQZjYWxsZXIAAAUEdW5pdAUDbmlsBQNuaWwJAM4IAgkAzAgCCQEMQm9vbGVhbkVudHJ5AgkBCWtleU9uU2FsZQIFBmNhbGxlcgUFYXJ0SWQFCnNlbGxTdGF0dXMJAMwIAgkBDEludGVnZXJFbnRyeQIJAQhrZXlQcmljZQIFBmNhbGxlcgUFYXJ0SWQFBXByaWNlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEKa2V5TWF4TWludAIFBmNhbGxlcgUFYXJ0SWQFB21heE1pbnQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEmtleUFzc2V0SWRBY2NlcHRlZAIFBmNhbGxlcgUFYXJ0SWQFB2Fzc2V0SWQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQprZXlFbmRTYWxlAgUGY2FsbGVyBQVhcnRJZAkAZAIFCmJhc2VIZWlnaHQFCGJsb2NrRW5kBQNuaWwFCnR4VG9DYWxsZXIBaQEKYnV5QXJ0d29yawIFYXJ0SWQGaXNzdWVyCQEHYnV5TWludAUFAWkFBWFydElkBQZpc3N1ZXICAAIAAWkBBnNldEJpZAIFYXJ0SWQGaXNzdWVyBA0kdDAzMDEwNTMwMTQ1CQEMaWRDYWxsZXJEYXRlAQUBaQQCaWQIBQ0kdDAzMDEwNTMwMTQ1Al8xBAZjYWxsZXIIBQ0kdDAzMDEwNTMwMTQ1Al8yBARkYXRlCAUNJHQwMzAxMDUzMDE0NQJfMwQNJHQwMzAxNTAzMDE4NgkBCWlzUGF5bWVudAEFAWkEB3BheW1lbnQIBQ0kdDAzMDE1MDMwMTg2Al8xBAZhbW91bnQIBQ0kdDAzMDE1MDMwMTg2Al8yBAdhc3NldElkAwkBASEBCQEJaXNEZWZpbmVkAQgFB3BheW1lbnQHYXNzZXRJZAIFV0FWRVMJANgEAQkBBXZhbHVlAQgFB3BheW1lbnQHYXNzZXRJZAQIYmxvY2tFbmQJAQ9nZXRJbnRlZ2VyQnlLZXkBCQEKa2V5RW5kU2FsZQIFBmlzc3VlcgUFYXJ0SWQDAwkBAiE9AgUIYmxvY2tFbmQAAAkAZwIFBmhlaWdodAUIYmxvY2tFbmQHCQACAQILU2FsZSBlbmRlZC4EBmJpZE5icgkBD2dldEludGVnZXJCeUtleQEJAKwCAgISY3VycmVudF9iaWRhbW91bnRfBQVhcnRJZAMJAQEhAQkBEGFjY2VwdGVkQXNzZXRJZHMBBQdhc3NldElkCQACAQISYXNzZXQgbm90IGFjY2VwdGVkAwkBASEBCQEPdmFsaWRhdGVNaW5TZWxsAgUHYXNzZXRJZAUGYW1vdW50CQACAQIOV3JvbmcgbWluIHNlbGwECmFtb3VudFNvbGQJAQ9nZXRJbnRlZ2VyQnlLZXkBCQEJa2V5SXNzdWVkAgUGaXNzdWVyBQVhcnRJZAQKbWF4Q2FuU2VsbAkBD2dldEludGVnZXJCeUtleQEJAQprZXlNYXhNaW50AgUGaXNzdWVyBQVhcnRJZAMJAGcCAAAFCm1heENhblNlbGwJAAIBAiNObyBtYXggZWRpdGlvbiBzZXQgZm9yIHRoaXMgYXJ0d29yawMJAGcCBQphbW91bnRTb2xkBQptYXhDYW5TZWxsCQACAQIYU29sZCBvdXQsIHlvdSBjYW5ub3QgYmlkCQDMCAIJAQtTdHJpbmdFbnRyeQIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAgRiaWRfBQVhcnRJZAIBXwUGaXNzdWVyAgFfBQZjYWxsZXICAV8FAmlkAgVfT1BFTgkArAICCQCsAgIJAKwCAgkArAICBQdhc3NldElkAgFfCQCkAwEFBmFtb3VudAIBXwkApAMBBQRkYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICEmN1cnJlbnRfYmlkYW1vdW50XwUFYXJ0SWQJAGQCBQZiaWROYnIAAQUDbmlsAWkBCWFjY2VwdEJpZAQFYXJ0SWQGaXNzdWVyBWJpZElkCGJpZE93bmVyBA0kdDAzMTM0NDMxMzg0CQEMaWRDYWxsZXJEYXRlAQUBaQQCaWQIBQ0kdDAzMTM0NDMxMzg0Al8xBAZjYWxsZXIIBQ0kdDAzMTM0NDMxMzg0Al8yBARkYXRlCAUNJHQwMzEzNDQzMTM4NAJfMwMJAQIhPQIFBmNhbGxlcgUGaXNzdWVyCQACAQIZWW91IGNhbm5vdCBkbyB0aGlzIGFjdGlvbgkBB2J1eU1pbnQFBQFpBQVhcnRJZAUGaXNzdWVyBQViaWRJZAUIYmlkT3duZXIBaQEJY2FuY2VsQmlkBAVhcnRJZAZpc3N1ZXIFYmlkSWQIYmlkT3duZXIEDSR0MDMxNjEwMzE2NzEJAQxpZENhbGxlckRhdGUBBQFpBAJpZAgFDSR0MDMxNjEwMzE2NzECXzEEBmNhbGxlcggFDSR0MDMxNjEwMzE2NzECXzIEBGRhdGUIBQ0kdDAzMTYxMDMxNjcxAl8zAwMJAQIhPQIFBmNhbGxlcgUIYmlkT3duZXIJAQIhPQIFBmNhbGxlcgUGaXNzdWVyBwkAAgECGVlvdSBjYW5ub3QgZG8gdGhpcyBhY3Rpb24EDXJldHVybk1vbmV5VG8DCQAAAgUGY2FsbGVyBQZpc3N1ZXIFCGJpZE93bmVyBQZjYWxsZXIEBmJpZE5icgkBD2dldEludGVnZXJCeUtleQEJAKwCAgISY3VycmVudF9iaWRhbW91bnRfBQVhcnRJZAQKYmlkRGF0YUtleQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAgRiaWRfBQVhcnRJZAIBXwUGaXNzdWVyAgFfBQhiaWRPd25lcgIBXwUFYmlkSWQEB2JpZERhdGEJAQ5nZXRTdHJpbmdCeUtleQEJAKwCAgUKYmlkRGF0YUtleQIFX09QRU4DCQAAAgUHYmlkRGF0YQIACQACAQINQmlkIG5vdCBmb3VuZAQKYmlkRGF0YUFycgkAtQkCBQdiaWREYXRhAgFfBAdhc3NldElkCQENZ2V0QmlkQXNzZXRJZAEJAJEDAgUKYmlkRGF0YUFycgAABAliaWRTdGF0dXMCCENBTkNFTEVECQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgUKYmlkRGF0YUtleQIFX09QRU4JAMwIAgkBC1N0cmluZ0VudHJ5AgkArAICCQCsAgIFCmJpZERhdGFLZXkCAV8FCWJpZFN0YXR1cwkArAICCQCsAgIFB2JpZERhdGECAV8JAKQDAQUEZGF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhJjdXJyZW50X2JpZGFtb3VudF8FBWFydElkCQBlAgUGYmlkTmJyAAEJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBB0FkZHJlc3MBCQDZBAEFDXJldHVybk1vbmV5VG8JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQpiaWREYXRhQXJyAAEFB2Fzc2V0SWQFA25pbAECdHgBCHZlcmlmaWVyAAQHJG1hdGNoMAUCdHgDCQABAgUHJG1hdGNoMAIXSW52b2tlU2NyaXB0VHJhbnNhY3Rpb24EA2ludgUHJG1hdGNoMAMDAwkAAAIIBQNpbnYIZnVuY3Rpb24CCmFkZEFydHdvcmsJAAACCAUDaW52BGRBcHAFBHRoaXMHCQAAAggFA2ludgNmZWUAoMIeBwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAkA2QQBCQEIYXNTdHJpbmcBCQCRAwIIBQNpbnYEYXJncwANAwMDCQAAAggFA2ludghmdW5jdGlvbgINdXBkYXRlQXJ0d29yawkAAAIIBQNpbnYEZEFwcAUEdGhpcwcJAAACCAUDaW52A2ZlZQCgwh4HCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACQDZBAEJAQhhc1N0cmluZwEJAJEDAggFA2ludgRhcmdzAAwDAwMJAAACCAUDaW52CGZ1bmN0aW9uAgtzZWxsQXJ0d29yawkAAAIIBQNpbnYEZEFwcAUEdGhpcwcJAAACCAUDaW52A2ZlZQCgwh4HCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACQDZBAEJAQhhc1N0cmluZwEJAJEDAggFA2ludgRhcmdzAAUJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAIBQJ0eA9zZW5kZXJQdWJsaWNLZXkJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAIBQJ0eA9zZW5kZXJQdWJsaWNLZXnUd3pP", "height": 2412864, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: CxATTQkJGwMW5NJnMhwXzm2Kowba6fCNhY2U4qbNpbhx Next: 9kDGwgP1t1AmFViMTyAqXeptj59HjpgLnxizf5tn51tm Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let VERSION = "1.5"
4+let VERSION = "1.1.10"
55
66 func getStringByKey (key) = valueOrElse(getString(this, key), "")
7+
8+
9+let unitTest = false
10+
11+let oracleFee = value(addressFromString(getStringByKey("conf_oracle_fee")))
12+
13+let signDapp = value(addressFromString(getStringByKey("conf_signweb_dapp")))
14+
15+let feeReceiver = getStringByKey("conf_fee_receiver")
16+
17+let userDapp = if (unitTest)
18+ then value(addressFromString("3Mt4RGMEyjSWYAocTPqd55wdHQQB3PU2UCm"))
19+ else value(addressFromString(getStringByKey("conf_users_dapp")))
20+
21+let whitelistDapp = value(addressFromString(getStringByKey("conf_whitelist_dapp")))
22+
23+let signAssetId = fromBase58String(getStringByKey("conf_accepted_asset_SIGN"))
24+
25+let usdnAssetId = fromBase58String(getStringByKey("conf_accepted_asset_USDN"))
26+
27+let usdtAssetId = fromBase58String(getStringByKey("conf_accepted_asset_USDT"))
28+
29+let wavesAssetId = base58''
30+
31+let chris = getStringByKey("conf_admin_1")
32+
33+func getIntegerByKeyFromOracle (key) = valueOrErrorMessage(getInteger(oracleFee, key), "Integer undefine or 0 in oracle")
34+
35+
36+func getIntegerByKey (key) = valueOrElse(getInteger(this, key), 0)
37+
38+
39+func checkWhitelist (key) = valueOrElse(getInteger(whitelistDapp, key), 0)
740
841
942 func getBooleanByKey (key) = valueOrElse(getBoolean(this, key), false)
1043
1144
12-func getIntegerByKey (key) = valueOrElse(getInteger(this, key), 0)
45+let signCut = 7
1346
47+let usdnWaveCut = 10
1448
15-let chris = getStringByKey("conf_admin_1")
49+let defaultLicence = getStringByKey("conf_default_licence")
1650
17-let dappRunningKey = "conf_dapp_is_running"
51+let defaultHashLicence = getStringByKey("conf_default_licence_hash")
1852
19-let maintenanceMSGKey = "conf_maintenance_msg"
53+let dappRunning = valueOrElse(getBoolean(userDapp, "conf_dapp_is_running"), true)
2054
21-let whitelistedonlyKey = "conf_whitelisted_only"
22-
23-let dappRunning = valueOrElse(getBoolean(this, dappRunningKey), true)
24-
25-let maintenanceMSG = valueOrElse(getString(this, maintenanceMSGKey), "")
26-
27-let whitelistedonly = valueOrElse(getBoolean(this, whitelistedonlyKey), true)
28-
29-let whitelistDapp = value(addressFromString(getStringByKey("conf_whitelist_dapp")))
30-
31-let userAllowed = "ALLOWED"
32-
33-let userRegistered = "REGISTERED"
34-
35-let userVerified = "VERIFIED"
55+let maintenanceMSG = valueOrElse(getString(userDapp, "conf_maintenance_msg"), "")
3656
3757 let userSuspended = "SUSPENDED"
3858
3959 let userRemoved = "REMOVED"
4060
41-let userChangeRequired = "CHANGE_REQUIRED"
42-
4361 let userUnregistered = "UNREGISTERED"
4462
45-let userReset = "RESET"
63+let userAllowed = "ALLOWED"
4664
47-func keyUserAddr (caller) = ("user_" + caller)
65+let currentCertificationPrice = getIntegerByKeyFromOracle(("certification_fee_" + toBase58String(signAssetId)))
66+
67+func getArtworkRoyalties (key) = valueOrElse(getInteger(this, key), 1000)
4868
4969
50-func keyUserName (caller) = ("user_name_" + caller)
51-
52-
53-func keyUserDesc (caller) = ("user_desc_" + caller)
54-
55-
56-func keyUserSocial (caller) = ("user_social_" + caller)
57-
58-
59-func keyUserThumb (caller) = ("user_thumb_" + caller)
60-
61-
62-func keyUserStatus (caller) = ("user_status_" + caller)
63-
64-
65-func keyUserRoyalties (caller) = ("user_royalties_" + caller)
66-
67-
68-func keyUserDate (caller) = ("user_date_" + caller)
69-
70-
71-func keyUserERC20 (caller) = ("user_ERC20_" + caller)
72-
73-
74-func keyArtistAgentAddr (artistAddr) = ("artist_agent_" + artistAddr)
75-
76-
77-func keyAgentArtistAddr (agentAddr,artistAddr) = ((("agent_" + agentAddr) + "_") + artistAddr)
78-
79-
80-func keyPrimaryShare (artistAddr) = ("artist_agent_primary_" + artistAddr)
81-
82-
83-func keySecondaryShare (artistAddr) = ("artist_agent_secondary_" + artistAddr)
84-
85-
86-func checkWhitelist (key) = valueOrElse(getInteger(whitelistDapp, key), 0)
70+func checkSignCertificate (signID,Owner,sha256Hash) = match getString(signDapp, ((("data_fc_" + signID) + "_") + Owner)) {
71+ case a: String =>
72+ if (contains(a, sha256Hash))
73+ then true
74+ else false
75+ case _ =>
76+ false
77+}
8778
8879
8980 func validateCID (cid) = if (contains(cid, "/"))
9586 else false
9687
9788
98-func validUserData (caller,name,description,thumb,isAnUpdate) = {
99- let validCID = if ((size(thumb) != 0))
100- then validateCID(thumb)
89+func validateHash (hash) = (size(hash) == 64)
90+
91+
92+func keyUserStatus (caller) = ("user_status_" + caller)
93+
94+
95+func keyDate (caller,artId) = ((("art_date_" + artId) + "_") + caller)
96+
97+
98+func keyName (caller,artId) = ((("art_name_" + artId) + "_") + caller)
99+
100+
101+func keyDesc (caller,artId) = ((("art_desc_" + artId) + "_") + caller)
102+
103+
104+func keyDisplayCid (caller,artId) = ((("art_display_cid_" + artId) + "_") + caller)
105+
106+
107+func keyExportHash (caller,artId) = ((("art_export_hash_" + artId) + "_") + caller)
108+
109+
110+func keyExportCid (caller,artId) = ((("art_export_cid_" + artId) + "_") + caller)
111+
112+
113+func keyMaxMint (caller,artId) = ((("art_maxmint_" + artId) + "_") + caller)
114+
115+
116+func keySignID (caller,artId) = ((("art_signid_" + artId) + "_") + caller)
117+
118+
119+func keyIssued (caller,artId) = ((("art_issued_" + artId) + "_") + caller)
120+
121+
122+func keyOnSale (caller,artId) = ((("art_onsale_" + artId) + "_") + caller)
123+
124+
125+func keyLicenceHash (caller,artId) = ((("art_licence_hash_" + artId) + "_") + caller)
126+
127+
128+func keyLicenceCid (caller,artId) = ((("art_licence_cid_" + artId) + "_") + caller)
129+
130+
131+func keyTags (caller,artId) = ((("art_tags_" + artId) + "_") + caller)
132+
133+
134+func keyType (caller,artId) = ((("art_type_" + artId) + "_") + caller)
135+
136+
137+func keyNote (caller,artId) = ((("art_note_" + artId) + "_") + caller)
138+
139+
140+func keyCrawler (caller,artId) = ((("art_crawler_cid_" + artId) + "_") + caller)
141+
142+
143+func keyRoyalties (caller,artId) = ((("art_royalties_" + artId) + "_") + caller)
144+
145+
146+func keyPrice (caller,artId) = ((("art_price_" + artId) + "_") + caller)
147+
148+
149+func keyEndSale (caller,artId) = ((("art_endsale_" + artId) + "_") + caller)
150+
151+
152+func keyAssetIdAccepted (caller,artId) = ((("art_assetAccepted_" + artId) + "_") + caller)
153+
154+
155+func keyFlag (caller,artId) = ((("art_flag_" + artId) + "_") + caller)
156+
157+
158+func keyArtistAgentAddr (artistAddr) = ("artist_agent_" + artistAddr)
159+
160+
161+func keyPrimaryShare (artistAddr) = ("artist_agent_primary_" + artistAddr)
162+
163+
164+func keyHashByTxidAddr (caller,txid) = ((("get_hashbytxidaddr_" + txid) + "_") + caller)
165+
166+
167+func keyOwnerByHash (sha256Hash) = ("get_owner_by_hash_" + sha256Hash)
168+
169+
170+func keyidBySignid (caller,signId) = ((("get_artidbysignid_" + signId) + "_") + caller)
171+
172+
173+func keyTxidByHashOwner (sha256Hash,caller) = ("get_txid_by_hash_owner_" + toBase58String(sha256_16Kb(toBytes((sha256Hash + caller)))))
174+
175+
176+func validateAllCID (cidDisplay,cidExport,cidLicence) = if (!(validateCID(cidDisplay)))
177+ then throw("Wrong Display CID")
178+ else if (!(validateCID(cidExport)))
179+ then throw("Wrong Export CID")
180+ else if (if ((cidLicence != ""))
181+ then !(validateCID(cidLicence))
182+ else false)
183+ then throw("Wrong Licence CID")
184+ else true
185+
186+
187+func validateAllHash (sha256Export,sha256Licence) = if (!(validateHash(sha256Export)))
188+ then throw("Export Hash 64 char. max")
189+ else if (!(validateHash(sha256Licence)))
190+ then throw("Licence Hash 64 char. max")
101191 else true
102- if (!(validCID))
103- then throw("CID don't match requirement!")
104- else if (if ((name == ""))
105- then true
106- else (description == ""))
107- then throw("Name and description cannot be empty")
108- else if ((size(description) > 600))
109- then throw("600 Char. max description")
110- else if ((size(name) > 45))
111- then throw("45 Char. max name")
112- else {
113- let status = getStringByKey(keyUserStatus(caller))
114- if (if ((status == userSuspended))
115- then true
116- else (status == userRemoved))
117- then throw("Account suspended/ removed.")
118- else if (if (!(isAnUpdate))
119- then (status == userRegistered)
120- else false)
121- then throw("Already registered")
122- else if (if (if (!(isAnUpdate))
123- then (status == "")
124- else false)
125- then whitelistedonly
126- else false)
127- then throw("Can't register, get approved first.")
128- else if (if (if (isAnUpdate)
129- then (status == "")
130- else false)
131- then true
132- else if (isAnUpdate)
133- then (status == userAllowed)
134- else false)
135- then throw("Register first")
136- else true
137- }
192+
193+
194+func validateString (str,max) = if ((size(str) == 0))
195+ then throw("Field cannot be is empty")
196+ else if ((size(str) > max))
197+ then throw((str + " is too long"))
198+ else true
199+
200+
201+func validateUser (caller) = {
202+ let userStatus = valueOrElse(getString(userDapp, keyUserStatus(caller)), userUnregistered)
203+ if (if ((userStatus == userUnregistered))
204+ then true
205+ else (userStatus == userAllowed))
206+ then "Register this account first with \"Account\" tab"
207+ else if ((userStatus == userSuspended))
208+ then "Account suspended"
209+ else if ((userStatus == userRemoved))
210+ then "Account removed"
211+ else ""
138212 }
139213
140214
141-func validateNewStatus (status,address,currentStatus) = {
142- let allStatus = [userVerified, userRegistered, userSuspended, userRemoved, userAllowed, userChangeRequired]
143- let statusToSet = if (containsElement(allStatus, status))
144- then status
145- else if (if ((status == userReset))
146- then (currentStatus == userAllowed)
147- else false)
148- then ""
149- else throw("Unknown status")
150- let userIsRegistered = getIntegerByKey(keyUserDate(address))
151- if (if ((userIsRegistered == 0))
152- then (statusToSet != userAllowed)
153- else false)
154- then throw("You cant set this status, user is not registered.")
155- else if (if ((currentStatus == userAllowed))
156- then (statusToSet == userAllowed)
157- else false)
158- then throw("User already allowed")
159- else if (if ((currentStatus == userRegistered))
160- then (statusToSet == userAllowed)
161- else false)
162- then throw("User already allowed & registered")
163- else if (if ((currentStatus == userVerified))
164- then (statusToSet == userAllowed)
165- else false)
166- then throw("User already allowed & verified")
167- else statusToSet
215+func setLIcence (cidLicence,sha256Licence) = {
216+ let cid = if ((size(cidLicence) == 0))
217+ then defaultLicence
218+ else cidLicence
219+ let hash = if ((size(sha256Licence) == 0))
220+ then defaultHashLicence
221+ else sha256Licence
222+ $Tuple2(cid, hash)
168223 }
169224
170225
171-func makeJSON (name,thumb,date) = (((((("{\"user_name\": \"" + name) + "\", \"user_thumb\":\"") + thumb) + "\",\"user_date\":\"") + date) + "\"}")
226+func validateArtworkData (caller,cidDisplay,cidExport,licenceCID,sha256Export,licenceHash,name,description,tags,royalties) = {
227+ let checkUser = validateUser(caller)
228+ if ((checkUser != ""))
229+ then throw(checkUser)
230+ else if ((size(cidDisplay) == 0))
231+ then throw("Display CID cannot be empty")
232+ else if (!(validateAllCID(cidDisplay, cidExport, licenceCID)))
233+ then throw("Problem with CID")
234+ else if (!(validateAllHash(sha256Export, licenceHash)))
235+ then throw("Problem with Hashes")
236+ else if (!(validateString(name, 100)))
237+ then throw("100 Char. max name")
238+ else if (!(validateString(description, 1000)))
239+ then throw("1000 Char. max description")
240+ else if (if ((0 > royalties))
241+ then true
242+ else (royalties > 1000))
243+ then throw("Royalties cannot be less than 0% or higher than 10%")
244+ else if ((size(split(tags, ",")) > 5))
245+ then throw("5 tags max.")
246+ else ""
247+ }
248+
249+
250+func isPayment (i) = if ((size(i.payments) == 0))
251+ then throw("No payment attached")
252+ else {
253+ let payment = value(i.payments[0])
254+ let amount = value(payment.amount)
255+ $Tuple2(payment, amount)
256+ }
257+
258+
259+func validatePayment (i) = {
260+ let $t089078943 = isPayment(i)
261+ let payment = $t089078943._1
262+ let amount = $t089078943._2
263+ let assetId = if (if (isDefined(payment.assetId))
264+ then (payment.assetId == signAssetId)
265+ else false)
266+ then payment.assetId
267+ else throw("Only SIGN token accepted as transaction fee")
268+ if ((amount != currentCertificationPrice))
269+ then throw(("Payment amount should be " + toString(currentCertificationPrice)))
270+ else $Tuple2(amount, assetId)
271+ }
272+
273+
274+func isArtMinted (addrToUse,artId) = match getInteger(this, keyIssued(addrToUse, artId)) {
275+ case b: Int =>
276+ if ((b != 0))
277+ then true
278+ else false
279+ case _ =>
280+ false
281+}
282+
283+
284+func validatePriceAssetId (i,priceAssetId,artworkPrice) = {
285+ let $t095319567 = isPayment(i)
286+ let payment = $t095319567._1
287+ let amount = $t095319567._2
288+ let assetId = if (!(isDefined(payment.assetId)))
289+ then unit
290+ else if (if ((size(priceAssetId) > 0))
291+ then (toBase58String(value(payment.assetId)) == priceAssetId)
292+ else false)
293+ then payment.assetId
294+ else throw("Wrong asset id")
295+ if (if ((assetId == unit))
296+ then (priceAssetId != "")
297+ else false)
298+ then throw("Wrong asset id")
299+ else if ((artworkPrice != amount))
300+ then throw("Payment don't match")
301+ else $Tuple2(amount, assetId)
302+ }
303+
304+
305+func acceptedAssetIds (assetId) = if (if (if (if (if ((assetId != toBase58String(signAssetId)))
306+ then (assetId != toBase58String(wavesAssetId))
307+ else false)
308+ then (assetId != "WAVES")
309+ else false)
310+ then (assetId != toBase58String(usdnAssetId))
311+ else false)
312+ then (assetId != toBase58String(usdtAssetId))
313+ else false)
314+ then throw("Only SIGN, USDN,USDT or WAVES accepted")
315+ else true
316+
317+
318+func validateMinSell (assetId,price) = {
319+ let minSellWaves = if (unitTest)
320+ then 10
321+ else getIntegerByKeyFromOracle("waves_min_sell")
322+ let minSellUsdn = 1000000
323+ let minSellSign = if (unitTest)
324+ then 1
325+ else (currentCertificationPrice * 2)
326+ if (if (if (if (if (if ((assetId == toBase58String(usdnAssetId)))
327+ then (minSellUsdn > price)
328+ else false)
329+ then (price != 0)
330+ else false)
331+ then true
332+ else if (if ((assetId == toBase58String(usdtAssetId)))
333+ then (minSellUsdn > price)
334+ else false)
335+ then (price != 0)
336+ else false)
337+ then true
338+ else if (if ((assetId == toBase58String(signAssetId)))
339+ then (minSellSign > price)
340+ else false)
341+ then (price != 0)
342+ else false)
343+ then true
344+ else if (if (if ((assetId == toBase58String(wavesAssetId)))
345+ then true
346+ else (assetId == "WAVES"))
347+ then (minSellWaves > price)
348+ else false)
349+ then (price != 0)
350+ else false)
351+ then throw("Wrong minimum sell price")
352+ else true
353+ }
354+
355+
356+func getBidAssetId (assetId) = if ((assetId == "WAVES"))
357+ then unit
358+ else fromBase58String(assetId)
359+
360+
361+func getPriceAssetIdFromBid (bidDataKey) = {
362+ let bidData = getStringByKey((bidDataKey + "_OPEN"))
363+ if ((bidData == ""))
364+ then throw("Bid not found")
365+ else {
366+ let bidDataArr = split(bidData, "_")
367+ let bidAmount = parseIntValue(bidDataArr[1])
368+ let bidAssetId = getBidAssetId(bidDataArr[0])
369+ if ((0 >= bidAmount))
370+ then throw("Wrong amount")
371+ else $Tuple2(bidAmount, bidAssetId)
372+ }
373+ }
374+
375+
376+func idCallerDateSponsored (i,pubKey) = if (!(dappRunning))
377+ then throw(maintenanceMSG)
378+ else {
379+ let isSponsored = valueOrElse(checkWhitelist((toString(addressFromPublicKey(fromBase58String(pubKey))) + "_free_txs")), 0)
380+ let caller = if (if (if ((toBase58String(i.caller.bytes) == toString(this)))
381+ then (size(i.payments) == 0)
382+ else false)
383+ then (isSponsored > 0)
384+ else false)
385+ then toString(addressFromPublicKey(fromBase58String(pubKey)))
386+ else toBase58String(i.caller.bytes)
387+ let get_sponsored_waves = if ((pubKey != ""))
388+ then invoke(whitelistDapp, "useFreeTx", [toString(addressFromPublicKey(fromBase58String(pubKey)))], nil)
389+ else unit
390+ if ((get_sponsored_waves == get_sponsored_waves))
391+ then $Tuple4(toBase58String(i.transactionId), caller, lastBlock.timestamp, (isSponsored > 0))
392+ else throw("Strict value is not equal to itself.")
393+ }
394+
395+
396+func idCallerDate (i) = if (!(dappRunning))
397+ then throw(maintenanceMSG)
398+ else $Tuple3(toBase58String(i.transactionId), toBase58String(i.caller.bytes), lastBlock.timestamp)
399+
400+
401+func buyMint (i,artId,issuer,bidId,bidOwner) = {
402+ let $t01291912978 = idCallerDate(i)
403+ let id = $t01291912978._1
404+ let caller = $t01291912978._2
405+ let date = $t01291912978._3
406+ let isBid = if (if (if ((caller == issuer))
407+ then (bidOwner != "")
408+ else false)
409+ then (bidId != "")
410+ else false)
411+ then true
412+ else false
413+ let blockEnd = getIntegerByKey(keyEndSale(caller, artId))
414+ if (if (if ((blockEnd != 0))
415+ then (height >= blockEnd)
416+ else false)
417+ then !(isBid)
418+ else false)
419+ then throw("Sale ended.")
420+ else {
421+ let callerIsIssuer = (caller == issuer)
422+ let totalNFT = getIntegerByKey("total_nft_issued")
423+ let signID = getStringByKey(keySignID(issuer, artId))
424+ let artworkName = getStringByKey(keyName(issuer, artId))
425+ if ((artworkName == ""))
426+ then throw("Art doesn't exist")
427+ else {
428+ let isOnSale = getBooleanByKey(keyOnSale(issuer, artId))
429+ let amountSold = getIntegerByKey(keyIssued(issuer, artId))
430+ let artworkPrice = if (callerIsIssuer)
431+ then (currentCertificationPrice * 2)
432+ else getIntegerByKey(keyPrice(issuer, artId))
433+ let priceAssetId = if (callerIsIssuer)
434+ then toBase58String(signAssetId)
435+ else getStringByKey(keyAssetIdAccepted(issuer, artId))
436+ let maxCanSell = getIntegerByKey(keyMaxMint(issuer, artId))
437+ if (if (if (!(isBid))
438+ then !(callerIsIssuer)
439+ else false)
440+ then if (if ((0 >= artworkPrice))
441+ then true
442+ else !(isOnSale))
443+ then true
444+ else (0 >= maxCanSell)
445+ else false)
446+ then throw("Art not for sale")
447+ else if (if (if (!(isBid))
448+ then callerIsIssuer
449+ else false)
450+ then (0 >= maxCanSell)
451+ else false)
452+ then throw("Max issuable not set")
453+ else {
454+ let checkUser = validateUser(issuer)
455+ if (if (isBid)
456+ then (checkUser != "")
457+ else false)
458+ then throw(checkUser)
459+ else {
460+ let bidDataKey = ((((((("bid_" + artId) + "_") + issuer) + "_") + bidOwner) + "_") + bidId)
461+ let $t01468114848 = if (isBid)
462+ then getPriceAssetIdFromBid(bidDataKey)
463+ else validatePriceAssetId(i, priceAssetId, artworkPrice)
464+ let amount = $t01468114848._1
465+ let assetId = $t01468114848._2
466+ let agent = valueOrElse(getString(userDapp, keyArtistAgentAddr(issuer)), feeReceiver)
467+ let agentShare = valueOrElse(getInteger(userDapp, keyPrimaryShare(issuer)), 0)
468+ let isWhitelisted = checkWhitelist(issuer)
469+ let cut = if ((isWhitelisted > height))
470+ then 0
471+ else if ((assetId == signAssetId))
472+ then signCut
473+ else usdnWaveCut
474+ let amountForSign = fraction(amount, cut, 100)
475+ let amountForAgent = if (if (if ((agent != feeReceiver))
476+ then (agentShare > 0)
477+ else false)
478+ then (height > isWhitelisted)
479+ else false)
480+ then fraction(amount, agentShare, 100)
481+ else 0
482+ let amountForCreator = (amount - amountForSign)
483+ if ((amountSold == maxCanSell))
484+ then throw("Art sold out")
485+ else {
486+ let newAmountSold = (amountSold + 1)
487+ let issueMeta = ((((((((((("Creator: " + issuer) + ",
488+ ArtID: ") + artId) + ",
489+ SignID: ") + signID) + ",
490+ Artwork name: ") + artworkName) + ",
491+ Issue: ") + toString(newAmountSold)) + "/") + toString(maxCanSell))
492+ let issueNFT = Issue(("SA_" + toString((totalNFT + 1))), issueMeta, 1, 0, false)
493+ let idNFT = calculateAssetId(issueNFT)
494+ let sellStatus = if (if ((newAmountSold == maxCanSell))
495+ then true
496+ else !(isOnSale))
497+ then false
498+ else true
499+ let receiveNFT = if (if (if ((caller == issuer))
500+ then (bidOwner != "")
501+ else false)
502+ then (bidId != "")
503+ else false)
504+ then addressFromStringValue(bidOwner)
505+ else i.caller
506+ let assetIdBid = if (!(isDefined(assetId)))
507+ then "WAVES"
508+ else toBase58String(value(assetId))
509+ let bidData = getStringByKey((bidDataKey + "_OPEN"))
510+ let bidDelOld = DeleteEntry((bidDataKey + "_OPEN"))
511+ let bidUpdate = StringEntry((bidDataKey + "_CLOSED"), ((bidData + "_") + toString(date)))
512+ let soldKey = ((((((("art_sold_" + toString(newAmountSold)) + "_of_") + toString(maxCanSell)) + "_") + artId) + "_") + issuer)
513+ let soldValue = if (!(isBid))
514+ then ((((((((((caller + "_") + toString(date)) + "_") + id) + "_") + toString(artworkPrice)) + "_") + priceAssetId) + "_") + toBase58String(idNFT))
515+ else ((((((((((toString(receiveNFT) + "_") + toString(date)) + "_") + id) + "_") + toString(amount)) + "_") + assetIdBid) + "_") + toBase58String(idNFT))
516+ let soldData = StringEntry(soldKey, soldValue)
517+ let commissions = if ((amountForAgent != 0))
518+ then [ScriptTransfer(Address(fromBase58String(feeReceiver)), (amountForSign - amountForAgent), assetId), ScriptTransfer(Address(fromBase58String(agent)), amountForAgent, assetId)]
519+ else [ScriptTransfer(Address(fromBase58String(feeReceiver)), amountForSign, assetId)]
520+ let buyRes = ([IntegerEntry(keyIssued(issuer, artId), newAmountSold), StringEntry(("nft_" + toBase58String(idNFT)), soldKey), IntegerEntry("total_nft_issued", (totalNFT + 1)), IntegerEntry(keyEndSale(issuer, artId), 0), BooleanEntry(keyOnSale(issuer, artId), sellStatus), issueNFT, ScriptTransfer(Address(fromBase58String(issuer)), amountForCreator, assetId), ScriptTransfer(receiveNFT, 1, idNFT)] ++ commissions)
521+ if (isBid)
522+ then [soldData, bidUpdate, bidDelOld] :: buyRes
523+ else soldData :: buyRes
524+ }
525+ }
526+ }
527+ }
528+ }
529+ }
172530
173531
174532 func asString (bv) = match bv {
179537 }
180538
181539
182-func getCaller (i,pubKey) = {
183- let isSponsored = valueOrElse(checkWhitelist((toString(addressFromPublicKey(fromBase58String(pubKey))) + "_free_txs")), 0)
184- let caller = if (if (if ((toBase58String(i.caller.bytes) == toString(this)))
185- then (size(i.payments) == 0)
186- else false)
187- then (isSponsored > 0)
188- else false)
189- then toString(addressFromPublicKey(fromBase58String(pubKey)))
190- else toBase58String(i.caller.bytes)
191- let get_sponsored_waves = if ((pubKey != ""))
192- then invoke(whitelistDapp, "useFreeTx", [toString(addressFromPublicKey(fromBase58String(pubKey)))], nil)
193- else unit
194- if ((get_sponsored_waves == get_sponsored_waves))
195- then $Tuple2(caller, (isSponsored > 0))
196- else throw("Strict value is not equal to itself.")
197- }
198-
199-
200540 @Callable(invoke)
201541 func setConf (key,val) = {
202542 let caller = toString(invoke.caller)
203543 if (containsElement([chris, toString(this)], caller))
204- then [StringEntry(key, val)]
544+ then if (contains(key, "conf_"))
545+ then [StringEntry(key, val)]
546+ else throw("Entries starting with conf_ only")
205547 else throw("You are not allowed to change this")
206548 }
207549
208550
209551
210-@Callable(invoke)
211-func appRunning (isLive,message) = {
212- let caller = toString(invoke.caller)
213- if (containsElement([chris, toString(this)], caller))
214- then [BooleanEntry(dappRunningKey, isLive), StringEntry(maintenanceMSGKey, message)]
215- else throw("You are not allowed to change this")
552+@Callable(i)
553+func addArtwork (sha256Hash,signID,name,description,tags,type,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence,crawler,royalties,pubKey) = {
554+ let $t01888118954 = idCallerDateSponsored(i, pubKey)
555+ let artId = $t01888118954._1
556+ let caller = $t01888118954._2
557+ let date = $t01888118954._3
558+ let isSponsored = $t01888118954._4
559+ if (!(validateHash(sha256Hash)))
560+ then throw("Hash should be 64 characters maximum")
561+ else {
562+ let $t01905519124 = setLIcence(cidLicence, sha256Licence)
563+ let licenceCID = $t01905519124._1
564+ let licenceHash = $t01905519124._2
565+ let validateArtwork = validateArtworkData(caller, cidDisplay, cidExport, licenceCID, sha256Export, licenceHash, name, description, tags, royalties)
566+ if ((validateArtwork != ""))
567+ then throw("Something went wrong!")
568+ else {
569+ let whitelisted_drop = (checkWhitelist((caller + "_free_drops")) > 0)
570+ let $t01942319507 = if (whitelisted_drop)
571+ then $Tuple2(0, signID)
572+ else validatePayment(i)
573+ let amount = $t01942319507._1
574+ let assetId = $t01942319507._2
575+ if (!(isDefined(amount)))
576+ then throw("Something went wrong")
577+ else {
578+ let entryExist = getStringByKey(keyTxidByHashOwner(sha256Hash, caller))
579+ if ((entryExist != ""))
580+ then throw("You already added it")
581+ else {
582+ let hashExist = getStringByKey(keyOwnerByHash(sha256Hash))
583+ if ((hashExist != ""))
584+ then throw("Hash already registered")
585+ else {
586+ let isSignCertified = checkSignCertificate(signID, caller, sha256Hash)
587+ if (!(isSignCertified))
588+ then throw("Sign Certificate not found for this address.")
589+ else {
590+ let decrease_whitelist_drop = if (whitelisted_drop)
591+ then invoke(whitelistDapp, "useFreeDrop", [caller], nil)
592+ else unit
593+ if ((decrease_whitelist_drop == decrease_whitelist_drop))
594+ then {
595+ let txToCaller = if (isSponsored)
596+ then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
597+ else nil
598+ ([StringEntry(keyOwnerByHash(sha256Hash), caller), StringEntry(keyTxidByHashOwner(sha256Hash, caller), artId), IntegerEntry(keyDate(caller, artId), date), StringEntry(keyName(caller, artId), name), StringEntry(keyDesc(caller, artId), description), StringEntry(keyDisplayCid(caller, artId), cidDisplay), StringEntry(keyExportCid(caller, artId), cidExport), StringEntry(keyExportHash(caller, artId), sha256Export), StringEntry(keyLicenceHash(caller, artId), licenceHash), StringEntry(keyLicenceCid(caller, artId), licenceCID), StringEntry(keyType(caller, artId), type), StringEntry(keyTags(caller, artId), tags), IntegerEntry(keyMaxMint(caller, artId), 0), StringEntry(keySignID(caller, artId), signID), IntegerEntry(keyIssued(caller, artId), 0), BooleanEntry(keyOnSale(caller, artId), false), StringEntry(keyidBySignid(caller, signID), artId), StringEntry(keyHashByTxidAddr(caller, artId), sha256Hash), StringEntry(keyCrawler(caller, artId), crawler), IntegerEntry(keyRoyalties(caller, artId), royalties), ScriptTransfer(Address(fromBase58String(feeReceiver)), amount, signAssetId)] ++ txToCaller)
599+ }
600+ else throw("Strict value is not equal to itself.")
601+ }
602+ }
603+ }
604+ }
605+ }
606+ }
216607 }
217608
218609
219610
220-@Callable(invoke)
221-func registrationMode (WLonly) = {
222- let caller = toString(invoke.caller)
223- if (containsElement([chris, toString(this)], caller))
224- then [BooleanEntry(whitelistedonlyKey, WLonly)]
225- else throw("You are not allowed to change this")
226- }
227-
228-
229-
230-@Callable(invoke)
231-func registerUser (name,description,thumb,social,royalties,pubKey) = if (!(dappRunning))
611+@Callable(i)
612+func updateArtwork (txid,name,description,tags,type,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence,crawler,royalties,pubKey) = if (!(dappRunning))
232613 then throw(maintenanceMSG)
233614 else {
234- let $t072777329 = getCaller(invoke, pubKey)
235- let caller = $t072777329._1
236- let isSponsored = $t072777329._2
237- let id = toBase58String(invoke.transactionId)
238- let timestamp = lastBlock.timestamp
239- if (!(validUserData(caller, name, description, thumb, false)))
240- then throw("Something went wrong")
615+ let $t02254122611 = idCallerDateSponsored(i, pubKey)
616+ let id = $t02254122611._1
617+ let caller = $t02254122611._2
618+ let date = $t02254122611._3
619+ let isSponsored = $t02254122611._4
620+ let $t02262122690 = setLIcence(cidLicence, sha256Licence)
621+ let licenceCID = $t02262122690._1
622+ let licenceHash = $t02262122690._2
623+ let validateArtwork = validateArtworkData(caller, cidDisplay, cidExport, licenceCID, sha256Export, licenceHash, name, description, tags, royalties)
624+ if ((validateArtwork != ""))
625+ then throw("Something went wrong!")
241626 else {
242- let json = makeJSON(toBase64String(toBytes(name)), toBase64String(toBytes(thumb)), toString(timestamp))
243- if (if ((0 > royalties))
244- then true
245- else (royalties > 1000))
246- then throw("Royalties cannot be less than 0% or higher than 10%")
627+ let entryExist = getStringByKey(keyName(caller, txid))
628+ if ((entryExist == ""))
629+ then throw("Entry not found")
247630 else {
248- let txToCaller = if (isSponsored)
249- then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
250- else nil
251- ([IntegerEntry(keyUserDate(caller), timestamp), StringEntry(keyUserAddr(caller), ((id + "_") + toString(timestamp))), StringEntry(keyUserName(caller), name), StringEntry(keyUserDesc(caller), description), StringEntry(keyUserSocial(caller), social), StringEntry(keyUserThumb(caller), thumb), StringEntry(keyUserStatus(caller), userRegistered), IntegerEntry(keyUserRoyalties(caller), royalties), DeleteEntry(("ALLOWED_" + caller)), StringEntry(((userRegistered + "_") + caller), json)] ++ txToCaller)
631+ let flag = getStringByKey(keyFlag(caller, txid))
632+ if ((flag == "ILLEGAL"))
633+ then throw("Cannot update ILLEGAL artwork")
634+ else if (!(isArtMinted(caller, txid)))
635+ then {
636+ let txToCaller = if (isSponsored)
637+ then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
638+ else nil
639+ ([StringEntry(keyName(caller, txid), name), StringEntry(keyDesc(caller, txid), description), StringEntry(keyDisplayCid(caller, txid), cidDisplay), StringEntry(keyExportCid(caller, txid), cidExport), StringEntry(keyExportHash(caller, txid), sha256Export), StringEntry(keyLicenceCid(caller, txid), licenceCID), StringEntry(keyLicenceHash(caller, txid), licenceHash), StringEntry(keyTags(caller, txid), tags), StringEntry(keyType(caller, txid), type), StringEntry(keyCrawler(caller, txid), crawler), IntegerEntry(keyRoyalties(caller, txid), royalties)] ++ txToCaller)
640+ }
641+ else throw("Already minted")
252642 }
253643 }
254644 }
255645
256646
257647
258-@Callable(invoke)
259-func updateUser (name,description,thumb,social,royalties,pubKey) = if (!(dappRunning))
260- then throw(maintenanceMSG)
261- else {
262- let $t087728876 = getCaller(invoke, pubKey)
263- let caller = $t087728876._1
264- let isSponsored = $t087728876._2
265- let status = getStringByKey(keyUserStatus(caller))
266- if (!(validUserData(caller, name, description, thumb, true)))
267- then throw("Something went wrong")
268- else {
269- let date = getIntegerByKey(keyUserDate(caller))
270- let json = makeJSON(toBase64String(toBytes(name)), toBase64String(toBytes(thumb)), toString(date))
271- if (if ((0 > royalties))
272- then true
273- else (royalties > 1000))
274- then throw("Royalties cannot be less than 0% or higher than 10%")
275- else {
276- let txToCaller = if (isSponsored)
277- then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
278- else nil
279- ([StringEntry(keyUserName(caller), name), StringEntry(keyUserDesc(caller), description), StringEntry(keyUserSocial(caller), social), StringEntry(keyUserThumb(caller), thumb), IntegerEntry(keyUserRoyalties(caller), royalties), StringEntry(((status + "_") + caller), json)] ++ txToCaller)
280- }
281- }
282- }
283-
284-
285-
286-@Callable(invoke)
287-func setERC20User (erc20,pubKey) = if (!(dappRunning))
288- then throw(maintenanceMSG)
289- else {
290- let $t01006310166 = getCaller(invoke, pubKey)
291- let caller = $t01006310166._1
292- let isSponsored = $t01006310166._2
293- let status = getStringByKey(keyUserStatus(caller))
294- if (if ((status != userRegistered))
295- then (status != userVerified)
296- else false)
297- then throw("Not allowed to set ERC20 address")
298- else {
299- let firstTwo = take(erc20, 2)
300- if (if ((firstTwo != "0x"))
301- then true
302- else (size(erc20) != 42))
303- then throw("This is not an erc20 address")
304- else {
305- let txToCaller = if (isSponsored)
306- then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
307- else nil
308- ([StringEntry(keyUserERC20(caller), erc20)] ++ txToCaller)
309- }
310- }
311- }
312-
313-
314-
315-@Callable(invoke)
316-func changeUserStatus (address,status,note) = {
317- let caller = toString(invoke.caller)
318- let currentStatus = getStringByKey(keyUserStatus(address))
319- let statusToSet = validateNewStatus(status, address, currentStatus)
320- let name = toBase64String(toBytes(getStringByKey(keyUserName(address))))
321- let thumb = toBase64String(toBytes(getStringByKey(keyUserThumb(address))))
322- let date = getIntegerByKey(keyUserDate(address))
323- let json = makeJSON(name, thumb, toString(date))
648+@Callable(i)
649+func flagArtwork (artId,addr,flag,note) = {
650+ let $t02431724351 = idCallerDate(i)
651+ let id = $t02431724351._1
652+ let caller = $t02431724351._2
324653 if (containsElement([chris, toString(this)], caller))
325- then [StringEntry(keyUserStatus(address), statusToSet), DeleteEntry(((currentStatus + "_") + address)), StringEntry(((statusToSet + "_") + address), json), StringEntry(("user_note_" + address), note)]
326- else throw("Not allowed to change user status")
327- }
328-
329-
330-
331-@Callable(invoke)
332-func deleteUser (address) = {
333- let caller = toString(invoke.caller)
334- let currentStatus = getStringByKey(keyUserStatus(address))
335- if (containsElement([chris, toString(this)], caller))
336- then [DeleteEntry(keyUserDate(address)), DeleteEntry(keyUserAddr(address)), DeleteEntry(keyUserName(address)), DeleteEntry(keyUserDesc(address)), DeleteEntry(keyUserSocial(address)), DeleteEntry(keyUserThumb(address)), DeleteEntry(("user_note_" + address)), DeleteEntry(((currentStatus + "_") + address)), DeleteEntry(keyUserRoyalties(address)), StringEntry(keyUserStatus(address), userRemoved)]
337- else throw("Not allowed")
654+ then if (containsElement(["CONSENT", "", "CHANGE_REQUIRED", "FLAGGED", "ILLEGAL"], flag))
655+ then [StringEntry(keyFlag(addr, artId), flag), StringEntry(keyNote(addr, artId), note)]
656+ else throw(("Unknow status " + flag))
657+ else throw("You are not allowed")
338658 }
339659
340660
341661
342662 @Callable(i)
343-func setAgent (artistAddr,agentAddr,primaryShare,secondaryShare) = if (!(dappRunning))
344- then throw(maintenanceMSG)
345- else {
346- let caller = toString(i.caller)
347- if (containsElement([chris, toString(this)], caller))
348- then if (if ((size(artistAddr) != 35))
349- then true
350- else (size(agentAddr) != 35))
351- then throw("Wrong address")
352- else [StringEntry(keyArtistAgentAddr(artistAddr), agentAddr), StringEntry(keyAgentArtistAddr(agentAddr, artistAddr), artistAddr), IntegerEntry(keyPrimaryShare(artistAddr), primaryShare), IntegerEntry(keySecondaryShare(artistAddr), secondaryShare)]
353- else throw("You are not allowed")
354- }
663+func deleteArtwork (artId,addr) = {
664+ let $t02478724821 = idCallerDate(i)
665+ let id = $t02478724821._1
666+ let caller = $t02478724821._2
667+ let addrToUse = if (containsElement([chris, toString(this)], caller))
668+ then addr
669+ else caller
670+ let entryExist = valueOrErrorMessage(getStringByKey(keyName(addrToUse, artId)), "No art matching for this address")
671+ if ((entryExist == ""))
672+ then throw("No art matching for this address")
673+ else {
674+ let sha256Hash = getStringByKey(keyHashByTxidAddr(addrToUse, artId))
675+ if ((sha256Hash == ""))
676+ then throw("No art hash matching for this address")
677+ else {
678+ let signID = getStringByKey(keySignID(addrToUse, artId))
679+ if ((signID == ""))
680+ then throw("No SIGN ID matching")
681+ else {
682+ let dataToDelete = [DeleteEntry(keyDate(addrToUse, artId)), DeleteEntry(keyName(addrToUse, artId)), DeleteEntry(keyDesc(addrToUse, artId)), DeleteEntry(keyDisplayCid(addrToUse, artId)), DeleteEntry(keyExportCid(addrToUse, artId)), DeleteEntry(keyExportHash(addrToUse, artId)), DeleteEntry(keyLicenceHash(addrToUse, artId)), DeleteEntry(keyLicenceCid(addrToUse, artId)), DeleteEntry(keyType(addrToUse, artId)), DeleteEntry(keyTags(addrToUse, artId)), DeleteEntry(keyMaxMint(addrToUse, artId)), DeleteEntry(keySignID(addrToUse, artId)), DeleteEntry(keyIssued(addrToUse, artId)), DeleteEntry(keyOnSale(addrToUse, artId)), DeleteEntry(keyFlag(addrToUse, artId)), DeleteEntry(keyPrice(addrToUse, artId)), DeleteEntry(keyAssetIdAccepted(addrToUse, artId)), DeleteEntry(keyOwnerByHash(sha256Hash)), DeleteEntry(keyidBySignid(addrToUse, signID)), DeleteEntry(keyTxidByHashOwner(sha256Hash, addrToUse)), DeleteEntry(keyEndSale(addrToUse, artId)), DeleteEntry(keyNote(addrToUse, artId)), DeleteEntry(keyCrawler(addrToUse, artId)), DeleteEntry(keyRoyalties(addrToUse, artId))]
683+ if (!(isArtMinted(addrToUse, artId)))
684+ then if (!(dappRunning))
685+ then throw(maintenanceMSG)
686+ else dataToDelete
687+ else if (containsElement([chris, toString(this)], caller))
688+ then dataToDelete
689+ else throw("Art already minted, you cannot delete it")
690+ }
691+ }
692+ }
693+ }
355694
356695
357696
358697 @Callable(i)
359-func unsetAgent (artistAddr,agentAddr) = if (!(dappRunning))
360- then throw(maintenanceMSG)
361- else {
362- let caller = toString(i.caller)
363- if (containsElement([chris, toString(this)], caller))
364- then if (if ((size(artistAddr) != 35))
365- then true
366- else (size(agentAddr) != 35))
367- then throw("Wrong address")
368- else [DeleteEntry(keyArtistAgentAddr(artistAddr)), DeleteEntry(keyAgentArtistAddr(agentAddr, artistAddr)), DeleteEntry(keyPrimaryShare(artistAddr)), DeleteEntry(keySecondaryShare(artistAddr))]
369- else throw("You are not allowed")
370- }
698+func sellArtwork (artId,price,maxMint,assetId,blockEnd,pubKey) = {
699+ let $t02765727727 = idCallerDateSponsored(i, pubKey)
700+ let id = $t02765727727._1
701+ let caller = $t02765727727._2
702+ let date = $t02765727727._3
703+ let isSponsored = $t02765727727._4
704+ let artworkName = getStringByKey(keyName(caller, artId))
705+ if ((artworkName == ""))
706+ then throw("This art doesn't match your account")
707+ else {
708+ let flag = getStringByKey(keyFlag(caller, artId))
709+ if (containsElement(["CHANGE_REQUIRED", "FLAGGED", "ILLEGAL"], flag))
710+ then throw("Flagged artwork")
711+ else {
712+ let bidNbr = getIntegerByKey(("current_bidamount_" + artId))
713+ if ((0 > blockEnd))
714+ then throw("Negative end")
715+ else if (if ((blockEnd > 0))
716+ then if ((maxMint != 1))
717+ then true
718+ else (price != 0)
719+ else false)
720+ then throw("Timed offer only allowed for unique edition and offer only")
721+ else {
722+ let baseHeight = if ((blockEnd == 0))
723+ then 0
724+ else height
725+ if (!(acceptedAssetIds(assetId)))
726+ then throw("Something went wrong!")
727+ else if (!(validateMinSell(assetId, price)))
728+ then throw("Something went wrong!")
729+ else {
730+ let checkUser = validateUser(caller)
731+ if ((checkUser != ""))
732+ then throw(checkUser)
733+ else {
734+ let amountSold = getIntegerByKey(keyIssued(caller, artId))
735+ let maxCanSell = getIntegerByKey(keyMaxMint(caller, artId))
736+ if ((maxMint > 100))
737+ then throw("100 editions max per artwork")
738+ else if (if ((amountSold != 0))
739+ then (amountSold == maxCanSell)
740+ else false)
741+ then throw("Max edition reached.")
742+ else if (if ((amountSold > 0))
743+ then (maxCanSell != maxMint)
744+ else false)
745+ then throw("Cannot change maximum issuable anymore")
746+ else if (if ((bidNbr > 0))
747+ then (maxCanSell != maxMint)
748+ else false)
749+ then throw("Cannot change maximum issuable with active orders")
750+ else {
751+ let sellStatus = if (if ((price > 0))
752+ then (maxMint > 0)
753+ else false)
754+ then true
755+ else false
756+ let txToCaller = if (isSponsored)
757+ then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
758+ else nil
759+ ([BooleanEntry(keyOnSale(caller, artId), sellStatus), IntegerEntry(keyPrice(caller, artId), price), IntegerEntry(keyMaxMint(caller, artId), maxMint), StringEntry(keyAssetIdAccepted(caller, artId), assetId), IntegerEntry(keyEndSale(caller, artId), (baseHeight + blockEnd))] ++ txToCaller)
760+ }
761+ }
762+ }
763+ }
764+ }
765+ }
766+ }
371767
372768
373769
374770 @Callable(i)
375-func deleteEntry (entry) = {
376- let caller = toString(i.caller)
377- if ((caller == chris))
378- then [DeleteEntry(entry)]
379- else throw("no")
771+func buyArtwork (artId,issuer) = buyMint(i, artId, issuer, "", "")
772+
773+
774+
775+@Callable(i)
776+func setBid (artId,issuer) = {
777+ let $t03010530145 = idCallerDate(i)
778+ let id = $t03010530145._1
779+ let caller = $t03010530145._2
780+ let date = $t03010530145._3
781+ let $t03015030186 = isPayment(i)
782+ let payment = $t03015030186._1
783+ let amount = $t03015030186._2
784+ let assetId = if (!(isDefined(payment.assetId)))
785+ then "WAVES"
786+ else toBase58String(value(payment.assetId))
787+ let blockEnd = getIntegerByKey(keyEndSale(issuer, artId))
788+ if (if ((blockEnd != 0))
789+ then (height >= blockEnd)
790+ else false)
791+ then throw("Sale ended.")
792+ else {
793+ let bidNbr = getIntegerByKey(("current_bidamount_" + artId))
794+ if (!(acceptedAssetIds(assetId)))
795+ then throw("asset not accepted")
796+ else if (!(validateMinSell(assetId, amount)))
797+ then throw("Wrong min sell")
798+ else {
799+ let amountSold = getIntegerByKey(keyIssued(issuer, artId))
800+ let maxCanSell = getIntegerByKey(keyMaxMint(issuer, artId))
801+ if ((0 >= maxCanSell))
802+ then throw("No max edition set for this artwork")
803+ else if ((amountSold >= maxCanSell))
804+ then throw("Sold out, you cannot bid")
805+ else [StringEntry((((((((("bid_" + artId) + "_") + issuer) + "_") + caller) + "_") + id) + "_OPEN"), ((((assetId + "_") + toString(amount)) + "_") + toString(date))), IntegerEntry(("current_bidamount_" + artId), (bidNbr + 1))]
806+ }
807+ }
808+ }
809+
810+
811+
812+@Callable(i)
813+func acceptBid (artId,issuer,bidId,bidOwner) = {
814+ let $t03134431384 = idCallerDate(i)
815+ let id = $t03134431384._1
816+ let caller = $t03134431384._2
817+ let date = $t03134431384._3
818+ if ((caller != issuer))
819+ then throw("You cannot do this action")
820+ else buyMint(i, artId, issuer, bidId, bidOwner)
821+ }
822+
823+
824+
825+@Callable(i)
826+func cancelBid (artId,issuer,bidId,bidOwner) = {
827+ let $t03161031671 = idCallerDate(i)
828+ let id = $t03161031671._1
829+ let caller = $t03161031671._2
830+ let date = $t03161031671._3
831+ if (if ((caller != bidOwner))
832+ then (caller != issuer)
833+ else false)
834+ then throw("You cannot do this action")
835+ else {
836+ let returnMoneyTo = if ((caller == issuer))
837+ then bidOwner
838+ else caller
839+ let bidNbr = getIntegerByKey(("current_bidamount_" + artId))
840+ let bidDataKey = ((((((("bid_" + artId) + "_") + issuer) + "_") + bidOwner) + "_") + bidId)
841+ let bidData = getStringByKey((bidDataKey + "_OPEN"))
842+ if ((bidData == ""))
843+ then throw("Bid not found")
844+ else {
845+ let bidDataArr = split(bidData, "_")
846+ let assetId = getBidAssetId(bidDataArr[0])
847+ let bidStatus = "CANCELED"
848+[DeleteEntry((bidDataKey + "_OPEN")), StringEntry(((bidDataKey + "_") + bidStatus), ((bidData + "_") + toString(date))), IntegerEntry(("current_bidamount_" + artId), (bidNbr - 1)), ScriptTransfer(Address(fromBase58String(returnMoneyTo)), parseIntValue(bidDataArr[1]), assetId)]
849+ }
850+ }
380851 }
381852
382853
383854 @Verifier(tx)
384855 func verifier () = match tx {
385856 case inv: InvokeScriptTransaction =>
386- if (if (if ((inv.function == "registerUser"))
857+ if (if (if ((inv.function == "addArtwork"))
387858 then (inv.dApp == this)
388859 else false)
389860 then (inv.fee == 500000)
390861 else false)
391- then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[5])))
392- else if (if (if ((inv.function == "updateUser"))
862+ then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[13])))
863+ else if (if (if ((inv.function == "updateArtwork"))
393864 then (inv.dApp == this)
394865 else false)
395866 then (inv.fee == 500000)
396867 else false)
397- then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[5])))
398- else if (if (if ((inv.function == "setERC20User"))
868+ then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[12])))
869+ else if (if (if ((inv.function == "sellArtwork"))
399870 then (inv.dApp == this)
400871 else false)
401872 then (inv.fee == 500000)
402873 else false)
403- then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[2])))
874+ then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[5])))
404875 else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
405876 case _ =>
406877 sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let VERSION = "1.5"
4+let VERSION = "1.1.10"
55
66 func getStringByKey (key) = valueOrElse(getString(this, key), "")
7+
8+
9+let unitTest = false
10+
11+let oracleFee = value(addressFromString(getStringByKey("conf_oracle_fee")))
12+
13+let signDapp = value(addressFromString(getStringByKey("conf_signweb_dapp")))
14+
15+let feeReceiver = getStringByKey("conf_fee_receiver")
16+
17+let userDapp = if (unitTest)
18+ then value(addressFromString("3Mt4RGMEyjSWYAocTPqd55wdHQQB3PU2UCm"))
19+ else value(addressFromString(getStringByKey("conf_users_dapp")))
20+
21+let whitelistDapp = value(addressFromString(getStringByKey("conf_whitelist_dapp")))
22+
23+let signAssetId = fromBase58String(getStringByKey("conf_accepted_asset_SIGN"))
24+
25+let usdnAssetId = fromBase58String(getStringByKey("conf_accepted_asset_USDN"))
26+
27+let usdtAssetId = fromBase58String(getStringByKey("conf_accepted_asset_USDT"))
28+
29+let wavesAssetId = base58''
30+
31+let chris = getStringByKey("conf_admin_1")
32+
33+func getIntegerByKeyFromOracle (key) = valueOrErrorMessage(getInteger(oracleFee, key), "Integer undefine or 0 in oracle")
34+
35+
36+func getIntegerByKey (key) = valueOrElse(getInteger(this, key), 0)
37+
38+
39+func checkWhitelist (key) = valueOrElse(getInteger(whitelistDapp, key), 0)
740
841
942 func getBooleanByKey (key) = valueOrElse(getBoolean(this, key), false)
1043
1144
12-func getIntegerByKey (key) = valueOrElse(getInteger(this, key), 0)
45+let signCut = 7
1346
47+let usdnWaveCut = 10
1448
15-let chris = getStringByKey("conf_admin_1")
49+let defaultLicence = getStringByKey("conf_default_licence")
1650
17-let dappRunningKey = "conf_dapp_is_running"
51+let defaultHashLicence = getStringByKey("conf_default_licence_hash")
1852
19-let maintenanceMSGKey = "conf_maintenance_msg"
53+let dappRunning = valueOrElse(getBoolean(userDapp, "conf_dapp_is_running"), true)
2054
21-let whitelistedonlyKey = "conf_whitelisted_only"
22-
23-let dappRunning = valueOrElse(getBoolean(this, dappRunningKey), true)
24-
25-let maintenanceMSG = valueOrElse(getString(this, maintenanceMSGKey), "")
26-
27-let whitelistedonly = valueOrElse(getBoolean(this, whitelistedonlyKey), true)
28-
29-let whitelistDapp = value(addressFromString(getStringByKey("conf_whitelist_dapp")))
30-
31-let userAllowed = "ALLOWED"
32-
33-let userRegistered = "REGISTERED"
34-
35-let userVerified = "VERIFIED"
55+let maintenanceMSG = valueOrElse(getString(userDapp, "conf_maintenance_msg"), "")
3656
3757 let userSuspended = "SUSPENDED"
3858
3959 let userRemoved = "REMOVED"
4060
41-let userChangeRequired = "CHANGE_REQUIRED"
42-
4361 let userUnregistered = "UNREGISTERED"
4462
45-let userReset = "RESET"
63+let userAllowed = "ALLOWED"
4664
47-func keyUserAddr (caller) = ("user_" + caller)
65+let currentCertificationPrice = getIntegerByKeyFromOracle(("certification_fee_" + toBase58String(signAssetId)))
66+
67+func getArtworkRoyalties (key) = valueOrElse(getInteger(this, key), 1000)
4868
4969
50-func keyUserName (caller) = ("user_name_" + caller)
51-
52-
53-func keyUserDesc (caller) = ("user_desc_" + caller)
54-
55-
56-func keyUserSocial (caller) = ("user_social_" + caller)
57-
58-
59-func keyUserThumb (caller) = ("user_thumb_" + caller)
60-
61-
62-func keyUserStatus (caller) = ("user_status_" + caller)
63-
64-
65-func keyUserRoyalties (caller) = ("user_royalties_" + caller)
66-
67-
68-func keyUserDate (caller) = ("user_date_" + caller)
69-
70-
71-func keyUserERC20 (caller) = ("user_ERC20_" + caller)
72-
73-
74-func keyArtistAgentAddr (artistAddr) = ("artist_agent_" + artistAddr)
75-
76-
77-func keyAgentArtistAddr (agentAddr,artistAddr) = ((("agent_" + agentAddr) + "_") + artistAddr)
78-
79-
80-func keyPrimaryShare (artistAddr) = ("artist_agent_primary_" + artistAddr)
81-
82-
83-func keySecondaryShare (artistAddr) = ("artist_agent_secondary_" + artistAddr)
84-
85-
86-func checkWhitelist (key) = valueOrElse(getInteger(whitelistDapp, key), 0)
70+func checkSignCertificate (signID,Owner,sha256Hash) = match getString(signDapp, ((("data_fc_" + signID) + "_") + Owner)) {
71+ case a: String =>
72+ if (contains(a, sha256Hash))
73+ then true
74+ else false
75+ case _ =>
76+ false
77+}
8778
8879
8980 func validateCID (cid) = if (contains(cid, "/"))
9081 then if (if ((76 > size(cid)))
9182 then (size(split(cid, "/")[0]) == 59)
9283 else false)
9384 then (16 > size(split(cid, "/")[1]))
9485 else false
9586 else false
9687
9788
98-func validUserData (caller,name,description,thumb,isAnUpdate) = {
99- let validCID = if ((size(thumb) != 0))
100- then validateCID(thumb)
89+func validateHash (hash) = (size(hash) == 64)
90+
91+
92+func keyUserStatus (caller) = ("user_status_" + caller)
93+
94+
95+func keyDate (caller,artId) = ((("art_date_" + artId) + "_") + caller)
96+
97+
98+func keyName (caller,artId) = ((("art_name_" + artId) + "_") + caller)
99+
100+
101+func keyDesc (caller,artId) = ((("art_desc_" + artId) + "_") + caller)
102+
103+
104+func keyDisplayCid (caller,artId) = ((("art_display_cid_" + artId) + "_") + caller)
105+
106+
107+func keyExportHash (caller,artId) = ((("art_export_hash_" + artId) + "_") + caller)
108+
109+
110+func keyExportCid (caller,artId) = ((("art_export_cid_" + artId) + "_") + caller)
111+
112+
113+func keyMaxMint (caller,artId) = ((("art_maxmint_" + artId) + "_") + caller)
114+
115+
116+func keySignID (caller,artId) = ((("art_signid_" + artId) + "_") + caller)
117+
118+
119+func keyIssued (caller,artId) = ((("art_issued_" + artId) + "_") + caller)
120+
121+
122+func keyOnSale (caller,artId) = ((("art_onsale_" + artId) + "_") + caller)
123+
124+
125+func keyLicenceHash (caller,artId) = ((("art_licence_hash_" + artId) + "_") + caller)
126+
127+
128+func keyLicenceCid (caller,artId) = ((("art_licence_cid_" + artId) + "_") + caller)
129+
130+
131+func keyTags (caller,artId) = ((("art_tags_" + artId) + "_") + caller)
132+
133+
134+func keyType (caller,artId) = ((("art_type_" + artId) + "_") + caller)
135+
136+
137+func keyNote (caller,artId) = ((("art_note_" + artId) + "_") + caller)
138+
139+
140+func keyCrawler (caller,artId) = ((("art_crawler_cid_" + artId) + "_") + caller)
141+
142+
143+func keyRoyalties (caller,artId) = ((("art_royalties_" + artId) + "_") + caller)
144+
145+
146+func keyPrice (caller,artId) = ((("art_price_" + artId) + "_") + caller)
147+
148+
149+func keyEndSale (caller,artId) = ((("art_endsale_" + artId) + "_") + caller)
150+
151+
152+func keyAssetIdAccepted (caller,artId) = ((("art_assetAccepted_" + artId) + "_") + caller)
153+
154+
155+func keyFlag (caller,artId) = ((("art_flag_" + artId) + "_") + caller)
156+
157+
158+func keyArtistAgentAddr (artistAddr) = ("artist_agent_" + artistAddr)
159+
160+
161+func keyPrimaryShare (artistAddr) = ("artist_agent_primary_" + artistAddr)
162+
163+
164+func keyHashByTxidAddr (caller,txid) = ((("get_hashbytxidaddr_" + txid) + "_") + caller)
165+
166+
167+func keyOwnerByHash (sha256Hash) = ("get_owner_by_hash_" + sha256Hash)
168+
169+
170+func keyidBySignid (caller,signId) = ((("get_artidbysignid_" + signId) + "_") + caller)
171+
172+
173+func keyTxidByHashOwner (sha256Hash,caller) = ("get_txid_by_hash_owner_" + toBase58String(sha256_16Kb(toBytes((sha256Hash + caller)))))
174+
175+
176+func validateAllCID (cidDisplay,cidExport,cidLicence) = if (!(validateCID(cidDisplay)))
177+ then throw("Wrong Display CID")
178+ else if (!(validateCID(cidExport)))
179+ then throw("Wrong Export CID")
180+ else if (if ((cidLicence != ""))
181+ then !(validateCID(cidLicence))
182+ else false)
183+ then throw("Wrong Licence CID")
184+ else true
185+
186+
187+func validateAllHash (sha256Export,sha256Licence) = if (!(validateHash(sha256Export)))
188+ then throw("Export Hash 64 char. max")
189+ else if (!(validateHash(sha256Licence)))
190+ then throw("Licence Hash 64 char. max")
101191 else true
102- if (!(validCID))
103- then throw("CID don't match requirement!")
104- else if (if ((name == ""))
105- then true
106- else (description == ""))
107- then throw("Name and description cannot be empty")
108- else if ((size(description) > 600))
109- then throw("600 Char. max description")
110- else if ((size(name) > 45))
111- then throw("45 Char. max name")
112- else {
113- let status = getStringByKey(keyUserStatus(caller))
114- if (if ((status == userSuspended))
115- then true
116- else (status == userRemoved))
117- then throw("Account suspended/ removed.")
118- else if (if (!(isAnUpdate))
119- then (status == userRegistered)
120- else false)
121- then throw("Already registered")
122- else if (if (if (!(isAnUpdate))
123- then (status == "")
124- else false)
125- then whitelistedonly
126- else false)
127- then throw("Can't register, get approved first.")
128- else if (if (if (isAnUpdate)
129- then (status == "")
130- else false)
131- then true
132- else if (isAnUpdate)
133- then (status == userAllowed)
134- else false)
135- then throw("Register first")
136- else true
137- }
192+
193+
194+func validateString (str,max) = if ((size(str) == 0))
195+ then throw("Field cannot be is empty")
196+ else if ((size(str) > max))
197+ then throw((str + " is too long"))
198+ else true
199+
200+
201+func validateUser (caller) = {
202+ let userStatus = valueOrElse(getString(userDapp, keyUserStatus(caller)), userUnregistered)
203+ if (if ((userStatus == userUnregistered))
204+ then true
205+ else (userStatus == userAllowed))
206+ then "Register this account first with \"Account\" tab"
207+ else if ((userStatus == userSuspended))
208+ then "Account suspended"
209+ else if ((userStatus == userRemoved))
210+ then "Account removed"
211+ else ""
138212 }
139213
140214
141-func validateNewStatus (status,address,currentStatus) = {
142- let allStatus = [userVerified, userRegistered, userSuspended, userRemoved, userAllowed, userChangeRequired]
143- let statusToSet = if (containsElement(allStatus, status))
144- then status
145- else if (if ((status == userReset))
146- then (currentStatus == userAllowed)
147- else false)
148- then ""
149- else throw("Unknown status")
150- let userIsRegistered = getIntegerByKey(keyUserDate(address))
151- if (if ((userIsRegistered == 0))
152- then (statusToSet != userAllowed)
153- else false)
154- then throw("You cant set this status, user is not registered.")
155- else if (if ((currentStatus == userAllowed))
156- then (statusToSet == userAllowed)
157- else false)
158- then throw("User already allowed")
159- else if (if ((currentStatus == userRegistered))
160- then (statusToSet == userAllowed)
161- else false)
162- then throw("User already allowed & registered")
163- else if (if ((currentStatus == userVerified))
164- then (statusToSet == userAllowed)
165- else false)
166- then throw("User already allowed & verified")
167- else statusToSet
215+func setLIcence (cidLicence,sha256Licence) = {
216+ let cid = if ((size(cidLicence) == 0))
217+ then defaultLicence
218+ else cidLicence
219+ let hash = if ((size(sha256Licence) == 0))
220+ then defaultHashLicence
221+ else sha256Licence
222+ $Tuple2(cid, hash)
168223 }
169224
170225
171-func makeJSON (name,thumb,date) = (((((("{\"user_name\": \"" + name) + "\", \"user_thumb\":\"") + thumb) + "\",\"user_date\":\"") + date) + "\"}")
226+func validateArtworkData (caller,cidDisplay,cidExport,licenceCID,sha256Export,licenceHash,name,description,tags,royalties) = {
227+ let checkUser = validateUser(caller)
228+ if ((checkUser != ""))
229+ then throw(checkUser)
230+ else if ((size(cidDisplay) == 0))
231+ then throw("Display CID cannot be empty")
232+ else if (!(validateAllCID(cidDisplay, cidExport, licenceCID)))
233+ then throw("Problem with CID")
234+ else if (!(validateAllHash(sha256Export, licenceHash)))
235+ then throw("Problem with Hashes")
236+ else if (!(validateString(name, 100)))
237+ then throw("100 Char. max name")
238+ else if (!(validateString(description, 1000)))
239+ then throw("1000 Char. max description")
240+ else if (if ((0 > royalties))
241+ then true
242+ else (royalties > 1000))
243+ then throw("Royalties cannot be less than 0% or higher than 10%")
244+ else if ((size(split(tags, ",")) > 5))
245+ then throw("5 tags max.")
246+ else ""
247+ }
248+
249+
250+func isPayment (i) = if ((size(i.payments) == 0))
251+ then throw("No payment attached")
252+ else {
253+ let payment = value(i.payments[0])
254+ let amount = value(payment.amount)
255+ $Tuple2(payment, amount)
256+ }
257+
258+
259+func validatePayment (i) = {
260+ let $t089078943 = isPayment(i)
261+ let payment = $t089078943._1
262+ let amount = $t089078943._2
263+ let assetId = if (if (isDefined(payment.assetId))
264+ then (payment.assetId == signAssetId)
265+ else false)
266+ then payment.assetId
267+ else throw("Only SIGN token accepted as transaction fee")
268+ if ((amount != currentCertificationPrice))
269+ then throw(("Payment amount should be " + toString(currentCertificationPrice)))
270+ else $Tuple2(amount, assetId)
271+ }
272+
273+
274+func isArtMinted (addrToUse,artId) = match getInteger(this, keyIssued(addrToUse, artId)) {
275+ case b: Int =>
276+ if ((b != 0))
277+ then true
278+ else false
279+ case _ =>
280+ false
281+}
282+
283+
284+func validatePriceAssetId (i,priceAssetId,artworkPrice) = {
285+ let $t095319567 = isPayment(i)
286+ let payment = $t095319567._1
287+ let amount = $t095319567._2
288+ let assetId = if (!(isDefined(payment.assetId)))
289+ then unit
290+ else if (if ((size(priceAssetId) > 0))
291+ then (toBase58String(value(payment.assetId)) == priceAssetId)
292+ else false)
293+ then payment.assetId
294+ else throw("Wrong asset id")
295+ if (if ((assetId == unit))
296+ then (priceAssetId != "")
297+ else false)
298+ then throw("Wrong asset id")
299+ else if ((artworkPrice != amount))
300+ then throw("Payment don't match")
301+ else $Tuple2(amount, assetId)
302+ }
303+
304+
305+func acceptedAssetIds (assetId) = if (if (if (if (if ((assetId != toBase58String(signAssetId)))
306+ then (assetId != toBase58String(wavesAssetId))
307+ else false)
308+ then (assetId != "WAVES")
309+ else false)
310+ then (assetId != toBase58String(usdnAssetId))
311+ else false)
312+ then (assetId != toBase58String(usdtAssetId))
313+ else false)
314+ then throw("Only SIGN, USDN,USDT or WAVES accepted")
315+ else true
316+
317+
318+func validateMinSell (assetId,price) = {
319+ let minSellWaves = if (unitTest)
320+ then 10
321+ else getIntegerByKeyFromOracle("waves_min_sell")
322+ let minSellUsdn = 1000000
323+ let minSellSign = if (unitTest)
324+ then 1
325+ else (currentCertificationPrice * 2)
326+ if (if (if (if (if (if ((assetId == toBase58String(usdnAssetId)))
327+ then (minSellUsdn > price)
328+ else false)
329+ then (price != 0)
330+ else false)
331+ then true
332+ else if (if ((assetId == toBase58String(usdtAssetId)))
333+ then (minSellUsdn > price)
334+ else false)
335+ then (price != 0)
336+ else false)
337+ then true
338+ else if (if ((assetId == toBase58String(signAssetId)))
339+ then (minSellSign > price)
340+ else false)
341+ then (price != 0)
342+ else false)
343+ then true
344+ else if (if (if ((assetId == toBase58String(wavesAssetId)))
345+ then true
346+ else (assetId == "WAVES"))
347+ then (minSellWaves > price)
348+ else false)
349+ then (price != 0)
350+ else false)
351+ then throw("Wrong minimum sell price")
352+ else true
353+ }
354+
355+
356+func getBidAssetId (assetId) = if ((assetId == "WAVES"))
357+ then unit
358+ else fromBase58String(assetId)
359+
360+
361+func getPriceAssetIdFromBid (bidDataKey) = {
362+ let bidData = getStringByKey((bidDataKey + "_OPEN"))
363+ if ((bidData == ""))
364+ then throw("Bid not found")
365+ else {
366+ let bidDataArr = split(bidData, "_")
367+ let bidAmount = parseIntValue(bidDataArr[1])
368+ let bidAssetId = getBidAssetId(bidDataArr[0])
369+ if ((0 >= bidAmount))
370+ then throw("Wrong amount")
371+ else $Tuple2(bidAmount, bidAssetId)
372+ }
373+ }
374+
375+
376+func idCallerDateSponsored (i,pubKey) = if (!(dappRunning))
377+ then throw(maintenanceMSG)
378+ else {
379+ let isSponsored = valueOrElse(checkWhitelist((toString(addressFromPublicKey(fromBase58String(pubKey))) + "_free_txs")), 0)
380+ let caller = if (if (if ((toBase58String(i.caller.bytes) == toString(this)))
381+ then (size(i.payments) == 0)
382+ else false)
383+ then (isSponsored > 0)
384+ else false)
385+ then toString(addressFromPublicKey(fromBase58String(pubKey)))
386+ else toBase58String(i.caller.bytes)
387+ let get_sponsored_waves = if ((pubKey != ""))
388+ then invoke(whitelistDapp, "useFreeTx", [toString(addressFromPublicKey(fromBase58String(pubKey)))], nil)
389+ else unit
390+ if ((get_sponsored_waves == get_sponsored_waves))
391+ then $Tuple4(toBase58String(i.transactionId), caller, lastBlock.timestamp, (isSponsored > 0))
392+ else throw("Strict value is not equal to itself.")
393+ }
394+
395+
396+func idCallerDate (i) = if (!(dappRunning))
397+ then throw(maintenanceMSG)
398+ else $Tuple3(toBase58String(i.transactionId), toBase58String(i.caller.bytes), lastBlock.timestamp)
399+
400+
401+func buyMint (i,artId,issuer,bidId,bidOwner) = {
402+ let $t01291912978 = idCallerDate(i)
403+ let id = $t01291912978._1
404+ let caller = $t01291912978._2
405+ let date = $t01291912978._3
406+ let isBid = if (if (if ((caller == issuer))
407+ then (bidOwner != "")
408+ else false)
409+ then (bidId != "")
410+ else false)
411+ then true
412+ else false
413+ let blockEnd = getIntegerByKey(keyEndSale(caller, artId))
414+ if (if (if ((blockEnd != 0))
415+ then (height >= blockEnd)
416+ else false)
417+ then !(isBid)
418+ else false)
419+ then throw("Sale ended.")
420+ else {
421+ let callerIsIssuer = (caller == issuer)
422+ let totalNFT = getIntegerByKey("total_nft_issued")
423+ let signID = getStringByKey(keySignID(issuer, artId))
424+ let artworkName = getStringByKey(keyName(issuer, artId))
425+ if ((artworkName == ""))
426+ then throw("Art doesn't exist")
427+ else {
428+ let isOnSale = getBooleanByKey(keyOnSale(issuer, artId))
429+ let amountSold = getIntegerByKey(keyIssued(issuer, artId))
430+ let artworkPrice = if (callerIsIssuer)
431+ then (currentCertificationPrice * 2)
432+ else getIntegerByKey(keyPrice(issuer, artId))
433+ let priceAssetId = if (callerIsIssuer)
434+ then toBase58String(signAssetId)
435+ else getStringByKey(keyAssetIdAccepted(issuer, artId))
436+ let maxCanSell = getIntegerByKey(keyMaxMint(issuer, artId))
437+ if (if (if (!(isBid))
438+ then !(callerIsIssuer)
439+ else false)
440+ then if (if ((0 >= artworkPrice))
441+ then true
442+ else !(isOnSale))
443+ then true
444+ else (0 >= maxCanSell)
445+ else false)
446+ then throw("Art not for sale")
447+ else if (if (if (!(isBid))
448+ then callerIsIssuer
449+ else false)
450+ then (0 >= maxCanSell)
451+ else false)
452+ then throw("Max issuable not set")
453+ else {
454+ let checkUser = validateUser(issuer)
455+ if (if (isBid)
456+ then (checkUser != "")
457+ else false)
458+ then throw(checkUser)
459+ else {
460+ let bidDataKey = ((((((("bid_" + artId) + "_") + issuer) + "_") + bidOwner) + "_") + bidId)
461+ let $t01468114848 = if (isBid)
462+ then getPriceAssetIdFromBid(bidDataKey)
463+ else validatePriceAssetId(i, priceAssetId, artworkPrice)
464+ let amount = $t01468114848._1
465+ let assetId = $t01468114848._2
466+ let agent = valueOrElse(getString(userDapp, keyArtistAgentAddr(issuer)), feeReceiver)
467+ let agentShare = valueOrElse(getInteger(userDapp, keyPrimaryShare(issuer)), 0)
468+ let isWhitelisted = checkWhitelist(issuer)
469+ let cut = if ((isWhitelisted > height))
470+ then 0
471+ else if ((assetId == signAssetId))
472+ then signCut
473+ else usdnWaveCut
474+ let amountForSign = fraction(amount, cut, 100)
475+ let amountForAgent = if (if (if ((agent != feeReceiver))
476+ then (agentShare > 0)
477+ else false)
478+ then (height > isWhitelisted)
479+ else false)
480+ then fraction(amount, agentShare, 100)
481+ else 0
482+ let amountForCreator = (amount - amountForSign)
483+ if ((amountSold == maxCanSell))
484+ then throw("Art sold out")
485+ else {
486+ let newAmountSold = (amountSold + 1)
487+ let issueMeta = ((((((((((("Creator: " + issuer) + ",
488+ ArtID: ") + artId) + ",
489+ SignID: ") + signID) + ",
490+ Artwork name: ") + artworkName) + ",
491+ Issue: ") + toString(newAmountSold)) + "/") + toString(maxCanSell))
492+ let issueNFT = Issue(("SA_" + toString((totalNFT + 1))), issueMeta, 1, 0, false)
493+ let idNFT = calculateAssetId(issueNFT)
494+ let sellStatus = if (if ((newAmountSold == maxCanSell))
495+ then true
496+ else !(isOnSale))
497+ then false
498+ else true
499+ let receiveNFT = if (if (if ((caller == issuer))
500+ then (bidOwner != "")
501+ else false)
502+ then (bidId != "")
503+ else false)
504+ then addressFromStringValue(bidOwner)
505+ else i.caller
506+ let assetIdBid = if (!(isDefined(assetId)))
507+ then "WAVES"
508+ else toBase58String(value(assetId))
509+ let bidData = getStringByKey((bidDataKey + "_OPEN"))
510+ let bidDelOld = DeleteEntry((bidDataKey + "_OPEN"))
511+ let bidUpdate = StringEntry((bidDataKey + "_CLOSED"), ((bidData + "_") + toString(date)))
512+ let soldKey = ((((((("art_sold_" + toString(newAmountSold)) + "_of_") + toString(maxCanSell)) + "_") + artId) + "_") + issuer)
513+ let soldValue = if (!(isBid))
514+ then ((((((((((caller + "_") + toString(date)) + "_") + id) + "_") + toString(artworkPrice)) + "_") + priceAssetId) + "_") + toBase58String(idNFT))
515+ else ((((((((((toString(receiveNFT) + "_") + toString(date)) + "_") + id) + "_") + toString(amount)) + "_") + assetIdBid) + "_") + toBase58String(idNFT))
516+ let soldData = StringEntry(soldKey, soldValue)
517+ let commissions = if ((amountForAgent != 0))
518+ then [ScriptTransfer(Address(fromBase58String(feeReceiver)), (amountForSign - amountForAgent), assetId), ScriptTransfer(Address(fromBase58String(agent)), amountForAgent, assetId)]
519+ else [ScriptTransfer(Address(fromBase58String(feeReceiver)), amountForSign, assetId)]
520+ let buyRes = ([IntegerEntry(keyIssued(issuer, artId), newAmountSold), StringEntry(("nft_" + toBase58String(idNFT)), soldKey), IntegerEntry("total_nft_issued", (totalNFT + 1)), IntegerEntry(keyEndSale(issuer, artId), 0), BooleanEntry(keyOnSale(issuer, artId), sellStatus), issueNFT, ScriptTransfer(Address(fromBase58String(issuer)), amountForCreator, assetId), ScriptTransfer(receiveNFT, 1, idNFT)] ++ commissions)
521+ if (isBid)
522+ then [soldData, bidUpdate, bidDelOld] :: buyRes
523+ else soldData :: buyRes
524+ }
525+ }
526+ }
527+ }
528+ }
529+ }
172530
173531
174532 func asString (bv) = match bv {
175533 case bv0: String =>
176534 bv0
177535 case _ =>
178536 throw("Sponsored Public Key String expected")
179537 }
180538
181539
182-func getCaller (i,pubKey) = {
183- let isSponsored = valueOrElse(checkWhitelist((toString(addressFromPublicKey(fromBase58String(pubKey))) + "_free_txs")), 0)
184- let caller = if (if (if ((toBase58String(i.caller.bytes) == toString(this)))
185- then (size(i.payments) == 0)
186- else false)
187- then (isSponsored > 0)
188- else false)
189- then toString(addressFromPublicKey(fromBase58String(pubKey)))
190- else toBase58String(i.caller.bytes)
191- let get_sponsored_waves = if ((pubKey != ""))
192- then invoke(whitelistDapp, "useFreeTx", [toString(addressFromPublicKey(fromBase58String(pubKey)))], nil)
193- else unit
194- if ((get_sponsored_waves == get_sponsored_waves))
195- then $Tuple2(caller, (isSponsored > 0))
196- else throw("Strict value is not equal to itself.")
197- }
198-
199-
200540 @Callable(invoke)
201541 func setConf (key,val) = {
202542 let caller = toString(invoke.caller)
203543 if (containsElement([chris, toString(this)], caller))
204- then [StringEntry(key, val)]
544+ then if (contains(key, "conf_"))
545+ then [StringEntry(key, val)]
546+ else throw("Entries starting with conf_ only")
205547 else throw("You are not allowed to change this")
206548 }
207549
208550
209551
210-@Callable(invoke)
211-func appRunning (isLive,message) = {
212- let caller = toString(invoke.caller)
213- if (containsElement([chris, toString(this)], caller))
214- then [BooleanEntry(dappRunningKey, isLive), StringEntry(maintenanceMSGKey, message)]
215- else throw("You are not allowed to change this")
552+@Callable(i)
553+func addArtwork (sha256Hash,signID,name,description,tags,type,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence,crawler,royalties,pubKey) = {
554+ let $t01888118954 = idCallerDateSponsored(i, pubKey)
555+ let artId = $t01888118954._1
556+ let caller = $t01888118954._2
557+ let date = $t01888118954._3
558+ let isSponsored = $t01888118954._4
559+ if (!(validateHash(sha256Hash)))
560+ then throw("Hash should be 64 characters maximum")
561+ else {
562+ let $t01905519124 = setLIcence(cidLicence, sha256Licence)
563+ let licenceCID = $t01905519124._1
564+ let licenceHash = $t01905519124._2
565+ let validateArtwork = validateArtworkData(caller, cidDisplay, cidExport, licenceCID, sha256Export, licenceHash, name, description, tags, royalties)
566+ if ((validateArtwork != ""))
567+ then throw("Something went wrong!")
568+ else {
569+ let whitelisted_drop = (checkWhitelist((caller + "_free_drops")) > 0)
570+ let $t01942319507 = if (whitelisted_drop)
571+ then $Tuple2(0, signID)
572+ else validatePayment(i)
573+ let amount = $t01942319507._1
574+ let assetId = $t01942319507._2
575+ if (!(isDefined(amount)))
576+ then throw("Something went wrong")
577+ else {
578+ let entryExist = getStringByKey(keyTxidByHashOwner(sha256Hash, caller))
579+ if ((entryExist != ""))
580+ then throw("You already added it")
581+ else {
582+ let hashExist = getStringByKey(keyOwnerByHash(sha256Hash))
583+ if ((hashExist != ""))
584+ then throw("Hash already registered")
585+ else {
586+ let isSignCertified = checkSignCertificate(signID, caller, sha256Hash)
587+ if (!(isSignCertified))
588+ then throw("Sign Certificate not found for this address.")
589+ else {
590+ let decrease_whitelist_drop = if (whitelisted_drop)
591+ then invoke(whitelistDapp, "useFreeDrop", [caller], nil)
592+ else unit
593+ if ((decrease_whitelist_drop == decrease_whitelist_drop))
594+ then {
595+ let txToCaller = if (isSponsored)
596+ then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
597+ else nil
598+ ([StringEntry(keyOwnerByHash(sha256Hash), caller), StringEntry(keyTxidByHashOwner(sha256Hash, caller), artId), IntegerEntry(keyDate(caller, artId), date), StringEntry(keyName(caller, artId), name), StringEntry(keyDesc(caller, artId), description), StringEntry(keyDisplayCid(caller, artId), cidDisplay), StringEntry(keyExportCid(caller, artId), cidExport), StringEntry(keyExportHash(caller, artId), sha256Export), StringEntry(keyLicenceHash(caller, artId), licenceHash), StringEntry(keyLicenceCid(caller, artId), licenceCID), StringEntry(keyType(caller, artId), type), StringEntry(keyTags(caller, artId), tags), IntegerEntry(keyMaxMint(caller, artId), 0), StringEntry(keySignID(caller, artId), signID), IntegerEntry(keyIssued(caller, artId), 0), BooleanEntry(keyOnSale(caller, artId), false), StringEntry(keyidBySignid(caller, signID), artId), StringEntry(keyHashByTxidAddr(caller, artId), sha256Hash), StringEntry(keyCrawler(caller, artId), crawler), IntegerEntry(keyRoyalties(caller, artId), royalties), ScriptTransfer(Address(fromBase58String(feeReceiver)), amount, signAssetId)] ++ txToCaller)
599+ }
600+ else throw("Strict value is not equal to itself.")
601+ }
602+ }
603+ }
604+ }
605+ }
606+ }
216607 }
217608
218609
219610
220-@Callable(invoke)
221-func registrationMode (WLonly) = {
222- let caller = toString(invoke.caller)
223- if (containsElement([chris, toString(this)], caller))
224- then [BooleanEntry(whitelistedonlyKey, WLonly)]
225- else throw("You are not allowed to change this")
226- }
227-
228-
229-
230-@Callable(invoke)
231-func registerUser (name,description,thumb,social,royalties,pubKey) = if (!(dappRunning))
611+@Callable(i)
612+func updateArtwork (txid,name,description,tags,type,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence,crawler,royalties,pubKey) = if (!(dappRunning))
232613 then throw(maintenanceMSG)
233614 else {
234- let $t072777329 = getCaller(invoke, pubKey)
235- let caller = $t072777329._1
236- let isSponsored = $t072777329._2
237- let id = toBase58String(invoke.transactionId)
238- let timestamp = lastBlock.timestamp
239- if (!(validUserData(caller, name, description, thumb, false)))
240- then throw("Something went wrong")
615+ let $t02254122611 = idCallerDateSponsored(i, pubKey)
616+ let id = $t02254122611._1
617+ let caller = $t02254122611._2
618+ let date = $t02254122611._3
619+ let isSponsored = $t02254122611._4
620+ let $t02262122690 = setLIcence(cidLicence, sha256Licence)
621+ let licenceCID = $t02262122690._1
622+ let licenceHash = $t02262122690._2
623+ let validateArtwork = validateArtworkData(caller, cidDisplay, cidExport, licenceCID, sha256Export, licenceHash, name, description, tags, royalties)
624+ if ((validateArtwork != ""))
625+ then throw("Something went wrong!")
241626 else {
242- let json = makeJSON(toBase64String(toBytes(name)), toBase64String(toBytes(thumb)), toString(timestamp))
243- if (if ((0 > royalties))
244- then true
245- else (royalties > 1000))
246- then throw("Royalties cannot be less than 0% or higher than 10%")
627+ let entryExist = getStringByKey(keyName(caller, txid))
628+ if ((entryExist == ""))
629+ then throw("Entry not found")
247630 else {
248- let txToCaller = if (isSponsored)
249- then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
250- else nil
251- ([IntegerEntry(keyUserDate(caller), timestamp), StringEntry(keyUserAddr(caller), ((id + "_") + toString(timestamp))), StringEntry(keyUserName(caller), name), StringEntry(keyUserDesc(caller), description), StringEntry(keyUserSocial(caller), social), StringEntry(keyUserThumb(caller), thumb), StringEntry(keyUserStatus(caller), userRegistered), IntegerEntry(keyUserRoyalties(caller), royalties), DeleteEntry(("ALLOWED_" + caller)), StringEntry(((userRegistered + "_") + caller), json)] ++ txToCaller)
631+ let flag = getStringByKey(keyFlag(caller, txid))
632+ if ((flag == "ILLEGAL"))
633+ then throw("Cannot update ILLEGAL artwork")
634+ else if (!(isArtMinted(caller, txid)))
635+ then {
636+ let txToCaller = if (isSponsored)
637+ then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
638+ else nil
639+ ([StringEntry(keyName(caller, txid), name), StringEntry(keyDesc(caller, txid), description), StringEntry(keyDisplayCid(caller, txid), cidDisplay), StringEntry(keyExportCid(caller, txid), cidExport), StringEntry(keyExportHash(caller, txid), sha256Export), StringEntry(keyLicenceCid(caller, txid), licenceCID), StringEntry(keyLicenceHash(caller, txid), licenceHash), StringEntry(keyTags(caller, txid), tags), StringEntry(keyType(caller, txid), type), StringEntry(keyCrawler(caller, txid), crawler), IntegerEntry(keyRoyalties(caller, txid), royalties)] ++ txToCaller)
640+ }
641+ else throw("Already minted")
252642 }
253643 }
254644 }
255645
256646
257647
258-@Callable(invoke)
259-func updateUser (name,description,thumb,social,royalties,pubKey) = if (!(dappRunning))
260- then throw(maintenanceMSG)
261- else {
262- let $t087728876 = getCaller(invoke, pubKey)
263- let caller = $t087728876._1
264- let isSponsored = $t087728876._2
265- let status = getStringByKey(keyUserStatus(caller))
266- if (!(validUserData(caller, name, description, thumb, true)))
267- then throw("Something went wrong")
268- else {
269- let date = getIntegerByKey(keyUserDate(caller))
270- let json = makeJSON(toBase64String(toBytes(name)), toBase64String(toBytes(thumb)), toString(date))
271- if (if ((0 > royalties))
272- then true
273- else (royalties > 1000))
274- then throw("Royalties cannot be less than 0% or higher than 10%")
275- else {
276- let txToCaller = if (isSponsored)
277- then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
278- else nil
279- ([StringEntry(keyUserName(caller), name), StringEntry(keyUserDesc(caller), description), StringEntry(keyUserSocial(caller), social), StringEntry(keyUserThumb(caller), thumb), IntegerEntry(keyUserRoyalties(caller), royalties), StringEntry(((status + "_") + caller), json)] ++ txToCaller)
280- }
281- }
282- }
283-
284-
285-
286-@Callable(invoke)
287-func setERC20User (erc20,pubKey) = if (!(dappRunning))
288- then throw(maintenanceMSG)
289- else {
290- let $t01006310166 = getCaller(invoke, pubKey)
291- let caller = $t01006310166._1
292- let isSponsored = $t01006310166._2
293- let status = getStringByKey(keyUserStatus(caller))
294- if (if ((status != userRegistered))
295- then (status != userVerified)
296- else false)
297- then throw("Not allowed to set ERC20 address")
298- else {
299- let firstTwo = take(erc20, 2)
300- if (if ((firstTwo != "0x"))
301- then true
302- else (size(erc20) != 42))
303- then throw("This is not an erc20 address")
304- else {
305- let txToCaller = if (isSponsored)
306- then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
307- else nil
308- ([StringEntry(keyUserERC20(caller), erc20)] ++ txToCaller)
309- }
310- }
311- }
312-
313-
314-
315-@Callable(invoke)
316-func changeUserStatus (address,status,note) = {
317- let caller = toString(invoke.caller)
318- let currentStatus = getStringByKey(keyUserStatus(address))
319- let statusToSet = validateNewStatus(status, address, currentStatus)
320- let name = toBase64String(toBytes(getStringByKey(keyUserName(address))))
321- let thumb = toBase64String(toBytes(getStringByKey(keyUserThumb(address))))
322- let date = getIntegerByKey(keyUserDate(address))
323- let json = makeJSON(name, thumb, toString(date))
648+@Callable(i)
649+func flagArtwork (artId,addr,flag,note) = {
650+ let $t02431724351 = idCallerDate(i)
651+ let id = $t02431724351._1
652+ let caller = $t02431724351._2
324653 if (containsElement([chris, toString(this)], caller))
325- then [StringEntry(keyUserStatus(address), statusToSet), DeleteEntry(((currentStatus + "_") + address)), StringEntry(((statusToSet + "_") + address), json), StringEntry(("user_note_" + address), note)]
326- else throw("Not allowed to change user status")
327- }
328-
329-
330-
331-@Callable(invoke)
332-func deleteUser (address) = {
333- let caller = toString(invoke.caller)
334- let currentStatus = getStringByKey(keyUserStatus(address))
335- if (containsElement([chris, toString(this)], caller))
336- then [DeleteEntry(keyUserDate(address)), DeleteEntry(keyUserAddr(address)), DeleteEntry(keyUserName(address)), DeleteEntry(keyUserDesc(address)), DeleteEntry(keyUserSocial(address)), DeleteEntry(keyUserThumb(address)), DeleteEntry(("user_note_" + address)), DeleteEntry(((currentStatus + "_") + address)), DeleteEntry(keyUserRoyalties(address)), StringEntry(keyUserStatus(address), userRemoved)]
337- else throw("Not allowed")
654+ then if (containsElement(["CONSENT", "", "CHANGE_REQUIRED", "FLAGGED", "ILLEGAL"], flag))
655+ then [StringEntry(keyFlag(addr, artId), flag), StringEntry(keyNote(addr, artId), note)]
656+ else throw(("Unknow status " + flag))
657+ else throw("You are not allowed")
338658 }
339659
340660
341661
342662 @Callable(i)
343-func setAgent (artistAddr,agentAddr,primaryShare,secondaryShare) = if (!(dappRunning))
344- then throw(maintenanceMSG)
345- else {
346- let caller = toString(i.caller)
347- if (containsElement([chris, toString(this)], caller))
348- then if (if ((size(artistAddr) != 35))
349- then true
350- else (size(agentAddr) != 35))
351- then throw("Wrong address")
352- else [StringEntry(keyArtistAgentAddr(artistAddr), agentAddr), StringEntry(keyAgentArtistAddr(agentAddr, artistAddr), artistAddr), IntegerEntry(keyPrimaryShare(artistAddr), primaryShare), IntegerEntry(keySecondaryShare(artistAddr), secondaryShare)]
353- else throw("You are not allowed")
354- }
663+func deleteArtwork (artId,addr) = {
664+ let $t02478724821 = idCallerDate(i)
665+ let id = $t02478724821._1
666+ let caller = $t02478724821._2
667+ let addrToUse = if (containsElement([chris, toString(this)], caller))
668+ then addr
669+ else caller
670+ let entryExist = valueOrErrorMessage(getStringByKey(keyName(addrToUse, artId)), "No art matching for this address")
671+ if ((entryExist == ""))
672+ then throw("No art matching for this address")
673+ else {
674+ let sha256Hash = getStringByKey(keyHashByTxidAddr(addrToUse, artId))
675+ if ((sha256Hash == ""))
676+ then throw("No art hash matching for this address")
677+ else {
678+ let signID = getStringByKey(keySignID(addrToUse, artId))
679+ if ((signID == ""))
680+ then throw("No SIGN ID matching")
681+ else {
682+ let dataToDelete = [DeleteEntry(keyDate(addrToUse, artId)), DeleteEntry(keyName(addrToUse, artId)), DeleteEntry(keyDesc(addrToUse, artId)), DeleteEntry(keyDisplayCid(addrToUse, artId)), DeleteEntry(keyExportCid(addrToUse, artId)), DeleteEntry(keyExportHash(addrToUse, artId)), DeleteEntry(keyLicenceHash(addrToUse, artId)), DeleteEntry(keyLicenceCid(addrToUse, artId)), DeleteEntry(keyType(addrToUse, artId)), DeleteEntry(keyTags(addrToUse, artId)), DeleteEntry(keyMaxMint(addrToUse, artId)), DeleteEntry(keySignID(addrToUse, artId)), DeleteEntry(keyIssued(addrToUse, artId)), DeleteEntry(keyOnSale(addrToUse, artId)), DeleteEntry(keyFlag(addrToUse, artId)), DeleteEntry(keyPrice(addrToUse, artId)), DeleteEntry(keyAssetIdAccepted(addrToUse, artId)), DeleteEntry(keyOwnerByHash(sha256Hash)), DeleteEntry(keyidBySignid(addrToUse, signID)), DeleteEntry(keyTxidByHashOwner(sha256Hash, addrToUse)), DeleteEntry(keyEndSale(addrToUse, artId)), DeleteEntry(keyNote(addrToUse, artId)), DeleteEntry(keyCrawler(addrToUse, artId)), DeleteEntry(keyRoyalties(addrToUse, artId))]
683+ if (!(isArtMinted(addrToUse, artId)))
684+ then if (!(dappRunning))
685+ then throw(maintenanceMSG)
686+ else dataToDelete
687+ else if (containsElement([chris, toString(this)], caller))
688+ then dataToDelete
689+ else throw("Art already minted, you cannot delete it")
690+ }
691+ }
692+ }
693+ }
355694
356695
357696
358697 @Callable(i)
359-func unsetAgent (artistAddr,agentAddr) = if (!(dappRunning))
360- then throw(maintenanceMSG)
361- else {
362- let caller = toString(i.caller)
363- if (containsElement([chris, toString(this)], caller))
364- then if (if ((size(artistAddr) != 35))
365- then true
366- else (size(agentAddr) != 35))
367- then throw("Wrong address")
368- else [DeleteEntry(keyArtistAgentAddr(artistAddr)), DeleteEntry(keyAgentArtistAddr(agentAddr, artistAddr)), DeleteEntry(keyPrimaryShare(artistAddr)), DeleteEntry(keySecondaryShare(artistAddr))]
369- else throw("You are not allowed")
370- }
698+func sellArtwork (artId,price,maxMint,assetId,blockEnd,pubKey) = {
699+ let $t02765727727 = idCallerDateSponsored(i, pubKey)
700+ let id = $t02765727727._1
701+ let caller = $t02765727727._2
702+ let date = $t02765727727._3
703+ let isSponsored = $t02765727727._4
704+ let artworkName = getStringByKey(keyName(caller, artId))
705+ if ((artworkName == ""))
706+ then throw("This art doesn't match your account")
707+ else {
708+ let flag = getStringByKey(keyFlag(caller, artId))
709+ if (containsElement(["CHANGE_REQUIRED", "FLAGGED", "ILLEGAL"], flag))
710+ then throw("Flagged artwork")
711+ else {
712+ let bidNbr = getIntegerByKey(("current_bidamount_" + artId))
713+ if ((0 > blockEnd))
714+ then throw("Negative end")
715+ else if (if ((blockEnd > 0))
716+ then if ((maxMint != 1))
717+ then true
718+ else (price != 0)
719+ else false)
720+ then throw("Timed offer only allowed for unique edition and offer only")
721+ else {
722+ let baseHeight = if ((blockEnd == 0))
723+ then 0
724+ else height
725+ if (!(acceptedAssetIds(assetId)))
726+ then throw("Something went wrong!")
727+ else if (!(validateMinSell(assetId, price)))
728+ then throw("Something went wrong!")
729+ else {
730+ let checkUser = validateUser(caller)
731+ if ((checkUser != ""))
732+ then throw(checkUser)
733+ else {
734+ let amountSold = getIntegerByKey(keyIssued(caller, artId))
735+ let maxCanSell = getIntegerByKey(keyMaxMint(caller, artId))
736+ if ((maxMint > 100))
737+ then throw("100 editions max per artwork")
738+ else if (if ((amountSold != 0))
739+ then (amountSold == maxCanSell)
740+ else false)
741+ then throw("Max edition reached.")
742+ else if (if ((amountSold > 0))
743+ then (maxCanSell != maxMint)
744+ else false)
745+ then throw("Cannot change maximum issuable anymore")
746+ else if (if ((bidNbr > 0))
747+ then (maxCanSell != maxMint)
748+ else false)
749+ then throw("Cannot change maximum issuable with active orders")
750+ else {
751+ let sellStatus = if (if ((price > 0))
752+ then (maxMint > 0)
753+ else false)
754+ then true
755+ else false
756+ let txToCaller = if (isSponsored)
757+ then [ScriptTransfer(Address(fromBase58String(caller)), 0, unit)]
758+ else nil
759+ ([BooleanEntry(keyOnSale(caller, artId), sellStatus), IntegerEntry(keyPrice(caller, artId), price), IntegerEntry(keyMaxMint(caller, artId), maxMint), StringEntry(keyAssetIdAccepted(caller, artId), assetId), IntegerEntry(keyEndSale(caller, artId), (baseHeight + blockEnd))] ++ txToCaller)
760+ }
761+ }
762+ }
763+ }
764+ }
765+ }
766+ }
371767
372768
373769
374770 @Callable(i)
375-func deleteEntry (entry) = {
376- let caller = toString(i.caller)
377- if ((caller == chris))
378- then [DeleteEntry(entry)]
379- else throw("no")
771+func buyArtwork (artId,issuer) = buyMint(i, artId, issuer, "", "")
772+
773+
774+
775+@Callable(i)
776+func setBid (artId,issuer) = {
777+ let $t03010530145 = idCallerDate(i)
778+ let id = $t03010530145._1
779+ let caller = $t03010530145._2
780+ let date = $t03010530145._3
781+ let $t03015030186 = isPayment(i)
782+ let payment = $t03015030186._1
783+ let amount = $t03015030186._2
784+ let assetId = if (!(isDefined(payment.assetId)))
785+ then "WAVES"
786+ else toBase58String(value(payment.assetId))
787+ let blockEnd = getIntegerByKey(keyEndSale(issuer, artId))
788+ if (if ((blockEnd != 0))
789+ then (height >= blockEnd)
790+ else false)
791+ then throw("Sale ended.")
792+ else {
793+ let bidNbr = getIntegerByKey(("current_bidamount_" + artId))
794+ if (!(acceptedAssetIds(assetId)))
795+ then throw("asset not accepted")
796+ else if (!(validateMinSell(assetId, amount)))
797+ then throw("Wrong min sell")
798+ else {
799+ let amountSold = getIntegerByKey(keyIssued(issuer, artId))
800+ let maxCanSell = getIntegerByKey(keyMaxMint(issuer, artId))
801+ if ((0 >= maxCanSell))
802+ then throw("No max edition set for this artwork")
803+ else if ((amountSold >= maxCanSell))
804+ then throw("Sold out, you cannot bid")
805+ else [StringEntry((((((((("bid_" + artId) + "_") + issuer) + "_") + caller) + "_") + id) + "_OPEN"), ((((assetId + "_") + toString(amount)) + "_") + toString(date))), IntegerEntry(("current_bidamount_" + artId), (bidNbr + 1))]
806+ }
807+ }
808+ }
809+
810+
811+
812+@Callable(i)
813+func acceptBid (artId,issuer,bidId,bidOwner) = {
814+ let $t03134431384 = idCallerDate(i)
815+ let id = $t03134431384._1
816+ let caller = $t03134431384._2
817+ let date = $t03134431384._3
818+ if ((caller != issuer))
819+ then throw("You cannot do this action")
820+ else buyMint(i, artId, issuer, bidId, bidOwner)
821+ }
822+
823+
824+
825+@Callable(i)
826+func cancelBid (artId,issuer,bidId,bidOwner) = {
827+ let $t03161031671 = idCallerDate(i)
828+ let id = $t03161031671._1
829+ let caller = $t03161031671._2
830+ let date = $t03161031671._3
831+ if (if ((caller != bidOwner))
832+ then (caller != issuer)
833+ else false)
834+ then throw("You cannot do this action")
835+ else {
836+ let returnMoneyTo = if ((caller == issuer))
837+ then bidOwner
838+ else caller
839+ let bidNbr = getIntegerByKey(("current_bidamount_" + artId))
840+ let bidDataKey = ((((((("bid_" + artId) + "_") + issuer) + "_") + bidOwner) + "_") + bidId)
841+ let bidData = getStringByKey((bidDataKey + "_OPEN"))
842+ if ((bidData == ""))
843+ then throw("Bid not found")
844+ else {
845+ let bidDataArr = split(bidData, "_")
846+ let assetId = getBidAssetId(bidDataArr[0])
847+ let bidStatus = "CANCELED"
848+[DeleteEntry((bidDataKey + "_OPEN")), StringEntry(((bidDataKey + "_") + bidStatus), ((bidData + "_") + toString(date))), IntegerEntry(("current_bidamount_" + artId), (bidNbr - 1)), ScriptTransfer(Address(fromBase58String(returnMoneyTo)), parseIntValue(bidDataArr[1]), assetId)]
849+ }
850+ }
380851 }
381852
382853
383854 @Verifier(tx)
384855 func verifier () = match tx {
385856 case inv: InvokeScriptTransaction =>
386- if (if (if ((inv.function == "registerUser"))
857+ if (if (if ((inv.function == "addArtwork"))
387858 then (inv.dApp == this)
388859 else false)
389860 then (inv.fee == 500000)
390861 else false)
391- then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[5])))
392- else if (if (if ((inv.function == "updateUser"))
862+ then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[13])))
863+ else if (if (if ((inv.function == "updateArtwork"))
393864 then (inv.dApp == this)
394865 else false)
395866 then (inv.fee == 500000)
396867 else false)
397- then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[5])))
398- else if (if (if ((inv.function == "setERC20User"))
868+ then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[12])))
869+ else if (if (if ((inv.function == "sellArtwork"))
399870 then (inv.dApp == this)
400871 else false)
401872 then (inv.fee == 500000)
402873 else false)
403- then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[2])))
874+ then sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(asString(inv.args[5])))
404875 else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
405876 case _ =>
406877 sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
407878 }
408879

github/deemru/w8io/169f3d6 
120.53 ms