Parcourir la source

Implement msg.value for Solana

Signed-off-by: Sean Young <sean@mess.org>
Sean Young il y a 4 ans
Parent
commit
27df84afbc

+ 2 - 1
CHANGELOG.md

@@ -7,13 +7,14 @@ will be documented here.
 ### Added
 - Added supported for solc import mapppings using `--importmap`
 - Added supported for Events on Solana
-- `block.number` and `block.slot` are implemented for Solana
+- `msg.value`, `block.number`, and `block.slot` are implemented for Solana
 - Verify ed25519 signatures with `signatureVerify()` on Solana
 
 ### Changed
 - On Solana, the return data is now provided in the program log. As a result,
   RPCs are now are now supported.
 - On the solang command line, the target must be specified.
+- The Solana instruction now includes a 64 bit value field
 
 ### Removed
 - The Sawtooth Sabre target has been removed.

+ 2 - 2
src/emit/mod.rs

@@ -292,10 +292,10 @@ pub trait TargetRuntime<'a> {
     fn return_data<'b>(&self, bin: &Binary<'b>, function: FunctionValue<'b>) -> PointerValue<'b>;
 
     /// Return the value we received
-    fn value_transferred<'b>(&self, bin: &Binary<'b>, ns: &ast::Namespace) -> IntValue<'b>;
+    fn value_transferred<'b>(&self, binary: &Binary<'b>, ns: &ast::Namespace) -> IntValue<'b>;
 
     /// Terminate execution, destroy bin and send remaining funds to addr
-    fn selfdestruct<'b>(&self, bin: &Binary<'b>, addr: IntValue<'b>, ns: &ast::Namespace);
+    fn selfdestruct<'b>(&self, binary: &Binary<'b>, addr: IntValue<'b>, ns: &ast::Namespace);
 
     /// Crypto Hash
     fn hash<'b>(

+ 16 - 2
src/emit/solana.rs

@@ -2928,8 +2928,19 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
     }
 
     /// Value received
-    fn value_transferred<'b>(&self, binary: &Binary<'b>, ns: &ast::Namespace) -> IntValue<'b> {
-        binary.value_type(ns).const_zero()
+    fn value_transferred<'b>(&self, binary: &Binary<'b>, _ns: &ast::Namespace) -> IntValue<'b> {
+        let parameters = self.sol_parameters(binary);
+
+        binary
+            .builder
+            .build_load(
+                binary
+                    .builder
+                    .build_struct_gep(parameters, 14, "value")
+                    .unwrap(),
+                "value",
+            )
+            .into_int_value()
     }
 
     /// Terminate execution, destroy binary and send remaining funds to addr
@@ -3141,6 +3152,9 @@ impl<'a> TargetRuntime<'a> for SolanaTarget {
 
                 binary.builder.build_load(value, "sender_address")
             }
+            ast::Expression::Builtin(_, _, ast::Builtin::Value, _) => {
+                self.value_transferred(binary, ns).into()
+            }
             ast::Expression::Builtin(_, _, ast::Builtin::GetAddress, _) => {
                 let parameters = self.sol_parameters(binary);
 

+ 2 - 1
tests/solana.rs

@@ -1272,12 +1272,13 @@ impl VirtualMachine {
         name: &str,
         args: &[Token],
         seeds: &[&(Account, Vec<u8>)],
+        value: u64,
     ) -> Vec<Token> {
         let program = &self.stack[0];
 
         println!("function for {}", hex::encode(&program.data));
 
-        let mut calldata = VirtualMachine::input(&program.data, &account_new(), 0, name, seeds);
+        let mut calldata = VirtualMachine::input(&program.data, &account_new(), value, name, seeds);
 
         println!("input: {} seeds {:?}", hex::encode(&calldata), seeds);
 

+ 5 - 5
tests/solana_tests/abi.rs

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

+ 13 - 7
tests/solana_tests/accessor.rs

@@ -12,7 +12,7 @@ fn types() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("f1", &[], &[]);
+    let returns = vm.function("f1", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(102))]);
 
@@ -25,7 +25,7 @@ fn types() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("f1", &[Token::Uint(ethereum_types::U256::from(2))], &[]);
+    let returns = vm.function("f1", &[Token::Uint(ethereum_types::U256::from(2))], &[], 0);
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(5))]);
 
@@ -52,6 +52,7 @@ fn types() {
             Token::Uint(ethereum_types::U256::from(2)),
         ],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(2))]);
@@ -70,7 +71,12 @@ fn types() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("f1", &[Token::Int(ethereum_types::U256::from(4000))], &[]);
+    let returns = vm.function(
+        "f1",
+        &[Token::Int(ethereum_types::U256::from(4000))],
+        &[],
+        0,
+    );
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(2))]);
 }
@@ -91,7 +97,7 @@ fn interfaces() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("f1", &[], &[]);
+    let returns = vm.function("f1", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::FixedBytes(b"ab".to_vec())]);
 }
@@ -107,7 +113,7 @@ fn constant() {
 
     vm.constructor("x", &[]);
 
-    let returns = vm.function("z", &[], &[]);
+    let returns = vm.function("z", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -126,7 +132,7 @@ fn constant() {
 
     vm.constructor("x", &[]);
 
-    let returns = vm.function("z", &[], &[]);
+    let returns = vm.function("z", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -145,7 +151,7 @@ fn constant() {
 
     vm.constructor("x", &[]);
 
-    let returns = vm.function("z", &[], &[]);
+    let returns = vm.function("z", &[], &[], 0);
 
     assert_eq!(
         returns,

+ 60 - 32
tests/solana_tests/arrays.rs

@@ -19,7 +19,7 @@ fn fixed_array() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -53,7 +53,7 @@ fn fixed_array() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -110,7 +110,7 @@ fn fixed_array() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -139,6 +139,7 @@ fn fixed_array() {
             Token::Bool(true),
         ])],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(26))]);
@@ -187,12 +188,13 @@ fn dynamic_array_fixed_elements() {
             Token::Uint(ethereum_types::U256::from(102)),
         ],
         &[],
+        0,
     );
 
     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", &[], &[]);
