cosmwasm: replace cw_storage in cw_wormhole

This commit is contained in:
Obie Kaku 2024-12-20 11:35:35 -06:00
parent 1dbe8459b9
commit 42c5c141b0
8 changed files with 51 additions and 110 deletions

2
cosmwasm/Cargo.lock generated
View File

@ -2678,8 +2678,8 @@ version = "0.1.0"
dependencies = [
"cosmwasm-schema",
"cosmwasm-std",
"cosmwasm-storage",
"cw-multi-test",
"cw-storage-plus 0.13.4",
"generic-array",
"hex",
"k256",

View File

@ -16,7 +16,7 @@ use cw_wormhole::{
},
error::ContractError,
msg::{ExecuteMsg as WormholeExecuteMsg, QueryMsg as WormholeQueryMsg},
state::{vaa_archive_add, vaa_archive_check, GovernancePacket, ParsedVAA},
state::{vaa_archive_check, GovernancePacket, ParsedVAA, VAA_ARCHIVE},
};
#[cfg(not(feature = "library"))]
@ -643,7 +643,7 @@ fn parse_and_archive_vaa(
if vaa_archive_check(deps.storage, vaa.hash.as_slice()) {
return ContractError::VaaAlreadyExecuted.std_err();
}
vaa_archive_add(deps.storage, vaa.hash.as_slice())?;
VAA_ARCHIVE.save(deps.storage, vaa.hash.as_slice(), &true)?;
// check if vaa is from governance
if is_governance_emitter(&state, vaa.emitter_chain, &vaa.emitter_address) {

View File

@ -5,7 +5,7 @@ use cw_wormhole::{
execute as core_execute, instantiate as core_instantiate, migrate as core_migrate,
query as core_query, query_parse_and_verify_vaa,
},
state::config_read,
state::CONFIG,
};
use wormhole_sdk::{
ibc_receiver::{Action, GovernancePacket},
@ -87,8 +87,8 @@ fn handle_vaa(deps: DepsMut, env: Env, vaa: Binary) -> anyhow::Result<Event> {
.context("failed to parse governance packet")?;
// validate the governance VAA is directed to this chain
let state = config_read(deps.storage)
.load()
let state = CONFIG
.load(deps.storage)
.context("failed to load contract config")?;
ensure!(
govpacket.chain == Chain::from(state.chain_id),

View File

@ -20,7 +20,7 @@ default = ["full"]
[dependencies]
cosmwasm-std = { version = "1.0.0" }
cosmwasm-storage = { version = "1.0.0" }
cw-storage-plus = "0.13.2"
cosmwasm-schema = { version = "1.0.0" }
schemars = "0.8.8"
serde = { version = "1.0.137", default-features = false, features = ["derive"] }

View File

@ -14,9 +14,9 @@ use crate::{
InstantiateMsg, MigrateMsg, QueryMsg,
},
state::{
config, config_read, guardian_set_get, guardian_set_set, sequence_read, sequence_set,
vaa_archive_add, vaa_archive_check, ConfigInfo, ContractUpgrade, GovernancePacket,
GuardianAddress, GuardianSetInfo, GuardianSetUpgrade, ParsedVAA, SetFee, TransferFee,
vaa_archive_check, ConfigInfo, ContractUpgrade, GovernancePacket, GuardianAddress,
GuardianSetInfo, GuardianSetUpgrade, ParsedVAA, SetFee, TransferFee, CONFIG, GUARDIAN_SET,
SEQUENCE, VAA_ARCHIVE,
},
};
@ -74,10 +74,10 @@ pub fn instantiate(
chain_id: msg.chain_id,
fee_denom: msg.fee_denom,
};
config(deps.storage).save(&state)?;
CONFIG.save(deps.storage, &state)?;
// Add initial guardian set to storage
guardian_set_set(
GUARDIAN_SET.save(
deps.storage,
state.guardian_set_index,
&msg.initial_guardian_set,
@ -109,10 +109,10 @@ fn handle_submit_vaa(
_info: MessageInfo,
data: &[u8],
) -> StdResult<Response> {
let state = config_read(deps.storage).load()?;
let state = CONFIG.load(deps.storage)?;
let vaa = parse_and_verify_vaa(deps.storage, data, env.block.time.seconds())?;
vaa_archive_add(deps.storage, vaa.hash.as_slice())?;
VAA_ARCHIVE.save(deps.storage, vaa.hash.as_slice(), &true)?;
if state.gov_chain == vaa.emitter_chain && state.gov_address == vaa.emitter_address {
if state.guardian_set_index != vaa.guardian_set_index {
@ -128,7 +128,7 @@ fn handle_submit_vaa(
fn handle_governance_payload(deps: DepsMut, env: Env, data: &[u8]) -> StdResult<Response> {
let gov_packet = GovernancePacket::deserialize(data)?;
let state = config_read(deps.storage).load()?;
let state = CONFIG.load(deps.storage)?;
let module = String::from_utf8(gov_packet.module).unwrap();
let module: String = module.chars().filter(|c| c != &'\0').collect();
@ -173,9 +173,10 @@ fn parse_and_verify_vaa(
}
// Load and check guardian set
let guardian_set = guardian_set_get(storage, vaa.guardian_set_index);
let guardian_set: GuardianSetInfo =
guardian_set.or_else(|_| ContractError::InvalidGuardianSetIndex.std_err())?;
let guardian_set = GUARDIAN_SET.may_load(storage, vaa.guardian_set_index);
let guardian_set: GuardianSetInfo = guardian_set
.or_else(|_| ContractError::InvalidGuardianSetIndex.std_err())?
.ok_or_else(|| ContractError::InvalidGuardianSetIndex.std())?;
if guardian_set.expiration_time != 0 && guardian_set.expiration_time < block_time {
return ContractError::GuardianSetExpired.std_err();
@ -232,7 +233,7 @@ fn vaa_update_guardian_set(deps: DepsMut, env: Env, data: &[u8]) -> StdResult<Re
5 [][20]uint8 guardian addresses
*/
let mut state = config_read(deps.storage).load()?;
let mut state = CONFIG.load(deps.storage)?;
let GuardianSetUpgrade {
new_guardian_set_index,
@ -247,13 +248,13 @@ fn vaa_update_guardian_set(deps: DepsMut, env: Env, data: &[u8]) -> StdResult<Re
state.guardian_set_index = new_guardian_set_index;
guardian_set_set(deps.storage, state.guardian_set_index, &new_guardian_set)?;
GUARDIAN_SET.save(deps.storage, state.guardian_set_index, &new_guardian_set)?;
config(deps.storage).save(&state)?;
CONFIG.save(deps.storage, &state)?;
let mut old_guardian_set = guardian_set_get(deps.storage, old_guardian_set_index)?;
let mut old_guardian_set = GUARDIAN_SET.load(deps.storage, old_guardian_set_index)?;
old_guardian_set.expiration_time = env.block.time.seconds() + state.guardian_set_expirity;
guardian_set_set(deps.storage, old_guardian_set_index, &old_guardian_set)?;
GUARDIAN_SET.save(deps.storage, old_guardian_set_index, &old_guardian_set)?;
Ok(Response::new()
.add_attribute("action", "guardian_set_change")
@ -278,12 +279,12 @@ fn vaa_update_contract(_deps: DepsMut, env: Env, data: &[u8]) -> StdResult<Respo
}
pub fn handle_set_fee(deps: DepsMut, _env: Env, data: &[u8]) -> StdResult<Response> {
let mut state = config_read(deps.storage).load()?;
let mut state = CONFIG.load(deps.storage)?;
let set_fee_msg = SetFee::deserialize(data, state.fee_denom.clone())?;
// Save new fees
state.fee = set_fee_msg.fee;
config(deps.storage).save(&state)?;
CONFIG.save(deps.storage, &state)?;
Ok(Response::new()
.add_attribute("action", "fee_change")
@ -292,7 +293,7 @@ pub fn handle_set_fee(deps: DepsMut, _env: Env, data: &[u8]) -> StdResult<Respon
}
pub fn handle_transfer_fee(deps: DepsMut, _env: Env, data: &[u8]) -> StdResult<Response> {
let state = config_read(deps.storage).load()?;
let state = CONFIG.load(deps.storage)?;
let transfer_msg = TransferFee::deserialize(data, state.fee_denom)?;
@ -309,7 +310,7 @@ fn handle_post_message(
message: &[u8],
nonce: u32,
) -> StdResult<Response> {
let state = config_read(deps.storage).load()?;
let state = CONFIG.load(deps.storage)?;
let fee = state.fee;
// Check fee
@ -318,8 +319,10 @@ fn handle_post_message(
}
let emitter = extend_address_to_32(&deps.api.addr_canonicalize(info.sender.as_str())?);
let sequence = sequence_read(deps.storage, emitter.as_slice());
sequence_set(deps.storage, emitter.as_slice(), sequence + 1)?;
let sequence = SEQUENCE
.may_load(deps.storage, emitter.as_slice())?
.ok_or(ContractError::SequenceNotFound.std())?;
SEQUENCE.save(deps.storage, emitter.as_slice(), &(sequence + 1))?;
Ok(Response::new()
.add_attribute("message.message", hex::encode(message))
@ -345,8 +348,8 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
}
pub fn query_guardian_set_info(deps: Deps) -> StdResult<GuardianSetInfoResponse> {
let state = config_read(deps.storage).load()?;
let guardian_set = guardian_set_get(deps.storage, state.guardian_set_index)?;
let state = CONFIG.load(deps.storage)?;
let guardian_set = GUARDIAN_SET.load(deps.storage, state.guardian_set_index)?;
let res = GuardianSetInfoResponse {
guardian_set_index: state.guardian_set_index,
addresses: guardian_set.addresses,
@ -370,7 +373,7 @@ pub fn query_address_hex(deps: Deps, address: &HumanAddr) -> StdResult<GetAddres
}
pub fn query_state(deps: Deps) -> StdResult<GetStateResponse> {
let state = config_read(deps.storage).load()?;
let state = CONFIG.load(deps.storage)?;
let res = GetStateResponse { fee: state.fee };
Ok(res)
}

View File

@ -7,6 +7,10 @@ pub enum ContractError {
#[error("InvalidVersion")]
InvalidVersion,
/// Sequence from emitter not found in state
#[error("SequenceNotFound")]
SequenceNotFound,
/// Guardian set with this index does not exist
#[error("InvalidGuardianSetIndex")]
InvalidGuardianSetIndex,

View File

@ -1,23 +1,17 @@
use cw_storage_plus::{Item, Map};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cosmwasm_std::{Binary, CanonicalAddr, Coin, StdResult, Storage, Uint128};
use cosmwasm_storage::{
bucket, bucket_read, singleton, singleton_read, Bucket, ReadonlyBucket, ReadonlySingleton,
Singleton,
};
use crate::{byte_utils::ByteUtils, error::ContractError};
use sha3::{Digest, Keccak256};
type HumanAddr = String;
pub static CONFIG_KEY: &[u8] = b"config";
pub static GUARDIAN_SET_KEY: &[u8] = b"guardian_set";
pub static SEQUENCE_KEY: &[u8] = b"sequence";
pub static WRAPPED_ASSET_KEY: &[u8] = b"wrapped_asset";
pub static WRAPPED_ASSET_ADDRESS_KEY: &[u8] = b"wrapped_asset_address";
pub const CONFIG: Item<ConfigInfo> = Item::new("config");
pub const GUARDIAN_SET: Map<u32, GuardianSetInfo> = Map::new("guardian_set");
pub const SEQUENCE: Map<&[u8], u64> = Map::new("sequence");
pub const VAA_ARCHIVE: Map<&[u8], bool> = Map::new("vaa_archive");
/// Legacy version of [`ConfigInfo`]. Required for the migration. In
/// particular, the last two fields of [`ConfigInfo`] have been added after the
@ -227,66 +221,13 @@ pub struct WormholeInfo {
pub guardian_set_expirity: u64,
}
pub fn config(storage: &mut dyn Storage) -> Singleton<ConfigInfo> {
singleton(storage, CONFIG_KEY)
}
pub fn config_read(storage: &dyn Storage) -> ReadonlySingleton<ConfigInfo> {
singleton_read(storage, CONFIG_KEY)
}
pub fn config_read_legacy(storage: &dyn Storage) -> ReadonlySingleton<ConfigInfoLegacy> {
singleton_read(storage, CONFIG_KEY)
}
pub fn guardian_set_set(
storage: &mut dyn Storage,
index: u32,
data: &GuardianSetInfo,
) -> StdResult<()> {
bucket(storage, GUARDIAN_SET_KEY).save(&index.to_be_bytes(), data)
}
pub fn guardian_set_get(storage: &dyn Storage, index: u32) -> StdResult<GuardianSetInfo> {
bucket_read(storage, GUARDIAN_SET_KEY).load(&index.to_be_bytes())
}
pub fn sequence_set(storage: &mut dyn Storage, emitter: &[u8], sequence: u64) -> StdResult<()> {
bucket(storage, SEQUENCE_KEY).save(emitter, &sequence)
}
pub fn sequence_read(storage: &dyn Storage, emitter: &[u8]) -> u64 {
bucket_read(storage, SEQUENCE_KEY)
.load(emitter)
.unwrap_or(0)
}
pub fn vaa_archive_add(storage: &mut dyn Storage, hash: &[u8]) -> StdResult<()> {
bucket(storage, GUARDIAN_SET_KEY).save(hash, &true)
}
pub fn vaa_archive_check(storage: &dyn Storage, hash: &[u8]) -> bool {
bucket_read(storage, GUARDIAN_SET_KEY)
.load(hash)
VAA_ARCHIVE
.may_load(storage, hash)
.unwrap_or(Some(false))
.unwrap_or(false)
}
pub fn wrapped_asset(storage: &mut dyn Storage) -> Bucket<HumanAddr> {
bucket(storage, WRAPPED_ASSET_KEY)
}
pub fn wrapped_asset_read(storage: &dyn Storage) -> ReadonlyBucket<HumanAddr> {
bucket_read(storage, WRAPPED_ASSET_KEY)
}
pub fn wrapped_asset_address(storage: &mut dyn Storage) -> Bucket<Vec<u8>> {
bucket(storage, WRAPPED_ASSET_ADDRESS_KEY)
}
pub fn wrapped_asset_address_read(storage: &dyn Storage) -> ReadonlyBucket<Vec<u8>> {
bucket_read(storage, WRAPPED_ASSET_ADDRESS_KEY)
}
pub struct GovernancePacket {
pub module: Vec<u8>,
pub action: u8,

View File

@ -1,4 +1,5 @@
use crate::msg::{ExecuteMsg, GetStateResponse, GuardianSetInfoResponse};
use crate::state::CONFIG;
use crate::testing::utils::{
create_transfer_vaa_body, instantiate_with_guardians, sign_vaa_body_version_2,
IntoGuardianAddress, WormholeApp,
@ -6,15 +7,13 @@ use crate::testing::utils::{
use crate::{
contract::instantiate,
msg::QueryMsg,
state::{ConfigInfo, GuardianAddress, ParsedVAA, CONFIG_KEY},
state::{ConfigInfo, GuardianAddress, ParsedVAA},
};
use cosmwasm_std::{
from_slice,
testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage},
Coin, OwnedDeps, Response, StdResult, Storage,
Coin, OwnedDeps, Response, StdResult,
};
use cosmwasm_std::{Deps, DepsMut, Empty, QuerierWrapper, StdError, Uint128, Uint256};
use cosmwasm_storage::to_length_prefixed;
use cw_multi_test::{ContractWrapper, Executor};
use k256::ecdsa::SigningKey;
use serde_wormhole::RawMessage;
@ -26,12 +25,6 @@ use wormhole_sdk::{relayer, Address, Amount, Chain, GuardianSetInfo, GOVERNANCE_
static INITIALIZER: &str = "initializer";
fn get_config_info<S: Storage>(storage: &S) -> ConfigInfo {
let key = to_length_prefixed(CONFIG_KEY);
let data = storage.get(&key).expect("data should exist");
from_slice(&data).expect("invalid data")
}
fn do_init(guardians: &[GuardianAddress]) -> OwnedDeps<MockStorage, MockApi, MockQuerier> {
let mut deps = mock_dependencies();
let init_msg = instantiate_with_guardians(guardians);
@ -42,7 +35,7 @@ fn do_init(guardians: &[GuardianAddress]) -> OwnedDeps<MockStorage, MockApi, Moc
// query the store directly
assert_eq!(
get_config_info(&deps.storage),
CONFIG.load(&deps.storage).expect("data should exist"),
ConfigInfo {
guardian_set_index: 0,
guardian_set_expirity: 50,