pencilflip 🍄 Profile picture
Jan 19, 2022 33 tweets 9 min read Read on X
.@armaniferrante recently published a great repository of 10 vulnerabilities to avoid when writing Solana programs.

Here's the quick rundown if you don't feel like digging into the code 👇

ImageImageImage
1) Signer authorization

If your instruction takes in an "authority" account, make sure the account has signed the transaction.

Why? Because only the owner of the "authority" account can sign for it—but anyone can pass in the account as a non-signer.
Don't do this—authority is not required to be a signer. Image
Instead, do this—authority IS required to be a signer! Image
2) Account data matching

Make sure that passed-in accounts contain valid data.

For example, if your instruction expects a token account, the token account should contain an owner, mint, amount, etc.

Otherwise, you may be operating with the wrong type of account!
Don't do this—the token account can contain arbitrary, invalid data. Image
Instead, do this—Anchor checks that the token account contains valid data, and that its owner is the signer of the transaction. Image
3) Checking account ownership

Make sure the passed-in accounts are owned by the correct program.

For example, if your instruction expects a token account, it should be owned by the token program.
Don't do this—this code doesn't check to make sure the token account is owned by the SPL token program, so it could be invalid. Image
Instead, do this—Anchor will verify account ownership for you! Image
4) Type cosplay

Make sure one account type (e.g. User) can't be confused for another account type (e.g. Metadata).

This one is a bit confusing, the examples should make it clearer.
Don't do this—you can't tell a deserialized User account from a deserialized Metadata account Image
The manual way to fix this is by adding a "discriminant" to both accounts, i.e. something that allows you to distinguish between them Image
The recommended way to fix this is by just using Anchor's #[account] macro, which will automatically add an 8-byte discriminator to the start of the account. Much easier! Image
5) Account initialization

This is similar to the previous vulnerability—when initializing accounts, make sure you account for the discriminator.

E.g., you don't want to initialize the wrong type of account. And you may not want to re-initialize an already initialized account.
Don't do this—the user account could be another account type (since there is no discriminator).

And this also lets people re-initialize previously initialized accounts. Image
Instead, do this—using #[account(init)] will create a new account and set its account discriminator. Image
6) Arbitrary CPI

When performing CPIs, make sure you're invoking the correct program.
Don't do this—the token program account gets passed in by the user, and could actually be some other program. Image
The manual way to fix this is checking to make sure the token program account has the right address. Image
The recommended way to fix this is by using Anchor's wrapper of the SPL token program. Image
7) Duplicate mutable accounts

If your program takes in two mutable accounts of the same type, make sure people don't pass in the same account twice.
Don't do this—user_a and user_b may be the same account. Image
Instead, use Anchor to verify that the two accounts are different. Image
8) Bump seed canonicalization

Often, you want to have a single PDA associated with a program ID + a set of seeds.

For example, associated token accounts (ATAs).

Thus, when verifying PDAs, you should use find_program_address instead of create_program_address.
Don't do this—since the bump is passed in by the user (and not verified), set_value could operate on multiple PDAs associated with the program ID + the set of seeds. Image
Instead, do this—both the PDA address and bump are verified, which means set_value will only operate on one "canonical" PDA. Image
9) PDA sharing

You should use a unique PDA for each "authority domain" (H/T @armaniferrante).

The example in the repo is a bit confusing, so let's consider a different one.
Let's say you have a bunch of liquidity pools, and each one has a PDA as an authority.

Instead of using the same PDA as the authority for each pool, it's more secure to use a unique PDA for each pool (e.g. derived from the two token mints the pool is for).
10) Closing accounts

If you no longer need an account, you should close it to reclaim its rent.

However, it turns out that closing an account is pretty tricky.
I'm not going to walk through all the complexities, because there are a lot.

Simply put, if you want to close an account, just use this Anchor macro Image
Hopefully all this made sense! If I made any errors, or if you have any questions, please let me know.
Lastly, I hear @armaniferrante (who understands this stuff much better than me) is working on a presentation to explain all these vulnerabilities more thoroughly, so stay tuned for that 👀

