Browse Source

Support retrieving balance of account on Solana

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 4 years ago
parent
commit
c898fb79a1

+ 1 - 0
CHANGELOG.md

@@ -9,6 +9,7 @@ will be documented here.
 - Added supported for Events on Solana
 - `msg.data`, `msg.sig`, `msg.value`, `block.number`, and `block.slot` are
   implemented for Solana
+- Implemented retrieving account balances on Solana
 - Verify ed25519 signatures with `signatureVerify()` on Solana
 - Added support for Rational numbers
 

+ 5 - 0
integration/solana/balances.sol

@@ -0,0 +1,5 @@
+contract balances {
+	function get_balance(address addr) public view returns (uint64) {
+		return addr.balance;
+	}
+}

+ 26 - 0
integration/solana/balances.spec.ts

@@ -0,0 +1,26 @@
+import expect from 'expect';
+import { establishConnection } from './index';
+
+describe('Deploy solang contract and test', () => {
+    it('balances', async function () {
+        this.timeout(50000);
+
+        let conn = await establishConnection();
+
+        let hash_functions = await conn.loadProgram("bundle.so", "balances.abi");
+
+        // call the constructor
+        await hash_functions.call_constructor(conn, 'balances', []);
+
+        let payer = '0x' + conn.payerAccount.publicKey.toBuffer().toString('hex');
+
+        let res = await hash_functions.call_function(conn, "get_balance", [payer], [conn.payerAccount.publicKey]);
+        let bal = Number(res[0]);
+
+        let rpc_bal = await conn.connection.getBalance(conn.payerAccount.publicKey);
+
+        console.log("bal from rpc " + bal);
+
+        expect(bal).toBe(rpc_bal);
+    });
+});

+ 0 - 1
integration/solana/index.ts

@@ -14,7 +14,6 @@ import fs from 'fs';
 import { AbiItem } from 'web3-utils';
 import { utils } from 'ethers';
 import crypto from 'crypto';
-import { encode } from 'querystring';
 const Web3EthAbi = require('web3-eth-abi');
 
 const default_url: string = "http://localhost:8899";

+ 40 - 0
src/emit/solana.rs

@@ -3349,6 +3349,46 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
                     )
                     .into()
             }
+            ast::Expression::Builtin(_, _, ast::Builtin::Balance, args) => {
+                assert_eq!(args.len(), 1);
+
+                let address = binary.build_alloca(function, binary.address_type(ns), "address");
+
+                binary.builder.build_store(
+                    address,
+                    self.expression(binary, &args[0], vartab, function, ns)
+                        .into_int_value(),
+                );
+
+                let account_lamport = binary.module.get_function("sol_account_lamport").unwrap();
+
+                let parameters = self.sol_parameters(binary);
+
+                let params = account_lamport.get_type().get_param_types();
+
+                let lamport = binary
+                    .builder
+                    .build_call(
+                        account_lamport,
+                        &[
+                            binary
+                                .builder
+                                .build_pointer_cast(address, params[0].into_pointer_type(), "")
+                                .into(),
+                            binary
+                                .builder
+                                .build_pointer_cast(parameters, params[1].into_pointer_type(), "")
+                                .into(),
+                        ],
+                        "",
+                    )
+                    .try_as_basic_value()
+                    .left()
+                    .unwrap()
+                    .into_pointer_value();
+
+                binary.builder.build_load(lamport, "lamport")
+            }
             _ => unimplemented!(),
         }
     }

+ 1 - 0
src/sema/mutability.rs

@@ -255,6 +255,7 @@ fn read_expression(expr: &Expression, state: &mut StateCheck) -> bool {
         | Expression::Builtin(loc, _, Builtin::GasLimit, _)
         | Expression::Builtin(loc, _, Builtin::TombstoneDeposit, _)
         | Expression::Builtin(loc, _, Builtin::MinimumBalance, _)
+        | Expression::Builtin(loc, _, Builtin::Balance, _)
         | Expression::Builtin(loc, _, Builtin::Random, _) => state.read(loc),
         Expression::Builtin(loc, _, Builtin::PayableSend, _)
         | Expression::Builtin(loc, _, Builtin::PayableTransfer, _)

BIN
stdlib/bpf/solana.bc


+ 23 - 0
stdlib/solana.c

@@ -226,6 +226,29 @@ uint64_t create_contract(uint8_t *input, uint32_t input_len, uint64_t space, Sol
     return sol_invoke_signed_c(&instruction, params->ka, params->ka_num, NULL, 0);
 }
 
+uint64_t *sol_account_lamport(
+    uint8_t *address,
+    SolParameters *params)
+{
+    SolPubkey pubkey;
+
+    __be32toleN(address, pubkey.x, SIZE_PUBKEY);
+
+    for (int i = 0; i < params->ka_num; i++)
+    {
+        if (SolPubkey_same(&pubkey, params->ka[i].key))
+        {
+            return params->ka[i].lamports;
+        }
+    }
+
+    sol_log_pubkey(&pubkey);
+    sol_log("account missing from transaction");
+    sol_panic();
+
+    return NULL;
+}
+
 struct ed25519_instruction_sig
 {
     uint16_t signature_offset;

+ 23 - 4
tests/solana.rs

@@ -36,9 +36,9 @@ use tiny_keccak::{Hasher, Keccak};
 
 mod solana_tests;
 
-type Account = [u8; 32];
+pub type Account = [u8; 32];
 
-fn account_new() -> Account {
+pub fn account_new() -> Account {
     let mut rng = rand::thread_rng();
 
     let mut a = [0u8; 32];
@@ -51,6 +51,7 @@ fn account_new() -> Account {
 struct AccountState {
     data: Vec<u8>,
     owner: Option<Account>,
+    lamports: u64,
 }
 
 struct VirtualMachine {
@@ -156,6 +157,7 @@ fn build_solidity(src: &str) -> VirtualMachine {
             AccountState {
                 data: code.clone(),
                 owner: None,
+                lamports: 0,
             },
         );
 
@@ -168,6 +170,7 @@ fn build_solidity(src: &str) -> VirtualMachine {
             AccountState {
                 data: [0u8; 4096].to_vec(),
                 owner: Some(program),
+                lamports: 0,
             },
         );
 
@@ -198,6 +201,7 @@ fn build_solidity(src: &str) -> VirtualMachine {
         AccountState {
             data: bincode::serialize(&clock_layout).unwrap(),
             owner: None,
+            lamports: 0,
         },
     );
 
@@ -250,7 +254,7 @@ fn serialize_parameters(
         // owner
         v.write_all(&acc.owner.unwrap_or([0u8; 32])).unwrap();
         // lamports
-        v.write_u64::<LittleEndian>(0).unwrap();
+        v.write_u64::<LittleEndian>(acc.lamports).unwrap();
 
         // account data
         v.write_u64::<LittleEndian>(acc.data.len() as u64).unwrap();
@@ -1020,6 +1024,7 @@ impl<'a> SyscallObject<UserError> for SyscallInvokeSignedC<'a> {
                             AccountState {
                                 data: vec![0; create_account.space as usize],
                                 owner: Some(create_account.program_id),
+                                lamports: 0,
                             },
                         );
 
@@ -1258,12 +1263,25 @@ impl VirtualMachine {
         args: &[Token],
         seeds: &[&(Account, Vec<u8>)],
         value: u64,
+        sender: Option<&Account>,
     ) -> Vec<Token> {
         let program = &self.stack[0];
 
         println!("function for {}", hex::encode(&program.data));
 
-        let mut calldata = VirtualMachine::input(&program.data, &account_new(), value, name, seeds);
+        let new = account_new();
+
+        let mut calldata = VirtualMachine::input(
+            &program.data,
+            if let Some(sender) = sender {
+                sender
+            } else {
+                &new
+            },
+            value,
+            name,
+            seeds,
+        );
 
         println!("input: {} seeds {:?}", hex::encode(&calldata), seeds);
 
@@ -1354,6 +1372,7 @@ impl VirtualMachine {
             AccountState {
                 data: vec![],
                 owner: Some([0u8; 32]),
+                lamports: 0,
             },
         );
 

+ 5 - 5
tests/solana_tests/abi.rs

@@ -37,9 +37,9 @@ fn packed() {
 
     vm.constructor("bar", &[], 0);
 
-    vm.function("test", &[], &[], 0);
-    vm.function("test2", &[], &[], 0);
-    vm.function("test3", &[], &[], 0);
+    vm.function("test", &[], &[], 0, None);
+    vm.function("test2", &[], &[], 0, None);
+    vm.function("test3", &[], &[], 0, None);
 }
 
 #[test]
@@ -56,7 +56,7 @@ fn inherited() {
 
     vm.constructor("bar", &[], 0);
 
-    vm.function("test", &[], &[], 0);
+    vm.function("test", &[], &[], 0, None);
 
     let mut vm = build_solidity(
         r#"
@@ -69,5 +69,5 @@ fn inherited() {
 
     vm.constructor("bar", &[], 0);
 
-    vm.function("test", &[], &[], 0);
+    vm.function("test", &[], &[], 0, None);
 }

+ 14 - 6
tests/solana_tests/accessor.rs

@@ -12,7 +12,7 @@ fn types() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("f1", &[], &[], 0);
+    let returns = vm.function("f1", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(102))]);
 
@@ -25,7 +25,13 @@ fn types() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("f1", &[Token::Uint(ethereum_types::U256::from(2))], &[], 0);
+    let returns = vm.function(
+        "f1",
+        &[Token::Uint(ethereum_types::U256::from(2))],
+        &[],
+        0,
+        None,
+    );
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(5))]);
 
@@ -53,6 +59,7 @@ fn types() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(2))]);
@@ -76,6 +83,7 @@ fn types() {
         &[Token::Int(ethereum_types::U256::from(4000))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(2))]);
@@ -97,7 +105,7 @@ fn interfaces() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("f1", &[], &[], 0);
+    let returns = vm.function("f1", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::FixedBytes(b"ab".to_vec())]);
 }
