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

Can't execute a Solana program compiled from Solidity code with Solang #59

Open
reselbob opened this issue Dec 12, 2023 · 4 comments
Open

Comments

@reselbob
Copy link

Hi:

I am trying to exercise a Solana program I migrated from Solidity using Solang.

I keep getting this error:

Error: SendTransactionError: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: invalid program argument
    at Connection.sendEncodedTransaction (/home/reselbob/Documents/solidity-to-solana/node_modules/@solana/web3.js/lib/index.cjs.js:9560:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Connection.sendRawTransaction (/home/reselbob/Documents/solidity-to-solana/node_modules/@solana/web3.js/lib/index.cjs.js:9526:20)
    at async Connection.sendTransaction (/home/reselbob/Documents/solidity-to-solana/node_modules/@solana/web3.js/lib/index.cjs.js:9517:12)
    at async sendAndConfirmTransaction (/home/reselbob/Documents/solidity-to-solana/node_modules/@solana/web3.js/lib/index.cjs.js:2145:21)
    at async callGetMessage (/home/reselbob/Documents/solidity-to-solana/scripts/SayHi.js:50:20) {
  logs: [
    'Program 5FWPj98F4TEfSvWxqYXQW4whdoLXTN2yeXfCJWfY7EjL invoke [1]',
    'Program 5FWPj98F4TEfSvWxqYXQW4whdoLXTN2yeXfCJWfY7EjL consumed 34 of 200000 compute units',
    'Program 5FWPj98F4TEfSvWxqYXQW4whdoLXTN2yeXfCJWfY7EjL failed: invalid program argument'
  ]
}

I demonstrate the issue in this 4 minute video.

For purposes of research, I am intentionally avoiding using Anchor.

Here is the Solidity code that I migrated.

Here is the client script I used to try to execute the program.

Here is the entire project on GitHub.

If the problem is due to some mistake on my part, in all sincerity I ask your forgiveness.

For what it's worth, this problem has been plaguing me for days.

Thanks in advance for any help and direction you can provide.

@ZYJLiu
Copy link
Collaborator

ZYJLiu commented Dec 13, 2023

With Solang, you won't be able to directly compile a Ethereum Solidity contract and deploy it as a Solana program.
There are some Solang specific annotations you'll need to include in the Solidity contract.

For example, below is an approximate equivalent for your SayHi contract for Solang.
It will simply print "Hi from Solidity code" to the program logs.

@program_id("3fuYYeHetUivCR7HWJ9n5AtiPq7Ztm2n45caxaYzG1Uy")
contract SayHi {
    @payer(payer)
    constructor() {
        print("Hi from Solidity code");
    }
}

To interact with the program once it's deployed, you can modify the ./scripts/SayHi.js file with the code below.
Although you mentioned avoiding Anchor, the example below uses the @coral-xyz/anchor library along with the program's IDL file to build the instruction to invoke the program.

The reason for using the Anchor client is because there is likely an 8 byte discriminator required as part of the instruction data for the program to know which instruction on the program to invoke (I'm not entirely sure how Solang does it).

const {
  Connection,
  Keypair,
  Transaction,
  PublicKey,
  sendAndConfirmTransaction,
} = require("@solana/web3.js");

const { extractKeys } = require("./KeyExtractor");

const { Program, AnchorProvider } = require("@coral-xyz/anchor");
// Generated IDL file
const IDL = require("../build/SayHi.json");
const CONTRACT_ADDRESS = "3fuYYeHetUivCR7HWJ9n5AtiPq7Ztm2n45caxaYzG1Uy";


async function callGetMessage() {

  const connection = new Connection('http://127.0.0.1:8899', 'confirmed');
  const programId = new PublicKey(CONTRACT_ADDRESS)

  const keyData = await extractKeys();
  const wallet = keyData.keyPair;

  // Set up Anchor client using program IDL
  const provider = new AnchorProvider(connection, wallet, {});
  const program = new Program(IDL, programId, provider);

  // Generate random keypair for "data account" created by "new" instruction
  const dataAccount = Keypair.generate();

  // Create instruction to invoke "new" instruction on program
  const instruction = await program.methods
      .new() // For Solang, the constructor is always the "new" instruction
      .accounts({ dataAccount: dataAccount.publicKey })
      .instruction();

  // Add instruction to transaction         
  const transaction = new Transaction().add(instruction);
  transaction.feePayer = wallet.publicKey;

  // Send transaction
  const txHash = await sendAndConfirmTransaction(
      connection,
      transaction,
      [wallet, dataAccount]
  );
  console.log(`Transaction confirmed: ${txHash}`);

  const transactionResponse = await connection.getTransaction(txHash);
  // Print out the transaction program logs
  console.log(JSON.stringify(transactionResponse.meta.logMessages, null, 2));
}

// Call the function to interact with the Solana program
callGetMessage().catch((error) => {
  console.error("Error:", error);
});

Below are the steps I used to get the example running. I'm not sure why, but the keypair for the program ID wasn't getting output anywhere so I generated one to use instead.

First, generate a new keypair to use as the address of the program ID.

solana-keygen new --outfile /program_id.json 

The output should be similar to the following:

Wrote new keypair to ./program_id.json
===============================================================================
pubkey: B2FSjQhJMstz2db9C9RRwG4TqFWdPR7UPjZY5VUSPQUV
===============================================================================

Copy the pubkey and then update the value in SayHi.Sol and SayHi.js

// SayHi.Sol
@program_id("B2FSjQhJMstz2db9C9RRwG4TqFWdPR7UPjZY5VUSPQUV")
// SayHi.js
const CONTRACT_ADDRESS = "B2FSjQhJMstz2db9C9RRwG4TqFWdPR7UPjZY5VUSPQUV";

Then run:

solang compile ./solidity/SayHi.sol --target solana --output build

Start a local validator in a separate terminal:

solana-test-validator

Then deploy the program, specifying filepath to the program_id.json. This will ensure the same program ID is used.

solana program deploy --program-id ./program_id.json ./build/SayHi.so

Once the program is deployed, run the SayHi.js script.

node SayHi.js

The output should be similar to the following:

Transaction confirmed: 3fxFwXdPvogCd3ZS3ezNUiuSUE659LY2L44QdTyCAGo6mNVwwcwRSnPYvBHYxKXaPJjr9s4mswgeuzDwBKUqQ4Rt
[
  "Program B2FSjQhJMstz2db9C9RRwG4TqFWdPR7UPjZY5VUSPQUV invoke [1]",
  "Program 11111111111111111111111111111111 invoke [2]",
  "Program 11111111111111111111111111111111 success",
  "Program log: Hi from Solidity code",
  "Program B2FSjQhJMstz2db9C9RRwG4TqFWdPR7UPjZY5VUSPQUV consumed 2565 of 200000 compute units",
  "Program B2FSjQhJMstz2db9C9RRwG4TqFWdPR7UPjZY5VUSPQUV success"
]

Let me know if it this solves the issue you were encountering!

@reselbob
Copy link
Author

Thanks @ZYJLiu I owe you one.

So it looks as if there is no getting away from Anchor. True?

@SolomonFoskaay
Copy link

Thanks @ZYJLiu I owe you one.

So it looks as if there is no getting away from Anchor. True?

@ZYJLiu has tried in his explanation.

My addition to his is that @reselbob why ignore Anchor?
Solang Solidity on Solana is still at an early stage and a lot of work is been done by the team behind it to improve it with new releases coming almost every month to fix and make it much easier for devs. Anchor is your best tool to embrace for now (you can drop it when Solang Solidity matures better until then you likely be complicating things that isn't already easy for yourself)

Yet you need to accept the fact that Solana is not another EVM-compatible Blockchain and that means the copy-paste of existing Solidity contracts is not possible (at least for now).

You will first need to understand Solana itself and then see how to adapt the existing contract (if possible yet with Solang) to fit Solana architecture.

Meanwhile, you can take my Solang Solidity for Solana 101 Course to get a bit familiar with Solana and Solang if a beginner free at https://dprogramminguniversity.com/freecourses/solang-solidity-for-solana-course-101/

@reselbob
Copy link
Author

Thank you for your thoughtful response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants