Created
April 23, 2022 12:44
-
-
Save zmnv/16157749797616ca888a807646f7cec9 to your computer and use it in GitHub Desktop.
Tezos Blog Smart Contract
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// You can use https://smartpy.io/ts-ide to originate or tests. | |
/** | |
* Tzblg Object (Child Contract). | |
* Used as microblog platform to store and moderate any TBytes data. | |
* Demo: https://tzblg.xyz/c/KT1X7PGL7gRwj4F3zx4S6DXKDEeTAJ6D47FM | |
*/ | |
export type PermissionsType = { | |
can_anyone_be_author: TBool; | |
can_admin_edit_other_authors: TBool; | |
can_author_remove: TBool; | |
can_author_update: TBool; | |
}; | |
interface TzblgObjectTStorage { | |
posts: TBig_map<TNat, | |
TRecord< | |
{ | |
id: TNat; | |
author: TAddress; | |
value: TBytes; | |
metadata: TBytes; | |
}, | |
['id', ['author', ['value', 'metadata']]] | |
> | |
>; | |
posts_lastId: TNat; | |
posts_payload_type: TString; | |
likes: TBig_map<TNat, TMap<TAddress, TMutez>>; | |
authors: TBig_map<TAddress, TString>, | |
config: { | |
admin: TAddress; | |
paused: TBool; | |
}; | |
permissions: PermissionsType; | |
metadata: TBig_map<TString, TBytes>; | |
sig: TString, | |
} | |
enum TzblgObjectErrorCodes { | |
TZBLG1_REMOVING_DISABLED, | |
TZBLG1_UPDATING_DISABLED, | |
TZBLG1_NOT_AUTHORIZED, | |
TZBLG1_POST_NOT_FOUND, | |
TZBLG1_AUTHOR_NOT_FOUND, | |
TZBLG1_POST_ALREADY_EXISTS, | |
TZBLG1_PAUSED, | |
TZBLG1_AUTHORS_CANT_LIKE_THEM_SELF, | |
TZBLG1_CANT_CHANGE_BASE_META, | |
} | |
const TZBLG_OBJECT_METADATA = [ | |
['', '0x74657a6f732d73746f726167653a6d657461'], | |
['meta', '0x7b0d0a20202020226e616d65223a2022547a626c67204f626a656374222c0d0a20202020226465736372697074696f6e223a2022436f6e74656e74204d616e6167656d656e7420536d61727420436f6e7472616374222c0d0a202020202276657273696f6e223a2022545a424c47312d4f424a4543542d4259544553222c0d0a2020202022696e7465726661636573223a205b22545a424c47312d4f424a4543542d323032312d31322d3138225d0d0a7d'], | |
['name', '0x547a626c67204f626a656374'], | |
['description', ''], | |
['imageUri', ''] | |
]; | |
const tzblg_object_initial_storage: TzblgObjectTStorage = { | |
sig: 'tzbgl1-object', | |
posts: [], | |
posts_lastId: 0, | |
posts_payload_type: 'TString', | |
likes: [], | |
config: { | |
admin: 'tz1hdQscorfqMzFqYxnrApuS5i6QSTuoAp3w', | |
paused: false, | |
}, | |
authors: [['tz1hdQscorfqMzFqYxnrApuS5i6QSTuoAp3w', '']], | |
permissions: { | |
can_anyone_be_author: true, | |
can_admin_edit_other_authors: true, | |
can_author_remove: true, | |
can_author_update: true, | |
}, | |
metadata: TZBLG_OBJECT_METADATA | |
} | |
class TzblgObjectStorage { | |
constructor(public storage: TzblgObjectTStorage = tzblg_object_initial_storage) { } | |
} | |
class TzblgObjectOffChainViews extends TzblgObjectStorage { | |
@OffChainView({ | |
pure: true, | |
name: "get_posts_count", | |
description: 'Get posts count', | |
}) | |
get_posts_count = (): TNat => { | |
return this.storage.posts_lastId; | |
}; | |
@OffChainView({ | |
pure: true, | |
name: "get_admin", | |
description: 'Get admin address', | |
}) | |
get_admin = (): TAddress => { | |
return this.storage.config.admin; | |
}; | |
@OffChainView({ | |
pure: true, | |
name: "get_metadata", | |
description: 'Get contract metadata', | |
}) | |
get_metadata = (): TBig_map<TString, TBytes> => { | |
return this.storage.metadata; | |
}; | |
@OffChainView({ | |
pure: true, | |
name: "get_permissions", | |
description: 'Get contract permissions', | |
}) | |
get_permissions = (): PermissionsType => { | |
return this.storage.permissions; | |
}; | |
@OffChainView({ | |
pure: true, | |
name: "is_paused", | |
description: 'Is contract paused? When paused, only <admin> can call main actions.', | |
}) | |
is_paused = (): TBool => { | |
return this.storage.config.paused; | |
}; | |
@OffChainView({ | |
pure: true, | |
name: "can_author_remove", | |
description: 'Is anybody can remove their posts?', | |
}) | |
can_author_remove = (): TBool => { | |
return this.storage.permissions.can_author_remove; | |
}; | |
@OffChainView({ | |
pure: true, | |
name: "can_author_update", | |
description: 'Is anybody can update their posts?', | |
}) | |
can_author_update = (): TBool => { | |
return this.storage.permissions.can_author_update; | |
}; | |
@OffChainView({ | |
pure: true, | |
name: "can_admin_edit_other_authors", | |
description: 'Can admin edit another authors posts?', | |
}) | |
can_admin_edit_other_authors = (): TBool => { | |
return this.storage.permissions.can_admin_edit_other_authors; | |
}; | |
} | |
/** | |
* @description Class that contains the contract metadata builder | |
*/ | |
class TzblgObjectMetadata extends TzblgObjectOffChainViews { | |
@MetadataBuilder | |
metadata = { | |
"name": "Tzblg Object", | |
"description": "Content Management Smart Contract", | |
"version": "TZBLG1-OBJECT-BYTES", | |
"interfaces": ["TZBLG1-OBJECT-2021-12-18"], | |
views: [ | |
this.get_posts_count, | |
this.get_admin, | |
this.get_metadata, | |
this.get_permissions, | |
this.is_paused, | |
this.can_author_remove, | |
this.can_author_update, | |
this.can_admin_edit_other_authors, | |
], | |
}; | |
} | |
class TzblgObjectHelpers extends TzblgObjectMetadata { | |
/** | |
* @description Fail if contract is paused (except admin). | |
*/ | |
@Inline | |
failIfPaused() { | |
if (Sp.sender !== this.storage.config.admin) { | |
Sp.verify(!this.storage.config.paused, TzblgObjectErrorCodes.TZBLG1_PAUSED); | |
} | |
} | |
/** | |
* @description Fail if the sender is not admin | |
*/ | |
@Inline | |
failIfSenderNotAdmin() { | |
Sp.verify(Sp.sender === this.storage.config.admin, TzblgObjectErrorCodes.TZBLG1_NOT_AUTHORIZED); | |
} | |
/** | |
* @description Fail if the post not found | |
*/ | |
@Inline | |
failIfPostNotFound(postId: TNat) { | |
Sp.verify(this.storage.posts.hasKey(postId), TzblgObjectErrorCodes.TZBLG1_POST_NOT_FOUND); | |
} | |
/** | |
* @description Fail if the post not found | |
*/ | |
@Inline | |
failIfAuthorNotFound(author: TAddress) { | |
Sp.verify(this.storage.authors.hasKey(author), TzblgObjectErrorCodes.TZBLG1_AUTHOR_NOT_FOUND); | |
} | |
/** | |
* @description Fail if the post not found | |
*/ | |
@Inline | |
failIfPostAlreadyExists(postId: TNat) { | |
Sp.verify(!this.storage.posts.hasKey(postId), TzblgObjectErrorCodes.TZBLG1_POST_ALREADY_EXISTS); | |
} | |
/** | |
* @description Fail if the sender is not author of the post | |
*/ | |
@Inline | |
failIfSenderNotAuthorOfPost(postId: TNat) { | |
const author = this.storage.posts.get(postId).author; | |
Sp.verify(Sp.sender === author, TzblgObjectErrorCodes.TZBLG1_NOT_AUTHORIZED); | |
} | |
/** | |
* @description Fail if the sender is not author of the post | |
*/ | |
@Inline | |
failIfSenderNotAuthorOrAdminOfPost(postId: TNat) { | |
const author = this.storage.posts.get(postId).author; | |
Sp.verify(Sp.sender === author || Sp.sender === this.storage.config.admin, TzblgObjectErrorCodes.TZBLG1_NOT_AUTHORIZED); | |
} | |
/** | |
* @description Fail if the sender is not author of the post | |
*/ | |
@Inline | |
failIfSenderNotAuthorOrAdmin(author: TAddress) { | |
Sp.verify(Sp.sender === author || Sp.sender === this.storage.config.admin, TzblgObjectErrorCodes.TZBLG1_NOT_AUTHORIZED); | |
} | |
/** | |
* @description Fail if contract was originated with can_author_remove is false. | |
*/ | |
@Inline | |
failIfCantRemove() { | |
Sp.verify(this.storage.permissions.can_author_remove, TzblgObjectErrorCodes.TZBLG1_REMOVING_DISABLED); | |
} | |
/** | |
* @description Fail if contract was originated with can_author_update is false. | |
*/ | |
@Inline | |
failIfCantUpdate() { | |
Sp.verify(this.storage.permissions.can_author_update, TzblgObjectErrorCodes.TZBLG1_UPDATING_DISABLED); | |
} | |
/** | |
* @description Fail if not authors | |
*/ | |
@Inline | |
failIfAuthorNotAuthorized() { | |
Sp.verify(this.storage.authors.hasKey(Sp.sender), TzblgObjectErrorCodes.TZBLG1_NOT_AUTHORIZED); | |
} | |
} | |
@Contract | |
export class TZBLG1 extends TzblgObjectHelpers { | |
/** | |
* @description Add a new post. | |
* @param {{value: TBytes}} params | |
*/ | |
@EntryPoint | |
add_post(params: { value: TBytes; metadata: TBytes }): void { | |
// COMMENTED TO PROVIDE PUBLISHING FOR ALL | |
// this.failIfAuthorNotAuthorized(); | |
this.failIfPaused(); | |
const postId: TNat = this.storage.posts_lastId; | |
this.failIfPostAlreadyExists(postId); | |
this.storage.posts.set(postId, { | |
id: postId, | |
author: Sp.sender, | |
value: params.value, | |
metadata: params.metadata, | |
}); | |
this.storage.posts_lastId = postId + 1; | |
} | |
@EntryPoint | |
remove_post(postId: TNat): void { | |
this.failIfPaused(); | |
this.failIfCantRemove(); | |
this.failIfPostNotFound(postId); | |
if (this.storage.permissions.can_admin_edit_other_authors) { | |
this.failIfSenderNotAuthorOrAdminOfPost(postId); | |
} else { | |
this.failIfSenderNotAuthorOfPost(postId); | |
} | |
this.storage.posts.remove(postId); | |
} | |
@EntryPoint | |
update_post(params: { postId: TNat; value: TBytes; metadata: TBytes }): void { | |
this.failIfPaused(); | |
this.failIfCantUpdate(); | |
const postId: TNat = params.postId; | |
this.failIfPostNotFound(postId); | |
if (this.storage.permissions.can_admin_edit_other_authors) { | |
this.failIfSenderNotAuthorOrAdminOfPost(postId); | |
} else { | |
this.failIfSenderNotAuthorOfPost(postId); | |
} | |
if (params.metadata !== '' as TBytes) { | |
this.storage.posts.set(postId, { | |
id: postId, | |
author: this.storage.posts.get(postId).author, | |
value: params.value, | |
metadata: params.metadata, | |
}); | |
} else { | |
this.storage.posts.set(postId, { | |
id: postId, | |
author: this.storage.posts.get(postId).author, | |
value: params.value, | |
metadata: this.storage.posts.get(postId).metadata, | |
}); | |
} | |
} | |
@EntryPoint | |
set_admin(address: TAddress): void { | |
this.failIfSenderNotAdmin(); | |
this.storage.config.admin = address; | |
} | |
/** | |
* @description Pause the contract | |
* @param {TBool} paused | |
*/ | |
@EntryPoint | |
pause(paused: TBool): void { | |
this.failIfSenderNotAdmin(); | |
this.storage.config.paused = paused; | |
} | |
@EntryPoint | |
set_author(author: TAddress, value: TString = ''): void { | |
this.failIfSenderNotAuthorOrAdmin(author); | |
if (Sp.sender !== this.storage.config.admin) { | |
this.failIfPaused(); | |
Sp.verify(this.storage.authors.hasKey(author), TzblgObjectErrorCodes.TZBLG1_NOT_AUTHORIZED); | |
} | |
this.storage.authors.set(author, value); | |
} | |
@EntryPoint | |
remove_author(author: TAddress): void { | |
Sp.verify(Sp.sender === this.storage.config.admin || Sp.sender === author, TzblgObjectErrorCodes.TZBLG1_NOT_AUTHORIZED); | |
Sp.verify(author !== this.storage.config.admin, TzblgObjectErrorCodes.TZBLG1_NOT_AUTHORIZED); | |
this.failIfAuthorNotFound(author); | |
this.storage.authors.remove(author); | |
} | |
@EntryPoint | |
like_post(postId: TNat): void { | |
this.failIfPostNotFound(postId); | |
const postAuthor = this.storage.posts.get(postId).author; | |
Sp.verify(Sp.sender !== postAuthor, TzblgObjectErrorCodes.TZBLG1_AUTHORS_CANT_LIKE_THEM_SELF); | |
// const authorAlreadyLikedThisPost = this.storage.likes.get(postId).hasKey(Sp.sender); | |
if (Sp.amount > (0 as TMutez)) { | |
const contract = Sp.contract<TUnit>(postAuthor).openSome("Invalid Interface"); | |
Sp.transfer(Sp.unit, Sp.amount, contract); | |
} | |
const postAlreadyLikedBySomebody = this.storage.likes.hasKey(postId); | |
if (postAlreadyLikedBySomebody) { | |
const isSenderAlreadyLikedThisPost = this.storage.likes.get(postId).hasKey(Sp.sender); | |
if (isSenderAlreadyLikedThisPost) { | |
const alreadyAmount = this.storage.likes.get(postId).get(Sp.sender); | |
this.storage.likes.get(postId).set(Sp.sender, Sp.amount + alreadyAmount); | |
} else { | |
this.storage.likes.get(postId).set(Sp.sender, Sp.amount); | |
} | |
} else { | |
this.storage.likes.set(postId, [[Sp.sender, Sp.amount]]); | |
} | |
} | |
@EntryPoint | |
set_metadata(key: TString, value: TBytes) { | |
this.failIfSenderNotAdmin(); | |
Sp.verify((key !== 'meta' && key !== ''), TzblgObjectErrorCodes.TZBLG1_CANT_CHANGE_BASE_META); | |
this.storage.metadata.set(key, value) | |
} | |
} | |
/** | |
* -------------------- [TESTS] Tzblg1 Object ----------------------- | |
*/ | |
Dev.test({ name: 'Object: Posts' }, () => { | |
Scenario.h2('TZBLG1 Posts'); | |
const admin = Scenario.testAccount('Administrator'); | |
const bob = Scenario.testAccount('Bob'); | |
const guest = Scenario.testAccount('Guest'); | |
Scenario.show([admin, bob, guest]); | |
Scenario.h4('Originate'); | |
const c1 = Scenario.originate(new TZBLG1(tzblg_object_initial_storage)); | |
Scenario.h4('Add Post by not authorized user'); | |
Scenario.transfer(c1.add_post({ value: '0x48656c6c6f20627920426f6221', metadata: '' }), { sender: bob.address, }); | |
Scenario.h4('Add Bob as author'); | |
Scenario.transfer(c1.set_author(bob.address, 'Bob Dylan Jr.'), { sender: admin.address }); | |
Scenario.h4('Add Post by Bob'); | |
Scenario.transfer(c1.add_post({ value: '0x426f622044796c616e204a722e', metadata: '' }), { sender: bob.address }); | |
Scenario.h4('Update Post by Bob'); | |
Scenario.transfer(c1.update_post({ postId: 0, value: '0x4e65772076616c7565', metadata: '' }), { sender: bob.address }); | |
Scenario.h4('Update Bobs Post by Guest'); | |
Scenario.transfer(c1.update_post({ postId: 0, value: '0x48612d6861206861616161', metadata: '' }), { sender: guest.address, valid: false }); | |
Scenario.h4('Update Bobs Post by Admin'); | |
Scenario.transfer(c1.update_post({ postId: 0, value: '0x4e65772076616c75652e205570646174656421', metadata: '' }), { sender: admin.address }); | |
Scenario.h4('Remove Bob post by Guest'); | |
Scenario.transfer(c1.add_post({ value: '0x4e657720706f737420746f2072656d6f7665', metadata: '' }), { sender: bob.address }); | |
Scenario.transfer(c1.remove_post(0), { sender: guest.address, valid: false }); | |
Scenario.h4('Remove Bob post by Admin'); | |
Scenario.transfer(c1.remove_post(0), { sender: admin.address }); | |
Scenario.h4('Remove Bob post by Bob'); | |
Scenario.transfer(c1.remove_post(1), { sender: bob.address }); | |
}); | |
Dev.test({ name: 'Object: Author' }, () => { | |
Scenario.h2('TZBLG1 Author'); | |
const admin = Scenario.testAccount('Administrator'); | |
const bob = Scenario.testAccount('Bob'); | |
const guest = Scenario.testAccount('Guest'); | |
Scenario.show([admin, bob, guest]); | |
Scenario.h4('Originate'); | |
const c1 = Scenario.originate(new TZBLG1(tzblg_object_initial_storage)); | |
Scenario.h4('Add Post by not authorized user'); | |
Scenario.transfer(c1.add_post({ value: '0x48656c6c6f20627920426f6221', metadata: '' }), { sender: bob.address, }); | |
Scenario.h4('Add Bob as author'); | |
Scenario.transfer(c1.set_author(bob.address, 'Bob Dyilan'), { sender: admin.address }); | |
Scenario.h4('Update Bobs name by Bob'); | |
Scenario.transfer(c1.set_author(bob.address, 'Bob Dylan Jr.'), { sender: bob.address }); | |
Scenario.h4('Update Bobs name by Guest'); | |
Scenario.transfer(c1.set_author(bob.address, 'Bob Dylan Jr.'), { sender: guest.address, valid: false }); | |
Scenario.h4('Update Bobs name by Admin'); | |
Scenario.transfer(c1.set_author(bob.address, 'banned'), { sender: admin.address }); | |
Scenario.h4('Remove Bob from Authors by Guest'); | |
Scenario.transfer(c1.remove_author(bob.address), { sender: guest.address, valid: false }); | |
Scenario.h4('Remove Bob from Authors by Bob'); | |
Scenario.transfer(c1.remove_author(bob.address), { sender: bob.address }); | |
Scenario.h4('Remove Admin from Authors by Admin'); | |
Scenario.transfer(c1.remove_author(admin.address), { sender: admin.address, valid: false }); | |
}); | |
Dev.test({ name: 'Object: Admin' }, () => { | |
Scenario.h2('TZBLG1 Admin'); | |
const admin = Scenario.testAccount('Administrator'); | |
const bob = Scenario.testAccount('Bob'); | |
const guest = Scenario.testAccount('Guest'); | |
Scenario.show([admin, bob, guest]); | |
Scenario.h4('Originate'); | |
const c1 = Scenario.originate(new TZBLG1(tzblg_object_initial_storage)); | |
Scenario.h4('Set Admin by Bob'); | |
Scenario.transfer(c1.set_admin(bob.address), { sender: bob.address, valid: false }); | |
Scenario.h4('Set Admin by Admin'); | |
Scenario.transfer(c1.set_admin(admin.address), { sender: admin.address }); | |
Scenario.h4('Set Admin by Guest'); | |
Scenario.transfer(c1.set_admin(admin.address), { sender: guest.address, valid: false }); | |
Scenario.h4('Set Bob as admin and pause contract'); | |
Scenario.transfer(c1.set_admin(bob.address), { sender: admin.address }); | |
Scenario.p('by admin:'); | |
Scenario.transfer(c1.pause(true), { sender: admin.address, valid: false }); | |
Scenario.p('by bob (new admin):'); | |
Scenario.transfer(c1.pause(true), { sender: bob.address }); | |
}); | |
Dev.test({ name: 'Object: Likes' }, () => { | |
Scenario.h2('TZBLG1 Likes'); | |
const admin = Scenario.testAccount('Administrator'); | |
const bob = Scenario.testAccount('Bob'); | |
const guest = Scenario.testAccount('Guest'); | |
Scenario.show([admin, bob, guest]); | |
Scenario.h4('Originate'); | |
const c1 = Scenario.originate(new TZBLG1(tzblg_object_initial_storage)); | |
Scenario.h4('Add Bob as Author'); | |
Scenario.transfer(c1.set_author(bob.address, 'Bob Dylan Jr.'), { sender: admin.address }); | |
Scenario.h4('Add post by Bob'); | |
Scenario.transfer(c1.add_post({ value: '0x68656c6c6f', metadata: '' }), { sender: bob.address }); | |
Scenario.h4('Like post by Bob (author)'); | |
Scenario.transfer(c1.like_post(0), { sender: bob.address, valid: false }); | |
Scenario.h4('Like post by Guest'); | |
Scenario.transfer(c1.like_post(0), { sender: guest.address }); | |
Scenario.h4('Like post by Guest (again)'); | |
Scenario.transfer(c1.like_post(0), { sender: guest.address }); | |
Scenario.h4('Like post by Guest (again with money)'); | |
Scenario.transfer(c1.like_post(0), { sender: guest.address, amount: 1000000 }); | |
Scenario.h4('Like post by Guest (again with money and again)'); | |
Scenario.transfer(c1.like_post(0), { sender: guest.address, amount: 1000000 }); | |
Scenario.h4('Like post by Admin'); | |
Scenario.transfer(c1.like_post(0), { sender: admin.address }); | |
}); | |
Dev.test({ name: 'Object: Pause' }, () => { | |
Scenario.h2('TZBLG1 Pause'); | |
const admin = Scenario.testAccount('Administrator'); | |
const bob = Scenario.testAccount('Bob'); | |
const guest = Scenario.testAccount('Guest'); | |
Scenario.show([admin, bob, guest]); | |
Scenario.h4('Originate'); | |
const c1 = Scenario.originate(new TZBLG1(tzblg_object_initial_storage)); | |
Scenario.h4('Set Pause as Guest'); | |
Scenario.transfer(c1.pause(true), { sender: guest.address, valid: false }); | |
Scenario.h4('Set Pause as Admin'); | |
Scenario.transfer(c1.pause(true), { sender: admin.address }); | |
Scenario.h4('Do something when pause'); | |
Scenario.transfer(c1.add_post({ value: '0x68656c6c6f20776f726c64206c6f6c', metadata: '' }), { sender: guest.address, valid: false }); | |
Scenario.transfer(c1.add_post({ value: '0x62792061646d696e', metadata: '' }), { sender: admin.address, }); | |
Scenario.transfer(c1.set_author(bob.address, 'Hel1o Kitty'), { sender: admin.address }); | |
Scenario.transfer(c1.add_post({ value: '0x68656c6c6f20776f726c64206c6f6c', metadata: '' }), { sender: bob.address, valid: false }); | |
}); | |
Dev.test({ name: 'Object: Set Metadata' }, () => { | |
Scenario.h2('TZBLG1 Set Metadata'); | |
const admin = Scenario.testAccount('Administrator'); | |
const bob = Scenario.testAccount('Bob'); | |
const guest = Scenario.testAccount('Guest'); | |
Scenario.show([admin, bob, guest]); | |
Scenario.h4('Originate'); | |
const c1 = Scenario.originate(new TZBLG1(tzblg_object_initial_storage)); | |
Scenario.h4('Set Metadata as Guest'); | |
Scenario.transfer(c1.set_metadata('imageUri', '0xFFFFFF'), { sender: guest.address, valid: false }); | |
Scenario.h4('Set Metadata as Admin'); | |
Scenario.transfer(c1.set_metadata('imageUri', '0x697066733a2f2f516d5147435a71484e3762545572724b387772384b357239656f41504c356864564732563661727a673147627266'), { sender: admin.address }); | |
Scenario.h4('Set Image again as Admin'); | |
Scenario.transfer(c1.set_metadata('imageUri', '0x697066733a2f2f516d66353675586851716f70376d6f6872456463764d77565947476250326b346259455765473938347061745052'), { sender: admin.address }); | |
Scenario.h4('Try to change base meta'); | |
Scenario.transfer(c1.set_metadata('meta', '0x00'), { sender: admin.address, valid: false }); | |
Scenario.h4('Try to change base meta'); | |
Scenario.transfer(c1.set_metadata('', '0x00'), { sender: admin.address, valid: false }); | |
}); | |
const config: TzblgObjectTStorage = { | |
sig: 'tzbgl1-object', | |
posts: [], | |
posts_lastId: 0, | |
posts_payload_type: 'TBytes', | |
likes: [], | |
config: { | |
admin: 'tz1PNE1qSjGFYMasZFhktcboZA4ryBZH5MAg', | |
paused: false, | |
}, | |
authors: [['tz1PNE1qSjGFYMasZFhktcboZA4ryBZH5MAg', 'Creator']], | |
permissions: { | |
can_anyone_be_author: true, | |
can_admin_edit_other_authors: true, | |
can_author_remove: true, | |
can_author_update: true, | |
}, | |
metadata: TZBLG_OBJECT_METADATA | |
} | |
Dev.compileContract('compile_contract', new TZBLG1(config)); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment