mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
contract/dao: Integration test port
This commit is contained in:
@@ -31,7 +31,7 @@ use darkfi_sdk::{
|
||||
pasta_prelude::*,
|
||||
pedersen_commitment_u64, poseidon_hash,
|
||||
util::{fp_mod_fv, fp_to_u64},
|
||||
Blind, FuncId, FuncRef, DAO_CONTRACT_ID, MONEY_CONTRACT_ID,
|
||||
BaseBlind, Blind, FuncId, FuncRef, DAO_CONTRACT_ID, MONEY_CONTRACT_ID,
|
||||
},
|
||||
pasta::pallas,
|
||||
};
|
||||
@@ -44,26 +44,19 @@ fn integration_test() -> Result<()> {
|
||||
init_logger();
|
||||
|
||||
// Holders this test will use:
|
||||
// * Faucet airdrops DRK
|
||||
// * Alice, Bob, and Charlie are members of the DAO.
|
||||
// * Rachel is the proposal recipient.
|
||||
// * Dao is the DAO wallet
|
||||
const HOLDERS: [Holder; 6] = [
|
||||
Holder::Faucet,
|
||||
Holder::Alice,
|
||||
Holder::Bob,
|
||||
Holder::Charlie,
|
||||
Holder::Rachel,
|
||||
Holder::Dao,
|
||||
];
|
||||
// * Rachel is the proposal recipient.
|
||||
const HOLDERS: [Holder; 5] =
|
||||
[Holder::Alice, Holder::Bob, Holder::Charlie, Holder::Dao, Holder::Rachel];
|
||||
|
||||
// Initialize harness
|
||||
let mut th = TestHarness::new(&["money".to_string(), "dao".to_string()], false).await?;
|
||||
let mut th = TestHarness::new(&HOLDERS, false).await?;
|
||||
|
||||
// We'll use the ALICE token as the DAO governance token
|
||||
let wallet = th.holders.get(&Holder::Alice).unwrap();
|
||||
let mint_authority = wallet.token_mint_authority;
|
||||
let token_blind = wallet.token_blind;
|
||||
let gov_token_blind = BaseBlind::random(&mut OsRng);
|
||||
|
||||
let auth_func_id = FuncRef {
|
||||
contract_id: *MONEY_CONTRACT_ID,
|
||||
@@ -73,7 +66,7 @@ fn integration_test() -> Result<()> {
|
||||
let token_attrs = TokenAttributes {
|
||||
auth_parent: auth_func_id,
|
||||
user_data: poseidon_hash([mint_authority.public.x(), mint_authority.public.y()]),
|
||||
blind: token_blind,
|
||||
blind: gov_token_blind,
|
||||
};
|
||||
let gov_token_id = token_attrs.to_token_id();
|
||||
|
||||
@@ -108,12 +101,20 @@ fn integration_test() -> Result<()> {
|
||||
info!("Stage 1. Creating DAO bulla");
|
||||
|
||||
info!("[Dao] Building DAO mint tx");
|
||||
let (dao_mint_tx, dao_mint_params) = th.dao_mint(&dao, &dao_keypair)?;
|
||||
let (dao_mint_tx, dao_mint_params, fee_params) =
|
||||
th.dao_mint(&Holder::Alice, &dao, &dao_keypair, current_block_height).await?;
|
||||
|
||||
for holder in &HOLDERS {
|
||||
info!("[{holder:?}] Executing DAO Mint tx");
|
||||
th.execute_dao_mint_tx(holder, &dao_mint_tx, &dao_mint_params, current_block_height)
|
||||
.await?;
|
||||
th.execute_dao_mint_tx(
|
||||
holder,
|
||||
dao_mint_tx.clone(),
|
||||
&dao_mint_params,
|
||||
&fee_params,
|
||||
current_block_height,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
th.assert_trees(&HOLDERS);
|
||||
@@ -121,35 +122,37 @@ fn integration_test() -> Result<()> {
|
||||
// =======================================
|
||||
// Airdrop some treasury tokens to the DAO
|
||||
// =======================================
|
||||
info!("Stage 2. Send Treasury token");
|
||||
|
||||
info!("[Faucet] Building DAO airdrop tx");
|
||||
info!("[Dao] Building DAO airdrop tx");
|
||||
let spend_hook =
|
||||
FuncRef { contract_id: *DAO_CONTRACT_ID, func_code: DaoFunction::Exec as u8 }
|
||||
.to_func_id();
|
||||
|
||||
let (airdrop_tx, airdrop_params) = th.airdrop_native(
|
||||
DRK_TOKEN_SUPPLY,
|
||||
&Holder::Dao,
|
||||
Some(spend_hook), // spend_hook
|
||||
Some(dao_mint_params.dao_bulla.inner()), // user_data
|
||||
)?;
|
||||
let (genesis_mint_tx, genesis_mint_params) = th
|
||||
.genesis_mint(
|
||||
&Holder::Dao,
|
||||
DRK_TOKEN_SUPPLY,
|
||||
Some(spend_hook),
|
||||
Some(dao_mint_params.dao_bulla.inner()),
|
||||
)
|
||||
.await?;
|
||||
|
||||
for holder in &HOLDERS {
|
||||
info!("[{holder:?}] Executing DAO airdrop tx");
|
||||
th.execute_airdrop_native_tx(
|
||||
th.execute_genesis_mint_tx(
|
||||
holder,
|
||||
&airdrop_tx,
|
||||
&airdrop_params,
|
||||
genesis_mint_tx.clone(),
|
||||
&genesis_mint_params,
|
||||
current_block_height,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
th.assert_trees(&HOLDERS);
|
||||
|
||||
// Gather the DAO owncoin
|
||||
th.gather_owncoin_from_output(&Holder::Dao, &airdrop_params.outputs[0], None)?;
|
||||
let _dao_tokens = &th.holders.get(&Holder::Dao).unwrap().unspent_money_coins;
|
||||
assert!(_dao_tokens.len() == 1);
|
||||
assert!(_dao_tokens[0].note.token_id == *DARK_TOKEN_ID);
|
||||
assert!(_dao_tokens[0].note.value == DRK_TOKEN_SUPPLY);
|
||||
|
||||
// ======================================
|
||||
// Mint the governance token to 3 holders
|
||||
@@ -157,79 +160,106 @@ fn integration_test() -> Result<()> {
|
||||
info!("Stage 3. Minting governance token");
|
||||
|
||||
info!("[Alice] Building governance token mint tx for Alice");
|
||||
let (a_token_mint_tx, a_token_mint_params, a_auth_token_mint_params) =
|
||||
th.token_mint(ALICE_GOV_SUPPLY, &Holder::Alice, &Holder::Alice, None, None)?;
|
||||
let (a_token_mint_tx, a_token_mint_params, a_auth_token_mint_params, a_fee_params) = th
|
||||
.token_mint(
|
||||
ALICE_GOV_SUPPLY,
|
||||
&Holder::Alice,
|
||||
&Holder::Alice,
|
||||
gov_token_blind,
|
||||
None,
|
||||
None,
|
||||
current_block_height,
|
||||
)
|
||||
.await?;
|
||||
|
||||
for holder in &HOLDERS {
|
||||
info!("[{holder:?}] Executing governance token mint tx for Alice");
|
||||
th.execute_token_mint_tx(
|
||||
holder,
|
||||
&a_token_mint_tx,
|
||||
a_token_mint_tx.clone(),
|
||||
&a_token_mint_params,
|
||||
&a_auth_token_mint_params,
|
||||
&a_fee_params,
|
||||
current_block_height,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
th.assert_trees(&HOLDERS);
|
||||
|
||||
// Gather owncoin
|
||||
th.gather_owncoin(
|
||||
&Holder::Alice,
|
||||
&a_token_mint_params.coin,
|
||||
&a_auth_token_mint_params.enc_note,
|
||||
None,
|
||||
)?;
|
||||
let _alice_tokens = &th.holders.get(&Holder::Alice).unwrap().unspent_money_coins;
|
||||
assert!(_alice_tokens.len() == 1);
|
||||
assert!(_alice_tokens[0].note.token_id == gov_token_id);
|
||||
assert!(_alice_tokens[0].note.value == ALICE_GOV_SUPPLY);
|
||||
|
||||
info!("[Alice] Building governance token mint tx for Bob");
|
||||
let (b_token_mint_tx, b_token_mint_params, b_auth_token_mint_params) =
|
||||
th.token_mint(BOB_GOV_SUPPLY, &Holder::Alice, &Holder::Bob, None, None)?;
|
||||
let (b_token_mint_tx, b_token_mint_params, b_auth_token_mint_params, b_fee_params) = th
|
||||
.token_mint(
|
||||
BOB_GOV_SUPPLY,
|
||||
&Holder::Alice,
|
||||
&Holder::Bob,
|
||||
gov_token_blind,
|
||||
None,
|
||||
None,
|
||||
current_block_height,
|
||||
)
|
||||
.await?;
|
||||
|
||||
for holder in &HOLDERS {
|
||||
info!("[{holder:?}] Executing governance token mint tx for Bob");
|
||||
th.execute_token_mint_tx(
|
||||
holder,
|
||||
&b_token_mint_tx,
|
||||
b_token_mint_tx.clone(),
|
||||
&b_token_mint_params,
|
||||
&b_auth_token_mint_params,
|
||||
&b_fee_params,
|
||||
current_block_height,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
th.assert_trees(&HOLDERS);
|
||||
|
||||
// Gather owncoin
|
||||
th.gather_owncoin(
|
||||
&Holder::Bob,
|
||||
&b_token_mint_params.coin,
|
||||
&b_auth_token_mint_params.enc_note,
|
||||
None,
|
||||
)?;
|
||||
let _bob_tokens = &th.holders.get(&Holder::Bob).unwrap().unspent_money_coins;
|
||||
assert!(_bob_tokens.len() == 1);
|
||||
assert!(_bob_tokens[0].note.token_id == gov_token_id);
|
||||
assert!(_bob_tokens[0].note.value == BOB_GOV_SUPPLY);
|
||||
|
||||
info!("[Alice] Building governance token mint tx for Charlie");
|
||||
let (c_token_mint_tx, c_token_mint_params, c_auth_token_mint_params) =
|
||||
th.token_mint(CHARLIE_GOV_SUPPLY, &Holder::Alice, &Holder::Charlie, None, None)?;
|
||||
let (c_token_mint_tx, c_token_mint_params, c_auth_token_mint_params, c_fee_params) = th
|
||||
.token_mint(
|
||||
CHARLIE_GOV_SUPPLY,
|
||||
&Holder::Alice,
|
||||
&Holder::Charlie,
|
||||
gov_token_blind,
|
||||
None,
|
||||
None,
|
||||
current_block_height,
|
||||
)
|
||||
.await?;
|
||||
|
||||
for holder in &HOLDERS {
|
||||
info!("[{holder:?}] Executing governance token mint tx for Charlie");
|
||||
th.execute_token_mint_tx(
|
||||
holder,
|
||||
&c_token_mint_tx,
|
||||
c_token_mint_tx.clone(),
|
||||
&c_token_mint_params,
|
||||
&c_auth_token_mint_params,
|
||||
&c_fee_params,
|
||||
current_block_height,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
th.assert_trees(&HOLDERS);
|
||||
|
||||
// Gather owncoin
|
||||
th.gather_owncoin(
|
||||
&Holder::Charlie,
|
||||
&c_token_mint_params.coin,
|
||||
&c_auth_token_mint_params.enc_note,
|
||||
None,
|
||||
)?;
|
||||
let _charlie_tokens = &th.holders.get(&Holder::Charlie).unwrap().unspent_money_coins;
|
||||
assert!(_charlie_tokens.len() == 1);
|
||||
assert!(_charlie_tokens[0].note.token_id == gov_token_id);
|
||||
assert!(_charlie_tokens[0].note.value == CHARLIE_GOV_SUPPLY);
|
||||
|
||||
// ================
|
||||
// Dao::Propose
|
||||
@@ -255,19 +285,28 @@ fn integration_test() -> Result<()> {
|
||||
// It's up to the auth module to decide what to do with it.
|
||||
let user_data = pallas::Base::ZERO;
|
||||
|
||||
let (propose_tx, propose_params, propose_info) = th.dao_propose(
|
||||
&Holder::Alice,
|
||||
&proposal_coinattrs,
|
||||
user_data,
|
||||
&dao,
|
||||
&dao_mint_params.dao_bulla,
|
||||
current_block_height,
|
||||
)?;
|
||||
let (propose_tx, (propose_params, fee_params), propose_info) = th
|
||||
.dao_propose(
|
||||
&Holder::Alice,
|
||||
&proposal_coinattrs,
|
||||
user_data,
|
||||
&dao,
|
||||
&dao_mint_params.dao_bulla,
|
||||
current_block_height,
|
||||
)
|
||||
.await?;
|
||||
|
||||
for holder in &HOLDERS {
|
||||
info!("[{holder:?}] Executing DAO proposal tx");
|
||||
th.execute_dao_propose_tx(holder, &propose_tx, &propose_params, current_block_height)
|
||||
.await?;
|
||||
th.execute_dao_propose_tx(
|
||||
holder,
|
||||
propose_tx.clone(),
|
||||
&propose_params,
|
||||
&fee_params,
|
||||
current_block_height,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
th.assert_trees(&HOLDERS);
|
||||
@@ -279,56 +318,75 @@ fn integration_test() -> Result<()> {
|
||||
info!("Stage 5. Start voting");
|
||||
|
||||
info!("[Alice] Building vote tx (yes)");
|
||||
let (alice_vote_tx, alice_vote_params) = th.dao_vote(
|
||||
&Holder::Alice,
|
||||
true,
|
||||
&dao,
|
||||
&dao_keypair,
|
||||
&propose_info,
|
||||
&propose_params.proposal_bulla,
|
||||
current_block_height,
|
||||
)?;
|
||||
let (alice_vote_tx, alice_vote_params, alice_vote_fee_params) = th
|
||||
.dao_vote(
|
||||
&Holder::Alice,
|
||||
true,
|
||||
&dao,
|
||||
&dao_keypair,
|
||||
&propose_info,
|
||||
&propose_params.proposal_bulla,
|
||||
current_block_height,
|
||||
)
|
||||
.await?;
|
||||
|
||||
info!("[Bob] Building vote tx (no)");
|
||||
let (bob_vote_tx, bob_vote_params) = th.dao_vote(
|
||||
&Holder::Bob,
|
||||
false,
|
||||
&dao,
|
||||
&dao_keypair,
|
||||
&propose_info,
|
||||
&propose_params.proposal_bulla,
|
||||
current_block_height,
|
||||
)?;
|
||||
let (bob_vote_tx, bob_vote_params, bob_vote_fee_params) = th
|
||||
.dao_vote(
|
||||
&Holder::Bob,
|
||||
false,
|
||||
&dao,
|
||||
&dao_keypair,
|
||||
&propose_info,
|
||||
&propose_params.proposal_bulla,
|
||||
current_block_height,
|
||||
)
|
||||
.await?;
|
||||
|
||||
info!("[Charlie] Building vote tx (yes)");
|
||||
let (charlie_vote_tx, charlie_vote_params) = th.dao_vote(
|
||||
&Holder::Charlie,
|
||||
true,
|
||||
&dao,
|
||||
&dao_keypair,
|
||||
&propose_info,
|
||||
&propose_params.proposal_bulla,
|
||||
current_block_height,
|
||||
)?;
|
||||
let (charlie_vote_tx, charlie_vote_params, charlie_vote_fee_params) = th
|
||||
.dao_vote(
|
||||
&Holder::Charlie,
|
||||
true,
|
||||
&dao,
|
||||
&dao_keypair,
|
||||
&propose_info,
|
||||
&propose_params.proposal_bulla,
|
||||
current_block_height,
|
||||
)
|
||||
.await?;
|
||||
|
||||
for holder in &HOLDERS {
|
||||
info!("[{holder:?}] Executing Alice vote tx");
|
||||
th.execute_dao_vote_tx(
|
||||
holder,
|
||||
&alice_vote_tx,
|
||||
alice_vote_tx.clone(),
|
||||
&alice_vote_params,
|
||||
&alice_vote_fee_params,
|
||||
current_block_height,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
|
||||
info!("[{holder:?}] Executing Bob vote tx");
|
||||
th.execute_dao_vote_tx(holder, &bob_vote_tx, &bob_vote_params, current_block_height)
|
||||
.await?;
|
||||
th.execute_dao_vote_tx(
|
||||
holder,
|
||||
bob_vote_tx.clone(),
|
||||
&bob_vote_params,
|
||||
&bob_vote_fee_params,
|
||||
current_block_height,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
|
||||
info!("[{holder:?}] Executing Charlie vote tx");
|
||||
th.execute_dao_vote_tx(
|
||||
holder,
|
||||
&charlie_vote_tx,
|
||||
charlie_vote_tx.clone(),
|
||||
&charlie_vote_params,
|
||||
&charlie_vote_fee_params,
|
||||
current_block_height,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
@@ -407,46 +465,44 @@ fn integration_test() -> Result<()> {
|
||||
info!("Stage 6. Execute the vote");
|
||||
|
||||
info!("[Dao] Building Dao::Exec tx");
|
||||
let (exec_tx, xfer_params, exec_params) = th.dao_exec(
|
||||
&dao,
|
||||
&dao_mint_params.dao_bulla,
|
||||
&propose_info,
|
||||
proposal_coinattrs,
|
||||
total_yes_vote_value,
|
||||
total_all_vote_value,
|
||||
total_yes_vote_blind,
|
||||
total_all_vote_blind,
|
||||
)?;
|
||||
let (exec_tx, xfer_params, exec_params, exec_fee_params) = th
|
||||
.dao_exec(
|
||||
&Holder::Alice,
|
||||
&dao,
|
||||
&dao_mint_params.dao_bulla,
|
||||
&propose_info,
|
||||
proposal_coinattrs,
|
||||
total_yes_vote_value,
|
||||
total_all_vote_value,
|
||||
total_yes_vote_blind,
|
||||
total_all_vote_blind,
|
||||
current_block_height,
|
||||
)
|
||||
.await?;
|
||||
|
||||
for holder in &HOLDERS {
|
||||
info!("[{holder:?}] Executing Dao::Exec tx");
|
||||
th.execute_dao_exec_tx(
|
||||
holder,
|
||||
&exec_tx,
|
||||
exec_tx.clone(),
|
||||
&xfer_params,
|
||||
&exec_params,
|
||||
&exec_fee_params,
|
||||
current_block_height,
|
||||
true,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
th.assert_trees(&HOLDERS);
|
||||
|
||||
// Gather the coins
|
||||
th.gather_owncoin_from_output(&Holder::Rachel, &xfer_params.outputs[0], None)?;
|
||||
th.gather_owncoin_from_output(&Holder::Dao, &xfer_params.outputs[1], None)?;
|
||||
|
||||
let rachel_wallet = th.holders.get(&Holder::Rachel).unwrap();
|
||||
assert!(rachel_wallet.unspent_money_coins[0].note.value == PROPOSAL_AMOUNT);
|
||||
assert!(rachel_wallet.unspent_money_coins[0].note.token_id == drk_token_id);
|
||||
|
||||
// FIXME: The harness doesn't register that we spent the first coin on the proposal.
|
||||
let dao_wallet = th.holders.get(&Holder::Dao).unwrap();
|
||||
assert!(dao_wallet.unspent_money_coins[1].note.value == DRK_TOKEN_SUPPLY - PROPOSAL_AMOUNT);
|
||||
assert!(dao_wallet.unspent_money_coins[1].note.token_id == drk_token_id);
|
||||
|
||||
// Stats
|
||||
th.statistics();
|
||||
assert!(dao_wallet.unspent_money_coins[0].note.value == DRK_TOKEN_SUPPLY - PROPOSAL_AMOUNT);
|
||||
assert!(dao_wallet.unspent_money_coins[0].note.token_id == drk_token_id);
|
||||
|
||||
// Thanks for reading
|
||||
Ok(())
|
||||
|
||||
@@ -101,6 +101,7 @@ pub enum Holder {
|
||||
Bob,
|
||||
Charlie,
|
||||
Dao,
|
||||
Rachel,
|
||||
}
|
||||
|
||||
/// Wallet instance for a single [`Holder`]
|
||||
|
||||
@@ -45,6 +45,8 @@ impl TestHarness {
|
||||
&mut self,
|
||||
holder: &Holder,
|
||||
amount: u64,
|
||||
spend_hook: Option<FuncId>,
|
||||
user_data: Option<pallas::Base>,
|
||||
) -> Result<(Transaction, MoneyGenesisMintParamsV1)> {
|
||||
let wallet = self.holders.get(holder).unwrap();
|
||||
|
||||
@@ -55,8 +57,8 @@ impl TestHarness {
|
||||
let builder = GenesisMintCallBuilder {
|
||||
keypair: wallet.keypair,
|
||||
amount,
|
||||
spend_hook: FuncId::none(),
|
||||
user_data: pallas::Base::ZERO,
|
||||
spend_hook: spend_hook.unwrap_or(FuncId::none()),
|
||||
user_data: user_data.unwrap_or(pallas::Base::ZERO),
|
||||
mint_zkbin: mint_zkbin.clone(),
|
||||
mint_pk: mint_pk.clone(),
|
||||
};
|
||||
|
||||
@@ -52,6 +52,7 @@ impl TestHarness {
|
||||
amount: u64,
|
||||
holder: &Holder,
|
||||
recipient: &Holder,
|
||||
token_blind: BaseBlind,
|
||||
spend_hook: Option<FuncId>,
|
||||
user_data: Option<pallas::Base>,
|
||||
block_height: u64,
|
||||
@@ -79,7 +80,6 @@ impl TestHarness {
|
||||
.to_func_id();
|
||||
|
||||
let (mint_auth_x, mint_auth_y) = mint_authority.public.xy();
|
||||
let token_blind = BaseBlind::random(&mut OsRng);
|
||||
|
||||
let token_attrs = TokenAttributes {
|
||||
auth_parent: auth_func_id,
|
||||
|
||||
Reference in New Issue
Block a user