Skip to content

Commit

Permalink
Implement require!
Browse files Browse the repository at this point in the history
  • Loading branch information
virgil-serbanuta committed Sep 24, 2024
1 parent 655ed4f commit a2d98a0
Show file tree
Hide file tree
Showing 22 changed files with 243 additions and 0 deletions.
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
```
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 @@ -56,6 +56,11 @@ module MX-RUST-GLUE
(T ==K i32 orBool T ==K u32)
orBool (T ==K i64 orBool T ==K u64)
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 mxListValue()
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()
}
}

0 comments on commit a2d98a0

Please sign in to comment.