@@ -113,7 +121,7 @@ fn constant() {
 
     vm.constructor("x", &[], 0);
 
-    let returns = vm.function("z", &[], &[], 0);
+    let returns = vm.function("z", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -132,7 +140,7 @@ fn constant() {
 
     vm.constructor("x", &[], 0);
 
-    let returns = vm.function("z", &[], &[], 0);
+    let returns = vm.function("z", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -151,7 +159,7 @@ fn constant() {
 
     vm.constructor("x", &[], 0);
 
-    let returns = vm.function("z", &[], &[], 0);
+    let returns = vm.function("z", &[], &[], 0, None);
 
     assert_eq!(
         returns,

+ 55 - 31
tests/solana_tests/arrays.rs

@@ -19,7 +19,7 @@ fn fixed_array() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -53,7 +53,7 @@ fn fixed_array() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -110,7 +110,7 @@ fn fixed_array() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -140,6 +140,7 @@ fn fixed_array() {
         ])],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(26))]);
@@ -189,12 +190,13 @@ fn dynamic_array_fixed_elements() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(26))]);
 
     // test that the abi encoder can handle fixed arrays
-    let returns = vm.function("set", &[], &[], 0);
+    let returns = vm.function("set", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -258,11 +260,12 @@ fn fixed_array_dynamic_elements() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(127))]);
 
-    let returns = vm.function("set", &[], &[], 0);
+    let returns = vm.function("set", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -327,11 +330,12 @@ fn dynamic_array_dynamic_elements() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(127))]);
 
-    let returns = vm.function("set", &[], &[], 0);
+    let returns = vm.function("set", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -387,6 +391,7 @@ fn fixed_array_fixed_elements_storage() {
         ],
         &[],
         0,
+        None,
     );
 
     vm.function(
@@ -397,6 +402,7 @@ fn fixed_array_fixed_elements_storage() {
         ],
         &[],
         0,
+        None,
     );
 
     let returns = vm.function(
@@ -404,6 +410,7 @@ fn fixed_array_fixed_elements_storage() {
         &[Token::Uint(ethereum_types::U256::from(2))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(
@@ -411,7 +418,7 @@ fn fixed_array_fixed_elements_storage() {
         vec![Token::Int(ethereum_types::U256::from(12123123)),],
     );
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -433,9 +440,10 @@ fn fixed_array_fixed_elements_storage() {
         ])],
         &[],
         0,
+        None,
     );
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -447,9 +455,9 @@ fn fixed_array_fixed_elements_storage() {
         ]),],
     );
 
-    vm.function("del", &[], &[], 0);
+    vm.function("del", &[], &[], 0, None);
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -501,6 +509,7 @@ fn fixed_array_dynamic_elements_storage() {
         ],
         &[],
         0,
+        None,
     );
 
     vm.function(
@@ -513,6 +522,7 @@ fn fixed_array_dynamic_elements_storage() {
         ],
         &[],
         0,
+        None,
     );
 
     let returns = vm.function(
@@ -520,11 +530,12 @@ fn fixed_array_dynamic_elements_storage() {
         &[Token::Uint(ethereum_types::U256::from(2))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::String(String::from("abcd"))]);
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -548,9 +559,10 @@ fn fixed_array_dynamic_elements_storage() {
         ])],
         &[],
         0,
+        None,
     );
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -562,9 +574,9 @@ fn fixed_array_dynamic_elements_storage() {
         ]),],
     );
 
-    vm.function("del", &[], &[], 0);
+    vm.function("del", &[], &[], 0, None);
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -620,7 +632,7 @@ fn storage_simple_dynamic_array() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("len", &[], &[], 0);
+    let returns = vm.function("len", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
 
@@ -629,15 +641,17 @@ fn storage_simple_dynamic_array() {
         &[Token::Int(ethereum_types::U256::from(102))],
         &[],
         0,
+        None,
     );
 
-    vm.function("push_zero", &[], &[], 0);
+    vm.function("push_zero", &[], &[], 0, None);
 
     vm.function(
         "push",
         &[Token::Int(ethereum_types::U256::from(12345678901u64))],
         &[],
         0,
+        None,
     );
 
     let returns = vm.function(
@@ -645,6 +659,7 @@ fn storage_simple_dynamic_array() {
         &[Token::Uint(ethereum_types::U256::from(0))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(102))]);
@@ -654,6 +669,7 @@ fn storage_simple_dynamic_array() {
         &[Token::Uint(ethereum_types::U256::from(1))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(0))]);
