I'm working on a Solana program using the Anchor framework, and due to policy requirements, I need to deploy multiple versions of the program on the mainnet, each with different program IDs. This policy is something I cannot change.
Anchor requires the use of the declare_id!() macro to define the program ID, which gets embedded into the binary during compilation:
declare_id!("YourProgramPublicKeyHere");
One solution I've considered is building separate binaries for each program ID. However, there's no straightforward way to inspect the compiled binary to ensure that it matches the intended program ID before deployment. If I accidentally deploy the wrong binary to a program ID, the deployment might succeed, but all user interactions with the program would fail, resulting in errors like:
errorLogs: [
'Program log: AnchorError occurred. Error Code: DeclaredProgramIdMismatch. Error Number: 4100. Error Message: The declared program id does not match the actual program id.'
],
This situation would cause 100% downtime until I can deploy the correct binary, which is unacceptable for my users.
How can I declare the program ID at runtime or deployment time to prevent the above issue? Is there a way to make the program dynamically recognize or accept the program ID it is deployed under, or to ensure that the deployed binary always matches the program ID? I'm looking for a solution that prevents the DeclaredProgramIdMismatch error and avoids potential downtime caused by deploying the wrong binary.
Is there any security considerations to just removing the declare_id
macro?
This way I can do
solana program deploy binary.so --program-id <correct_id>
but then how do I know the program ID at runtime? I can now refer to it such as ID
which my program requires.
Any guidance or best practices to handle this scenario in Anchor would be greatly appreciated!
In most cases, it's totally safe to just remove declare_id!
. It's typically only useful for downstream crates to know what program to target for transactions. If you want to have multiple deployments, then you can just have multiple IDs in the binary, ie:
mod deployment_one {
declare_id!(...);
}
mod deployment_two {
declare_id!(...);
}
And then users can decide which of those deployments they want to target.