I am trying to invoke Anchor-contract from a regular solana contract and i am keep getting the error
Program log: AnchorError occurred. Error Code: InstructionMissing. Error Number: 100. Error Message: 8 byte instruction identifier not provided.
This is my instruction
#[derive(Debug, BorshDeserialize, BorshSerialize, PartialEq)]
pub enum ConfigInstruction {
Initialize,
}
pub fn initialize(
program_id: &Pubkey,
config: &Pubkey,
authority: &Pubkey,
) -> Instruction {
let accounts = vec![
AccountMeta::new(*config, true),
AccountMeta::new(*authority, true),
AccountMeta::new_readonly(system_program::id(), false),
];
Instruction::new_with_borsh(
*program_id,
&ConfigInstruction::Initialize,
accounts,
)
}
Seems like anchor is waiting a 8-byte long encoded instruction. While borsh serializes it to a vector with size 1. Any idea what am i doing wrong?
Really took some time to sort this out. Posting so this might be helpful for someone else.
So in order to use anchor's instruction for non-anchor contract you need to import InstructionData trait
use anchor_lang::InstructionData;
You instructions will be available using
use your_anchor_program::instruction::CamelCaseInstructionName
Create instruction as usual
Instruction {
program_id: *program_id,
accounts: vec![
...
],
data: CamelCaseInstructionName.data(),
}
Related
I am trying to compile and set up a local Solana node with Metaplex installed for local development. Right now when compiling with anchor build - I've been getting the following error:
To deploy this program:
$ solana program deploy /sol/metaplex/program-library/target/deploy/mpl_fixed_price_sale.so
The program address will default to this keypair (override with --program-id):
/sol/metaplex/program-library/target/deploy/mpl_fixed_price_sale-keypair.json
thread 'main' panicked at 'Code not parseable: Error("space must be provided with init")', lang/syn/src/idl/file.rs:360:58
stack backtrace:
0: rust_begin_unwind
at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/std/src/panicking.rs:584:5
1: core::panicking::panic_fmt
at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/core/src/panicking.rs:143:14
2: core::result::unwrap_failed
at /rustc/7737e0b5c4103216d6fd8cf941b7ab9bdbaace7c/library/core/src/result.rs:1749:5
3: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
4: anchor_syn::idl::file::parse_account_derives
5: anchor_syn::idl::file::parse
6: anchor_cli::extract_idl
7: anchor_cli::build_cwd
8: anchor_cli::build_all
9: anchor_cli::build
10: anchor_cli::entry
11: anchor::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
It appears to originate in: fixed-price-sale/program/src/lib.rs inside pub struct Buy the following lines:
pub struct Buy<'info> {
...
#[account(init_if_needed, seeds=[HISTORY_PREFIX.as_bytes(), user_wallet.key().as_ref(), market.key().as_ref()], bump, payer=user_wallet)]
trade_history: Box<Account<'info, TradeHistory>>,
...
}
When I comment these two lines out and comment out an entire fixed-price-sale/program/src/processor/buy.rs - it compiles with some warnings, but clearly there is now functionality missing. What is missing here?
Looks like a bug. The space parameter is missing.
Need to change:
...
#[account(
init_if_needed,
seeds=[
HISTORY_PREFIX.as_bytes(),
user_wallet.key().as_ref(),
market.key().as_ref()
],
bump,
payer=user_wallet
)]
trade_history: Box<Account<'info, TradeHistory>>,
...
to this:
...
#[account(
init_if_needed,
space=TradeHistory::LEN, // <-------------- Added this line
seeds=[
HISTORY_PREFIX.as_bytes(),
user_wallet.key().as_ref(),
market.key().as_ref()
],
bump,
payer=user_wallet
)]
trade_history: Box<Account<'info, TradeHistory>>,
...
The problem occurs when using the command "near-vm" to execute a simulation test of an assemblyscript smart contract method that takes inputs of type numbers like i32, u32, i64, u64. The following error is returned "FunctionCallError":"WasmUnknownError".
How to reproduce:
git clone the https://github.com/Learn-NEAR/starter--near-sdk-as
Build (yarn) and Run test (yarn test). Everything should works well
Now add simple public method to add to numbers in src/simple/assembly/index.ts
export function add(a: i32, b: i32): i32 {
return a + b;
}
Optionally you can also add a corresponding unit test src/simple/__tests__/index.unit.spec.ts and it will pass successfully
it("should return the sum of two integers", () => {
const sum = add(1, 2);
expect(sum).toBe(3);
})
Now the problem occurs when running simulation test using near-vm
yarn near-vm --wasm-file build/debug/simple.wasm --method-name add --input '{"a": 1, "b": :2}
Then you get "FunctionCallError":"WasmUnknownError"
{"outcome"{"balance":"10000000000000000000000000",
"storage_usage":100,"return_data":"None","burnt_gas":39848843793,"used_gas":39848843793,"logs":[]},
"err":{"FunctionCallError":"WasmUnknownError"},"receipts":[],"state":{}}
Note that this problem doesn't occur when the method parameters are strings.
the simulation tests there are outdated and need to be updated
Check out this new way of simulating NEAR contracts
https://github.com/near/workspaces-js
I am trying set default value for StorageValue, but its giving error:
#[pallet::type_value]
pub fn DefaultRegistrationFees<T: Config>() -> u128 { 100u128 }
#[pallet::storage]
#[pallet::getter(fn profile_registration_fees)]
pub type RegistrationFee<T> = StorageValue<_, u128, OptionQuery, DefaultRegistrationFees<T>>;
Error:
lib.rs(81, 12): the trait frame_support::storage::types::QueryKindTrait<u128, pallet::DefaultRegistrationFees<T>> is not implemented for frame_support::pallet_prelude::OptionQuery
https://substrate.dev/docs/en/knowledgebase/runtime/storage#default-values
I guess you want to write:
pub type RegistrationFee<T> = StorageValue<_, u128, ValueQuery, DefaultRegistrationFees<T>>;
So to use a ValueQuery instead of OptionQuery.
the QueryKind generic of the storage determine how the storage should be handled when there is no value in storage. With OptionQuery, when no value is in storage the method get will return None. With ValueQuery, when no value is in storage the method get will return the value configured with the generic OnEmpty.
So when configuring a specific default, you want to use ValueQuery.
I am trying to put together and example of coding inline assembly code in a 'C' program. I have not had any success. I am using GCC 4.9.0. As near as I can tell my syntax is correct. However the build blows up with the following errors:
/tmp/ccqC2wtq.s:48: Error: syntax error; found `(', expected `,'
Makefile:51: recipe for target 'all' failed
/tmp/ccqC2wtq.s:48: Error: junk at end of line: `(31)'
/tmp/ccqC2wtq.s:49: Error: syntax error; found `(', expected `,'
/tmp/ccqC2wtq.s:49: Error: junk at end of line: `(9)'
These are related to the input/output/clobbers lines in the code. Anyone have an idea where I went wrong?
asm volatile("li 7, %0\n" // load destination address
"li 8, %1\n" // load source address
"li 9, 100\n" // load count
// save source address for return
"mr 3,7\n"
// prepare for loop
"subi 8,8,1\n"
"subi 9,9,1\n"
// perform copy
"1:\n"
"lbzu 10,2(8)\n"
"stbu 10,2(7)\n"
"subi 9,9,1\n" // Decrement the count
"bne 1b\n" // If zero, we've finished
"blr\n"
: // no outputs
: "m" (array), "m" (stringArray)
: "r7", "r8"
);
It's not clear what you are trying to do with the initial instructions:
li 7, %0
li 8, %1
Do you want to load the address of the variables into those registers? In general, this is not possible because the address is not representable in an immediate operand. The easiest way out is to avoid using r7 and r8, and instead use %0 and %1 directly as the register names. It seems that you want to use these registers as base addresses, so you should use the b constraint:
: "b" (array), "b" (stringArray)
Then GCC will take care of the details of materializing the address in a suitable fashion.
You cannot return using blr from inline assembler because it's not possible to tear down the stack frame GCC created. You also need to double-check the clobbers and make sure that you list all the things you clobber (including condition codes, memory, and overwritten input operands).
I was able to get this working by declaring a pair of pointers and initializing them with the addresses of the arrays. I didn't realize that the addresses wouldn't be available directly. I've used inline assembly very sparsely in the past, usually just
to raise or lower interrupt masks, not to do anything that references variables. I just
had some folks who wanted an example. And the "blr" was leftover when I copied a
snipet of a pure assembly routine to use as a starting point. Thanks for the responses.
The final code piece looks like this:
int main()
{
char * stringArrayPtr;
unsigned char * myArrayPtr;
unsigned char myArray[100];
stringArrayPtr = (char *)&stringArray;
myArrayPtr = myArray;
asm volatile(
"lwz 7,%[myArrayPtr]\n" // load destination address
"lwz 8, %[stringArrayPtr]\n" // load source address
"li 9, 100\n" // load count
"mr 3,7\n" // save source address for return
"subi 8,8,1\n" // prepare for loop
"subi 9,9,1\n"
"1:\n" // perform copy
"lbzu 10,1(8)\n"
"stbu 10,1(7)\n"
"subic. 9,9,1\n" // Decrement the count
"bne 1b\n" // If zero, we've finished
// The outputs / inputs / clobbered list
// No output variables are specified here
// See GCC documentation on extended assembly for details.
:
: [stringArrayPtr] "m" (stringArrayPtr), [myArrayPtr]"m"(myArrayPtr)
: "7","8","9","10"
);
}
I am not sure of the behaviour of error messages in Substrate runtimes in relation to Substrate UI, and if they inherently cause a transaction failure or not.
For example in the democracy SRML I see the following line:
ensure!(!<Cancellations<T>>::exists(h), "cannot cancel the same proposal twice");
Which presumably is a macro that ensures that the transaction fails or stops processing if the h (the proposal hash) already exists. There is clearly a message associated with this error.
Am I right to assume that the transaction fails (without the rest of the SRML code being executed) when this test fails?
If so, how do I detect the failure in Substrate UI, and possibly see the message itself?
If not, then presumably some further code is necessary in the runtime module which explicitly creates an error. I have seen Err() - but not in conjunction with ensure!()
As https://github.com/paritytech/substrate/pull/3433 is merged, the ExtrinsicFailed event now includes a DispatchError, which will provide additional error code.
There isn't much documentations available so I will just use system module as example.
First you need to decl_error, note the error variants can only be simple C like enum
https://github.com/paritytech/substrate/blob/5420de3face1349a97eb954ae71c5b0b940c31de/srml/system/src/lib.rs#L334
decl_error! {
/// Error for the System module
pub enum Error {
BadSignature,
BlockFull,
RequireSignedOrigin,
RequireRootOrigin,
RequireNoOrigin,
}
}
Then you need to associate the declared Error type
https://github.com/paritytech/substrate/blob/5420de3face1349a97eb954ae71c5b0b940c31de/srml/system/src/lib.rs#L253
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
type Error = Error;
Then you can just return your Error in dispatch calls when things failed
https://github.com/paritytech/substrate/blob/5420de3face1349a97eb954ae71c5b0b940c31de/srml/system/src/lib.rs#L543
pub fn ensure_root<OuterOrigin, AccountId>(o: OuterOrigin) -> Result<(), Error>
where OuterOrigin: Into<Result<RawOrigin<AccountId>, OuterOrigin>>
{
match o.into() {
Ok(RawOrigin::Root) => Ok(()),
_ => Err(Error::RequireRootOrigin),
}
}
Right now you will only able to see a two numbers, module index and error code from JS side. Later there could be support to include the error details in metadata so that frontend will be able to provide a better response.
Related issue:
https://github.com/paritytech/substrate/issues/2954
The ensure! macro is expaneded as:
#[macro_export]
macro_rules! fail {
( $y:expr ) => {{
return Err($y);
}}
}
#[macro_export]
macro_rules! ensure {
( $x:expr, $y:expr ) => {{
if !$x {
$crate::fail!($y);
}
}}
}
So basically, it's just a quicker way to return Err. At 1.0, the error msg will only be printed to stdout(at least what I've tested so far), doesn't know if it'll be included in blockchain in the future(so can be viewed in substrate ui)..