Explorar el Código

Disallow try-catch statements on Solana (#1044)

Signed-off-by: Lucas Steuernagel <lucas.tnagel@gmail.com>

Signed-off-by: Lucas Steuernagel <lucas.tnagel@gmail.com>
Lucas Steuernagel hace 3 años
padre
commit
b54da8dd77
Se han modificado 3 ficheros con 57 adiciones y 1 borrados
  1. 4 0
      docs/language/statements.rst
  2. 12 0
      src/sema/statements.rs
  3. 41 1
      src/sema/tests/mod.rs

+ 4 - 0
docs/language/statements.rst

@@ -218,6 +218,10 @@ An internal function cannot be called from a try catch statement. Not all proble
 for example, out of gas cannot be caught. The ``revert()`` and ``require()`` builtins may
 for example, out of gas cannot be caught. The ``revert()`` and ``require()`` builtins may
 be passed a reason code, which can be inspected using the ``catch Error(string)`` syntax.
 be passed a reason code, which can be inspected using the ``catch Error(string)`` syntax.
 
 
+.. warning::
+    On Solana, any transaction that fails halts the execution of a contract. The try-catch statement, thus,
+    is not supported for Solana contracts and the compiler will raise an error if it detects its usage.
+
 .. code-block:: solidity
 .. code-block:: solidity
 
 
     contract aborting {
     contract aborting {

+ 12 - 0
src/sema/statements.rs

@@ -15,6 +15,7 @@ use crate::sema::symtable::{VariableInitializer, VariableUsage};
 use crate::sema::unused_variable::{assigned_variable, check_function_call, used_variable};
 use crate::sema::unused_variable::{assigned_variable, check_function_call, used_variable};
 use crate::sema::yul::resolve_inline_assembly;
 use crate::sema::yul::resolve_inline_assembly;
 use crate::sema::Recurse;
 use crate::sema::Recurse;
+use crate::Target;
 use solang_parser::pt;
 use solang_parser::pt;
 use solang_parser::pt::CatchClause;
 use solang_parser::pt::CatchClause;
 use solang_parser::pt::CodeLocation;
 use solang_parser::pt::CodeLocation;
@@ -1810,6 +1811,17 @@ fn try_catch(
     ns: &mut Namespace,
     ns: &mut Namespace,
     diagnostics: &mut Diagnostics,
     diagnostics: &mut Diagnostics,
 ) -> Result<(Statement, bool), ()> {
 ) -> Result<(Statement, bool), ()> {
+    if ns.target == Target::Solana {
+        diagnostics.push(Diagnostic::error(
+            *loc,
+            "The try-catch statement is not supported on Solana. Please, go to \
+             https://solang.readthedocs.io/en/latest/language/statements.html#try-catch-statement \
+             for more information"
+                .to_string(),
+        ));
+        return Err(());
+    }
+
     let mut expr = expr.remove_parenthesis();
     let mut expr = expr.remove_parenthesis();
     let mut ok = None;
     let mut ok = None;
 
 

+ 41 - 1
src/sema/tests/mod.rs

@@ -14,7 +14,6 @@ pub(crate) fn parse(src: &'static str) -> ast::Namespace {
     cache.set_file_contents("test.sol", src.to_string());
     cache.set_file_contents("test.sol", src.to_string());
 
 
     let ns = parse_and_resolve(OsStr::new("test.sol"), &mut cache, Target::EVM);
     let ns = parse_and_resolve(OsStr::new("test.sol"), &mut cache, Target::EVM);
-    ns.print_diagnostics_in_plain(&cache, false);
     ns
     ns
 }
 }
 
 
@@ -453,3 +452,44 @@ fn test_types() {
     );
     );
     assert_eq!(errors.len(), 15);
     assert_eq!(errors.len(), 15);
 }
 }
+
+#[test]
+fn try_catch_solana() {
+    let file = r#"
+    contract aborting {
+    function abort() public returns (int32, bool) {
+        revert("bar");
+    }
+}
+
+contract runner {
+    function test() public pure {
+        aborting abort = new aborting();
+
+        try abort.abort() returns (int32 a, bool b) {
+            // call succeeded; return values are in a and b
+        }
+        catch Error(string x) {
+            if (x == "bar") {
+                // "bar" reason code was provided through revert() or require()
+            }
+        }
+        catch (bytes raw) {
+            // if no error string could decoding, we end up here with the raw data
+        }
+    }
+}
+    "#;
+
+    let mut cache = FileResolver::new();
+    cache.set_file_contents("test.sol", file.to_string());
+
+    let ns = parse_and_resolve(OsStr::new("test.sol"), &mut cache, Target::Solana);
+
+    assert_eq!(ns.diagnostics.len(), 3);
+    assert!(ns.diagnostics.contains_message("found contract 'runner'"));
+    assert!(ns.diagnostics.contains_message("found contract 'aborting'"));
+    assert!(ns.diagnostics.contains_message("The try-catch statement is not \
+     supported on Solana. Please, go to \
+     https://solang.readthedocs.io/en/latest/language/statements.html#try-catch-statement for more information"));
+}