@@ -663,6 +679,7 @@ fn storage_simple_dynamic_array() {
         &[Token::Uint(ethereum_types::U256::from(2))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(
@@ -670,7 +687,7 @@ fn storage_simple_dynamic_array() {
         vec![Token::Int(ethereum_types::U256::from(12345678901u64))]
     );
 
-    let returns = vm.function("copy", &[], &[], 0);
+    let returns = vm.function("copy", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -681,14 +698,14 @@ fn storage_simple_dynamic_array() {
         ])],
     );
 
-    let returns = vm.function("pop", &[], &[], 0);
+    let returns = vm.function("pop", &[], &[], 0, None);
 
     assert_eq!(
         returns,
         vec![Token::Int(ethereum_types::U256::from(12345678901u64))]
     );
 
-    let returns = vm.function("len", &[], &[], 0);
+    let returns = vm.function("len", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(2))]);
 
@@ -705,9 +722,10 @@ fn storage_simple_dynamic_array() {
         ])],
         &[],
         0,
+        None,
     );
 
-    let returns = vm.function("copy", &[], &[], 0);
+    let returns = vm.function("copy", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -722,9 +740,9 @@ fn storage_simple_dynamic_array() {
         ])],
     );
 
-    vm.function("rm", &[], &[], 0);
+    vm.function("rm", &[], &[], 0, None);
 
-    let returns = vm.function("len", &[], &[], 0);
+    let returns = vm.function("len", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
 }
@@ -745,7 +763,7 @@ fn storage_pop_running_on_empty() {
 
     vm.constructor("foo", &[], 0);
 
-    vm.function("pop", &[], &[], 0);
+    vm.function("pop", &[], &[], 0, None);
 }
 
 #[test]
@@ -802,7 +820,7 @@ fn storage_dynamic_array_of_structs() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("len", &[], &[], 0);
+    let returns = vm.function("len", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
 
@@ -814,9 +832,10 @@ fn storage_dynamic_array_of_structs() {
         ])],
         &[],
         0,
+        None,
     );
 
-    vm.function("push_empty", &[], &[], 0);
+    vm.function("push_empty", &[], &[], 0, None);
 
     vm.function(
         "push2",
@@ -826,6 +845,7 @@ fn storage_dynamic_array_of_structs() {
         ])],
         &[],
         0,
+        None,
     );
 
     let returns = vm.function(
@@ -833,6 +853,7 @@ fn storage_dynamic_array_of_structs() {
         &[Token::Uint(ethereum_types::U256::from(0))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(
@@ -848,6 +869,7 @@ fn storage_dynamic_array_of_structs() {
         &[Token::Uint(ethereum_types::U256::from(1))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(
@@ -863,6 +885,7 @@ fn storage_dynamic_array_of_structs() {
         &[Token::Uint(ethereum_types::U256::from(2))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(
@@ -873,7 +896,7 @@ fn storage_dynamic_array_of_structs() {
         ])]
     );
 
-    let returns = vm.function("copy", &[], &[], 0);
+    let returns = vm.function("copy", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -893,7 +916,7 @@ fn storage_dynamic_array_of_structs() {
         ])]
     );
 
-    let returns = vm.function("pop", &[], &[], 0);
+    let returns = vm.function("pop", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -903,7 +926,7 @@ fn storage_dynamic_array_of_structs() {
         ])]
     );
 
-    let returns = vm.function("len", &[], &[], 0);
+    let returns = vm.function("len", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(2))]);
 
@@ -937,9 +960,10 @@ fn storage_dynamic_array_of_structs() {
         ])],
         &[],
         0,
+        None,
     );
 
-    let returns = vm.function("copy", &[], &[], 0);
+    let returns = vm.function("copy", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -971,9 +995,9 @@ fn storage_dynamic_array_of_structs() {
         ])]
     );
 
-    vm.function("rm", &[], &[], 0);
+    vm.function("rm", &[], &[], 0, None);
 
-    let returns = vm.function("len", &[], &[], 0);
+    let returns = vm.function("len", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
 }

+ 32 - 3
tests/solana_tests/balance.rs

@@ -1,4 +1,4 @@
-use crate::build_solidity;
+use crate::{account_new, build_solidity, AccountState};
 use ethabi::Token;
 
 #[test]
@@ -14,7 +14,7 @@ fn msg_value() {
 
     vm.constructor("c", &[], 0);
 
-    let returns = vm.function("test", &[], &[], 102);
+    let returns = vm.function("test", &[], &[], 102, None);
 
     assert_eq!(returns[0], Token::Uint(ethereum_types::U256::from(306)));
 }
@@ -54,5 +54,34 @@ fn function_not_payable() {
 
     vm.constructor("c", &[], 0);
 
-    vm.function("test", &[], &[], 102);
+    vm.function("test", &[], &[], 102, None);
+}
+
+#[test]
+fn get_balance() {
+    let mut vm = build_solidity(
+        r#"
+        contract c {
+            function test() public view returns (uint64) {
+                return msg.sender.balance;
+            }
+        }"#,
+    );
+
+    vm.constructor("c", &[], 0);
+
+    let new = account_new();
+
+    vm.account_data.insert(
+        new,
+        AccountState {
+            data: Vec::new(),
+            owner: None,
+            lamports: 102,
+        },
+    );
+
+    let returns = vm.function("test", &[], &[], 0, Some(&new));
+
+    assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(102))]);
 }

+ 5 - 4
tests/solana_tests/builtin.rs

