Skip to content
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
20 changes: 18 additions & 2 deletions investment_vault/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1366,17 +1366,33 @@ impl InvestmentVault {
let parsed = client.verify_vaa(&vaa);
let transfer = wormhole::parse_bridge_payload(&env, &parsed.payload);

// Trust decision keyed off the VAA envelope's guardian-verified origin
// chain, not the payload-embedded (unverified) transfer.source_chain (#452).
let trusted: bool = env
.storage()
.persistent()
.get(&BridgeDataKey::TrustedEmitter(
transfer.source_chain,
parsed.emitter_chain,
parsed.emitter_address.clone(),
))
.unwrap_or(false);
if !trusted {
panic!("emitter not trusted");
}
// The payload's target_chain is decoded and is now checked (#454) rather
// than silently ignored — the field exists specifically to prevent a
// message meant for a different destination from being processed here.
if transfer.target_chain != wormhole::chain_id::STELLAR {
panic_with_error!(&env, VaultError::BridgeWrongTargetChain);
}
// The payload's token_address is decoded and is now checked (#453) rather
// than silently ignored — otherwise a VAA about a different asset would
// be accepted and minted as HBS anyway if the emitter is ever reused for
// a multi-asset bridge.
if transfer.token_address != wormhole::address_to_bytes32(&env, &env.current_contract_address())
{
panic_with_error!(&env, VaultError::BridgeTokenMismatch);
}
let digest: BytesN<32> = env.crypto().sha256(&vaa).into();
if env
.storage()
Expand All @@ -1397,7 +1413,7 @@ impl InvestmentVault {
lock_deposit(&env, &to);
events::bridge_transfer_completed(
&env,
transfer.source_chain,
parsed.emitter_chain,
&parsed.emitter_address,
&to,
transfer.amount,
Expand Down
6 changes: 6 additions & 0 deletions investment_vault/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ pub enum VaultError {
InvestmentCapExceeded = 43,
/// Requested amount exceeds the configured MaxTransactionAmount compliance limit (#457).
ExceedsMaxTransactionAmount = 44,
/// complete_bridge_transfer's decoded payload's token_address does not match
/// this vault's own contract address (#453).
BridgeTokenMismatch = 45,
/// complete_bridge_transfer's decoded payload targets a chain other than
/// Stellar (#454).
BridgeWrongTargetChain = 46,
}

#[contracttype]
Expand Down
6 changes: 6 additions & 0 deletions project_registry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ use stellar_macros::only_owner;
const MAX_URI_LEN: u32 = 512;
/// Minimum URI length — must contain at least a scheme and one character (#117).
const MIN_URI_LEN: u32 = 8;
/// Maximum governance proposal description length in bytes, mirroring the
/// URI-length bound above — prevents excessively large ledger entries (#455).
const MAX_PROPOSAL_DESCRIPTION_LEN: u32 = 2048;
/// Current schema version for instance and persistent contract state (#66).
const STATE_VERSION: u32 = 1;

Expand Down Expand Up @@ -551,6 +554,9 @@ impl ProjectRegistry {
if voting_duration_secs < MIN_VOTING_PERIOD {
panic_with_error!(&env, RegistryError::VotingPeriodTooShort);
}
if description.len() > MAX_PROPOSAL_DESCRIPTION_LEN {
panic_with_error!(&env, RegistryError::ProposalDescriptionTooLong);
}
let counter: u32 = env
.storage()
.instance()
Expand Down
2 changes: 2 additions & 0 deletions project_registry/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ pub enum RegistryError {
BatchTooLarge = 37,
/// Project is already certified with the target status.
AlreadyCertified = 38,
/// create_proposal's description exceeds MAX_PROPOSAL_DESCRIPTION_LEN (#455).
ProposalDescriptionTooLong = 39,
}

/// Certification state for a green project (#130).
Expand Down
Loading