Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement require! #98

Merged
merged 2 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mx-rust-semantics/main/calls.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
```k

requires "calls/implementation.md"
requires "calls/macros.md"

module MX-RUST-CALLS
imports private MX-RUST-CALLS-IMPLEMENTATION
imports private MX-RUST-CALLS-MACROS
endmodule

```
2 changes: 0 additions & 2 deletions mx-rust-semantics/main/calls/implementation.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ module MX-RUST-CALLS-IMPLEMENTATION
imports private RUST-REPRESENTATION
imports private RUST-SHARED-SYNTAX

rule rustValueToMx(tuple(.ValueList)) => mxUnitValue()

rule (.K => rustValueToMx(V))
~> rustValuesToMx((V:Value , L:ValueList => L), _:MxValueList)
rule (V:MxValue => .K)
Expand Down
22 changes: 22 additions & 0 deletions mx-rust-semantics/main/calls/macros.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
```k

module MX-RUST-CALLS-MACROS
imports private RUST-SHARED-SYNTAX
imports private RUST-VALUE-SYNTAX
imports private MX-COMMON-SYNTAX

syntax MxRustInstruction ::= requireMacro(condition:Expression, message:Expression)
[seqstrict]

rule ( #token("require", "Identifier") :: .SimplePathList !
( Condition:Expression, Message:Expression, .CallParamsList ) ;
):MacroInvocationSemi:KItem
=> requireMacro(... condition:Condition, message:Message)

rule requireMacro(... condition: ptrValue(_, true), message: _:PtrValue) => .K
rule requireMacro(... condition: ptrValue(_, false), message: ptrValue(_, Message:String))
=> MX#signalError(mxStringValue(Message))

endmodule

```
5 changes: 5 additions & 0 deletions mx-rust-semantics/main/glue.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ module MX-RUST-GLUE

rule ptrValue(_, V) ~> rustValueToMx => rustValueToMx(V)

rule rustValueToMx(tuple(.ValueList)) => mxUnitValue()

rule rustValueToMx(V:Value) => mxIntValue({valueToInteger(V)}:>Int)
requires notBool isSemanticsError(valueToInteger(V))

endmodule

```
8 changes: 8 additions & 0 deletions mx-rust-semantics/test/execution.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module MX-RUST-TESTING-PARSING-SYNTAX
syntax MxRustTest ::= ExecutionTest
syntax ExecutionItem ::= "set_named" String
| "push_named" String
| "catch_error" String
| "get_bigint_from_struct"
| "check_eq" Int
| TestInstruction
Expand All @@ -19,6 +20,7 @@ endmodule

module MX-RUST-TEST
imports private COMMON-K-CELL
imports private K-EQUAL-SYNTAX
imports private MX-RUST-EXECUTION-TEST-CONFIGURATION
imports private MX-RUST-TESTING-PARSING-SYNTAX
imports private RUST-EXECUTION-CONFIGURATION
Expand All @@ -43,6 +45,12 @@ module MX-RUST-TEST
)
~> get_bigint_from_struct
=> mxRustGetBigIntFromStruct(S)

rule #exception(_, Message) ~> catch_error Message => .K [priority(30)]
rule (#exception(_, Message1) #as E:MxInstructions) ~> (catch_error Message2 #as C)
=> catch_error C ~> E
requires Message1 =/=K Message2
[priority(30)]
endmodule

```
4 changes: 4 additions & 0 deletions mx-semantics/main/accounts/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ module MX-ACCOUNTS-TOOLS
rule [dropWorldState]:
<k> dropWorldState => .K ... </k>
<mx-world-stack> (ListItem(_) => .List) ... </mx-world-stack>
rule [popWorldState]:
<k> popWorldState => .K ... </k>
<mx-world-stack> (ListItem(ACCTDATA) => .List) ... </mx-world-stack>
<mx-accounts> _ => ACCTDATA </mx-accounts>

