Skip to content

Commit

Permalink
Implement the send() function for contracts (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
virgil-serbanuta authored Sep 26, 2024
1 parent ee20e88 commit 5481094
Show file tree
Hide file tree
Showing 13 changed files with 256 additions and 7 deletions.
2 changes: 2 additions & 0 deletions mx-rust-semantics/main/expression/rust-to-mx.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ module MX-RUST-EXPRESSION-RUST-TO-MX
<values> Values:Map </values>
[owise]
rule rustToMx(S:String => mxStringValue(S))
rule rustToMx(V:Value => mxIntValue({valueToInteger(V)}:>Int))
requires notBool isSemanticsError(valueToInteger(V))
rule rustToMx(tuple(V:ValueList)) => rustValuesToMxListValue(V, .MxValueList)
syntax RustMxInstruction ::= rustValuesToMxListValue(ValueListOrError, MxValueList)
Expand Down
2 changes: 2 additions & 0 deletions mx-rust-semantics/main/glue.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ module MX-RUST-GLUE
rule rustValueToMx(V:Value) => mxIntValue({valueToInteger(V)}:>Int)
requires notBool isSemanticsError(valueToInteger(V))
rule mxIntValue(0) ~> mxRustCheckMxStatus => .K
endmodule
```
2 changes: 2 additions & 0 deletions mx-rust-semantics/main/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ requires "modules/address.md"
requires "modules/biguint.md"
requires "modules/hooks.md"
requires "modules/proxy.md"
requires "modules/send.md"
requires "modules/storage.md"
requires "modules/token-identifier.md"
Expand All @@ -12,6 +13,7 @@ module MX-RUST-MODULES
imports private MX-RUST-MODULES-BIGUINT
imports private MX-RUST-MODULES-HOOKS
imports private MX-RUST-MODULES-PROXY
imports private MX-RUST-MODULES-SEND
imports private MX-RUST-MODULES-STORAGE
imports private MX-RUST-MODULES-TOKEN-IDENTIFIER
endmodule
Expand Down
2 changes: 1 addition & 1 deletion mx-rust-semantics/main/modules/address.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ module MX-RUST-MODULES-ADDRESS
( struct
( #token("ManagedAddress", "Identifier"):Identifier
, #token("mx_address_value", "Identifier"):Identifier |-> AddressValueId:Int
_:Map
.Map
)
)
=> ptr(AddressValueId) ~> rustValueToMx
Expand Down
5 changes: 0 additions & 5 deletions mx-rust-semantics/main/modules/proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@ module MX-RUST-MODULES-PROXY
<trait-path> ProxyType </trait-path>
<method-name> MethodName </method-name>
syntax MxOrRustValueOrInstruction ::= MxOrRustValue | MxRustInstruction
syntax RustMxInstruction ::= rustMxManagedExecuteOnDestContext
( destination: MxOrRustValueOrInstruction // MxOrRustValue
, egldValue: MxOrRustValueOrInstruction // MxOrRustValue
Expand Down Expand Up @@ -225,9 +223,6 @@ module MX-RUST-MODULES-PROXY
...
</values>
syntax MxInstructions ::= "mxRustCheckMxStatus"
rule mxIntValue(0) ~> mxRustCheckMxStatus => .K
rule implicitCast
( struct(#token("MxRust#Proxy", "Identifier"):Identifier, _) #as V
, T
Expand Down
122 changes: 122 additions & 0 deletions mx-rust-semantics/main/modules/send.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
```k
module MX-RUST-MODULES-SEND
imports private COMMON-K-CELL
imports private MX-COMMON-SYNTAX
imports private MX-RUST-REPRESENTATION
imports private MX-RUST-REPRESENTATION-CONVERSIONS
imports private RUST-EXECUTION-CONFIGURATION
imports private RUST-SHARED-SYNTAX
syntax Identifier ::= "MxRust#Send" [token]
syntax MxRustStructType ::= "sendType" [function, total]
rule sendType
=> rustStructType
( MxRust#Send
, .MxRustStructFields
)
rule
normalizedMethodCall
( MxRust#Send
, #token("new", "Identifier"):Identifier
, .PtrList
)
=> mxRustNewStruct
( sendType
, .CallParamsList
)
rule
<k>
normalizedMethodCall
( MxRust#Send
, #token("direct_esdt", "Identifier"):Identifier
, ( ptr(_SelfId:Int)
, ptr(AddressId:Int)
, ptr(TokenIdId:Int)
, ptr(NonceId:Int)
, ptr(AmountId:Int)
, .PtrList
)
)
=> rustMxDirectEsdt
(... destination: Address
, tokenId: TokenId
, nonce: Nonce
, amount: Amount
)
~> mxRustCheckMxStatus
~> ptrValue(null, ())
...
</k>
<values>
AddressId |-> Address:Value
TokenIdId |-> TokenId:Value
NonceId |-> Nonce:Value
AmountId |-> Amount:Value
...
</values>
syntax RustMxInstruction ::= rustMxDirectEsdt
( destination: MxOrRustValueOrInstruction // MxOrRustValue
, tokenId: MxOrRustValueOrInstruction // MxOrRustValue
, nonce: MxOrRustValueOrInstruction // MxOrRustValue
, amount: MxOrRustValueOrInstruction // MxOrRustValue
)
context rustMxDirectEsdt
(... destination: HOLE:MxOrRustValue => rustToMx(HOLE)
, tokenId: _:MxOrRustValue
, nonce: _:MxOrRustValue
, amount: _:MxOrRustValue
)
[result(MxValue)]
context rustMxDirectEsdt
(... destination: Destination:MxOrRustValue
, tokenId: HOLE:MxOrRustValue => rustToMx(HOLE)
, nonce: _:MxOrRustValue
, amount: _:MxOrRustValue
)
requires isMxValue(Destination)
[result(MxValue)]
context rustMxDirectEsdt
(... destination: Destination:MxOrRustValue
, tokenId: TokenId:MxOrRustValue
, nonce: HOLE:MxOrRustValue => rustToMx(HOLE)
, amount: _:MxOrRustValue
)
requires isMxValue(Destination)
andBool isMxValue(TokenId)
[result(MxValue)]
context rustMxDirectEsdt
(... destination: Destination:MxOrRustValue
, tokenId: TokenId:MxOrRustValue
, nonce: Nonce:MxOrRustValue
, amount: HOLE:MxOrRustValue => rustToMx(HOLE)
)
requires isMxValue(Destination)
andBool isMxValue(TokenId)
andBool isMxValue(Nonce)
[result(MxValue)]
rule rustMxDirectEsdt
(... destination: mxListValue(Destination:MxValue , .MxValueList)
, tokenId: mxListValue(mxStringValue(TokenId:String) , .MxValueList)
, nonce: mxIntValue(Nonce:Int)
, amount: mxIntValue(Amount:Int)
)
=> MX#managedMultiTransferESDTNFTExecute
( Destination
, mxTransfersValue
( mxTransferValue(... token:TokenId, nonce:Nonce, value: Amount)
, .MxEsdtTransferList
)
, mxIntValue(0) // TODO: Use some gas value
, mxStringValue("")
, mxListValue(.MxValueList)
)
endmodule
```
2 changes: 2 additions & 0 deletions mx-rust-semantics/main/preprocessing.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
```k
requires "preprocessing/contract.md"
requires "preprocessing/methods.md"
requires "preprocessing/proxy.md"
requires "preprocessing/traits.md"
module MX-RUST-PREPROCESSING
imports private MX-RUST-PREPROCESSING-CONTRACT
imports private MX-RUST-PREPROCESSING-METHODS
imports private MX-RUST-PREPROCESSING-PROXY
imports private MX-RUST-PREPROCESSING-TRAITS
Expand Down
59 changes: 59 additions & 0 deletions mx-rust-semantics/main/preprocessing/contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
```k
module MX-RUST-PREPROCESSING-CONTRACT
imports COMMON-K-CELL
imports MX-RUST-REPRESENTATION
imports RUST-PREPROCESSING-CONFIGURATION
syntax MxRustInstruction ::= rustMxAddContractSend(TypePath)
rule rustMxAddContractMethods(Trait:TypePath)
=> rustMxAddContractSend(Trait:TypePath)
rule
<k>
rustMxAddContractSend(Trait:TypePath)
=> error
( "send already exists for trait"
, ListItem(Trait)
)
...
</k>
<trait-path> Trait </trait-path>
<method-name> #token("send", "Identifier") </method-name>
[priority(50)]
rule
<k>
rustMxAddContractSend(Trait:TypePath)
=> .K
...
</k>
<trait-path> Trait </trait-path>
( .Bag
=> <method>
<method-name> #token("send", "Identifier") </method-name>
<method-params> self : $selftype , .NormalizedFunctionParameterList </method-params>
<method-return-type> #token("MxRust#CallReturnType", "Identifier") </method-return-type>
<method-implementation>
block({
.InnerAttributes
(
(
( #token("MxRust#Send", "Identifier")
:: (#token("new", "Identifier"):PathExprSegment)
:: .PathExprSegments
)
( .CallParamsList )
):Expression
):Statements
})
</method-implementation>
<method-outer-attributes> `emptyOuterAttributes`(.KList):OuterAttributes </method-outer-attributes>
</method>
)
[priority(100)]
endmodule
```
2 changes: 1 addition & 1 deletion mx-rust-semantics/main/preprocessing/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ module MX-RUST-PREPROCESSING-METHODS
<trait-path> T </trait-path>
<method-list> MethodNames:List </method-list>
rule mxRustPreprocessMethods(_:TypePath, contract, .List) => .K
rule mxRustPreprocessMethods(Trait:TypePath, contract, .List) => rustMxAddContractMethods(Trait)
rule mxRustPreprocessMethods(Trait:TypePath, proxy, .List) => rustMxAddProxyMethods(Trait)
rule mxRustPreprocessMethods
Expand Down
5 changes: 5 additions & 0 deletions mx-rust-semantics/main/representation.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module MX-RUST-REPRESENTATION
syntax MxRustInstruction ::= "mxRustPreprocessTraits"
| mxRustPreprocessMethods(TypePath, TraitType)
| rustMxAddContractMethods(TypePath)
| rustMxAddProxyMethods(TypePath)
| mxRustCreateAccount(String)
| mxRustCreateContract
Expand All @@ -28,12 +29,15 @@ module MX-RUST-REPRESENTATION
| mxRustGetStringFromId(Int)
| mxRustNewStruct(MxRustStructType, CallParamsList)
[strict(2), result(ValueWithPtr)]
| "mxRustCheckMxStatus"
syntax TraitType ::= "contract" | "proxy"
syntax MxRustType ::= "noType" | rustType(Type)
syntax MxRustTypeOrError ::= MxRustType | SemanticsError
syntax Value ::= MxRustType
syntax MxOrRustValueOrInstruction ::= MxOrRustValue | MxRustInstruction
syntax Expression ::= concatString(Expression, Expression) [seqstrict]
| toString(Expression) [strict]
| rawValue(Value)
Expand Down Expand Up @@ -77,6 +81,7 @@ module MX-RUST-REPRESENTATION-CONVERSIONS
syntax MxOrRustValueListOrError ::= MxOrRustValueList | SemanticsError
syntax MxRustInstruction ::= mxToRustTyped(MxRustType)
// TODO: Merge rustToMx and rustValueToMx
syntax MxRustInstruction ::= rustToMx(MxOrRustValue)
| "rustToMx"
endmodule
Expand Down
Empty file.
42 changes: 42 additions & 0 deletions tests/mx-rust-contracts/send.1.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
addAccount("Caller");
setBalance("TestContract", "MyToken", 0, 1234);
setCallee("Caller");

push mxIntValue(0);
push mxStringValue("MyToken");
push mxStringValue("Caller");
call 3 MX#bigIntGetESDTExternalBalance;
get_big_int;
check_eq mxIntValue(0);

push mxIntValue(0);
push mxStringValue("MyToken");
push mxStringValue("TestContract");
call 3 MX#bigIntGetESDTExternalBalance;
get_big_int;
check_eq mxIntValue(1234);

push mxListValue(mxStringValue("Caller"), mxStringValue("MyToken"), mxIntValue(10));
push mxStringValue("sendTo");
push mxIntValue(0);
push mxTransfersValue();
push mxIntValue(0);
push mxStringValue("TestContract");
call 6 MX#managedExecuteOnDestContext;
get_big_int;
check_eq mxIntValue(0);

push mxIntValue(0);
push mxStringValue("MyToken");
push mxStringValue("Caller");
call 3 MX#bigIntGetESDTExternalBalance;
get_big_int;
check_eq mxIntValue(10);

push mxIntValue(0);
push mxStringValue("MyToken");
push mxStringValue("TestContract");
call 3 MX#bigIntGetESDTExternalBalance;
get_big_int;
check_eq mxIntValue(1224)

18 changes: 18 additions & 0 deletions tests/mx-rust-contracts/send.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#![no_std]

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

#[multiversx_sc::contract]
pub trait Storage {
#[init]
fn init(&self) {}

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

#[endpoint(sendTo)]
fn send_to(&self, address: ManagedAddress, token: TokenIdentifier, amount: BigUint) {
self.send().direct_esdt(address, token, 0_u64, amount);
}
}

0 comments on commit 5481094

Please sign in to comment.