• • •

Missing some Tweet in this thread? You can try to force a refresh
 

Keep Current with pencilflip 🍄

pencilflip 🍄 Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!

PDF

Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @pencilflip

Jul 20, 2022
Metaplex recently announced a new Digital Asset Standard, which is meant to improve upon the existing Metaplex NFT Protocol

Their doc, while thorough, is also long and complex 😵‍💫

So here's a quick and simple summary of the most important improvements

1/ COST

The DAS reduces the cost to mint a basic NFT from ~0.012 SOL → ~0.003 SOL

I assume NFT compression (basically, moving more data off-chain to save costs) will reduce minting costs even more, but estimated costs for compressed NFTs are not mentioned in the docs Image
2/ INCREASED FUNCTIONALITY

The DAS moves more functionality into the NFT program

For example, sales will be forced to go through the program, meaning royalties can be enforced

As another example, fractionalization will also be built into the program

Read 8 tweets
Mar 22, 2022
Solana NFTs 101 🎓

🌟 Part 1: Account overview 🌟

Solana NFTs are composed of at least three accounts:

1. Token mint account
2. Token account
3. Metadata account
4. [Optional] Edition account

Let's review these accounts one-by-one Image
1/ Every token in Solana, fungible or non-fungible, has a mint account

The mint account's address uniquely identifies the token

This account also determines who is allowed to mint more tokens and how many tokens are in supply

NFT mints should have supply = 1 and decimals = 0 Image
2/ Once a single NFT has been minted, which increases supply from 0 to 1, the mint authority (the account that is allowed to mint more tokens) should be set to "None"

This means no more tokens can be minted, fixing the supply at 1—the token is now non-fungible!
Read 14 tweets
Jan 16, 2022
The @metaplex team is working on a new metadata standard for both fungible and non-fungible tokens.

It's backwards compatible and has official support for on-chain collections. And it's currently being tested in devnet.

For more details, see below 👇
1/ First, and perhaps most importantly, this new standard is backwards compatible.

This means NFTs that use the old standard will still function properly (e.g. be displayed properly in Phantom) once the new standard rolls out.
2/ So, what changes does the new standard introduce?

First, let's look at the old on-chain metadata struct. Image
Read 14 tweets
Dec 30, 2021
If you're writing Solana instructions involving tokens/NFTs, please require the token's mint account to be passed!

Otherwise, if you query for the mint's transactions, transactions that include your instruction may not show up... more on this 👇
For example—the regular "Transfer" instruction of the SPL Token Program does not take in the mint account.

Thus, if you transfer an NFT using this instruction, it WON'T show up on that NFT's Solana Explorer page. Image
That's why @phantom uses the "Transfer Checked" instruction, which does take in the mint account.

And that's why NFT transfers conducted via Phantom will always show up in Solana Explorer for the token mint account. Image
Read 7 tweets
Dec 12, 2021
Solana vs. Ethereum L2s, a UX comparison
1/ A lot of people are excited about ZK-rollups, and for good reason.

However, from a UX experience, ZK-rollups aren't too different than existing L2s. E.g. Polygon already offers low fees and fast transactions.

Let's look at Solana vs. L2s, and see why one might be preferred.
2/ To simplify things, I'll mainly be looking at Polygon.

Yes, I know that ZK-rollups are more secure than Polygon's sidechain.

But really, most users don't care about that 🤷‍♂️. Users care about things like low fees and fast transactions, e.g. how good the UX is.
Read 14 tweets
Dec 10, 2021
How do Solana CPIs work?

That is, how do Solana programs call into other Solana programs?

Here's a quick 6 tweet explanation 👇
1/ If you're unfamiliar with Solana transactions/instructions, you might want to take a look at this first.

2/ Calling between programs is achieved by one program invoking an instruction of the other.

Here's how that looks in practice.

The first arg is the instruction to be invoked, and the second arg is the array of accounts required by that instruction.
Read 9 tweets

Did Thread Reader help you today?

Support us! We are indie developers!


This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!

Ethereum

0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy

Bitcoin

3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us!

:(