Browse Source

change ownership

jpcaulfi 3 years ago
parent
commit
caf2ff3751

+ 11 - 0
basics/change-ownership/README.md

@@ -0,0 +1,11 @@
+# Create Account
+
+:wrench: We're going to create a Solana account. :wrench:   
+   
+This account is going to be a **system account** - meaning it will be owned by the System Program. In short, this means only the System Program will be allowed to modify it's data.   
+   
+In this example, this account will simply hold some SOL.
+
+### Links:
+- [Solana Cookbook - How to Create a System Account](https://solanacookbook.com/references/accounts.html#how-to-create-a-system-account)
+- [Rust Docs - solana_program::system_instruction::create_account](https://docs.rs/solana-program/latest/solana_program/system_instruction/fn.create_account.html)

+ 14 - 0
basics/change-ownership/anchor/Anchor.toml

@@ -0,0 +1,14 @@
+[features]
+seeds = false
+[programs.devnet]
+create_system_account = "6gUwvaZPvC8ZxKuC1h5aKz4mRd7pFyEfUZckiEsBZSbk"
+
+[registry]
+url = "https://anchor.projectserum.com"
+
+[provider]
+cluster = "devnet"
+wallet = "~/.config/solana/id.json"
+
+[scripts]
+test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

+ 13 - 0
basics/change-ownership/anchor/Cargo.toml

@@ -0,0 +1,13 @@
+[workspace]
+members = [
+    "programs/*"
+]
+
+[profile.release]
+overflow-checks = true
+lto = "fat"
+codegen-units = 1
+[profile.release.build-override]
+opt-level = 3
+incremental = false
+codegen-units = 1

+ 14 - 0
basics/change-ownership/anchor/package.json

@@ -0,0 +1,14 @@
+{
+    "dependencies": {
+        "@project-serum/anchor": "^0.24.2"
+    },
+    "devDependencies": {
+        "@types/bn.js": "^5.1.0",
+        "@types/chai": "^4.3.0",
+        "@types/mocha": "^9.0.0",
+        "chai": "^4.3.4",
+        "mocha": "^9.0.3",
+        "ts-mocha": "^10.0.0",
+        "typescript": "^4.3.5"
+    }
+}

+ 19 - 0
basics/change-ownership/anchor/programs/create-system-account/Cargo.toml

@@ -0,0 +1,19 @@
+[package]
+name = "create-system-account"
+version = "0.1.0"
+description = "Created with Anchor"
+edition = "2021"
+
+[lib]
+crate-type = ["cdylib", "lib"]
+name = "create_system_account"
+
+[features]
+no-entrypoint = []
+no-idl = []
+no-log-ix-name = []
+cpi = ["no-entrypoint"]
+default = []
+
+[dependencies]
+anchor-lang = "0.24.2"

+ 2 - 0
basics/change-ownership/anchor/programs/create-system-account/Xargo.toml

@@ -0,0 +1,2 @@
+[target.bpfel-unknown-unknown.dependencies.std]
+features = []

+ 43 - 0
basics/change-ownership/anchor/programs/create-system-account/src/lib.rs

@@ -0,0 +1,43 @@
+use anchor_lang::prelude::*;
+use anchor_lang::system_program;
+
+
+declare_id!("6gUwvaZPvC8ZxKuC1h5aKz4mRd7pFyEfUZckiEsBZSbk");
+
+const LAMPORTS_PER_SOL: u64 = 1000000000;
+
+#[program]
+pub mod create_system_account {
+    use super::*;
+
+    pub fn create_system_account(ctx: Context<CreateSystemAccount>) -> Result<()> {
+
+        msg!("Program invoked. Creating a system account...");
+        msg!("  New public key will be: {}", &ctx.accounts.new_account.key().to_string());
+
+        system_program::create_account(
+            CpiContext::new(
+                ctx.accounts.system_program.to_account_info(),
+                system_program::CreateAccount {
+                    from: ctx.accounts.payer.to_account_info(),         // From pubkey
+                    to: ctx.accounts.new_account.to_account_info(),     // To pubkey
+                },
+            ),
+            1 * LAMPORTS_PER_SOL,                           // Lamports (1 SOL)
+            0,                                         // Space
+            &ctx.accounts.system_program.key(),         // Owner
+        )?;
+
+        msg!("Account created succesfully.");
+        Ok(())
+    }
+}
+
+#[derive(Accounts)]
+pub struct CreateSystemAccount<'info> {
+    #[account(mut)]
+    pub payer: Signer<'info>,
+    #[account(mut)]
+    pub new_account: Signer<'info>,
+    pub system_program: Program<'info, System>,
+}

+ 58 - 0
basics/change-ownership/anchor/tests/test.ts

@@ -0,0 +1,58 @@
+import * as anchor from "@project-serum/anchor";
+import { CreateSystemAccount } from "../target/types/create_system_account";
+
+
+describe("Create a system account", () => {
+
+  const provider = anchor.AnchorProvider.env();
+  anchor.setProvider(provider);
+  const wallet = provider.wallet as anchor.Wallet;
+  const program = anchor.workspace.CreateSystemAccount as anchor.Program<CreateSystemAccount>;
+
+  it("Create the account", async () => {
+
+    const newKeypair = anchor.web3.Keypair.generate();
+    
+    await program.methods.createSystemAccount()
+      .accounts({
+        payer: wallet.publicKey,
+        newAccount: newKeypair.publicKey,
+        systemProgram: anchor.web3.SystemProgram.programId
+      })
+      .signers([wallet.payer, newKeypair])
+      .rpc();
+
+  });
+
+  it("Change ownership for the account", async () => {
+
+    const newKeypair = anchor.web3.Keypair.generate();
+
+    let ix = anchor.web3.SystemProgram.assign({
+        accountPubkey: newKeypair.publicKey,
+        programId: program.programId,
+    })
+
+    await anchor.web3.sendAndConfirmTransaction(
+        provider.connection, 
+        new anchor.web3.Transaction().add(ix),
+        [wallet.payer, newKeypair]
+    );
+});
+
+it("Change it again using the System Program", async () => {
+
+    const newKeypair = anchor.web3.Keypair.generate();
+
+    let ix = anchor.web3.SystemProgram.assign({
+        accountPubkey: newKeypair.publicKey,
+        programId: anchor.web3.SystemProgram.programId,
+    })
+
+    await anchor.web3.sendAndConfirmTransaction(
+        provider.connection, 
+        new anchor.web3.Transaction().add(ix),
+        [wallet.payer, newKeypair]
+    );
+});
+});

+ 10 - 0
basics/change-ownership/anchor/tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}