@@ -26,21 +26,21 @@ fn builtins() {
 
     vm.constructor("timestamp", &[], 0);
 
-    let returns = vm.function("mr_now", &[], &[], 0);
+    let returns = vm.function("mr_now", &[], &[], 0, None);
 
     assert_eq!(
         returns,
         vec![Token::Uint(ethereum_types::U256::from(1620656423))]
     );
 
-    let returns = vm.function("mr_slot", &[], &[], 0);
+    let returns = vm.function("mr_slot", &[], &[], 0, None);
 
     assert_eq!(
         returns,
         vec![Token::Uint(ethereum_types::U256::from(70818331))]
     );
 
-    let returns = vm.function("mr_blocknumber", &[], &[], 0);
+    let returns = vm.function("mr_blocknumber", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -52,6 +52,7 @@ fn builtins() {
         &[Token::Uint(ethereum_types::U256::from(0xdeadcafeu32))],
         &[],
         0,
+        None,
     );
 
     if let Token::Bytes(v) = &returns[0] {
@@ -66,7 +67,7 @@ fn builtins() {
         )]
     );
 
-    let returns = vm.function("sig", &[], &[], 0);
+    let returns = vm.function("sig", &[], &[], 0, None);
 
     if let Token::FixedBytes(v) = &returns[0] {
         println!("{}", hex::encode(v));

+ 17 - 1
tests/solana_tests/call.rs

@@ -79,7 +79,13 @@ fn simple_external_call() {
 
     vm.constructor("bar1", &[], 0);
 
-    vm.function("test_bar", &[Token::String(String::from("yo"))], &[], 0);
+    vm.function(
+        "test_bar",
+        &[Token::String(String::from("yo"))],
+        &[],
+        0,
+        None,
+    );
 
     assert_eq!(vm.logs, "bar1 says: yo");
 
@@ -96,6 +102,7 @@ fn simple_external_call() {
         &[Token::String(String::from("uncle beau"))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(vm.logs, "bar0 says: uncle beau");
@@ -107,6 +114,7 @@ fn simple_external_call() {
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
         0,
+        None,
     );
 
     assert_eq!(vm.logs, "bar1 says: cross contract call");
@@ -136,6 +144,7 @@ fn external_call_with_returns() {
         &[Token::Int(ethereum_types::U256::from(21))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(res, vec![Token::Int(ethereum_types::U256::from(24))]);
@@ -151,6 +160,7 @@ fn external_call_with_returns() {
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
         0,
+        None,
     );
 
     assert_eq!(res, vec![Token::Int(ethereum_types::U256::from(15))]);
@@ -187,6 +197,7 @@ fn external_raw_call_with_returns() {
         &[Token::Int(ethereum_types::U256::from(21))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(res, vec![Token::Int(ethereum_types::U256::from(24))]);
@@ -202,6 +213,7 @@ fn external_raw_call_with_returns() {
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
         0,
+        None,
     );
 
     assert_eq!(res, vec![Token::Int(ethereum_types::U256::from(15))]);
@@ -250,6 +262,7 @@ fn external_call_with_string_returns() {
         &[Token::Int(ethereum_types::U256::from(22))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(res, vec![Token::String(String::from("foo:22"))]);
@@ -267,6 +280,7 @@ fn external_call_with_string_returns() {
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
         0,
+        None,
     );
 
     assert_eq!(res, vec![Token::String(String::from("foo:7"))]);
@@ -276,6 +290,7 @@ fn external_call_with_string_returns() {
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
         0,
+        None,
     );
 
     let res = vm.function(
@@ -283,6 +298,7 @@ fn external_call_with_string_returns() {
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
         0,
+        None,
     );
 
     assert_eq!(res[0], Token::FixedBytes(bar0_account.to_vec()));

+ 2 - 2
tests/solana_tests/constant.rs

@@ -20,7 +20,7 @@ fn constant() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("f", &[], &[], 0);
+    let returns = vm.function("f", &[], &[], 0, None);
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(42))]);
 
     let mut vm = build_solidity(
@@ -40,7 +40,7 @@ fn constant() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("f", &[], &[], 0);
+    let returns = vm.function("f", &[], &[], 0, None);
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(42))]);
 }
 

+ 4 - 3
tests/solana_tests/create_contract.rs

@@ -35,7 +35,7 @@ fn simple_create_contract() {
 
     let seed = vm.create_empty_account();
 
-    let bar1 = vm.function("test_other", &[], &[&seed], 0);
+    let bar1 = vm.function("test_other", &[], &[&seed], 0, None);
 
     assert_eq!(vm.logs, "bar1 says: yo from bar0");
 
@@ -48,6 +48,7 @@ fn simple_create_contract() {
         &[bar1[0].clone(), Token::String(String::from("xywoleh"))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(vm.logs, "Hello xywoleh");
@@ -154,7 +155,7 @@ fn missing_contract() {
 
     vm.constructor("bar0", &[], 0);
 
-    let _ = vm.function("test_other", &[], &[], 0);
+    let _ = vm.function("test_other", &[], &[], 0, None);
 }
 
 #[test]
@@ -184,7 +185,7 @@ fn two_contracts() {
     let seed1 = vm.create_empty_account();
     let seed2 = vm.create_empty_account();
 
-    let _bar1 = vm.function("test_other", &[], &[&seed1, &seed2], 0);
+    let _bar1 = vm.function("test_other", &[], &[&seed1, &seed2], 0, None);
 
     assert_eq!(vm.logs, "bar1 says: yo from bar0bar1 says: hi from bar0");
 

+ 6 - 6
tests/solana_tests/destructure.rs

@@ -17,7 +17,7 @@ fn conditional_destructure() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("f", &[Token::Bool(true), Token::Bool(true)], &[], 0);
+    let returns = vm.function("f", &[Token::Bool(true), Token::Bool(true)], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -27,7 +27,7 @@ fn conditional_destructure() {
         ]
     );
 
-    let returns = vm.function("f", &[Token::Bool(true), Token::Bool(false)], &[], 0);
+    let returns = vm.function("f", &[Token::Bool(true), Token::Bool(false)], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -37,7 +37,7 @@ fn conditional_destructure() {
         ]
     );
 
-    let returns = vm.function("f", &[Token::Bool(false), Token::Bool(false)], &[], 0);
+    let returns = vm.function("f", &[Token::Bool(false), Token::Bool(false)], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -47,7 +47,7 @@ fn conditional_destructure() {
         ]
     );
 
-    let returns = vm.function("f", &[Token::Bool(false), Token::Bool(true)], &[], 0);
+    let returns = vm.function("f", &[Token::Bool(false), Token::Bool(true)], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -76,7 +76,7 @@ fn casting_destructure() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("f", &[], &[], 0);
+    let returns = vm.function("f", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -98,7 +98,7 @@ fn casting_destructure() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("f", &[], &[], 0);
+    let returns = vm.function("f", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::String(String::from("Hello")),]);
 }

+ 2 - 2
tests/solana_tests/events.rs

@@ -17,7 +17,7 @@ fn simple_event() {
 
     vm.constructor("c", &[], 0);
 
-    vm.function("go", &[], &[], 0);
+    vm.function("go", &[], &[], 0, None);
 
     let log = vm.events();
 
@@ -66,7 +66,7 @@ fn less_simple_event() {
 
     vm.constructor("c", &[], 0);
 
-    vm.function("go", &[], &[], 0);
+    vm.function("go", &[], &[], 0, None);
 
     let log = vm.events();
 

+ 1 - 1
tests/solana_tests/expressions.rs

@@ -35,7 +35,7 @@ fn interfaceid() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,

+ 24 - 6
tests/solana_tests/hash.rs

@@ -16,7 +16,7 @@ fn constants_hash_tests() {
     );
 
     runtime.constructor("tester", &[], 0);
-    runtime.function("test", &[], &[], 0);
+    runtime.function("test", &[], &[], 0, None);
 
     let mut runtime = build_solidity(
         r##"
@@ -30,7 +30,7 @@ fn constants_hash_tests() {
     );
 
     runtime.constructor("tester", &[], 0);
-    runtime.function("test", &[], &[], 0);
+    runtime.function("test", &[], &[], 0, None);
 
     let mut runtime = build_solidity(
         r##"
@@ -44,7 +44,7 @@ fn constants_hash_tests() {
     );
 
     runtime.constructor("tester", &[], 0);
-    runtime.function("test", &[], &[], 0);
+    runtime.function("test", &[], &[], 0, None);
 
     // blake2 hash functions are substrate isms. Ensure they don't exist
     let ns = parse_and_resolve(
@@ -96,7 +96,13 @@ fn hash_tests() {
     );
 
     runtime.constructor("tester", &[], 0);
-    let hash = runtime.function("test", &[Token::Bytes(b"Hello, World!".to_vec())], &[], 0);
+    let hash = runtime.function(
+        "test",
+        &[Token::Bytes(b"Hello, World!".to_vec())],
+        &[],
+        0,
+        None,
+    );
 
     assert_eq!(
         hash,
@@ -117,7 +123,13 @@ fn hash_tests() {
     );
 
     runtime.constructor("tester", &[], 0);
-    let hash = runtime.function("test", &[Token::Bytes(b"Hello, World!".to_vec())], &[], 0);
+    let hash = runtime.function(
+        "test",
+        &[Token::Bytes(b"Hello, World!".to_vec())],
+        &[],
+        0,
+        None,
+    );
 
     assert_eq!(
         hash,
@@ -139,7 +151,13 @@ fn hash_tests() {
     );
 
     runtime.constructor("tester", &[], 0);
-    let hash = runtime.function("test", &[Token::Bytes(b"Hello, World!".to_vec())], &[], 0);
+    let hash = runtime.function(
+        "test",
+        &[Token::Bytes(b"Hello, World!".to_vec())],
+        &[],
+        0,
+        None,
+    );
 
     assert_eq!(
         hash,

+ 21 - 5
tests/solana_tests/mappings.rs

@@ -33,6 +33,7 @@ fn simple_mapping() {
             ],
             &[],
             0,
+            None,
         );
     }
 
@@ -42,6 +43,7 @@ fn simple_mapping() {
             &[Token::Uint(ethereum_types::U256::from(102 + i))],
             &[],
             0,
+            None,
         );
 
         assert_eq!(
@@ -55,6 +57,7 @@ fn simple_mapping() {
         &[Token::Uint(ethereum_types::U256::from(101))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
@@ -64,6 +67,7 @@ fn simple_mapping() {
         &[Token::Uint(ethereum_types::U256::from(104))],
         &[],
         0,
+        None,
     );
 
     for i in 0..10 {
@@ -72,6 +76,7 @@ fn simple_mapping() {
             &[Token::Uint(ethereum_types::U256::from(102 + i))],
             &[],
             0,
+            None,
         );
 
         if 102 + i != 104 {
@@ -122,7 +127,7 @@ fn less_simple_mapping() {
         &[
             Token::Uint(ethereum_types::U256::from(12313132131321312311213131u128)),
             Token::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
-        ], &[], 0
+        ], &[], 0, None
     );
 
     vm.function(
@@ -133,6 +138,7 @@ fn less_simple_mapping() {
         ],
         &[],
         0,
+        None,
     );
 
     let returns = vm.function(
@@ -142,6 +148,7 @@ fn less_simple_mapping() {
         ))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(
@@ -190,7 +197,7 @@ fn string_mapping() {
         &[
             Token::String(String::from("a")),
             Token::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
-        ], &[],0
+        ], &[],0, None
     );
 
     vm.function(
@@ -201,9 +208,10 @@ fn string_mapping() {
         ],
         &[],
         0,
+        None,
     );
 
-    let returns = vm.function("get", &[Token::String(String::from("a"))], &[], 0);
+    let returns = vm.function("get", &[Token::String(String::from("a"))], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -238,6 +246,7 @@ fn mapping_in_mapping() {
         ],
         &[],
         0,
+        None,
     );
 
     let returns = vm.function(
@@ -248,6 +257,7 @@ fn mapping_in_mapping() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::FixedBytes(vec![0x98])]);
@@ -260,6 +270,7 @@ fn mapping_in_mapping() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::FixedBytes(vec![0])]);
@@ -272,6 +283,7 @@ fn mapping_in_mapping() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::FixedBytes(vec![0])]);
@@ -314,7 +326,7 @@ fn sparse_array() {
         &[
             Token::Uint(ethereum_types::U256::from(909090909)),
             Token::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
-        ], &[],0
+        ], &[],0, None
     );
 
     vm.function(
@@ -325,6 +337,7 @@ fn sparse_array() {
         ],
         &[],
         0,
+        None,
     );
 
     let returns = vm.function(
@@ -332,6 +345,7 @@ fn sparse_array() {
         &[Token::Uint(ethereum_types::U256::from(909090909))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(
@@ -380,7 +394,7 @@ fn massive_sparse_array() {
         &[
             Token::Uint(ethereum_types::U256::from(786868768768678687686877u128)),
             Token::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
-        ], &[],0
+        ], &[],0, None
     );
 
     vm.function(
@@ -391,6 +405,7 @@ fn massive_sparse_array() {
         ],
         &[],
         0,
+        None,
     );
 
     let returns = vm.function(
@@ -400,6 +415,7 @@ fn massive_sparse_array() {
         ))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(

+ 39 - 10
tests/solana_tests/primitives.rs

@@ -25,7 +25,7 @@ fn assert_false() {
 
     vm.constructor("foo", &[], 0);
 
-    vm.function("assert_fails", &[], &[], 0);
+    vm.function("assert_fails", &[], &[], 0, None);
 }
 
 #[test]
@@ -42,7 +42,7 @@ fn assert_true() {
 
     vm.constructor("foo", &[], 0);
 
-    vm.function("assert_fails", &[], &[], 0);
+    vm.function("assert_fails", &[], &[], 0, None);
 }
 
 #[test]
@@ -74,16 +74,16 @@ fn boolean() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("return_true", &[], &[], 0);
+    let returns = vm.function("return_true", &[], &[], 0, None);
 
     assert_eq!(returns, vec![ethabi::Token::Bool(true),]);
 
-    let returns = vm.function("return_false", &[], &[], 0);
+    let returns = vm.function("return_false", &[], &[], 0, None);
 
     assert_eq!(returns, vec![ethabi::Token::Bool(false),]);
 
-    vm.function("true_arg", &[ethabi::Token::Bool(true)], &[], 0);
-    vm.function("false_arg", &[ethabi::Token::Bool(false)], &[], 0);
+    vm.function("true_arg", &[ethabi::Token::Bool(true)], &[], 0, None);
+    vm.function("false_arg", &[ethabi::Token::Bool(false)], &[], 0, None);
 }
 
 #[test]
@@ -108,7 +108,7 @@ fn address() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("return_address", &[], &[], 0);
+    let returns = vm.function("return_address", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -126,6 +126,7 @@ fn address() {
         ])],
         &[],
         0,
+        None,
     );
 }
 
@@ -152,7 +153,7 @@ fn test_enum() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("return_enum", &[], &[], 0);
+    let returns = vm.function("return_enum", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -164,6 +165,7 @@ fn test_enum() {
         &[ethabi::Token::Uint(ethereum_types::U256::from(6))],
         &[],
         0,
+        None,
     );
 }
 
@@ -208,7 +210,7 @@ fn bytes() {
 
         vm.constructor("test", &[], 0);
 
-        let returns = vm.function("return_literal", &[], &[], 0);
+        let returns = vm.function("return_literal", &[], &[], 0, None);
 
         assert_eq!(
             returns,
@@ -220,6 +222,7 @@ fn bytes() {
             &[ethabi::Token::FixedBytes(vec![1, 2, 3, 4, 5, 6, 7])],
             &[],
             0,
+            None,
         );
 
         assert_eq!(
@@ -245,6 +248,7 @@ fn bytes() {
                 ],
                 &[],
                 0,
+                None,
             );
 
             let res: Vec<u8> = a.iter().zip(b.iter()).map(|(a, b)| a | b).collect();
@@ -266,6 +270,7 @@ fn bytes() {
                 ],
                 &[],
                 0,
+                None,
             );
 
             let res: Vec<u8> = a.iter().zip(b.iter()).map(|(a, b)| a & b).collect();
@@ -280,6 +285,7 @@ fn bytes() {
                 ],
                 &[],
                 0,
+                None,
             );
 
             let res: Vec<u8> = a.iter().zip(b.iter()).map(|(a, b)| a ^ b).collect();
@@ -298,6 +304,7 @@ fn bytes() {
                 ],
                 &[],
                 0,
+                None,
             );
 
             let mut res = (BigUint::from_bytes_be(&a) << r).to_bytes_be();
@@ -320,6 +327,7 @@ fn bytes() {
                 ],
                 &[],
                 0,
+                None,
             );
 
             let mut res = (BigUint::from_bytes_be(&a) >> r).to_bytes_be();
@@ -416,7 +424,7 @@ fn uint() {
             truncate_uint(&mut a, width);
             truncate_uint(&mut b, width);
 
-            let res = vm.function("pass", &[ethabi::Token::Uint(a)], &[], 0);
+            let res = vm.function("pass", &[ethabi::Token::Uint(a)], &[], 0, None);
 
             println!("{:x} = {:?} o", a, res);
 
@@ -425,6 +433,7 @@ fn uint() {
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
                 0,
+                None,
             );
 
             let (mut res, _) = a.overflowing_add(b);
@@ -440,6 +449,7 @@ fn uint() {
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
                 0,
+                None,
             );
 
             let (mut res, _) = a.overflowing_sub(b);
@@ -453,6 +463,7 @@ fn uint() {
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
                 0,
+                None,
             );
 
             let (mut res, _) = a.overflowing_mul(b);
@@ -466,6 +477,7 @@ fn uint() {
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
                 0,
+                None,
             );
 
             let (mut res, _) = a.overflowing_pow(b);
@@ -480,6 +492,7 @@ fn uint() {
                     &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                     &[],
                     0,
+                    None,
                 );
 
                 let mut res = a.div(b);
@@ -493,6 +506,7 @@ fn uint() {
                     &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                     &[],
                     0,
+                    None,
                 );
 
                 let mut res = a.rem(b);
@@ -507,6 +521,7 @@ fn uint() {
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
                 0,
+                None,
             );
 
             let mut res = ethereum_types::U256([
@@ -525,6 +540,7 @@ fn uint() {
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
                 0,
+                None,
             );
 
             let mut res = ethereum_types::U256([
@@ -543,6 +559,7 @@ fn uint() {
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
                 0,
+                None,
             );
 
             let mut res = ethereum_types::U256([
@@ -566,6 +583,7 @@ fn uint() {
                 ],
                 &[],
                 0,
+                None,
             );
 
             let mut res = a.shl(r);
@@ -582,6 +600,7 @@ fn uint() {
                 ],
                 &[],
                 0,
+                None,
             );
 
             let mut res = a.shr(r);
@@ -687,6 +706,7 @@ fn int() {
                 &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
                 &[],
                 0,
+                None,
             );
 
             let res = big_a.clone().add(&big_b);
@@ -700,6 +720,7 @@ fn int() {
                 &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
                 &[],
                 0,
+                None,
             );
 
             let res = bigint_to_eth(&big_a.clone().sub(&big_b), width);
@@ -711,6 +732,7 @@ fn int() {
                 &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
                 &[],
                 0,
+                None,
             );
 
             let res = bigint_to_eth(&big_a.clone().mul(&big_b), width);
@@ -723,6 +745,7 @@ fn int() {
                     &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
                     &[],
                     0,
+                    None,
                 );
 
                 let res = bigint_to_eth(&big_a.clone().div(&big_b), width);
@@ -734,6 +757,7 @@ fn int() {
                     &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
                     &[],
                     0,
+                    None,
                 );
 
                 let res = big_a.clone().rem(&big_b);
@@ -748,6 +772,7 @@ fn int() {
                 &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
                 &[],
                 0,
+                None,
             );
 
             let mut res = ethereum_types::U256([
@@ -766,6 +791,7 @@ fn int() {
                 &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
                 &[],
                 0,
+                None,
             );
 
             let mut res = ethereum_types::U256([
@@ -784,6 +810,7 @@ fn int() {
                 &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
                 &[],
                 0,
+                None,
             );
 
             let mut res = ethereum_types::U256([
@@ -807,6 +834,7 @@ fn int() {
                 ],
                 &[],
                 0,
+                None,
             );
 
             let mut res = a.shl(r);
@@ -823,6 +851,7 @@ fn int() {
                 ],
                 &[],
                 0,
+                None,
             );
 
             let res = bigint_to_eth(&big_a.clone().shr(r), width);

+ 9 - 8
tests/solana_tests/rational.rs

@@ -35,14 +35,14 @@ fn rational() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("test", &[], &[], 0);
+    let returns = vm.function("test", &[], &[], 0, None);
 
     assert_eq!(
         returns,
         vec![ethabi::Token::Uint(ethereum_types::U256::from(4))]
     );
 
-    let returns = vm.function("test2", &[], &[], 0);
+    let returns = vm.function("test2", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -61,7 +61,7 @@ fn rational() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("test", &[], &[], 0);
+    let returns = vm.function("test", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -80,7 +80,7 @@ fn rational() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("test", &[], &[], 0);
+    let returns = vm.function("test", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -99,7 +99,7 @@ fn rational() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("test", &[], &[], 0);
+    let returns = vm.function("test", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -118,7 +118,7 @@ fn rational() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("test", &[], &[], 0);
+    let returns = vm.function("test", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -136,7 +136,7 @@ fn rational() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("test", &[], &[], 0);
+    let returns = vm.function("test", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -154,7 +154,7 @@ fn rational() {
 
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("test", &[], &[], 0);
+    let returns = vm.function("test", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -177,6 +177,7 @@ fn rational() {
         &[ethabi::Token::Uint(ethereum_types::U256::from(982451653))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(

+ 14 - 14
tests/solana_tests/returns.rs

@@ -31,19 +31,19 @@ fn return_single() {
     );
     vm.constructor("foo", &[], 0);
 
-    let returns = vm.function("f", &[], &[], 0);
+    let returns = vm.function("f", &[], &[], 0, None);
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(2)),]);
 
-    let returns = vm.function("g", &[], &[], 0);
+    let returns = vm.function("g", &[], &[], 0, None);
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(3)),]);
 
-    let returns = vm.function("h", &[], &[], 0);
+    let returns = vm.function("h", &[], &[], 0, None);
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(2)),]);
 
-    let returns = vm.function("i", &[], &[], 0);
+    let returns = vm.function("i", &[], &[], 0, None);
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(24)),]);
 
-    let returns = vm.function("j", &[], &[], 0);
+    let returns = vm.function("j", &[], &[], 0, None);
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(5)),]);
 }
 
@@ -59,7 +59,7 @@ fn return_ternary() {
     );
 
     vm.constructor("foo", &[], 0);
-    let returns = vm.function("f", &[], &[], 0);
+    let returns = vm.function("f", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -79,7 +79,7 @@ fn return_ternary() {
     );
 
     vm.constructor("foo", &[], 0);
-    let returns = vm.function("f", &[], &[], 0);
+    let returns = vm.function("f", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -200,9 +200,9 @@ fn return_nothing() {
     );
 
     vm.constructor("foo", &[], 0);
-    let _returns = vm.function("strange", &[], &[], 0);
-    let _returns = vm.function("inc", &[], &[], 0);
-    let returns = vm.function("get", &[], &[], 0);
+    let _returns = vm.function("strange", &[], &[], 0, None);
+    let _returns = vm.function("inc", &[], &[], 0, None);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(2)),]);
 
@@ -230,8 +230,8 @@ fn return_nothing() {
     );
 
     vm.constructor("foo", &[], 0);
-    let _returns = vm.function("f", &[], &[], 0);
-    let returns = vm.function("get", &[], &[], 0);
+    let _returns = vm.function("f", &[], &[], 0, None);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(5)),]);
 }
@@ -252,7 +252,7 @@ fn return_function() {
     );
 
     vm.constructor("foo", &[], 0);
-    let returns = vm.function("f", &[], &[], 0);
+    let returns = vm.function("f", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -276,7 +276,7 @@ fn return_function() {
     );
 
     vm.constructor("foo", &[], 0);
-    let returns = vm.function("f", &[], &[], 0);
+    let returns = vm.function("f", &[], &[], 0, None);
 
     assert_eq!(
         returns,

+ 5 - 0
tests/solana_tests/signature_verify.rs

@@ -67,6 +67,7 @@ fn verify() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Bool(false)]);
@@ -83,6 +84,7 @@ fn verify() {
         AccountState {
             data: instructions,
             owner: None,
+            lamports: 0,
         },
     );
 
@@ -97,6 +99,7 @@ fn verify() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Bool(true)]);
@@ -114,6 +117,7 @@ fn verify() {
         AccountState {
             data: instructions,
             owner: None,
+            lamports: 0,
         },
     );
 
@@ -126,6 +130,7 @@ fn verify() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(returns, vec![Token::Bool(false)]);

+ 11 - 6
tests/solana_tests/simple.rs

@@ -22,7 +22,7 @@ fn simple() {
 
     vm.logs.truncate(0);
 
-    vm.function("test", &[], &[], 0);
+    vm.function("test", &[], &[], 0, None);
 
     assert_eq!(vm.logs, "Hello from function");
 }
@@ -75,6 +75,7 @@ fn parameters() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(vm.logs, "x is 10");
@@ -89,6 +90,7 @@ fn parameters() {
         ],
         &[],
         0,
+        None,
     );
 
     assert_eq!(vm.logs, "y is 102");
@@ -112,6 +114,7 @@ fn returns() {
         &[ethabi::Token::Uint(ethereum_types::U256::from(10))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(
@@ -135,6 +138,7 @@ fn returns() {
         &[ethabi::Token::Uint(ethereum_types::U256::from(982451653))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(
@@ -179,18 +183,18 @@ fn flipper() {
         hex::decode("6fc90ec500000000000000001800000001").unwrap()
     );
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(returns, vec![ethabi::Token::Bool(true)]);
 
-    vm.function("flip", &[], &[], 0);
+    vm.function("flip", &[], &[], 0, None);
 
     assert_eq!(
         vm.data()[0..17].to_vec(),
         hex::decode("6fc90ec500000000000000001800000000").unwrap()
     );
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(returns, vec![ethabi::Token::Bool(false)]);
 }
@@ -232,7 +236,7 @@ fn incrementer() {
         0,
     );
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -244,9 +248,10 @@ fn incrementer() {
         &[ethabi::Token::Uint(ethereum_types::U256::from(7))],
         &[],
         0,
+        None,
     );
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(
         returns,

+ 44 - 30
tests/solana_tests/storage.rs

@@ -16,7 +16,7 @@ fn simple() {
     );
 
     vm.constructor("foo", &[], 0);
-    let returns = vm.function("boom", &[], &[], 0);
+    let returns = vm.function("boom", &[], &[], 0, None);
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(0)),]);
 
     let mut vm = build_solidity(
@@ -40,7 +40,7 @@ fn simple() {
     );
 
     vm.constructor("c", &[], 0);
-    let returns = vm.function("func", &[], &[], 0);
+    let returns = vm.function("func", &[], &[], 0, None);
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(1)),]);
 }
 
@@ -68,7 +68,7 @@ fn string() {
         vec![65, 177, 160, 100, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0]
     );
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::String(String::from(""))]);
 
@@ -77,6 +77,7 @@ fn string() {
         &[Token::String(String::from("Hello, World!"))],
         &[],
         0,
+        None,
     );
 
     assert_eq!(
@@ -86,7 +87,7 @@ fn string() {
 
     assert_eq!(vm.data()[40..53].to_vec(), b"Hello, World!");
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::String(String::from("Hello, World!"))]);
 
@@ -97,9 +98,10 @@ fn string() {
         &[Token::String(String::from("Hallo, Werld!"))],
         &[],
         0,
+        None,
     );
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::String(String::from("Hallo, Werld!"))]);
 
@@ -110,9 +112,9 @@ fn string() {
 
     // Try setting this to an empty string. This is also a special case where
     // the result should be offset 0
-    vm.function("set", &[Token::String(String::from(""))], &[], 0);
+    vm.function("set", &[Token::String(String::from(""))], &[], 0, None);
 
-    let returns = vm.function("get", &[], &[], 0);
+    let returns = vm.function("get", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::String(String::from(""))]);
 
@@ -154,7 +156,7 @@ fn bytes() {
         vec![11, 66, 182, 57, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0]
     );
 
-    let returns = vm.function("foo_length", &[], &[], 0);
+    let returns = vm.function("foo_length", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
 
@@ -165,6 +167,7 @@ fn bytes() {
         )],
         &[],
         0,
+        None,
     );
 
     assert_eq!(
@@ -182,6 +185,7 @@ fn bytes() {
             &[Token::Uint(ethereum_types::U256::from(i))],
             &[],
             0,
+            None,
         );
 
         assert_eq!(returns, vec![Token::FixedBytes(vec![b])]);
@@ -195,6 +199,7 @@ fn bytes() {
         ],
         &[],
         0,
+        None,
     );
 
     vm.function(
@@ -205,6 +210,7 @@ fn bytes() {
         ],
         &[],
         0,
+        None,
     );
 
     for (i, b) in b"ThE shoEmaker always wears the worst shoes"
@@ -217,6 +223,7 @@ fn bytes() {
             &[Token::Uint(ethereum_types::U256::from(i))],
             &[],
             0,
+            None,
         );
 
         assert_eq!(returns, vec![Token::FixedBytes(vec![b])]);
@@ -259,6 +266,7 @@ fn bytes_set_subscript_range() {
         ],
         &[],
         0,
+        None,
     );
 }
 
@@ -297,6 +305,7 @@ fn bytes_get_subscript_range() {
         )],
         &[],
         0,
