Here is a draft article on the subject:
Solana: Can other programs write to PDA accounts even if the `Account'' type is used and ownership is checked?
When building decentralized applications (dApps) on Solana, you may encounter scenarios where other programs need to access your Plasma Data Accounts (PDAs). The Anchor Framework provides a convenient way to handle these interactions using the #[account] macro. However, we often wonder: can other programs write to PDA accounts if theAccount'' 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 that the ownership of the account is correct, verifying that:
- The owner of the account is not the current program.
- If the ownership check fails, the account is marked as unowned.
Can other programs write to PDA accounts with ownership checked?
Now, let's consider whether other programs can write to PDA accounts, even if theAccounttype 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 tied to 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 write to a PDA account with verified ownership, you must:
- Make sure that your program has the necessary permissions to access storage variables related to the account owner.
- Verify that the "Account" type is used correctly by checking the account ownership before writing to it.
Code example: Writing to a PDA account with verified ownership
Here is an example code snippet from a Solana program:
use anchor_lang::prelude::*;
#[program]
pub mod my_program {
use super::{My Account, My Storage};
#[account]
pub struct MyAccount {
pub storage_var1: u8,
pub storage_var2: i32,
}
#[params]
pub fn create_account(
_owner: AccountId,
_data: [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<'_>,
_data: [u8; 32],
) -> Result {
if !self.owner.key == current_program.key {
return Err(Error::InvalidProgramId);
}
// Write to storage variables
Ok(())
}
#[action]
pub fn read_from_storage(
mut self: account<'_>,
_data: [u8; 32],
) -> Result {
if !self.owner.key == current_program.key {
return Err(Error::InvalidProgramId);
}
// Read from storage variables
Ok(())
}
#[program]
pub main mode {
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_storageand
read_from_storage` functions check whether they have permission to access the storage variables associated with the account owner. If not, they return an error.