-
Notifications
You must be signed in to change notification settings - Fork 321
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Transfer hook : token stop #112
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nice usecase \o/ Love the idea of having the config in the meta data.
|
||
## Future Improvements | ||
|
||
Once [PR #7099](https://github.com/solana-labs/solana-program-library/pull/7099) in the Solana Program Library is merged and deployed to mainnet, this implementation can be further simplified: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this one is merged.
import { TokenStop } from "../target/types/token_stop"; | ||
import { | ||
createTransferCheckedWithTransferHookInstruction, | ||
ExtraAccountMeta, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused imports
anchor.setProvider(provider); | ||
const connection = provider.connection; | ||
|
||
//const conn = new web3.Connection("https://api.mainnet-beta.solana.com"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still needed?
const receiver = new Keypair(); | ||
|
||
// Airdrop SOL to sender and receiver | ||
const airdropAmount = 1000000000; // 1 SOL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could be web3.LAMPORTS_PER_SOL
const transferInstruction2 = SystemProgram.transfer({ | ||
fromPubkey: wallet.publicKey, | ||
toPubkey: mintKeypair.publicKey, | ||
lamports: 1000000000, // 1 SOL, adjust as needed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could be web3.LAMPORTS_PER_SOL
initializeTransferHookInstruction, | ||
initializeMetadataPointerInstruction, | ||
initializeMintInstruction, | ||
//initializeMetadataInstruction, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is now in tx2 right?
); | ||
|
||
// Attempt to transfer tokens from sender to receiver | ||
const transferAmount = 100000000; // 0.1 tokens |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have 0 decimals this would not be 0.1 tokens right?
console.log("Transfer succeeded (unexpected)"); | ||
|
||
throw new Error("Transfer should have failed when transfers are stopped"); | ||
} catch (error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you can be bothered this could be written in a nice way using the promise returned by sendAndConfirm and then use smth similar to this: await expect(sendPromise).to.eventually.be.rejectedWith(
SendTransactionError,
/Transfer: insufficient lamports/,
),
let mint_info = ctx.accounts.mint.to_account_info(); | ||
let mint_data = mint_info.data.borrow(); | ||
let mint = StateWithExtensions::<Token2022Mint>::unpack(&mint_data)?; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could add a check for good pratice to check if its actually currently transferring
fn check_is_transferring(ctx: &Context) -> Result<()> {
let source_token_info = ctx.accounts.source_token.to_account_info();
let mut account_data_ref: RefMut<&mut [u8]> = source_token_info.try_borrow_mut_data()?;
let mut account = PodStateWithExtensionsMut::::unpack(*account_data_ref)?;
let account_extension = account.get_extension_mut::()?;
if !bool::from(account_extension.transferring) {
return err!(TransferError::IsNotCurrentlyTransferring);
}
Ok(())
}
|
||
use super::*; | ||
|
||
pub fn stop_transfer(ctx: Context<StopTransfer>) -> Result<()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like anyone could trigger the stop or resume the transfer. A nice addition would be to save the authority also in the token meta data or add an admin key check or use the mint authority as admin .
Example on how to use a transfer hook to enable / disable token transfers while storing the current transferability state in the mint metadata