0x1::TreasuryWithdrawDaoProposal
TreasuryWithdrawDaoProposal is a dao proposal for withdraw Token from Treasury.
WrappedWithdrawCapability
WithdrawToken
plugin
propose_withdraw
execute_withdraw_proposal
withdraw_for_block_reward
use 0x1::CoreAddresses;
use 0x1::Dao;
use 0x1::Errors;
use 0x1::Signer;
use 0x1::Token;
use 0x1::Treasury;
WrappedWithdrawCapability
A wrapper of Token MintCapability.
struct WrappedWithdrawCapability<TokenT> has key
cap: Treasury::WithdrawCapability<TokenT>
WithdrawToken
WithdrawToken request.
struct WithdrawToken has copy, drop, store
receiver: address
amount: u128
period: u64
const ERR_NOT_AUTHORIZED: u64 = 101;
Only receiver can execute TreasuryWithdrawDaoProposal
const ERR_NEED_RECEIVER_TO_EXECUTE: u64 = 102;
The withdraw amount of propose is too many.
const ERR_TOO_MANY_WITHDRAW_AMOUNT: u64 = 103;
plugin
Plugin method of the module. Should be called by token issuer.
public fun plugin<TokenT: store>(signer: &signer, cap: Treasury::WithdrawCapability<TokenT>)
public fun plugin<TokenT: store>(signer: &signer, cap: Treasury::WithdrawCapability<TokenT>) {
let token_issuer = Token::token_address<TokenT>();
assert!(Signer::address_of(signer) == token_issuer, Errors::requires_address(ERR_NOT_AUTHORIZED));
move_to(signer, WrappedWithdrawCapability<TokenT> { cap: cap });
}
pragma aborts_if_is_partial = false;
let sender = Signer::address_of(signer);
aborts_if sender != Token::SPEC_TOKEN_TEST_ADDRESS();
aborts_if !exists<Treasury::WithdrawCapability<TokenT>>(sender);
aborts_if exists<WrappedWithdrawCapability<TokenT>>(sender);
ensures !exists<Treasury::WithdrawCapability<TokenT>>(sender);
ensures exists<WrappedWithdrawCapability<TokenT>>(sender);
propose_withdraw
Entrypoint for the proposal.
public fun propose_withdraw<TokenT: copy, drop, store>(signer: &signer, receiver: address, amount: u128, period: u64, exec_delay: u64)
public fun propose_withdraw<TokenT: copy + drop + store>(signer: &signer, receiver: address, amount: u128, period: u64, exec_delay: u64) {
let quorum_votes = Dao::quorum_votes<TokenT>();
assert!(amount <= quorum_votes, Errors::invalid_argument(ERR_TOO_MANY_WITHDRAW_AMOUNT));
Dao::propose<TokenT, WithdrawToken>(
signer,
WithdrawToken { receiver, amount, period },
exec_delay,
);
}
pragma aborts_if_is_partial = false;
let quorum_votes = Dao::spec_quorum_votes<TokenT>();
aborts_if amount > quorum_votes;
include Dao::AbortIfDaoConfigNotExist<TokenT>;
include Dao::AbortIfDaoInfoNotExist<TokenT>;
aborts_if !exists<Timestamp::CurrentTimeMilliseconds>(CoreAddresses::SPEC_GENESIS_ADDRESS());
aborts_if exec_delay > 0 && exec_delay < Dao::spec_dao_config<TokenT>().min_action_delay;
include Dao::CheckQuorumVotes<TokenT>;
let sender = Signer::address_of(signer);
aborts_if exists<Dao::Proposal<TokenT, WithdrawToken>>(sender);
execute_withdraw_proposal
Once the proposal is agreed, anyone can call the method to make the proposal happen.
public fun execute_withdraw_proposal<TokenT: copy, drop, store>(signer: &signer, proposer_address: address, proposal_id: u64)
public fun execute_withdraw_proposal<TokenT: copy + drop + store>(
signer: &signer,
proposer_address: address,
proposal_id: u64,
) acquires WrappedWithdrawCapability {
let WithdrawToken { receiver, amount, period } = Dao::extract_proposal_action<TokenT, WithdrawToken>(
proposer_address,
proposal_id,
);
assert!(receiver == Signer::address_of(signer), Errors::requires_address(ERR_NEED_RECEIVER_TO_EXECUTE));
let cap = borrow_global_mut<WrappedWithdrawCapability<TokenT>>(Token::token_address<TokenT>());
let linear_cap = Treasury::issue_linear_withdraw_capability<TokenT>(&mut cap.cap, amount, period);
Treasury::add_linear_withdraw_capability(signer, linear_cap);
}
pragma aborts_if_is_partial = true;
let expected_states = vec<u8>(6);
include Dao::CheckProposalStates<TokenT, WithdrawToken>{expected_states};
let proposal = global<Dao::Proposal<TokenT, WithdrawToken>>(proposer_address);
aborts_if Option::is_none(proposal.action);
aborts_if !exists<WrappedWithdrawCapability<TokenT>>(Token::SPEC_TOKEN_TEST_ADDRESS());
withdraw_for_block_reward
Provider a port for get block reward STC from Treasury, only genesis account can invoke this function. The TreasuryWithdrawCapability is locked in TreasuryWithdrawDaoProposal, and only can withdraw by DAO proposal. This approach is not graceful, but restricts the operation to genesis accounts only, so there are no security issues either.
public fun withdraw_for_block_reward<TokenT: store>(signer: &signer, reward: u128): Token::Token<TokenT>
public fun withdraw_for_block_reward<TokenT: store>(signer: &signer, reward: u128):Token<TokenT> acquires WrappedWithdrawCapability {
CoreAddresses::assert_genesis_address(signer);
let cap = borrow_global_mut<WrappedWithdrawCapability<TokenT>>(Signer::address_of(signer));
Treasury::withdraw_with_capability(&mut cap.cap, reward)
}
pragma verify = false;
pragma aborts_if_is_strict;
pragma aborts_if_is_partial;