+    let returns = vm.function("set", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -255,11 +257,12 @@ fn fixed_array_dynamic_elements() {
             Token::Uint(ethereum_types::U256::from(102)),
         ],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(127))]);
 
-    let returns = vm.function("set", &[], &[]);
+    let returns = vm.function("set", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -323,11 +326,12 @@ fn dynamic_array_dynamic_elements() {
             Token::Uint(ethereum_types::U256::from(102)),
         ],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(127))]);
 
-    let returns = vm.function("set", &[], &[]);
+    let returns = vm.function("set", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -382,6 +386,7 @@ fn fixed_array_fixed_elements_storage() {
             Token::Int(ethereum_types::U256::from(12123123)),
         ],
         &[],
+        0,
     );
 
     vm.function(
@@ -391,12 +396,14 @@ fn fixed_array_fixed_elements_storage() {
             Token::Int(ethereum_types::U256::from(123456789)),
         ],
         &[],
+        0,
     );
 
     let returns = vm.function(
         "get_elem",
         &[Token::Uint(ethereum_types::U256::from(2))],
         &[],
+        0,
     );
 
     assert_eq!(
@@ -404,7 +411,7 @@ fn fixed_array_fixed_elements_storage() {
         vec![Token::Int(ethereum_types::U256::from(12123123)),],
     );
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -425,9 +432,10 @@ fn fixed_array_fixed_elements_storage() {
             Token::Int(ethereum_types::U256::from(4)),
         ])],
         &[],
+        0,
     );
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -439,9 +447,9 @@ fn fixed_array_fixed_elements_storage() {
         ]),],
     );
 
-    vm.function("del", &[], &[]);
+    vm.function("del", &[], &[], 0);
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -492,6 +500,7 @@ fn fixed_array_dynamic_elements_storage() {
             Token::String(String::from("abcd")),
         ],
         &[],
+        0,
     );
 
     vm.function(
@@ -503,17 +512,19 @@ fn fixed_array_dynamic_elements_storage() {
             )),
         ],
         &[],
+        0,
     );
 
     let returns = vm.function(
         "get_elem",
         &[Token::Uint(ethereum_types::U256::from(2))],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::String(String::from("abcd"))]);
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -536,9 +547,10 @@ fn fixed_array_dynamic_elements_storage() {
             Token::String(String::from("d")),
         ])],
         &[],
+        0,
     );
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -550,9 +562,9 @@ fn fixed_array_dynamic_elements_storage() {
         ]),],
     );
 
-    vm.function("del", &[], &[]);
+    vm.function("del", &[], &[], 0);
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -608,24 +620,31 @@ fn storage_simple_dynamic_array() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("len", &[], &[]);
+    let returns = vm.function("len", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
 
-    vm.function("push", &[Token::Int(ethereum_types::U256::from(102))], &[]);
+    vm.function(
+        "push",
+        &[Token::Int(ethereum_types::U256::from(102))],
+        &[],
+        0,
+    );
 
-    vm.function("push_zero", &[], &[]);
+    vm.function("push_zero", &[], &[], 0);
 
     vm.function(
         "push",
         &[Token::Int(ethereum_types::U256::from(12345678901u64))],
         &[],
+        0,
     );
 
     let returns = vm.function(
         "subscript",
         &[Token::Uint(ethereum_types::U256::from(0))],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(102))]);
@@ -634,6 +653,7 @@ fn storage_simple_dynamic_array() {
         "subscript",
         &[Token::Uint(ethereum_types::U256::from(1))],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(0))]);
@@ -642,6 +662,7 @@ fn storage_simple_dynamic_array() {
         "subscript",
         &[Token::Uint(ethereum_types::U256::from(2))],
         &[],
+        0,
     );
 
     assert_eq!(
@@ -649,7 +670,7 @@ fn storage_simple_dynamic_array() {
         vec![Token::Int(ethereum_types::U256::from(12345678901u64))]
     );
 
-    let returns = vm.function("copy", &[], &[]);
+    let returns = vm.function("copy", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -660,14 +681,14 @@ fn storage_simple_dynamic_array() {
         ])],
     );
 
-    let returns = vm.function("pop", &[], &[]);
+    let returns = vm.function("pop", &[], &[], 0);
 
     assert_eq!(
         returns,
         vec![Token::Int(ethereum_types::U256::from(12345678901u64))]
     );
 
-    let returns = vm.function("len", &[], &[]);
+    let returns = vm.function("len", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(2))]);
 
@@ -683,9 +704,10 @@ fn storage_simple_dynamic_array() {
             Token::Int(ethereum_types::U256::from(7)),
         ])],
         &[],
+        0,
     );
 
-    let returns = vm.function("copy", &[], &[]);
+    let returns = vm.function("copy", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -700,9 +722,9 @@ fn storage_simple_dynamic_array() {
         ])],
     );
 
-    vm.function("rm", &[], &[]);
+    vm.function("rm", &[], &[], 0);
 
-    let returns = vm.function("len", &[], &[]);
+    let returns = vm.function("len", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
 }
@@ -723,7 +745,7 @@ fn storage_pop_running_on_empty() {
 
     vm.constructor("foo", &[]);
 
-    vm.function("pop", &[], &[]);
+    vm.function("pop", &[], &[], 0);
 }
 
 #[test]