+ 8 - 0
basics/change-ownership/native/cicd.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This script is for quick building & deploying of the program.
+# It also serves as a reference for the commands used for building & deploying Solana programs.
+# Run this bad boy with "bash cicd.sh" or "./cicd.sh"
+
+cargo build-bpf --manifest-path=./program/Cargo.toml --bpf-out-dir=./program/target/so
+solana program deploy ./program/target/so/program.so

+ 18 - 0
basics/change-ownership/native/package.json

@@ -0,0 +1,18 @@
+{
+  "scripts": {
+    "test": "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts"
+  },
+  "dependencies": {
+    "@solana/web3.js": "^1.47.3",
+    "fs": "^0.0.1-security"
+  },
+  "devDependencies": {
+    "@types/bn.js": "^5.1.0",
+    "@types/chai": "^4.3.1",
+    "@types/mocha": "^9.1.1",
+    "chai": "^4.3.4",
+    "mocha": "^9.0.3",
+    "ts-mocha": "^10.0.0",
+    "typescript": "^4.3.5"
+  }
+}

+ 10 - 0
basics/change-ownership/native/program/Cargo.toml

@@ -0,0 +1,10 @@
+[package]
+name = "program"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+solana-program = "1.10.12"
+
+[lib]
+crate-type = ["cdylib", "lib"]

