Преглед на файлове

Fix external call on Solana (#835)

Lucas Steuernagel преди 3 години
родител
ревизия
3e71853525
променени са 2 файла, в които са добавени 70 реда и са изтрити 7 реда
  1. 40 7
      src/codegen/expression.rs
  2. 30 0
      tests/solana_tests/call.rs

+ 40 - 7
src/codegen/expression.rs

@@ -2310,13 +2310,46 @@ pub fn emit_function_call(
                     vec![function],
                 );
 
-                tys.insert(0, Type::Bytes(4));
+                let (payload, address) = if ns.target == Target::Solana {
+                    tys.insert(0, Type::Address(false));
+                    tys.insert(1, Type::Address(false));
+                    tys.insert(2, Type::Uint(64));
+                    tys.insert(3, Type::Bytes(4));
+                    tys.insert(4, Type::Bytes(1));
+                    tys.insert(5, Type::Bytes(4));
 
-                let payload = Expression::AbiEncode {
-                    loc: *loc,
-                    tys,
-                    packed: vec![selector],
-                    args,
+                    (
+                        Expression::AbiEncode {
+                            loc: *loc,
+                            tys,
+                            packed: vec![
+                                address,
+                                Expression::Builtin(
+                                    *loc,
+                                    vec![Type::Address(false)],
+                                    Builtin::GetAddress,
+                                    Vec::new(),
+                                ),
+                                value.clone(),
+                                Expression::NumberLiteral(*loc, Type::Bytes(4), BigInt::zero()),
+                                Expression::NumberLiteral(*loc, Type::Bytes(1), BigInt::zero()),
+                                selector,
+                            ],
+                            args,
+                        },
+                        None,
+                    )
+                } else {
+                    tys.insert(0, Type::Bytes(4));
+                    (
+                        Expression::AbiEncode {
+                            loc: *loc,
+                            tys,
+                            packed: vec![selector],
+                            args,
+                        },
+                        Some(address),
+                    )
                 };
 
                 cfg.add(
@@ -2324,7 +2357,7 @@ pub fn emit_function_call(
                     Instr::ExternalCall {
                         success: None,
                         accounts: None,
-                        address: Some(address),
+                        address,
                         payload,
                         value,
                         gas,

+ 30 - 0
tests/solana_tests/call.rs

@@ -153,6 +153,36 @@ fn external_raw_call_with_returns() {
     assert_eq!(res, vec![Token::Int(U256::from(15))]);
 }
 
+#[test]
+fn call_external_func_type() {
+    let mut vm = build_solidity(
+        r#"
+    contract testing {
+
+    function testPtr(int a) public pure returns (int, int) {
+        return (a/2, 3);
+    }
+
+    function doTest() public view returns (int, int) {
+    function(int) external pure returns (int, int) sfPtr = this.testPtr;
+
+       (int a, int b) = sfPtr(2);
+       return (a, b);
+    }
+}
+    "#,
+    );
+
+    vm.constructor("testing", &[], 0);
+
+    let res = vm.function("doTest", &[], &[], 0, None);
+
+    assert_eq!(
+        res,
+        vec![Token::Int(U256::from(1)), Token::Int(U256::from(3))]
+    );
+}
+
 #[test]
 fn external_call_with_string_returns() {
     let mut vm = build_solidity(