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 Fixes and Improvements #742

Merged
merged 59 commits into from
Sep 15, 2023
Merged

Audit Fixes and Improvements #742

merged 59 commits into from
Sep 15, 2023

Conversation

JakeHartnell
Copy link
Member

@JakeHartnell JakeHartnell commented Sep 2, 2023

Address most of the issues from the recent smart contract audit, also fixes one or two things they didn't catch. Many improvements across the board.

Additionally:

Major changes from the current development version:

  • dao-voting-native-staked and dao-voting-token-factory-staked have been merged into one contract to reduce code duplication. When using an existing token, a new cw_tokenfactory_issuer is no longer instantiated as it was pointless and it would be impossible to garuntee if the admin would be set correctly.
  • The API of cw_tokenfactory_issuer has been greatly simplified.
  • cw_tokenfactory_issuer uses cw_ownable to implement two-step ownership transfer, as well as to allow for DAOs to easily reject ownership altogether.
  • dao-voting-cw721-staked is now consistent with the other voting modules in terms of not taking an owner, the owner of a voting module should always be the DAO.
  • Advanced features such as freezing, denylist, and more are disabled by default in cw_tokenfactory_issuer. DAOs must explicitly vote to enable them later so everyone can see what they are getting into.
  • Hooks are now properly dispatched during staking and unstaking. Additionally, hooks have been merged into a new dao-hooks package to allow for better code reuse. A new DaoHooks enum contains all hooks used in the codebase to make it easy to write generic contracts leveraging any DAO hook.
  • Better validation with more code reuse.
  • Unsetting the BeforeSendHook, renouncing ownership, and disabling Token Factory admin have been documented and tested.

In addition, many other improvements have been added, including numerous small informational issues (non-critical) mentioned in the audit.

JakeHartnell and others added 30 commits September 2, 2023 23:19
sg721 has two addresses that control it. The `minter` which can mint
NFTs, and the `creator` which can update collection metadata and
royalties.

We now set both of those to be the DAO.
Many of these methods are not needed thanks to Authz.
DAOs may wish to disable the BeforeSendHook at some point, or
potentially set it to a custom cosmwasm contract if they wish to
customize functionality a bit more.

Modifies the SetBeforeSendHook method to allow for this, and adds tests
that it's indeed possible to set it to nil.
These are powerful features, but many may not want them as they can be
abused. DAOs that want these features will have to explicitly enable
them via a governance prop.
@codecov
Copy link

codecov bot commented Sep 9, 2023

Welcome to Codecov 🎉

Once merged to your default branch, Codecov will compare your coverage reports and display the results in this comment.

Thanks for integrating Codecov - We've got you covered ☂️

@JakeHartnell JakeHartnell changed the title Audit Fixes and Improvements (part 1) Audit Fixes and Improvements Sep 12, 2023
Comment on lines 69 to 76
// Validate denom by checking supply
let supply: Coin = deps.querier.query_supply(msg.denom.to_string())?;
println!("supply {:?}", supply);
if Uint128::is_zero(&supply.amount) {
return Err(ContractError::InvalidDenom {});
}

// Validate active threshold

Choose a reason for hiding this comment

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

The fix looks good to me! There is just a println remaining in line 71 that looks like its left over from debugging

Copy link
Member Author

Choose a reason for hiding this comment

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

Silly me! Thanks for catching that.

Copy link
Member

@NoahSaso NoahSaso left a comment

Choose a reason for hiding this comment

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

damn beast.

@JakeHartnell JakeHartnell merged commit 3518a28 into development Sep 15, 2023
8 checks passed
@JakeHartnell JakeHartnell deleted the audit-fixes branch September 15, 2023 01:57
Comment on lines +82 to +98
pub fn execute_stake_hook(
deps: DepsMut,
_env: Env,
_info: MessageInfo,
stake_hook: StakeChangedHookMsg,
) -> Result<Response, ContractError> {
match stake_hook {
StakeChangedHookMsg::Stake { .. } => {
let mut count = STAKE_COUNTER.load(deps.storage)?;
count += Uint128::new(1);
STAKE_COUNTER.save(deps.storage, &count)?;
}
StakeChangedHookMsg::Unstake { .. } => {
let mut count = STAKE_COUNTER.load(deps.storage)?;
count += Uint128::new(1);
STAKE_COUNTER.save(deps.storage, &count)?;
}

Choose a reason for hiding this comment

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

Both Stake and Unstake adding to the counter look like a mistake unless you are tracking something like "total number of operations". Can you please check?

Copy link
Member Author

Choose a reason for hiding this comment

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

Total number of operations.

Comment on lines +694 to +715
VALIDATE_ABSOLUTE_COUNT_FOR_NEW_NFT_CONTRACTS => {
// Check that absolute count is not greater than supply
// NOTE: we have to check this in a reply as it is potentially possible
// to include non-mint messages in `initial_nfts`.
if let Some(ActiveThreshold::AbsoluteCount { count }) =
ACTIVE_THRESHOLD.may_load(deps.storage)?
{
// Load config for nft contract address
let collection_addr = CONFIG.load(deps.storage)?.nft_address;

// Query the total supply of the NFT contract
let supply: NumTokensResponse = deps
.querier
.query_wasm_smart(collection_addr, &Cw721QueryMsg::NumTokens {})?;

// Chec the count is not greater than supply
if count > Uint128::new(supply.count.into()) {
return Err(ContractError::InvalidActiveCount {});
}
}
Ok(Response::new())
}

Choose a reason for hiding this comment

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

This only partially remediates issue 7; there can still be a supply of zero NFTs if an ActiveThreshold::Percentage is in place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consistent Voting Power Change hook interfaces
5 participants