+        None,
     );
 
     vm.function(
@@ -304,6 +313,7 @@ fn bytes_get_subscript_range() {
         &[Token::Uint(ethereum_types::U256::from(0x80000000u64))],
         &[],
         0,
+        None,
     );
 }
 
@@ -354,29 +364,29 @@ fn bytes_push_pop() {
 
     vm.constructor("c", &[], 0);
 
-    let returns = vm.function("get_bs", &[], &[], 0);
+    let returns = vm.function("get_bs", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Bytes(vec!(0x0e, 0xda))]);
 
-    let returns = vm.function("pop", &[], &[], 0);
+    let returns = vm.function("pop", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::FixedBytes(vec!(0xda))]);
 
-    let returns = vm.function("get_bs", &[], &[], 0);
+    let returns = vm.function("get_bs", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Bytes(vec!(0x0e))]);
 
-    vm.function("push", &[Token::FixedBytes(vec![0x41])], &[], 0);
+    vm.function("push", &[Token::FixedBytes(vec![0x41])], &[], 0, None);
 
     println!("data:{}", hex::encode(&vm.data()));
 
-    let returns = vm.function("get_bs", &[], &[], 0);
+    let returns = vm.function("get_bs", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Bytes(vec!(0x0e, 0x41))]);
 
-    vm.function("push", &[Token::FixedBytes(vec![0x01])], &[], 0);
+    vm.function("push", &[Token::FixedBytes(vec![0x01])], &[], 0, None);
 
