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

[audit] 3. Users can inflate their voting power by registering duplicate NFT token IDs #864

Merged
merged 2 commits into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 0 additions & 4 deletions contracts/external/cw-tokenfactory-issuer/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// Ignore integration tests for code coverage since there will be problems with dynamic linking libosmosistesttube
// and also, tarpaulin will not be able read coverage out of wasm binary anyway
#![cfg(not(tarpaulin))]

#[cfg(feature = "test-tube")]
mod cases;
#[cfg(feature = "test-tube")]
Expand Down
14 changes: 8 additions & 6 deletions contracts/external/dao-migrator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

Here is the [discussion](https://github.com/DA0-DA0/dao-contracts/discussions/607).

A migrator module for a DAO DAO DAO which handles migration for DAO modules
A migrator module for a DAO DAO DAO which handles migration for DAO modules
and test it went successfully.

DAO core migration is handled by a proposal, which adds this module and do
Expand All @@ -14,6 +14,7 @@ If custom module is found, this TX fails and migration is cancelled, custom
module requires a custom migration to be done by the DAO.

# General idea

1. Proposal is made to migrate DAO core to V2, which also adds this module to the DAO.
2. On init of this contract, a callback is fired to do the migration.
3. Then we check to make sure the DAO doesn't have custom modules.
Expand All @@ -23,9 +24,10 @@ module requires a custom migration to be done by the DAO.
7. In any case where 1 migration fails, we fail the whole TX.

# Important notes
* custom modules cannot reliably be migrated by this contract,
because of that we fail the process to avoid any unwanted results.

* If any module migration fails we fail the whole thing,
this is to make sure that we either have a fully working V2,
or we do nothing and make sure the DAO is operational at any time.
- custom modules cannot reliably be migrated by this contract,
because of that we fail the process to avoid any unwanted results.

- If any module migration fails we fail the whole thing,
this is to make sure that we either have a fully working V2,
or we do nothing and make sure the DAO is operational at any time.
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl SuiteBuilder {
if let Some(candidates) = self.with_proposal {
suite
.propose(
&suite.sender(),
suite.sender(),
(0..candidates)
.map(|_| vec![unimportant_message()])
.collect(),
Expand Down
6 changes: 5 additions & 1 deletion contracts/voting/dao-voting-onft-staked/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,14 @@ pub fn execute_confirm_stake(
deps: DepsMut,
env: Env,
info: MessageInfo,
token_ids: Vec<String>,
mut token_ids: Vec<String>,
) -> Result<Response, ContractError> {
let config = CONFIG.load(deps.storage)?;

// de-duplicate token IDs to prevent double-counting exploit
Copy link
Collaborator

@bekauz bekauz Aug 11, 2024

Choose a reason for hiding this comment

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

@NoahSaso maybe we can switch this to a set eventually?

token_ids.sort();
token_ids.dedup();

// verify sender prepared and transferred all the tokens
let sender_prepared_all = token_ids
.iter()
Expand Down
19 changes: 19 additions & 0 deletions contracts/voting/dao-voting-onft-staked/src/testing/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,25 @@ fn test_stake_tokens() -> anyhow::Result<()> {
assert_eq!(total, Uint128::new(1));
assert_eq!(personal, Uint128::new(1));

// Registering duplicate token IDs does not provide more voting power.
mint_nft(&mut app, &nft, STAKER, "2")?;
prepare_stake_nft(&mut app, &module, STAKER, "2")?;
send_nft(&mut app, &nft, "2", STAKER, module.as_str())?;
app.execute_contract(
Addr::unchecked(STAKER),
module.clone(),
&ExecuteMsg::ConfirmStake {
token_ids: vec!["2".to_string(), "2".to_string(), "2".to_string()],
},
&[],
)?;

app.update_block(next_block);

let (total, personal) = query_total_and_voting_power(&app, &module, STAKER, None)?;
assert_eq!(total, Uint128::new(2));
assert_eq!(personal, Uint128::new(2));

Ok(())
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
// Ignore integration tests for code coverage since there will be problems with dynamic linking libosmosistesttube
// and also, tarpaulin will not be able read coverage out of wasm binary anyway
#![cfg(not(tarpaulin))]

mod integration_tests;
mod test_env;
4 changes: 0 additions & 4 deletions packages/dao-testing/src/test_tube/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// Ignore integration tests for code coverage since there will be problems with dynamic linking libosmosistesttube
// and also, tarpaulin will not be able read coverage out of wasm binary anyway
#![cfg(not(tarpaulin))]

// Integrationg tests using an actual chain binary, requires
// the "test-tube" feature to be enabled
// cargo test --features test-tube
Expand Down
Loading