+ 46 - 0
basics/change-ownership/native/program/src/lib.rs

@@ -0,0 +1,46 @@
+use solana_program::{
+    account_info::{AccountInfo, next_account_info}, 
+    entrypoint, 
+    entrypoint::ProgramResult, 
+    msg, 
+    native_token::LAMPORTS_PER_SOL,
+    program::invoke,
+    pubkey::Pubkey,
+    system_instruction,
+    system_program,
+};
+
+
+entrypoint!(process_instruction);
+
+
+fn process_instruction(
+    _program_id: &Pubkey,
+    accounts: &[AccountInfo],
+    _instruction_data: &[u8],
+) -> ProgramResult {
+
+    let accounts_iter = &mut accounts.iter();
+    let payer = next_account_info(accounts_iter)?;
+    let new_account = next_account_info(accounts_iter)?;
+    let system_program = next_account_info(accounts_iter)?;
+    
+    msg!("Program invoked. Creating a system account...");
+    msg!("  New public key will be: {}", &new_account.key.to_string());
+    
+    invoke(
+        &system_instruction::create_account(
+            &payer.key,
+            &new_account.key,
+            1 * LAMPORTS_PER_SOL,
+            0,
+            &system_program::ID,
+        ),
+        &[
+            payer.clone(), new_account.clone(), system_program.clone()
+        ]
+    )?;
+
+    msg!("Account created succesfully.");
+    Ok(())
+}

+ 80 - 0
basics/change-ownership/native/tests/test.ts

@@ -0,0 +1,80 @@
+import {
+    Connection,
+    Keypair,
+    LAMPORTS_PER_SOL,
+    PublicKey,
+    sendAndConfirmTransaction,
+    SystemProgram,
+    Transaction,
+    TransactionInstruction,
+} from '@solana/web3.js';
+
+
+function createKeypairFromFile(path: string): Keypair {
+    return Keypair.fromSecretKey(
+        Buffer.from(JSON.parse(require('fs').readFileSync(path, "utf-8")))
+    )
+};
+
+
+describe("Change an account's owner", async () => {
+
+    const connection = new Connection(`http://localhost:8899`, 'confirmed');
+    const payer = createKeypairFromFile(require('os').homedir() + '/.config/solana/id.json');
+    
+    const PROGRAM_ID: PublicKey = new PublicKey(
+        "Au21huMZuDQrbzu2Ec5ohpW5CKRqhcGV6qLawfydStGs"
+    );
+
+    const newKeypair = Keypair.generate();
+  
+    it("Create the account", async () => {
+
+        let ix = SystemProgram.createAccount({
+            fromPubkey: payer.publicKey,
+            newAccountPubkey: newKeypair.publicKey,
+            lamports: 1 * LAMPORTS_PER_SOL,
+            space: 0,
+            programId: SystemProgram.programId,
+        });
+
+        await sendAndConfirmTransaction(
+            connection, 
+            new Transaction().add(ix),
+            [payer, newKeypair]
+        );
+    });
+
+    it("Change ownership for the account", async () => {
+
+        const newKeypair = Keypair.generate();
+
+        let ix = SystemProgram.assign({
+            accountPubkey: newKeypair.publicKey,
+            programId: PROGRAM_ID
+        })
+
+        await sendAndConfirmTransaction(
+            connection, 
+            new Transaction().add(ix),
+            [payer, newKeypair]
+        );
+    });
+
+    it("Change it again using the System Program", async () => {
+
+        const newKeypair = Keypair.generate();
+
+        let ix = SystemProgram.assign({
+            accountPubkey: newKeypair.publicKey,
+            programId: SystemProgram.programId,
+        })
+
+        await sendAndConfirmTransaction(
+            connection, 
+            new Transaction().add(ix),
+            [payer, newKeypair]
+        );
+    });
+  });
+  

+ 10 - 0
basics/change-ownership/native/tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}