Skip to content

Instantly share code, notes, and snippets.

@hoffmabc
Last active January 27, 2025 14:24
Show Gist options
  • Select an option

  • Save hoffmabc/a87c20bf98d87bff984a5bf643a408cf to your computer and use it in GitHub Desktop.

Select an option

Save hoffmabc/a87c20bf98d87bff984a5bf643a408cf to your computer and use it in GitHub Desktop.

Revisions

  1. hoffmabc revised this gist Jan 27, 2025. 1 changed file with 12 additions and 0 deletions.
    12 changes: 12 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -55,4 +55,16 @@ pub fn validate_account(accounts: &[AccountInfo], index: u8, is_signer: bool, is
    }
    }
    Ok(())
    }

    pub fn validate_bitcoin_address(address: &str, network_type: &NetworkType, strict: bool) -> Result<(), ProgramError> {
    let network_unchecked_address = Address::from_str(address)
    .map_err(|_| ProgramError::Custom(ERROR_INVALID_ADDRESS))?;

    if strict || *network_type == NetworkType::Bitcoin {
    network_unchecked_address
    .require_network(map_network_type(network_type))
    .map_err(|_| ProgramError::Custom(ERROR_INVALID_ADDRESS_NETWORK))?;
    }
    Ok(())
    }
  2. hoffmabc revised this gist Jan 27, 2025. 1 changed file with 32 additions and 0 deletions.
    32 changes: 32 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -23,4 +23,36 @@ pub fn prepare_settlement_batch(accounts: &[AccountInfo], params: &SettlementBat
    } else {
    Ok(())
    }
    }

    pub fn validate_account(accounts: &[AccountInfo], index: u8, is_signer: bool, is_writable: bool, account_type: Option<AccountType>, related_account_index: Option<u8>) -> Result<(), ProgramError> {
    if index as usize >= accounts.len() {
    return Err(ProgramError::Custom(ERROR_INVALID_ACCOUNT_INDEX));
    }
    let account = &accounts[index as usize];
    if account.is_signer != is_signer || account.is_writable != is_writable {
    return Err(ProgramError::Custom(ERROR_INVALID_ACCOUNT_FLAGS));
    }
    if let Some(account_type) = account_type {
    if get_type(account)? != account_type {
    return Err(ProgramError::Custom(ERROR_INVALID_ACCOUNT_TYPE));
    }
    if let Some(related_account_index) = related_account_index{
    let related_key = match account_type {
    AccountType::Program => ProgramState::get_withdraw_account_key(&account),
    AccountType::Withdraw => WithdrawState::get_program_state_account_key(&account),
    AccountType::Token => TokenState::get_program_state_account_key(&account),
    AccountType::RuneReceiver => RuneReceiverState::get_program_state_account_key(&account),
    _ => Err(ProgramError::Custom(ERROR_INVALID_ACCOUNT_TYPE))
    }?;
    if related_key != *accounts[related_account_index as usize].key {
    return Err(ProgramError::Custom(ERROR_STATE_ACCOUNT_MISMATCH));
    }
    }
    } else {
    if !account.data_is_empty() {
    return Err(ProgramError::Custom(ERROR_ALREADY_INITIALIZED))
    }
    }
    Ok(())
    }
  3. hoffmabc created this gist Jan 27, 2025.
    26 changes: 26 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,26 @@
    pub fn prepare_settlement_batch(accounts: &[AccountInfo], params: &SettlementBatchParams, raw_params_data: &[u8]) -> Result<(), ProgramError> {
    validate_account(accounts, 0, true, true, Some(AccountType::Program), None)?;
    if ProgramState::get_settlement_hash(&accounts[0])? != EMPTY_HASH {
    return Err(ProgramError::Custom(ERROR_SETTLEMENT_IN_PROGRESS));
    }
    ProgramState::clear_events(&accounts[0])?;
    let mut running_netting_total: i64 = 0;

    for token_settlements in &params.settlements {
    validate_account(accounts, token_settlements.account_index, false, false, Some(AccountType::Token), Some(0))?;
    let decrement_sum: u64 = verify_decrements(&accounts, token_settlements.account_index, &token_settlements.decrements)?;
    let increment_sum: u64 = verify_increments(&accounts, token_settlements.account_index, &token_settlements.increments)? + token_settlements.fee_amount;
    running_netting_total += increment_sum as i64 - decrement_sum as i64;
    }

    if running_netting_total != 0 {
    msg!("Netting failed {}", running_netting_total);
    return Err(ProgramError::Custom(ERROR_NETTING));
    }

    if ProgramState::get_events_count(&accounts[0])? == 0 {
    ProgramState::set_settlement_hash(&accounts[0], hash(raw_params_data))
    } else {
    Ok(())
    }
    }