@@ -780,7 +802,7 @@ fn storage_dynamic_array_of_structs() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("len", &[], &[]);
+    let returns = vm.function("len", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
 
@@ -791,9 +813,10 @@ fn storage_dynamic_array_of_structs() {
             Token::Bool(true),
         ])],
         &[],
+        0,
     );
 
-    vm.function("push_empty", &[], &[]);
+    vm.function("push_empty", &[], &[], 0);
 
     vm.function(
         "push2",
@@ -802,12 +825,14 @@ fn storage_dynamic_array_of_structs() {
             Token::Bool(true),
         ])],
         &[],
+        0,
     );
 
     let returns = vm.function(
         "subscript",
         &[Token::Uint(ethereum_types::U256::from(0))],
         &[],
+        0,
     );
 
     assert_eq!(
@@ -822,6 +847,7 @@ fn storage_dynamic_array_of_structs() {
         "subscript",
         &[Token::Uint(ethereum_types::U256::from(1))],
         &[],
+        0,
     );
 
     assert_eq!(
@@ -836,6 +862,7 @@ fn storage_dynamic_array_of_structs() {
         "subscript",
         &[Token::Uint(ethereum_types::U256::from(2))],
         &[],
+        0,
     );
 
     assert_eq!(
@@ -846,7 +873,7 @@ fn storage_dynamic_array_of_structs() {
         ])]
     );
 
-    let returns = vm.function("copy", &[], &[]);
+    let returns = vm.function("copy", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -866,7 +893,7 @@ fn storage_dynamic_array_of_structs() {
         ])]
     );
 
-    let returns = vm.function("pop", &[], &[]);
+    let returns = vm.function("pop", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -876,7 +903,7 @@ fn storage_dynamic_array_of_structs() {
         ])]
     );
 
-    let returns = vm.function("len", &[], &[]);
+    let returns = vm.function("len", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(2))]);
 
@@ -909,9 +936,10 @@ fn storage_dynamic_array_of_structs() {
             ]),
         ])],
         &[],
+        0,
     );
 
-    let returns = vm.function("copy", &[], &[]);
+    let returns = vm.function("copy", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -943,9 +971,9 @@ fn storage_dynamic_array_of_structs() {
         ])]
     );
 
-    vm.function("rm", &[], &[]);
+    vm.function("rm", &[], &[], 0);
 
-    let returns = vm.function("len", &[], &[]);
+    let returns = vm.function("len", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
 }

+ 20 - 0
tests/solana_tests/balance.rs

@@ -0,0 +1,20 @@
+use crate::build_solidity;
+use ethabi::Token;
+
+#[test]
+fn msg_value() {
+    let mut vm = build_solidity(
+        r#"
+        contract c {
+            function test() public payable returns (uint64) {
+                return msg.value * 3;
+            }
+        }"#,
+    );
+
+    vm.constructor("c", &[]);
+
+    let returns = vm.function("test", &[], &[], 102);
+
+    assert_eq!(returns[0], Token::Uint(ethereum_types::U256::from(306)));
+}

+ 3 - 3
tests/solana_tests/builtin.rs

@@ -20,21 +20,21 @@ fn timestamp() {
 
     vm.constructor("timestamp", &[]);
 
-    let returns = vm.function("mr_now", &[], &[]);
+    let returns = vm.function("mr_now", &[], &[], 0);
 
     assert_eq!(
         returns,
         vec![Token::Uint(ethereum_types::U256::from(1620656423))]
     );
 
-    let returns = vm.function("mr_slot", &[], &[]);
+    let returns = vm.function("mr_slot", &[], &[], 0);
 
     assert_eq!(
         returns,
         vec![Token::Uint(ethereum_types::U256::from(70818331))]
     );
 
-    let returns = vm.function("mr_blocknumber", &[], &[]);
+    let returns = vm.function("mr_blocknumber", &[], &[], 0);
 
     assert_eq!(
         returns,

+ 11 - 1
tests/solana_tests/call.rs

@@ -79,7 +79,7 @@ fn simple_external_call() {
 
     vm.constructor("bar1", &[]);
 
-    vm.function("test_bar", &[Token::String(String::from("yo"))], &[]);
+    vm.function("test_bar", &[Token::String(String::from("yo"))], &[], 0);
 
     assert_eq!(vm.logs, "bar1 says: yo");
 
@@ -95,6 +95,7 @@ fn simple_external_call() {
         "test_bar",
         &[Token::String(String::from("uncle beau"))],
         &[],
+        0,
     );
 
     assert_eq!(vm.logs, "bar0 says: uncle beau");
@@ -105,6 +106,7 @@ fn simple_external_call() {
         "test_other",
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
+        0,
     );
 
     assert_eq!(vm.logs, "bar1 says: cross contract call");
@@ -133,6 +135,7 @@ fn external_call_with_returns() {
         "test_bar",
         &[Token::Int(ethereum_types::U256::from(21))],
         &[],
+        0,
     );
 
     assert_eq!(res, vec![Token::Int(ethereum_types::U256::from(24))]);
@@ -147,6 +150,7 @@ fn external_call_with_returns() {
         "test_other",
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
+        0,
     );
 
     assert_eq!(res, vec![Token::Int(ethereum_types::U256::from(15))]);
@@ -182,6 +186,7 @@ fn external_raw_call_with_returns() {
         "test_bar",
         &[Token::Int(ethereum_types::U256::from(21))],
         &[],
+        0,
     );
 
     assert_eq!(res, vec![Token::Int(ethereum_types::U256::from(24))]);
@@ -196,6 +201,7 @@ fn external_raw_call_with_returns() {
         "test_other",
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
+        0,
     );
 
     assert_eq!(res, vec![Token::Int(ethereum_types::U256::from(15))]);
@@ -243,6 +249,7 @@ fn external_call_with_string_returns() {
         "test_bar",
         &[Token::Int(ethereum_types::U256::from(22))],
         &[],
+        0,
     );
 
     assert_eq!(res, vec![Token::String(String::from("foo:22"))]);
@@ -259,6 +266,7 @@ fn external_call_with_string_returns() {
         "test_other",
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
+        0,
     );
 
     assert_eq!(res, vec![Token::String(String::from("foo:7"))]);
@@ -267,12 +275,14 @@ fn external_call_with_string_returns() {
         "test_this",
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
+        0,
     );
 
     let res = vm.function(
         "test_sender",
         &[Token::FixedBytes(bar1_account.to_vec())],
         &[],
+        0,
     );
 
     assert_eq!(res[0], Token::FixedBytes(bar0_account.to_vec()));

+ 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]);
+    let bar1 = vm.function("test_other", &[], &[&seed], 0);
 
     assert_eq!(vm.logs, "bar1 says: yo from bar0");
 
@@ -47,6 +47,7 @@ fn simple_create_contract() {
         "call_bar1_at_address",
         &[bar1[0].clone(), Token::String(String::from("xywoleh"))],
         &[],
+        0,
     );
 
     assert_eq!(vm.logs, "Hello xywoleh");
@@ -85,7 +86,7 @@ fn missing_contract() {
 
     vm.constructor("bar0", &[]);
 
-    let _ = vm.function("test_other", &[], &[]);
+    let _ = vm.function("test_other", &[], &[], 0);
 }
 
 #[test]
@@ -115,7 +116,7 @@ fn two_contracts() {
     let seed1 = vm.create_empty_account();
     let seed2 = vm.create_empty_account();
 
-    let _bar1 = vm.function("test_other", &[], &[&seed1, &seed2]);
+    let _bar1 = vm.function("test_other", &[], &[&seed1, &seed2], 0);
 
     assert_eq!(vm.logs, "bar1 says: yo from bar0bar1 says: hi from bar0");
 

+ 4 - 4
tests/solana_tests/destructure.rs

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

+ 2 - 2
tests/solana_tests/events.rs

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

+ 1 - 1
tests/solana_tests/expressions.rs

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

+ 6 - 6
tests/solana_tests/hash.rs

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

+ 31 - 7
tests/solana_tests/mappings.rs

@@ -32,6 +32,7 @@ fn simple_mapping() {
                 Token::Uint(ethereum_types::U256::from(300331 + i)),
             ],
             &[],
+            0,
         );
     }
 
