0x1::UpgradeModuleDaoProposal
UpgradeModuleDaoProposal is a proposal moudle used to upgrade contract codes under a token.
UpgradeModuleCapability
UpgradeModule
UpgradeModuleV2
plugin
propose_module_upgrade_v2
submit_module_upgrade_plan
use 0x1::Dao;
use 0x1::Errors;
use 0x1::PackageTxnManager;
use 0x1::Signer;
use 0x1::Token;
UpgradeModuleCapability
A wrapper of PackageTxnManager::UpgradePlanCapability
.
struct UpgradeModuleCapability<TokenT> has key
UpgradeModule
request of upgrading module contract code.
struct UpgradeModule has copy, drop, store
module_address: address
package_hash: vector<u8>
version: u64
UpgradeModuleV2
struct UpgradeModuleV2 has copy, drop, store
module_address: address
package_hash: vector<u8>
version: u64
enforced: bool
const ERR_NOT_AUTHORIZED: u64 = 401;
const ERR_ADDRESS_MISSMATCH: u64 = 402;
const ERR_UNABLE_TO_UPGRADE: u64 = 400;
plugin
If this goverment can upgrade module, call this to register capability.
public fun plugin<TokenT: store>(signer: &signer, cap: PackageTxnManager::UpgradePlanCapability)
public fun plugin<TokenT: store>(
signer: &signer,
cap: PackageTxnManager::UpgradePlanCapability,
) {
let token_issuer = Token::token_address<TokenT>();
assert!(Signer::address_of(signer) == token_issuer, Errors::requires_address(ERR_NOT_AUTHORIZED));
move_to(signer, UpgradeModuleCapability<TokenT> { cap })
}
pragma aborts_if_is_partial = false;
let sender = Signer::address_of(signer);
aborts_if sender != Token::SPEC_TOKEN_TEST_ADDRESS();
aborts_if exists<UpgradeModuleCapability<TokenT>>(sender);
schema AbortIfUnableUpgrade<TokenT> {
module_address: address;
let token_issuer = Token::SPEC_TOKEN_TEST_ADDRESS();
aborts_if !exists<UpgradeModuleCapability<TokenT>>(token_issuer);
let cap = global<UpgradeModuleCapability<TokenT>>(token_issuer).cap;
aborts_if PackageTxnManager::account_address(cap) != module_address;
}
propose_module_upgrade_v2
public fun propose_module_upgrade_v2<TokenT: copy, drop, store>(signer: &signer, module_address: address, package_hash: vector<u8>, version: u64, exec_delay: u64, enforced: bool)
public fun propose_module_upgrade_v2<TokenT: copy + drop + store>(
signer: &signer,
module_address: address,
package_hash: vector<u8>,
version: u64,
exec_delay: u64,
enforced: bool,
) acquires UpgradeModuleCapability {
let cap = borrow_global<UpgradeModuleCapability<TokenT>>(Token::token_address<TokenT>());
let account_address = PackageTxnManager::account_address(&cap.cap);
assert!(account_address == module_address, Errors::requires_capability(ERR_ADDRESS_MISSMATCH));
Dao::propose<TokenT, UpgradeModuleV2>(
signer,
UpgradeModuleV2 { module_address, package_hash, version, enforced },
exec_delay,
);
}
pragma aborts_if_is_partial = true;
include AbortIfUnableUpgrade<TokenT>;
submit_module_upgrade_plan
Once the proposal is agreed, anyone can call this method to generate the upgrading plan.
public fun submit_module_upgrade_plan<TokenT: copy, drop, store>(proposer_address: address, proposal_id: u64)
public fun submit_module_upgrade_plan<TokenT: copy + drop + store>(
proposer_address: address,
proposal_id: u64,
) acquires UpgradeModuleCapability {
let UpgradeModuleV2 { module_address, package_hash, version, enforced } = Dao::extract_proposal_action<
TokenT,
UpgradeModuleV2,
>(proposer_address, proposal_id);
let cap = borrow_global<UpgradeModuleCapability<TokenT>>(Token::token_address<TokenT>());
let account_address = PackageTxnManager::account_address(&cap.cap);
assert!(account_address == module_address, Errors::requires_capability(ERR_ADDRESS_MISSMATCH));
PackageTxnManager::submit_upgrade_plan_with_cap_v2(
&cap.cap,
package_hash,
version,
enforced,
);
}
let expected_states = vec<u8>(6);
include Dao::CheckProposalStates<TokenT, UpgradeModule>{expected_states};
let proposal = global<Dao::Proposal<TokenT, UpgradeModule>>(proposer_address);
aborts_if Option::is_none(proposal.action);
let action = proposal.action.vec[0];
include AbortIfUnableUpgrade<TokenT>{module_address: action.module_address};
pragma verify = false;
pragma aborts_if_is_strict;
pragma aborts_if_is_partial;