Browse Source

receive() functions are not supported on Solana

A receive() function should be called whenever a contract/account has
its native balance credited. Solana has no mechanism by which this can
be implemented.

Note that these functions were never implemented, but there was no error
or warning about this when compiling code with a receive() function.

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

+ 4 - 0
docs/language/functions.rst

@@ -478,3 +478,7 @@ Both functions must be declared ``external``.
             // execute if function selector does not match "foo(uint32)" and value sent
         }
     }
+
+..  note::
+    On Solana, there is no mechanism to have some code executed if an account
+    gets credited. So, `receive()` functions are not supported.

+ 9 - 0
docs/targets/solana.rst

@@ -73,6 +73,15 @@ package has `documentation <https://solana-labs.github.io/solana-solidity.js/>`_
 are `some examples <https://solana-labs.github.io/solana-solidity.js/>`_. There is also
 `solang's integration tests <https://github.com/hyperledger-labs/solang/tree/main/integration/solana>`_.
 
+Receive function
+________________
+
+In Solidity the `receive()` function, when defined, is called whenever the native
+balance for an account gets credited, for example through a contract calling
+``account.transfer(value);``. On Solana, there is no method that implement
+this. The balance of an account can be credited without any code being executed.
+
+`receive()` functions are not permitted on the Solana target.
 
 Builtin Imports
 ________________

+ 37 - 30
src/sema/functions.rs

@@ -529,46 +529,53 @@ pub fn contract_function(
 
         Some(pos)
     } else if func.ty == pt::FunctionTy::Receive || func.ty == pt::FunctionTy::Fallback {
-        if let Some(prev_func_no) = ns.contracts[contract_no]
-            .functions
-            .iter()
-            .find(|func_no| ns.functions[**func_no].ty == func.ty)
-        {
-            let prev_loc = ns.functions[*prev_func_no].loc;
-
-            ns.diagnostics.push(Diagnostic::error_with_note(
-                func.loc,
-                format!("{} function already defined", func.ty),
-                prev_loc,
-                "location of previous definition".to_string(),
-            ));
-            return None;
-        }
-
-        if let pt::Visibility::External(_) = fdecl.visibility {
-            // ok
-        } else {
+        if func.ty == pt::FunctionTy::Receive && ns.target == Target::Solana {
             ns.diagnostics.push(Diagnostic::error(
                 func.loc,
-                format!("{} function must be declared external", func.ty),
+                format!("target {} does not support receive() functions, see https://solang.readthedocs.io/en/latest/language/functions.html#fallback-and-receive-function", ns.target),
             ));
-            return None;
-        }
+        } else {
+            if let Some(prev_func_no) = ns.contracts[contract_no]
+                .functions
+                .iter()
+                .find(|func_no| ns.functions[**func_no].ty == func.ty)
+            {
+                let prev_loc = ns.functions[*prev_func_no].loc;
 
-        if fdecl.is_payable() {
-            if func.ty == pt::FunctionTy::Fallback {
+                ns.diagnostics.push(Diagnostic::error_with_note(
+                    func.loc,
+                    format!("{} function already defined", func.ty),
+                    prev_loc,
+                    "location of previous definition".to_string(),
+                ));
+                return None;
+            }
+
+            if let pt::Visibility::External(_) = fdecl.visibility {
+                // ok
+            } else {
                 ns.diagnostics.push(Diagnostic::error(
+                    func.loc,
+                    format!("{} function must be declared external", func.ty),
+                ));
+                return None;
+            }
+
+            if fdecl.is_payable() {
+                if func.ty == pt::FunctionTy::Fallback {
+                    ns.diagnostics.push(Diagnostic::error(
                     func.loc,
                     format!("{} function must not be declare payable, use 'receive() external payable' instead", func.ty),
+                ));
+                    return None;
+                }
+            } else if func.ty == pt::FunctionTy::Receive {
+                ns.diagnostics.push(Diagnostic::error(
+                    func.loc,
+                    format!("{} function must be declared payable", func.ty),
                 ));
                 return None;
             }
-        } else if func.ty == pt::FunctionTy::Receive {
-            ns.diagnostics.push(Diagnostic::error(
-                func.loc,
-                format!("{} function must be declared payable", func.ty),
-            ));
-            return None;
         }
 
         let pos = ns.functions.len();

+ 5 - 3
tests/contract_testcases/solana/doccomments_everywhere.dot

@@ -130,9 +130,10 @@ strict digraph "tests/contract_testcases/solana/doccomments_everywhere.sol" {
 	diagnostic_132 [label="'Counters' not found\nlevel Error\ntests/contract_testcases/solana/doccomments_everywhere.sol:6:22-30"]
 	diagnostic_133 [label="'Counters' not found\nlevel Error\ntests/contract_testcases/solana/doccomments_everywhere.sol:7:3-11"]
 	diagnostic_134 [label="'ERC1155' not found\nlevel Error\ntests/contract_testcases/solana/doccomments_everywhere.sol:17:17-24"]
-	diagnostic_135 [label="'_tokenIds' not found\nlevel Error\ntests/contract_testcases/solana/doccomments_everywhere.sol:28:29-38"]
-	diagnostic_136 [label="cannot find overloaded function which matches signature\nlevel Error\ntests/contract_testcases/solana/doccomments_everywhere.sol:53:7-50"]
-	diagnostic_137 [label="cannot find overloaded function which matches signature\nlevel Error\ntests/contract_testcases/solana/doccomments_everywhere.sol:86:7-38"]
+	diagnostic_135 [label="target solana does not support receive() functions, see https://solang.readthedocs.io/en/latest/language/functions.html#fallback-and-receive-function\nlevel Error\ntests/contract_testcases/solana/doccomments_everywhere.sol:19:3-29"]
+	diagnostic_136 [label="'_tokenIds' not found\nlevel Error\ntests/contract_testcases/solana/doccomments_everywhere.sol:28:29-38"]
+	diagnostic_137 [label="cannot find overloaded function which matches signature\nlevel Error\ntests/contract_testcases/solana/doccomments_everywhere.sol:53:7-50"]
+	diagnostic_138 [label="cannot find overloaded function which matches signature\nlevel Error\ntests/contract_testcases/solana/doccomments_everywhere.sol:86:7-38"]
 	events -> MintProperty
 	contracts -> contract
 	contract -> tags [label="tags"]
@@ -267,4 +268,5 @@ strict digraph "tests/contract_testcases/solana/doccomments_everywhere.sol" {
 	diagnostics -> diagnostic_135 [label="Error"]
 	diagnostics -> diagnostic_136 [label="Error"]
 	diagnostics -> diagnostic_137 [label="Error"]
+	diagnostics -> diagnostic_138 [label="Error"]
 }