diff --git a/API.md b/API.md index 69188dfb..3a10925c 100644 --- a/API.md +++ b/API.md @@ -1,14 +1,14 @@ -# **TON Solidity API** +# **TVM Solidity API** -TON Solidity compiler expands Solidity language with different API functions to facilitate TON -contract development. +TVM Solidity compiler expands Solidity language with different API functions to facilitate TVM contract development. ## Table of Contents * [Compiler version](#compiler-version) -* [TON specific types](#ton-specific-types) - * [TON units](#ton-units) +* [TVM specific types](#tvm-specific-types) + * [TVM units](#tvm-units) * [TvmCell](#tvmcell) + * [constructing TvmCell](#constructing-tvmcell) * [\.depth()](#tvmcelldepth) * [\.dataSize()](#tvmcelldatasize) * [\.dataSizeQ()](#tvmcelldatasizeq) @@ -63,12 +63,13 @@ contract development. * [\.storeRef()](#tvmbuilderstoreref) * [\.storeTons()](#tvmbuilderstoretons) * [ExtraCurrencyCollection](#extracurrencycollection) - * [optional(Type)](#optionaltype) + * [optional(T)](#optionalt) * [constructing an optional](#constructing-an-optional) - * [\.hasValue()](#optionaltypehasvalue) - * [\.get()](#optionaltypeget) - * [\.set()](#optionaltypeset) - * [\.reset()](#optionaltypereset) + * [\.hasValue()](#optionalthasvalue) + * [\.get()](#optionaltget) + * [\.getOr()](#optionaltgetor) + * [\.getOrDefault()](#optionaltgetordefault) + * [\.set()](#optionaltset) * [Keyword `null`](#keyword-null) * [variant](#variant) * [variant.isUint()](#variantisuint) @@ -78,7 +79,7 @@ contract development. * [\.pop()](#vectortypepop) * [\.length()](#vectortypelength) * [\.empty()](#vectortypeempty) -* [TON specific control structures](#ton-specific-control-structures) +* [TVM specific control structures](#tvm-specific-control-structures) * [Range-based for loop](#range-based-for-loop) * [repeat](#repeat) * [try-catch](#try-catch) @@ -150,6 +151,7 @@ contract development. * [\.add()](#mappingadd) * [\.getSet()](#mappinggetset) * [\.getAdd()](#mappinggetadd) + * [\.getDel()](#mappinggetdel) * [\.getReplace()](#mappinggetreplace) * [\.keys() \.values()](#mappingkeys-mappingvalues) * [Fixed point number](#fixed-point-number) @@ -161,7 +163,7 @@ contract development. * [Function call via library name](#function-call-via-library-name) * [Function call via object](#function-call-via-object) * [Pragmas](#pragmas) - * [pragma ton-solidity](#pragma-ton-solidity) + * [pragma ever-solidity](#pragma-ever-solidity) * [pragma copyleft](#pragma-copyleft) * [pragma ignoreIntOverflow](#pragma-ignoreintoverflow) * [pragma AbiHeader](#pragma-abiheader) @@ -201,6 +203,9 @@ contract development. * [msg.isInternal, msg.isExternal and msg.isTickTock](#msgisinternal-msgisexternal-and-msgisticktock) * [msg.createdAt](#msgcreatedat) * [msg.data](#msgdata) + * [msg.forwardFee](#msgforwardfee) + * [msg.importFee](#msgimportFee) + * [msg.body](#msgbody) * [msg.hasStateInit](#msghasstateinit) * [**tvm** namespace](#tvm-namespace) * [TVM instructions](#tvm-instructions) @@ -278,6 +283,7 @@ contract development. * [sha256](#sha256) * [gasToValue](#gastovalue) * [valueToGas](#valuetogas) + * [gasleft](#gasleft) * [TVM exception codes](#tvm-exception-codes) * [Solidity runtime errors](#solidity-runtime-errors) * [Division and rounding](#division-and-rounding) @@ -288,7 +294,7 @@ contract development. ### Compiler version -TON Solidity compiler add its current version to the generated code. This version can be obtained: +TVM Solidity compiler add its current version to the generated code. This version can be obtained: 1) using [tvm_linker](https://github.com/tonlabs/TVM-linker#2-decoding-of-boc-messages-prepared-externally) from a `*.tvc` file: @@ -302,13 +308,30 @@ TON Solidity compiler add its current version to the generated code. This versio tonos-cli decode tvc [--tvc] [--boc] ``` -### TON specific types +### TVM specific types -TON Solidity compiler expands functionality of some existing types and adds several new TVM specific types: TvmCell, TvmSlice, TvmBuilder and ExtraCurrencyCollection. Full description of these types can be found in [TVM][1] and [TON Blockchain][2] specifications. +TVM Solidity compiler expands functionality of some existing types and adds several new TVM specific types: TvmCell, TvmSlice, TvmBuilder and ExtraCurrencyCollection. Full description of these types can be found in [TVM][1] and [Blockchain][2] specifications. -#### TON units +#### TVM units -A literal number can take a suffix to specify a subdenomination of TON currency, where numbers without a postfix are assumed to be nanotons. +A literal number can take a suffix to specify a subdenomination of currency, where numbers without a postfix are assumed to be nanoevers. + +```TVMSolidity +uint a0 = 1 nano; // a0 == 1 == 1e-9 ever +uint a1 = 1 nanoever; // a1 == 1 == 1e-9 ever +uint a3 = 1 ever; // a3 == 1 000 000 000 (1e9) +uint a4 = 1 Ever; // a4 == 1 000 000 000 (1e9) +uint a5 = 1 micro; // a5 == 1 000 == 1e-6 ever +uint a6 = 1 microever; // a6 == 1 000 == 1e-6 ever +uint a7 = 1 milli; // a7 == 1 000 000 == 1e-3 ever +uint a8 = 1 milliever; // a8 == 1 000 000 == 1e-3 ever +uint a9 = 1 kiloever; // a9 == 1 000 000 000 000 (1e12) == 1e3 ever +uint a10 = 1 kEver; // a10 == 1 000 000 000 000 (1e12) == 1e3 ever +uint a11 = 1 megaever; // a11 == 1 000 000 000 000 000 (1e15) == 1e6 ever +uint a12 = 1 MEver; // a12 == 1 000 000 000 000 000 (1e15) == 1e6 ever +uint a13 = 1 gigaever; // a13 == 1 000 000 000 000 000 000 (1e18) == 1e9 ever +uint a14 = 1 GEver; // a14 == 1 000 000 000 000 000 000 (1e18) == 1e9 ever +``` ```TVMSolidity uint a0 = 1 nano; // a0 == 1 @@ -326,21 +349,6 @@ uint a11 = 1 megaton; // a11 == 1 000 000 000 000 000 (1e15) uint a12 = 1 MTon; // a12 == 1 000 000 000 000 000 (1e15) uint a13 = 1 gigaton; // a13 == 1 000 000 000 000 000 000 (1e18) uint a14 = 1 GTon; // a14 == 1 000 000 000 000 000 000 (1e18) - -uint a0 = 1 nano; // a0 == 1 == 1e-9 ever -uint a1 = 1 nanoever; // a1 == 1 == 1e-9 ever -uint a3 = 1 ever; // a3 == 1 000 000 000 (1e9) -uint a4 = 1 Ever; // a4 == 1 000 000 000 (1e9) -uint a5 = 1 micro; // a5 == 1 000 == 1e-6 ever -uint a6 = 1 microever; // a6 == 1 000 == 1e-6 ever -uint a7 = 1 milli; // a7 == 1 000 000 == 1e-3 ever -uint a8 = 1 milliever; // a8 == 1 000 000 == 1e-3 ever -uint a9 = 1 kiloever; // a9 == 1 000 000 000 000 (1e12) == 1e3 ever -uint a10 = 1 kEver; // a10 == 1 000 000 000 000 (1e12) == 1e3 ever -uint a11 = 1 megaever; // a11 == 1 000 000 000 000 000 (1e15) == 1e6 ever -uint a12 = 1 MEver; // a12 == 1 000 000 000 000 000 (1e15) == 1e6 ever -uint a13 = 1 gigaever; // a13 == 1 000 000 000 000 000 000 (1e18) == 1e9 ever -uint a14 = 1 GEver; // a14 == 1 000 000 000 000 000 000 (1e18) == 1e9 ever ``` #### TvmCell @@ -351,6 +359,17 @@ operators and functions to work with this type: Comparison operators: `==`, `!=` (evaluate to `bool`) +##### constructing TvmCell + +To create empty cell use `TvmCell()`. Example: + +```TVMSolidity +TvmCell cell = ...; +if (cell == TvmCell()) { // check whether `cell` is empty + +} +``` + ##### \.depth() ```TVMSolidity @@ -669,7 +688,7 @@ contract B { // pubkey - pubkey of the contract A // timestamp - timestamp that used for replay protection - // flag - always equals to true + // flag - always is equal to true // a == 111 // b == 22 // c == 3 @@ -797,7 +816,7 @@ Same as [\.loadSlice() and \.loadSliceQ()](#tvmsliceloadsl #### TvmBuilder -`TvmBuilder` represents *TVM cell builder* ([TVM][1] - 1.1.3). TON Solidity compiler defines the following +`TvmBuilder` represents *TVM cell builder* ([TVM][1] - 1.1.3). TVM Solidity compiler defines the following functions to work with this type: ##### \.toSlice() @@ -1016,7 +1035,7 @@ optional(uint256) res = curCol.getReplace(key, value); uint256 uintValue = curCol[index]; ``` -#### optional(Type) +#### optional(T) The template optional type manages an optional contained value, i.e. a value that may or may not be present. @@ -1030,41 +1049,49 @@ opt.set(11); // just sets value opt = 22; // just sets value, too opt.get() = 33; // if 'opt' has value then set value. Otherwise throws an exception. -optional(uint) another = ...; +optional(uint) another = 44; opt = another; ``` -##### \.hasValue() +##### \.hasValue() ```TVMSolidity -.hasValue() returns (bool); +.hasValue() returns (bool); ``` Checks whether the `optional` contains a value. -##### \.get() +##### \.get() ```TVMSolidity -.get() returns (Type); +.get() returns (T); ``` Returns the contained value, if the `optional` contains one. Otherwise, throws an exception. -##### \.set() +##### \.getOr() ```TVMSolidity -.set(Type value); +.getOr(T default) returns (T); ``` -Replaces content of the `optional` with **value**. +Returns the contained value, if the `optional` contains one. Otherwise, returns `default`. -##### \.reset() +##### \.getOrDefault() ```TVMSolidity -.reset(); +.getOrDefault() returns (T); ``` -Deletes content of the `optional`. +Returns the contained value, if the `optional` contains one. Otherwise, returns the default value for `T` type. + +##### \.set() + +```TVMSolidity +.set(Type value); +``` + +Replaces content of the `optional` with **value**. ##### Keyword `null` @@ -1162,7 +1189,7 @@ vector(uint) vect; bool is_empty = vect.empty(); ``` -### TON specific control structures +### TVM specific control structures ### Range-based for loop @@ -1279,6 +1306,29 @@ try { } ``` +You can pass either of the parameters: + +```TVMSolidity +uint c; +try { + c = a + b; +} catch (variant , uint16 errorCode) { + if (errorCode == 4) { + + } +} +``` + +Or you can pass all parameters: + +```TVMSolidity +uint c; +try { + c = a + b; +} catch { +} +``` + ### Changes and extensions in Solidity types #### Integers @@ -1536,7 +1586,7 @@ If `bytes` object has less than **N** bytes, extra bytes are padded with zero bi #### string -TON Solidity compiler expands `string` type with the following functions: +TVM Solidity compiler expands `string` type with the following functions: **Note**: Due to VM restrictions string length can't exceed `1024 * 127 = 130048` bytes. @@ -1671,14 +1721,14 @@ Placeholder should be specified in such formats: * `"{}"` - empty placeholder * `"{:[0]{"x","d","X","t"}}"` - placeholder for integers. Fills num with 0 if format starts with "0". Formats integer to have specified `width`. Can format integers in decimal ("d" postfix), lower hex ("x") -or upper hex ("X") form. Format "t" prints number (in nanotons) as a fixed point Ton sum. +or upper hex ("X") form. Format "t" prints number (in nanoevers) as a fixed point sum. Warning: this function consumes too much gas, that's why it's better not to use it onchain. Example: ```TVMSolidity -string str = format("Hello {} 0x{:X} {} {}.{} tons", 123, 255, address.makeAddrStd(-33,0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF123456789ABCDE), 100500, 32); -// str == "Hello 123 0xFF -21:7fffffffffffffffffffffffffffffffffffffffffffffffff123456789abcde 100500.32 tons" +string str = format("Hello {} 0x{:X} {} {}.{} evers", 123, 255, address.makeAddrStd(-33,0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF123456789ABCDE), 100500, 32); +// str == "Hello 123 0xFF -21:7fffffffffffffffffffffffffffffffffffffffffffffffff123456789abcde 100500.32 evers" str = format("Hello {}", 123); // str == "Hello 123" str = format("Hello 0x{:X}", 123); // str == "Hello 0x7B" str = format("{}", -123); // str == "-123" @@ -1689,7 +1739,7 @@ str = format("{:06}", 123); // str == "000123" str = format("{:06d}", 123); // str == "000123" str = format("{:06X}", 123); // str == "00007B" str = format("{:6x}", 123); // str == " 7b" -uint128 a = 1 ton; +uint128 a = 1 ever; str = format("{:t}", a); // str == "1.000000000" a = 123; str = format("{:t}", a); // str == "0.000000123" @@ -1736,7 +1786,7 @@ If `string` object has less than **N** bytes, extra bytes are padded with zero b #### address `address` represents different types of TVM addresses: **addr_none**, **addr_extern**, -**addr_std** and **addr_var**. TON Solidity compiler expands `address` type with the following +**addr_std** and **addr_var**. TVM Solidity compiler expands `address` type with the following members and functions: ##### Object creating @@ -1802,7 +1852,7 @@ Returns the `address` value of **addr_std** or **addr_var** if **addr_var** has address(this).balance returns (uint128); ``` -Returns balance of the current contract account in nanotons. +Returns balance of the current contract account in nanoevers. ##### \.currencies @@ -1860,11 +1910,11 @@ Checks whether this `address` is of type **addr_none**. ##### \.unpack() ```TVMSolidity -
.unpack() returns (int8 /*wid*/, uint256 /*value*/); +
.unpack() returns (int32 /*wid*/, uint256 /*value*/); ``` Parses `address` containing a valid `MsgAddressInt` (`addr_std`), applies rewriting -from the anycast (if present) to the same-length prefix of the address, and returns both the +from the anycast (if exists) to the same-length prefix of the address, and returns both the workchain `wid` and the 256-bit address `value`. If the address `value` is not 256-bit, or if `address` is not a valid serialization of `MsgAddressInt`, throws a cell deserialization [exception](#tvm-exception-codes). @@ -1874,7 +1924,7 @@ It's wrapper for opcode `REWRITESTDADDR`. Example: ```TVMSolidity -(int8 wid, uint addr) = address(this).unpack(); +(int32 wid, uint addr) = address(this).unpack(); ``` ##### \.transfer() @@ -1885,7 +1935,7 @@ Example: Sends an internal outbound message to the `address`. Function parameters: -* `value` (`uint128`) - amount of nanotons sent attached to the message. Note: the sent value is +* `value` (`uint128`) - amount of nanoevers sent attached to the message. Note: the sent value is withdrawn from the contract's balance even if the contract has been called by internal inbound message. * `currencies` (`ExtraCurrencyCollection`) - additional currencies attached to the message. Defaults to an empty set. @@ -1938,9 +1988,9 @@ addr.transfer(value, bounce, flag); addr.transfer(value, bounce, flag, body); addr.transfer(value, bounce, flag, body, c); // using named parameters -destination.transfer({value: 1 ton, bounce: false, flag: 128, body: cell, currencies: c}); -destination.transfer({bounce: false, value: 1 ton, flag: 128, body: cell}); -destination.transfer({value: 1 ton, bounce: false, stateInit: stateInit}); +destination.transfer({value: 1 ever, bounce: false, flag: 128, body: cell, currencies: c}); +destination.transfer({bounce: false, value: 1 ever, flag: 128, body: cell}); +destination.transfer({value: 1 ever, bounce: false, stateInit: stateInit}); ``` See example of `address.transfer()` usage: @@ -1949,7 +1999,7 @@ See example of `address.transfer()` usage: #### mapping -TON Solidity compiler expands `mapping` type with the following functions. In examples +TVM Solidity compiler expands `mapping` type with the following functions. In examples below `\` defines the object of `mapping(KeyType => ValueType)` type. Address, bytes, string, bool, contract, enum, fixed bytes, integer and struct types can @@ -2095,7 +2145,7 @@ containing that key and the associated value. Returns an empty `optional` if the .fetch(KeyType key) returns (optional(ValueType)); ``` -Checks whether **key** is present in the `mapping` and returns an `optional` with the associated value. +Checks whether **key** exists in the `mapping` and returns an `optional` with the associated value. Returns an empty `optional` if there is no such key. ##### \.exists() @@ -2104,7 +2154,7 @@ Returns an empty `optional` if there is no such key. .exists(KeyType key) returns (bool); ``` -Returns whether **key** is present in the `mapping`. +Returns whether **key** exists in the `mapping`. ##### \.empty() @@ -2120,7 +2170,7 @@ Returns whether the `mapping` is empty. .replace(KeyType key, ValueType value) returns (bool); ``` -Sets the value associated with **key** only if **key** is present in the `mapping` and +Sets the value associated with **key** only if **key** exists in the `mapping` and returns the success flag. ##### \.add() @@ -2129,7 +2179,7 @@ returns the success flag. .add(KeyType key, ValueType value) returns (bool); ``` -Sets the value associated with **key** only if **key** is not present in the `mapping`. +Sets the value associated with **key** only if **key** does not exist in the `mapping`. ##### \.getSet() @@ -2146,17 +2196,26 @@ previous value associated with the **key**, if any. Otherwise, returns an empty .getAdd(KeyType key, ValueType value) returns (optional(ValueType)); ``` -Sets the value associated with **key**, but only if **key** is not present in the `mapping`. -Returns an `optional` with the old value without changing the dictionary if that value is present +Sets the value associated with **key**, but only if **key** does not exist in the `mapping`. +Returns an `optional` with the old value without changing the dictionary if that value exists in the `mapping`, otherwise returns an empty `optional`. +##### \.getDel() + +```TVMSolidity +.getDel(KeyType key) returns (optional(ValueType)); +``` + +Deletes the **key** from the `mapping` **map** and returns an `optional` +with the corresponding value. Returns an empty optional if the key does not exist. + ##### \.getReplace() ```TVMSolidity .getReplace(KeyType key, ValueType value) returns (optional(ValueType)); ``` -Sets the value associated with **key**, but only if **key** is present in the `mapping`. +Sets the value associated with **key**, but only if **key** exists in the `mapping`. On success, returns an `optional` with the old value associated with the **key**. Otherwise, returns an empty `optional`. @@ -2327,7 +2386,7 @@ contract MyContract { ##### Function call via object -In TON solidity **arguments of a function call passed by value not by +In TVM Solidity **arguments of a function call passed by value not by reference**. It's effective for numbers and even for huge arrays. See ([TVM][1] - A.2.3.2). **But if a library function is called like `obj.func(b, c)` then the @@ -2383,7 +2442,7 @@ contract MyContract { ### Import -TON Solidity compiler allows user to import remote files using link starting with `http`. +TVM Solidity compiler allows user to import remote files using link starting with `http`. If import file name starts with `http`, then compiler tries to download the file using this link and saves it to the folder `.solc_imports`. If compiler fails to create this folder or to download the file, then an error is emitted. @@ -2393,7 +2452,7 @@ to download the file, then an error is emitted. Example: ```TVMSolidity -pragma ton-solidity >= 0.35.0; +pragma ever-solidity >= 0.35.0; pragma AbiHeader expire; pragma AbiHeader pubkey; @@ -2413,13 +2472,13 @@ the pragma to all your files if you want to enable it in your whole project. If you import another file, the pragma from that file is not automatically applied to the importing file. -#### pragma ton-solidity +#### pragma ever-solidity ```TVMSolidity -pragma ton-solidity >= 0.35.5; // Check if the compiler version is greater or equal than 0.35.5 -pragma ton-solidity ^ 0.35.5; // Check if the compiler version is greater or equal than 0.35.5 and less than 0.36.0 -pragma ton-solidity < 0.35.5; // Check if the compiler version is less than 0.35.5 -pragma ton-solidity >= 0.35.5 < 0.35.7; // Check if the compiler version is equal to either 0.35.5 or 0.35.6 +pragma ever-solidity >= 0.35.5; // Check if the compiler version is greater or equal than 0.35.5 +pragma ever-solidity ^ 0.35.5; // Check if the compiler version is greater or equal than 0.35.5 and less than 0.36.0 +pragma ever-solidity < 0.35.5; // Check if the compiler version is less than 0.35.5 +pragma ever-solidity >= 0.35.5 < 0.35.7; // Check if the compiler version is equal to either 0.35.5 or 0.35.6 ``` Used to restrict source file compilation to the particular compiler versions. @@ -2482,16 +2541,16 @@ Here is example of [message expiration time](https://docs.ton.dev/86757ecb2/p/88 pragma msgValue ; ``` -Allows specifying default value in nanotons attached to the +Allows specifying default value in nanoevers attached to the internal outbound messages used to call another contract. If it's not -specified, this value is set to 10 000 000 nanotons. +specified, this value is set to 10 000 000 nanoevers. Example: ```TVMSolidity pragma msgValue 123456789; pragma msgValue 1e8; -pragma msgValue 10 ton; +pragma msgValue 10 ever; pragma msgValue 10_000_000_123; ``` @@ -2502,7 +2561,7 @@ pragma upgrade func; pragma upgrade oldsol; ``` -Defines that code is compiled with special selector that is needed to upgrade func/solidity contracts. +Defines that code is compiled with special selector that is needed to upgrade FunC/Solidity contracts. ### State variables @@ -2566,8 +2625,8 @@ contract C { `receive` function is called in two cases: -1. [msg.data](#msgdata) (or message body) is empty. -2. [msg.data](#msgdata) starts with 32-bit zero. Then message body may contain data, +1. [msg.body](#msgbody) (or message body) is empty. +2. [msg.body](#msgbody) starts with 32-bit zero. Then message body may contain data, for example [string](#string) with comment. If in the contract there is no `receive` function then the contract has an implicit empty `receive` @@ -2580,8 +2639,8 @@ contract Sink { uint public msgWithPayload = 0; receive() external { ++counter; - // if the inbound internal message has payload then we can get it using `msg.data` - TvmSlice s = msg.data; + // if the inbound internal message has payload then we can get it using `msg.body` + TvmSlice s = msg.body; if (!s.empty()) { ++msgWithPayload; } @@ -2590,18 +2649,18 @@ contract Sink { // file bomber.sol contract Bomber { - // This function send tons 3 times to the Sink contract. Sink's function receive will handle + // This function send evers 3 times to the Sink contract. Sink's function receive will handle // that messages. function f(address addr) pure public { tvm.accept(); - addr.transfer({value: 1 ton}); // message's body is empty + addr.transfer({value: 1 ever}); // message's body is empty TvmBuilder b; - addr.transfer({value: 1 ton, body: b.toCell()}); // message's body is empty, too + addr.transfer({value: 1 ever, body: b.toCell()}); // message's body is empty, too b.store(uint32(0), "Thank you for the coffee!"); // body of the message contains 32-bit zero number and the string - addr.transfer({value: 20 ton, body: b.toCell()}); + addr.transfer({value: 20 ever, body: b.toCell()}); } } ``` @@ -2646,20 +2705,20 @@ contract ContractB { tvm.accept(); // The message contains a function id that the contract doesn't contain. // There is wrong casting to ContractAnother. `addr` is ContractA's address. - ContractAnother(addr).sum{value: 1 ton}(2, 2); + ContractAnother(addr).sum{value: 1 ever}(2, 2); { TvmBuilder b; b.storeUnsigned(1, 1); // Bit-length of the message is equal to 20 bits. - addr.transfer({value: 2 ton, body: b.toCell()}); + addr.transfer({value: 2 ever, body: b.toCell()}); } { TvmBuilder b; b.storeRef(b); // Bit-length of the message is equal to zero but the message contains one reference. - addr.transfer({value: 1 ton, body: b.toCell()}); + addr.transfer({value: 1 ever, body: b.toCell()}); } TvmBuilder b; @@ -2667,7 +2726,7 @@ contract ContractB { b.store(id, uint(2)); // ContractA's fallback function won't be called because the message body doesn't contain // the second ContractA.f's parameter. It will cause cell underflow exception in ContractA. - addr.transfer({value: 1 ton, body: b.toCell()}); + addr.transfer({value: 1 ever, body: b.toCell()}); } } ``` @@ -2974,12 +3033,12 @@ function f(uint n) public responsible pure { ### External function calls -TON Solidity compiler allows specifying different parameters of the outbound internal message that +TVM Solidity compiler allows specifying different parameters of the outbound internal message that is sent via external function call. Note, all external function calls are asynchronous, so callee function will be called after termination of the current transaction. `value`, `currencies`, `bounce` or `flag` options can be set. See [\.transfer()](#addresstransfer) where these options are described. -**Note:** if `value` isn't set, then the default value is equal to 0.01 ton, or 10^7 nanoton. It's equal +**Note:** if `value` isn't set, then the default value is equal to 0.01 ever, or 10^7 nanoever. It's equal to 10_000 units of gas in workchain. If the callee function returns some value and marked as `responsible` then `callback` option must be set. This callback function will be called by another contract. Remote function will pass its return @@ -2997,14 +3056,14 @@ interface IContract { contract Caller { function callExt(address addr) public { - IContract(addr).f(123); // attached default value: 0.01 ton - IContract(addr).f{value: 10 ton}(123); - IContract(addr).f{value: 10 ton, flag: 3}(123); - IContract(addr).f{value: 10 ton, bounce: true}(123); + IContract(addr).f(123); // attached default value: 0.01 ever + IContract(addr).f{value: 10 ever}(123); + IContract(addr).f{value: 10 ever, flag: 3}(123); + IContract(addr).f{value: 10 ever, bounce: true}(123); IContract(addr).f{value: 1 micro, bounce: false, flag: 128}(123); ExtraCurrencyCollection cc; cc[12] = 1000; - IContract(addr).f{value: 10 ton, currencies:cc}(123); + IContract(addr).f{value: 10 ever, currencies:cc}(123); } } ``` @@ -3024,7 +3083,7 @@ contract RemoteContract { contract Caller { function test(address addr, uint x) public pure { // `getCost` returns result to `onGetCost` - RemoteContract(addr).getCost{value: 1 ton, callback: Caller.onGetCost}(x); + RemoteContract(addr).getCost{value: 1 ever, callback: Caller.onGetCost}(x); } function onGetCost(uint cost) public { @@ -3058,7 +3117,7 @@ and [4.1_CurrencyExchange.sol](https://github.com/tonlabs/samples/blob/master/so #### Synchronous calls -TON Solidity compiler allows user to perform synchronous calls. To do it user should call a remote contract +TVM Solidity compiler allows user to perform synchronous calls. To do it user should call a remote contract function with `.await` suffix. Example: ```TVMSolidity @@ -3188,7 +3247,7 @@ msg.value (uint128) Returns: -* Balance of the inbound message in nanotons for internal message. +* Balance of the inbound message in nanoevers for internal message. * 0 for external message. * Undefined value for tick/tock transaction. @@ -3225,10 +3284,38 @@ Returns the field **created_at** of the external inbound message. ##### msg.data ```TVMSolidity -msg.data (TvmSlice) +msg.data (TvmCell) +``` + +Returns [the whole message](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L155). + +##### msg.forwardFee + +```TVMSolidity +msg.forwardFee (varUint16) +``` + +Returns: + * the [forward fee](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L126) for the internal inbound message. + * `0` for the external inbound message. + +##### msg.importFee + +```TVMSolidity +msg.importFee (varUint16) ``` -Returns the payload of an inbound message. +Returns: + * the field [import_fee](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L130) for external inbound message. **Note:** field `import_fee` is set offchain by user as they want and does not reflect the real import fee of the message. + * `0` for the internal inbound message. + +##### msg.body + +```TVMSolidity +msg.body (TvmSlice) +``` + +Returns the payload (message body) of an inbound message. ##### msg.hasStateInit @@ -3293,7 +3380,7 @@ of `tvm.accept()`. tvm.buyGas(uint value); ``` -Computes the amount of gas that can be bought for `value` nanotons, and sets **gl** +Computes the amount of gas that can be bought for `value` nanoevers, and sets **gl** accordingly in the same way as [tvm.setGasLimit()](#tvmsetgaslimit). ##### tvm.commit() @@ -3458,8 +3545,8 @@ tvm.rawReserve(uint value, uint8 flag); tvm.rawReserve(uint value, ExtraCurrencyCollection currency, uint8 flag); ``` -Creates an output action that reserves **reserve** nanotons. It is roughly equivalent to -create an outbound message carrying **reserve** nanotons to oneself, so that the subsequent output +Creates an output action that reserves **reserve** nanoevers. It is roughly equivalent to +create an outbound message carrying **reserve** nanoevers to oneself, so that the subsequent output actions would not be able to spend more money than the remainder. It's a wrapper for opcodes "RAWRESERVE" and "RAWRESERVEX". See [TVM][1]. @@ -3471,22 +3558,22 @@ of the contract before the transaction minus storage fee. Note: `original_balanc * `remaining_balance` is contract's current remaining balance at the action phase after some handled actions and before handing the "rawReserve" action. -Let's consider how much nanotons (**reserve**) are reserved in all cases of **flag**: +Let's consider how much nanoevers (**reserve**) are reserved in all cases of **flag**: -* 0 -> `reserve = value` nanotons. -* 1 -> `reserve = remaining_balance - value` nanotons. -* 2 -> `reserve = min(value, remaining_balance)` nanotons. -* 3 = 2 + 1 -> `reserve = remaining_balance - min(value, remaining_balance)` nanotons. +* 0 -> `reserve = value` nanoevers. +* 1 -> `reserve = remaining_balance - value` nanoevers. +* 2 -> `reserve = min(value, remaining_balance)` nanoevers. +* 3 = 2 + 1 -> `reserve = remaining_balance - min(value, remaining_balance)` nanoevers. -* 4 -> `reserve = original_balance + value` nanotons. -* 5 = 4 + 1 -> `reserve = remaining_balance - (original_balance + value)` nanotons. -* 6 = 4 + 2 -> `reserve = min(original_balance + value, remaining_balance) = remaining_balance` nanotons. -* 7 = 4 + 2 + 1 -> `reserve = remaining_balance - min(original_balance + value, remaining_balance)` nanotons. +* 4 -> `reserve = original_balance + value` nanoevers. +* 5 = 4 + 1 -> `reserve = remaining_balance - (original_balance + value)` nanoevers. +* 6 = 4 + 2 -> `reserve = min(original_balance + value, remaining_balance) = remaining_balance` nanoevers. +* 7 = 4 + 2 + 1 -> `reserve = remaining_balance - min(original_balance + value, remaining_balance)` nanoevers. -* 12 = 8 + 4 -> `reserve = original_balance - value` nanotons. -* 13 = 8 + 4 + 1 -> `reserve = remaining_balance - (original_balance - value)` nanotons. -* 14 = 8 + 4 + 2 -> `reserve = min(original_balance - value, remaining_balance)` nanotons. -* 15 = 8 + 4 + 2 + 1 -> `reserve = remaining_balance - min(original_balance - value, remaining_balance)` nanotons. +* 12 = 8 + 4 -> `reserve = original_balance - value` nanoevers. +* 13 = 8 + 4 + 1 -> `reserve = remaining_balance - (original_balance - value)` nanoevers. +* 14 = 8 + 4 + 2 -> `reserve = min(original_balance - value, remaining_balance)` nanoevers. +* 15 = 8 + 4 + 2 + 1 -> `reserve = remaining_balance - min(original_balance - value, remaining_balance)` nanoevers. All other values of `flag` are invalid. @@ -3503,7 +3590,7 @@ To make it clear, let's consider the order of `reserve` calculation: Example: ```TVMSolidity -tvm.rawReserve(1 ton, 4 + 8); +tvm.rawReserve(1 ever, 4 + 8); ``` See also: [23_rawReserve.sol](https://github.com/tonlabs/samples/blob/master/solidity/23_rawReserve.sol) @@ -3544,13 +3631,16 @@ uint256 hash = tvm.hash(bytes); ##### tvm.checkSign() ```TVMSolidity -tvm.checkSign(uint256 hash, uint256 SignHighPart, uint256 SignLowPart, uint256 pubkey) returns (bool); -tvm.checkSign(uint256 hash, TvmSlice signature, uint256 pubkey) returns (bool); +(1) +tvm.checkSign(uint256 dataHash, uint256 SignHighPart, uint256 SignLowPart, uint256 pubkey) returns (bool); +(2) +tvm.checkSign(uint256 dataHash, TvmSlice signature, uint256 pubkey) returns (bool); +(3) tvm.checkSign(TvmSlice data, TvmSlice signature, uint256 pubkey) returns (bool); ``` Executes TVM instruction "CHKSIGNU" ([TVM][1] - A.11.6. - F910) for variants 1 and 2. -This command checks the Ed25519-signature of the **hash** using public key **pubkey**. +This command checks the Ed25519-signature of the **dataHash** using public key **pubkey**. Signature is represented by two uint256 **SignHighPart** and **SignLowPart** in the first variant and by the slice **signature** in the second variant. In the third variant executes TVM instruction "CHKSIGNS" ([TVM][1] - A.11.6. - F911). @@ -3560,21 +3650,24 @@ Signature is represented by the slice **signature**. Example: ```TVMSolidity -uint256 hash; +// option 1 +uint256 dataHash; uint256 SignHighPart; uint256 SignLowPart; uint256 pubkey; -bool signatureIsValid = tvm.checkSign(hash, SignHighPart, SignLowPart, pubkey); // 1 variant +bool signatureIsValid = tvm.checkSign(dataHash, SignHighPart, SignLowPart, pubkey); -uint256 hash; +// option 2 +uint256 dataHash; TvmSlice signature; uint256 pubkey; -bool signatureIsValid = tvm.checkSign(hash, signature, pubkey); // 2 variant +bool signatureIsValid = tvm.checkSign(dataHash, signature, pubkey); +// option 3 TvmSlice data; TvmSlice signature; uint256 pubkey; -bool signatureIsValid = tvm.checkSign(hash, signature, pubkey); // 3 variant +bool signatureIsValid = tvm.checkSign(data, signature, pubkey); ``` ##### Deploy contract from contract @@ -3742,7 +3835,7 @@ Examples: ```TVMSolidity TvmCell stateInit = ...; -address newWallet = new SimpleWallet{value: 1 ton, stateInit: stateInit}(arg0, arg1, ...); +address newWallet = new SimpleWallet{value: 1 ever, stateInit: stateInit}(arg0, arg1, ...); ``` ##### `code` option usage @@ -3751,7 +3844,7 @@ address newWallet = new SimpleWallet{value: 1 ton, stateInit: stateInit}(arg0, a ```TVMSolidity TvmCell code = ...; -address newWallet = new SimpleWallet{value: 1 ton, code: code}(arg0, arg1, ...); +address newWallet = new SimpleWallet{value: 1 ever, code: code}(arg0, arg1, ...); ``` The following options can only be used with the `code` option: @@ -3760,7 +3853,7 @@ The following options can only be used with the `code` option: * `varInit` (`initializer list`) - used to set [static](#keyword-static) variables of the new contract. * `splitDepth` (`uint8`) - splitting depth. `0 <= splitDepth <= 31`. By default, it has no value. -Example of these options usage: +Example of usage of these options: ```TVMSolidity // file SimpleWallet.sol @@ -3774,7 +3867,7 @@ contract SimpleWallet { // file containing a contract that deploys a SimpleWallet TvmCell code = ...; address newWallet = new SimpleWallet{ - value: 1 ton, + value: 1 ever, code: code, pubkey: 0xe8b1d839abe27b2abb9d4a2943a9143a9c7e2ae06799bd24dec1d7a8891ae5dd, splitDepth: 15, @@ -3801,7 +3894,7 @@ Possible values of the `flag` are described here: [\.transfer()](#addr TvmCell stateInit = ...; address newWallet = new SimpleWallet{ stateInit: stateInit, - value: 1 ton, + value: 1 ever, wid: -1, flag: 0 }(arg0, arg1, ...); @@ -3972,15 +4065,15 @@ contract Remote { // deploy the contract TvmCell body = tvm.encodeBody(Remote, 100, 200, 300); -addr.transfer({value: 10 ton, body: body, stateInit: stateInit }); +addr.transfer({value: 10 ever, body: body, stateInit: stateInit }); // call the function TvmCell body = tvm.encodeBody(Remote.func, 123, -654); -addr.transfer({value: 10 ton, body: body}); +addr.transfer({value: 10 ever, body: body}); // call the responsible function TvmCell body = tvm.encodeBody(Remote.getCost, onGetCost, 105); -addr.transfer({value: 10 ton, body: body}); +addr.transfer({value: 10 ever, body: body}); ``` See also: @@ -4056,7 +4149,7 @@ but stores special data: * on error id - 32 bits; * abi version - 8 bits; Can be specified manually and contain full abi version in little endian half bytes (e.g. version = "2.3" -> abiVer: 0x32) * header mask - 3 bits in such order: time, expire, pubkey; -* optional value signBoxHandle - 1 bit (whether value is present) + \[32 bits\]; +* optional value signBoxHandle - 1 bit (whether value exists) + \[32 bits\]; * control flags byte - 8 bits. Currently used bits: 1 - override time (dengine will replace time value with current time) @@ -4398,7 +4491,7 @@ Returns the starting logical time of the current block. The pseudorandom number generator uses the random seed. The initial value of the random seed before a smart contract execution in -TON Blockchain is a hash of the smart contract address and the global +TVM compatible blockchains is a hash of the smart contract address and the global block random seed. If there are several runs of the same smart contract inside a block, then all of these runs will have the same random seed. This can be fixed, for example, by running `rnd.shuffle()` (without @@ -4629,39 +4722,46 @@ valueToGas(uint128 value) returns (uint128 gas) valueToGas(uint128 value, int8 wid) returns (uint128 gas) ``` -Counts how much **gas** could be bought on **value** nanotons in workchain **wid**. +Counts how much **gas** could be bought on **value** nanoevers in workchain **wid**. Throws an exception if **wid** is not equal to `0` or `-1`. If `wid` is omitted than used the contract's `wid`. +#### gasleft + +```TVMSolidity +gasleft() returns (uint64) +``` + +Returns the remaining gas. Supported only if `CapGasRemainingInsn` capability is set. + ### TVM exception codes -| Name | Code | Definition | -|-------------------|:----:|----------------------------------------------------------------------------------------------------------------------------------------------------| -| Stack underflow | 2 | Not enough arguments in the stack for a primitive | -| Stack overflow | 3 | More values have been stored on a stack than allowed by this version of TVM | -| Integer overflow | 4 | Integer does not fit into expected range (by default −2256 ≤ x < 2256), or a division by zero has occurred | -| Range check error | 5 | Integer out of expected range | -| Invalid opcode | 6 | Instruction or its immediate arguments cannot be decoded | -| Type check error | 7 | An argument to a primitive is of incorrect value type | -| Cell overflow | 8 | Error in one of the serialization primitives | -| Cell underflow | 9 | Deserialization error | -| Dictionary error | 10 | Error while deserializing a dictionary object | -| Unknown error | 11 | Unknown error, may be thrown by user programs | -| Fatal error | 12 | Thrown by TVM in situations deemed impossible | -| Out of gas | 13 | Thrown by TVM when the remaining gas (g r ) becomes negative. This exception usually cannot be caught and leads to an immediate termination of TVM | +| Name | Code | Definition | +|-------------------|:----:|-----------------------------------------------------------------------------------------------------------------------------------------------------| +| Stack underflow | 2 | Not enough arguments in the stack for a primitive | +| Stack overflow | 3 | More values have been stored on a stack than allowed by this version of TVM | +| Integer overflow | 4 | Integer does not fit into expected range (by default −2256 ≤ x < 2256), or a division by zero has occurred | +| Range check error | 5 | Integer out of expected range | +| Invalid opcode | 6 | Instruction or its immediate arguments cannot be decoded | +| Type check error | 7 | An argument to a primitive is of incorrect value type | +| Cell overflow | 8 | Error in one of the serialization primitives | +| Cell underflow | 9 | Deserialization error | +| Dictionary error | 10 | Error while deserializing a dictionary object | +| Unknown error | 11 | Unknown error, may be thrown by user programs | +| Fatal error | 12 | Thrown by TVM in situations deemed impossible | +| Out of gas | -14 | Thrown by TVM when the remaining gas (gr) becomes negative. This exception cannot be caught and leads to an immediate termination of TVM | See also: [TVM][1] - 4.5.7 ### Solidity runtime errors -Smart-contract written on solidity can throw runtime errors while execution. +Smart-contract written in TVM Solidity can throw runtime errors while execution. Solidity runtime error codes: * **40** - External inbound message has an invalid signature. See [tvm.pubkey()](#tvmpubkey) and [msg.pubkey()](#msgpubkey). * **50** - Array index or index of [\.at()](#mappingat) is out of range. * **51** - Contract's constructor has already been called. * **52** - Replay protection exception. See `timestamp` in [pragma AbiHeader](#pragma-abiheader). - * **53** - See [\.unpack()](#addressunpack). * **54** - `.pop` call for an empty array. * **55** - See [tvm.insertPubkey()](#tvminsertpubkey). * **57** - External inbound message is expired. See `expire` in [pragma AbiHeader](#pragma-abiheader). @@ -4669,12 +4769,12 @@ Solidity runtime error codes: * **60** - Inbound message has wrong function id. In the contract there are no functions with such function id and there is no fallback function that could handle the message. See [fallback](#fallback). * **61** - Deploying `StateInit` has no public key in `data` field. * **62** - Reserved for internal usage. - * **63** - See [\.get()](#optionaltypeget). + * **63** - See [\.get()](#optionaltget). * **64** - `tvm.buildExtMSg()` call with wrong parameters. See [tvm.buildExtMsg()](#tvmbuildextmsg). * **66** - Convert an integer to a string with width less than number length. See [format()](#format). * **67** - See [gasToValue](#gastovalue) and [valueToGas](#valuetogas). * **68** - There is no config parameter 20 or 21. - * **69** - Zero to the power of zero calculation (`0**0` in solidity style or `0^0`). + * **69** - Zero to the power of zero calculation (`0**0` in TVM Solidity style or `0^0`). * **70** - `string` method `substr` was called with substr longer than the whole string. * **71** - Function marked by `externalMsg` was called by internal message. * **72** - Function marked by `internalMsg` was called by external message. @@ -4735,22 +4835,22 @@ function of special function like `receive`, `fallback`, `onBounce`, `onTickTock Before calling contract's function `main_external` does: 1. Checks the message signature. Let's consider how the signature is checked: - - If signature is present and `pubkey` header isn't defined then `tvm.pubkey()` is used + - If signature exists and `pubkey` header isn't defined then `tvm.pubkey()` is used for checking. - - If signature isn't present and `pubkey` header isn't defined then signature isn't checked. - - If signature is present, `pubkey` header is defined and `pubkey` isn't present in the + - If signature isn't exists and `pubkey` header isn't defined then signature isn't checked. + - If signature exists, `pubkey` header is defined and `pubkey` isn't exists in the message then `tvm.pubkey()` is used for checking. - - If signature is present, `pubkey` header is defined and `pubkey` is present in the + - If signature exists, `pubkey` header is defined and `pubkey` exists in the message then `msg.pubkey()` is used for checking. - - If signature isn't present, `pubkey` header is defined and `pubkey` is present in the + - If signature isn't exists, `pubkey` header is defined and `pubkey` exists in the message then an [exception with code 58](#solidity-runtime-errors) is thrown. 2. Replay protection: - - `time` is present and there is no `afterSignatureCheck` then the contract checks whether - `oldTime` < `time` < `now` * 1000 + 30 minutes. If it's true then `oldTime` is updated by new `time`. + - [*time* header](#pragma-abiheader) exists (`pragma AbiHeader notime` is not used) then the contract checks whether + `oldTime` < `time` < `now * 1000 + 30 minutes`. If it's true then `oldTime` is updated by new `time`. Otherwise, an exception is thrown. - there is `afterSignatureCheck` (despite usage of `time`) then make your own replay protection. 3. Message expiration: - - `expire` is present and there is no `afterSignatureCheck` then the contract checks whether + - `expire` exists and there is no `afterSignatureCheck` then the contract checks whether `expire` > `now`. - there is `afterSignatureCheck` (despite usage of `expire`) then make your own check. diff --git a/Cargo.lock b/Cargo.lock index e04b66c1..f905a1ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ "gimli", ] @@ -99,15 +99,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" [[package]] name = "anstyle-parse" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ "utf8parse", ] @@ -145,12 +145,12 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "assert_cmd" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d6b683edf8d1119fe420a94f8a7e389239666aa72e65495d91c00462510151" +checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" dependencies = [ "anstyle", - "bstr 1.5.0", + "bstr 1.6.0", "doc-comment", "predicates", "predicates-core", @@ -177,9 +177,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ "addr2line", "cc", @@ -211,6 +211,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "blake2b_simd" version = "0.5.11" @@ -251,12 +257,11 @@ dependencies = [ [[package]] name = "bstr" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", - "once_cell", "regex-automata", "serde", ] @@ -320,7 +325,7 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", - "bitflags", + "bitflags 1.3.2", "strsim 0.8.0", "textwrap", "unicode-width", @@ -329,9 +334,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.4" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80672091db20273a15cf9fdd4e47ed43b5091ec9841bf4c6145c9dfbbcae09ed" +checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" dependencies = [ "clap_builder", "clap_derive", @@ -340,27 +345,26 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.4" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1458a1df40e1e2afebb7ab60ce55c1fa8f431146205aa5f4887e0b111c27636" +checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" dependencies = [ "anstream", "anstyle", - "bitflags", "clap_lex", "strsim 0.10.0", ] [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.27", ] [[package]] @@ -398,9 +402,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -552,9 +556,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "errno" @@ -663,9 +667,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" @@ -702,25 +706,13 @@ dependencies = [ "cc", ] -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys", -] - [[package]] name = "is-terminal" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", + "hermit-abi 0.3.2", "rustix", "windows-sys", ] @@ -736,9 +728,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" @@ -766,15 +758,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" [[package]] name = "lockfree" @@ -798,9 +790,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] @@ -813,9 +805,9 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "num" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ "num-bigint", "num-complex", @@ -891,18 +883,18 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "object" -version = "0.30.4" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] @@ -970,18 +962,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.28" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -1076,26 +1068,32 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ "aho-corasick", "memchr", + "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.1.10" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "rust-argon2" @@ -1117,13 +1115,12 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.37.20" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" dependencies = [ - "bitflags", + "bitflags 2.3.3", "errno", - "io-lifetimes", "libc", "linux-raw-sys", "windows-sys", @@ -1131,35 +1128,35 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "serde" -version = "1.0.164" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.27", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" dependencies = [ "itoa", "ryu", @@ -1224,17 +1221,17 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "sold" -version = "0.70.0" +version = "0.71.0" dependencies = [ "assert_cmd", "atty", - "clap 4.3.4", + "clap 4.3.19", "cmake", "dunce", "failure", @@ -1289,9 +1286,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.18" +version = "2.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" dependencies = [ "proc-macro2", "quote", @@ -1349,8 +1346,8 @@ dependencies = [ [[package]] name = "ton_abi" -version = "2.3.108" -source = "git+https://github.com/tonlabs/ever-abi.git?tag=2.3.108#af5ae77b9f15c9c40ef8af567391fae0ee711e21" +version = "2.3.129" +source = "git+https://github.com/tonlabs/ever-abi.git?tag=2.3.129#6445189dbf5aa9b7ecac93c06421eacc09461a0b" dependencies = [ "base64 0.10.1", "byteorder", @@ -1371,8 +1368,8 @@ dependencies = [ [[package]] name = "ton_block" -version = "1.9.70" -source = "git+https://github.com/tonlabs/ever-block.git?tag=1.9.70#fb352a619905ea2866ceeae59bbdca451fff0ded" +version = "1.9.88" +source = "git+https://github.com/tonlabs/ever-block.git?tag=1.9.88#d38a615860e38e4a6ff3c56c6bf1c2a459e7c80a" dependencies = [ "base64 0.13.1", "crc", @@ -1389,8 +1386,8 @@ dependencies = [ [[package]] name = "ton_labs_assembler" -version = "1.2.118" -source = "git+https://github.com/tonlabs/ever-assembler.git?tag=1.2.118#d2009265ae21f6bc332bcadf5adb7fd41d63611f" +version = "1.2.130" +source = "git+https://github.com/tonlabs/ever-assembler.git?tag=1.2.130#625bd9075e27b4d3bee21481ccc504dc8d891a1e" dependencies = [ "failure", "hex 0.4.3", @@ -1404,8 +1401,8 @@ dependencies = [ [[package]] name = "ton_types" -version = "2.0.12" -source = "git+https://github.com/tonlabs/ever-types.git?tag=2.0.12#4dd14bdbf060b744665ed7745cf771c0e0c9914d" +version = "2.0.18" +source = "git+https://github.com/tonlabs/ever-types.git?tag=2.0.18#cc9e204f9122967b0f1d5af3208f8ccc36e706ef" dependencies = [ "aes-ctr", "base64 0.13.1", @@ -1431,8 +1428,8 @@ dependencies = [ [[package]] name = "ton_vm" -version = "1.8.162" -source = "git+https://github.com/tonlabs/ever-vm.git?tag=1.8.162#448722b486f9fdfe99cac2befb01184592bf8dad" +version = "1.8.189" +source = "git+https://github.com/tonlabs/ever-vm.git?tag=1.8.189#5bc2dece1944b22a9cfafee3d7ad7f577f5fb10f" dependencies = [ "diffy", "ed25519 1.5.3", @@ -1452,8 +1449,8 @@ dependencies = [ [[package]] name = "tvm_linker" -version = "0.20.3" -source = "git+https://github.com/tonlabs/TVM-linker.git?tag=0.20.3#d52a117d09694e4af92578ccd5098dc0f3a00514" +version = "0.20.4" +source = "git+https://github.com/tonlabs/TVM-linker.git?tag=0.20.4#307243825a49f5f589657cfa235903e49207efe7" dependencies = [ "base64 0.13.1", "clap 2.34.0", @@ -1487,9 +1484,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-width" @@ -1590,7 +1587,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.27", "wasm-bindgen-shared", ] @@ -1612,7 +1609,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.27", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1665,9 +1662,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -1748,7 +1745,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.27", ] [[package]] diff --git a/Changelog_TON.md b/Changelog.md similarity index 94% rename from Changelog_TON.md rename to Changelog.md index 300523c8..0ffccf51 100644 --- a/Changelog_TON.md +++ b/Changelog.md @@ -1,7 +1,31 @@ +### 0.71.0 (2023-07-20) + +Bugfixes: + * Fixed segmentation fault of the compiler that could occur in some cases of using `try-catch` (experimental feature). + * Fixed compilation error in case of using operator `+` for constant strings. + * Fixed segmentation fault of the compiler that could occur in the case of using `constructor` with `functionID()`. + * Fixed an exception which could occur on contract upgrade in case of state variables number being reduced, yet still exceeding 16. + +Breaking changes: + * Now [msg.data](API.md#msgdata) returns the whole message instead of the message body. Use [msg.body](API.md#msgbody) to get the message body (payload). + * `
.unpack` returns `(int32, uint256)` instead of `(int8, uint256)`. + +Compiler features: + * Supported [.getOr()](API.md#optionaltgetor) and [.getOrDefault()](API.md#optionaltgetordefault). + * Supported creating empty cell via `TvmCell()`. + * Supported `.store()` for `varInt`/`varUint`. + * Supported [msg.forwardFee](API.md#msgforwardfee). + * Supported [msg.importFee](API.md#msgimportfee). + * Supported [gasleft](API.md#gasleft). + * Supported [\.getDel()](API.md#mappinggetdel). + +Gas optimizations: + * Assorted stack optimizations. + ### 0.70.0 (2023-06-14) Compiler features: - * Supported [inline assembly](./API.md#assembly). + * Supported [inline assembly](API.md#assembly). * Supported overriding `onCodeUpgrade` function. * Supported [User-defined Value Types](https://docs.soliditylang.org/en/latest/types.html#user-defined-value-types). You can also use this type in public functions. * [Supported `type(T).min` and `type(T).max`](API.md#type-information). @@ -643,14 +667,14 @@ Bugfixes: ### 0.30 (2020-08-21) -APIs for common TON-specific functionality: +APIs for common TVM-specific functionality: * Supported tick and tock transactions. See onTickTock function. Bug fixes. ### 0.29 (2020-08-19) -APIs for common TON-specific functionality: +APIs for common TVM-specific functionality: * Supported optional type * Added methods for optional type: set, hasValue, get @@ -659,7 +683,7 @@ Changed APIs to handle mappings: fetch, min, max, prev, next and ect. ### 0.20 (2020-03-30) -APIs for common TON-specific functionality: +APIs for common TVM-specific functionality: * Migrated frontend to 0.6.3 * Native types support @@ -675,7 +699,7 @@ APIs for common TON-specific functionality: ### 0.18 (2020-01-30) -APIs for common TON-specific functionality: +APIs for common TVM-specific functionality: * Address constructors and accessors * Extended address format that includes workchain ID * Members for workchain ID and the actual address part diff --git a/README.md b/README.md index e82b4726..57afc874 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ - - + + -# Sol2TVM Compiler +# the TVM Solidity compiler [![GitHub](https://img.shields.io/github/license/tonlabs/TON-Solidity-Compiler?style=for-the-badge)](./LICENSE) [![Everscale](https://custom-icon-badges.demolab.com/badge/-everscale-13173e?style=for-the-badge&logoColor=yellow&logo=everscale)](https://everscale.network/) -Port of the Solidity smart-contract [compiler](https://github.com/ethereum/solidity) generating TVM bytecode for TON blockchain. Please refer to upstream README.md for information on the language itself. +Port of the Solidity smart-contract [compiler](https://github.com/ethereum/solidity) generating TVM bytecode for TVM compatible blockchains (Everscale, Venom, Gosh, TON). Please refer to upstream README.md for information on the language itself. -## TON Solidity API reference +## TVM Solidity API reference [API documentation is here](https://github.com/tonlabs/TON-Solidity-Compiler/blob/master/API.md) @@ -24,7 +24,13 @@ Port of the Solidity smart-contract [compiler](https://github.com/ethereum/solid Original Instructions about how to build and install the Solidity compiler can be found in the [Solidity documentation](https://solidity.readthedocs.io/en/latest/installing-solidity.html#building-from-source). -### Ubuntu Linux +### Sold driver + +Documentation is available at [README.md](https://github.com/tonlabs/TON-Solidity-Compiler/blob/master/sold/README.md) (RECOMMENDED). + +### Building compiler + +#### Ubuntu Linux ```shell git clone https://github.com/tonlabs/TON-Solidity-Compiler @@ -36,13 +42,13 @@ cmake ../compiler/ -DCMAKE_BUILD_TYPE=Release cmake --build . -- -j8 ``` -Make other TON toolchain utilities aware of the language runtime library location via an environment variable: specify path to `stdlib_sol.tvm`. +Make other toolchain utilities aware of the language runtime library location via an environment variable: specify path to `stdlib_sol.tvm`. ```shell sh ./compiler/scripts/install_lib_variable.sh ``` -### Windows 10 +#### Windows 10 Install Visual Studio Build Tools 2019, Git bash, cmake. Run Developer PowerShell for VS 2019 @@ -57,23 +63,15 @@ cmake -DBoost_DIR="..\compiler\deps\boost\lib\cmake\Boost-1.77.0" -DCMAKE_MSVC_R cmake --build . --config Release -- /m ``` -To facilitate work with other TON tools add path to stdlib_sol.tvm into environment variable `TVM_LINKER_LIB_PATH`. - -## Sold driver - -Documentation is available at [README.md](https://github.com/tonlabs/TON-Solidity-Compiler/blob/master/sold/README.md). +To facilitate work with other toolchain utilities add path to `stdlib_sol.tvm` into environment variable `TVM_LINKER_LIB_PATH`. ## Links -Code samples in Solidity for TON can be found there: [https://github.com/tonlabs/samples/tree/master/solidity](https://github.com/tonlabs/samples/tree/master/solidity) - -TVM linker repository: [https://github.com/tonlabs/TVM-linker](https://github.com/tonlabs/TVM-linker) - -TON OS command line tool: [https://github.com/tonlabs/tonos-cli](https://github.com/tonlabs/tonos-cli) - -Example of usage TON OS for working (deploying, calling and etc.) with TON blockchain can be found there: [Write smart contract in Solidity](https://docs.ton.dev/86757ecb2/p/950f8a-write-smart-contract-in-solidity) - -Change log: [Changelog_TON.md](https://github.com/tonlabs/TON-Solidity-Compiler/blob/master/Changelog_TON.md) + * [Code samples](https://github.com/tonlabs/samples/tree/master/solidity) in TVM Solidity + * [TVM linker repository](https://github.com/tonlabs/TVM-linker) + * [tonos-cli](https://github.com/tonlabs/tonos-cli) command line interface for TVM compatible blockchains + * Example of usage `tonos-cli` for working (deploying, calling and etc.) with TVM compatible blockchains can be found there: [Write smart contract in Solidity](https://docs.ton.dev/86757ecb2/p/950f8a-write-smart-contract-in-solidity) + * [Changelog](https://github.com/tonlabs/TON-Solidity-Compiler/blob/master/Changelog_TON.md) ## License [GNU GENERAL PUBLIC LICENSE Version 3](./LICENSE) diff --git a/compiler/CMakeLists.txt b/compiler/CMakeLists.txt index 67ade9bb..722c04ec 100644 --- a/compiler/CMakeLists.txt +++ b/compiler/CMakeLists.txt @@ -21,7 +21,7 @@ include(EthPolicy) eth_policy() # project name and version should be set after cmake_policy CMP0048 -set(PROJECT_VERSION "0.70.0") +set(PROJECT_VERSION "0.71.0") # OSX target needed in order to support std::visit set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX) diff --git a/compiler/libsolidity/analysis/GlobalContext.cpp b/compiler/libsolidity/analysis/GlobalContext.cpp index 4e3c476b..51a75292 100644 --- a/compiler/libsolidity/analysis/GlobalContext.cpp +++ b/compiler/libsolidity/analysis/GlobalContext.cpp @@ -45,8 +45,8 @@ int magicVariableToID(std::string const& _name) else if (_name == "block") return -4; else if (_name == "blockhash") return -5; else if (_name == "ecrecover") return -6; - else if (_name == "format") return -105; else if (_name == "gasleft") return -7; + else if (_name == "format") return -105; else if (_name == "keccak256") return -8; else if (_name == "logtvm") return -102; else if (_name == "math") return -103; @@ -86,6 +86,7 @@ inline vector> constructMagicVariable magicVarDecl("addmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, StateMutability::Pure)), magicVarDecl("assert", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Assert, StateMutability::Pure)), magicVarDecl("block", TypeProvider::magic(MagicType::Kind::Block)), + magicVarDecl("gasleft", TypeProvider::function(strings(), {"uint64"}, FunctionType::Kind::GasLeft, StateMutability::Pure)), magicVarDecl("msg", TypeProvider::magic(MagicType::Kind::Message)), magicVarDecl("mulmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, StateMutability::Pure)), magicVarDecl("now", TypeProvider::uint(32)), diff --git a/compiler/libsolidity/analysis/TypeChecker.cpp b/compiler/libsolidity/analysis/TypeChecker.cpp index d83a394b..1fd8472c 100644 --- a/compiler/libsolidity/analysis/TypeChecker.cpp +++ b/compiler/libsolidity/analysis/TypeChecker.cpp @@ -1157,24 +1157,26 @@ bool TypeChecker::visit(IfStatement const& _ifStatement) void TypeChecker::endVisit(TryStatement const& _tryStatement) { TryCatchClause const& clause = _tryStatement.clause(); - std::vector> const& errArgs = clause.parameters()->parameters(); + if (clause.parameters() != nullptr) { + std::vector> const& errArgs = clause.parameters()->parameters(); - auto printError = [&](SourceLocation const& loc){ - m_errorReporter.typeError( - 228_error, - loc, - "Expected `catch (variant value, uint number) { ... }`."); - }; - if (errArgs.size() != 2) { - printError(clause.location()); - return; - } - if (*errArgs.at(0)->type() != *TypeProvider::variant()) { - printError(errArgs.at(0)->location()); - } - if (*errArgs.at(1)->type() != *TypeProvider::uint(16)) { - printError(errArgs.at(1)->location()); - } + auto printError = [&](SourceLocation const& loc){ + m_errorReporter.typeError( + 228_error, + loc, + "Expected `catch (variant value, uint16 number) { ... }`."); + }; + if (errArgs.size() != 2) { + printError(clause.location()); + return; + } + if (*errArgs.at(0)->type() != *TypeProvider::variant()) { + printError(errArgs.at(0)->location()); + } + if (*errArgs.at(1)->type() != *TypeProvider::uint(16)) { + printError(errArgs.at(1)->location()); + } + } } bool TypeChecker::visit(WhileStatement const& _whileStatement) @@ -1901,7 +1903,11 @@ Type const* TypeChecker::typeCheckTypeConversionAndRetrieveReturnType( bool const isPositionalCall = _functionCall.names().empty(); Type const* resultType = dynamic_cast(*expressionType).actualType(); - if (arguments.size() != 1) + if (arguments.empty() && resultType->category() == Type::Category::TvmCell) + { + // all right + } + else if (arguments.size() != 1) m_errorReporter.typeError( 2558_error, _functionCall.location(), @@ -2154,6 +2160,7 @@ void TypeChecker::typeCheckTvmEncodeArg(Type const* type, Expression const& node case Type::Category::TvmBuilder: case Type::Category::TvmCell: case Type::Category::TvmSlice: + case Type::Category::VarInteger: break; case Type::Category::Optional: { diff --git a/compiler/libsolidity/analysis/ViewPureChecker.cpp b/compiler/libsolidity/analysis/ViewPureChecker.cpp index 7f5a7bde..edf7f4ca 100644 --- a/compiler/libsolidity/analysis/ViewPureChecker.cpp +++ b/compiler/libsolidity/analysis/ViewPureChecker.cpp @@ -318,6 +318,7 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess) member == "add" || member == "getSet" || member == "getAdd" || + member == "getDel" || member == "getReplace") { if (isStateVar) mutability = StateMutability::NonPayable; @@ -365,6 +366,9 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess) {MagicType::Kind::Math, "muldivmod"}, {MagicType::Kind::Math, "muldivr"}, {MagicType::Kind::Math, "sign"}, + {MagicType::Kind::Message, "body"}, + {MagicType::Kind::Message, "forwardFee"}, + {MagicType::Kind::Message, "importFee"}, {MagicType::Kind::Message, "createdAt"}, {MagicType::Kind::Message, "currencies"}, {MagicType::Kind::Message, "data"}, @@ -403,6 +407,7 @@ void ViewPureChecker::endVisit(MemberAccess const& _memberAccess) {MagicType::Kind::TVM, "functionId"}, {MagicType::Kind::TVM, "hash"}, {MagicType::Kind::TVM, "hexdump"}, + {MagicType::Kind::TVM, "initCodeHash"}, {MagicType::Kind::TVM, "insertPubkey"}, {MagicType::Kind::TVM, "log"}, {MagicType::Kind::TVM, "rawConfigParam"}, diff --git a/compiler/libsolidity/ast/AST.cpp b/compiler/libsolidity/ast/AST.cpp index 32dbdf21..1390ff0b 100644 --- a/compiler/libsolidity/ast/AST.cpp +++ b/compiler/libsolidity/ast/AST.cpp @@ -173,7 +173,7 @@ FunctionDefinition const* ContractDefinition::constructor() const bool ContractDefinition::canBeDeployed() const { - // In TON, libraries are also not deployable. + // In TVM, libraries are also not deployable. return !abstract() && !isInterface() && !isLibrary(); } diff --git a/compiler/libsolidity/ast/Types.cpp b/compiler/libsolidity/ast/Types.cpp index dab3d911..d3a93e33 100644 --- a/compiler/libsolidity/ast/Types.cpp +++ b/compiler/libsolidity/ast/Types.cpp @@ -507,7 +507,7 @@ MemberList::MemberMap AddressType::nativeMembers(ASTNode const*) const }; members.emplace_back("unpack", TypeProvider::function( TypePointers{}, - TypePointers{TypeProvider::integer(8, IntegerType::Modifier::Signed), TypeProvider::uint256()}, + TypePointers{TypeProvider::integer(32, IntegerType::Modifier::Signed), TypeProvider::uint256()}, strings{}, strings{string(), string()}, FunctionType::Kind::AddressUnpack, @@ -537,7 +537,7 @@ MemberList::MemberMap AddressType::nativeMembers(ASTNode const*) const TypeProvider::tvmcell(), TypeProvider::extraCurrencyCollection(), TypeProvider::tvmcell(), - }, + }, {}, {"value", "bounce", "flag", "body", "currencies", "stateInit"}, {}, @@ -2097,14 +2097,19 @@ static void appendMapMethods(MemberList::MemberMap& members, Type const* keyType FunctionType::Kind::MappingValues, StateMutability::Pure )); - members.emplace_back("fetch", TypeProvider::function( - TypePointers{keyType}, - TypePointers{TypeProvider::optional(valueType)}, - strings{string{}}, - strings{string{}}, - FunctionType::Kind::MappingFetch, - StateMutability::Pure - )); + for (const std::string name : {"fetch", "getDel"}) { + members.emplace_back( + name.c_str(), + TypeProvider::function( + TypePointers{keyType}, + TypePointers{TypeProvider::optional(valueType)}, + strings{string{}}, + strings{string{}}, + FunctionType::Kind::MappingFetch, + StateMutability::Pure + ) + ); + } members.emplace_back("exists", TypeProvider::function( TypePointers{keyType}, TypePointers{TypeProvider::boolean()}, @@ -3123,6 +3128,8 @@ string FunctionType::richIdentifier() const case Kind::StructUnpack: id += "structunpack"; break; case Kind::OptionalGet: id += "optionalmethod"; break; + case Kind::OptionalGetOr: id += "optionalgetor"; break; + case Kind::OptionalGetOrDefault: id += "optionalgetordefault"; break; case Kind::OptionalHasValue: id += "optionalhasvalue"; break; case Kind::OptionalReset: id += "optionalreset"; break; case Kind::OptionalSet: id += "optionalmethod"; break; @@ -3320,10 +3327,10 @@ string FunctionType::richIdentifier() const case Kind::GoshUnzip: id += "goshunzip"; break; case Kind::GoshZip: id += "goshzip"; break; case Kind::GoshZipDiff: id += "goshzipdiff"; break; - case Kind::GoshApplyBinPatch: id += "goshapplybinpatch"; break; - case Kind::GoshApplyBinPatchQ: id += "goshapplybinpatchq"; break; - case Kind::GoshApplyZipBinPatch: id += "goshapplyzipbinpatch"; break; - case Kind::GoshApplyZipBinPatchQ: id += "goshapplyzipbinpatchq"; break; + case Kind::GoshApplyBinPatch: id += "goshapplybinpatch"; break; + case Kind::GoshApplyBinPatchQ: id += "goshapplybinpatchq"; break; + case Kind::GoshApplyZipBinPatch: id += "goshapplyzipbinpatch"; break; + case Kind::GoshApplyZipBinPatchQ: id += "goshapplyzipbinpatchq"; break; } id += "_" + stateMutabilityToString(m_stateMutability); id += identifierList(m_parameterTypes) + "returns" + identifierList(m_returnParameterTypes); @@ -4429,12 +4436,15 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const {"hasStateInit", TypeProvider::boolean()}, {"gas", TypeProvider::uint256()}, {"value", TypeProvider::uint(128)}, - {"data", TypeProvider::tvmslice()}, + {"data", TypeProvider::tvmcell()}, {"sig", TypeProvider::fixedBytes(4)}, {"currencies", TypeProvider::extraCurrencyCollection()}, {"isExternal", TypeProvider::boolean()}, {"isInternal", TypeProvider::boolean()}, {"isTickTock", TypeProvider::boolean()}, + {"body", TypeProvider::tvmslice()}, + {"forwardFee", TypeProvider::varInteger(16, IntegerType::Modifier::Unsigned)}, + {"importFee", TypeProvider::varInteger(16, IntegerType::Modifier::Unsigned)}, }); case Kind::TVM: { MemberList::MemberMap members = { @@ -4566,12 +4576,12 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const )); members.emplace_back("rawConfigParam", TypeProvider::function( - {TypeProvider::integer(32, IntegerType::Modifier::Signed)}, - {TypeProvider::optional(TypeProvider::tvmcell())}, - {{}}, - {{}}, - FunctionType::Kind::TVMRawConfigParam, - StateMutability::Pure + {TypeProvider::integer(32, IntegerType::Modifier::Signed)}, + {TypeProvider::optional(TypeProvider::tvmcell())}, + {{}}, + {{}}, + FunctionType::Kind::TVMRawConfigParam, + StateMutability::Pure )); members.emplace_back("buildExtMsg", TypeProvider::function( @@ -4921,7 +4931,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const type, StateMutability::Pure, nullptr, FunctionType::Options::withArbitraryParameters() - )}); + )}); } for (auto const&[name, type] : std::vector>{ @@ -4939,7 +4949,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const type, StateMutability::Pure, nullptr, FunctionType::Options::withArbitraryParameters() - )}); + )}); } members.push_back({ "applyPatchQ", @@ -4953,22 +4963,22 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const nullptr, FunctionType::Options::withArbitraryParameters() )}); - for (auto const&[name, type] : std::vector>{ - {"applyZipPatchQ", FunctionType::Kind::GoshApplyZipPatchQ}, - {"applyBinPatchQ", FunctionType::Kind::GoshApplyBinPatchQ}, - {"applyZipBinPatchQ", FunctionType::Kind::GoshApplyZipBinPatchQ}, - }) { - members.push_back({ name.c_str(), - TypeProvider::function( - {TypeProvider::bytesMemory(), TypeProvider::bytesMemory()}, - {TypeProvider::optional(TypeProvider::bytesMemory())}, - {{}, {}}, - {{}}, - type, - StateMutability::Pure, + for (auto const&[name, type] : std::vector>{ + {"applyZipPatchQ", FunctionType::Kind::GoshApplyZipPatchQ}, + {"applyBinPatchQ", FunctionType::Kind::GoshApplyBinPatchQ}, + {"applyZipBinPatchQ", FunctionType::Kind::GoshApplyZipBinPatchQ}, + }) { + members.push_back({ name.c_str(), + TypeProvider::function( + {TypeProvider::bytesMemory(), TypeProvider::bytesMemory()}, + {TypeProvider::optional(TypeProvider::bytesMemory())}, + {{}, {}}, + {{}}, + type, + StateMutability::Pure, nullptr, FunctionType::Options::withArbitraryParameters() - )}); - } + )}); + } members.push_back({ "zip", @@ -5093,55 +5103,87 @@ Type const* InaccessibleDynamicType::decodingType() const MemberList::MemberMap OptionalType::nativeMembers(ASTNode const*) const { - MemberList::MemberMap members; - members.emplace_back("hasValue", TypeProvider::function( - TypePointers{}, - TypePointers{TypeProvider::boolean()}, - strings{}, - strings{string()}, - FunctionType::Kind::OptionalHasValue, - StateMutability::Pure - )); - members.emplace_back("get", TypeProvider::function( - TypePointers{}, - TypePointers{valueType()}, - strings{}, - strings{string()}, - FunctionType::Kind::OptionalGet, - StateMutability::Pure - )); - members.emplace_back("set", TypeProvider::function( - TypePointers{valueType()}, - TypePointers{}, - strings{string()}, - strings{}, - FunctionType::Kind::OptionalSet, - StateMutability::Pure - )); + TypePointers comps; + strings names; if (auto tuple = dynamic_cast(valueType())) { - TypePointers input; - strings names; for (Type const* comp : tuple->components()) { - input.push_back(comp); - names.push_back(""); + comps.emplace_back(comp); + names.emplace_back(""); } - members.emplace_back("set", TypeProvider::function( - input, + } else { + comps.emplace_back(valueType()); + names.emplace_back(""); + } + + + MemberList::MemberMap members = { + { + "hasValue", + TypeProvider::function( + {}, + {TypeProvider::boolean()}, + {}, + {{}}, + FunctionType::Kind::OptionalHasValue, + StateMutability::Pure + ) + }, + { + "get", + TypeProvider::function( + {}, + {valueType()}, + {}, + {{}}, + FunctionType::Kind::OptionalGet, + StateMutability::Pure + ) + }, + { + "getOrDefault", + TypeProvider::function( + {}, + {valueType()}, + {}, + {{}}, + FunctionType::Kind::OptionalGetOrDefault, + StateMutability::Pure + ) + }, + { + "set", + TypeProvider::function( + comps, {}, names, {}, FunctionType::Kind::OptionalSet, StateMutability::Pure - )); - } - members.emplace_back("reset", TypeProvider::function( - TypePointers{}, - TypePointers{}, - strings{}, - strings{}, - FunctionType::Kind::OptionalReset, - StateMutability::Pure - )); + ) + }, + { + "getOr", + TypeProvider::function( + comps, + {valueType()}, + names, + {{}}, + FunctionType::Kind::OptionalGetOr, + StateMutability::Pure + ) + }, + { + "reset", + TypeProvider::function( + {}, + {}, + {}, + {}, + FunctionType::Kind::OptionalReset, + StateMutability::Pure + ) + } + }; return members; } @@ -5906,16 +5948,16 @@ MemberList::MemberMap Variant::nativeMembers(ASTNode const* /*_currentScope*/) c {}, {{}}, FunctionType::Kind::VariantIsUint, - StateMutability::Pure + StateMutability::Pure + )); + members.emplace_back("toUint", TypeProvider::function( + {}, + {TypeProvider::uint256()}, + {}, + {{}}, + FunctionType::Kind::VariantToUint, + StateMutability::Pure )); - members.emplace_back("toUint", TypeProvider::function( - {}, - {TypeProvider::uint256()}, - {}, - {{}}, - FunctionType::Kind::VariantToUint, - StateMutability::Pure - )); return members; } @@ -6003,7 +6045,7 @@ MemberList::MemberMap TvmBuilderType::nativeMembers(const ASTNode *) const ) }, { - "depth", TypeProvider::function( + "depth", TypeProvider::function( TypePointers{}, TypePointers{TypeProvider::uint(16)}, strings{}, @@ -6283,12 +6325,12 @@ TypeResult VarInteger::unaryOperatorResult(Token _operator) const { } TypeResult VarInteger::binaryOperatorResult(Token _operator, Type const* _other) const { - Type const* resultType = m_int.binaryOperatorResult(_operator, _other); + Type const* resultType = m_int.binaryOperatorResult(_operator, _other); if (resultType == nullptr) return nullptr; - if (resultType->isImplicitlyConvertibleTo(*this)) { - resultType = this; - } + if (resultType->isImplicitlyConvertibleTo(*this)) { + resultType = this; + } return resultType; } diff --git a/compiler/libsolidity/ast/Types.h b/compiler/libsolidity/ast/Types.h index 9c3330b4..c1763273 100644 --- a/compiler/libsolidity/ast/Types.h +++ b/compiler/libsolidity/ast/Types.h @@ -950,7 +950,7 @@ class ReferenceType: public CompositeType std::string identifierLocationSuffix() const; // TODO DELETE - // it's useless parameter in TON + // it's useless parameter in TVM bool m_isPointer = true; }; @@ -1532,9 +1532,11 @@ class FunctionType: public Type MappingValues, ///< .values() for a mapping OptionalGet, ///< .get() for optional - OptionalSet, ///< .set() for optional + OptionalGetOr, ///< .getOr() for optional + OptionalGetOrDefault, ///< .getOrDefault() for optional OptionalHasValue, ///< .hasValue() for optional OptionalReset, ///< .reset() for optional + OptionalSet, ///< .set() for optional StringMethod, ///< string methods StringSubstr, ///< string.substr() diff --git a/compiler/libsolidity/codegen/DictOperations.cpp b/compiler/libsolidity/codegen/DictOperations.cpp index e77b653b..b2a72d76 100644 --- a/compiler/libsolidity/codegen/DictOperations.cpp +++ b/compiler/libsolidity/codegen/DictOperations.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -10,10 +10,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ -/** - * @author TON Labs - * @date 2021 - */ #include "DictOperations.hpp" #include "TVMPusher.hpp" @@ -93,12 +89,14 @@ void DictPrevNext::prevNext(bool saveOrigKeyAndNoTuple) { GetFromDict::GetFromDict(StackPusher &pusher, const Type &keyType, const Type &valueType, const GetDictOperation op, - const DataType &dataType) : + std::optional inputValueType) : DictOperation{pusher, keyType, valueType}, op{op}, - dataType{dataType} + inputValueType{inputValueType} { - + bool hasInputValue = isIn(op,GetDictOperation::GetSetFromMapping, GetDictOperation::GetAddFromMapping, + GetDictOperation::GetReplaceFromMapping); + solAssert(hasInputValue == inputValueType.has_value()); } void GetFromDict::getDict() { @@ -112,85 +110,101 @@ void GetFromDict::getDict() { int ret{}; pusher.startOpaque(); switch (op) { - case GetDictOperation::GetSetFromMapping: - case GetDictOperation::GetAddFromMapping: - case GetDictOperation::GetReplaceFromMapping: { - take = 4; - ret = 2; - if (op == GetDictOperation::GetSetFromMapping) - opcode += "SETGET"; - else if (op == GetDictOperation::GetAddFromMapping) - opcode += "ADDGET"; - else if (op == GetDictOperation::GetReplaceFromMapping) - opcode += "REPLACEGET"; - else - solUnimplemented(""); - - bool didUseOpcodeWithRef = false; - switch (dataType) { - case DataType::Builder: - opcode += "B"; - break; - case DataType::Cell: - didUseOpcodeWithRef = true; - opcode += "REF"; - break; - case DataType::Slice: - break; - } - pusher.pushAsym(opcode); - - StackPusher::DecodeType decodeType{}; - if (op == GetDictOperation::GetAddFromMapping) - decodeType = StackPusher::DecodeType::PushNullOrDecodeValue; - else if ( - op == GetDictOperation::GetSetFromMapping || - op == GetDictOperation::GetReplaceFromMapping - ) - decodeType = StackPusher::DecodeType::DecodeValueOrPushNull; - else - solUnimplemented(""); - int ss = pusher.stackSize(); - pusher.recoverKeyAndValueAfterDictOperation(&keyType, &valueType, false, didUseOpcodeWithRef, decodeType); - solAssert(ss == pusher.stackSize(), ""); + case GetDictOperation::GetSetFromMapping: + case GetDictOperation::GetAddFromMapping: + case GetDictOperation::GetReplaceFromMapping: { + take = 4; + ret = 2; + + if (op == GetDictOperation::GetSetFromMapping) + opcode += "SETGET"; + else if (op == GetDictOperation::GetAddFromMapping) + opcode += "ADDGET"; + else if (op == GetDictOperation::GetReplaceFromMapping) + opcode += "REPLACEGET"; + else + solUnimplemented(""); + + bool didUseOpcodeWithRef = false; + switch (inputValueType.value()) { + case DataType::Builder: + opcode += "B"; + break; + case DataType::Cell: + didUseOpcodeWithRef = true; + opcode += "REF"; + break; + case DataType::Slice: break; } - case GetDictOperation::Exist: { - take = 3; - ret = 1; - opcode += "GET"; - pusher.pushAsym(opcode); - checkExist(); - break; + pusher.pushAsym(opcode); + + StackPusher::DecodeType decodeType{}; + if (op == GetDictOperation::GetAddFromMapping) + decodeType = StackPusher::DecodeType::PushNullOrDecodeValue; + else if ( + op == GetDictOperation::GetSetFromMapping || + op == GetDictOperation::GetReplaceFromMapping + ) + decodeType = StackPusher::DecodeType::DecodeValueOrPushNull; + else + solUnimplemented(""); + + int ss = pusher.stackSize(); + pusher.recoverKeyAndValueAfterDictOperation(&keyType, &valueType, false, didUseOpcodeWithRef, decodeType); + + solAssert(ss == pusher.stackSize(), ""); + break; + } + case GetDictOperation::Exist: { + take = 3; + ret = 1; + opcode += "GET"; + pusher.pushAsym(opcode); + checkExist(); + break; + } + case GetDictOperation::Fetch: + case GetDictOperation::GetFromArray: + case GetDictOperation::GetFromMapping: { + take = 3; + ret = 1; + opcode += "GET"; + bool isInRef = pusher.doesDictStoreValueInRef(&keyType, &valueType); + if (isInRef) { + opcode += "REF"; } - case GetDictOperation::Fetch: - case GetDictOperation::GetFromArray: - case GetDictOperation::GetFromMapping: { - take = 3; - ret = 1; - opcode += "GET"; - bool isInRef = pusher.doesDictStoreValueInRef(&keyType, &valueType); - if (isInRef) { - opcode += "REF"; - } - pusher.pushAsym(opcode); - if (op == GetDictOperation::GetFromArray) { - pusher._throw("THROWIFNOT " + toString(TvmConst::RuntimeException::ArrayIndexOutOfRange)); - } - StackPusher::DecodeType decodeType{}; - if (op == GetDictOperation::Fetch) { - decodeType = StackPusher::DecodeType::DecodeValueOrPushNull; - } else if (op == GetDictOperation::GetFromArray) { - decodeType = StackPusher::DecodeType::DecodeValue; - } else if (op == GetDictOperation::GetFromMapping) { - decodeType = StackPusher::DecodeType::DecodeValueOrPushDefault; - } else { - solUnimplemented(""); - } - pusher.recoverKeyAndValueAfterDictOperation(&keyType, &valueType, false, isInRef, decodeType); - break; + pusher.pushAsym(opcode); + if (op == GetDictOperation::GetFromArray) { + pusher._throw("THROWIFNOT " + toString(TvmConst::RuntimeException::ArrayIndexOutOfRange)); + } + StackPusher::DecodeType decodeType{}; + if (op == GetDictOperation::Fetch) { + decodeType = StackPusher::DecodeType::DecodeValueOrPushNull; + } else if (op == GetDictOperation::GetFromArray) { + decodeType = StackPusher::DecodeType::DecodeValue; + } else if (op == GetDictOperation::GetFromMapping) { + decodeType = StackPusher::DecodeType::DecodeValueOrPushDefault; + } else { + solUnimplemented(""); + } + pusher.recoverKeyAndValueAfterDictOperation(&keyType, &valueType, false, isInRef, decodeType); + break; + } + case GetDictOperation::GetDelFromMapping: { + take = 3; + ret = 2; + opcode += "DELGET"; + bool isInRef = pusher.doesDictStoreValueInRef(&keyType, &valueType); + if (isInRef) { + opcode += "REF"; } + pusher.pushAsym(opcode); + StackPusher::DecodeType decodeType = StackPusher::DecodeType::DecodeValueOrPushNull; + pusher.recoverKeyAndValueAfterDictOperation(&keyType, &valueType, false, isInRef, decodeType); + break; + } } pusher.endOpaque(take, ret); diff --git a/compiler/libsolidity/codegen/DictOperations.hpp b/compiler/libsolidity/codegen/DictOperations.hpp index 9106c694..e0568225 100644 --- a/compiler/libsolidity/codegen/DictOperations.hpp +++ b/compiler/libsolidity/codegen/DictOperations.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -10,10 +10,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ -/** - * @author TON Labs - * @date 2021 - */ #pragma once @@ -72,7 +68,7 @@ class DictPrevNext : public DictOperation { class GetFromDict : public DictOperation { public: GetFromDict(StackPusher& pusher, Type const& keyType, Type const& valueType, const GetDictOperation op, - const DataType& dataType); + std::optional inputValueType); void getDict(); @@ -81,7 +77,7 @@ class GetFromDict : public DictOperation { protected: const GetDictOperation op{}; - const DataType dataType{}; + const std::optional inputValueType; }; class DictSet : public DictOperation { diff --git a/compiler/libsolidity/codegen/PeepholeOptimizer.cpp b/compiler/libsolidity/codegen/PeepholeOptimizer.cpp index 8dafa9b1..0e38c0b5 100644 --- a/compiler/libsolidity/codegen/PeepholeOptimizer.cpp +++ b/compiler/libsolidity/codegen/PeepholeOptimizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2021 * Peephole optimizer */ @@ -1104,9 +1102,11 @@ std::optional PrivatePeepholeOptimizer::optimizeAt2(Pointer // LD[I|U] N / LDDICT / LDREF / LD[I|U]X N // DROP - if ((is(cmd1, "LDU", "LDI", "LDREF", "LDDICT", "LDUX", "LDIX")) && + if ((is(cmd1, "LDU", "LDI", "LDREF", "LDDICT", "LDUX", "LDIX", + "LDSLICE", "LDSLICEX")) && isDrop(cmd2) ) { + // TODO add LD[I|U]LE[4|8] int n = isDrop(cmd2).value(); Pointer newOpcode = gen("P" + cmd1GenOp->fullOpcode()); if (n == 1) { @@ -1122,8 +1122,11 @@ std::optional PrivatePeepholeOptimizer::optimizeAt2(Pointer std::optional PrivatePeepholeOptimizer::optimizeAt3(Pointer const& cmd1, Pointer const& cmd2, Pointer const& cmd3, bool m_withUnpackOpaque) { auto isPUSH1 = isPUSH(cmd1); + auto cmd1PushCellOrSlice = to(cmd1.get()); auto isPUSH2 = isPUSH(cmd2); + auto cmd2PushCellOrSlice = to(cmd2.get()); auto cmd3GenOpcode = to(cmd3.get()); + auto cmd3SubProgram = to(cmd3.get()); // NEW // s01 @@ -1274,6 +1277,20 @@ std::optional PrivatePeepholeOptimizer::optimizeAt3(Pointer } } + + if (cmd1PushCellOrSlice && cmd1PushCellOrSlice->type() == PushCellOrSlice::Type::PUSHREF && + cmd2PushCellOrSlice && cmd2PushCellOrSlice->type() == PushCellOrSlice::Type::PUSHREF + ) { + if (cmd3SubProgram) { + std::vector> const& instructions = cmd3SubProgram->block()->instructions(); + if (instructions.size() == 1 && + *instructions.at(0) == *createNode(".inline __concatenateStrings_macro", 2, 1)) { + string hexStr = cmd1PushCellOrSlice->chainBlob() + cmd2PushCellOrSlice->chainBlob(); + return Result{3, makePushCellOrSlice(hexStr, false)}; + } + } + } + // TODO delete, fix in stackOpt // Note: breaking stack // DUP @@ -1287,7 +1304,7 @@ std::optional PrivatePeepholeOptimizer::optimizeAt3(Pointer std::vector> const &cmds = ifRef->trueBody()->instructions(); if (cmds.size() == 1) { if (auto gen = to(cmds.at(0).get())) { - if (isIn(gen->fullOpcode(), "CALL $c7_to_c4$", "CALL $upd_only_time_in_c4$")) { + if (isIn(gen->fullOpcode(), ".inline __c7_to_c4", ".inline __upd_only_time_in_c4")) { return Result{2, cmd2}; } } @@ -1452,7 +1469,7 @@ std::optional PrivatePeepholeOptimizer::optimizeAt5(Pointer std::optional slice = StrUtils::unitBitStringToHex(bitStr, ""); if (slice.has_value()) { return Result{5, - genPushSlice(*slice), + genPushSlice(*slice), gen("NEWC"), gen("STSLICE")}; } @@ -2005,7 +2022,7 @@ std::optional PrivatePeepholeOptimizer::squashPush(const int idx1) const int n = 0; while (true) { auto cmdI = to(get(i).get()); - if (cmdI && cmd1PushCellOrSlice->equal(*cmdI)) + if (cmdI && *cmd1PushCellOrSlice == *cmdI) { n++; i = nextCommandLine(i); diff --git a/compiler/libsolidity/codegen/PeepholeOptimizer.hpp b/compiler/libsolidity/codegen/PeepholeOptimizer.hpp index 8d1c3757..da5c4884 100644 --- a/compiler/libsolidity/codegen/PeepholeOptimizer.hpp +++ b/compiler/libsolidity/codegen/PeepholeOptimizer.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2021 * Peephole optimizer */ diff --git a/compiler/libsolidity/codegen/SizeOptimizer.cpp b/compiler/libsolidity/codegen/SizeOptimizer.cpp index 8c239656..9a416f64 100644 --- a/compiler/libsolidity/codegen/SizeOptimizer.cpp +++ b/compiler/libsolidity/codegen/SizeOptimizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2022-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2022 * Size optimizer */ diff --git a/compiler/libsolidity/codegen/SizeOptimizer.hpp b/compiler/libsolidity/codegen/SizeOptimizer.hpp index e150be86..a54c2cc9 100644 --- a/compiler/libsolidity/codegen/SizeOptimizer.hpp +++ b/compiler/libsolidity/codegen/SizeOptimizer.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2022 * Size optimizer */ diff --git a/compiler/libsolidity/codegen/StackOpcodeSquasher.cpp b/compiler/libsolidity/codegen/StackOpcodeSquasher.cpp index 0442db5b..6c1a45b4 100644 --- a/compiler/libsolidity/codegen/StackOpcodeSquasher.cpp +++ b/compiler/libsolidity/codegen/StackOpcodeSquasher.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -10,11 +10,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ -/** - * @author TON Labs - * @date 2021 - * - */ #include #include diff --git a/compiler/libsolidity/codegen/StackOpcodeSquasher.hpp b/compiler/libsolidity/codegen/StackOpcodeSquasher.hpp index cf7c7d5c..a14ee027 100644 --- a/compiler/libsolidity/codegen/StackOpcodeSquasher.hpp +++ b/compiler/libsolidity/codegen/StackOpcodeSquasher.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -10,11 +10,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ -/** - * @author TON Labs - * @date 2021 - * - */ #pragma once diff --git a/compiler/libsolidity/codegen/StackOptimizer.cpp b/compiler/libsolidity/codegen/StackOptimizer.cpp index 409bc203..686248ae 100644 --- a/compiler/libsolidity/codegen/StackOptimizer.cpp +++ b/compiler/libsolidity/codegen/StackOptimizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2021 * Stack optimizer */ diff --git a/compiler/libsolidity/codegen/StackOptimizer.hpp b/compiler/libsolidity/codegen/StackOptimizer.hpp index 1313cf4f..4ccf7fbb 100644 --- a/compiler/libsolidity/codegen/StackOptimizer.hpp +++ b/compiler/libsolidity/codegen/StackOptimizer.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2021 * Stack optimizer */ diff --git a/compiler/libsolidity/codegen/TVM.cpp b/compiler/libsolidity/codegen/TVM.cpp index fe183377..7b98b19a 100644 --- a/compiler/libsolidity/codegen/TVM.cpp +++ b/compiler/libsolidity/codegen/TVM.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * TVM codegen driver */ diff --git a/compiler/libsolidity/codegen/TVM.hpp b/compiler/libsolidity/codegen/TVM.hpp index 45441e73..3915081c 100644 --- a/compiler/libsolidity/codegen/TVM.hpp +++ b/compiler/libsolidity/codegen/TVM.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * TVM codegen driver */ diff --git a/compiler/libsolidity/codegen/TVMABI.cpp b/compiler/libsolidity/codegen/TVMABI.cpp index bb684115..095e07d6 100644 --- a/compiler/libsolidity/codegen/TVMABI.cpp +++ b/compiler/libsolidity/codegen/TVMABI.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -10,10 +10,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ -/** - * @author TON Labs - * @date 2019 - */ #include diff --git a/compiler/libsolidity/codegen/TVMABI.hpp b/compiler/libsolidity/codegen/TVMABI.hpp index 62283ff9..5e3513ae 100644 --- a/compiler/libsolidity/codegen/TVMABI.hpp +++ b/compiler/libsolidity/codegen/TVMABI.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,9 +11,7 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 - * ABI generator and parser for TON + * ABI generator and parser */ #pragma once diff --git a/compiler/libsolidity/codegen/TVMAnalyzer.cpp b/compiler/libsolidity/codegen/TVMAnalyzer.cpp index 6ca796f2..f61dbcde 100644 --- a/compiler/libsolidity/codegen/TVMAnalyzer.cpp +++ b/compiler/libsolidity/codegen/TVMAnalyzer.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * AST analyzer specified to search for TVM specific issues. */ diff --git a/compiler/libsolidity/codegen/TVMAnalyzer.hpp b/compiler/libsolidity/codegen/TVMAnalyzer.hpp index 9314a408..cb80ee93 100644 --- a/compiler/libsolidity/codegen/TVMAnalyzer.hpp +++ b/compiler/libsolidity/codegen/TVMAnalyzer.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * AST analyzer specified to search for TVM specific issues. */ diff --git a/compiler/libsolidity/codegen/TVMCommons.cpp b/compiler/libsolidity/codegen/TVMCommons.cpp index d5701f57..165fb2d3 100644 --- a/compiler/libsolidity/codegen/TVMCommons.cpp +++ b/compiler/libsolidity/codegen/TVMCommons.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * Common TVM codegen routines, in particular, types, data structures, scope, stack manipulations, etc. */ @@ -387,7 +385,8 @@ DictValueType toDictValueType(const Type::Category& category) { } } -std::string stringToBytes(const std::string& str) { +// e.g.: hello -> 68656c6c6f +std::string stringToHex(const std::string& str) { std::string slice; for (char index : str) { std::stringstream ss; @@ -589,8 +588,10 @@ std::optional StrUtils::unitSlices(const std::string& sliceA, const std::optional StrUtils::unitBitStringToHex(const std::string& bitStringA, const std::string& bitStringB) { const std::string& bitString = bitStringA + bitStringB; - if (bitString.length() > TvmConst::CellBitLength) + if (bitString.length() > TvmConst::CellBitLength) { + // TODO implement return std::nullopt; + } return {"x" + StrUtils::binaryStringToSlice(bitString)}; } diff --git a/compiler/libsolidity/codegen/TVMCommons.hpp b/compiler/libsolidity/codegen/TVMCommons.hpp index e0de43e9..c8ebca45 100644 --- a/compiler/libsolidity/codegen/TVMCommons.hpp +++ b/compiler/libsolidity/codegen/TVMCommons.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * Common TVM codegen routines, in particular, types, data structures, scope, stack manipulations, etc. */ @@ -352,6 +350,7 @@ enum class GetDictOperation { GetFromMapping, GetSetFromMapping, GetAddFromMapping, + GetDelFromMapping, GetReplaceFromMapping, GetFromArray, Fetch, @@ -366,7 +365,7 @@ struct LValueInfo { }; DictValueType toDictValueType(const Type::Category& category); -std::string stringToBytes(const std::string& str); +std::string stringToHex(const std::string& str); std::set getAllBaseFunctions(CallableDeclaration const* f); bool isLoc(Pointer const& node); std::vector split(const std::string &s, char sep = '\n'); diff --git a/compiler/libsolidity/codegen/TVMConstants.hpp b/compiler/libsolidity/codegen/TVMConstants.hpp index acefe532..f6fe0c13 100644 --- a/compiler/libsolidity/codegen/TVMConstants.hpp +++ b/compiler/libsolidity/codegen/TVMConstants.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * TVM constants and runtime error codes */ @@ -75,7 +73,6 @@ namespace TvmConst { const int ArrayIndexOutOfRange = 50; const int ConstructorIsCalledTwice = 51; const int ReplayProtection = 52; - const int AddressUnpackException = 53; const int PopFromEmptyArray = 54; const int InsertPubkeyException = 55; const int MessageIsExpired = 57; diff --git a/compiler/libsolidity/codegen/TVMContractCompiler.cpp b/compiler/libsolidity/codegen/TVMContractCompiler.cpp index 9229666d..98bff562 100644 --- a/compiler/libsolidity/codegen/TVMContractCompiler.cpp +++ b/compiler/libsolidity/codegen/TVMContractCompiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * AST to TVM bytecode contract compiler */ @@ -167,7 +165,7 @@ void TVMConstructorCompiler::c4ToC7WithMemoryInitAndConstructorProtection() { m_pusher.fixStack(-1); // fix stack m_pusher.startContinuation(); - m_pusher.pushCall(0, 0, "c4_to_c7_with_init_storage"); + m_pusher.pushMacro(0, 0, "c4_to_c7_with_init_storage"); m_pusher.endContinuationFromRef(); m_pusher._if(); @@ -295,26 +293,26 @@ TVMContractCompiler::generateContractCode( if (!ctx.isBaseFunction(_function)) functions.push_back(TVMFunctionCompiler::generateOnCodeUpgrade(ctx, _function)); } else { - if (_function->isPublic()) { - bool isBaseMethod = _function != getContractFunctions(contract, _function->name()).back(); - if (!isBaseMethod) { - functions.push_back(TVMFunctionCompiler::generatePublicFunction(ctx, _function)); - - StackPusher pusher{&ctx}; - ChainDataEncoder encoder{&pusher}; // TODO delete pusher - uint32_t functionId = encoder.calculateFunctionIDWithReason(_function, - ReasonOfOutboundMessage::RemoteCallInternal); - ctx.addPublicFunction(functionId, _function->name()); - } - } std::string functionName = ctx.getFunctionInternalName(_function); - if (_function->visibility() <= Visibility::Public) { - functions.push_back(TVMFunctionCompiler::generatePrivateFunction(ctx, functionName, _function)); - } - { - const std::string macroName = functionName + "_macro"; - functions.push_back(TVMFunctionCompiler::generateMacro(ctx, _function, macroName)); + if (!ctx.isStdlib()) { + if (_function->isPublic()) { + bool isBaseMethod = _function != getContractFunctions(contract, _function->name()).back(); + if (!isBaseMethod) { + functions.push_back(TVMFunctionCompiler::generatePublicFunction(ctx, _function)); + + StackPusher pusher{&ctx}; + ChainDataEncoder encoder{&pusher}; // TODO delete pusher + uint32_t functionId = encoder.calculateFunctionIDWithReason(_function, + ReasonOfOutboundMessage::RemoteCallInternal); + ctx.addPublicFunction(functionId, _function->name()); + } + } + if (_function->visibility() <= Visibility::Public) { + functions.push_back(TVMFunctionCompiler::generatePrivateFunction(ctx, functionName, _function)); + } } + const std::string macroName = functionName + "_macro"; + functions.push_back(TVMFunctionCompiler::generateMacro(ctx, _function, macroName)); } ctx.setCurrentFunction(nullptr); diff --git a/compiler/libsolidity/codegen/TVMContractCompiler.hpp b/compiler/libsolidity/codegen/TVMContractCompiler.hpp index e1565c13..85bd81c1 100644 --- a/compiler/libsolidity/codegen/TVMContractCompiler.hpp +++ b/compiler/libsolidity/codegen/TVMContractCompiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * AST to TVM bytecode contract compiler */ diff --git a/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp b/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp index 969925ff..f1f21880 100644 --- a/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp +++ b/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * Expression compiler for TVM */ @@ -675,6 +673,16 @@ void TVMExpressionCompiler::visitMsgMagic(MemberAccess const &_node) { "ADDCONST -2", "PICK", }, 0, 1, true)); + } else if (_node.memberName() == "data") { // msg.data + m_pusher.push(createNode(std::vector{ + "DEPTH", + "ADDCONST -3", + "PICK", + }, 0, 1, true)); + } else if (_node.memberName() == "forwardFee") { // msg.forwardFee + m_pusher.pushMacro(0, 1, "__forwardFee_macro"); + } else if (_node.memberName() == "importFee") { // msg.importFee + m_pusher.pushMacro(0, 1, "__importFee_macro"); } else if (isIn(_node.memberName(), "isInternal", "isExternal", "isTickTock")) { m_pusher.push(createNode(std::vector{ "DEPTH", @@ -781,7 +789,7 @@ void TVMExpressionCompiler::visitMsgMagic(MemberAccess const &_node) { "IFELSE" }, 0, 1, true)); m_pusher.pushRefContAndCallX(0, 1, true); - } else if (_node.memberName() == "data") { + } else if (_node.memberName() == "body") { m_pusher.push(createNode(std::vector{ "DEPTH", "ADDCONST -4", diff --git a/compiler/libsolidity/codegen/TVMExpressionCompiler.hpp b/compiler/libsolidity/codegen/TVMExpressionCompiler.hpp index 29383b4e..f0f6f6a1 100644 --- a/compiler/libsolidity/codegen/TVMExpressionCompiler.hpp +++ b/compiler/libsolidity/codegen/TVMExpressionCompiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * Expression compiler for TVM */ diff --git a/compiler/libsolidity/codegen/TVMFunctionCall.cpp b/compiler/libsolidity/codegen/TVMFunctionCall.cpp index bd769541..2f6779fe 100644 --- a/compiler/libsolidity/codegen/TVMFunctionCall.cpp +++ b/compiler/libsolidity/codegen/TVMFunctionCall.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * Function call compiler for TVM */ @@ -66,6 +64,17 @@ void FunctionCallCompiler::compile() { cast_error(m_functionCall, "Unsupported function call"); }; + if (m_funcType) { + switch (m_funcType->kind()) { + case FunctionType::Kind::GasLeft: { + m_pusher << "GASREMAINING"; + return; + } + default: + break; + } + } + if (checkRemoteMethodCall(m_functionCall) || (_memberAccess != nullptr && libraryCall(*_memberAccess)) || checkForMappingOrCurrenciesMethods() || @@ -81,7 +90,11 @@ void FunctionCallCompiler::compile() { } else if (*m_functionCall.annotation().kind == FunctionCallKind::StructConstructorCall) { structConstructorCall(); } else if (*m_functionCall.annotation().kind == FunctionCallKind::TypeConversion) { - typeConversion(); + if (m_arguments.empty()) { + createObject(); + } else { + typeConversion(); + } } else { if (_memberAccess != nullptr) { auto category = getType(&_memberAccess->expression())->category(); @@ -172,7 +185,8 @@ bool FunctionCallCompiler::checkForMappingOrCurrenciesMethods() { const ASTString &memberName = ma->memberName(); if (isIn(memberName, "delMin", "delMax")) { mappingDelMinOrMax(memberName == std::string{"delMin"}); - } else if (isIn(memberName, "at", "fetch", "exists", "replace", "add", "getSet", "getAdd", "getReplace")) { + } else if (isIn(memberName, "at", "fetch", "exists", "replace", "add", + "getSet", "getAdd", "getDel", "getReplace")) { mappingGetSet(); } else if (isIn(memberName, "min", "max")) { mappingMinMaxMethod(memberName == std::string{"min"}); @@ -221,6 +235,21 @@ void FunctionCallCompiler::mappingGetSet() { m_pusher.prepareKeyForDictOperations(keyType, false); acceptExpr(&memberAccess->expression()); // index dict m_pusher.getDict(*keyType, *valueType, GetDictOperation::Exist); + } else if (isIn(memberName, "getDel")) { + const int stackSize = m_pusher.stackSize(); + + auto ma = to(&m_functionCall.expression()); + const LValueInfo lValueInfo = m_exprCompiler.expandLValue(&ma->expression(), true); + + pushArgAndConvert(0); // lValue... map key + m_pusher.prepareKeyForDictOperations(keyType, false); + m_pusher.blockSwap(1, 1); // lValue... key map + + m_pusher.getDict(*keyType, *valueType, GetDictOperation::GetDelFromMapping); // lValue... map' value + + const int cntOfValuesOnStack = m_pusher.stackSize() - stackSize; + m_pusher.blockSwap(cntOfValuesOnStack - 1, 1); // value lValue... map' + m_exprCompiler.collectLValue(lValueInfo, true, false); // value } else if (isIn(memberName, "replace", "add", "getSet", "getAdd", "getReplace")) { const int stackSize = m_pusher.stackSize(); auto ma = to(&m_functionCall.expression()); @@ -247,12 +276,14 @@ void FunctionCallCompiler::mappingGetSet() { op = GetDictOperation::GetSetFromMapping; } else if (memberName == "getAdd") { op = GetDictOperation::GetAddFromMapping; + } else if (memberName == "getAdd") { + op = GetDictOperation::GetDelFromMapping; } else if (memberName == "getReplace") { op = GetDictOperation::GetReplaceFromMapping; } else { solUnimplemented(""); } - m_pusher.getDict(*keyType, *valueType, op, dataType); + m_pusher.getAndSetDict(*keyType, *valueType, op, dataType); // mapLValue... map optValue } const int cntOfValuesOnStack = m_pusher.stackSize() - stackSize; // mapLValue... map optValue @@ -2120,26 +2151,55 @@ bool FunctionCallCompiler::checkForOptionalMethods(MemberAccess const &_node) { if (!optional) return false; - if (_node.memberName() == "hasValue") { + auto retTuple = to(m_retType); + int retQty = retTuple ? retTuple->components().size() : 1; + + ASTString const &memberName = _node.memberName(); + if (memberName == "hasValue") { acceptExpr(&_node.expression()); m_pusher << "ISNULL"; m_pusher << "NOT"; - return true; - } - - if (_node.memberName() == "get") { + } else if (memberName == "get") { acceptExpr(&_node.expression()); m_pusher.pushS(0); m_pusher.checkOptionalValue(); - if (auto tt = to(m_retType)) { - m_pusher.untuple(tt->components().size()); + if (retTuple) { + m_pusher.untuple(retTuple->components().size()); } else if (optValueAsTuple(m_retType)) { m_pusher.untuple(1); } - return true; - } + } else if (isIn(memberName, "getOr", "getOrDefault")) { + int startSize = m_pusher.stackSize(); + acceptExpr(&_node.expression()); + + m_pusher.startOpaque(); + m_pusher.pushS(0); + m_pusher << "ISNULL"; + + m_pusher.startContinuation(); + m_pusher.drop(); + if (memberName == "getOr") { + pushArgs(); + } else if (memberName == "getOrDefault") { + m_pusher.pushDefaultValue(optional->valueType()); + } else { + solUnimplemented(""); + } + m_pusher.endContinuation(); + + m_pusher.startContinuation(); + if (retTuple) { + m_pusher.untuple(retTuple->components().size()); + } else if (optValueAsTuple(m_retType)) { + m_pusher.untuple(1); + } + m_pusher.endContinuation(); + + m_pusher.ifElse(); + m_pusher.endOpaque(1, retQty); - if (_node.memberName() == "set") { + solAssert(startSize + retQty == m_pusher.stackSize(), ""); + } else if (memberName == "set") { Type const* rightType{}; if (m_arguments.size() >= 2) { vector types; @@ -2154,17 +2214,14 @@ bool FunctionCallCompiler::checkForOptionalMethods(MemberAccess const &_node) { pushArgs(false, false); m_pusher.hardConvert(getType(&_node.expression()), rightType); m_exprCompiler.collectLValue(lValueInfo, true, false); - return true; - } - - if (_node.memberName() == "reset") { + } else if (memberName == "reset") { const LValueInfo lValueInfo = m_exprCompiler.expandLValue(&_node.expression(), false); m_pusher.pushDefaultValue(optional); m_exprCompiler.collectLValue(lValueInfo, true, false); - return true; + } else { + return false; } - - return false; + return true; } void FunctionCallCompiler::cellMethods(MemberAccess const &_node) { @@ -2776,7 +2833,7 @@ bool FunctionCallCompiler::checkForTvmFunction(const MemberAccess &_node) { m_pusher.fixStack(-1); // fix stack m_pusher.startContinuation(); - m_pusher.pushCall(0, 0, "c7_to_c4"); + m_pusher.pushMacro(0, 0, "c7_to_c4"); m_pusher.endContinuationFromRef(); m_pusher.ifNot(); @@ -3076,6 +3133,18 @@ bool FunctionCallCompiler::checkAddressThis() { return false; } +void FunctionCallCompiler::createObject() { + Type const* resultType = m_functionCall.annotation().type; + switch (resultType->category()) { + case Type::Category::TvmCell: { + m_pusher.pushDefaultValue(resultType); + break; + } + default: + solUnimplemented(""); + } +} + void FunctionCallCompiler::typeConversion() { Type::Category argCategory = m_arguments[0]->annotation().type->category(); Type const* argType = m_arguments[0]->annotation().type; @@ -3711,8 +3780,8 @@ void FunctionCallCompiler::checkStateInit() { // code:(Maybe ^Cell) data:(Maybe ^Cell) // library:(HashmapE 256 SimpleLib) - m_pusher << "LDOPTREF"; - m_pusher << "LDOPTREF"; + m_pusher << "LDDICT"; + m_pusher << "LDDICT"; m_pusher << "LDDICT"; m_pusher << "ENDS"; m_pusher.drop(3); @@ -3842,8 +3911,8 @@ void FunctionCallCompiler::buildStateInit(std::map(logstr); if (literal && literal->value().size() < 16) { - std::string hexStr = stringToBytes(literal->value()); + std::string hexStr = stringToHex(literal->value()); m_pusher << "PRINTSTR x" + hexStr; } else { pushArgs(); diff --git a/compiler/libsolidity/codegen/TVMFunctionCall.hpp b/compiler/libsolidity/codegen/TVMFunctionCall.hpp index c29fd05c..e8373776 100644 --- a/compiler/libsolidity/codegen/TVMFunctionCall.hpp +++ b/compiler/libsolidity/codegen/TVMFunctionCall.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * Function call compiler for TVM */ @@ -71,6 +69,7 @@ class FunctionCallCompiler { void mathFunction(MemberAccess const& _node); bool checkBaseContractCall(MemberAccess const& _node, Type::Category category); bool checkAddressThis(); + void createObject(); void typeConversion(); bool checkLocalFunctionOrLibCall(const Identifier* identifier); bool checkSolidityUnits(); diff --git a/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp b/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp index 27ea4b12..2883f3b5 100644 --- a/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp +++ b/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * AST to TVM bytecode contract compiler */ @@ -211,7 +209,7 @@ TVMFunctionCompiler::generateC4ToC7WithInitMemory(TVMCompilerContext& ctx) { pusher << "GTINT 1"; pusher.startContinuation(); - pusher.pushCall(0, 0, "c4_to_c7"); + pusher.pushMacro(0, 0, "c4_to_c7"); pusher.endContinuationFromRef(); pusher.startContinuation(); @@ -495,7 +493,7 @@ Pointer TVMFunctionCompiler::generatePrivateFunction(TVMCompilerContext& ctx, const std::string& name, FunctionDefinition const* funDef) { StackPusher pusher{&ctx}; const std::string macroName = name + "_macro"; - pusher.pushCall(0, 0, macroName); + pusher.pushMacro(0, 0, macroName); return createNode(0, 0, name, Function::FunctionType::PrivateFunction, pusher.getBlock(), funDef); } @@ -507,7 +505,7 @@ Pointer TVMFunctionCompiler::generateLibraryFunction( StackPusher pusher{&ctx}; TVMFunctionCompiler funCompiler{pusher, 0, function, true, true, 0}; const std::string macroName = name + "_macro"; - pusher.pushCall(0, 0, macroName); + pusher.pushMacro(0, 0, macroName); return createNode(0, 0, name, Function::FunctionType::PrivateFunctionWithObj, pusher.getBlock()); } @@ -929,8 +927,12 @@ bool TVMFunctionCompiler::visit(TryStatement const& _tryState) { // try body m_pusher.startContinuation(); - for (ASTPointer const& variable : _tryState.clause().parameters()->parameters()) { - m_pusher.getStack().add(variable.get(), true); + if (_tryState.clause().parameters()) { + for (ASTPointer const& variable : _tryState.clause().parameters()->parameters()) { + m_pusher.getStack().add(variable.get(), true); + } + } else { + m_pusher.fixStack(+2); } _tryState.clause().block().accept(*this); m_pusher.drop(m_pusher.stackSize() - startStackSize); @@ -1732,7 +1734,7 @@ void TVMFunctionCompiler::defaultReplayProtection() { // msgSlice m_pusher << "LDU 64 ; timestamp msgSlice"; m_pusher.exchange(1); - m_pusher.pushCall(1, 0, "replay_protection_macro"); + m_pusher.pushMacro(1, 0, "replay_protection_macro"); } void TVMFunctionCompiler::expire() { @@ -1749,7 +1751,7 @@ void TVMFunctionCompiler::callPublicFunctionOrFallback() { if (m_pusher.ctx().isFallBackGenerated()) { m_pusher.drop(2); m_pusher.startContinuation(); - m_pusher.pushCall(0, 0, "fallback_macro"); + m_pusher.pushMacro(0, 0, "fallback_macro"); m_pusher.pushRefContAndCallX(0, 0, false); } else { m_pusher._throw("THROW " + toString(TvmConst::RuntimeException::NoFallback)); @@ -1810,7 +1812,7 @@ TVMFunctionCompiler::generateMainInternal(TVMCompilerContext& ctx, ContractDefin pusher.pushS(1); pusher << "LDSLICE 32"; pusher.dropUnder(1, 1); - pusher.pushCall(0, 0, "on_bounce_macro"); + pusher.pushMacro(0, 0, "on_bounce_macro"); pusher.endContinuationFromRef(); pusher.ifJmp(); } else { @@ -1879,7 +1881,7 @@ void TVMFunctionCompiler::pushC4ToC7IfNeed() { m_pusher.was_c4_to_c7_called(); m_pusher.fixStack(-1); // fix stack m_pusher.startContinuation(); - m_pusher.pushCall(0, 0, "c4_to_c7"); + m_pusher.pushMacro(0, 0, "c4_to_c7"); m_pusher.endContinuationFromRef(); m_pusher._if(); } @@ -1898,13 +1900,13 @@ void TVMFunctionCompiler::updC4IfItNeeds() { ) { m_pusher.pushS(0); m_pusher.startContinuation(); - m_pusher.pushCall(0, 0, "upd_only_time_in_c4"); + m_pusher.pushMacro(0, 0, "upd_only_time_in_c4"); m_pusher.endContinuationFromRef(); m_pusher._if(); } else { m_pusher.pushS(0); m_pusher.startContinuation(); - m_pusher.pushCall(0, 0, "c7_to_c4"); + m_pusher.pushMacro(0, 0, "c7_to_c4"); m_pusher.endContinuationFromRef(); m_pusher._if(); } @@ -1954,7 +1956,7 @@ void TVMFunctionCompiler::pushReceiveOrFallback() { m_pusher.endContinuation(); m_pusher.ifNot(); m_pusher.startContinuation(); - m_pusher.pushCall(0, 0, "receive_macro"); + m_pusher.pushMacro(0, 0, "receive_macro"); m_pusher.endContinuationFromRef(); m_pusher.ifJmp(); } else { @@ -1993,7 +1995,7 @@ void TVMFunctionCompiler::buildPublicFunctionSelector( m_pusher << "EQUAL"; m_pusher.fixStack(-1); // fix stack m_pusher.startContinuation(); - m_pusher.pushCall(0, 0, name); + m_pusher.pushMacro(0, 0, name); m_pusher.endContinuationFromRef(); m_pusher.ifJmp(); }; diff --git a/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp b/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp index 4a491218..c8b81fd5 100644 --- a/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp +++ b/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * AST to TVM bytecode contract compiler */ diff --git a/compiler/libsolidity/codegen/TVMInlineFunctionChecker.cpp b/compiler/libsolidity/codegen/TVMInlineFunctionChecker.cpp index 2e007678..1da6cebe 100644 --- a/compiler/libsolidity/codegen/TVMInlineFunctionChecker.cpp +++ b/compiler/libsolidity/codegen/TVMInlineFunctionChecker.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -10,10 +10,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ -/** - * @author TON Labs - * @date 2020-01-29 - */ #include diff --git a/compiler/libsolidity/codegen/TVMInlineFunctionChecker.hpp b/compiler/libsolidity/codegen/TVMInlineFunctionChecker.hpp index 2126a4c1..6f3c9e29 100644 --- a/compiler/libsolidity/codegen/TVMInlineFunctionChecker.hpp +++ b/compiler/libsolidity/codegen/TVMInlineFunctionChecker.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -10,10 +10,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ -/** - * @author TON Labs - * @date 2020-01-29 - */ #pragma once diff --git a/compiler/libsolidity/codegen/TVMPusher.cpp b/compiler/libsolidity/codegen/TVMPusher.cpp index edaca1be..ae49aef5 100644 --- a/compiler/libsolidity/codegen/TVMPusher.cpp +++ b/compiler/libsolidity/codegen/TVMPusher.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -10,10 +10,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ -/** - * @author TON Labs - * @date 2019 - */ #include @@ -45,7 +41,7 @@ void StackPusher::pushLoc(const std::string& file, int line) { } void StackPusher::pushString(const std::string& _str, bool toSlice) { - std::string hexStr = stringToBytes(_str); // 2 * len(_str) == len(hexStr). One symbol to 2 hex digits + std::string hexStr = stringToHex(_str); // 2 * len(_str) == len(hexStr). One symbol to 2 hex digits solAssert(hexStr.length() % 2 == 0, ""); if (4 * hexStr.length() <= TvmConst::MaxPushSliceBitLength && toSlice) { pushSlice("x" + hexStr); @@ -53,24 +49,7 @@ void StackPusher::pushString(const std::string& _str, bool toSlice) { } const int saveStackSize = stackSize(); - const int length = hexStr.size(); - const int symbolQty = ((TvmConst::CellBitLength / 8) * 8) / 4; // one symbol in string == 8 bit. Letter can't be divided by 2 cells - PushCellOrSlice::Type type = toSlice ? PushCellOrSlice::Type::PUSHREFSLICE : PushCellOrSlice::Type::PUSHREF; - std::vector> data; - int start = 0; - do { - std::string slice = hexStr.substr(start, std::min(symbolQty, length - start)); - data.emplace_back(type, "x" + slice); - start += symbolQty; - type = PushCellOrSlice::Type::CELL; - } while (start < length); - - Pointer cell; - for (const auto&[t, d] : data | boost::adaptors::reversed) { - cell = createNode(t, d, cell); - } - solAssert(cell != nullptr, ""); - m_instructions.back().emplace_back(cell); + m_instructions.back().emplace_back(makePushCellOrSlice(hexStr, toSlice)); change(0, 1); ensureSize(saveStackSize + 1, ""); @@ -91,8 +70,7 @@ Pointer StackPusher::generateC7ToT4Macro(bool forAwait) { pushC7(); *this << "FALSE"; setIndexQ(stateVarQty + TvmConst::C7::FirstIndexForVariables); - untuple(stateVarQty + TvmConst::C7::FirstIndexForVariables + 1); - drop(); + unpackFirst(stateVarQty + TvmConst::C7::FirstIndexForVariables); reverse(stateVarQty + TvmConst::C7::FirstIndexForVariables, 0); drop(TvmConst::C7::FirstIndexForVariables); solAssert(saveStack + stateVarQty == stackSize(), ""); @@ -653,14 +631,18 @@ StackPusher::makeAsym(const string& cmd) { asymOpcodes.insert("DICT" + type + op + suf); } } + for (std::string op : {"SETGET", "ADDGET", "REPLACEGET"}) { - for (std::string suf : {"", "REF", "B"}) { + for (std::string suf : {"", "REF", "B"}) asymOpcodes.insert("DICT" + type + op + suf); - } } - for (std::string suf : {"", "REF", "PREV", "PREVEQ", "NEXT", "NEXTEQ"}) { + + for (std::string op : {"DELGET"}) + for (std::string suf : {"", "REF"}) + asymOpcodes.insert("DICT" + type + op + suf); + + for (std::string suf : {"", "REF", "PREV", "PREVEQ", "NEXT", "NEXTEQ"}) asymOpcodes.insert("DICT" + type + "GET" + suf); - } } for (std::string preload : {"", "P"}) @@ -947,16 +929,13 @@ TVMStack &StackPusher::getStack() { } void StackPusher::untuple(int n) { - solAssert(0 <= n, ""); - if (n <= 15) { - *this << "UNTUPLE " + toString(n); - } else { - solAssert(n <= 255, ""); - pushInt(n); - auto b = createNode("UNTUPLEVAR", 2, n); - m_instructions.back().push_back(b); - change(2, n); - } + solAssert(0 <= n && n <= 255, ""); + *this << "UNTUPLE " + toString(n); +} + +void StackPusher::unpackFirst(int n) { + solAssert(0 <= n && n <= 255, ""); + *this << "UNPACKFIRST " + toString(n); } void StackPusher::indexWithExcep(int index) { @@ -1005,9 +984,22 @@ void StackPusher::tuple(int qty) { } void StackPusher::resetAllStateVars() { - for (VariableDeclaration const *variable: ctx().notConstantStateVariables()) { - pushDefaultValue(variable->type()); - setGlob(variable); + std::vector const stateVariables = ctx().notConstantStateVariables(); + if (m_ctx->tooMuchStateVariables()) { + pushC7(); + *this << "FALSE"; + setIndexQ(TvmConst::C7::FirstIndexForVariables); + unpackFirst(TvmConst::C7::FirstIndexForVariables); + for (VariableDeclaration const *variable: stateVariables) + pushDefaultValue(variable->type()); + const int stateVarQty = stateVariables.size(); + tuple(TvmConst::C7::FirstIndexForVariables + stateVarQty); + popC7(); + } else { + for (VariableDeclaration const *variable: stateVariables) + pushDefaultValue(variable->type()); + for (VariableDeclaration const *variable: stateVariables | boost::adaptors::reversed) + setGlob(variable); } } @@ -1108,64 +1100,70 @@ bool StackPusher::fastLoad(const Type* type) { // slice switch (type->category()) { case Type::Category::Optional: { - startOpaque(); - const int saveStakeSize = stackSize(); - auto opt = to(type); + auto optType = to(type); + auto optValueType = optType->valueType(); + auto array = to(optType->valueType()); + if (optValueType->category() == Type::Category::TvmCell || (array && array->isByteArrayOrString())) { + *this << "LDDICT"; + } else { + startOpaque(); + const int saveStakeSize = stackSize(); + auto opt = to(type); - auto f = [&](bool reverseOrder) { - if (isSmallOptional(opt)) { - load(opt->valueType(), reverseOrder); - } else { - *this << "LDREFRTOS"; - std::unique_ptr sc; - if (auto st = to(opt->valueType())) { - sc = std::make_unique(this, st); - } else if (auto tt = to(opt->valueType())) { - sc = std::make_unique(this, tt); + auto f = [&](bool reverseOrder) { + if (isSmallOptional(opt)) { + load(opt->valueType(), reverseOrder); } else { - solUnimplemented(""); - } - sc->convertSliceToTuple(); - if (!reverseOrder) { - exchange(1); + *this << "LDREFRTOS"; + std::unique_ptr sc; + if (auto st = to(opt->valueType())) { + sc = std::make_unique(this, st); + } else if (auto tt = to(opt->valueType())) { + sc = std::make_unique(this, tt); + } else { + solUnimplemented(""); + } + sc->convertSliceToTuple(); + if (!reverseOrder) { + exchange(1); + } } - } - }; + }; - *this << "LDI 1"; // hasValue slice - exchange(1); // slice hasValue - fixStack(-1); // fix stack + *this << "LDI 1"; // hasValue slice + exchange(1); // slice hasValue + fixStack(-1); // fix stack - startContinuation(); - if (optValueAsTuple(opt->valueType())) { - f(true); - tuple(1); - exchange(1); - } else { - f(false); - } - endContinuation(); - fixStack(-1); // fix stack - if (!hasLock()) { - solAssert(saveStakeSize == stackSize(), ""); - } + startContinuation(); + if (optValueAsTuple(opt->valueType())) { + f(true); + tuple(1); + exchange(1); + } else { + f(false); + } + endContinuation(); + fixStack(-1); // fix stack + if (!hasLock()) { + solAssert(saveStakeSize == stackSize(), ""); + } - startContinuation(); - pushNull(); - exchange(1); - endContinuation(); - fixStack(-1); // fix stack - if (!hasLock()) { - solAssert(saveStakeSize == stackSize(), ""); - } + startContinuation(); + pushNull(); + exchange(1); + endContinuation(); + fixStack(-1); // fix stack + if (!hasLock()) { + solAssert(saveStakeSize == stackSize(), ""); + } - ifElse(); - fixStack(+1); // fix stack - if (!hasLock()) { - solAssert(saveStakeSize + 1 == stackSize(), ""); + ifElse(); + fixStack(+1); // fix stack + if (!hasLock()) { + solAssert(saveStakeSize + 1 == stackSize(), ""); + } + endOpaque(1, 2); } - endOpaque(1, 2); - return true; } case Type::Category::Tuple: { @@ -1237,6 +1235,7 @@ bool StackPusher::fastLoad(const Type* type) { default: solUnimplemented(type->toString()); } + solUnimplemented(""); // true => value slice // false => slice value } @@ -1435,56 +1434,64 @@ void StackPusher::store( int deltaStack = 1; switch (type->category()) { case Type::Category::Optional: { - startOpaque(); auto optType = to(type); - if (!reverse) - exchange(1); // builder value - pushS(0); // builder value value - *this << "ISNULL"; // builder value isnull - fixStack(-1); // fix stack - ensureSize(stackSize); + auto optValueType = optType->valueType(); + auto array = to(optType->valueType()); + if (optValueType->category() == Type::Category::TvmCell || (array && array->isByteArrayOrString())) { + if (reverse) + exchange(1); // value builder + *this << "STDICT"; + } else { + startOpaque(); + if (!reverse) + exchange(1); // builder value + pushS(0); // builder value value + *this << "ISNULL"; // builder value isnull + fixStack(-1); // fix stack + ensureSize(stackSize); - startContinuation(); - // builder value - drop(1); // builder - stzeroes(1); // builder' - endContinuation(); - fixStack(+1); // fix stack - ensureSize(stackSize); + startContinuation(); + // builder value + drop(1); // builder + stzeroes(1); // builder' + endContinuation(); + fixStack(+1); // fix stack + ensureSize(stackSize); - startContinuation(); - // builder value - if (isIn(optType->valueType()->category(), Type::Category::Optional, Type::Category::Mapping)) { - untuple(1); - } - // builder value - if (isSmallOptional(optType)) { - exchange(1); // value builder - stones(1); // value builder' - store(optType->valueType(), false); // builder'' - } else { - // builder' value - std::unique_ptr sc; - if (optType->valueType()->category() == Type::Category::Tuple) { - auto tup = to(optType->valueType()); - sc = std::make_unique(this, tup); - } else if (optType->valueType()->category() == Type::Category::Struct) { - auto st = to(optType->valueType()); - sc = std::make_unique(this, st); + startContinuation(); + // builder value + if (isIn(optType->valueType()->category(), Type::Category::Optional, Type::Category::Mapping)) { + untuple(1); + } + // builder value + if (isSmallOptional(optType)) { + exchange(1); // value builder + stones(1); // value builder' + store(optType->valueType(), false); // builder'' } else { - // TODO add test for struct - solUnimplemented(""); + // builder' value + std::unique_ptr sc; + if (optType->valueType()->category() == Type::Category::Tuple) { + auto tup = to(optType->valueType()); + sc = std::make_unique(this, tup); + } else if (optType->valueType()->category() == Type::Category::Struct) { + auto st = to(optType->valueType()); + sc = std::make_unique(this, st); + } else { + // TODO add test for struct + solUnimplemented(""); + } + sc->tupleToBuilder(); + *this << "STBREFR"; + stones(1); // builder' } - sc->tupleToBuilder(); - *this << "STBREFR"; - stones(1); // builder' - } - endContinuation(); - fixStack(+1); // fix stack - ensureSize(stackSize); + endContinuation(); + fixStack(+1); // fix stack + ensureSize(stackSize); - ifElse(); - endOpaque(2, 1); + ifElse(); + endOpaque(2, 1); + } break; } case Type::Category::TvmCell: @@ -2023,7 +2030,7 @@ void StackPusher::pushParameter(std::vector> con void StackPusher::pushMacroCallInCallRef(int take, int ret, const string& functionName) { startContinuation(); - pushCall(take, ret, functionName); + pushMacro(take, ret, functionName); pushRefContAndCallX(take, ret, false); } @@ -2060,9 +2067,9 @@ void StackPusher::pushCallOrCallRef( } } -void StackPusher::pushCall(int take, int ret, const std::string& functionName) { +void StackPusher::pushMacro(int take, int ret, const std::string& functionName) { change(take, ret); - auto opcode = createNode("CALL $" + functionName + "$", take, ret); + auto opcode = createNode(".inline __" + functionName, take, ret); m_instructions.back().push_back(opcode); } @@ -2757,6 +2764,13 @@ void StackPusher::pushDefaultValue(Type const* _type) { pushDefaultValue(&userDefValue->underlyingType()); break; } + case Type::Category::Tuple: { + auto tuple = to(_type); + for (Type const* comp : tuple->components()) { + pushDefaultValue(comp); + } + break; + } default: solUnimplemented(""); } @@ -2766,10 +2780,19 @@ void StackPusher::pushDefaultValue(Type const* _type) { void StackPusher::getDict( Type const& keyType, Type const& valueType, + const GetDictOperation op +) { + GetFromDict d(*this, keyType, valueType, op, std::nullopt); + d.getDict(); +} + +void StackPusher::getAndSetDict( + const Type &keyType, + const Type &valueType, const GetDictOperation op, - const DataType& dataType + const DataType inputValueType ) { - GetFromDict d(*this, keyType, valueType, op, dataType); + GetFromDict d(*this, keyType, valueType, op, inputValueType); d.getDict(); } diff --git a/compiler/libsolidity/codegen/TVMPusher.hpp b/compiler/libsolidity/codegen/TVMPusher.hpp index 895e788c..95b886f9 100644 --- a/compiler/libsolidity/codegen/TVMPusher.hpp +++ b/compiler/libsolidity/codegen/TVMPusher.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -10,10 +10,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ -/** - * @author TON Labs - * @date 2019 - */ #pragma once @@ -220,6 +216,7 @@ class StackPusher { void pushString(const std::string& str, bool toSlice); void pushLog(); void untuple(int n); + void unpackFirst(int n); void indexWithExcep(int index); void indexNoexcep(int index); void setIndex(int index); @@ -264,7 +261,7 @@ class StackPusher { void pushParameter(std::vector> const& params); void pushMacroCallInCallRef(int take, int ret, const std::string& fname); void pushCallOrCallRef(const std::string& functionName, FunctionType const* ft, const std::optional>& deltaStack = std::nullopt); - void pushCall(int take, int ret, const std::string& functionName); + void pushMacro(int take, int ret, const std::string& functionName); void computeConstCell(std::string const& expName); void computeConstSlice(std::string const& expName); void drop(int cnt = 1); @@ -318,8 +315,14 @@ class StackPusher { void getDict( const Type& keyType, const Type& valueType, - GetDictOperation op, - const DataType& dataType = DataType::Slice + const GetDictOperation op + ); + + void getAndSetDict( + const Type &keyType, + const Type &valueType, + const GetDictOperation op, + const DataType inputValueType ); void pushEmptyArray(); diff --git a/compiler/libsolidity/codegen/TVMSimulator.cpp b/compiler/libsolidity/codegen/TVMSimulator.cpp index 057baecc..f1899ac7 100644 --- a/compiler/libsolidity/codegen/TVMSimulator.cpp +++ b/compiler/libsolidity/codegen/TVMSimulator.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,11 +11,10 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2021 * Simulator of TVM execution */ +#include "TVMCommons.hpp" #include "TVMSimulator.hpp" using namespace solidity::frontend; @@ -127,7 +126,7 @@ bool Simulator::visit(GenOpcode &_node) { m_stackSize += _node.ret() - _node.take(); m_commands.emplace_back(_node.shared_from_this()); } - m_wasCall |= _node.opcode() == "CALL"; + m_wasCall |= isIn(_node.opcode(), "CALL", "EXECUTE", ".inline"); return false; } diff --git a/compiler/libsolidity/codegen/TVMSimulator.hpp b/compiler/libsolidity/codegen/TVMSimulator.hpp index fe296f33..cbfe849e 100644 --- a/compiler/libsolidity/codegen/TVMSimulator.hpp +++ b/compiler/libsolidity/codegen/TVMSimulator.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2021 * Simulator of TVM execution */ diff --git a/compiler/libsolidity/codegen/TVMStructCompiler.cpp b/compiler/libsolidity/codegen/TVMStructCompiler.cpp index c7b7e26c..5eb2d59a 100644 --- a/compiler/libsolidity/codegen/TVMStructCompiler.cpp +++ b/compiler/libsolidity/codegen/TVMStructCompiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * Struct compiler for TVM */ diff --git a/compiler/libsolidity/codegen/TVMStructCompiler.hpp b/compiler/libsolidity/codegen/TVMStructCompiler.hpp index 755c10bd..10e6fd32 100644 --- a/compiler/libsolidity/codegen/TVMStructCompiler.hpp +++ b/compiler/libsolidity/codegen/TVMStructCompiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2019 * Struct compiler for TVM */ diff --git a/compiler/libsolidity/codegen/TVMTypeChecker.cpp b/compiler/libsolidity/codegen/TVMTypeChecker.cpp index bc1bd954..d642a0ce 100644 --- a/compiler/libsolidity/codegen/TVMTypeChecker.cpp +++ b/compiler/libsolidity/codegen/TVMTypeChecker.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2020-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -10,10 +10,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ -/** - * @author TON Labs - * @date 2019 - */ #include @@ -210,7 +206,7 @@ bool TVMTypeChecker::visit(const FunctionDefinition &f) { if (f.functionID().value() == 0) { m_errorReporter.typeError(228_error, f.location(), "functionID can't be equal to zero because this value is reserved for receive function."); } - if (!f.isPublic() && f.name() != "onCodeUpgrade") { + if (!f.functionIsExternallyVisible() && f.name() != "onCodeUpgrade") { m_errorReporter.typeError(228_error, f.location(), "Only public/external functions and function `onCodeUpgrade` can have functionID."); } if (f.isReceive() || f.isFallback() || f.isOnTickTock() || f.isOnBounce()) { @@ -263,38 +259,17 @@ bool TVMTypeChecker::visit(IndexRangeAccess const& indexRangeAccess) { return true; } -bool TVMTypeChecker::visit(FunctionCall const& _functionCall) { +void TVMTypeChecker::checkDeprecation(FunctionCall const& _functionCall) { auto memberAccess = to(&_functionCall.expression()); ASTString const& memberName = memberAccess ? memberAccess->memberName() : ""; Type const* expressionType = _functionCall.expression().annotation().type; - std::vector> const& arguments = _functionCall.arguments(); switch (expressionType->category()) { case Type::Category::Function: { auto functionType = to(expressionType); - - if (functionType->hasDeclaration()) { - auto fd = to(&functionType->declaration()); - if (fd && fd->name() == "onCodeUpgrade") { - if (m_inherHelper->isBaseFunction(fd)) { - m_errorReporter.typeError( - 228_error, _functionCall.location(), - "It is forbidden to call base functions of \"onCodeUpgrade\"."); - } - } - } - switch (functionType->kind()) { - case FunctionType::Kind::TVMInitCodeHash: - if (*GlobalParams::g_tvmVersion == TVMVersion::ton()) { - m_errorReporter.typeError(228_error, _functionCall.location(), - "\"tvm.initCodeHash()\"" + isNotSupportedVM); - } - break; - case FunctionType::Kind::TVMCode: - if (*GlobalParams::g_tvmVersion == TVMVersion::ton()) { - m_errorReporter.typeError(228_error, _functionCall.location(), - "\"tvm.code()\"" + isNotSupportedVM); - } + case FunctionType::Kind::OptionalReset: + m_errorReporter.warning(228_error, _functionCall.location(), + "\".reset()\" is deprecated. Use \"delete ;\"."); break; case FunctionType::Kind::TVMSliceLoad: if (memberName == "decode") { @@ -357,6 +332,72 @@ bool TVMTypeChecker::visit(FunctionCall const& _functionCall) { default: break; } + break; + } + default: + break; + } +} + +void TVMTypeChecker::checkSupport(FunctionCall const& _functionCall) { + Type const* expressionType = _functionCall.expression().annotation().type; + switch (expressionType->category()) { + case Type::Category::Function: { + auto functionType = to(expressionType); + switch (functionType->kind()) { + case FunctionType::Kind::GasLeft: + if (*GlobalParams::g_tvmVersion == TVMVersion::ton()) { + m_errorReporter.typeError(228_error, _functionCall.location(), + "\"gasleft()\"" + isNotSupportedVM); + } + break; + case FunctionType::Kind::TVMInitCodeHash: + if (*GlobalParams::g_tvmVersion == TVMVersion::ton()) { + m_errorReporter.typeError(228_error, _functionCall.location(), + "\"tvm.initCodeHash()\"" + isNotSupportedVM); + } + break; + case FunctionType::Kind::TVMCode: + if (*GlobalParams::g_tvmVersion == TVMVersion::ton()) { + m_errorReporter.typeError(228_error, _functionCall.location(), + "\"tvm.code()\"" + isNotSupportedVM); + } + break; + default: + break; + } + break; + } + default: + break; + } + + if (_functionCall.isAwait() && *GlobalParams::g_tvmVersion == TVMVersion::ton()) { + m_errorReporter.typeError(228_error, _functionCall.location(), + "\"*.await\"" + isNotSupportedVM); + } +} + +bool TVMTypeChecker::visit(FunctionCall const& _functionCall) { + checkDeprecation(_functionCall); + checkSupport(_functionCall); + + Type const* expressionType = _functionCall.expression().annotation().type; + std::vector> const& arguments = _functionCall.arguments(); + switch (expressionType->category()) { + case Type::Category::Function: { + auto functionType = to(expressionType); + + if (functionType->hasDeclaration()) { + auto fd = to(&functionType->declaration()); + if (fd && fd->name() == "onCodeUpgrade") { + if (m_inherHelper->isBaseFunction(fd)) { + m_errorReporter.typeError( + 228_error, _functionCall.location(), + "It is forbidden to call base functions of \"onCodeUpgrade\"."); + } + } + } switch (functionType->kind()) { case FunctionType::Kind::TVMSliceLoadInt: @@ -385,11 +426,6 @@ bool TVMTypeChecker::visit(FunctionCall const& _functionCall) { break; } - if (_functionCall.isAwait() && *GlobalParams::g_tvmVersion == TVMVersion::ton()) { - m_errorReporter.typeError(228_error, _functionCall.location(), - "\"*.await\"" + isNotSupportedVM); - } - return true; } diff --git a/compiler/libsolidity/codegen/TVMTypeChecker.hpp b/compiler/libsolidity/codegen/TVMTypeChecker.hpp index 664d69b9..0c37f2aa 100644 --- a/compiler/libsolidity/codegen/TVMTypeChecker.hpp +++ b/compiler/libsolidity/codegen/TVMTypeChecker.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -10,10 +10,6 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ -/** - * @author TON Labs - * @date 2019 - */ #pragma once @@ -36,6 +32,8 @@ class TVMTypeChecker : public ASTConstVisitor { bool visit(FunctionDefinition const& fc) override; bool visit(ContractDefinition const& ) override; bool visit(IndexRangeAccess const& ) override; + void checkDeprecation(FunctionCall const& _functionCall); + void checkSupport(FunctionCall const& _functionCall); bool visit(FunctionCall const& ) override; bool visit(PragmaDirective const& ) override; bool visit(MemberAccess const& ) override; diff --git a/compiler/libsolidity/codegen/TvmAst.cpp b/compiler/libsolidity/codegen/TvmAst.cpp index 9797d8ea..6324923d 100644 --- a/compiler/libsolidity/codegen/TvmAst.cpp +++ b/compiler/libsolidity/codegen/TvmAst.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2021 * TVM Solidity abstract syntax tree. */ @@ -33,6 +31,15 @@ using namespace solidity::frontend; using namespace std; +namespace { + bool eq(Pointer const& a,Pointer const& b) { + if ((a == nullptr) ^ (b == nullptr)) { + return false; + } + return a == nullptr || *a == *b; + } +} + void Loc::accept(TvmAstVisitor& _visitor) { _visitor.visit(*this); } @@ -260,12 +267,14 @@ void PushCellOrSlice::accept(TvmAstVisitor& _visitor) { bool PushCellOrSlice::operator==(TvmAstNode const& _node) const { auto p = to(&_node); if (p && std::tie(m_type, m_blob) == std::tie(p->m_type, p->m_blob)) { - if (m_child == nullptr && p->m_child == nullptr) { - return true; + if ((m_child == nullptr) ^ (p->m_child == nullptr)) { + return false; } - if (m_child != nullptr && p->m_child != nullptr) { - return *m_child.get() == *p->m_child.get(); + if (m_child == nullptr) { + // p->m_child == nullptr also + return true; } + return *m_child.get() == *p->m_child.get(); } return false; } @@ -280,23 +289,15 @@ bool PushCellOrSlice::operator<(TvmAstNode const& _node) const { return std::tie(m_type, m_blob, *m_child) < std::tie(p->m_type, p->m_blob, *p->m_child); } -bool PushCellOrSlice::equal(PushCellOrSlice const& another) const { - PushCellOrSlice const* a = this; - PushCellOrSlice const* b = &another; - while (true) { - if (a->m_blob != b->m_blob || a->m_type != b->m_type) { - return false; - } - if (!a->m_child && !b->m_child) { - return true; - } - if (!a->m_child || !b->m_child) { - return false; - } - a = a->m_child.get(); - b = b->m_child.get(); +std::string PushCellOrSlice::chainBlob() const { + string s; + PushCellOrSlice const* p = this; + while (p != nullptr) { + solAssert(p->blob().at(0) == 'x'); + s += p->blob().substr(1); + p = p->child().get(); } - solUnimplemented(""); + return s; } void PushCellOrSlice::updToRef() { @@ -392,6 +393,12 @@ void TvmIfElse::accept(TvmAstVisitor& _visitor) { } } +bool TvmIfElse::operator==(TvmAstNode const& _node) const { + auto op = to(&_node); + return op && eq(m_trueBody, op->m_trueBody) && eq(op->m_falseBody, op->m_falseBody) && + std::tie(m_withNot, m_withJmp, m_ret) == std::tie(op->m_withNot, op->m_withJmp, op->m_ret); +} + void TvmRepeat::accept(TvmAstVisitor& _visitor) { if (_visitor.visit(*this)) { @@ -516,6 +523,7 @@ Pointer gen(const std::string& cmd) { {"BLOCKLT", {0, 1, true}}, {"FALSE", {0, 1, true}}, + {"GASREMAINING", {0, 1}}, {"GETPARAM", {0, 1, true}}, {"INITCODEHASH", {0, 1, true}}, {"LTIME", {0, 1, true}}, @@ -622,7 +630,6 @@ Pointer gen(const std::string& cmd) { {"LDILE8", {1, 2}}, {"LDMSGADDR", {1, 2}}, {"LDONES", {1, 2, true}}, - {"LDOPTREF", {1, 2}}, {"LDREF", {1, 2}}, {"LDREFRTOS", {1, 2}}, {"LDSLICE", {1, 2}}, @@ -692,7 +699,6 @@ Pointer gen(const std::string& cmd) { {"STILE8", {2, 1}}, {"STIR", {2, 1}}, {"STONES", {2, 1}}, - {"STOPTREF", {2, 1}}, {"STREF", {2, 1}}, {"STREFR", {2, 1}}, {"STSLICE", {2, 1}}, @@ -760,6 +766,9 @@ Pointer gen(const std::string& cmd) { } else if (f("UNTUPLE")) { int ret = boost::lexical_cast(param); opcode = createNode(cmd, 1, ret); + } else if (f("UNPACKFIRST")) { + int ret = boost::lexical_cast(param); + opcode = createNode(cmd, 1, ret); } else if (f("LSHIFT") || f("RSHIFT")) { if (param.empty()) { opcode = createNode(cmd, 2, 1); @@ -779,6 +788,7 @@ Pointer gen(const std::string& cmd) { return opcode; } +// TODO DELETE use makePushCellOrSlice Pointer genPushSlice(const std::string& data) { if (StrUtils::toBitString(data).length() <= TvmConst::MaxPushSliceBitLength) return createNode( @@ -793,6 +803,28 @@ Pointer genPushSlice(const std::string& data) { ); } +Pointer makePushCellOrSlice(std::string const& hexStr, bool toSlice) { + solAssert(hexStr.size() % 2 == 0, ""); + + const int length = hexStr.size(); + const int symbolQty = ((TvmConst::CellBitLength / 8) * 8) / 4; // one symbol in string == 8 bit. Letter can't be divided by 2 cells + PushCellOrSlice::Type type = toSlice ? PushCellOrSlice::Type::PUSHREFSLICE : PushCellOrSlice::Type::PUSHREF; + std::vector> data; + int start = 0; + do { + std::string slice = hexStr.substr(start, std::min(symbolQty, length - start)); + data.emplace_back(type, "x" + slice); + start += symbolQty; + type = PushCellOrSlice::Type::CELL; + } while (start < length); + + Pointer cell; + for (const auto&[t, d] : data | boost::adaptors::reversed) { + cell = createNode(t, d, cell); + } + return cell; +} + Pointer makeDROP(int cnt) { solAssert(cnt >= 1, ""); return createNode(Stack::Opcode::DROP, cnt); diff --git a/compiler/libsolidity/codegen/TvmAst.hpp b/compiler/libsolidity/codegen/TvmAst.hpp index 6e4b44b2..dab915a2 100644 --- a/compiler/libsolidity/codegen/TvmAst.hpp +++ b/compiler/libsolidity/codegen/TvmAst.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2021 * TVM Solidity abstract syntax tree. */ @@ -280,8 +278,8 @@ namespace solidity::frontend int ret() const override { return 1; } Type type() const { return m_type; } std::string const &blob() const { return m_blob; } + std::string chainBlob() const; Pointer child() const { return m_child; } - bool equal(PushCellOrSlice const& another) const; // TODO delete void updToRef(); private: Type m_type; @@ -365,7 +363,7 @@ namespace solidity::frontend Pointer const &falseBody, int ret); void accept(TvmAstVisitor& _visitor) override; - bool operator==(TvmAstNode const&) const override { return false; } // TODO + bool operator==(TvmAstNode const&) const override; bool withNot() const { return m_withNot; } bool withJmp() const { return m_withJmp; } Pointer const& trueBody() const { return m_trueBody; } @@ -501,7 +499,8 @@ namespace solidity::frontend }; Pointer gen(const std::string& cmd); - Pointer genPushSlice(const std::string& data); + Pointer genPushSlice(const std::string& _str); + Pointer makePushCellOrSlice(std::string const& hexStr, bool toSlice); Pointer makeDROP(int cnt = 1); Pointer makePOP(int i); Pointer makeBLKPUSH(int qty, int index); @@ -539,7 +538,7 @@ namespace solidity::frontend bool isXCHG(Pointer const& node, int i, int j); std::optional isXCHG_S0(Pointer const& node); std::optional> isREVERSE(Pointer const& node); - Pointer isPlainPushSlice(Pointer const& node); + Pointer isPlainPushSlice(Pointer const& node); // TODO DELETE, support long slices int getRootBitSize(PushCellOrSlice const &_node); diff --git a/compiler/libsolidity/codegen/TvmAstVisitor.cpp b/compiler/libsolidity/codegen/TvmAstVisitor.cpp index e9bea4f5..c0707faf 100644 --- a/compiler/libsolidity/codegen/TvmAstVisitor.cpp +++ b/compiler/libsolidity/codegen/TvmAstVisitor.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2021 * Visitor for TVM Solidity abstract syntax tree. */ @@ -103,7 +101,27 @@ bool Printer::visit(GenOpcode &_node) { else if (_node.fullOpcode() == "UNTUPLE 1") m_out << "UNSINGLE"; else if (_node.fullOpcode() == "UNTUPLE 2") m_out << "UNPAIR"; else if (_node.fullOpcode() == "UNTUPLE 3") m_out << "UNTRIPLE"; - else if (_node.fullOpcode() == "STSLICECONST x4_") m_out << "STZERO"; + else if (_node.opcode() == "UNTUPLE") { + int ret = boost::lexical_cast(_node.arg()); + if (ret <= 15) { + m_out << "UNTUPLE " << ret; + } else { + m_out << "PUSHINT " << ret; + endL(); + tabs(); + m_out << "UNTUPLEVAR"; + } + } else if (_node.opcode() == "UNPACKFIRST") { + int ret = boost::lexical_cast(_node.arg()); + if (ret <= 15) { + m_out << "UNPACKFIRST " << ret; + } else { + m_out << "PUSHINT " << ret; + endL(); + tabs(); + m_out << "UNPACKFIRSTVAR"; + } + } else if (_node.fullOpcode() == "STSLICECONST x4_") m_out << "STZERO"; else if (_node.fullOpcode() == "STSLICECONST xc_") m_out << "STONE"; else if (isIn(_node.opcode(), "INDEX_EXCEP", "INDEX_NOEXCEP")) { int index = boost::lexical_cast(_node.arg()); @@ -631,7 +649,7 @@ bool Printer::visit(TryCatch &_node) { _node.tryBody()->accept(*this); _node.catchBody()->accept(*this); tabs(); - m_out << ".blob xF2FE ; TRYKEEP" << std::endl; + m_out << "TRYKEEP" << std::endl; return false; } diff --git a/compiler/libsolidity/codegen/TvmAstVisitor.hpp b/compiler/libsolidity/codegen/TvmAstVisitor.hpp index 8a7097e9..faeb362f 100644 --- a/compiler/libsolidity/codegen/TvmAstVisitor.hpp +++ b/compiler/libsolidity/codegen/TvmAstVisitor.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2021-2023 EverX. All Rights Reserved. * * Licensed under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. @@ -11,8 +11,6 @@ * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ /** - * @author TON Labs - * @date 2021 * Visitor for TVM Solidity abstract syntax tree. */ @@ -28,98 +26,98 @@ namespace solidity::frontend { - class TvmAstVisitor { - public: - virtual ~TvmAstVisitor() = default; - virtual bool visit(AsymGen &_node) { return visitNode(_node); } - virtual bool visit(DeclRetFlag &_node) { return visitNode(_node); } - virtual bool visit(Opaque &_node) { return visitNode(_node); } - virtual bool visit(HardCode &_node) { return visitNode(_node); } - virtual bool visit(Loc &_node) { return visitNode(_node); } - virtual bool visit(TvmReturn &_node) { return visitNode(_node); } - virtual bool visit(ReturnOrBreakOrCont &_node) { return visitNode(_node); } - virtual bool visit(TvmException &_node) { return visitNode(_node); } - virtual bool visit(GenOpcode &_node) { return visitNode(_node); } - virtual bool visit(PushCellOrSlice &_node) { return visitNode(_node); } - virtual bool visit(Glob &_node) { return visitNode(_node); } - virtual bool visit(Stack &_node) { return visitNode(_node); } - virtual bool visit(CodeBlock &_node) { return visitNode(_node); } - virtual bool visit(SubProgram &_node) { return visitNode(_node); } - virtual bool visit(LogCircuit &_node) { return visitNode(_node); } - virtual bool visit(TvmIfElse &_node) { return visitNode(_node); } - virtual bool visit(TvmRepeat &_node) { return visitNode(_node); } - virtual bool visit(TvmUntil &_node) { return visitNode(_node); } - virtual bool visit(While &_node) { return visitNode(_node); } - virtual bool visit(TryCatch &_node) { return visitNode(_node); } - virtual bool visit(Contract &_node) { return visitNode(_node); } - virtual bool visit(Function &_node) { return visitNode(_node); } +class TvmAstVisitor { +public: + virtual ~TvmAstVisitor() = default; + virtual bool visit(AsymGen &_node) { return visitNode(_node); } + virtual bool visit(DeclRetFlag &_node) { return visitNode(_node); } + virtual bool visit(Opaque &_node) { return visitNode(_node); } + virtual bool visit(HardCode &_node) { return visitNode(_node); } + virtual bool visit(Loc &_node) { return visitNode(_node); } + virtual bool visit(TvmReturn &_node) { return visitNode(_node); } + virtual bool visit(ReturnOrBreakOrCont &_node) { return visitNode(_node); } + virtual bool visit(TvmException &_node) { return visitNode(_node); } + virtual bool visit(GenOpcode &_node) { return visitNode(_node); } + virtual bool visit(PushCellOrSlice &_node) { return visitNode(_node); } + virtual bool visit(Glob &_node) { return visitNode(_node); } + virtual bool visit(Stack &_node) { return visitNode(_node); } + virtual bool visit(CodeBlock &_node) { return visitNode(_node); } + virtual bool visit(SubProgram &_node) { return visitNode(_node); } + virtual bool visit(LogCircuit &_node) { return visitNode(_node); } + virtual bool visit(TvmIfElse &_node) { return visitNode(_node); } + virtual bool visit(TvmRepeat &_node) { return visitNode(_node); } + virtual bool visit(TvmUntil &_node) { return visitNode(_node); } + virtual bool visit(While &_node) { return visitNode(_node); } + virtual bool visit(TryCatch &_node) { return visitNode(_node); } + virtual bool visit(Contract &_node) { return visitNode(_node); } + virtual bool visit(Function &_node) { return visitNode(_node); } - virtual void endVisit(CodeBlock &_node) { endVisitNode(_node); } - protected: - virtual bool visitNode(TvmAstNode const&) { return true; } - virtual void endVisitNode(TvmAstNode const&) { } - }; + virtual void endVisit(CodeBlock &_node) { endVisitNode(_node); } +protected: + virtual bool visitNode(TvmAstNode const&) { return true; } + virtual void endVisitNode(TvmAstNode const&) { } +}; - class Printer : public TvmAstVisitor { - public: - explicit Printer(std::ostream& out) : m_out{out} { } - bool visit(AsymGen &_node) override; - bool visit(DeclRetFlag &_node) override; - bool visit(Opaque &_node) override; - bool visit(HardCode &_node) override; - bool visit(Loc &_node) override; - bool visit(TvmReturn &_node) override; - bool visit(ReturnOrBreakOrCont &_node) override; - bool visit(TvmException &_node) override; - bool visit(GenOpcode &_node) override; - bool visit(PushCellOrSlice &_node) override; - bool visit(Glob &_node) override; - bool visit(Stack &_node) override; - bool visit(CodeBlock &_node) override; - bool visit(SubProgram &_node) override; - bool visit(LogCircuit &_node) override; - bool visit(TvmIfElse &_node) override; - bool visit(TvmRepeat &_node) override; - bool visit(TvmUntil &_node) override; - bool visit(TryCatch &_node) override; - bool visit(While &_node) override; - bool visit(Contract &_node) override; - bool visit(Function &_node) override; - protected: - bool visitNode(TvmAstNode const&) override; - private: - void endL(); - void tabs(); - void printPushInt(std::string const& arg, std::string const& comment = ""); - void printPushInt(int i); - private: - std::ostream& m_out; - int m_tab{}; - }; +class Printer : public TvmAstVisitor { +public: + explicit Printer(std::ostream& out) : m_out{out} { } + bool visit(AsymGen &_node) override; + bool visit(DeclRetFlag &_node) override; + bool visit(Opaque &_node) override; + bool visit(HardCode &_node) override; + bool visit(Loc &_node) override; + bool visit(TvmReturn &_node) override; + bool visit(ReturnOrBreakOrCont &_node) override; + bool visit(TvmException &_node) override; + bool visit(GenOpcode &_node) override; + bool visit(PushCellOrSlice &_node) override; + bool visit(Glob &_node) override; + bool visit(Stack &_node) override; + bool visit(CodeBlock &_node) override; + bool visit(SubProgram &_node) override; + bool visit(LogCircuit &_node) override; + bool visit(TvmIfElse &_node) override; + bool visit(TvmRepeat &_node) override; + bool visit(TvmUntil &_node) override; + bool visit(TryCatch &_node) override; + bool visit(While &_node) override; + bool visit(Contract &_node) override; + bool visit(Function &_node) override; +protected: + bool visitNode(TvmAstNode const&) override; +private: + void endL(); + void tabs(); + void printPushInt(std::string const& arg, std::string const& comment = ""); + void printPushInt(int i); +private: + std::ostream& m_out; + int m_tab{}; +}; - class LocSquasher : public TvmAstVisitor { - public: - bool visit(CodeBlock &_node) override; - }; +class LocSquasher : public TvmAstVisitor { +public: + bool visit(CodeBlock &_node) override; +}; - class DeleterAfterRet : public TvmAstVisitor { - public: - void endVisit(CodeBlock &_node) override; - }; +class DeleterAfterRet : public TvmAstVisitor { +public: + void endVisit(CodeBlock &_node) override; +}; - class DeleterCallX : public TvmAstVisitor { - public: - bool visit(Function &_node) override; - }; +class DeleterCallX : public TvmAstVisitor { +public: + bool visit(Function &_node) override; +}; - class LogCircuitExpander : public TvmAstVisitor { - public: - void endVisit(CodeBlock &_node) override; - private: - bool isPureOperation(Pointer const& op); - private: - int m_stackSize{}; - std::vector> m_newInst; - }; +class LogCircuitExpander : public TvmAstVisitor { +public: + void endVisit(CodeBlock &_node) override; +private: + bool isPureOperation(Pointer const& op); +private: + int m_stackSize{}; + std::vector> m_newInst; +}; } // end solidity::frontend diff --git a/compiler/scripts/install_deps.sh b/compiler/scripts/install_deps.sh index 0b686201..33c026f4 100755 --- a/compiler/scripts/install_deps.sh +++ b/compiler/scripts/install_deps.sh @@ -99,6 +99,9 @@ case $(uname -s) in 12.*) echo "Installing solidity dependencies on macOS 12 Monterey." ;; + 13.*) + echo "Installing solidity dependencies on macOS 13." + ;; *) echo "Unsupported macOS version." echo "We only support Mavericks, Yosemite, El Capitan, Sierra, High Sierra, Mojave, Catalina, Big Sur and Monterey." diff --git a/compiler/solc/CommandLineParser.cpp b/compiler/solc/CommandLineParser.cpp index 46e87423..b840f4ae 100644 --- a/compiler/solc/CommandLineParser.cpp +++ b/compiler/solc/CommandLineParser.cpp @@ -512,7 +512,7 @@ void CommandLineParser::parseOutputSelection() po::options_description CommandLineParser::optionsDescription() { // Declare the supported options. - po::options_description desc((R"(solc, the Ever Solidity commandline compiler. + po::options_description desc((R"(solc, the TVM Solidity commandline compiler. This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions. See 'solc --)" + g_strLicense + R"(' diff --git a/lib/stdlib_sol.tvm b/lib/stdlib_sol.tvm index f80d6998..48153b53 100644 --- a/lib/stdlib_sol.tvm +++ b/lib/stdlib_sol.tvm @@ -1,7 +1,3 @@ -.globl insert_pubkey -.type insert_pubkey, @function -CALL $insert_pubkey_macro$ - .macro insert_pubkey_macro .loc stdlib.sol, 14 SWAP @@ -107,10 +103,6 @@ THROWIFNOT 55 ENDC .loc stdlib.sol, 0 -.globl replay_protection -.type replay_protection, @function -CALL $replay_protection_macro$ - .macro replay_protection_macro .loc stdlib.sol, 61 GETGLOB 3 @@ -130,37 +122,25 @@ THROWIFNOT 52 SETGLOB 3 .loc stdlib.sol, 0 -.globl __tonToGas -.type __tonToGas, @function -CALL $__tonToGas_macro$ - .macro __tonToGas_macro .loc stdlib.sol, 67 PUSHPOW2 16 SWAP CALLREF { - CALL $__gasGasPrice_macro$ + .inline ____gasGasPrice_macro } MULDIV .loc stdlib.sol, 0 -.globl __gasToTon -.type __gasToTon, @function -CALL $__gasToTon_macro$ - .macro __gasToTon_macro .loc stdlib.sol, 71 CALLREF { - CALL $__gasGasPrice_macro$ + .inline ____gasGasPrice_macro } PUSHPOW2 16 MULDIVC .loc stdlib.sol, 0 -.globl __gasGasPrice -.type __gasGasPrice, @function -CALL $__gasGasPrice_macro$ - .macro __gasGasPrice_macro .loc stdlib.sol, 75 DUP @@ -192,10 +172,6 @@ PLDU 64 BLKDROP2 4, 1 .loc stdlib.sol, 0 -.globl __exp -.type __exp, @function -CALL $__exp_macro$ - .macro __exp_macro .loc stdlib.sol, 83 PUSHINT 1 @@ -234,10 +210,6 @@ WHILE BLKDROP2 2, 1 .loc stdlib.sol, 0 -.globl parseInteger -.type parseInteger, @function -CALL $parseInteger_macro$ - .macro parseInteger_macro .loc stdlib.sol, 99 TUPLE 0 @@ -320,10 +292,6 @@ DROP BLKDROP2 2, 1 .loc stdlib.sol, 0 -.globl convertIntToDecStr_short -.type convertIntToDecStr_short, @function -CALL $convertIntToDecStr_short_macro$ - .macro convertIntToDecStr_short_macro .loc stdlib.sol, 112 ROTREV @@ -334,14 +302,10 @@ DUP ROLL 5 LESSINT 0 CALLREF { - CALL $convertIntToDecStr_macro$ + .inline __convertIntToDecStr_macro } .loc stdlib.sol, 0 -.globl convertIntToDecStr -.type convertIntToDecStr, @function -CALL $convertIntToDecStr_macro$ - .macro convertIntToDecStr_macro .loc stdlib.sol, 116 PUSH S4 @@ -446,7 +410,7 @@ IFNOT ROLL 3 PUSHINT 10 CALLREF { - CALL $parseInteger_macro$ + .inline __parseInteger_macro } .loc stdlib.sol, 132 DUP @@ -734,10 +698,6 @@ IFELSE BLKDROP 5 .loc stdlib.sol, 0 -.globl convertAddressToHexString -.type convertAddressToHexString, @function -CALL $convertAddressToHexString_macro$ - .macro convertAddressToHexString_macro .loc stdlib.sol, 181 REWRITESTDADDR @@ -745,7 +705,7 @@ REWRITESTDADDR OVER2 ROLL 3 CALLREF { - CALL $convertIntToHexStr_short_macro$ + .inline __convertIntToHexStr_short_macro } POP S3 POP S3 @@ -796,14 +756,10 @@ TRUE DUP FALSE CALLREF { - CALL $convertIntToHexStr_macro$ + .inline __convertIntToHexStr_macro } .loc stdlib.sol, 0 -.globl convertFixedPointToString -.type convertFixedPointToString, @function -CALL $convertFixedPointToString_macro$ - .macro convertFixedPointToString_macro .loc stdlib.sol, 195 OVER @@ -814,7 +770,7 @@ PUSH3 S2, S0, S2 OR THROWIFNOT 69 CALLREF { - CALL $__exp_macro$ + .inline ____exp_macro } DIVMOD .loc stdlib.sol, 197 @@ -826,7 +782,7 @@ ROLL 7 SGN LESSINT 0 CALLREF { - CALL $convertIntToDecStr_macro$ + .inline __convertIntToDecStr_macro } POP S4 POP S4 @@ -876,14 +832,10 @@ SWAP TRUE FALSE CALLREF { - CALL $convertIntToDecStr_macro$ + .inline __convertIntToDecStr_macro } .loc stdlib.sol, 0 -.globl convertIntToHexStr_short -.type convertIntToHexStr_short, @function -CALL $convertIntToHexStr_short_macro$ - .macro convertIntToHexStr_short_macro .loc stdlib.sol, 210 ROTREV @@ -895,14 +847,10 @@ TRUE ROLL 6 LESSINT 0 CALLREF { - CALL $convertIntToHexStr_macro$ + .inline __convertIntToHexStr_macro } .loc stdlib.sol, 0 -.globl convertIntToHexStr -.type convertIntToHexStr, @function -CALL $convertIntToHexStr_macro$ - .macro convertIntToHexStr_macro .loc stdlib.sol, 214 PUSH S5 @@ -1007,7 +955,7 @@ IFNOT ROLL 4 PUSHINT 16 CALLREF { - CALL $parseInteger_macro$ + .inline __parseInteger_macro } .loc stdlib.sol, 230 DUP @@ -1337,10 +1285,6 @@ IFELSE BLKDROP 6 .loc stdlib.sol, 0 -.globl storeStringInBuilders -.type storeStringInBuilders, @function -CALL $storeStringInBuilders_macro$ - .macro storeStringInBuilders_macro .loc stdlib.sol, 288 OVER @@ -1412,10 +1356,6 @@ STSLICE BLKDROP2 3, 1 .loc stdlib.sol, 0 -.globl assembleList -.type assembleList, @function -CALL $assembleList_macro$ - .macro assembleList_macro .loc stdlib.sol, 306 PUSHCONT { @@ -1452,10 +1392,6 @@ ENDC NIP .loc stdlib.sol, 0 -.globl __stoi -.type __stoi, @function -CALL $__stoi_macro$ - .macro __stoi_macro .loc stdlib.sol, 315 CTOS @@ -1685,10 +1621,6 @@ IF BLKDROP2 2, 1 .loc stdlib.sol, 0 -.globl strToList -.type strToList, @function -CALL $strToList_macro$ - .macro strToList_macro .loc stdlib.sol, 370 TUPLE 0 @@ -1742,10 +1674,6 @@ NEWC STSLICE .loc stdlib.sol, 0 -.globl bytes_substr -.type bytes_substr, @function -CALL $bytes_substr_macro$ - .macro bytes_substr_macro .loc stdlib.sol, 385 PUSH S3 @@ -1779,14 +1707,10 @@ GEQ THROWIFNOT 70 .loc stdlib.sol, 392 CALLREF { - CALL $__subCell_macro$ + .inline ____subCell_macro } .loc stdlib.sol, 0 -.globl __substr -.type __substr, @function -CALL $__substr_macro$ - .macro __substr_macro .loc stdlib.sol, 396 PUSH S2 @@ -1817,14 +1741,10 @@ THROWIFNOT 70 .loc stdlib.sol, 401 UFITS 256 CALLREF { - CALL $__subCell_macro$ + .inline ____subCell_macro } .loc stdlib.sol, 0 -.globl __subCell -.type __subCell, @function -CALL $__subCell_macro$ - .macro __subCell_macro .loc stdlib.sol, 404 PUSHREF { @@ -1946,15 +1866,11 @@ PUSHCONT { WHILE .loc stdlib.sol, 430 CALLREF { - CALL $assembleList_macro$ + .inline __assembleList_macro } BLKDROP2 2, 1 .loc stdlib.sol, 0 -.globl compareLongStrings -.type compareLongStrings, @function -CALL $compareLongStrings_macro$ - .macro compareLongStrings_macro .loc stdlib.sol, 437 SWAP @@ -2033,15 +1949,11 @@ DROP2 PUSHINT 0 .loc stdlib.sol, 0 -.globl concatenateStrings -.type concatenateStrings, @function -CALL $concatenateStrings_macro$ - .macro concatenateStrings_macro .loc stdlib.sol, 459 SWAP CALLREF { - CALL $strToList_macro$ + .inline __strToList_macro } .loc stdlib.sol, 460 ROT @@ -2049,7 +1961,7 @@ CTOS .loc stdlib.sol, 461 BLKPUSH 3, 2 CALLREF { - CALL $storeStringInBuilders_macro$ + .inline __storeStringInBuilders_macro } POP S3 POP S3 @@ -2066,7 +1978,7 @@ PUSHCONT { .loc stdlib.sol, 464 BLKPUSH 3, 2 CALLREF { - CALL $storeStringInBuilders_macro$ + .inline __storeStringInBuilders_macro } POP S3 POP S3 @@ -2076,14 +1988,10 @@ WHILE .loc stdlib.sol, 466 DROP CALLREF { - CALL $assembleList_macro$ + .inline __assembleList_macro } .loc stdlib.sol, 0 -.globl __strchr -.type __strchr, @function -CALL $__strchr_macro$ - .macro __strchr_macro .loc stdlib.sol, 469 NULL @@ -2134,10 +2042,6 @@ BLKDROP 3 NIP .loc stdlib.sol, 0 -.globl __strrchr -.type __strrchr, @function -CALL $__strrchr_macro$ - .macro __strrchr_macro .loc stdlib.sol, 479 NULL @@ -2184,10 +2088,6 @@ BLKDROP 3 NIP .loc stdlib.sol, 0 -.globl __strstr -.type __strstr, @function -CALL $__strstr_macro$ - .macro __strstr_macro .loc stdlib.sol, 514 NULL @@ -2394,10 +2294,6 @@ BLKDROP 6 BLKDROP2 2, 1 .loc stdlib.sol, 0 -.globl __toLowerCase -.type __toLowerCase, @function -CALL $__toLowerCase_macro$ - .macro __toLowerCase_macro .loc stdlib.sol, 549 NEWC @@ -2497,10 +2393,6 @@ ENDC NIP .loc stdlib.sol, 0 -.globl __toUpperCase -.type __toUpperCase, @function -CALL $__toUpperCase_macro$ - .macro __toUpperCase_macro .loc stdlib.sol, 574 NEWC @@ -2600,10 +2492,6 @@ ENDC NIP .loc stdlib.sol, 0 -.globl stateInitHash -.type stateInitHash, @function -CALL $stateInitHash_macro$ - .macro stateInitHash_macro .loc stdlib.sol, 599 NEWC @@ -2625,3 +2513,68 @@ CTOS SHA256U .loc stdlib.sol, 0 +.macro __forwardFee_macro +.loc stdlib.sol, 622 +DEPTH +ADDCONST -3 +PICK +CTOS +.loc stdlib.sol, 623 +DUP +LDU 1 +POP S2 +.loc stdlib.sol, 624 +PUSHCONT { + .loc stdlib.sol, 635 + DROP + PUSHINT 0 + .loc stdlib.sol, 0 +} +PUSHCONT { + .loc stdlib.sol, 629 + LDU 3 + LDMSGADDR + LDMSGADDR + LDVARUINT16 + LDDICT + LDVARUINT16 + BLKDROP2 6, 1 + .loc stdlib.sol, 633 + LDVARUINT16 + DROP + .loc stdlib.sol, 0 +} +IFELSE +.loc stdlib.sol, 0 + +.macro __importFee_macro +.loc stdlib.sol, 640 +DEPTH +ADDCONST -3 +PICK +CTOS +.loc stdlib.sol, 641 +DUP +LDU 2 +POP S2 +.loc stdlib.sol, 642 +EQINT 2 +PUSHCONT { + .loc stdlib.sol, 645 + LDMSGADDR + LDMSGADDR + BLKDROP2 2, 1 + .loc stdlib.sol, 646 + LDVARUINT16 + DROP + .loc stdlib.sol, 0 +} +PUSHCONT { + .loc stdlib.sol, 648 + DROP + PUSHINT 0 + .loc stdlib.sol, 0 +} +IFELSE +.loc stdlib.sol, 0 + diff --git a/sold/Cargo.toml b/sold/Cargo.toml index 5425c8da..f454a2b8 100644 --- a/sold/Cargo.toml +++ b/sold/Cargo.toml @@ -1,7 +1,7 @@ [package] edition = '2021' name = 'sold' -version = '0.70.0' +version = '0.71.0' [[bin]] name = 'sold' @@ -16,10 +16,10 @@ serde_json = { features = [ 'unbounded_depth' ], version = '1.0' } strip-ansi-escapes = '0.1' clap = { features = [ 'derive' ], version = '4.2' } serde = { features = [ 'derive' ], version = '1.0' } -ton_abi = { git = 'https://github.com/tonlabs/ever-abi.git', tag = '2.3.108' } -ton_block = { git = 'https://github.com/tonlabs/ever-block.git', tag = '1.9.70' } -ton_types = { git = 'https://github.com/tonlabs/ever-types.git', tag = '2.0.12' } -tvm_linker = { git = 'https://github.com/tonlabs/TVM-linker.git', tag = '0.20.3' } +ton_abi = { git = 'https://github.com/tonlabs/ever-abi.git', tag = '2.3.129' } +ton_block = { git = 'https://github.com/tonlabs/ever-block.git', tag = '1.9.88' } +ton_types = { git = 'https://github.com/tonlabs/ever-types.git', tag = '2.0.18' } +tvm_linker = { git = 'https://github.com/tonlabs/TVM-linker.git', tag = '0.20.4' } [build-dependencies] cmake = '0.1' diff --git a/sold/build.rs b/sold/build.rs index 0c3e1969..941a3b2f 100644 --- a/sold/build.rs +++ b/sold/build.rs @@ -1,5 +1,5 @@ /* - * Copyright 2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use * this file except in compliance with the License. @@ -7,8 +7,7 @@ * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific TON DEV software governing permissions and - * limitations under the License. + * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ use std::process::Command; diff --git a/sold/src/lib.rs b/sold/src/lib.rs index 2b1ef4bc..d4b94431 100644 --- a/sold/src/lib.rs +++ b/sold/src/lib.rs @@ -450,7 +450,7 @@ impl fmt::Display for TvmVersion { } #[derive(Parser, Debug)] -#[clap(author, about = "sold, the Ever Solidity commandline driver", long_about = None)] +#[clap(author, about = "sold, the TVM Solidity commandline driver", long_about = None)] #[clap(arg_required_else_help = true)] #[clap(version = VERSION.get().unwrap().as_str())] pub struct Args { diff --git a/sold/src/libsolc.rs b/sold/src/libsolc.rs index 4eb05008..207ef692 100644 --- a/sold/src/libsolc.rs +++ b/sold/src/libsolc.rs @@ -1,5 +1,5 @@ /* - * Copyright 2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use * this file except in compliance with the License. @@ -7,8 +7,7 @@ * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific TON DEV software governing permissions and - * limitations under the License. + * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ #![allow(non_upper_case_globals)] diff --git a/sold/src/main.rs b/sold/src/main.rs index 13c4e813..c0780d1c 100644 --- a/sold/src/main.rs +++ b/sold/src/main.rs @@ -1,5 +1,5 @@ /* - * Copyright 2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use * this file except in compliance with the License. @@ -7,8 +7,7 @@ * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific TON DEV software governing permissions and - * limitations under the License. + * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ use clap::Parser; diff --git a/sold/src/printer.rs b/sold/src/printer.rs index b37b8952..22b2957f 100644 --- a/sold/src/printer.rs +++ b/sold/src/printer.rs @@ -1,5 +1,5 @@ /* - * Copyright 2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use * this file except in compliance with the License. @@ -7,8 +7,7 @@ * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific TON DEV software governing permissions and - * limitations under the License. + * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ use std::fs::File; diff --git a/sold/tests/tests.rs b/sold/tests/tests.rs index ecffa2f9..cd006523 100644 --- a/sold/tests/tests.rs +++ b/sold/tests/tests.rs @@ -1,5 +1,5 @@ /* - * Copyright 2022 TON DEV SOLUTIONS LTD. + * Copyright (C) 2019-2023 EverX. All Rights Reserved. * * Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use * this file except in compliance with the License. @@ -7,8 +7,7 @@ * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific TON DEV software governing permissions and - * limitations under the License. + * See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html */ use predicates::prelude::*;