@@ -40,6 +41,7 @@ fn simple_mapping() {
             "get",
             &[Token::Uint(ethereum_types::U256::from(102 + i))],
             &[],
+            0,
         );
 
         assert_eq!(
@@ -48,17 +50,28 @@ fn simple_mapping() {
         );
     }
 
-    let returns = vm.function("get", &[Token::Uint(ethereum_types::U256::from(101))], &[]);
+    let returns = vm.function(
+        "get",
+        &[Token::Uint(ethereum_types::U256::from(101))],
+        &[],
+        0,
+    );
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
 
-    vm.function("rm", &[Token::Uint(ethereum_types::U256::from(104))], &[]);
+    vm.function(
+        "rm",
+        &[Token::Uint(ethereum_types::U256::from(104))],
+        &[],
+        0,
+    );
 
     for i in 0..10 {
         let returns = vm.function(
             "get",
             &[Token::Uint(ethereum_types::U256::from(102 + i))],
             &[],
+            0,
         );
 
         if 102 + i != 104 {
@@ -109,7 +122,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
     );
 
     vm.function(
@@ -119,6 +132,7 @@ fn less_simple_mapping() {
             Token::Int(ethereum_types::U256::from(102)),
         ],
         &[],
+        0,
     );
 
     let returns = vm.function(
@@ -127,6 +141,7 @@ fn less_simple_mapping() {
             12313132131321312311213131u128,
         ))],
         &[],
+        0,
     );
 
     assert_eq!(
@@ -175,7 +190,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
     );
 
     vm.function(
@@ -185,9 +200,10 @@ fn string_mapping() {
             Token::Int(ethereum_types::U256::from(102)),
         ],
         &[],
+        0,
     );
 
-    let returns = vm.function("get", &[Token::String(String::from("a"))], &[]);
+    let returns = vm.function("get", &[Token::String(String::from("a"))], &[], 0);
 
     assert_eq!(
         returns,
@@ -221,6 +237,7 @@ fn mapping_in_mapping() {
             Token::FixedBytes(vec![0x98]),
         ],
         &[],
+        0,
     );
 
     let returns = vm.function(
@@ -230,6 +247,7 @@ fn mapping_in_mapping() {
             Token::Int(ethereum_types::U256::from(102)),
         ],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::FixedBytes(vec![0x98])]);
@@ -241,6 +259,7 @@ fn mapping_in_mapping() {
             Token::Int(ethereum_types::U256::from(103)),
         ],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::FixedBytes(vec![0])]);
@@ -252,6 +271,7 @@ fn mapping_in_mapping() {
             Token::Int(ethereum_types::U256::from(102)),
         ],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::FixedBytes(vec![0])]);
@@ -294,7 +314,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
     );
 
     vm.function(
@@ -304,12 +324,14 @@ fn sparse_array() {
             Token::Int(ethereum_types::U256::from(102)),
         ],
         &[],
+        0,
     );
 
     let returns = vm.function(
         "get",
         &[Token::Uint(ethereum_types::U256::from(909090909))],
         &[],
+        0,
     );
 
     assert_eq!(
@@ -358,7 +380,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
     );
 
     vm.function(
@@ -368,6 +390,7 @@ fn massive_sparse_array() {
             Token::Int(ethereum_types::U256::from(102)),
         ],
         &[],
+        0,
     );
 
     let returns = vm.function(
@@ -376,6 +399,7 @@ fn massive_sparse_array() {
             786868768768678687686877u128,
         ))],
         &[],