// ------------------------------------------------------
rule transferFunds(... from: From:String, to: To:String, amount: 0)
Expand Down
10 changes: 10 additions & 0 deletions mx-semantics/main/errors/hooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
```k

module MX-ERRORS-HOOKS
imports private MX-COMMON-SYNTAX

rule MX#signalError(mxStringValue(Message:String)) => #exception(UserError, Message)

endmodule

```
27 changes: 27 additions & 0 deletions mx-semantics/main/errors/tools.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
```k

module MX-ERRORS-TOOLS
imports private COMMON-K-CELL
imports private K-EQUAL-SYNTAX
imports private MX-CALL-RESULT-CONFIGURATION
imports private MX-COMMON-SYNTAX

syntax MxInstructions ::= setErrorVMOutput(ExceptionCode, String)

rule #exception(_, _) ~> (Next:KItem => .K)
requires Next =/=K endCall
rule #exception(Code, Message) ~> endCall
=> setErrorVMOutput(Code, Message) ~> popCallState ~> popWorldState

rule [setErrorVMOutput]:
<k> setErrorVMOutput(Code, Message) => .K ... </k>
<mx-call-result>
_ => mxCallResult
(... returnCode: Code
, returnMessage: Message
, out: mxListValue(.MxValueList)
)
</mx-call-result>
endmodule

```
4 changes: 4 additions & 0 deletions mx-semantics/main/mx-common.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ requires "blocks/hooks.md"
requires "call-state/tools.md"
requires "calls/hooks.md"
requires "calls/tools.md"
requires "errors/hooks.md"
requires "errors/tools.md"
requires "tools.md"

module MX-COMMON
Expand All @@ -23,6 +25,8 @@ module MX-COMMON
imports private MX-CALL-STATE-TOOLS
imports private MX-CALLS-HOOKS
imports private MX-CALLS-TOOLS
imports private MX-ERRORS-HOOKS
imports private MX-ERRORS-TOOLS
imports private MX-STORAGE-HOOKS
imports private MX-STORAGE-TOOLS
imports private MX-TOOLS
Expand Down
1 change: 1 addition & 0 deletions mx-semantics/main/syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ module MX-COMMON-SYNTAX
| "resetCallState" [symbol(resetCallState)]
| "pushWorldState" [symbol(pushWorldState)]
| "dropWorldState" [symbol(dropWorldState)]
| "popWorldState" [symbol(popWorldState)]
| "clearBigInts" [symbol(clearBigInts)]
| "endCall" [symbol(endCall)]
| "finishExecuteOnDestContext" [symbol(finishExecuteOnDestContext)]
Expand Down
Empty file.
13 changes: 13 additions & 0 deletions tests/mx-rust-contracts/require.1.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
setCallee("Owner");

push mxListValue();
push mxStringValue("callRequirePassesRetv");
push mxIntValue(0);
push mxTransfersValue();
push mxIntValue(0);
push mxStringValue("TestContract");
call 6 MX#managedExecuteOnDestContext;
check_eq mxIntValue(0);

push_return_value;
check_eq mxIntValue(3)
Empty file.
12 changes: 12 additions & 0 deletions tests/mx-rust-contracts/require.2.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
setCallee("Owner");

push mxListValue();
push mxStringValue("callRequireFailsRetv");
push mxIntValue(0);
push mxTransfersValue();
push mxIntValue(0);
push mxStringValue("TestContract");
call 6 MX#managedExecuteOnDestContext;
check_eq mxIntValue(7000);

catch_error "error signalled by smartcontract: Require failure"
Empty file.
13 changes: 13 additions & 0 deletions tests/mx-rust-contracts/require.3.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
setCallee("Owner");

push mxListValue();
push mxStringValue("callRequirePassesInstr");
push mxIntValue(0);
push mxTransfersValue();
push mxIntValue(0);
push mxStringValue("TestContract");
call 6 MX#managedExecuteOnDestContext;
check_eq mxIntValue(0);