-    let returns = vm.function("get_bs", &[], &[], 0);
+    let returns = vm.function("get_bs", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Bytes(vec!(0x0e, 0x41, 0x01))]);
 }
@@ -397,7 +407,7 @@ fn bytes_empty_pop() {
 
     vm.constructor("c", &[], 0);
 
-    vm.function("pop", &[], &[], 0);
+    vm.function("pop", &[], &[], 0, None);
 }
 
 #[test]
@@ -429,7 +439,7 @@ fn simple_struct() {
 
     vm.constructor("c", &[], 0);
 
-    vm.function("set_s2", &[], &[], 0);
+    vm.function("set_s2", &[], &[], 0, None);
 
     assert_eq!(
         vm.data()[0..32].to_vec(),
@@ -439,7 +449,7 @@ fn simple_struct() {
         ]
     );
 
-    let returns = vm.function("get_s1", &[], &[], 0);
+    let returns = vm.function("get_s1", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -457,9 +467,10 @@ fn simple_struct() {
         ])],
         &[],
         0,
+        None,
     );
 
-    let returns = vm.function("get_s1", &[], &[], 0);
+    let returns = vm.function("get_s1", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -505,7 +516,7 @@ fn struct_in_struct() {
 
     vm.constructor("c", &[], 0);
 
-    vm.function("set_s2", &[], &[], 0);
+    vm.function("set_s2", &[], &[], 0, None);
 
     assert_eq!(
         vm.data()[0..52].to_vec(),
@@ -516,7 +527,7 @@ fn struct_in_struct() {
         ]
     );
 
-    let returns = vm.function("get_s1", &[], &[], 0);
+    let returns = vm.function("get_s1", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -542,9 +553,10 @@ fn struct_in_struct() {
         ])],
         &[],
         0,
+        None,
     );
 