+        0,
     );
 
     assert_eq!(

+ 1 - 0
tests/solana_tests/mod.rs

@@ -2,6 +2,7 @@ mod abi;
 mod accessor;
 mod arrays;
 mod assembly;
+mod balance;
 mod builtin;
 mod call;
 mod create_contract;

+ 84 - 19
tests/solana_tests/primitives.rs

@@ -25,7 +25,7 @@ fn assert_false() {
 
     vm.constructor("foo", &[]);
 
-    vm.function("assert_fails", &[], &[]);
+    vm.function("assert_fails", &[], &[], 0);
 }
 
 #[test]
@@ -42,7 +42,7 @@ fn assert_true() {
 
     vm.constructor("foo", &[]);
 
-    vm.function("assert_fails", &[], &[]);
+    vm.function("assert_fails", &[], &[], 0);
 }
 
 #[test]
@@ -74,16 +74,16 @@ fn boolean() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("return_true", &[], &[]);
+    let returns = vm.function("return_true", &[], &[], 0);
 
     assert_eq!(returns, vec![ethabi::Token::Bool(true),]);
 
-    let returns = vm.function("return_false", &[], &[]);
+    let returns = vm.function("return_false", &[], &[], 0);
 
     assert_eq!(returns, vec![ethabi::Token::Bool(false),]);
 
-    vm.function("true_arg", &[ethabi::Token::Bool(true)], &[]);
-    vm.function("false_arg", &[ethabi::Token::Bool(false)], &[]);
+    vm.function("true_arg", &[ethabi::Token::Bool(true)], &[], 0);
+    vm.function("false_arg", &[ethabi::Token::Bool(false)], &[], 0);
 }
 
 #[test]
@@ -108,7 +108,7 @@ fn address() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("return_address", &[], &[]);
+    let returns = vm.function("return_address", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -125,6 +125,7 @@ fn address() {
             134, 82, 130, 112, 97, 218, 24, 157, 198, 40, 105, 118, 27,
         ])],
         &[],
+        0,
     );
 }
 
@@ -151,7 +152,7 @@ fn test_enum() {
 
     vm.constructor("foo", &[]);
 
-    let returns = vm.function("return_enum", &[], &[]);
+    let returns = vm.function("return_enum", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -162,6 +163,7 @@ fn test_enum() {
         "enum_arg",
         &[ethabi::Token::Uint(ethereum_types::U256::from(6))],
         &[],
+        0,
     );
 }
 
@@ -206,7 +208,7 @@ fn bytes() {
 
         vm.constructor("test", &[]);
 
-        let returns = vm.function("return_literal", &[], &[]);
+        let returns = vm.function("return_literal", &[], &[], 0);
 
         assert_eq!(
             returns,
@@ -217,6 +219,7 @@ fn bytes() {
             "return_arg",
             &[ethabi::Token::FixedBytes(vec![1, 2, 3, 4, 5, 6, 7])],
             &[],
+            0,
         );
 
         assert_eq!(
@@ -241,6 +244,7 @@ fn bytes() {
                     ethabi::Token::FixedBytes(b.to_vec()),
                 ],
                 &[],
+                0,
             );
 
             let res: Vec<u8> = a.iter().zip(b.iter()).map(|(a, b)| a | b).collect();
@@ -261,6 +265,7 @@ fn bytes() {
                     ethabi::Token::FixedBytes(b.to_vec()),
                 ],
                 &[],
+                0,
             );
 
             let res: Vec<u8> = a.iter().zip(b.iter()).map(|(a, b)| a & b).collect();
@@ -274,6 +279,7 @@ fn bytes() {
                     ethabi::Token::FixedBytes(b.to_vec()),
                 ],
                 &[],
+                0,
             );
 
             let res: Vec<u8> = a.iter().zip(b.iter()).map(|(a, b)| a ^ b).collect();
@@ -291,6 +297,7 @@ fn bytes() {
                     ethabi::Token::Uint(ethereum_types::U256::from(r)),
                 ],
                 &[],
+                0,
             );
 
             let mut res = (BigUint::from_bytes_be(&a) << r).to_bytes_be();
@@ -312,6 +319,7 @@ fn bytes() {
                     ethabi::Token::Uint(ethereum_types::U256::from(r)),
                 ],
                 &[],
+                0,
             );
 
             let mut res = (BigUint::from_bytes_be(&a) >> r).to_bytes_be();
