Skip to content
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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

tiago18c
Copy link

@tiago18c tiago18c commented Aug 6, 2024

Example on how to use a transfer hook to enable / disable token transfers while storing the current transferability state in the mint metadata

Copy link
Collaborator

@Woody4618 Woody4618 left a 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:
Copy link
Collaborator

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,
Copy link
Collaborator

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");
Copy link
Collaborator

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
Copy link
Collaborator

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
Copy link
Collaborator

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,
Copy link
Collaborator

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
Copy link
Collaborator

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) {
Copy link
Collaborator

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)?;

Copy link
Collaborator

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<()> {
Copy link
Collaborator

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 .

@heyAyushh heyAyushh added the contribute:anchor Adds anchor example contribution to repo label Nov 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribute:anchor Adds anchor example contribution to repo
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants