Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

able to update DAOExt #108

Merged
merged 5 commits into from
Sep 5, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/StarcoinFramework/BuildInfo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ compiled_package_info:
? address: "0x00000000000000000000000000000001"
name: YieldFarmingV2
: StarcoinFramework
source_digest: 695F4208154FB109E223367B79D9AD3C30261C91BF6F595A3B9D2226BC5103B0
source_digest: C2A8ED3808648261C25F3710FE00C7A174ECD66EFA876EC74D6668802EF8AF3E
build_flags:
dev_mode: false
test_mode: false
Expand Down
19 changes: 19 additions & 0 deletions integration-tests/daospace/dao_ext.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
processed 9 tasks

task 6 'run'. lines 65-74:
{
"gas_used": 970329,
"status": "Executed"
}

task 7 'run'. lines 76-85:
{
"gas_used": 76940,
"status": "Executed"
}

task 8 'run'. lines 87-96:
{
"gas_used": 76940,
"status": "Executed"
}
96 changes: 96 additions & 0 deletions integration-tests/daospace/dao_ext.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//# init -n dev

//# faucet --addr creator --amount 100000000000

//# faucet --addr alice --amount 10000000000

//# faucet --addr bob --amount 10000000000

//# publish
module creator::DAOHelper {
use StarcoinFramework::DAOAccount;
use StarcoinFramework::DAOSpace::{Self, CapType};
use StarcoinFramework::Vector;
use StarcoinFramework::Option;

struct X has store, copy, drop {
value: u64,
}

const NAME: vector<u8> = b"X";

/// directly upgrade the sender account to DAOAccount and create DAO
public(script) fun create_dao(
sender: signer,
voting_delay: u64,
voting_period: u64,
voting_quorum_rate: u8,
min_action_delay: u64,
min_proposal_deposit: u128, ) {
let dao_account_cap = DAOAccount::upgrade_to_dao(sender);


//let dao_signer = DAOAccount::dao_signer(&dao_account_cap);
let config = DAOSpace::new_dao_config(
voting_delay,
voting_period,
voting_quorum_rate,
min_action_delay,
min_proposal_deposit,
);
let dao_ext = X { value: 0};
let dao_root_cap = DAOSpace::create_dao<X>(dao_account_cap, *&NAME, Option::none<vector<u8>>(), Option::none<vector<u8>>(), b"ipfs://description", dao_ext, config);
DAOSpace::install_plugin_with_root_cap<X, XPlugin>(&dao_root_cap, required_caps());

DAOSpace::burn_root_cap(dao_root_cap);
}

struct XPlugin has store, drop {}

public fun required_caps(): vector<CapType> {
let caps = Vector::singleton(DAOSpace::modify_ext_cap_type());
caps
}

public fun modify_ext(value: u64): u64 {
let witness = XPlugin {};
let ext_cap = DAOSpace::acquire_modify_ext_cap<X, XPlugin>(&witness);
let X { value } = DAOSpace::modify_ext_with_cap<X, XPlugin>(&ext_cap, X { value });
value
}
}

//# block --author 0x1 --timestamp 86400000

//# run --signers creator
script {
use creator::DAOHelper;

fun main(sender: signer) {
// time unit is millsecond
DAOHelper::create_dao(sender, 10000, 3600000, 2, 10000, 10);
}
}
// check: EXECUTED

//# run --signers alice
script {
use creator::DAOHelper;

fun main(_sender: signer) {
let ext_value = DAOHelper::modify_ext(123);
assert!(ext_value == 0, 101);
}
}
// check: EXECUTED