-    let returns = vm.function("get_s1", &[], &[], 0);
+    let returns = vm.function("get_s1", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -589,7 +601,7 @@ fn string_in_struct() {
 
     vm.constructor("c", &[], 0);
 
-    vm.function("set_s2", &[], &[], 0);
+    vm.function("set_s2", &[], &[], 0, None);
 
     assert_eq!(
         vm.data()[0..64].to_vec(),
@@ -600,7 +612,7 @@ fn string_in_struct() {
         ]
     );
 
-    let returns = vm.function("get_s1", &[], &[], 0);
+    let returns = vm.function("get_s1", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -620,9 +632,10 @@ fn string_in_struct() {
         ])],
         &[],
         0,
+        None,
     );
 
-    let returns = vm.function("get_s1", &[], &[], 0);
+    let returns = vm.function("get_s1", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -688,9 +701,9 @@ fn complex_struct() {
 
     vm.constructor("c", &[], 0);
 
-    vm.function("set_s2", &[], &[], 0);
+    vm.function("set_s2", &[], &[], 0, None);
 
-    let returns = vm.function("get_s1", &[], &[], 0);
+    let returns = vm.function("get_s1", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -738,9 +751,10 @@ fn complex_struct() {
         ],
         &[],
         0,
+        None,
     );
 
-    let returns = vm.function("get_s1", &[], &[], 0);
+    let returns = vm.function("get_s1", &[], &[], 0, None);
 
     assert_eq!(
         returns,
@@ -765,9 +779,9 @@ fn complex_struct() {
         ]
     );
 
-    vm.function("rm", &[], &[], 0);
+    vm.function("rm", &[], &[], 0, None);
 
-    let returns = vm.function("get_s1", &[], &[], 0);
+    let returns = vm.function("get_s1", &[], &[], 0, None);
 
     assert_eq!(
         returns,

+ 4 - 4
tests/solana_tests/unused_variable_elimination.rs

@@ -36,13 +36,13 @@ fn test_returns() {
 
     let mut vm = build_solidity(file);
     vm.constructor("c1", &[], 0);
-    let _ = vm.function("assign", &[], &[], 0);
-    let returns = vm.function("pb1", &[], &[], 0);
+    let _ = vm.function("assign", &[], &[], 0, None);
+    let returns = vm.function("pb1", &[], &[], 0, None);
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(5))]);
 
-    let returns = vm.function("test1", &[], &[], 0);
+    let returns = vm.function("test1", &[], &[], 0, None);
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(52))]);
-    let returns = vm.function("test2", &[], &[], 0);
+    let returns = vm.function("test2", &[], &[], 0, None);
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(5))]);
 }

+ 2 - 2
tests/solana_tests/using.rs

@@ -28,7 +28,7 @@ fn using_for_contracts() {
     );
 
     runtime.constructor("C", &[], 0);
-    runtime.function("test", &[], &[], 0);
+    runtime.function("test", &[], &[], 0, None);
 
     assert_eq!(runtime.logs, "Hello");
 
@@ -71,7 +71,7 @@ fn using_for_contracts() {
     );
 
     runtime.constructor("foo", &[], 0);
-    runtime.function("test", &[], &[], 0);
+    runtime.function("test", &[], &[], 0, None);
 
     assert_eq!(runtime.logs, "X libX contractx:2");
 }