push_return_value;
check_eq mxUnitValue()
Empty file.
12 changes: 12 additions & 0 deletions tests/mx-rust-contracts/require.4.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
setCallee("Owner");

push mxListValue();
push mxStringValue("callRequireFailsInstr");
push mxIntValue(0);
push mxTransfersValue();
push mxIntValue(0);
push mxStringValue("TestContract");
call 6 MX#managedExecuteOnDestContext;
check_eq mxIntValue(7000);

catch_error "error signalled by smartcontract: Require failure"
Empty file.
24 changes: 24 additions & 0 deletions tests/mx-rust-contracts/require.5.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
setCallee("Owner");

push mxListValue();
push mxStringValue("callRequireFailsUndoRetv");
push mxIntValue(0);
push mxTransfersValue();
push mxIntValue(0);
push mxStringValue("TestContract");
call 6 MX#managedExecuteOnDestContext;
check_eq mxIntValue(7000);

catch_error "error signalled by smartcontract: Require failure";

push mxListValue();
push mxStringValue("getMyStorage");
push mxIntValue(0);
push mxTransfersValue();
push mxIntValue(0);
push mxStringValue("TestContract");
call 6 MX#managedExecuteOnDestContext;
check_eq mxIntValue(0);

push_return_value;
check_eq mxIntValue(10)
Empty file.
24 changes: 24 additions & 0 deletions tests/mx-rust-contracts/require.6.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
setCallee("Owner");

push mxListValue();
push mxStringValue("callRequireFailsUndoInstr");
push mxIntValue(0);
push mxTransfersValue();
push mxIntValue(0);
push mxStringValue("TestContract");
call 6 MX#managedExecuteOnDestContext;
check_eq mxIntValue(7000);

catch_error "error signalled by smartcontract: Require failure";

push mxListValue();
push mxStringValue("getMyStorage");
push mxIntValue(0);
push mxTransfersValue();
push mxIntValue(0);
push mxStringValue("TestContract");
call 6 MX#managedExecuteOnDestContext;
check_eq mxIntValue(0);

push_return_value;
check_eq mxIntValue(10)
62 changes: 62 additions & 0 deletions tests/mx-rust-contracts/require.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#![no_std]

#[allow(unused_imports)]
use multiversx_sc::imports::*;

#[multiversx_sc::contract]
pub trait RequireContract {
#[view(noArg)]
#[storage_mapper("my_value")]
fn my_storage(&self) -> SingleValueMapper<BigUint>;

#[init]
fn init(&self) {
self.my_storage().set_if_empty(BigUint::from(10))
}

#[upgrade]
fn upgrade(&self) {}

#[endpoint(callRequirePassesRetv)]
fn call_require_passes_retv(&self) -> u64 {
require!(5_u64 > 4_u64, "Require failure");
3_u64
}

#[endpoint(callRequireFailsRetv)]
fn call_require_fails_retv(&self) -> u64 {
require!(5_u64 > 6_u64, "Require failure");
3_u64
}

#[endpoint(callRequirePassesInstr)]
fn call_require_passes_Instr(&self) {
require!(5_u64 > 4_u64, "Require failure");
3_u64;
}

#[endpoint(callRequireFailsInstr)]
fn call_require_fails_instr(&self) -> u64 {
require!(5_u64 > 6_u64, "Require failure");
3_u64;
}

#[endpoint(callRequireFailsUndoRetv)]
fn call_require_fails_undo_retv(&self) {
self.my_storage().set(BigUint::from(100_u64));
require!(5_u64 > 6_u64, "Require failure");
self.my_storage().set(BigUint::from(100_u64))
}

#[endpoint(callRequireFailsUndoInstr)]
fn call_require_fails_undo_instr(&self) -> u64 {
self.my_storage().set(BigUint::from(100_u64));
require!(5_u64 > 6_u64, "Require failure");
self.my_storage().set(BigUint::from(100_u64));
}

#[endpoint(getMyStorage)]
fn get_my_storage(&self) -> BigUint {
self.my_storage().get()
}
}
Loading