@@ -408,7 +416,7 @@ fn uint() {
             truncate_uint(&mut a, width);
             truncate_uint(&mut b, width);
 
-            let res = vm.function("pass", &[ethabi::Token::Uint(a)], &[]);
+            let res = vm.function("pass", &[ethabi::Token::Uint(a)], &[], 0);
 
             println!("{:x} = {:?} o", a, res);
 
@@ -416,6 +424,7 @@ fn uint() {
                 "add",
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
+                0,
             );
 
             let (mut res, _) = a.overflowing_add(b);
@@ -430,6 +439,7 @@ fn uint() {
                 "sub",
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
+                0,
             );
 
             let (mut res, _) = a.overflowing_sub(b);
@@ -442,6 +452,7 @@ fn uint() {
                 "mul",
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
+                0,
             );
 
             let (mut res, _) = a.overflowing_mul(b);
@@ -454,6 +465,7 @@ fn uint() {
                 "pow",
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
+                0,
             );
 
             let (mut res, _) = a.overflowing_pow(b);
@@ -467,6 +479,7 @@ fn uint() {
                     "div",
                     &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                     &[],
+                    0,
                 );
 
                 let mut res = a.div(b);
@@ -479,6 +492,7 @@ fn uint() {
                     "mod",
                     &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                     &[],
+                    0,
                 );
 
                 let mut res = a.rem(b);
@@ -488,7 +502,12 @@ fn uint() {
                 assert_eq!(add, vec![ethabi::Token::Uint(res)]);
             }
 
-            let or = vm.function("or", &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)], &[]);
+            let or = vm.function(
+                "or",
+                &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
+                &[],
+                0,
+            );
 
             let mut res = ethereum_types::U256([
                 a.0[0] | b.0[0],
@@ -505,6 +524,7 @@ fn uint() {
                 "and",
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
+                0,
             );
 
             let mut res = ethereum_types::U256([
@@ -522,6 +542,7 @@ fn uint() {
                 "xor",
                 &[ethabi::Token::Uint(a), ethabi::Token::Uint(b)],
                 &[],
+                0,
             );
 
             let mut res = ethereum_types::U256([
@@ -544,6 +565,7 @@ fn uint() {
                     ethabi::Token::Uint(ethereum_types::U256::from(r)),
                 ],
                 &[],
+                0,
             );
 
             let mut res = a.shl(r);
@@ -559,6 +581,7 @@ fn uint() {
                     ethabi::Token::Uint(ethereum_types::U256::from(r)),
                 ],
                 &[],
+                0,
             );
 
             let mut res = a.shr(r);
@@ -659,7 +682,12 @@ fn int() {
             let big_a = eth_to_bigint(&a, width);
             let big_b = eth_to_bigint(&b, width);
 
-            let add = vm.function("add", &[ethabi::Token::Int(a), ethabi::Token::Int(b)], &[]);
+            let add = vm.function(
+                "add",
+                &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
+                &[],
+                0,
+            );
 
             let res = big_a.clone().add(&big_b);
 
@@ -667,26 +695,46 @@ fn int() {
 
             assert_eq!(add, vec![ethabi::Token::Int(res)]);
 
-            let sub = vm.function("sub", &[ethabi::Token::Int(a), ethabi::Token::Int(b)], &[]);
+            let sub = vm.function(
+                "sub",
+                &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
+                &[],
+                0,
+            );
 
             let res = bigint_to_eth(&big_a.clone().sub(&big_b), width);
 
             assert_eq!(sub, vec![ethabi::Token::Int(res)]);
 
-            let mul = vm.function("mul", &[ethabi::Token::Int(a), ethabi::Token::Int(b)], &[]);
+            let mul = vm.function(
+                "mul",
+                &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
+                &[],
+                0,
+            );
 
             let res = bigint_to_eth(&big_a.clone().mul(&big_b), width);
 
             assert_eq!(mul, vec![ethabi::Token::Int(res)]);
 
             if b != ethereum_types::U256::zero() {
-                let div = vm.function("div", &[ethabi::Token::Int(a), ethabi::Token::Int(b)], &[]);
+                let div = vm.function(
+                    "div",
+                    &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
+                    &[],
+                    0,
+                );
 
                 let res = bigint_to_eth(&big_a.clone().div(&big_b), width);
 
                 assert_eq!(div, vec![ethabi::Token::Int(res)]);
 
-                let add = vm.function("mod", &[ethabi::Token::Int(a), ethabi::Token::Int(b)], &[]);
+                let add = vm.function(
+                    "mod",
+                    &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
+                    &[],
+                    0,
+                );
 
                 let res = big_a.clone().rem(&big_b);
 
@@ -695,7 +743,12 @@ fn int() {
                 assert_eq!(add, vec![ethabi::Token::Int(res)]);
             }
 
-            let or = vm.function("or", &[ethabi::Token::Int(a), ethabi::Token::Int(b)], &[]);
+            let or = vm.function(
+                "or",
+                &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
+                &[],
+                0,
+            );
 
             let mut res = ethereum_types::U256([
                 a.0[0] | b.0[0],
@@ -708,7 +761,12 @@ fn int() {
 
             assert_eq!(or, vec![ethabi::Token::Int(res)]);
 
-            let and = vm.function("and", &[ethabi::Token::Int(a), ethabi::Token::Int(b)], &[]);
+            let and = vm.function(
+                "and",
+                &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
+                &[],
+                0,
+            );
 
             let mut res = ethereum_types::U256([
                 a.0[0] & b.0[0],
@@ -721,7 +779,12 @@ fn int() {
 
             assert_eq!(and, vec![ethabi::Token::Int(res)]);
 
-            let xor = vm.function("xor", &[ethabi::Token::Int(a), ethabi::Token::Int(b)], &[]);
+            let xor = vm.function(
+                "xor",
+                &[ethabi::Token::Int(a), ethabi::Token::Int(b)],
+                &[],
+                0,
+            );
 
             let mut res = ethereum_types::U256([
                 a.0[0] ^ b.0[0],
@@ -743,6 +806,7 @@ fn int() {
                     ethabi::Token::Uint(ethereum_types::U256::from(r)),
                 ],
                 &[],
+                0,
             );
 
             let mut res = a.shl(r);
@@ -758,6 +822,7 @@ fn int() {
                     ethabi::Token::Uint(ethereum_types::U256::from(r)),
                 ],
                 &[],
+                0,
             );
 
             let res = bigint_to_eth(&big_a.clone().shr(r), width);

+ 3 - 0
tests/solana_tests/signature_verify.rs

@@ -66,6 +66,7 @@ fn verify() {
             Token::Bytes(signature_bs.clone()),
         ],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::Bool(false)]);
@@ -95,6 +96,7 @@ fn verify() {
             Token::Bytes(signature_bs.clone()),
         ],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::Bool(true)]);
@@ -123,6 +125,7 @@ fn verify() {
             Token::Bytes(signature_bs),
         ],
         &[],
+        0,
     );
 
     assert_eq!(returns, vec![Token::Bool(false)]);

+ 11 - 6
tests/solana_tests/simple.rs

@@ -21,7 +21,7 @@ fn simple() {
 
     vm.logs.truncate(0);
 
-    vm.function("test", &[], &[]);
+    vm.function("test", &[], &[], 0);
 
     assert_eq!(vm.logs, "Hello from function");
 }
@@ -73,6 +73,7 @@ fn parameters() {
             ethabi::Token::Uint(ethereum_types::U256::from(10)),
         ],
         &[],
+        0,
     );
 
     assert_eq!(vm.logs, "x is 10");
@@ -86,6 +87,7 @@ fn parameters() {
             ethabi::Token::Uint(ethereum_types::U256::from(102)),
         ],
         &[],
+        0,
     );
 
     assert_eq!(vm.logs, "y is 102");
@@ -108,6 +110,7 @@ fn returns() {
         "test",
         &[ethabi::Token::Uint(ethereum_types::U256::from(10))],
         &[],
+        0,
     );
 
     assert_eq!(
@@ -130,6 +133,7 @@ fn returns() {
         "test",
         &[ethabi::Token::Uint(ethereum_types::U256::from(982451653))],
         &[],
+        0,
     );
 
     assert_eq!(
@@ -174,18 +178,18 @@ fn flipper() {
         hex::decode("6fc90ec500000000000000001800000001").unwrap()
     );
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(returns, vec![ethabi::Token::Bool(true)]);
 
-    vm.function("flip", &[], &[]);
+    vm.function("flip", &[], &[], 0);
 
     assert_eq!(
         vm.data()[0..17].to_vec(),
         hex::decode("6fc90ec500000000000000001800000000").unwrap()
     );
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(returns, vec![ethabi::Token::Bool(false)]);
 }
@@ -226,7 +230,7 @@ fn incrementer() {
         &[ethabi::Token::Uint(ethereum_types::U256::from(5))],
     );
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -237,9 +241,10 @@ fn incrementer() {
         "inc",
         &[ethabi::Token::Uint(ethereum_types::U256::from(7))],
         &[],
+        0,
     );
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(
         returns,

+ 52 - 30
tests/solana_tests/storage.rs

@@ -25,11 +25,16 @@ 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", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::String(String::from(""))]);
 
-    vm.function("set", &[Token::String(String::from("Hello, World!"))], &[]);
+    vm.function(
+        "set",
+        &[Token::String(String::from("Hello, World!"))],
+        &[],
+        0,
+    );
 
     assert_eq!(
         vm.data()[0..20].to_vec(),
@@ -38,15 +43,20 @@ fn string() {
 
     assert_eq!(vm.data()[40..53].to_vec(), b"Hello, World!");
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::String(String::from("Hello, World!"))]);
 
     // try replacing it with a string of the same length. This is a special
     // fast-path handling
-    vm.function("set", &[Token::String(String::from("Hallo, Werld!"))], &[]);
+    vm.function(
+        "set",
+        &[Token::String(String::from("Hallo, Werld!"))],
+        &[],
+        0,
+    );
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::String(String::from("Hallo, Werld!"))]);
 
@@ -57,9 +67,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(""))], &[]);
+    vm.function("set", &[Token::String(String::from(""))], &[], 0);
 
-    let returns = vm.function("get", &[], &[]);
+    let returns = vm.function("get", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::String(String::from(""))]);
 
@@ -101,7 +111,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", &[], &[]);
+    let returns = vm.function("foo_length", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Uint(ethereum_types::U256::from(0))]);
 
@@ -111,6 +121,7 @@ fn bytes() {
             b"The shoemaker always wears the worst shoes".to_vec(),
         )],
         &[],
