Forráskód Böngészése

Make instruction data compatible with anchor (#1105)

*Solana* breaking change.

For constructors, a function selector is now required.

Remove the following from the instruction data:
 - Sender
 - Destination
 - Value
 - Seeds
 - Contract hash

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 2 éve
szülő
commit
54f89fa8be

+ 2 - 2
integration/anchor/package.json

@@ -7,7 +7,7 @@
     },
     "dependencies": {
         "@project-serum/anchor": "^0.25.0",
-        "@solana/solidity": "0.0.24",
+        "@solana/solidity": "0.0.25",
         "ts-node": "^10.9.1",
         "tsc-node": "^0.0.3"
     },
@@ -22,4 +22,4 @@
         "ts-mocha": "^10.0.0",
         "typescript": "^4.3.5"
     }
-}
+}

+ 1 - 1
integration/solana/package.json

@@ -18,7 +18,7 @@
   },
   "dependencies": {
     "@dao-xyz/borsh": "3.3.0",
-    "@solana/solidity": "0.0.24",
+    "@solana/solidity": "0.0.25",
     "@solana/spl-token": "0.2.0",
     "@solana/web3.js": "^1.30.2 <1.40.0",
     "ethers": "^5.2.0",

+ 18 - 33
src/codegen/constructor.rs

@@ -5,11 +5,10 @@ use crate::codegen::encoding::create_encoder;
 use crate::codegen::expression::{default_gas, expression};
 use crate::codegen::vartable::Vartable;
 use crate::codegen::{Expression, Options};
-use crate::sema::ast;
-use crate::sema::ast::{CallArgs, Function, Namespace, Type};
-use crate::Target;
-use num_bigint::{BigInt, Sign};
-use num_traits::Zero;
+use crate::sema::{
+    ast,
+    ast::{CallArgs, Function, Namespace, Type},
+};
 use solang_parser::pt::Loc;
 
 /// This function encodes the constructor arguments and place an instruction in the CFG to
@@ -58,36 +57,22 @@ pub(super) fn call_constructor(
         .map(|e| expression(e, cfg, callee_contract_no, func, ns, vartab, opt))
         .collect::<Vec<Expression>>();
 
-    let mut args;
-    if ns.target == Target::Solana {
-        let value_arg = value.clone().unwrap_or_else(|| {
-            Expression::NumberLiteral(Loc::Codegen, Type::Uint(64), BigInt::zero())
-        });
-        let selector = ns.contracts[*contract_no].selector();
-        let padding = Expression::NumberLiteral(*loc, Type::Bytes(1), BigInt::zero());
+    let selector = match constructor_no {
+        Some(func_no) => ns.functions[*func_no].selector(ns, contract_no),
+        None => ns.contracts[*contract_no]
+            .default_constructor
+            .as_ref()
+            .unwrap()
+            .0
+            .selector(ns, contract_no),
+    };
 
-        args = vec![
-            value_arg,
-            Expression::NumberLiteral(*loc, Type::Uint(32), BigInt::from(selector)),
-            padding,
-        ];
-    } else {
-        let selector = match constructor_no {
-            Some(func_no) => ns.functions[*func_no].selector(ns, contract_no),
-            None => ns.contracts[*contract_no]
-                .default_constructor
-                .as_ref()
-                .unwrap()
-                .0
-                .selector(ns, contract_no),
-        };
+    let mut args = vec![Expression::BytesLiteral(
+        *loc,
+        Type::FunctionSelector,
+        selector,
+    )];
 
-        args = vec![Expression::NumberLiteral(
-            *loc,
-            Type::Uint(32),
-            BigInt::from_bytes_le(Sign::Plus, &selector),
-        )];
-    };
     args.append(&mut constructor_args);
 
     let mut encoder = create_encoder(ns, false);

+ 167 - 114
src/codegen/dispatch.rs

@@ -8,59 +8,80 @@ use crate::codegen::{
     Builtin, Expression, Options,
 };
 use crate::{
-    sema::ast::{Namespace, Parameter, Type},
+    sema::ast::{Namespace, StructType, Type},
     Target,
 };
 use num_bigint::{BigInt, Sign};
 use num_traits::Zero;
-use solang_parser::pt;
-use solang_parser::pt::{FunctionTy, Loc};
-use std::sync::Arc;
+use solang_parser::{pt, pt::Loc};
 
 /// Create the dispatch for the Solana target
 pub(super) fn function_dispatch(
     contract_no: usize,
     all_cfg: &[ControlFlowGraph],
     ns: &mut Namespace,
+    opt: &Options,
 ) -> ControlFlowGraph {
     let mut vartab = Vartable::new(ns.next_id);
-    let mut cfg = ControlFlowGraph::new(
-        format!("dispatch_{}", ns.contracts[contract_no].name),
-        ASTFunction::None,
-    );
+    let mut cfg = ControlFlowGraph::new("solang_dispatch".into(), ASTFunction::None);
+
+    let switch_block = cfg.new_basic_block("switch".to_string());
+    let no_function_matched = cfg.new_basic_block("no_function_matched".to_string());
+
+    let argsdata_var = vartab.temp_name("input", &Type::BufferPointer);
+    let argslen_var = vartab.temp_name("input_len", &Type::Uint(64));
 
-    cfg.params = Arc::new(vec![
-        Parameter {
+    let sol_params =
+        Expression::FunctionArg(Loc::Codegen, Type::Struct(StructType::SolParameters), 0);
+
+    // ty:bufferptr argsdata_var = load ty:ref(ty:bufferptr) (structmember ty:ref(ty:bufferptr) (funcarg ty:struct(solparam), 2))
+    cfg.add(
+        &mut vartab,
+        Instr::Set {
+            res: argsdata_var,
             loc: Loc::Codegen,
-            id: None,
-            ty: Type::BufferPointer,
-            ty_loc: None,
-            indexed: false,
-            readonly: false,
-            recursive: false,
+            expr: Expression::Load(
+                Loc::Codegen,
+                Type::Ref(Type::BufferPointer.into()),
+                Expression::StructMember(
+                    Loc::Codegen,
+                    Type::Ref(Type::BufferPointer.into()),
+                    sol_params.clone().into(),
+                    2,
+                )
+                .into(),
+            ),
         },
-        Parameter {
+    );
+
+    let argsdata = Expression::Variable(Loc::Codegen, Type::BufferPointer, argsdata_var);
+
+    // ty:uint64 argslen_var = load ref(ty:uint64) (structmember ref(ty:uin64) (funcarg ty:struct(solparam), 3))
+    cfg.add(
+        &mut vartab,
+        Instr::Set {
+            res: argslen_var,
             loc: Loc::Codegen,
-            id: None,
-            ty: Type::Uint(64),
-            ty_loc: None,
-            indexed: false,
-            readonly: false,
-            recursive: false,
+            expr: Expression::Load(
+                Loc::Codegen,
+                Type::Ref(Type::Uint(64).into()),
+                Expression::StructMember(
+                    Loc::Codegen,
+                    Type::Ref(Type::Uint(64).into()),
+                    sol_params.into(),
+                    3,
+                )
+                .into(),
+            ),
         },
-    ]);
+    );
 
-    let switch_block = cfg.new_basic_block("switch".to_string());
-    let no_function_matched = cfg.new_basic_block("no_function_matched".to_string());
+    let argslen = Expression::Variable(Loc::Codegen, Type::Uint(64), argslen_var);
 
     let not_fallback = Expression::MoreEqual(
         Loc::Codegen,
-        Box::new(Expression::FunctionArg(Loc::Codegen, Type::Uint(64), 1)),
-        Box::new(Expression::NumberLiteral(
-            Loc::Codegen,
-            Type::Uint(64),
-            BigInt::from(8u8),
-        )),
+        argslen.clone().into(),
+        Expression::NumberLiteral(Loc::Codegen, Type::Uint(64), BigInt::from(8u8)).into(),
     );
 
     cfg.add(
@@ -73,9 +94,6 @@ pub(super) fn function_dispatch(
     );
     cfg.set_basic_block(switch_block);
 
-    let argsdata = Expression::FunctionArg(Loc::Codegen, Type::BufferPointer, 0);
-    let argslen = Expression::FunctionArg(Loc::Codegen, Type::Uint(64), 1);
-
     let fid = Expression::Builtin(
         Loc::Codegen,
         vec![Type::Uint(64)],
@@ -106,22 +124,60 @@ pub(super) fn function_dispatch(
         )),
     );
 
+    let magic = vartab.temp_name("magic", &Type::Uint(32));
+
+    cfg.add(
+        &mut vartab,
+        Instr::LoadStorage {
+            res: magic,
+            ty: Type::Uint(32),
+            storage: Expression::NumberLiteral(Loc::Codegen, Type::Uint(32), 0.into()),
+        },
+    );
+
     let mut cases = Vec::new();
+
     for (cfg_no, func_cfg) in all_cfg.iter().enumerate() {
-        if func_cfg.ty != pt::FunctionTy::Function || !func_cfg.public {
+        if !func_cfg.public {
             continue;
         }
 
-        add_dispatch_case(
-            cfg_no,
-            func_cfg,
-            &argsdata,
-            argslen.clone(),
-            &mut cases,
-            ns,
-            &mut vartab,
-            &mut cfg,
-        );
+        let entry = if func_cfg.ty == pt::FunctionTy::Function {
+            add_function_dispatch_case(
+                cfg_no,
+                func_cfg,
+                magic,
+                &argsdata,
+                argslen.clone(),
+                contract_no,
+                ns,
+                &mut vartab,
+                &mut cfg,
+            )
+        } else if func_cfg.ty == pt::FunctionTy::Constructor {
+            add_constructor_dispatch_case(
+                contract_no,
+                cfg_no,
+                &argsdata,
+                argslen.clone(),
+                func_cfg,
+                ns,
+                &mut vartab,
+                &mut cfg,
+                opt,
+            )
+        } else {
+            continue;
+        };
+
+        cases.push((
+            Expression::NumberLiteral(
+                Loc::Codegen,
+                Type::Uint(64),
+                BigInt::from_bytes_le(Sign::Plus, &func_cfg.selector),
+            ),
+            entry,
+        ));
     }
 
     cfg.set_basic_block(switch_block);
@@ -195,18 +251,52 @@ pub(super) fn function_dispatch(
 }
 
 /// Add the dispatch for function given a matched selector
-fn add_dispatch_case(
+fn add_function_dispatch_case(
     cfg_no: usize,
     func_cfg: &ControlFlowGraph,
+    magic: usize,
     argsdata: &Expression,
     argslen: Expression,
-    cases: &mut Vec<(Expression, usize)>,
+    contract_no: usize,
     ns: &Namespace,
     vartab: &mut Vartable,
     cfg: &mut ControlFlowGraph,
-) {
-    let bb = cfg.new_basic_block(format!("function_cfg_{}", cfg_no));
-    cfg.set_basic_block(bb);
+) -> usize {
+    let entry = cfg.new_basic_block(format!("function_cfg_{}", cfg_no));
+    cfg.set_basic_block(entry);
+
+    // check for magic in data account, to see if data account is initialized
+    let magic_ok = cfg.new_basic_block("magic_ok".into());
+    let magic_bad = cfg.new_basic_block("magic_bad".into());
+
+    cfg.add(
+        vartab,
+        Instr::BranchCond {
+            cond: Expression::Equal(
+                Loc::Codegen,
+                Expression::Variable(Loc::Codegen, Type::Uint(32), magic).into(),
+                Expression::NumberLiteral(
+                    Loc::Codegen,
+                    Type::Uint(32),
+                    ns.contracts[contract_no].selector().into(),
+                )
+                .into(),
+            ),
+            true_block: magic_ok,
+            false_block: magic_bad,
+        },
+    );
+
+    cfg.set_basic_block(magic_bad);
+
+    cfg.add(
+        vartab,
+        Instr::ReturnCode {
+            code: ReturnCode::InvalidDataError,
+        },
+    );
+
+    cfg.set_basic_block(magic_ok);
 
     let truncated_len = Expression::Trunc(Loc::Codegen, Type::Uint(32), Box::new(argslen));
 
@@ -277,86 +367,53 @@ fn add_dispatch_case(
         );
     }
 
-    cases.push((
-        Expression::NumberLiteral(
-            Loc::Codegen,
-            Type::Uint(64),
-            BigInt::from_bytes_le(Sign::Plus, &func_cfg.selector),
-        ),
-        bb,
-    ));
+    entry
 }
 
 /// Create the dispatch for a contract constructor. This case creates a new function in
 /// the CFG because we want to use the abi decoding implementation from codegen.
-pub(super) fn constructor_dispatch(
+fn add_constructor_dispatch_case(
     contract_no: usize,
-    constructor_cfg_no: usize,
-    all_cfg: &[ControlFlowGraph],
+    cfg_no: usize,
+    argsdata: &Expression,
+    argslen: Expression,
+    func_cfg: &ControlFlowGraph,
     ns: &mut Namespace,
+    vartab: &mut Vartable,
+    cfg: &mut ControlFlowGraph,
     opt: &Options,
-) -> ControlFlowGraph {
-    let mut vartab = Vartable::new(ns.next_id);
-    let mut func_name = format!("constructor_dispatch_{}", all_cfg[constructor_cfg_no].name);
-    for params in all_cfg[constructor_cfg_no].params.iter() {
-        func_name.push_str(format!("_{}", params.ty.to_string(ns)).as_str());
-    }
-    let mut cfg = ControlFlowGraph::new(func_name, ASTFunction::None);
-    cfg.ty = FunctionTy::Function;
-    cfg.public = all_cfg[constructor_cfg_no].public;
-
-    cfg.params = Arc::new(vec![
-        Parameter {
-            loc: Loc::Codegen,
-            id: None,
-            ty: Type::BufferPointer,
-            ty_loc: None,
-            indexed: false,
-            readonly: false,
-            recursive: false,
-        },
-        Parameter {
-            loc: Loc::Codegen,
-            id: None,
-            ty: Type::Uint(64),
-            ty_loc: None,
-            indexed: false,
-            readonly: false,
-            recursive: false,
-        },
-    ]);
-
-    let data = Expression::FunctionArg(Loc::Codegen, Type::BufferPointer, 0);
-    let data_len = Expression::FunctionArg(Loc::Codegen, Type::Uint(64), 1);
+) -> usize {
+    let entry = cfg.new_basic_block(format!("constructor_cfg_{}", cfg_no));
+    cfg.set_basic_block(entry);
 
     let mut returns: Vec<Expression> = Vec::new();
-    if !all_cfg[constructor_cfg_no].params.is_empty() {
-        let tys = all_cfg[constructor_cfg_no]
+
+    if !func_cfg.params.is_empty() {
+        let tys = func_cfg
             .params
             .iter()
             .map(|e| e.ty.clone())
             .collect::<Vec<Type>>();
         let encoder = create_encoder(ns, false);
-        let truncated_len = Expression::Trunc(Loc::Codegen, Type::Uint(32), Box::new(data_len));
+        let truncated_len = Expression::Trunc(Loc::Codegen, Type::Uint(32), Box::new(argslen));
         returns = encoder.abi_decode(
             &Loc::Codegen,
-            &data,
+            argsdata,
             &tys,
             ns,
-            &mut vartab,
-            &mut cfg,
+            vartab,
+            cfg,
             Some(truncated_len),
         );
     }
 
     if ns.target == Target::Solana {
-        if let ASTFunction::SolidityFunction(function_no) = all_cfg[constructor_cfg_no].function_no
-        {
+        if let ASTFunction::SolidityFunction(function_no) = func_cfg.function_no {
             let func = &ns.functions[function_no];
 
-            solana_deploy(func, &returns, contract_no, &mut vartab, &mut cfg, ns, opt);
+            solana_deploy(func, &returns, contract_no, vartab, cfg, ns, opt);
         } else if let Some((func, _)) = &ns.contracts[contract_no].default_constructor {
-            solana_deploy(func, &returns, contract_no, &mut vartab, &mut cfg, ns, opt);
+            solana_deploy(func, &returns, contract_no, vartab, cfg, ns, opt);
         } else {
             unreachable!();
         }
@@ -364,7 +421,7 @@ pub(super) fn constructor_dispatch(
 
     // Call storage initializer
     cfg.add(
-        &mut vartab,
+        vartab,
         Instr::Call {
             res: vec![],
             return_tys: vec![],
@@ -376,25 +433,21 @@ pub(super) fn constructor_dispatch(
     );
 
     cfg.add(
-        &mut vartab,
+        vartab,
         Instr::Call {
             res: vec![],
             return_tys: vec![],
-            call: InternalCallTy::Static {
-                cfg_no: constructor_cfg_no,
-            },
+            call: InternalCallTy::Static { cfg_no },
             args: returns,
         },
     );
 
     cfg.add(
-        &mut vartab,
+        vartab,
         Instr::ReturnCode {
             code: ReturnCode::Success,
         },
     );
 
-    vartab.finalize(ns, &mut cfg);
-
-    cfg
+    entry
 }

+ 10 - 91
src/codegen/expression.rs

@@ -2190,35 +2190,12 @@ pub fn emit_function_call(
 
             let success = vartab.temp_name("success", &Type::Bool);
 
-            let (payload, address) = if ns.target == Target::Solana && call_args.accounts.is_none()
-            {
-                let encoder_args = vec![
-                    address,
-                    Expression::Builtin(
-                        *loc,
-                        vec![Type::Address(false)],
-                        Builtin::GetAddress,
-                        vec![],
-                    ),
-                    value.clone(),
-                    Expression::NumberLiteral(*loc, Type::Bytes(4), BigInt::zero()),
-                    Expression::NumberLiteral(*loc, Type::Bytes(1), BigInt::zero()),
-                    args,
-                ];
-
-                let mut encoder = create_encoder(ns, true);
-                let (encoded, _) = encoder.abi_encode(loc, encoder_args, ns, vartab, cfg);
-                (encoded, None)
-            } else {
-                (args, Some(address))
-            };
-
             cfg.add(
                 vartab,
                 Instr::ExternalCall {
                     success: Some(success),
-                    address,
-                    payload,
+                    address: Some(address),
+                    payload: args,
                     value,
                     accounts,
                     seeds,
@@ -2278,41 +2255,10 @@ pub fn emit_function_call(
 
                 tys.insert(0, Type::Bytes(selector.len() as u8));
 
-                let address = if ns.target == Target::Solana && dest_func.selector.is_none() {
-                    let mut encoder_args: Vec<Expression> = Vec::with_capacity(6 + args.len());
-                    encoder_args.push(address);
-                    encoder_args.push(Expression::Builtin(
-                        *loc,
-                        vec![Type::Address(false)],
-                        Builtin::GetAddress,
-                        Vec::new(),
-                    ));
-                    encoder_args.push(value.clone());
-                    encoder_args.push(Expression::NumberLiteral(
-                        *loc,
-                        Type::Bytes(4),
-                        BigInt::zero(),
-                    ));
-                    encoder_args.push(Expression::NumberLiteral(
-                        *loc,
-                        Type::Bytes(1),
-                        BigInt::zero(),
-                    ));
-                    encoder_args.push(Expression::BytesLiteral(
-                        *loc,
-                        Type::Bytes(selector.len() as u8),
-                        selector,
-                    ));
-                    encoder_args.append(&mut args);
-                    args = encoder_args;
-                    None
-                } else {
-                    args.insert(
-                        0,
-                        Expression::BytesLiteral(*loc, Type::Bytes(selector.len() as u8), selector),
-                    );
-                    Some(address)
-                };
+                args.insert(
+                    0,
+                    Expression::BytesLiteral(*loc, Type::Bytes(selector.len() as u8), selector),
+                );
 
                 let mut encoder = create_encoder(ns, false);
                 let (payload, _) = encoder.abi_encode(loc, args, ns, vartab, cfg);
@@ -2322,7 +2268,7 @@ pub fn emit_function_call(
                     Instr::ExternalCall {
                         success: None,
                         accounts,
-                        address,
+                        address: Some(address),
                         payload,
                         seeds,
                         value,
@@ -2376,35 +2322,8 @@ pub fn emit_function_call(
                 let selector = function.external_function_selector();
                 let address = function.external_function_address();
 
-                let address = if ns.target == Target::Solana {
-                    let mut encoder_args: Vec<Expression> = Vec::with_capacity(6 + args.len());
-                    encoder_args.push(address);
-                    encoder_args.push(Expression::Builtin(
-                        *loc,
-                        vec![Type::Address(false)],
-                        Builtin::GetAddress,
-                        Vec::new(),
-                    ));
-                    encoder_args.push(value.clone());
-                    encoder_args.push(Expression::NumberLiteral(
-                        *loc,
-                        Type::Bytes(4),
-                        BigInt::zero(),
-                    ));
-                    encoder_args.push(Expression::NumberLiteral(
-                        *loc,
-                        Type::Bytes(1),
-                        BigInt::zero(),
-                    ));
-                    encoder_args.push(selector);
-                    encoder_args.append(&mut args);
-                    args = encoder_args;
-                    None
-                } else {
-                    tys.insert(0, Type::Bytes(4));
-                    args.insert(0, selector);
-                    Some(address)
-                };
+                tys.insert(0, Type::Bytes(ns.target.selector_length()));
+                args.insert(0, selector);
 
                 let mut encoder = create_encoder(ns, false);
                 let (payload, _) = encoder.abi_encode(loc, args, ns, vartab, cfg);
@@ -2415,7 +2334,7 @@ pub fn emit_function_call(
                         success: None,
                         accounts: None,
                         seeds: None,
-                        address,
+                        address: Some(address),
                         payload,
                         value,
                         gas,

+ 3 - 13
src/codegen/mod.rs

@@ -35,14 +35,13 @@ use crate::{sema::ast, Target};
 use std::cmp::Ordering;
 
 use crate::codegen::cfg::ASTFunction;
-use crate::codegen::dispatch::{constructor_dispatch, function_dispatch};
+use crate::codegen::dispatch::function_dispatch;
 use crate::codegen::yul::generate_yul_function_cfg;
 use crate::sema::Recurse;
 use num_bigint::{BigInt, Sign};
 use num_rational::BigRational;
 use num_traits::{FromPrimitive, Zero};
-use solang_parser::pt;
-use solang_parser::pt::{CodeLocation, FunctionTy};
+use solang_parser::{pt, pt::CodeLocation};
 
 // The sizeof(struct account_data_header)
 pub const SOLANA_FIRST_OFFSET: u64 = 16;
@@ -217,18 +216,9 @@ fn contract(contract_no: usize, ns: &mut Namespace, opt: &Options) {
         // TODO: This is a temporary solution. Once Substrate's dispatch moves to codegen,
         // we can remove this if-condition.
         if ns.target == Target::Solana {
-            let dispatch_cfg = function_dispatch(contract_no, &all_cfg, ns);
+            let dispatch_cfg = function_dispatch(contract_no, &all_cfg, ns, opt);
             ns.contracts[contract_no].dispatch_no = all_cfg.len();
             all_cfg.push(dispatch_cfg);
-
-            for cfg_no in 0..all_cfg.len() {
-                if all_cfg[cfg_no].ty == FunctionTy::Constructor && all_cfg[cfg_no].public {
-                    let dispatch_cfg = constructor_dispatch(contract_no, cfg_no, &all_cfg, ns, opt);
-                    ns.contracts[contract_no].constructor_dispatch = Some(all_cfg.len());
-                    all_cfg.push(dispatch_cfg);
-                    break;
-                }
-            }
         }
 
         ns.contracts[contract_no].cfg = all_cfg;

+ 0 - 2
src/codegen/yul/tests/expression.rs

@@ -138,7 +138,6 @@ fn contract_constant_variable() {
         code: OnceCell::new(),
         instantiable: true,
         dispatch_no: 0,
-        constructor_dispatch: None,
         program_id: None,
     };
     ns.contracts.push(contract);
@@ -260,7 +259,6 @@ fn slot_suffix() {
         code: OnceCell::new(),
         instantiable: true,
         dispatch_no: 0,
-        constructor_dispatch: None,
         program_id: None,
     };
     ns.contracts.push(contract);

+ 9 - 5
src/emit/functions.rs

@@ -33,11 +33,15 @@ pub(super) fn emit_functions<'a, T: TargetRuntime<'a>>(
                 ns,
             );
 
-            assert_eq!(bin.module.get_function(&cfg.name), None);
-
-            let func_decl = bin
-                .module
-                .add_function(&cfg.name, ftype, Some(Linkage::Internal));
+            let func_decl = if let Some(func) = bin.module.get_function(&cfg.name) {
+                // must not have a body yet
+                assert_eq!(func.get_first_basic_block(), None);
+
+                func
+            } else {
+                bin.module
+                    .add_function(&cfg.name, ftype, Some(Linkage::Internal))
+            };
 
             bin.functions.insert(cfg_no, func_decl);
 

+ 18 - 220
src/emit/solana/mod.rs

@@ -4,7 +4,6 @@ pub(super) mod target;
 
 use crate::sema::ast;
 use crate::Target;
-use std::collections::HashMap;
 use std::str;
 
 use crate::codegen::{cfg::ReturnCode, Options};
@@ -20,16 +19,7 @@ use crate::emit::functions::emit_functions;
 use crate::emit::loop_builder::LoopBuilder;
 use crate::emit::{Binary, TargetRuntime};
 
-pub struct SolanaTarget {
-    magic: u32,
-}
-
-pub struct Contract<'a> {
-    magic: u32,
-    contract: &'a ast::Contract,
-    constructor: Option<FunctionValue<'a>>,
-    functions: HashMap<usize, FunctionValue<'a>>,
-}
+pub struct SolanaTarget();
 
 // Implement the Solana target which uses BPF
 impl SolanaTarget {
@@ -41,9 +31,7 @@ impl SolanaTarget {
         filename: &'a str,
         opt: &'a Options,
     ) -> Binary<'a> {
-        let mut target = SolanaTarget {
-            magic: contract.selector(),
-        };
+        let mut target = SolanaTarget();
 
         let mut binary = Binary::new(
             context,
@@ -83,25 +71,20 @@ impl SolanaTarget {
 
         emit_functions(&mut target, &mut binary, contract, ns);
 
-        let constructor = contract
-            .constructor_dispatch
-            .map(|cfg_no| binary.functions[&cfg_no]);
-
-        let mut functions = HashMap::new();
-
-        std::mem::swap(&mut functions, &mut binary.functions);
-
-        target.emit_dispatch(
-            &mut binary,
-            &[Contract {
-                magic: target.magic,
-                contract,
-                constructor,
-                functions,
-            }],
-        );
-
-        binary.internalize(&["entrypoint", "sol_log_"]);
+        binary.internalize(&[
+            "entrypoint",
+            "sol_log_",
+            "sol_log_pubkey",
+            "sol_invoke_signed_c",
+            "sol_panic_",
+            "sol_get_return_data",
+            "sol_set_return_data",
+            "sol_create_program_address",
+            "sol_try_find_program_address",
+            "sol_sha256",
+            "sol_keccak256",
+            "sol_log_data",
+        ]);
 
         binary
     }
@@ -236,24 +219,13 @@ impl SolanaTarget {
     fn contract_storage_account<'b>(&self, binary: &Binary<'b>) -> PointerValue<'b> {
         let parameters = self.sol_parameters(binary);
 
-        let ka_cur = binary
-            .builder
-            .build_load(
-                binary
-                    .builder
-                    .build_struct_gep(parameters, 2, "ka_cur")
-                    .unwrap(),
-                "ka_cur",
-            )
-            .into_int_value();
-
         let account_info = unsafe {
             binary.builder.build_gep(
                 parameters,
                 &[
                     binary.context.i32_type().const_int(0, false),
                     binary.context.i32_type().const_int(0, false),
-                    ka_cur,
+                    binary.context.i32_type().const_int(0, false),
                 ],
                 "account",
             )
@@ -296,17 +268,6 @@ impl SolanaTarget {
     fn contract_storage_data<'b>(&self, binary: &Binary<'b>) -> PointerValue<'b> {
         let parameters = self.sol_parameters(binary);
 
-        let ka_cur = binary
-            .builder
-            .build_load(
-                binary
-                    .builder
-                    .build_struct_gep(parameters, 2, "ka_cur")
-                    .unwrap(),
-                "ka_cur",
-            )
-            .into_int_value();
-
         binary
             .builder
             .build_load(
@@ -316,7 +277,7 @@ impl SolanaTarget {
                         &[
                             binary.context.i32_type().const_int(0, false),
                             binary.context.i32_type().const_int(0, false),
-                            ka_cur,
+                            binary.context.i32_type().const_int(0, false),
                             binary.context.i32_type().const_int(3, false),
                         ],
                         "data",
@@ -327,169 +288,6 @@ impl SolanaTarget {
             .into_pointer_value()
     }
 
-    fn emit_dispatch<'b>(&mut self, binary: &mut Binary<'b>, contracts: &[Contract<'b>]) {
-        let function = binary.module.get_function("solang_dispatch").unwrap();
-
-        let entry = binary.context.append_basic_block(function, "entry");
-
-        binary.builder.position_at_end(entry);
-
-        let sol_params = function.get_nth_param(0).unwrap().into_pointer_value();
-
-        let input = binary
-            .builder
-            .build_load(
-                binary
-                    .builder
-                    .build_struct_gep(sol_params, 5, "input")
-                    .unwrap(),
-                "data",
-            )
-            .into_pointer_value();
-
-        let input_len = binary
-            .builder
-            .build_load(
-                binary
-                    .builder
-                    .build_struct_gep(sol_params, 6, "input_len")
-                    .unwrap(),
-                "data_len",
-            )
-            .into_int_value();
-
-        // load magic value of binary storage
-        binary.parameters = Some(sol_params);
-
-        let storage_data = self.contract_storage_data(binary);
-
-        let magic_value_ptr = binary.builder.build_pointer_cast(
-            storage_data,
-            binary.context.i32_type().ptr_type(AddressSpace::Generic),
-            "magic_value_ptr",
-        );
-
-        let magic_value = binary
-            .builder
-            .build_load(magic_value_ptr, "magic")
-            .into_int_value();
-
-        let constructor_block = binary
-            .context
-            .append_basic_block(function, "constructor_call");
-        let badmagic_block = binary.context.append_basic_block(function, "bad_magic");
-
-        // if the magic is zero it's a virgin binary
-        // if the magic is our magic value, it's a function call
-        // if the magic is another magic value, it is an error
-
-        // Generate function call dispatch
-        let function_block = binary.builder.get_insert_block().unwrap();
-
-        let mut cases = vec![(binary.context.i32_type().const_zero(), constructor_block)];
-
-        for contract in contracts {
-            let dispatch_function = contract.functions[&contract.contract.dispatch_no];
-
-            let function_block = binary
-                .context
-                .append_basic_block(function, &format!("function_{}", contract.contract.name));
-
-            binary.builder.position_at_end(function_block);
-
-            let rc = binary
-                .builder
-                .build_call(
-                    dispatch_function,
-                    &[input.into(), input_len.into(), sol_params.into()],
-                    "res",
-                )
-                .try_as_basic_value()
-                .left()
-                .unwrap()
-                .into_int_value();
-
-            binary.builder.build_return(Some(&rc));
-
-            cases.push((
-                binary
-                    .context
-                    .i32_type()
-                    .const_int(contract.magic as u64, false),
-                function_block,
-            ));
-        }
-
-        binary.builder.position_at_end(badmagic_block);
-
-        binary.builder.build_return(Some(
-            &binary.context.i64_type().const_int(4u64 << 32, false),
-        ));
-
-        binary.builder.position_at_end(function_block);
-
-        binary
-            .builder
-            .build_switch(magic_value, badmagic_block, &cases);
-
-        // generate constructor code
-        let mut cases = Vec::new();
-
-        binary.builder.position_at_end(constructor_block);
-
-        for contract in contracts {
-            let constructor_block = binary
-                .context
-                .append_basic_block(function, &format!("constructor_{}", contract.contract.name));
-
-            binary.builder.position_at_end(constructor_block);
-
-            cases.push((
-                binary
-                    .context
-                    .i32_type()
-                    .const_int(contract.magic as u64, false),
-                constructor_block,
-            ));
-
-            // There is only one possible constructor
-            let ret = if let Some(constructor_function) = contract.constructor {
-                binary
-                    .builder
-                    .build_call(
-                        constructor_function,
-                        &[input.into(), input_len.into(), sol_params.into()],
-                        "constructor_dispatch_call",
-                    )
-                    .try_as_basic_value()
-                    .left()
-                    .unwrap()
-            } else {
-                // return 0 for success
-                binary.context.i64_type().const_int(0, false).into()
-            };
-
-            binary.builder.build_return(Some(&ret));
-        }
-
-        binary.builder.position_at_end(constructor_block);
-
-        let magic_value = binary
-            .builder
-            .build_load(
-                binary
-                    .builder
-                    .build_struct_gep(sol_params, 9, "contract")
-                    .unwrap(),
-                "magic",
-            )
-            .into_int_value();
-
-        binary
-            .builder
-            .build_switch(magic_value, badmagic_block, &cases);
-    }
-
     /// Free binary storage and zero out
     fn storage_free<'b>(
         &self,

+ 46 - 85
src/emit/solana/target.rs

@@ -1259,43 +1259,6 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
         seeds: Option<(PointerValue<'b>, IntValue<'b>)>,
         ns: &ast::Namespace,
     ) {
-        let address_length = binary
-            .context
-            .i32_type()
-            .const_int(ns.address_length as u64 * 2, false);
-
-        let malloc_length = binary.builder.build_int_add(
-            encoded_args_len.into_int_value(),
-            address_length,
-            "malloc_length",
-        );
-
-        // The format of the payload is:
-        // 32 bytes recv (will be filled in by create_contract C function)
-        // 32 bytes sender (will be filled in by create_contract C function)
-        // 4 bytes contract selector/magic
-        // remainder: abi encoded constructor arguments
-        let payload = binary
-            .builder
-            .build_call(
-                binary.module.get_function("__malloc").unwrap(),
-                &[malloc_length.into()],
-                "",
-            )
-            .try_as_basic_value()
-            .left()
-            .unwrap()
-            .into_pointer_value();
-
-        let enc = unsafe { binary.builder.build_gep(payload, &[address_length], "enc") };
-
-        let buffer_bytes = binary.vector_bytes(encoded_args);
-        binary.builder.build_call(
-            binary.module.get_function("__memcpy").unwrap(),
-            &[enc.into(), buffer_bytes.into(), encoded_args_len.into()],
-            "",
-        );
-
         let const_program_id = binary.builder.build_pointer_cast(
             binary.emit_global_string(
                 "const_program_id",
@@ -1353,8 +1316,8 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
             .build_call(
                 create_contract,
                 &[
-                    payload.into(),
-                    malloc_length.into(),
+                    binary.vector_bytes(encoded_args).into(),
+                    encoded_args_len.into(),
                     address.into(),
                     const_program_id.into(),
                     signer_seeds.into(),
@@ -1521,7 +1484,9 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
         _ty: ast::CallTy,
         _ns: &ast::Namespace,
     ) {
-        let ret = if let Some(address) = address {
+        let address = address.unwrap();
+
+        let ret = if let Some((accounts, accounts_len)) = accounts {
             // build instruction
             let instruction_ty: BasicTypeEnum = binary
                 .module
@@ -1547,8 +1512,6 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                 ),
             );
 
-            let (accounts, accounts_len) = accounts.unwrap();
-
             binary.builder.build_store(
                 binary
                     .builder
@@ -1679,17 +1642,27 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
 
             let external_call = binary.module.get_function("external_call").unwrap();
 
-            let arg2 = binary.builder.build_pointer_cast(
-                parameters,
-                external_call.get_type().get_param_types()[2].into_pointer_type(),
-                "",
+            // cast [u8; 32]* to SolPubkey*
+            let address = binary.builder.build_pointer_cast(
+                address,
+                binary
+                    .module
+                    .get_struct_type("struct.SolPubkey")
+                    .unwrap()
+                    .ptr_type(AddressSpace::Generic),
+                "address",
             );
 
             binary
                 .builder
                 .build_call(
                     external_call,
-                    &[payload.into(), payload_len.into(), arg2.into()],
+                    &[
+                        address.into(),
+                        payload.into(),
+                        payload_len.into(),
+                        parameters.into(),
+                    ],
                     "",
                 )
                 .try_as_basic_value()
@@ -2046,49 +2019,37 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
 
                 binary.builder.build_load(slot, "timestamp")
             }
-            codegen::Expression::Builtin(_, _, codegen::Builtin::Sender, _) => {
-                let parameters = self.sol_parameters(binary);
-
-                let sender = binary
-                    .builder
-                    .build_load(
-                        binary
-                            .builder
-                            .build_struct_gep(parameters, 10, "sender")
-                            .unwrap(),
-                        "sender",
-                    )
-                    .into_pointer_value();
-
-                let sender_address = binary.builder.build_pointer_cast(
-                    sender,
-                    binary.address_type(ns).ptr_type(AddressSpace::Generic),
-                    "",
-                );
-
-                binary.builder.build_load(sender_address, "sender_address")
-            }
             codegen::Expression::Builtin(_, _, codegen::Builtin::GetAddress, _) => {
                 let parameters = self.sol_parameters(binary);
 
-                let account_id = binary
-                    .builder
-                    .build_load(
-                        binary
-                            .builder
-                            .build_struct_gep(parameters, 4, "account_id")
-                            .unwrap(),
-                        "account_id",
+                let key = unsafe {
+                    binary.builder.build_gep(
+                        parameters,
+                        &[
+                            binary.context.i32_type().const_int(0, false), // first SolParameters
+                            binary.context.i32_type().const_int(0, false), // first field of SolParameters
+                            binary.context.i32_type().const_int(0, false), // first element of ka[]
+                            binary.context.i32_type().const_int(0, false), // first field of SolAccountInfo (key)
+                        ],
+                        "key",
                     )
-                    .into_pointer_value();
+                };
 
+                // SolPubkey** => [u8; 32]**
                 let value = binary.builder.build_pointer_cast(
-                    account_id,
-                    binary.address_type(ns).ptr_type(AddressSpace::Generic),
+                    key,
+                    binary
+                        .address_type(ns)
+                        .ptr_type(AddressSpace::Generic)
+                        .ptr_type(AddressSpace::Generic),
                     "",
                 );
 
-                binary.builder.build_load(value, "self_address")
+                let key_pointer = binary.builder.build_load(value, "key_pointer");
+
+                binary
+                    .builder
+                    .build_load(key_pointer.into_pointer_value(), "key")
             }
             codegen::Expression::Builtin(_, _, codegen::Builtin::ProgramId, _) => {
                 let parameters = self.sol_parameters(binary);
@@ -2098,7 +2059,7 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                     .build_load(
                         binary
                             .builder
-                            .build_struct_gep(parameters, 7, "program_id")
+                            .build_struct_gep(parameters, 4, "program_id")
                             .unwrap(),
                         "program_id",
                     )
@@ -2120,7 +2081,7 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                     .build_load(
                         binary
                             .builder
-                            .build_struct_gep(sol_params, 5, "input")
+                            .build_struct_gep(sol_params, 2, "input")
                             .unwrap(),
                         "data",
                     )
@@ -2131,7 +2092,7 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                     .build_load(
                         binary
                             .builder
-                            .build_struct_gep(sol_params, 6, "input_len")
+                            .build_struct_gep(sol_params, 3, "input_len")
                             .unwrap(),
                         "data_len",
                     )
@@ -2166,7 +2127,7 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                     .build_load(
                         binary
                             .builder
-                            .build_struct_gep(sol_params, 5, "input")
+                            .build_struct_gep(sol_params, 2, "input")
                             .unwrap(),
                         "data",
                     )

+ 0 - 2
src/sema/ast.rs

@@ -656,8 +656,6 @@ pub struct Contract {
     pub instantiable: bool,
     /// CFG number of this contract's dispatch function
     pub dispatch_no: usize,
-    /// CFG number of this contract's constructor dispatch
-    pub constructor_dispatch: Option<usize>,
     /// Account of deployed program code on Solana
     pub program_id: Option<Vec<u8>>,
 }

+ 0 - 1
src/sema/contracts.rs

@@ -46,7 +46,6 @@ impl ast::Contract {
             code: OnceCell::new(),
             instantiable,
             dispatch_no: 0,
-            constructor_dispatch: None,
             program_id: None,
         }
     }

BIN
stdlib/bpf/solana.bc


+ 7 - 26
stdlib/solana.c

@@ -5,7 +5,7 @@
 #include "stdlib.h"
 #include "solana_sdk.h"
 
-extern uint64_t solang_dispatch(const SolParameters *param);
+extern uint64_t solang_dispatch(SolParameters *param);
 extern void __init_heap();
 
 // The address 'SysvarC1ock11111111111111111111111111111111' base58 decoded
@@ -26,21 +26,14 @@ entrypoint(const uint8_t *input)
         return ret;
     }
 
-    int account_no;
-
     params.ka_clock = NULL;
     params.ka_instructions = NULL;
-    params.ka_cur = UINT64_MAX;
 
-    for (account_no = 0; account_no < params.ka_num; account_no++)
+    for (int account_no = 0; account_no < params.ka_num; account_no++)
     {
         const SolAccountInfo *acc = &params.ka[account_no];
 
-        if (SolPubkey_same(params.account_id, acc->key) && params.ka_cur == UINT64_MAX)
-        {
-            params.ka_cur = account_no;
-        }
-        else if (SolPubkey_same(&clock_address, acc->key))
+        if (SolPubkey_same(&clock_address, acc->key))
         {
             params.ka_clock = acc;
         }
@@ -50,11 +43,6 @@ entrypoint(const uint8_t *input)
         }
     }
 
-    if (params.ka_cur != 0)
-    {
-        return ERROR_INVALID_INSTRUCTION_DATA;
-    }
-
     __init_heap();
 
     return solang_dispatch(&params);
@@ -67,11 +55,8 @@ uint64_t sol_invoke_signed_c(
     const SolSignerSeeds *signers_seeds,
     int signers_seeds_len);
 
-uint64_t external_call(uint8_t *input, uint32_t input_len, SolParameters *params)
+uint64_t external_call(const SolPubkey *address, uint8_t *input, uint32_t input_len, SolParameters *params)
 {
-    // The first 32 bytes of the input is the destination address
-    const SolPubkey *dest = (const SolPubkey *)input;
-
     SolAccountMeta metas[10];
     SolInstruction instruction = {
         .program_id = NULL,
@@ -87,13 +72,12 @@ uint64_t external_call(uint8_t *input, uint32_t input_len, SolParameters *params
     {
         const SolAccountInfo *acc = &params->ka[account_no];
 
-        if (SolPubkey_same(dest, acc->key))
+        if (SolPubkey_same(address, acc->key))
         {
             metas[0].pubkey = acc->key;
             metas[0].is_writable = acc->is_writable;
             metas[0].is_signer = acc->is_signer;
             instruction.program_id = acc->owner;
-            params->ka_last_called = acc;
         }
         else
         {
@@ -161,9 +145,6 @@ uint64_t create_contract(uint8_t *input, uint32_t input_len, SolPubkey *address,
         return ERROR_NEW_ACCOUNT_NEEDED;
     }
 
-    __memcpy8(input, address, SIZE_PUBKEY / 8);
-    __memcpy8(input + SIZE_PUBKEY, params->account_id->x, SIZE_PUBKEY / 8);
-
     return sol_invoke_signed_c(&instruction, params->ka, params->ka_num, seeds, seeds_len);
 }
 
@@ -190,7 +171,7 @@ uint64_t *sol_account_lamport(
 
 void sol_transfer(uint8_t *to_address, uint64_t lamports, SolParameters *params)
 {
-    uint64_t *from = params->ka[params->ka_cur].lamports;
+    uint64_t *from = params->ka[0].lamports;
     uint64_t *to = sol_account_lamport(to_address, params);
 
     if (__builtin_sub_overflow(*from, lamports, from))
@@ -208,7 +189,7 @@ void sol_transfer(uint8_t *to_address, uint64_t lamports, SolParameters *params)
 
 bool sol_try_transfer(uint8_t *to_address, uint64_t lamports, SolParameters *params)
 {
-    uint64_t *from = params->ka[params->ka_cur].lamports;
+    uint64_t *from = params->ka[0].lamports;
     uint64_t *to = sol_account_lamport(to_address, params);
 
     uint64_t from_balance;

+ 0 - 51
stdlib/solana_sdk.h

@@ -212,19 +212,11 @@ typedef struct
   SolAccountInfo ka[10]; /** Pointer to an array of SolAccountInfo, must already
                           point to an array of SolAccountInfos */
   uint64_t ka_num;       /** Number of SolAccountInfo entries in `ka` */
-  uint64_t ka_cur;
-  const SolAccountInfo *ka_last_called;
-  SolPubkey *account_id;
   const uint8_t *input;  /** pointer to the instruction data */
   uint64_t input_len;    /** Length in bytes of the instruction data */
   SolPubkey *program_id; /** program_id of the currently executing program */
   const SolAccountInfo *ka_clock;
-  uint32_t contract;
-  const SolPubkey *sender;
-  SolSignerSeed seeds[10];
-  int seeds_len;
   const SolAccountInfo *ka_instructions;
-  uint64_t value;
 } SolParameters;
 
 /**
@@ -340,48 +332,6 @@ static uint64_t sol_deserialize(
   uint64_t data_len = *(uint64_t *)input;
   input += sizeof(uint64_t);
 
-  if (data_len < SIZE_PUBKEY * 2 + sizeof(uint32_t) + 1)
-  {
-    return ERROR_INVALID_INSTRUCTION_DATA;
-  }
-
-  params->account_id = (SolPubkey *)input;
-  input += SIZE_PUBKEY;
-  data_len -= SIZE_PUBKEY;
-  params->sender = (SolPubkey *)input;
-  input += SIZE_PUBKEY;
-  data_len -= SIZE_PUBKEY;
-  params->value = *(uint64_t *)input;
-  input += sizeof(uint64_t);
-  data_len -= sizeof(uint64_t);
-
-  // FIXME: check that sender is a signer
-
-  params->contract = *(uint32_t *)input;
-  input += sizeof(uint32_t);
-  data_len -= sizeof(uint32_t);
-  uint8_t seeds_len = *input;
-  input += 1;
-  data_len -= 1;
-
-  for (int i = 0; i < seeds_len; i++)
-  {
-    uint8_t seed_len = *input;
-    input += 1;
-    data_len -= 1;
-
-    if (data_len < seed_len)
-    {
-      return ERROR_INVALID_INSTRUCTION_DATA;
-    }
-
-    params->seeds[i].len = seed_len;
-    params->seeds[i].addr = input;
-    input += seed_len;
-    data_len -= seed_len;
-  }
-  params->seeds_len = seeds_len;
-
   params->input_len = data_len;
   params->input = input;
   input += data_len;
@@ -580,7 +530,6 @@ static void sol_log_params(const SolParameters *params)
     sol_log_64(0, 0, 0, 0, params->ka[i].rent_epoch);
   }
   sol_log("- Eth abi Instruction data\0");
-  sol_log_pubkey(params->account_id);
   sol_log_array(params->input, params->input_len);
 }
 

+ 96 - 96
tests/codegen_testcases/solidity/borsh_decoding_simple_types.sol

@@ -8,12 +8,12 @@ contract Testing {
     function addressContract(bytes memory buffer) public pure returns (address, Other) {
         (address a, Other b) = abi.decode(buffer, (address, Other));
 	    // CHECK: ty:bytes %buffer = (arg #0)
-	    // CHECK: ty:uint32 %temp.61 = (builtin ArrayLength ((arg #0)))
-	    // CHECK: branchcond (uint32 64 <= %temp.61), block1, block2
+	    // CHECK: ty:uint32 %temp.64 = (builtin ArrayLength ((arg #0)))
+	    // CHECK: branchcond (uint32 64 <= %temp.64), block1, block2
         // CHECK: block1: # inbounds
-        // CHECK: ty:address %temp.62 = (builtin ReadFromBuffer ((arg #0), uint32 0))
-        // CHECK: ty:contract Other %temp.63 = (builtin ReadFromBuffer ((arg #0), uint32 32))
-        // CHECK: branchcond (unsigned less uint32 64 < %temp.61), block3, block4
+        // CHECK: ty:address %temp.65 = (builtin ReadFromBuffer ((arg #0), uint32 0))
+        // CHECK: ty:contract Other %temp.66 = (builtin ReadFromBuffer ((arg #0), uint32 32))
+        // CHECK: branchcond (unsigned less uint32 64 < %temp.64), block3, block4
         // CHECK: block2: # out_of_bounds
         // CHECK: assert-failure
 
@@ -21,8 +21,8 @@ contract Testing {
 	    // CHECK: assert-failure
 
         // CHECK: block4: # buffer_read
-	    // CHECK: ty:address %a = %temp.62
-	    // CHECK: ty:contract Other %b = %temp.63
+	    // CHECK: ty:address %a = %temp.65
+	    // CHECK: ty:contract Other %b = %temp.66
         return (a, b);
     }
 
@@ -33,17 +33,17 @@ contract Testing {
         abi.decode(buffer, (uint8, uint16, uint32, uint64, uint128, uint256));
 
 	    // CHECK: ty:bytes %buffer = (arg #0)
-	    // CHECK: ty:uint32 %temp.64 = (builtin ArrayLength ((arg #0)))
-	    // CHECK: branchcond (uint32 63 <= %temp.64), block1, block2
+	    // CHECK: ty:uint32 %temp.67 = (builtin ArrayLength ((arg #0)))
+	    // CHECK: branchcond (uint32 63 <= %temp.67), block1, block2
 
         // CHECK: block1: # inbounds
-	    // CHECK: ty:uint8 %temp.65 = (builtin ReadFromBuffer ((arg #0), uint32 0))
-	    // CHECK: ty:uint16 %temp.66 = (builtin ReadFromBuffer ((arg #0), uint32 1))
-	    // CHECK: ty:uint32 %temp.67 = (builtin ReadFromBuffer ((arg #0), uint32 3))
-	    // CHECK: ty:uint64 %temp.68 = (builtin ReadFromBuffer ((arg #0), uint32 7))
-	    // CHECK: ty:uint128 %temp.69 = (builtin ReadFromBuffer ((arg #0), uint32 15))
-	    // CHECK: ty:uint256 %temp.70 = (builtin ReadFromBuffer ((arg #0), uint32 31))
-	    // CHECK: branchcond (unsigned less uint32 63 < %temp.64), block3, block4
+	    // CHECK: ty:uint8 %temp.68 = (builtin ReadFromBuffer ((arg #0), uint32 0))
+	    // CHECK: ty:uint16 %temp.69 = (builtin ReadFromBuffer ((arg #0), uint32 1))
+	    // CHECK: ty:uint32 %temp.70 = (builtin ReadFromBuffer ((arg #0), uint32 3))
+	    // CHECK: ty:uint64 %temp.71 = (builtin ReadFromBuffer ((arg #0), uint32 7))
+	    // CHECK: ty:uint128 %temp.72 = (builtin ReadFromBuffer ((arg #0), uint32 15))
+	    // CHECK: ty:uint256 %temp.73 = (builtin ReadFromBuffer ((arg #0), uint32 31))
+	    // CHECK: branchcond (unsigned less uint32 63 < %temp.67), block3, block4
 
         // CHECK: block2: # out_of_bounds
         // CHECK: assert-failure
@@ -52,12 +52,12 @@ contract Testing {
 	    // CHECK: assert-failure
 
         // CHECK: block4: # buffer_read
-	    // CHECK: ty:uint8 %a = %temp.65
-	    // CHECK: ty:uint16 %b = %temp.66
-	    // CHECK: ty:uint32 %c = %temp.67
-	    // CHECK: ty:uint64 %d = %temp.68
-	    // CHECK: ty:uint128 %e = %temp.69
-	    // CHECK: ty:uint256 %f = %temp.70
+	    // CHECK: ty:uint8 %a = %temp.68
+	    // CHECK: ty:uint16 %b = %temp.69
+	    // CHECK: ty:uint32 %c = %temp.70
+	    // CHECK: ty:uint64 %d = %temp.71
+	    // CHECK: ty:uint128 %e = %temp.72
+	    // CHECK: ty:uint256 %f = %temp.73
 
         return (a, b, c, d, e, f);
     }
@@ -68,17 +68,17 @@ contract Testing {
         (int8 a, int16 b, int32 c, int64 d, int128 e, int256 f) =
         abi.decode(buffer, (int8, int16, int32, int64, int128, int256));
 
-        // CHECK: ty:uint32 %temp.71 = (builtin ArrayLength ((arg #0)))
-	    // CHECK: branchcond (uint32 63 <= %temp.71), block1, block2
+        // CHECK: ty:uint32 %temp.74 = (builtin ArrayLength ((arg #0)))
+	    // CHECK: branchcond (uint32 63 <= %temp.74), block1, block2
 
         // CHECK: block1: # inbounds
-	    // CHECK: ty:int8 %temp.72 = (builtin ReadFromBuffer ((arg #0), uint32 0))
-	    // CHECK: ty:int16 %temp.73 = (builtin ReadFromBuffer ((arg #0), uint32 1))
-	    // CHECK: ty:int32 %temp.74 = (builtin ReadFromBuffer ((arg #0), uint32 3))
-	    // CHECK: ty:int64 %temp.75 = (builtin ReadFromBuffer ((arg #0), uint32 7))
-	    // CHECK: ty:int128 %temp.76 = (builtin ReadFromBuffer ((arg #0), uint32 15))
-	    // CHECK: ty:int256 %temp.77 = (builtin ReadFromBuffer ((arg #0), uint32 31))
-	    // CHECK: branchcond (unsigned less uint32 63 < %temp.71), block3, block4
+	    // CHECK: ty:int8 %temp.75 = (builtin ReadFromBuffer ((arg #0), uint32 0))
+	    // CHECK: ty:int16 %temp.76 = (builtin ReadFromBuffer ((arg #0), uint32 1))
+	    // CHECK: ty:int32 %temp.77 = (builtin ReadFromBuffer ((arg #0), uint32 3))
+	    // CHECK: ty:int64 %temp.78 = (builtin ReadFromBuffer ((arg #0), uint32 7))
+	    // CHECK: ty:int128 %temp.79 = (builtin ReadFromBuffer ((arg #0), uint32 15))
+	    // CHECK: ty:int256 %temp.80 = (builtin ReadFromBuffer ((arg #0), uint32 31))
+	    // CHECK: branchcond (unsigned less uint32 63 < %temp.74), block3, block4
 
         // CHECK: block2: # out_of_bounds
 	    // CHECK: assert-failure
@@ -87,12 +87,12 @@ contract Testing {
 	    // CHECK: assert-failure
 
         // CHECK: block4: # buffer_read
-		// CHECK: ty:int8 %a = %temp.72
-	    // CHECK: ty:int16 %b = %temp.73
-	    // CHECK: ty:int32 %c = %temp.74
-	    // CHECK: ty:int64 %d = %temp.75
-	    // CHECK: ty:int128 %e = %temp.76
-	    // CHECK: ty:int256 %f = %temp.77
+		// CHECK: ty:int8 %a = %temp.75
+	    // CHECK: ty:int16 %b = %temp.76
+	    // CHECK: ty:int32 %c = %temp.77
+	    // CHECK: ty:int64 %d = %temp.78
+	    // CHECK: ty:int128 %e = %temp.79
+	    // CHECK: ty:int256 %f = %temp.80
 
         return (a, b, c, d, e, f);
      }
@@ -101,15 +101,15 @@ contract Testing {
     function fixedBytes(bytes memory buffer) public pure returns (bytes1, bytes5, bytes20, bytes32) {
         (bytes1 a, bytes5 b, bytes20 c, bytes32 d) = abi.decode(buffer, (bytes1, bytes5, bytes20, bytes32));
 
-        // CHECK: ty:uint32 %temp.78 = (builtin ArrayLength ((arg #0)))
-	    // CHECK: branchcond (uint32 58 <= %temp.78), block1, block2
+        // CHECK: ty:uint32 %temp.81 = (builtin ArrayLength ((arg #0)))
+	    // CHECK: branchcond (uint32 58 <= %temp.81), block1, block2
 
         // CHECK: block1: # inbounds
-	    // CHECK: ty:bytes1 %temp.79 = (builtin ReadFromBuffer ((arg #0), uint32 0))
-	    // CHECK: ty:bytes5 %temp.80 = (builtin ReadFromBuffer ((arg #0), uint32 1))
-	    // CHECK: ty:bytes20 %temp.81 = (builtin ReadFromBuffer ((arg #0), uint32 6))
-	    // CHECK: ty:bytes32 %temp.82 = (builtin ReadFromBuffer ((arg #0), uint32 26))
-	    // CHECK: branchcond (unsigned less uint32 58 < %temp.78), block3, block4
+	    // CHECK: ty:bytes1 %temp.82 = (builtin ReadFromBuffer ((arg #0), uint32 0))
+	    // CHECK: ty:bytes5 %temp.83 = (builtin ReadFromBuffer ((arg #0), uint32 1))
+	    // CHECK: ty:bytes20 %temp.84 = (builtin ReadFromBuffer ((arg #0), uint32 6))
+	    // CHECK: ty:bytes32 %temp.85 = (builtin ReadFromBuffer ((arg #0), uint32 26))
+	    // CHECK: branchcond (unsigned less uint32 58 < %temp.81), block3, block4
 
         // CHECK: block2: # out_of_bounds
 	    // CHECK: assert-failure
@@ -118,10 +118,10 @@ contract Testing {
 	    // CHECK: assert-failure
 
         // CHECK: block4: # buffer_read
-    	// CHECK: ty:bytes1 %a = %temp.79
-	    // CHECK: ty:bytes5 %b = %temp.80
-	    // CHECK: ty:bytes20 %c = %temp.81
-	    // CHECK: ty:bytes32 %d = %temp.82
+		// CHECK: ty:bytes1 %a = %temp.82
+	    // CHECK: ty:bytes5 %b = %temp.83
+	    // CHECK: ty:bytes20 %c = %temp.84
+	    // CHECK: ty:bytes32 %d = %temp.85
 
         return (a, b, c, d);
     }
@@ -131,38 +131,38 @@ contract Testing {
         (bytes memory a, string memory b) = abi.decode(buffer, (bytes, string));
 
         // CHECK: ty:bytes %buffer = (arg #0)
-	    // CHECK: ty:uint32 %temp.83 = (builtin ArrayLength ((arg #0)))
-	    // CHECK: branchcond (uint32 4 <= %temp.83), block1, block2
+	    // CHECK: ty:uint32 %temp.86 = (builtin ArrayLength ((arg #0)))
+	    // CHECK: branchcond (uint32 4 <= %temp.86), block1, block2
 
         // CHECK: block1: # inbounds
-	    // CHECK: ty:uint32 %temp.84 = (builtin ReadFromBuffer ((arg #0), uint32 0))
-	    // CHECK: ty:uint32 %1.cse_temp = ((%temp.84 + uint32 4) + uint32 0)
-	    // CHECK: branchcond (%1.cse_temp <= %temp.83), block3, block4
+	    // CHECK: ty:uint32 %temp.87 = (builtin ReadFromBuffer ((arg #0), uint32 0))
+	    // CHECK: ty:uint32 %1.cse_temp = ((%temp.87 + uint32 4) + uint32 0)
+	    // CHECK: branchcond (%1.cse_temp <= %temp.86), block3, block4
 
         // CHECK: block2: # out_of_bounds
 	    // CHECK: assert-failure
 
         // CHECK: block3: # inbounds
-	    // CHECK: ty:bytes %temp.85 = (alloc bytes len %temp.84)
-	    // CHECK: memcpy src: (advance ptr: %buffer, by: uint32 4), dest: %temp.85, bytes_len: %temp.84
+	    // CHECK: ty:bytes %temp.88 = (alloc bytes len %temp.87)
+	    // CHECK: memcpy src: (advance ptr: %buffer, by: uint32 4), dest: %temp.88, bytes_len: %temp.87
 	    // CHECK: ty:uint32 %2.cse_temp = (%1.cse_temp + uint32 4)
-	    // CHECK: branchcond (%2.cse_temp <= %temp.83), block5, block6
+	    // CHECK: branchcond (%2.cse_temp <= %temp.86), block5, block6
 
         // CHECK: block4: # out_of_bounds
 	    // CHECK: assert-failure
 
         // CHECK: block5: # inbounds
-	    // CHECK: ty:uint32 %temp.86 = (builtin ReadFromBuffer ((arg #0), (uint32 0 + (%temp.84 + uint32 4))))
-	    // CHECK: ty:uint32 %3.cse_temp = ((%temp.86 + uint32 4) + %1.cse_temp)
-	    // CHECK: branchcond (%3.cse_temp <= %temp.83), block7, block8
+	    // CHECK: ty:uint32 %temp.89 = (builtin ReadFromBuffer ((arg #0), (uint32 0 + (%temp.87 + uint32 4))))
+	    // CHECK: ty:uint32 %3.cse_temp = ((%temp.89 + uint32 4) + %1.cse_temp)
+	    // CHECK: branchcond (%3.cse_temp <= %temp.86), block7, block8
 
         // CHECK: block6: # out_of_bounds
     	// CHECK: assert-failure
 
         // CHECK: block7: # inbounds
-	    // CHECK: ty:string %temp.87 = (alloc string len %temp.86)
-	    // CHECK: memcpy src: (advance ptr: %buffer, by: %2.cse_temp), dest: %temp.87, bytes_len: %temp.86
-	    // CHECK: branchcond (unsigned less %3.cse_temp < %temp.83), block9, block10
+	    // CHECK: ty:string %temp.90 = (alloc string len %temp.89)
+	    // CHECK: memcpy src: (advance ptr: %buffer, by: %2.cse_temp), dest: %temp.90, bytes_len: %temp.89
+	    // CHECK: branchcond (unsigned less %3.cse_temp < %temp.86), block9, block10
 
         // CHECK: block8: # out_of_bounds
 	    // CHECK: assert-failure
@@ -171,8 +171,8 @@ contract Testing {
 	    // CHECK: assert-failure
 
         // CHECK: block10: # buffer_read
-	    // CHECK: ty:bytes %a = %temp.85
-	    // CHECK: ty:string %b = %temp.87
+	    // CHECK: ty:bytes %a = %temp.88
+	    // CHECK: ty:string %b = %temp.90
 
         return (a, b);
     }
@@ -184,12 +184,12 @@ contract Testing {
     // BEGIN-CHECK: Testing::Testing::function::decodeEnum__bytes
     function decodeEnum(bytes memory buffer) public pure returns (WeekDays) {
         WeekDays a = abi.decode(buffer, (WeekDays));
-	    // CHECK: ty:uint32 %temp.91 = (builtin ArrayLength ((arg #0)))
-	    // CHECK: branchcond (uint32 1 <= %temp.91), block1, block2
+	    // CHECK: ty:uint32 %temp.94 = (builtin ArrayLength ((arg #0)))
+	    // CHECK: branchcond (uint32 1 <= %temp.94), block1, block2
 
         // CHECK: block1: # inbounds
-	    // CHECK: ty:enum Testing.WeekDays %temp.92 = (builtin ReadFromBuffer ((arg #0), uint32 0))
-	    // CHECK: branchcond (unsigned less uint32 1 < %temp.91), block3, block4
+	    // CHECK: ty:enum Testing.WeekDays %temp.95 = (builtin ReadFromBuffer ((arg #0), uint32 0))
+	    // CHECK: branchcond (unsigned less uint32 1 < %temp.94), block3, block4
 
         // CHECK: block2: # out_of_bounds
 	    // CHECK: assert-failure
@@ -198,7 +198,7 @@ contract Testing {
 	    // CHECK: assert-failure
 
         // CHECK: block4: # buffer_read
-	    // CHECK: ty:enum Testing.WeekDays %a = %temp.92
+	    // CHECK: ty:enum Testing.WeekDays %a = %temp.95
         return a;
     }
 
@@ -217,17 +217,17 @@ contract Testing {
     function decodeStruct(bytes memory buffer) public pure returns (noPadStruct memory, PaddedStruct memory) {
         (noPadStruct memory a, PaddedStruct memory b) = abi.decode(buffer, (noPadStruct, PaddedStruct));
 
-        // CHECK: ty:uint32 %temp.93 = (builtin ArrayLength ((arg #0)))
-	    // CHECK: branchcond (uint32 57 <= %temp.93), block1, block2
+        // CHECK: ty:uint32 %temp.96 = (builtin ArrayLength ((arg #0)))
+	    // CHECK: branchcond (uint32 57 <= %temp.96), block1, block2
 
         // CHECK: block1: # inbounds
-	    // CHECK: ty:struct Testing.noPadStruct %temp.94 = struct {  }
-	    // CHECK: memcpy src: %buffer, dest: %temp.94, bytes_len: uint32 8
-	    // CHECK: ty:uint128 %temp.95 = (builtin ReadFromBuffer ((arg #0), uint32 8))
-	    // CHECK: ty:uint8 %temp.96 = (builtin ReadFromBuffer ((arg #0), uint32 24))
-	    // CHECK: ty:bytes32 %temp.97 = (builtin ReadFromBuffer ((arg #0), uint32 25))
-	    // CHECK: ty:struct Testing.PaddedStruct %temp.98 = struct { %temp.95, %temp.96, %temp.97 }
-	    // CHECK: branchcond (unsigned less uint32 57 < %temp.93), block3, block4
+	    // CHECK: ty:struct Testing.noPadStruct %temp.97 = struct {  }
+	    // CHECK: memcpy src: %buffer, dest: %temp.97, bytes_len: uint32 8
+	    // CHECK: ty:uint128 %temp.98 = (builtin ReadFromBuffer ((arg #0), uint32 8))
+	    // CHECK: ty:uint8 %temp.99 = (builtin ReadFromBuffer ((arg #0), uint32 24))
+	    // CHECK: ty:bytes32 %temp.100 = (builtin ReadFromBuffer ((arg #0), uint32 25))
+	    // CHECK: ty:struct Testing.PaddedStruct %temp.101 = struct { %temp.98, %temp.99, %temp.100 }
+	    // CHECK: branchcond (unsigned less uint32 57 < %temp.96), block3, block4
 
         // CHECK: block2: # out_of_bounds
 	    // CHECK: assert-failure
@@ -236,8 +236,8 @@ contract Testing {
 	    // CHECK: assert-failure
 
         // CHECK: block4: # buffer_read
-	    // CHECK: ty:struct Testing.noPadStruct %a = %temp.94
-	    // CHECK: ty:struct Testing.PaddedStruct %b = %temp.98
+	    // CHECK: ty:struct Testing.noPadStruct %a = %temp.97
+	    // CHECK: ty:struct Testing.PaddedStruct %b = %temp.101
         return (a, b);
     }
 
@@ -246,31 +246,31 @@ contract Testing {
         (uint32[4] memory a, noPadStruct[2] memory b, noPadStruct[] memory c) =
         abi.decode(buffer, (uint32[4], noPadStruct[2], noPadStruct[]));
 
-        // CHECK: ty:uint32 %temp.99 = (builtin ArrayLength ((arg #0)))
-	    // CHECK: branchcond (uint32 32 <= %temp.99), block1, block2
+        // CHECK: ty:uint32 %temp.102 = (builtin ArrayLength ((arg #0)))
+	    // CHECK: branchcond (uint32 32 <= %temp.102), block1, block2
 
         // CHECK: block1: # inbounds
-	    // CHECK: ty:uint32[4] %temp.100 =  [  ]
-	    // CHECK: memcpy src: %buffer, dest: %temp.100, bytes_len: uint32 16
-	    // CHECK: ty:struct Testing.noPadStruct[2] %temp.101 =  [  ]
-	    // CHECK: memcpy src: (advance ptr: %buffer, by: uint32 16), dest: %temp.101, bytes_len: uint32 16
-	    // CHECK: branchcond (uint32 36 <= %temp.99), block3, block4
+	    // CHECK: ty:uint32[4] %temp.103 =  [  ]
+	    // CHECK: memcpy src: %buffer, dest: %temp.103, bytes_len: uint32 16
+	    // CHECK: ty:struct Testing.noPadStruct[2] %temp.104 =  [  ]
+	    // CHECK: memcpy src: (advance ptr: %buffer, by: uint32 16), dest: %temp.104, bytes_len: uint32 16
+	    // CHECK: branchcond (uint32 36 <= %temp.102), block3, block4
 
         // CHECK: block2: # out_of_bounds
 	    // CHECK: assert-failure
 
         // CHECK: block3: # inbounds
-	    // CHECK: ty:uint32 %temp.102 = (builtin ReadFromBuffer ((arg #0), uint32 32))
-	    // CHECK: ty:struct Testing.noPadStruct[] %temp.103 = (alloc struct Testing.noPadStruct[] len %temp.102)
-	    // CHECK: ty:uint32 %1.cse_temp = (%temp.102 * uint32 8)
-	    // CHECK: branchcond ((uint32 36 + %1.cse_temp) <= %temp.99), block5, block6
+	    // CHECK: ty:uint32 %temp.105 = (builtin ReadFromBuffer ((arg #0), uint32 32))
+	    // CHECK: ty:struct Testing.noPadStruct[] %temp.106 = (alloc struct Testing.noPadStruct[] len %temp.105)
+	    // CHECK: ty:uint32 %1.cse_temp = (%temp.105 * uint32 8)
+	    // CHECK: branchcond ((uint32 36 + %1.cse_temp) <= %temp.102), block5, block6
 
         // CHECK: block4: # out_of_bounds
 	    // CHECK: assert-failure
 
         // CHECK: block5: # inbounds
-	    // CHECK: memcpy src: (advance ptr: %buffer, by: uint32 36), dest: %temp.103, bytes_len: %1.cse_temp
-	    // CHECK: branchcond (unsigned less (uint32 32 + (%1.cse_temp + uint32 4)) < %temp.99), block7, block8
+	    // CHECK: memcpy src: (advance ptr: %buffer, by: uint32 36), dest: %temp.106, bytes_len: %1.cse_temp
+	    // CHECK: branchcond (unsigned less (uint32 32 + (%1.cse_temp + uint32 4)) < %temp.102), block7, block8
 
         // CHECK: block6: # out_of_bounds
 	    // CHECK: assert-failure
@@ -279,9 +279,9 @@ contract Testing {
 	    // CHECK: assert-failure
 
         // CHECK: block8: # buffer_read
-	    // CHECK: ty:uint32[4] %a = %temp.100
-	    // CHECK: ty:struct Testing.noPadStruct[2] %b = %temp.101
-	    // CHECK: ty:struct Testing.noPadStruct[] %c = %temp.103
+	    // CHECK: ty:uint32[4] %a = %temp.103
+	    // CHECK: ty:struct Testing.noPadStruct[2] %b = %temp.104
+	    // CHECK: ty:struct Testing.noPadStruct[] %c = %temp.106
 
         return (a, b, c);
     }

+ 9 - 30
tests/solana.rs

@@ -1424,7 +1424,7 @@ impl<'a> SyscallObject<UserError> for SyscallInvokeSignedC<'a> {
                     instruction => panic!("instruction {} not supported", instruction),
                 }
             } else {
-                let data_id: Account = instruction.data[..32].try_into().unwrap();
+                let data_id: Account = instruction.accounts[0].pubkey.0;
 
                 println!(
                     "calling {} program_id {}",
@@ -1594,17 +1594,19 @@ impl VirtualMachine {
         res
     }
 
-    fn constructor(&mut self, name: &str, args: &[BorshToken]) {
-        self.constructor_expected(0, name, args)
+    /// FIXME: remove name argument
+    fn constructor(&mut self, _name: &str, args: &[BorshToken]) {
+        self.constructor_expected(0, args)
     }
 
-    fn constructor_expected(&mut self, expected: u64, name: &str, args: &[BorshToken]) {
+    fn constructor_expected(&mut self, expected: u64, args: &[BorshToken]) {
         self.return_data = None;
 
         let program = &self.stack[0];
         println!("constructor for {}", hex::encode(program.data));
 
-        let mut calldata = VirtualMachine::input(&program.data, name);
+        let mut calldata = discriminator("global", "new");
+
         if program.abi.as_ref().unwrap().constructor.is_some() {
             let mut encoded_data = encode_arguments(args);
             calldata.append(&mut encoded_data);
@@ -1639,10 +1641,7 @@ impl VirtualMachine {
 
         println!("function {} for {}", name, hex::encode(program.data));
 
-        let mut calldata = VirtualMachine::input(&program.data, name);
-
-        let selector = discriminator("global", name);
-        calldata.extend_from_slice(&selector);
+        let mut calldata = discriminator("global", name);
         let mut encoded_args = encode_arguments(args);
         calldata.append(&mut encoded_args);
 
@@ -1677,9 +1676,7 @@ impl VirtualMachine {
 
         println!("function for {}", hex::encode(program.data));
 
-        let mut calldata = VirtualMachine::input(&program.data, name);
-
-        println!("input: {}", hex::encode(&calldata));
+        let mut calldata = Vec::new();
 
         let selector = discriminator("global", name);
         calldata.extend_from_slice(&selector);
@@ -1693,24 +1690,6 @@ impl VirtualMachine {
         self.execute(&default_metas, &calldata)
     }
 
-    fn input(recv: &Account, name: &str) -> Vec<u8> {
-        let mut calldata: Vec<u8> = recv.to_vec();
-        calldata.extend_from_slice(&[0u8; 32]);
-        calldata.extend_from_slice(&0u64.to_le_bytes());
-
-        let mut hasher = Keccak::v256();
-        let mut hash = [0u8; 32];
-        hasher.update(name.as_bytes());
-        hasher.finalize(&mut hash);
-        calldata.extend(&hash[0..4]);
-
-        let seeds_len = 0u8;
-
-        calldata.push(seeds_len);
-
-        calldata
-    }
-
     fn default_metas(&self) -> Vec<AccountMeta> {
         // Just include everything
         let mut accounts = vec![AccountMeta {

+ 2 - 2
tests/solana_tests/create_contract.rs

@@ -162,7 +162,7 @@ fn create_contract_wrong_program_id() {
     let program = &vm.programs[0].program;
     vm.account_data.get_mut(program).unwrap().data = code;
 
-    vm.constructor_expected(7 << 32, "bar0", &[]);
+    vm.constructor_expected(7 << 32, &[]);
 
     assert_eq!(
         vm.logs,
@@ -303,7 +303,7 @@ fn account_too_small() {
 
     vm.account_data.get_mut(&data).unwrap().data.truncate(100);
 
-    vm.constructor_expected(5 << 32, "bar", &[]);
+    vm.constructor_expected(5 << 32, &[]);
 }
 
 #[test]