//# run --signers bob
script {
use creator::DAOHelper;

fun main(_sender: signer) {
let ext_value = DAOHelper::modify_ext(234);
assert!(ext_value == 123, 101);
}
}
// check: EXECUTED
32 changes: 31 additions & 1 deletion sources/daospace/DAOSpace.move
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ module StarcoinFramework::DAOSpace {
const ERR_NFT_ERROR: u64 = 104;
const ERR_ALREADY_INIT: u64 = 105;
const ERR_TOKEN_ERROR: u64 = 106;
const ERR_DAO_EXT: u64 = 107;

/// member
const ERR_EXPECT_MEMBER: u64 = 200;
Expand Down Expand Up @@ -182,6 +183,9 @@ module StarcoinFramework::DAOSpace {
/// Create a token burning capability type.
public fun token_burn_cap_type(): CapType { CapType{code: 10 } }

/// Create a modifying DAOExt capability type.
public fun modify_ext_cap_type(): CapType { CapType{code: 11 } }

/// Create all capability types.
public fun all_caps(): vector<CapType> {
let caps = Vector::singleton(install_plugin_cap_type());
Expand All @@ -193,6 +197,9 @@ module StarcoinFramework::DAOSpace {
Vector::push_back(&mut caps, member_cap_type());
Vector::push_back(&mut caps, proposal_cap_type());
Vector::push_back(&mut caps, grant_cap_type());
Vector::push_back(&mut caps, token_mint_cap_type());
Vector::push_back(&mut caps, token_burn_cap_type());
Vector::push_back(&mut caps, modify_ext_cap_type());
caps
}

Expand All @@ -217,6 +224,8 @@ module StarcoinFramework::DAOSpace {

struct DAOGrantCap<phantom DAOT, phantom PluginT> has drop {}

struct DAOModifyExtCap<phantom DAOT, phantom PluginT> has drop {}

struct DAOGrantWithdrawTokenKey<phantom DAOT, phantom PluginT ,phantom TokenT> has key, store{
/// The total amount of tokens that can be withdrawn by this capability
total: u128,
Expand Down Expand Up @@ -340,7 +349,21 @@ module StarcoinFramework::DAOSpace {
DAORootCap<DAOT>{}
}

// Upgrade account to DAO account and create DAO
/// Modify DAOExt with new ext and return the old one.
public fun modify_ext_with_cap<DAOT: store, PluginT>(_cap: &DAOModifyExtCap<DAOT, PluginT>, ext: DAOT): DAOT
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里返回 DAOT 后,应该是插件接收 DAOT,那么要求 DAOT 必须有 destroy 方法 或者 drop 能力,否则插件将无法处理这个 DAOT?

Copy link
Collaborator Author

@pause125 pause125 Sep 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里返回 DAOT 后,应该是插件接收 DAOT,那么要求 DAOT 必须有 destroy 方法 或者 drop 能力,否则插件将无法处理这个 DAOT?

有道理,确实是个问题。
解决办法:

  1. 要求 DAOT 有 destroy 方法或 drop 能力,这个似乎也不太合理。
  2. 去掉 PluginT 泛型, 这样就不能由插件来管理 DAOExt 的更新了, 只能每个 DAOT 自己实现如何管理。

我认为方案2 似乎更可行一点?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2?DAOT 本来就是 DAOT 注册那个 module 定义的,其他的插件和构造不出来。

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我的意思就是,每个 DAO,比如 StarcoinDAO, 如果想要修改 ext, 那定义 StarcoinDAO 的时候,就要自己自己实现相应的方法去管理 modify_ext_with_cap 返回的 StarcoinDAO,就不能再用插件了。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

嗯,我也是这个意思。那是不是也不需要 cap 了,直接提供 modify_ext 方法就行。

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我现在的场景是将已安装的前端插件挂载到 DaoExt 中,后续添加前端插件可以更新就行

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我现在的场景是将已安装的前端插件挂载到 DaoExt 中,后续添加前端插件可以更新就行

这样是不是可以增加一个 vector<plugin_module> 结构,内部只保存一些字符串(安装的前端插件名、对应的合约插件名等)
可以配合新增加的 TypeInfo module

Copy link
Collaborator Author

@pause125 pause125 Sep 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我现在的场景是将已安装的前端插件挂载到 DaoExt 中,后续添加前端插件可以更新就行

看起来除了更新插件,应该还有读取 DAOExt 的需求? 你其实是想把合约当成一个数据库,用来存储前端插件,并提供读取,写入的功能?类似于下面这样的使用过程:

let ext: DAOT = DAOSpace::take<DAOT>();
ext.installed_web_plugins.push_back(new_installed_plugin);
DAOSapce::save<DAOT>(ext)

DAOSpace 不能直接读取和更新 DAOExt 的内容,只有把里面的 DAOExt 里面的struct 拿出来,你自己 DAO 里更新ext 的内容后再存回去。

这样的话也可以直接在你的模板 DAO 里面的,新增一个 struct 来管理就可以了。

struct InstalledWebPlugins {
    plugins: vector<InstalledWebPluginInfo> 
}

@WGB5445 应该也是这个意思吧?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yubing744 既然这期打算同时考虑前端插件,那不如把前端插件的部分需求也直接定义在 DAOSpace 里?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yubing744 既然这期打算同时考虑前端插件,那不如把前端插件的部分需求也直接定义在 DAOSpace 里?

后面是计划时将前端插件直接集成进DAOSpace,但是能修改DAOExt应该是一个通用需求

acquires DAOAccountCapHolder, DAOExt {
let dao_addr = dao_address<DAOT>();
assert!(exists<DAOExt<DAOT>>(dao_addr), Errors::not_published(ERR_DAO_EXT));
let DAOExt { ext: old_ext } = move_from<DAOExt<DAOT>>(dao_addr);

let dao_signer = dao_signer<DAOT>();
move_to(&dao_signer, DAOExt{
ext
});
old_ext
}

/// Upgrade account to DAO account and create DAO
public fun upgrade_to_dao<DAOT: store>(sender: signer, name: vector<u8>, image_data:Option::Option<vector<u8>>, image_url:Option::Option<vector<u8>>, description:vector<u8>, ext: DAOT, config: DAOConfig): DAORootCap<DAOT> acquires DAOEvent{
let cap = DAOAccount::upgrade_to_dao(sender);
create_dao<DAOT>(cap, name, image_data, image_url, description, ext, config)
Expand Down Expand Up @@ -1049,6 +1072,13 @@ module StarcoinFramework::DAOSpace {
DAOGrantCap<DAOT, PluginT>{}
}

/// Acquire the modifying DAOExt capability
/// _witness parameter ensures that the caller is the module which define PluginT
public fun acquire_modify_ext_cap<DAOT: store, PluginT>(_witness: &PluginT): DAOModifyExtCap<DAOT, PluginT> acquires InstalledPluginInfo {
validate_cap<DAOT, PluginT>(modify_ext_cap_type());
DAOModifyExtCap<DAOT, PluginT>{}
}

/// Delegate the token mint capability to DAO
/// _witness parameter ensures that the caller is the module which define PluginT
public fun delegate_token_mint_cap<DAOT: store, PluginT, TokenT: store>(cap: Token::MintCapability<TokenT>, _witness: &PluginT)
Expand Down