+        0,
     );
 
     assert_eq!(
@@ -127,6 +138,7 @@ fn bytes() {
             "get_foo_offset",
             &[Token::Uint(ethereum_types::U256::from(i))],
             &[],
+            0,
         );
 
         assert_eq!(returns, vec![Token::FixedBytes(vec![b])]);
@@ -139,6 +151,7 @@ fn bytes() {
             Token::FixedBytes(b"E".to_vec()),
         ],
         &[],
+        0,
     );
 
     vm.function(
@@ -148,6 +161,7 @@ fn bytes() {
             Token::FixedBytes(b"E".to_vec()),
         ],
         &[],
+        0,
     );
 
     for (i, b) in b"ThE shoEmaker always wears the worst shoes"
@@ -159,6 +173,7 @@ fn bytes() {
             "get_foo_offset",
             &[Token::Uint(ethereum_types::U256::from(i))],
             &[],
+            0,
         );
 
         assert_eq!(returns, vec![Token::FixedBytes(vec![b])]);
@@ -200,6 +215,7 @@ fn bytes_set_subscript_range() {
             Token::FixedBytes(b"E".to_vec()),
         ],
         &[],
+        0,
     );
 }
 
@@ -237,12 +253,14 @@ fn bytes_get_subscript_range() {
             b"The shoemaker always wears the worst shoes".to_vec(),
         )],
         &[],
+        0,
     );
 
     vm.function(
         "get_foo_offset",
         &[Token::Uint(ethereum_types::U256::from(0x80000000u64))],
         &[],
+        0,
     );
 }
 
@@ -293,29 +311,29 @@ fn bytes_push_pop() {
 
     vm.constructor("c", &[]);
 
-    let returns = vm.function("get_bs", &[], &[]);
+    let returns = vm.function("get_bs", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Bytes(vec!(0x0e, 0xda))]);
 
