Here is a draft of the article on the subject:
Solana: Can other programs write to PDA accounts even if Account
type is used and ownership is checked?
When building decentralized applications (dApps) in Solana, you may encounter scenarios where other programs need to access your Plasma Data accounts (PDAs). The Anchor framework provides a convenient way to manage these interactions using the #[account] macro. However, we often wonder: can other programs write to PDA accounts if Account
type is used and ownership is checked?
Anchor framework #[account]
macro
In the Anchor framework, the [#[account]]
macro allows you to define a Plasma Data account in your program. This account has its own set of storage variables, transactions, and methods that can be called on it. The Account
type is used to represent these variables and transactions.
When defining an account, the Anchor framework checks whether the account ownership is correct by verifying that:
- The account is not owned by the current program.
- If the ownership check fails, the account is marked as unowned.
Can other programs write to PDA accounts with verified ownership?
Now let’s consider whether other programs can write to PDA accounts, even if the Account
type is used and ownership is checked. The short answer is yes, but only under certain conditions.
When you define an account using the [#[account]]
macro, the Anchor framework adds a set of storage variables that are associated with the account owner. These variables can be accessed by other programs that have permission to write to PDA accounts. However, the ownership check still applies, and if it fails, the account is marked as unowned.
To save to a PDA account with verified ownership, you must:
- Make sure that the program has the necessary permissions to access the storage variables associated with the account owner.
- Verify that the
Account
type is used correctly by checking the ownership of the account before saving to it.
Sample Code: Saving to a PDA account with verified ownership
Here is a sample code snippet from Solana:
use anchor_lang::prelude::*;
#[program]
pub mod my_program {
use super::{MyAccount, MyStorage};
#[account]
pub struct MyAccount {
pub storage_var1: u8,
pub storage_var2: i32,
}
#[param]
pub fn create_account(
_owner: AccountId,
_date: [u8; 32],
) -> Result {
let my_account = MyAccount {
storage_var1: 42,
storage_var2: 123,
};
Self::set_initial_value(my_account).signer?;
Ok(my_account)
}
#[action]
pub fn write_to_storage(
mut self: Account<'_>,
_date: [u8; 32],
) -> Result {
if !self.owner.key == current_program.key {
return Err(Error::InvalidProgramId);
}
// Writing to storage variables
Ok(())
}
#[action]
pub fn read_from_storage(
mut self: Account<'_>,
_date: [u8; 32],
) -> Result {
if !self.owner.key == current_program.key {
return Err(Error::InvalidProgramId);
}
// Reading from storage variables
Ok(())
}
#[program]
pub mod main {
use super::*;
const STORAGE_VAR1: u8 = 42;
const STORAGE_VAR2: i32 = 123;
pub fn my_program() -> Result {
let my_account = MyAccount::create()?;
Ok(my_account)
}
}
}
In this example, the write_to_storage
and read_from_storage
functions check if they have permission to access the storage variables associated with the account owner. If not, they return an error.