Instantly share code, notes, and snippets.
Created
August 7, 2021 00:36
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save hoakbuilds/ce9ca7a36c8437f8d06d6ed5d3945cbc to your computer and use it in GitHub Desktop.
Example on how to use multi signature accounts to control a token's mint and freeze authorities.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// An example on how to control the freeze authority of a token using multi signatures | |
/// </summary> | |
public class FreezeAuthorityExample : IExample | |
{ | |
private static readonly IRpcClient rpcClient = ClientFactory.GetClient(Cluster.TestNet); | |
private const string MnemonicWords = | |
"route clerk disease box emerge airport loud waste attitude film army tray " + | |
"forward deal onion eight catalog surface unit card window walnut wealth medal"; | |
public void Run() | |
{ | |
Wallet.Wallet wallet = new (MnemonicWords); | |
RequestResult<ResponseValue<BlockHash>> blockHash = rpcClient.GetRecentBlockHash(); | |
ulong minBalanceForExemptionMultiSig = | |
rpcClient.GetMinimumBalanceForRentExemption(TokenProgram.MultisigAccountDataSize).Result; | |
Console.WriteLine($"MinBalanceForRentExemption MultiSig >> {minBalanceForExemptionMultiSig}"); | |
ulong minBalanceForExemptionAcc = | |
rpcClient.GetMinimumBalanceForRentExemption(TokenProgram.TokenAccountDataSize).Result; | |
Console.WriteLine($"MinBalanceForRentExemption Account >> {minBalanceForExemptionAcc}"); | |
ulong minBalanceForExemptionMint = | |
rpcClient.GetMinimumBalanceForRentExemption(TokenProgram.MintAccountDataSize).Result; | |
Console.WriteLine($"MinBalanceForRentExemption Mint Account >> {minBalanceForExemptionMint}"); | |
Account ownerAccount = wallet.GetAccount(10); | |
Account mintAccount = wallet.GetAccount(94330); | |
Account initialAccount = wallet.GetAccount(84330); | |
// the signers for the token mint | |
Account mintMultiSignature = wallet.GetAccount(10116); | |
Account mintSigner1 = wallet.GetAccount(251280); | |
Account mintSigner2 = wallet.GetAccount(251281); | |
Account mintSigner3 = wallet.GetAccount(251282); | |
Account mintSigner4 = wallet.GetAccount(251283); | |
Account mintSigner5 = wallet.GetAccount(251284); | |
// The signers for the freeze account | |
Account freezeMultiSignature = wallet.GetAccount(3057); | |
Account freezeSigner1 = wallet.GetAccount(25410); | |
Account freezeSigner2 = wallet.GetAccount(25411); | |
Account freezeSigner3 = wallet.GetAccount(25412); | |
Account freezeSigner4 = wallet.GetAccount(25413); | |
Account freezeSigner5 = wallet.GetAccount(25414); | |
// First we create a multi sig account to use as the token's freeze authority | |
byte[] msgData = new TransactionBuilder().SetRecentBlockHash(blockHash.Result.Value.Blockhash) | |
.SetFeePayer(ownerAccount) | |
.AddInstruction(SystemProgram.CreateAccount( | |
ownerAccount, | |
freezeMultiSignature, | |
minBalanceForExemptionMultiSig, | |
TokenProgram.MultisigAccountDataSize, | |
TokenProgram.ProgramIdKey)) | |
.AddInstruction(TokenProgram.InitializeMultiSignature( | |
freezeMultiSignature, | |
new List<PublicKey> | |
{ | |
freezeSigner1, | |
freezeSigner2, | |
freezeSigner3, | |
freezeSigner4, | |
freezeSigner5 | |
}, 3)) | |
.CompileMessage(); | |
Message msg = Examples.DecodeMessageFromWire(msgData); | |
Console.WriteLine("\n\tPOPULATING TRANSACTION WITH SIGNATURES\t"); | |
Transaction tx = Transaction.Populate(msg, | |
new List<byte[]> | |
{ | |
ownerAccount.Sign(msgData), | |
freezeMultiSignature.Sign(msgData), | |
}); | |
byte[] txBytes = Examples.LogTransactionAndSerialize(tx); | |
string signature = Examples.SubmitTxSendAndLog(txBytes); | |
Examples.PollConfirmedTx(signature); | |
blockHash = rpcClient.GetRecentBlockHash(); | |
// Then we create an account which will be the token's mint authority | |
// In this same transaction we initialize the token mint with said authorities | |
msgData = new TransactionBuilder().SetRecentBlockHash(blockHash.Result.Value.Blockhash) | |
.SetFeePayer(ownerAccount) | |
.AddInstruction(SystemProgram.CreateAccount( | |
ownerAccount, | |
mintMultiSignature, | |
minBalanceForExemptionMultiSig, | |
TokenProgram.MultisigAccountDataSize, | |
TokenProgram.ProgramIdKey)) | |
.AddInstruction(TokenProgram.InitializeMultiSignature( | |
mintMultiSignature, | |
new List<PublicKey> | |
{ | |
mintSigner1, | |
mintSigner2, | |
mintSigner3, | |
mintSigner4, | |
mintSigner5 | |
}, 3)) | |
.AddInstruction(SystemProgram.CreateAccount( | |
ownerAccount, | |
mintAccount, | |
minBalanceForExemptionMint, | |
TokenProgram.MintAccountDataSize, | |
TokenProgram.ProgramIdKey)) | |
.AddInstruction(TokenProgram.InitializeMint( | |
mintAccount, | |
10, | |
mintMultiSignature, | |
freezeMultiSignature)) | |
.CompileMessage(); | |
msg = Examples.DecodeMessageFromWire(msgData); | |
Console.WriteLine("\n\tPOPULATING TRANSACTION WITH SIGNATURES\t"); | |
tx = Transaction.Populate(msg, | |
new List<byte[]> | |
{ | |
ownerAccount.Sign(msgData), | |
mintMultiSignature.Sign(msgData), | |
mintAccount.Sign(msgData), | |
}); | |
txBytes = Examples.LogTransactionAndSerialize(tx); | |
signature = Examples.SubmitTxSendAndLog(txBytes); | |
Examples.PollConfirmedTx(signature); | |
blockHash = rpcClient.GetRecentBlockHash(); | |
// Here we mint tokens to an account using the mint authority multi sig | |
msgData = new TransactionBuilder().SetRecentBlockHash(blockHash.Result.Value.Blockhash) | |
.SetFeePayer(ownerAccount) | |
.AddInstruction(SystemProgram.CreateAccount( | |
ownerAccount, | |
initialAccount, | |
minBalanceForExemptionAcc, | |
TokenProgram.TokenAccountDataSize, | |
TokenProgram.ProgramIdKey)) | |
.AddInstruction(TokenProgram.InitializeAccount( | |
initialAccount, | |
mintAccount, | |
ownerAccount.PublicKey)) | |
.AddInstruction(TokenProgram.MintTo( | |
mintAccount, | |
initialAccount, | |
25000, | |
mintMultiSignature, | |
new List<PublicKey> | |
{ | |
mintSigner1, | |
mintSigner2, | |
mintSigner4 | |
})) | |
.AddInstruction(MemoProgram.NewMemo(ownerAccount, "Hello from Sol.Net")) | |
.CompileMessage(); | |
msg = Examples.DecodeMessageFromWire(msgData); | |
Console.WriteLine("\n\tPOPULATING TRANSACTION WITH SIGNATURES\t"); | |
tx = Transaction.Populate(msg, | |
new List<byte[]> | |
{ | |
ownerAccount.Sign(msgData), | |
initialAccount.Sign(msgData), | |
mintSigner1.Sign(msgData), | |
mintSigner2.Sign(msgData), | |
mintSigner4.Sign(msgData), | |
}); | |
txBytes = Examples.LogTransactionAndSerialize(tx); | |
signature = Examples.SubmitTxSendAndLog(txBytes); | |
Examples.PollConfirmedTx(signature); | |
blockHash = rpcClient.GetRecentBlockHash(); | |
// After doing this, we freeze the account to which we just minted tokens | |
// Notice how the signers used are different, because the `freezeAuthority` has different signers | |
msgData = new TransactionBuilder().SetRecentBlockHash(blockHash.Result.Value.Blockhash) | |
.SetFeePayer(ownerAccount) | |
.AddInstruction(TokenProgram.FreezeAccount( | |
initialAccount, | |
mintAccount, | |
freezeMultiSignature, | |
TokenProgram.ProgramIdKey, | |
new List<PublicKey> | |
{ | |
freezeSigner2, | |
freezeSigner3, | |
freezeSigner4, | |
})) | |
.AddInstruction(MemoProgram.NewMemo(ownerAccount, "Hello from Sol.Net")) | |
.CompileMessage(); | |
msg = Examples.DecodeMessageFromWire(msgData); | |
Console.WriteLine("\n\tPOPULATING TRANSACTION WITH SIGNATURES\t"); | |
tx = Transaction.Populate(msg, | |
new List<byte[]> | |
{ | |
ownerAccount.Sign(msgData), | |
freezeSigner2.Sign(msgData), | |
freezeSigner3.Sign(msgData), | |
freezeSigner4.Sign(msgData), | |
}); | |
txBytes = Examples.LogTransactionAndSerialize(tx); | |
signature = Examples.SubmitTxSendAndLog(txBytes); | |
Examples.PollConfirmedTx(signature); | |
blockHash = rpcClient.GetRecentBlockHash(); | |
// Because we're actually cool people, we now thaw that same account and then set the authority to nothing | |
msgData = new TransactionBuilder().SetRecentBlockHash(blockHash.Result.Value.Blockhash) | |
.SetFeePayer(ownerAccount) | |
.AddInstruction(TokenProgram.ThawAccount( | |
initialAccount, | |
mintAccount, | |
freezeMultiSignature, | |
TokenProgram.ProgramIdKey, | |
new List<PublicKey> | |
{ | |
freezeSigner2, | |
freezeSigner3, | |
freezeSigner4, | |
})) | |
.AddInstruction(TokenProgram.SetAuthority( | |
mintAccount, | |
AuthorityType.FreezeAccount, | |
freezeMultiSignature, | |
null, | |
new List<PublicKey> | |
{ | |
freezeSigner2, | |
freezeSigner3, | |
freezeSigner4, | |
})) | |
.AddInstruction(MemoProgram.NewMemo(ownerAccount, "Hello from Sol.Net")) | |
.CompileMessage(); | |
msg = Examples.DecodeMessageFromWire(msgData); | |
Console.WriteLine("\n\tPOPULATING TRANSACTION WITH SIGNATURES\t"); | |
tx = Transaction.Populate(msg, | |
new List<byte[]> | |
{ | |
ownerAccount.Sign(msgData), | |
freezeSigner2.Sign(msgData), | |
freezeSigner3.Sign(msgData), | |
freezeSigner4.Sign(msgData), | |
}); | |
txBytes = Examples.LogTransactionAndSerialize(tx); | |
signature = Examples.SubmitTxSendAndLog(txBytes); | |
Examples.PollConfirmedTx(signature); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
wow that is useful.
I wanna build smart contract to mint token using multsig.
please help me.