-    let returns = vm.function("pop", &[], &[]);
+    let returns = vm.function("pop", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::FixedBytes(vec!(0xda))]);
 
-    let returns = vm.function("get_bs", &[], &[]);
+    let returns = vm.function("get_bs", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Bytes(vec!(0x0e))]);
 
-    vm.function("push", &[Token::FixedBytes(vec![0x41])], &[]);
+    vm.function("push", &[Token::FixedBytes(vec![0x41])], &[], 0);
 
     println!("data:{}", hex::encode(&vm.data()));
 
-    let returns = vm.function("get_bs", &[], &[]);
+    let returns = vm.function("get_bs", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Bytes(vec!(0x0e, 0x41))]);
 
-    vm.function("push", &[Token::FixedBytes(vec![0x01])], &[]);
+    vm.function("push", &[Token::FixedBytes(vec![0x01])], &[], 0);
 
-    let returns = vm.function("get_bs", &[], &[]);
+    let returns = vm.function("get_bs", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Bytes(vec!(0x0e, 0x41, 0x01))]);
 }
@@ -336,7 +354,7 @@ fn bytes_empty_pop() {
 
     vm.constructor("c", &[]);
 
-    vm.function("pop", &[], &[]);
+    vm.function("pop", &[], &[], 0);
 }
 
 #[test]
@@ -368,7 +386,7 @@ fn simple_struct() {
 
     vm.constructor("c", &[]);
 
-    vm.function("set_s2", &[], &[]);
+    vm.function("set_s2", &[], &[], 0);
 
     assert_eq!(
         vm.data()[0..32].to_vec(),
@@ -378,7 +396,7 @@ fn simple_struct() {
         ]
     );
 
-    let returns = vm.function("get_s1", &[], &[]);
+    let returns = vm.function("get_s1", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -395,9 +413,10 @@ fn simple_struct() {
             Token::Uint(ethereum_types::U256::from(3240121)),
         ])],
         &[],
+        0,
     );
 
-    let returns = vm.function("get_s1", &[], &[]);
+    let returns = vm.function("get_s1", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -443,7 +462,7 @@ fn struct_in_struct() {
 
     vm.constructor("c", &[]);
 
-    vm.function("set_s2", &[], &[]);
+    vm.function("set_s2", &[], &[], 0);
 
     assert_eq!(
         vm.data()[0..52].to_vec(),
@@ -454,7 +473,7 @@ fn struct_in_struct() {
         ]
     );
 
-    let returns = vm.function("get_s1", &[], &[]);
+    let returns = vm.function("get_s1", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -479,9 +498,10 @@ fn struct_in_struct() {
             Token::Uint(ethereum_types::U256::from(12345678901234567890u64)),
         ])],
         &[],
+        0,
     );
 
-    let returns = vm.function("get_s1", &[], &[]);
+    let returns = vm.function("get_s1", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -526,7 +546,7 @@ fn string_in_struct() {
 
     vm.constructor("c", &[]);
 
-    vm.function("set_s2", &[], &[]);
+    vm.function("set_s2", &[], &[], 0);
 
     assert_eq!(
         vm.data()[0..64].to_vec(),
@@ -537,7 +557,7 @@ fn string_in_struct() {
         ]
     );
 
-    let returns = vm.function("get_s1", &[], &[]);
+    let returns = vm.function("get_s1", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -556,9 +576,10 @@ fn string_in_struct() {
             Token::Uint(ethereum_types::U256::from(12345678901234567890u64)),
         ])],
         &[],
+        0,
     );
 
-    let returns = vm.function("get_s1", &[], &[]);
+    let returns = vm.function("get_s1", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -624,9 +645,9 @@ fn complex_struct() {
 
     vm.constructor("c", &[]);
 
-    vm.function("set_s2", &[], &[]);
+    vm.function("set_s2", &[], &[], 0);
 
-    let returns = vm.function("get_s1", &[], &[]);
+    let returns = vm.function("get_s1", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -673,9 +694,10 @@ fn complex_struct() {
             Token::String(String::from("yadayada")),
         ],
         &[],
+        0,
     );
 
-    let returns = vm.function("get_s1", &[], &[]);
+    let returns = vm.function("get_s1", &[], &[], 0);
 
     assert_eq!(
         returns,
@@ -700,9 +722,9 @@ fn complex_struct() {
         ]
     );
 
-    vm.function("rm", &[], &[]);
+    vm.function("rm", &[], &[], 0);
 
-    let returns = vm.function("get_s1", &[], &[]);
+    let returns = vm.function("get_s1", &[], &[], 0);
 
     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", &[]);
-    let _ = vm.function("assign", &[], &[]);
-    let returns = vm.function("pb1", &[], &[]);
+    let _ = vm.function("assign", &[], &[], 0);
+    let returns = vm.function("pb1", &[], &[], 0);
 
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(5))]);
 
-    let returns = vm.function("test1", &[], &[]);
+    let returns = vm.function("test1", &[], &[], 0);
     assert_eq!(returns, vec![Token::Int(ethereum_types::U256::from(52))]);
-    let returns = vm.function("test2", &[], &[]);
+    let returns = vm.function("test2", &[], &[], 0);
     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", &[]);
-    runtime.function("test", &[], &[]);
+    runtime.function("test", &[], &[], 0);
 
     assert_eq!(runtime.logs, "Hello");
 
@@ -71,7 +71,7 @@ fn using_for_contracts() {
     );
 
     runtime.constructor("foo", &[]);
-    runtime.function("test", &[], &[]);
+    runtime.function("test", &[], &[], 0);
 
     assert_eq!(runtime.logs, "X libX contractx:2");
 }