diff --git a/API.md b/API.md
index 21b2275d..c87e8263 100644
--- a/API.md
+++ b/API.md
@@ -162,6 +162,17 @@ When deploying contracts, you should use the latest released version of Solidity
* [\
.isNone()](#addressisnone)
* [\.unpack()](#addressunpack)
* [\.transfer()](#addresstransfer)
+ * [address_std](#address_std)
+ * [address_std.makeAddrStd()](#address_stdmakeaddrstd)
+ * [address_std.addrNone](#address_stdaddrnone)
+ * [\.wid](#address_stdwid)
+ * [\.value](#address_stdvalue)
+ * [\.getType()](#address_stdgettype)
+ * [\.isStdZero()](#address_stdisstdzero)
+ * [\.isStdAddrWithoutAnyCast()](#address_stdisstdaddrwithoutanycast)
+ * [\.isNone()](#address_stdisnone)
+ * [\.unpack()](#address_stdunpack)
+ * [\.transfer()](#address_stdtransfer)
* [mapping](#mapping)
* [Keyword `emptyMap`](#keyword-emptymap)
* [\.operator[]](#mappingoperator)
@@ -204,6 +215,7 @@ When deploying contracts, you should use the latest released version of Solidity
* [Keyword `nostorage`](#keyword-nostorage)
* [Keyword `public`](#keyword-public)
* [Special contract functions](#special-contract-functions)
+ * [getter](#getter)
* [receive](#receive)
* [fallback](#fallback)
* [onBounce](#onbounce)
@@ -1802,7 +1814,7 @@ Returns "non-quiet" integer. If `` is `NaN`, then throws an exception. `T` is
function f(quint32 a, quint32 b) private pure {
quint32 s = a + b;
if (!s.isNaN()) {
- uint32 ss = s.get();
+ uint32 sum = s.get();
// ...
}
}
@@ -1819,7 +1831,7 @@ Returns "non-quiet" integer. If `` is `NaN`, then returns `default`. `T` is `
```TVMSolidity
function f(quint32 a, quint32 b) private pure {
quint32 s = a + b;
- uint32 ss = s.getOr(42); // ss is equal to `a + b` or 42
+ uint32 sum = s.getOr(42); // sum is equal to `a + b` or 42
// ...
}
```
@@ -1835,7 +1847,7 @@ Returns "non-quiet" integer. If `` is `NaN`, then returns default value. `T`
```TVMSolidity
function f(quint32 a, quint32 b) private pure {
quint32 s = a + b;
- uint32 ss = s.getOrDefault(); // ss is equal to `a + b` or 0
+ uint32 sum = s.getOrDefault(); // sum is equal to `a + b` or 0
// ...
}
```
@@ -1851,7 +1863,7 @@ Returns optional integer. If `` is `NaN`, then returns [null](#keyword-null).
```TVMSolidity
function f(quint32 a, quint32 b) private pure {
quint32 s = a + b;
- optional(uint32) ss = s.toOptional(); // ss is equal to `a + b` or null
+ optional(uint32) sum = s.toOptional(); // sum is equal to `a + b` or null
// ...
}
```
@@ -2249,7 +2261,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 ever;
+coins a = 1 ever;
str = format("{:t}", a); // str == "1.000000000"
a = 123;
str = format("{:t}", a); // str == "0.000000123"
@@ -2298,8 +2310,8 @@ 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**. TVM Solidity compiler expands `address` type with the following
+`address` represents different types of TVM addresses: [**addr_none**, **addr_extern**,
+**addr_std** and **addr_var**](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L100C1-L100C10). TVM Solidity compiler expands `address` type with the following
members and functions:
##### Object creating
@@ -2307,7 +2319,7 @@ members and functions:
##### constructor()
```TVMSolidity
-uint address_value;
+uint address_value = ...;
address addrStd = address(address_value);
```
@@ -2316,9 +2328,9 @@ Constructs `address` of type **addr_std** with zero workchain id and given addre
##### address.makeAddrStd()
```TVMSolidity
-int8 wid;
-uint address;
-address addrStd = address.makeAddrStd(wid, address);
+int8 wid = ...;
+uint value = ...;
+address addrStd = address.makeAddrStd(wid, value);
```
Constructs `address` of type **addr_std** with given workchain id **wid** and value **address_value**.
@@ -2380,13 +2392,14 @@ Returns currencies on the balance of the current contract account.
##### \.getType()
```TVMSolidity
-.getType() returns (uint8);
+.getType() returns (uint4);
```
Returns type of the `address`:
-0 - **addr_none**
-1 - **addr_extern**
-2 - **addr_std**
+ * 0 - `addr_none`
+ * 1 - `addr_extern`
+ * 2 - `addr_std`
+ * 3 - `addr_var`
##### \.isStdZero()
@@ -2488,7 +2501,7 @@ In order to clarify flags usage see [this sample](https://github.com/everx-labs/
```TVMSolidity
address dest = ...;
-uint128 value = ...;
+coins value = ...;
bool bounce = ...;
uint16 flag = ...;
TvmCell body = ...;
@@ -2510,6 +2523,102 @@ See example of `address.transfer()` usage:
* [giver](https://github.com/everx-labs/samples/blob/master/solidity/7_Giver.sol)
+#### address_std
+
+`address_std` type is same as [address](#address) but can be [addr_std or addr_none](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb#L100C1-L100C10).
+
+```TVMSolidity
+uint address_value = ...;
+address_std addrStd = address_std(address_value);
+```
+
+Constructs `address_std` of type **addr_std** with zero workchain id and given value.
+
+##### address_std.makeAddrStd()
+
+```TVMSolidity
+int8 wid;
+uint value;
+address_std addrStd = address.makeAddrStd(wid, value);
+```
+
+Constructs `address_std` of type **addr_std** with given workchain id **wid** and value **address_value**.
+
+##### address_std.addrNone
+
+```TVMSolidity
+address_std addrNone = address_std.addrNone;
+```
+
+Constructs `address_std` of type **addr_none**.
+
+##### \.wid
+
+```TVMSolidity
+.wid returns (int8);
+```
+
+Returns the workchain id of **addr_std**. Throws "range check error" [exception](#tvm-exception-codes) for other `address_std` types.
+
+##### \.value
+
+```TVMSolidity
+.value returns (uint);
+```
+
+Returns the `address_std` value of **addr_std**. Throws "range check error" [exception](#tvm-exception-codes) for other `address_std` types.
+
+
+##### \.getType()
+
+```TVMSolidity
+.getType() returns (uint4);
+```
+
+Returns type of the `address_std`:
+* 0 - `addr_none`
+* 2 - `addr_std`
+
+##### \.isStdZero()
+
+```TVMSolidity
+.isStdZero() returns (bool);
+```
+
+Returns the result of comparison between this `address` with zero `address` of type **addr_std**.
+
+##### \.isStdAddrWithoutAnyCast()
+
+```TVMSolidity
+.isStdAddrWithoutAnyCast() returns (bool);
+```
+
+Checks whether this `address_std` is of type **addr_std** without any cast.
+
+##### \.isNone()
+
+```TVMSolidity
+.isNone() returns (bool);
+```
+
+Checks whether this `address_std` is of type **addr_none**.
+
+##### \.unpack()
+
+```TVMSolidity
+.unpack() returns (int8 /*wid*/, uint256 /*value*/);
+```
+
+Same as [\.unpack()](#addressunpack)
+
+##### \.transfer()
+
+```TVMSolidity
+.transfer(varuint16 value, bool bounce, uint16 flag, TvmCell body, mapping(uint32 => varuint32) currencies, TvmCell stateInit);
+```
+
+Same as [\.transfer()](#addresstransfer)
+
#### mapping
TVM Solidity compiler expands `mapping` type with the following functions. In examples
@@ -3187,6 +3296,31 @@ contract C {
### Special contract functions
+#### getter
+
+Smart-contract `getter` function is a function that can be called only off-chain. Keyword `getter` is used to mark such functions. `getter` function can not be called on-chain (either external/internal message or onTickTock transaction). They specifically designed to read some data from smart-contracts off-chain. Example:
+
+```TVMSolidity
+contract C {
+
+ address_std m_address;
+ mapping(uint64 => uint8) m_values;
+
+ function get_address() getter returns (address_std) {
+ return m_address;
+ }
+
+ function get_value(uint key) getter returns (uint8) {
+ return m_values.contains(key) ? m_values.at(key) : 255;
+ }
+}
+```
+
+Use `ever-cli run` to call getter function. Example:
+```bash
+ever-cli -j run --abi test_getter_2.abi.json get_value '{"key": 10}'`
+```
+
#### receive
`receive` function is called in two cases:
@@ -5129,7 +5263,14 @@ contract ContractCreator {
##### abi.decodeData()
```TVMSolidity
-abi.decodeData(ContractName, TvmSlice) returns (uint256 /*pubkey*/, uint64 /*timestamp*/, bool /*constructorFlag*/, Type1 /*var1*/, Type2 /*var2*/, ...);
+abi.decodeData(ContractName, TvmSlice) returns (
+ uint256 /*pubkey*/,
+ uint64 /*timestamp*/,
+ bool /*constructorFlag*/,
+ Type1 /*var1*/,
+ Type2 /*var2*/,
+ ...
+);
```
Loads state variables from `TvmSlice` that is obtained from the field `data` of `stateInit`.
@@ -5138,31 +5279,31 @@ Example:
```
contract A {
- uint a = 111;
- uint b = 22;
- uint c = 3;
- uint d = 44;
- address e = address(12);
- address f;
+ uint a = 111;
+ uint b = 22;
+ uint c = 3;
+ uint d = 44;
+ address e = address(12);
+ address f;
+ constructor() {}
}
contract B {
- function f(TvmCell data) public pure {
- TvmSlice s = data.toSlice();
- (uint256 pubkey, uint64 timestamp, bool flag,
- uint a, uint b, uint c, uint d, address e, address f) = abi.decodeData(A, s);
-
- // pubkey - pubkey of the contract A
- // timestamp - timestamp that used for replay protection
- // flag - always is equal to true
- // a == 111
- // b == 22
- // c == 3
- // d == 44
- // e == address(12)
- // f == address.addrNone
- // s.empty()
- }
+ function f(TvmCell data) public pure {
+ TvmSlice s = data.toSlice();
+ (uint256 pubkey, uint64 timestamp, bool flag,
+ uint a, uint b, uint c, uint d, address e, address f) = abi.decodeData(A, s);
+
+ // pubkey - pubkey of the contract A
+ // timestamp - timestamp that used for replay protection
+ // flag - constructor flag is set if the contract is deployed
+ // a == 111
+ // b == 22
+ // c == 3
+ // d == 44
+ // e == address(12)
+ // f == address.addrNone
+ }
}
```
@@ -5262,7 +5403,7 @@ function mechanics.
```TVMSolidity
abi.encodeBody(function, arg0, arg1, arg2, ...) returns (TvmCell);
abi.encodeBody(function, callbackFunction, arg0, arg1, arg2, ...) returns (TvmCell);
-abi.encodeBody(contract, arg0, arg1, arg2, ...) returns (TvmCell);
+abi.encodeBody(ContractName, arg0, arg1, arg2, ...) returns (TvmCell);
```
Constructs a message body for the function call. Body can be used as a payload for [\.transfer()](#addresstransfer).
@@ -5376,20 +5517,32 @@ See example of how to use this function:
##### abi.encodeIntMsg()
```TVMSolidity
+// (1)
abi.encodeIntMsg({
dest: address,
- value: uint128,
+ value: coins,
call: {function, [callbackFunction,] arg0, arg1, arg2, ...},
bounce: bool,
currencies: mapping(uint32 => varuint32),
stateInit: TvmCell
})
returns (TvmCell);
+
+// (2)
+abi.encodeIntMsg({
+ dest: address,
+ value: coins,
+ call: {ContractName, arg0, arg1, arg2, ...},
+ bounce: bool,
+ currencies: mapping(uint32 => varuint32),
+ stateInit: TvmCell
+})
+returns (TvmCell);
```
-Generates an internal outbound message that contains a function call. The result `TvmCell` can be used to send a
-message using [tvm.sendrawmsg()](#tvmsendrawmsg). If the `function` is `responsible`, then
-`callbackFunction` parameter must be set.
+Generates an internal outbound message that contains a function (1) or constructor (2) call.
+The result `TvmCell` can be used to send a message using [tvm.sendrawmsg()](#tvmsendrawmsg).
+If the `function` is `responsible`, then `callbackFunction` parameter must be set.
`dest`, `value` and `call` parameters are mandatory. Another parameters can be omitted. See
[\.transfer()](#addresstransfer) where these options and their default values are
diff --git a/Cargo.lock b/Cargo.lock
index 3bb67f4a..540c9834 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -60,9 +60,9 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.6.14"
+version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
+checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -75,33 +75,33 @@ dependencies = [
[[package]]
name = "anstyle"
-version = "1.0.7"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
+checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56"
[[package]]
name = "anstyle-parse"
-version = "0.2.4"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
-version = "1.1.0"
+version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.3"
+version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
+checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
dependencies = [
"anstyle",
"windows-sys",
@@ -109,19 +109,20 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.86"
+version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8"
[[package]]
name = "assert_cmd"
-version = "2.0.14"
+version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8"
+checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d"
dependencies = [
"anstyle",
"bstr",
"doc-comment",
+ "libc",
"predicates",
"predicates-core",
"predicates-tree",
@@ -141,9 +142,9 @@ dependencies = [
[[package]]
name = "autocfg"
-version = "1.3.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "base64"
@@ -168,9 +169,9 @@ dependencies = [
[[package]]
name = "blst"
-version = "0.3.12"
+version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62dc83a094a71d43eeadd254b1ec2d24cb6a0bb6cadce00df51f0db594711a32"
+checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874"
dependencies = [
"cc",
"glob",
@@ -180,9 +181,9 @@ dependencies = [
[[package]]
name = "bstr"
-version = "1.9.1"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
+checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c"
dependencies = [
"memchr",
"regex-automata",
@@ -203,9 +204,12 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
-version = "1.1.5"
+version = "1.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052"
+checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f"
+dependencies = [
+ "shlex",
+]
[[package]]
name = "cfg-if"
@@ -238,9 +242,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.9"
+version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462"
+checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
dependencies = [
"clap_builder",
"clap_derive",
@@ -248,9 +252,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.9"
+version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942"
+checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
dependencies = [
"anstream",
"anstyle",
@@ -260,9 +264,9 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.5.8"
+version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
+checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
"heck",
"proc-macro2",
@@ -272,24 +276,24 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "0.7.1"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
+checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
[[package]]
name = "cmake"
-version = "0.1.50"
+version = "0.1.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
+checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a"
dependencies = [
"cc",
]
[[package]]
name = "colorchoice"
-version = "1.0.1"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "const-oid"
@@ -299,15 +303,15 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "core-foundation-sys"
-version = "0.8.6"
+version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "cpufeatures"
-version = "0.2.12"
+version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
+checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
dependencies = [
"libc",
]
@@ -407,9 +411,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "dunce"
-version = "1.0.4"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
+checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
name = "ed25519"
@@ -438,8 +442,8 @@ dependencies = [
[[package]]
name = "ever_abi"
-version = "2.6.1"
-source = "git+https://github.com/everx-labs/ever-abi.git?tag=2.6.1#9b789948eb3d9be16b080c7c29453cce0be25f15"
+version = "2.7.2"
+source = "git+https://github.com/everx-labs/ever-abi.git?tag=2.7.2#70f946130a68db322fa7fe735c77e5998c4fefb4"
dependencies = [
"anyhow",
"byteorder",
@@ -456,8 +460,8 @@ dependencies = [
[[package]]
name = "ever_assembler"
-version = "1.6.3"
-source = "git+https://github.com/everx-labs/ever-assembler.git?tag=1.6.3#a663b51ca018fec1af8c499cf5ffd5f0670e10dd"
+version = "1.6.14"
+source = "git+https://github.com/everx-labs/ever-assembler.git?tag=1.6.14#0569ad4c246813f3b3f2db27b427c67afd23e8e9"
dependencies = [
"anyhow",
"clap",
@@ -474,8 +478,8 @@ dependencies = [
[[package]]
name = "ever_block"
-version = "1.11.0"
-source = "git+https://github.com/everx-labs/ever-block.git?tag=1.11.0#c4d06d5e033897134aac6b54ee077b87775a35b4"
+version = "1.11.11"
+source = "git+https://github.com/everx-labs/ever-block.git?tag=1.11.11#5d617e2f0a8f7ec2b3e0aab9167280260a5ad7f2"
dependencies = [
"aes-ctr",
"anyhow",
@@ -504,8 +508,8 @@ dependencies = [
[[package]]
name = "ever_vm"
-version = "2.2.1"
-source = "git+https://github.com/everx-labs/ever-vm.git?tag=2.2.1#280daf4d22a04e108881951e32926ed925be86e5"
+version = "2.2.12"
+source = "git+https://github.com/everx-labs/ever-vm.git?tag=2.2.12#ebd07bab74de939cfc71b1f56aa314cb58695318"
dependencies = [
"anyhow",
"ever_block",
@@ -596,9 +600,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "iana-time-zone"
-version = "0.1.60"
+version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@@ -619,9 +623,9 @@ dependencies = [
[[package]]
name = "is_terminal_polyfill"
-version = "1.70.0"
+version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "itoa"
@@ -631,9 +635,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
-version = "0.3.69"
+version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
+checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
dependencies = [
"wasm-bindgen",
]
@@ -646,14 +650,14 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
-version = "0.2.155"
+version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
+checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]]
name = "lockfree"
-version = "0.5.1"
-source = "git+https://github.com/everx-labs/lockfree.git#bfcb66587dc4ffed9e8e9248995ad2fe8dc3669e"
+version = "0.5.2"
+source = "git+https://github.com/everx-labs/lockfree.git#2a30df72944ed48255a97defcd387dd4962f3dd5"
dependencies = [
"owned-alloc",
]
@@ -772,9 +776,9 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.19.0"
+version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "opaque-debug"
@@ -800,15 +804,18 @@ dependencies = [
[[package]]
name = "ppv-lite86"
-version = "0.2.17"
+version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
+dependencies = [
+ "zerocopy",
+]
[[package]]
name = "predicates"
-version = "3.1.0"
+version = "3.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8"
+checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97"
dependencies = [
"anstyle",
"difflib",
@@ -820,15 +827,15 @@ dependencies = [
[[package]]
name = "predicates-core"
-version = "1.0.6"
+version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174"
+checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931"
[[package]]
name = "predicates-tree"
-version = "1.0.9"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf"
+checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13"
dependencies = [
"predicates-core",
"termtree",
@@ -836,18 +843,18 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.86"
+version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
+checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.36"
+version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
@@ -884,9 +891,9 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.10.5"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
@@ -896,9 +903,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.7"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
dependencies = [
"aho-corasick",
"memchr",
@@ -907,15 +914,15 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.8.4"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rustc_version"
-version = "0.4.0"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
@@ -934,18 +941,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]]
name = "serde"
-version = "1.0.204"
+version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
+checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.204"
+version = "1.0.214"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
+checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
dependencies = [
"proc-macro2",
"quote",
@@ -954,11 +961,12 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.120"
+version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
+checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
dependencies = [
"itoa",
+ "memchr",
"ryu",
"serde",
]
@@ -974,6 +982,12 @@ dependencies = [
"digest",
]
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
[[package]]
name = "signature"
version = "2.2.0"
@@ -991,7 +1005,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "sold"
-version = "0.76.0"
+version = "0.77.0"
dependencies = [
"anyhow",
"assert_cmd",
@@ -1042,9 +1056,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
-version = "2.0.71"
+version = "2.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462"
+checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
dependencies = [
"proc-macro2",
"quote",
@@ -1059,18 +1073,18 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
[[package]]
name = "thiserror"
-version = "1.0.63"
+version = "1.0.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
+checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.63"
+version = "1.0.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
+checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602"
dependencies = [
"proc-macro2",
"quote",
@@ -1094,9 +1108,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-ident"
-version = "1.0.12"
+version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "utf8parse"
@@ -1106,9 +1120,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "version_check"
-version = "0.9.4"
+version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "vte"
@@ -1147,19 +1161,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.92"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
+checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
dependencies = [
"cfg-if",
+ "once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.92"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
+checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
dependencies = [
"bumpalo",
"log",
@@ -1172,9 +1187,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.92"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
+checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1182,9 +1197,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.92"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
+checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
@@ -1195,9 +1210,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.92"
+version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
+checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
[[package]]
name = "winapi"
@@ -1232,9 +1247,9 @@ dependencies = [
[[package]]
name = "windows-sys"
-version = "0.52.0"
+version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
@@ -1315,6 +1330,27 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "zerocopy"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "zeroize"
version = "1.8.1"
diff --git a/Changelog.md b/Changelog.md
index 7467d724..b4474658 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,26 @@
+### 0.77.0 (2024-10-31)
+
+Bugfixes:
+ * Fixed wrong type conversion. For example: conversion from `stack(varuint)` to `stack(varint)` was supported. But now
+it's an error.
+ * Type checker: `abi.decodeData()` function could take any type for 2d parameter.
+ * [format()](API.md#format) threw an exception for non `addr_std` address. See [issues #168](https://github.com/everx-labs/TVM-Solidity-Compiler/issues/168).
+Now [format()](API.md#format) can take address of any type.
+ * Fixed bug when you iterate over array of mapping. See [issues #169](https://github.com/everx-labs/TVM-Solidity-Compiler/issues/169).
+ * Fixed bug when overloading inline function. See [issues #167](https://github.com/everx-labs/TVM-Solidity-Compiler/issues/167).
+ * Fixed compilation failure on formatted output pattern. See [issues #166](https://github.com/everx-labs/TVM-Solidity-Compiler/issues/166).
+
+Compiler features:
+ * Supported [ABI 2.7](https://github.com/everx-labs/ever-abi/blob/master/CHANGELOG.md#version-270)
+ * Supported [getters](API.md#getter).
+ * Supported [address_std](API.md#address_std) type.
+ * Supported encoding internal message to call constructor. See option 2 [abi.encodeIntMsg()](API.md#abiencodeintmsg).
+
+Optimizations:
+ * optimized decoding function parameters if the function marked as `externalMsg` or `internalMsg`.
+
+Function [\.getType()](API.md#addressgettype) now returns `uint4` instead of `uint8`.
+
### 0.76.0 (2024-07-18)
Compiler features:
diff --git a/README.md b/README.md
index a4098ce8..967e8a85 100644
--- a/README.md
+++ b/README.md
@@ -57,7 +57,7 @@ cmake --build . --config Release -- /m
* [Code samples](https://github.com/everx-labs/samples/tree/master/solidity) in TVM Solidity
* [ever-cli](https://github.com/everx-labs/ever-cli) command line interface for TVM compatible blockchains
* Example of usage `ever-cli` for working (deploying, calling 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/everx-labs/TVM-Solidity-Compiler/blob/master/Changelog_TON.md)
+ * [Changelog](./Changelog.md)
## License
[GNU GENERAL PUBLIC LICENSE Version 3](./LICENSE)
diff --git a/compiler/CMakeLists.txt b/compiler/CMakeLists.txt
index 20815f8a..e841a083 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.76.0")
+set(PROJECT_VERSION "0.77.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/liblangutil/Token.h b/compiler/liblangutil/Token.h
index 35f415ee..cc6b11af 100644
--- a/compiler/liblangutil/Token.h
+++ b/compiler/liblangutil/Token.h
@@ -182,6 +182,7 @@ namespace solidity::langutil
K(Override, "override", 0) \
K(Payable, "payable", 0) \
K(Public, "public", 0) \
+ K(Getter, "getter", 0) \
K(Pragma, "pragma", 0) \
K(Private, "private", 0) \
K(Pure, "pure", 0) \
@@ -244,6 +245,7 @@ namespace solidity::langutil
K(Bytes, "bytes", 0) \
K(String, "string", 0) \
K(Address, "address", 0) \
+ K(AddressStd, "address_std", 0) \
K(Bool, "bool", 0) \
K(TvmCell, "TvmCell", 0) \
K(TvmSlice, "TvmSlice", 0) \
@@ -368,7 +370,7 @@ namespace TokenTraits
constexpr bool isVariableVisibilitySpecifier(Token op) {
return op == Token::Public || op == Token::Private || op == Token::Internal;
}
- constexpr bool isVisibilitySpecifier(Token op) { return isVariableVisibilitySpecifier(op) || op == Token::External; }
+ constexpr bool isVisibilitySpecifier(Token op) { return isVariableVisibilitySpecifier(op) || op == Token::External || op == Token::Getter; }
constexpr bool isStateMutabilitySpecifier(Token op)
{
diff --git a/compiler/libsolidity/analysis/TypeChecker.cpp b/compiler/libsolidity/analysis/TypeChecker.cpp
index 2b43f488..1b39e43f 100644
--- a/compiler/libsolidity/analysis/TypeChecker.cpp
+++ b/compiler/libsolidity/analysis/TypeChecker.cpp
@@ -427,6 +427,7 @@ TypePointers TypeChecker::checkSliceDecode(std::vector(curType);
auto intKey = to(mappingType->keyType());
- auto addrKey = to(mappingType->keyType());
- if (intKey == nullptr && addrKey == nullptr) {
+ auto addrKey = isIn(mappingType->keyType()->category(), Type::Category::Address, Type::Category::AddressStd);
+ if (intKey == nullptr && !addrKey) {
printError(
"Key type of the mapping must be "
"any of int/uint types with M from 8 to 256 or std address.");
@@ -691,6 +693,7 @@ bool TypeChecker::isBadAbiType(
}
case Type::Category::Address:
+ case Type::Category::AddressStd:
case Type::Category::Bool:
case Type::Category::Contract:
case Type::Category::Enum:
@@ -980,6 +983,7 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
auto mapType = dynamic_cast(varType);
switch (mapType->keyType()->category()) {
case Type::Category::Address:
+ case Type::Category::AddressStd:
case Type::Category::Array: // usual arrays (e.g. uint[]) are checked in another place
case Type::Category::Bool:
case Type::Category::Contract:
@@ -2315,6 +2319,7 @@ TypeChecker::Result TypeChecker::canStoreToBuilder(Type const* type, bool _topTy
case Type::Category::TvmSlice:
return {_topType, std::nullopt};
case Type::Category::Address:
+ case Type::Category::AddressStd:
case Type::Category::Array:
case Type::Category::Bool:
case Type::Category::Contract:
@@ -2383,6 +2388,7 @@ void TypeChecker::checkStoreQ(Expression const& _argument) {
}
case Type::Category::TvmCell:
case Type::Category::Address:
+ case Type::Category::AddressStd:
case Type::Category::Contract:
case Type::Category::TvmSlice:
case Type::Category::Integer:
@@ -2530,17 +2536,14 @@ TypeChecker::getFunctionDefinition(Expression const* expr) {
return dynamic_cast(declaration);
}
-std::pair
+std::pair
TypeChecker::getConstructorDefinition(Expression const* expr) {
- auto contractType = getContractType(expr);
- if (contractType == nullptr) {
- return {};
- }
- FunctionDefinition const* constr = contractType->contractDefinition().constructor();
- if (constr == nullptr) {
- return {true, nullptr};
+ ContractType const* contractType = getContractType(expr);
+ FunctionDefinition const* constr{};
+ if (contractType != nullptr) {
+ constr = contractType->contractDefinition().constructor();
}
- return {true, constr};
+ return {contractType, constr};
}
ContractType const* TypeChecker::getContractType(Expression const* expr) {
@@ -2789,20 +2792,21 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
std::vector> const& argumentNames = _functionCall.names();
bool isFunctionWithDefaultValues = false;
{
- auto ma = dynamic_cast(&_functionCall.expression());
- if (ma && ma->memberName() == "transfer" && dynamic_cast(ma->expression().annotation().type)) {
- isFunctionWithDefaultValues = true;
- }
- if (ma && dynamic_cast(ma->expression().annotation().type)) {
- if (ma->memberName() == "encodeStateInit" ||
- ma->memberName() == "buildStateInit" ||
- ma->memberName() == "buildDataInit" ||
- ma->memberName() == "encodeData" ||
- ma->memberName() == "encodeOldDataInit" ||
- ma->memberName() == "buildExtMsg" ||
- ma->memberName() == "encodeIntMsg" ||
- ma->memberName() == "buildIntMsg")
- isFunctionWithDefaultValues = true;
+ if (auto ma = dynamic_cast(&_functionCall.expression())) {
+ auto category = ma->expression().annotation().type->category();
+ if (ma->memberName() == "transfer" && (category == Type::Category::Address || category == Type::Category::AddressStd))
+ isFunctionWithDefaultValues = true;
+ if (dynamic_cast(ma->expression().annotation().type)) {
+ if (ma->memberName() == "encodeStateInit" ||
+ ma->memberName() == "buildStateInit" ||
+ ma->memberName() == "buildDataInit" ||
+ ma->memberName() == "encodeData" ||
+ ma->memberName() == "encodeOldDataInit" ||
+ ma->memberName() == "buildExtMsg" ||
+ ma->memberName() == "encodeIntMsg" ||
+ ma->memberName() == "buildIntMsg")
+ isFunctionWithDefaultValues = true;
+ }
}
}
@@ -3144,7 +3148,7 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
}
FunctionDefinition const*
-TypeChecker::checkPubFunctionAndGetDefinition(Expression const& arg, bool printError) {
+TypeChecker::checkPubFunctionAndGetDefinition(Expression const& arg, bool printError) const {
FunctionDefinition const* funcDef = getFunctionDefinition(&arg);
if (funcDef) {
if (!funcDef->isPublic()) {
@@ -3170,28 +3174,36 @@ TypeChecker::checkPubFunctionAndGetDefinition(Expression const& arg, bool printE
}
FunctionDefinition const*
-TypeChecker::checkPubFunctionOrContractTypeAndGetDefinition(Expression const& arg) {
- FunctionDefinition const* funcDef = checkPubFunctionAndGetDefinition(arg);
+TypeChecker::checkPubFunctionOrContractTypeAndGetDefinition(Expression const& arg) const {
+ FunctionDefinition const* funcDef = checkPubFunctionAndGetDefinition(arg, false);
if (funcDef) {
return funcDef;
}
- const auto &[isContract, constructorDef] = getConstructorDefinition(&arg);
- if (!isContract) {
+ const auto &[contract, constructorDef] = getConstructorDefinition(&arg);
+ if (contract == nullptr) {
m_errorReporter.fatalTypeError(
4974_error,
arg.location(),
- "Function or contract type required, but " +
+ "Expected function or contract type, but " +
type(arg)->toString(true) +
" provided."
);
+ } else if (constructorDef == nullptr) {
+ m_errorReporter.typeError(
+ 2672_error,
+ arg.location(),
+ SecondarySourceLocation()
+ .append("Contract definition is here:", contract->contractDefinition().location()),
+ "Contract has no constructor."
+ );
}
return constructorDef;
}
void TypeChecker::checkInitList(InitializerList const* list, ContractType const& ct,
- langutil::SourceLocation const& _functionCallLocation
-) {
+ SourceLocation const& _functionCallLocation
+) const {
std::vector stateVariables;
for (auto const &[v, _, ___] : ct.stateVariables()) {
boost::ignore_unused(_);
@@ -3716,7 +3728,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::TVMSlicePreloadQ:
{
checkAtLeastOneArg();
- TypePointers members = checkSliceDecode(_functionCall.arguments()); // TODO make for Q
+ TypePointers members = checkSliceDecodeQ(_functionCall.arguments());
if (members.size() == 1)
returnTypes = TypePointers{TypeProvider::optional(members.at(0))};
else
@@ -3736,7 +3748,8 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
std::string("Expected two arguments.")
);
}
- FunctionDefinition const* functionDeclaration = checkPubFunctionOrContractTypeAndGetDefinition(*arguments.front().get());
+ FunctionDefinition const* functionDeclaration =
+ checkPubFunctionOrContractTypeAndGetDefinition(*arguments.front().get());
if (functionDeclaration != nullptr) { // if nullptr => default constructor
if (functionDeclaration->isResponsible()) {
returnTypes.push_back(TypeProvider::uint(32)); // callback function
@@ -3758,7 +3771,8 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
std::string("Expected one argument.")
);
}
- FunctionDefinition const* functionDeclaration = checkPubFunctionOrContractTypeAndGetDefinition(*arguments.front().get());
+ FunctionDefinition const* functionDeclaration =
+ checkPubFunctionOrContractTypeAndGetDefinition(*arguments.front().get());
if (functionDeclaration != nullptr) { // if nullptr => default constructor
if (functionDeclaration->isResponsible()) {
returnTypes.push_back(TypeProvider::uint(32)); // callback function
@@ -3811,6 +3825,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
_functionCall.location(),
std::string("Expected two arguments.")
);
+ expectType(*arguments.at(1), *TypeProvider::tvmslice(), false);
}
else if (functionType->kind() == FunctionType::Kind::TVMSliceLoadStateVars)
{
@@ -4082,7 +4097,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
returnTypes = functionType->returnParameterTypes();
break;
}
- case FunctionType::Kind::ABIBuildIntMsg: {
+ case FunctionType::Kind::ABIEncodeIntMsg: {
checkHasNamedParams();
for (const std::string name : {"dest", "call", "value"}) {
@@ -4100,11 +4115,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
int index = findName("call");
index != -1
) {
- auto callList = dynamic_cast(arguments.at(index).get());
- if (callList) {
- // now, we ignore constructor call, because in this case we must set stateInit
- checkPubFunctionAndGetDefinition(*callList->function(), true);
-
+ if (auto callList = dynamic_cast(arguments.at(index).get())) {
std::vector params;
params.push_back(callList->function());
for (const ASTPointer & p : callList->arguments()) {
diff --git a/compiler/libsolidity/analysis/TypeChecker.h b/compiler/libsolidity/analysis/TypeChecker.h
index e2500124..cbc12539 100644
--- a/compiler/libsolidity/analysis/TypeChecker.h
+++ b/compiler/libsolidity/analysis/TypeChecker.h
@@ -146,12 +146,12 @@ class TypeChecker: private ASTConstVisitor
void checkStoreQ(Expression const& _argument);
void typeCheckTvmEncodeFunctions(FunctionCall const& _functionCall);
static FunctionDefinition const* getFunctionDefinition(Expression const* expr);
- static std::pair getConstructorDefinition(Expression const* expr);
+ static std::pair getConstructorDefinition(Expression const* expr);
static ContractType const* getContractType(Expression const* expr);
- FunctionDefinition const* checkPubFunctionAndGetDefinition(Expression const& arg, bool printError = false);
- FunctionDefinition const* checkPubFunctionOrContractTypeAndGetDefinition(Expression const& arg);
+ FunctionDefinition const* checkPubFunctionAndGetDefinition(Expression const& arg, bool printError = false) const;
+ FunctionDefinition const* checkPubFunctionOrContractTypeAndGetDefinition(Expression const& arg) const;
void checkInitList(InitializerList const* list, ContractType const& ct,
- langutil::SourceLocation const& _functionCallLocation);
+ langutil::SourceLocation const& _functionCallLocation) const;
void checkCallList(
std::vector const& arguments,
FunctionCall const& _functionCall,
diff --git a/compiler/libsolidity/analysis/ViewPureChecker.cpp b/compiler/libsolidity/analysis/ViewPureChecker.cpp
index 1366a734..27e78892 100644
--- a/compiler/libsolidity/analysis/ViewPureChecker.cpp
+++ b/compiler/libsolidity/analysis/ViewPureChecker.cpp
@@ -82,7 +82,8 @@ void ViewPureChecker::endVisit(FunctionDefinition const& _funDef)
!_funDef.isFallback() &&
!_funDef.isReceive() &&
!_funDef.virtualSemantics() &&
- !_funDef.isInlineAssembly()
+ !_funDef.isInlineAssembly() &&
+ _funDef.visibility() != Visibility::Getter
)
m_errorReporter.warning(
2018_error,
diff --git a/compiler/libsolidity/ast/AST.cpp b/compiler/libsolidity/ast/AST.cpp
index 9e71380f..9221938a 100644
--- a/compiler/libsolidity/ast/AST.cpp
+++ b/compiler/libsolidity/ast/AST.cpp
@@ -435,6 +435,7 @@ FunctionTypePointer FunctionDefinition::functionType(bool _internal) const
switch (visibility())
{
case Visibility::Default:
+ case Visibility::Getter:
solAssert(false, "visibility() should not return Default");
case Visibility::Private:
case Visibility::Internal:
@@ -455,6 +456,7 @@ FunctionTypePointer FunctionDefinition::functionType(bool _internal) const
return {};
case Visibility::Public:
case Visibility::External:
+ case Visibility::Getter:
return TypeProvider::function(*this, FunctionType::Kind::External);
}
}
@@ -830,6 +832,7 @@ FunctionTypePointer VariableDeclaration::functionType(bool _internal) const
switch (visibility())
{
case Visibility::Default:
+ case Visibility::Getter:
solAssert(false, "visibility() should not return Default");
case Visibility::Private:
case Visibility::Internal:
diff --git a/compiler/libsolidity/ast/AST.h b/compiler/libsolidity/ast/AST.h
index 93ddaaa1..09a159ec 100644
--- a/compiler/libsolidity/ast/AST.h
+++ b/compiler/libsolidity/ast/AST.h
@@ -242,6 +242,8 @@ class Declaration: public ASTNode, public Scopable
return "private";
case Visibility::External:
return "external";
+ case Visibility::Getter:
+ return "getter";
default:
solAssert(false, "Invalid visibility specifier.");
}
diff --git a/compiler/libsolidity/ast/ASTEnums.h b/compiler/libsolidity/ast/ASTEnums.h
index d2e2d33a..b76baf14 100644
--- a/compiler/libsolidity/ast/ASTEnums.h
+++ b/compiler/libsolidity/ast/ASTEnums.h
@@ -37,7 +37,7 @@ enum class VirtualLookup { Static, Virtual, Super };
enum class StateMutability { Pure, View, NonPayable };
/// Visibility ordered from restricted to unrestricted.
-enum class Visibility { Default, Private, Internal, Public, External };
+enum class Visibility { Default, Private, Internal, Public, External, Getter };
enum class Arithmetic { Checked, Wrapping };
diff --git a/compiler/libsolidity/ast/TypeProvider.cpp b/compiler/libsolidity/ast/TypeProvider.cpp
index 701d4f7d..0d53c53d 100644
--- a/compiler/libsolidity/ast/TypeProvider.cpp
+++ b/compiler/libsolidity/ast/TypeProvider.cpp
@@ -46,6 +46,7 @@ std::unique_ptr TypeProvider::m_variant;
TupleType const TypeProvider::m_emptyTuple{};
AddressType const TypeProvider::m_address{};
+AddressStdType const TypeProvider::m_addressStd{};
InitializerListType const TypeProvider::m_initializerList{};
CallListType const TypeProvider::m_callList{};
@@ -1184,7 +1185,7 @@ void TypeProvider::reset()
instance().m_stringLiteralTypes.clear();
instance().m_ufixedMxN.clear();
instance().m_fixedMxN.clear();
- instance().m_varinterger.clear();
+ instance().m_varinteger.clear();
}
template
@@ -1252,6 +1253,8 @@ Type const* TypeProvider::fromElementaryTypeName(ElementaryTypeNameToken const&
return fixedPoint(128, 18, FixedPointType::Modifier::Unsigned);
case Token::Address:
return address();
+ case Token::AddressStd:
+ return addressStd();
case Token::Bool:
return boolean();
case Token::TvmCell:
@@ -1404,7 +1407,7 @@ StringLiteralType const* TypeProvider::stringLiteral(std::string const& literal)
}
VarIntegerType const* TypeProvider::varinteger(unsigned m, IntegerType::Modifier _modifier) {
- auto& map = instance().m_varinterger;
+ auto& map = instance().m_varinteger;
auto i = map.find(std::make_pair(m, _modifier));
if (i != map.end())
return i->second.get();
diff --git a/compiler/libsolidity/ast/TypeProvider.h b/compiler/libsolidity/ast/TypeProvider.h
index c19bc075..9c04ae05 100644
--- a/compiler/libsolidity/ast/TypeProvider.h
+++ b/compiler/libsolidity/ast/TypeProvider.h
@@ -89,6 +89,7 @@ class TypeProvider
static ArraySliceType const* arraySlice(ArrayType const& _arrayType);
static AddressType const* address() noexcept { return &m_address; }
+ static AddressStdType const* addressStd() noexcept { return &m_addressStd; }
static InitializerListType const* initializerList() noexcept { return &m_initializerList; }
static CallListType const* callList() noexcept { return &m_callList; }
@@ -244,6 +245,7 @@ class TypeProvider
static TupleType const m_emptyTuple;
static AddressType const m_address;
+ static AddressStdType const m_addressStd;
static InitializerListType const m_initializerList;
static CallListType const m_callList;
static std::array, 257> const m_intM;
@@ -255,7 +257,7 @@ class TypeProvider
static std::array, 32> const m_bytesM;
static std::array, 9> const m_magics; ///< MagicType's except MetaType
- std::map, std::unique_ptr> m_varinterger{};
+ std::map, std::unique_ptr> m_varinteger{};
std::map, std::unique_ptr> m_ufixedMxN{};
std::map, std::unique_ptr> m_fixedMxN{};
std::map> m_stringLiteralTypes{};
diff --git a/compiler/libsolidity/ast/Types.cpp b/compiler/libsolidity/ast/Types.cpp
index 40452886..99b8ed38 100644
--- a/compiler/libsolidity/ast/Types.cpp
+++ b/compiler/libsolidity/ast/Types.cpp
@@ -516,7 +516,7 @@ BoolResult AddressType::isImplicitlyConvertibleTo(Type const& _convertTo) const
if (Type::isImplicitlyConvertibleTo(_convertTo))
return true;
- return _convertTo.category() == category();
+ return _convertTo.category() == Category::Address || _convertTo.category() == Category::AddressStd;
}
BoolResult AddressType::isExplicitlyConvertibleTo(Type const& _convertTo) const
@@ -560,11 +560,6 @@ TypeResult AddressType::binaryOperatorResult(Token _operator, Type const* _other
return Type::commonType(this, _other);
}
-bool AddressType::operator==(Type const& _other) const
-{
- return _other.category() == category();
-}
-
MemberList::MemberMap AddressType::nativeMembers(ASTNode const*) const
{
MemberList::MemberMap members = {
@@ -586,7 +581,7 @@ MemberList::MemberMap AddressType::nativeMembers(ASTNode const*) const
));
members.emplace_back("getType", TypeProvider::function(
TypePointers{},
- TypePointers{TypeProvider::uint(8)},
+ TypePointers{TypeProvider::uint(4)},
strings{},
strings{std::string()},
FunctionType::Kind::AddressType,
@@ -620,6 +615,107 @@ MemberList::MemberMap AddressType::nativeMembers(ASTNode const*) const
return members;
}
+std::string AddressStdType::richIdentifier() const
+{
+ return "t_address_std";
+}
+
+std::string AddressStdType::toString(bool) const {
+ return "address_std";
+}
+
+std::string AddressStdType::canonicalName() const {
+ return "address_std";
+}
+
+u256 AddressStdType::literalValue(Literal const* _literal) const
+{
+ solAssert(_literal, "");
+ solAssert(_literal->value().substr(0, 2) == "0x", "");
+ return u256(_literal->valueWithoutUnderscores());
+}
+
+BoolResult AddressStdType::isImplicitlyConvertibleTo(Type const& _convertTo) const {
+ if (Type::isImplicitlyConvertibleTo(_convertTo))
+ return true;
+
+ return _convertTo.category() == Category::Address || _convertTo.category() == Category::AddressStd;
+}
+
+BoolResult AddressStdType::isExplicitlyConvertibleTo(Type const& _convertTo) const {
+ if ((_convertTo.category() == category()) || isImplicitlyConvertibleTo(_convertTo))
+ return true;
+ else if (dynamic_cast(&_convertTo))
+ return true;
+
+ return false;
+}
+
+TypeResult AddressStdType::unaryOperatorResult(Token _operator) const
+{
+ return _operator == Token::Delete ? TypeProvider::emptyTuple() : nullptr;
+}
+
+
+TypeResult AddressStdType::binaryOperatorResult(Token _operator, Type const* _other) const
+{
+ if (!TokenTraits::isCompareOp(_operator))
+ return TypeResult::err("Arithmetic operations on addresses are not supported. Convert to integer first before using them.");
+
+ return Type::commonType(this, _other);
+}
+
+MemberList::MemberMap AddressStdType::nativeMembers(ASTNode const*) const {
+ MemberList::MemberMap members = {
+ {"wid", TypeProvider::integer(8, IntegerType::Modifier::Signed)},
+ {"value", TypeProvider::uint256()},
+ {"isStdZero", TypeProvider::function(strings(), strings{"bool"}, FunctionType::Kind::AddressIsZero, StateMutability::Pure)},
+ {"isNone", TypeProvider::function(strings(), strings{"bool"}, FunctionType::Kind::AddressIsZero, StateMutability::Pure)},
+ };
+ members.emplace_back("unpack", TypeProvider::function(
+ TypePointers{},
+ TypePointers{TypeProvider::integer(8, IntegerType::Modifier::Signed), TypeProvider::uint256()},
+ strings{},
+ strings{std::string(), std::string()},
+ FunctionType::Kind::AddressUnpack,
+ StateMutability::Pure
+ ));
+ members.emplace_back("getType", TypeProvider::function(
+ TypePointers{},
+ TypePointers{TypeProvider::uint(4)},
+ strings{},
+ strings{std::string()},
+ FunctionType::Kind::AddressType,
+ StateMutability::Pure
+ ));
+ members.emplace_back("isStdAddrWithoutAnyCast", TypeProvider::function(
+ TypePointers{},
+ TypePointers{TypeProvider::boolean()},
+ strings{},
+ strings{std::string()},
+ FunctionType::Kind::AddressIsStdAddrWithoutAnyCast,
+ StateMutability::Pure
+ ));
+ members.emplace_back("transfer", TypeProvider::function(
+ {
+ TypeProvider::coins(),
+ TypeProvider::boolean(),
+ TypeProvider::uint(16),
+ TypeProvider::tvmcell(),
+ TypeProvider::extraCurrencyCollection(),
+ TypeProvider::tvmcell(),
+ },
+ {},
+ {"value", "bounce", "flag", "body", "currencies", "stateInit"},
+ {},
+ FunctionType::Kind::AddressTransfer,
+ StateMutability::Pure,
+ nullptr,
+ FunctionType::Options::withArbitraryParameters()
+ ));
+ return members;
+}
+
namespace
{
@@ -722,7 +818,7 @@ BoolResult IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
category == Type::Category::FixedPoint
)
return true;
- else if (dynamic_cast(&_convertTo) || dynamic_cast(&_convertTo))
+ else if (dynamic_cast(&_convertTo) || dynamic_cast(&_convertTo) || dynamic_cast(&_convertTo))
return !isSigned();
else if (auto fixedBytesType = dynamic_cast(&_convertTo))
return (!isSigned() && (numBits() == fixedBytesType->numBytes() * 8));
@@ -1198,7 +1294,7 @@ BoolResult RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo)
auto category = _convertTo.category();
if (category == Category::FixedBytes)
return false;
- else if (dynamic_cast(&_convertTo) || dynamic_cast(&_convertTo))
+ else if (dynamic_cast(&_convertTo) || dynamic_cast(&_convertTo) || dynamic_cast(&_convertTo))
return (m_value == 0) ||
(!isNegative() &&
!isFractional() &&
@@ -1570,7 +1666,7 @@ BoolResult FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) con
return true;
else if (auto integerType = dynamic_cast(&_convertTo))
return (!integerType->isSigned() && integerType->numBits() == numBytes() * 8);
- else if (dynamic_cast(&_convertTo))
+ else if (dynamic_cast(&_convertTo) || dynamic_cast(&_convertTo))
return numBytes() == 32;
return false;
@@ -1716,7 +1812,7 @@ BoolResult ContractType::isExplicitlyConvertibleTo(Type const& _convertTo) const
if (m_super)
return false;
- if (dynamic_cast(&_convertTo))
+ if (dynamic_cast(&_convertTo) || dynamic_cast(&_convertTo))
return true;
return isImplicitlyConvertibleTo(_convertTo);
@@ -3267,7 +3363,7 @@ std::string FunctionType::richIdentifier() const
case Kind::LogTVM: id += "logtvm"; break;
case Kind::TVMAccept: id += "tvmaccept"; break;
- case Kind::ABIBuildIntMsg: id += "abibuildintmsg"; break;
+ case Kind::ABIEncodeIntMsg: id += "abibuildintmsg"; break;
case Kind::ABICodeSalt: id += "abicodesalt"; break;
case Kind::ABIDecodeFunctionParams: id += "abidecodefunctionparams"; break;
case Kind::ABIDecodeData: id += "abidecodestatevars"; break;
@@ -4220,10 +4316,6 @@ std::string NullType::richIdentifier() const {
return "null";
}
-bool NullType::operator==(Type const& _other) const {
- return _other.category() == category();
-}
-
std::string NullType::toString(bool /*_short*/) const {
return "null";
}
@@ -4241,10 +4333,6 @@ std::string EmptyMapType::richIdentifier() const {
return "emptyMap";
}
-bool EmptyMapType::operator==(Type const& _other) const {
- return _other.category() == category();
-}
-
std::string EmptyMapType::toString(bool /*_short*/) const {
return "emptyMap";
}
@@ -4274,6 +4362,11 @@ std::string NanType::toString(bool) const
return "NaN";
}
+std::string NanType::canonicalName() const
+{
+ return "NaN";
+}
+
std::string TypeType::richIdentifier() const
{
return "t_type" + identifierList(actualType());
@@ -4395,6 +4488,16 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons
FunctionType::Kind::AddressMakeAddrStd,
StateMutability::Pure
));
+ } else if (m_actualType->category() == Category::AddressStd) {
+ members.emplace_back("addrNone", TypeProvider::addressStd());
+ members.emplace_back("makeAddrStd", TypeProvider::function(
+ TypePointers{TypeProvider::integer(8, IntegerType::Modifier::Signed), TypeProvider::uint256()},
+ TypePointers{TypeProvider::addressStd()},
+ strings{std::string(), std::string()},
+ strings{std::string()},
+ FunctionType::Kind::AddressMakeAddrStd,
+ StateMutability::Pure
+ ));
}
else if (m_actualType->category() == Category::UserDefinedValueType)
{
@@ -4745,7 +4848,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
"stateInit", // can be omitted
},
{{}},
- FunctionType::Kind::ABIBuildIntMsg,
+ FunctionType::Kind::ABIEncodeIntMsg,
StateMutability::Pure,
nullptr,
FunctionType::Options::withArbitraryParameters()
@@ -5117,7 +5220,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
"stateInit", // can be omitted
},
{{}},
- FunctionType::Kind::ABIBuildIntMsg,
+ FunctionType::Kind::ABIEncodeIntMsg,
StateMutability::Pure,
nullptr,
FunctionType::Options::withArbitraryParameters()
@@ -6625,6 +6728,11 @@ MemberList::MemberMap Variant::nativeMembers(ASTNode const* /*_currentScope*/) c
return members;
}
+bool TvmVectorType::operator==(Type const& _other) const {
+ auto vect = to(&_other);
+ return vect && *this->valueType() == *vect->valueType();
+}
+
TypeResult TvmVectorType::unaryOperatorResult(Token _operator) const {
if (_operator == Token::Delete)
return TypeProvider::emptyTuple();
@@ -6720,6 +6828,11 @@ TypeResult TvmStackType::unaryOperatorResult(Token _operator) const {
return nullptr;
}
+bool TvmStackType::operator==(Type const& _other) const {
+ auto stack = to(&_other);
+ return stack && *this->valueType() == *stack->valueType();
+}
+
MemberList::MemberMap TvmStackType::nativeMembers(const ASTNode *) const
{
MemberList::MemberMap members =
@@ -7167,6 +7280,11 @@ MemberList::MemberMap StringBuilderType::nativeMembers(const ASTNode *) const {
return members;
}
+bool VarIntegerType::operator==(Type const& _other) const {
+ auto varInt = to(&_other);
+ return varInt && m_int == varInt->m_int;
+}
+
BoolResult VarIntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const {
return m_int.isImplicitlyConvertibleTo(_convertTo);
}
diff --git a/compiler/libsolidity/ast/Types.h b/compiler/libsolidity/ast/Types.h
index 420bdece..fc9d0b79 100644
--- a/compiler/libsolidity/ast/Types.h
+++ b/compiler/libsolidity/ast/Types.h
@@ -194,14 +194,9 @@ class Type
Module,
InaccessibleDynamic,
TvmCell, TvmSlice, TvmBuilder, StringBuilder, TvmVector, TvmStack, Variant,
- VarInteger,
- QInteger,
- QBool,
+ VarInteger, QInteger, QBool,
InitializerList, CallList, // <-- variables of that types can't be declared in solidity contract
- Optional,
- Null,
- EmptyMap,
- TVMNaN
+ Optional, Null, EmptyMap, TVMNaN, AddressStd
};
/// @returns a pointer to _a or _b if the other is implicitly convertible to it or nullptr otherwise
@@ -446,7 +441,36 @@ class AddressType: public Type
TypeResult unaryOperatorResult(Token _operator) const override;
TypeResult binaryOperatorResult(Token _operator, Type const* _other) const override;
- bool operator==(Type const& _other) const override;
+ unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : 160 / 8; }
+ unsigned storageBytes() const override { return 160 / 8; }
+ bool leftAligned() const override { return false; }
+ bool isValueType() const override { return true; }
+ bool nameable() const override { return true; }
+
+ MemberList::MemberMap nativeMembers(ASTNode const*) const override;
+
+ std::string toString(bool _withoutDataLocation) const override;
+ std::string canonicalName() const override;
+
+ u256 literalValue(Literal const* _literal) const override;
+
+ Type const* encodingType() const override { return this; }
+ TypeResult interfaceType(bool) const override { return this; }
+};
+
+/**
+ * Type for std or none addresses.
+ */
+class AddressStdType: public Type
+{
+public:
+ Category category() const override { return Category::AddressStd; }
+
+ std::string richIdentifier() const override;
+ BoolResult isImplicitlyConvertibleTo(Type const& _other) const override;
+ BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
+ TypeResult unaryOperatorResult(Token _operator) const override;
+ TypeResult binaryOperatorResult(Token _operator, Type const* _other) const override;
unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : 160 / 8; }
unsigned storageBytes() const override { return 160 / 8; }
@@ -767,7 +791,7 @@ class TvmVectorType: public Type
public:
TvmVectorType(Type const* _type):
m_type(_type) {}
-
+ bool operator==(Type const& _other) const override;
Category category() const override { return Category::TvmVector; }
bool isValueType() const override { return true; }
std::string richIdentifier() const override;
@@ -793,7 +817,7 @@ class TvmStackType: public Type
public:
TvmStackType(Type const* _type):
m_type(_type) {}
-
+ bool operator==(Type const& _other) const override;
Category category() const override { return Category::TvmStack; }
bool isValueType() const override { return true; }
std::string richIdentifier() const override;
@@ -873,6 +897,7 @@ class VarIntegerType: public Type
{
public:
explicit VarIntegerType(uint32_t _n, IntegerType::Modifier _modifier) : m_n{_n}, m_int{(_n - 1) * 8, _modifier} {}
+ bool operator==(Type const& _other) const override;
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
Category category() const override { return Category::VarInteger; }
@@ -898,7 +923,6 @@ class QIntegerType: public Type
explicit QIntegerType(uint32_t _n, IntegerType::Modifier _modifier) :
m_int{std::make_unique(_n, _modifier)} {}
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
-// BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
Category category() const override { return Category::QInteger; }
bool isValueType() const override { return true; }
bool operator==(Type const& _other) const override;
@@ -920,7 +944,6 @@ class QBoolType: public Type
public:
explicit QBoolType() = default;
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
-// BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
Category category() const override { return Category::QBool; }
bool isValueType() const override { return true; }
std::string richIdentifier() const override { return "t_qbool"; }
@@ -1545,12 +1568,12 @@ class FunctionType: public Type
BlsG1MultiExp,
BlsG2MultiExp,
- ABIBuildIntMsg, ///< abi.encodeIntMsg()
ABICodeSalt, ///< abi.codeSalt()
ABIDecodeData, ///< abi.decodeData(contract_name, slice)
ABIDecodeFunctionParams, ///< abi.decodeFunctionParams()
ABIEncodeBody, ///< abi.encodeBody()
ABIEncodeData, ///< abi.encodeData()
+ ABIEncodeIntMsg, ///< abi.encodeIntMsg()
ABIEncodeStateInit, ///< abi.encodeStateInit()
ABIFunctionId, ///< abi.functionId(function_name)
ABISetCodeSalt, ///< abi.setCodeSalt()
@@ -1972,7 +1995,6 @@ class NullType: public Type
Category category() const override { return Category::Null; }
BoolResult isImplicitlyConvertibleTo(Type const& _other) const override;
std::string richIdentifier() const override;
- bool operator==(Type const& _other) const override;
std::string toString(bool _short) const override;
std::string canonicalName() const override;
TypeResult interfaceType(bool) const override { return this; }
@@ -1986,7 +2008,6 @@ class EmptyMapType: public Type
Category category() const override { return Category::EmptyMap; }
BoolResult isImplicitlyConvertibleTo(Type const& _other) const override;
std::string richIdentifier() const override;
- bool operator==(Type const& _other) const override;
std::string toString(bool _short) const override;
std::string canonicalName() const override;
TypeResult interfaceType(bool) const override { return this; }
@@ -2000,9 +2021,8 @@ class NanType: public Type
Category category() const override { return Category::TVMNaN; }
BoolResult isImplicitlyConvertibleTo(Type const& _other) const override;
std::string richIdentifier() const override;
- //bool operator==(Type const& _other) const override;
std::string toString(bool _short) const override;
- //std::string canonicalName() const override;
+ std::string canonicalName() const override;
TypeResult interfaceType(bool) const override { return this; }
TypeResult binaryOperatorResult(Token, Type const*) const override { return nullptr; }
bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); }
diff --git a/compiler/libsolidity/codegen/DictOperations.cpp b/compiler/libsolidity/codegen/DictOperations.cpp
index 0903a25b..547e522f 100644
--- a/compiler/libsolidity/codegen/DictOperations.cpp
+++ b/compiler/libsolidity/codegen/DictOperations.cpp
@@ -30,8 +30,6 @@ DictOperation::DictOperation(StackPusher& pusher, Type const& keyType, Type cons
void DictMinMax::minOrMax(bool saveOrigKeyAndNoTuple) {
// stack: dict
pusher.pushInt(dictKeyLength(&keyType)); // dict nbits
-
- const bool haveKey = true;
bool isInRef = pusher.doesDictStoreValueInRef(&keyType, &valueType);
dictOpcode = "DICT" + typeToDictChar(&keyType) + (isMin? "MIN" : "MAX") + (isInRef? "REF" : "");
@@ -40,7 +38,7 @@ void DictMinMax::minOrMax(bool saveOrigKeyAndNoTuple) {
pusher.recoverKeyAndValueAfterDictOperation(
&keyType,
&valueType,
- haveKey,
+ true,
isInRef,
StackPusher::DecodeType::DecodeValueOrPushNull,
saveOrigKeyAndNoTuple
diff --git a/compiler/libsolidity/codegen/TVMABI.cpp b/compiler/libsolidity/codegen/TVMABI.cpp
index 53236a43..be762a55 100644
--- a/compiler/libsolidity/codegen/TVMABI.cpp
+++ b/compiler/libsolidity/codegen/TVMABI.cpp
@@ -75,7 +75,7 @@ Json::Value TVMABI::generateFunctionIdsJson(
Json::Value
TVMABI::generatePrivateFunctionIdsJson(
ContractDefinition const& contract,
- std::vector> _sourceUnits,
+ std::vector> const& _sourceUnits,
PragmaDirectiveHelper const& pragmaHelper
) {
Json::Value ids{Json::arrayValue};
@@ -99,25 +99,11 @@ Json::Value TVMABI::generateABIJson(
std::vector const &pragmaDirectives
) {
PragmaDirectiveHelper pdh{pragmaDirectives};
- TVMCompilerContext ctx(contract, pdh);
-
- const std::vector publicFunctions = TVMABI::publicFunctions(*contract);
- std::vector events {};
-
- for (const auto &_event : contract->definedInterfaceEvents())
- events.push_back(_event);
- for (std::shared_ptr const& source: _sourceUnits)
- for (ASTPointer const &node: source->nodes())
- if (auto lib = dynamic_cast(node.get()))
- if (lib->isLibrary())
- for (const auto &event : lib->definedInterfaceEvents())
- events.push_back(event);
-
- std::set used;
+ TVMCompilerContext ctx{contract, pdh};
Json::Value root(Json::objectValue);
root["ABI version"] = 2;
- root["version"] = "2.4";
+ root["version"] = "2.7";
// header
{
@@ -133,7 +119,9 @@ Json::Value TVMABI::generateABIJson(
// functions
{
+ std::set used;
Json::Value functions(Json::arrayValue);
+ const std::vector publicFunctions = TVMABI::publicFunctions(*contract);
for (FunctionDefinition const* f : publicFunctions) {
auto funcName = TVMCompilerContext::getFunctionExternalName(f);
if (used.count(funcName))
@@ -158,6 +146,16 @@ Json::Value TVMABI::generateABIJson(
// events
{
+ std::vector events {};
+ for (const auto &_event : contract->definedInterfaceEvents())
+ events.push_back(_event);
+ for (std::shared_ptr const& source: _sourceUnits)
+ for (ASTPointer const &node: source->nodes())
+ if (auto lib = dynamic_cast(node.get()))
+ if (lib->isLibrary())
+ for (const auto &event : lib->definedInterfaceEvents())
+ events.push_back(event);
+
Json::Value eventAbi(Json::arrayValue);
std::set usedEvents;
for (const auto &e: events) {
@@ -215,6 +213,20 @@ Json::Value TVMABI::generateABIJson(
root["fields"] = fields;
}
+ // getters
+ {
+ Json::Value functions(Json::arrayValue);
+ std::set used;
+ auto getters = TVMABI::getters(*contract);
+ for (FunctionDefinition const* f : getters) {
+ auto funcName = TVMCompilerContext::getFunctionExternalName(f);
+ solAssert(used.count(funcName) == 0, "");
+ used.insert(funcName);
+ functions.append(toJson(funcName, convertArray(f->parameters()), convertArray(f->returnParameters()), f));
+ }
+ root["getters"] = functions;
+ }
+
return root;
}
@@ -252,17 +264,17 @@ void TVMABI::generateABI(
print(root["functions"], out);
*out << "\t" << "],\n";
+ *out << "\t" << R"("getters": [)" << "\n";
+ print(root["getters"], out);
+ *out << "\t" << "],\n";
+
*out << "\t" << R"("events": [)" << "\n";
print(root["events"], out);
+ *out << "\t" << "],\n";
- if (root.isMember("fields")) {
- *out << "\t" << "],\n";
- *out << "\t" << R"("fields": [)" << "\n";
- printData(root["fields"], out);
- *out << "\t" << "]\n";
- } else {
- *out << "\t" << "]\n";
- }
+ *out << "\t" << R"("fields": [)" << "\n";
+ printData(root["fields"], out);
+ *out << "\t" << "]\n";
*out << "}" << endl;
}
@@ -274,14 +286,32 @@ std::vector TVMABI::publicFunctions(ContractDefiniti
for (auto c : contract.annotation().linearizedBaseContracts) {
for (const auto &_function : c->definedFunctions()) {
- if (!_function->isConstructor() && _function->isPublic() &&
- !_function->isReceive() && !_function->isFallback() && !_function->isOnBounce() && !_function->isOnTickTock())
+ if (!_function->isConstructor() &&
+ _function->isPublic() &&
+ !_function->isReceive() &&
+ !_function->isFallback() &&
+ !_function->isOnBounce() &&
+ !_function->isOnTickTock() &&
+ _function->visibility() != Visibility::Getter
+ )
publicFunctions.push_back(_function);
}
}
return publicFunctions;
}
+std::vector TVMABI::getters(ContractDefinition const& contract) {
+ std::vector getters;
+ for (auto c : contract.annotation().linearizedBaseContracts) {
+ for (const auto &_function : c->definedFunctions()) {
+ if (!_function->isConstructor() &&
+ _function->visibility() == Visibility::Getter)
+ getters.push_back(_function);
+ }
+ }
+ return getters;
+}
+
void TVMABI::printData(const Json::Value &json, std::ostream* out) {
for (unsigned f = 0; f < json.size(); ++f) {
const auto &element = json[f];
@@ -436,14 +466,16 @@ Json::Value TVMABI::setupNameTypeComponents(const string &name, const Type *type
} else {
const Type::Category category = type->category();
TypeInfo ti(type);
- if (category == Type::Category::Address || category == Type::Category::Contract) {
+ if (category == Type::Category::Address || category == Type::Category::Contract)
typeName = "address";
- } else if (category == Type::Category::VarInteger) {
+ else if (category == Type::Category::AddressStd)
+ typeName = "address_std";
+ else if (category == Type::Category::VarInteger) {
auto varint = to(type);
typeName = varint->toString(false);
- } else if (auto* fixedBytesType = to(type)) {
+ } else if (auto* fixedBytesType = to(type))
typeName = "fixedbytes" + toString(fixedBytesType->numBytes());
- } else if (ti.isNumeric) {
+ else if (ti.isNumeric) {
if (to(type)) {
typeName = "bool";
} else if (ti.isSigned) {
@@ -635,21 +667,39 @@ void ChainDataDecoder::decodePublicFunctionParameters(
*pusher << "ENDS";
}
-void ChainDataDecoder::decodeFunctionParameters(const std::vector& types, bool isResponsible) {
- pusher->startOpaque();
- pusher->pushS(1);
- pusher->fixStack(-1); // fix stack
+ChainDataDecoder::DecodeType ChainDataDecoder::getDecodeType(FunctionDefinition const* f) {
+ if (f->isExternalMsg())
+ return DecodeType::ONLY_EXT_MSG;
+ if (f->isInternalMsg())
+ return DecodeType::ONLY_INT_MSG;
+ return DecodeType::BOTH;
+}
- pusher->startContinuation();
- decodePublicFunctionParameters(types, isResponsible, false);
- pusher->endContinuation();
+void ChainDataDecoder::decodeFunctionParameters(const std::vector& types, bool isResponsible, DecodeType decodeType) {
+ switch (decodeType) {
+ case DecodeType::ONLY_EXT_MSG:
+ decodePublicFunctionParameters(types, isResponsible, false);
+ break;
+ case DecodeType::ONLY_INT_MSG:
+ decodePublicFunctionParameters(types, isResponsible, true);
+ break;
+ case DecodeType::BOTH:
+ pusher->startOpaque();
+ pusher->pushS(1);
+ pusher->fixStack(-1); // fix stack
- pusher->startContinuation();
- decodePublicFunctionParameters(types, isResponsible, true);
- pusher->endContinuation();
+ pusher->startContinuation();
+ decodePublicFunctionParameters(types, isResponsible, false);
+ pusher->endContinuation();
- pusher->ifElse();
- pusher->endOpaque(1, types.size());
+ pusher->startContinuation();
+ decodePublicFunctionParameters(types, isResponsible, true);
+ pusher->endContinuation();
+
+ pusher->ifElse();
+ pusher->endOpaque(1, types.size());
+ break;
+ }
}
void ChainDataDecoder::decodeData(int offset, int usedRefs, const std::vector& types) {
@@ -744,7 +794,9 @@ void ChainDataDecoder::decodeParameter(Type const* type, DecodePosition* positio
to(type) ||
to(type) ||
to(type) ||
- (category == Type::Category::Address || category == Type::Category::Contract)
+ category == Type::Category::Address ||
+ category == Type::Category::Contract ||
+ category == Type::Category::AddressStd
) {
loadNextSliceIfNeed(position->loadNextCell(type));
pusher->load(type, false);
@@ -764,7 +816,7 @@ void ChainDataDecoder::decodeParameterQ(Type const* type, DecodePosition* positi
to(type) ||
to(type) ||
to(type) ||
- (category == Type::Category::Address || category == Type::Category::Contract)
+ (category == Type::Category::Address || category == Type::Category::AddressStd || category == Type::Category::Contract)
) {
loadNextSliceIfNeed(position->loadNextCell(type));
pusher->loadQ(type);
diff --git a/compiler/libsolidity/codegen/TVMABI.hpp b/compiler/libsolidity/codegen/TVMABI.hpp
index 3e6324de..8efaa7ed 100644
--- a/compiler/libsolidity/codegen/TVMABI.hpp
+++ b/compiler/libsolidity/codegen/TVMABI.hpp
@@ -32,7 +32,7 @@ class TVMABI {
);
static Json::Value generatePrivateFunctionIdsJson(
ContractDefinition const& contract,
- std::vector> _sourceUnits,
+ const std::vector>& _sourceUnits,
PragmaDirectiveHelper const& pragmaHelper
);
static void generateABI(ContractDefinition const* contract,
@@ -43,6 +43,7 @@ class TVMABI {
std::vector const& pragmaDirectives);
private:
static std::vector publicFunctions(ContractDefinition const& contract);
+ static std::vector getters(ContractDefinition const& contract);
static void printData(const Json::Value& json, std::ostream* out);
static void print(const Json::Value& json, std::ostream* out);
static Json::Value toJson(
@@ -95,7 +96,13 @@ class ChainDataDecoder : private boost::noncopyable {
static int minBits(bool hasCallback);
public:
void decodePublicFunctionParameters(const std::vector& types, bool isResponsible, bool isInternal);
- void decodeFunctionParameters(const std::vector& types, bool isResponsible);
+ enum class DecodeType {
+ ONLY_EXT_MSG,
+ ONLY_INT_MSG,
+ BOTH
+ };
+ static DecodeType getDecodeType(FunctionDefinition const*);
+ void decodeFunctionParameters(const std::vector& types, bool isResponsible, DecodeType decodeType);
void decodeData(int offset, int usedRefs, const std::vector& types);
void decodeParameters(
const std::vector& types,
diff --git a/compiler/libsolidity/codegen/TVMAnalyzer.cpp b/compiler/libsolidity/codegen/TVMAnalyzer.cpp
index 57da3686..3e42cdd2 100644
--- a/compiler/libsolidity/codegen/TVMAnalyzer.cpp
+++ b/compiler/libsolidity/codegen/TVMAnalyzer.cpp
@@ -69,7 +69,7 @@ bool TVMAnalyzer::visit(ContractDefinition const& contract) {
for (EventDefinition const* event : contract.definedInterfaceEvents()) {
if (used.count(event->name())) {
m_errorReporter.declarationError(
- 2018_error,
+ 5022_error,
event->location(),
SecondarySourceLocation().append("Another declaration is here:", used.at(event->name())->location()),
"Event overriding is not supported."
diff --git a/compiler/libsolidity/codegen/TVMCommons.cpp b/compiler/libsolidity/codegen/TVMCommons.cpp
index 47e8c666..bb3bd44d 100644
--- a/compiler/libsolidity/codegen/TVMCommons.cpp
+++ b/compiler/libsolidity/codegen/TVMCommons.cpp
@@ -95,8 +95,8 @@ const Type *getType(const VariableDeclaration *var) {
return var->annotation().type;
}
-bool isAddressOrContractType(const Type *type) {
- return to(type) || to(type);
+bool isAddressOrAddressStdOrContractType(const Type *type) {
+ return to(type) || to(type) || to(type);
}
bool isUsualArray(const Type *type) {
@@ -169,7 +169,7 @@ std::string typeToDictChar(Type const *keyType) {
}
int dictKeyLength(Type const *key) {
- if (isIn(key->category(), Type::Category::Address, Type::Category::Contract)) {
+ if (isIn(key->category(), Type::Category::Address, Type::Category::AddressStd, Type::Category::Contract)) {
return AddressInfo::stdAddrWithoutAnyCastLength();
}
@@ -332,6 +332,7 @@ getTupleTypes(TupleType const* tuple) {
DictValueType toDictValueType(const Type::Category& category) {
switch (category) {
case Type::Category::Address:
+ case Type::Category::AddressStd:
return DictValueType::Address;
case Type::Category::Array:
return DictValueType::Array;
@@ -382,7 +383,10 @@ ABITypeSize::ABITypeSize(Type const* _type) {
}
void ABITypeSize::init(Type const* type) {
- if (isAddressOrContractType(type)){
+ if (type->category() == Type::Category::AddressStd) {
+ maxBits = 2 + (1 + 5 + 30) + 8 + 256;
+ maxRefs = 0;
+ } else if (isAddressOrAddressStdOrContractType(type)){
maxBits = AddressInfo::maxBitLength();
maxRefs = 0;
} else if (isIntegralType(type)) {
@@ -793,4 +797,29 @@ bool isFitUseless(Type const* left, Type const* right, Type const* common, Token
);
}
+// { width: 16, poly: 0x1021, init: 0x0000, refin: false, refout: false,
+// xorout: 0x0000, check: 0x31c3, residue: 0x0000 };
+/*
+ Name : CRC-16 CCITT
+ Poly : 0x1021 x^16 + x^12 + x^5 + 1
+ Init : 0x0000
+ Revert: false
+ XorOut: 0x0000
+ MaxLen: 4095 байт (32767 бит)
+*/
+unsigned short crc16(char const *pcBlock, unsigned short len)
+{
+ unsigned short crc = 0;
+ unsigned char i;
+
+ while (len--)
+ {
+ crc ^= (unsigned char)(*pcBlock++) << 8;
+
+ for (i = 0; i < 8; i++)
+ crc = crc & 0x8000 ? (crc << 1) ^ 0x1021 : crc << 1;
+ }
+ return crc;
+}
+
} // end namespace solidity::frontend
diff --git a/compiler/libsolidity/codegen/TVMCommons.hpp b/compiler/libsolidity/codegen/TVMCommons.hpp
index 121fd213..6ee937f9 100644
--- a/compiler/libsolidity/codegen/TVMCommons.hpp
+++ b/compiler/libsolidity/codegen/TVMCommons.hpp
@@ -52,7 +52,7 @@ constexpr uint64_t str2int(const char* str, int i = 0) {
std::string functionName(FunctionDefinition const* _function);
std::string eventName(EventDefinition const* _event);
-bool isAddressOrContractType(const Type* type);
+bool isAddressOrAddressStdOrContractType(const Type* type);
bool isUsualArray(const Type* type);
bool isByteArrayOrString(const Type* type);
bool isString(const Type* type);
@@ -268,7 +268,7 @@ std::pair, std::vector>
getParams(const ast_vec& params, size_t offset = 0) {
std::vector types;
std::vector nodes;
- for (auto it = params.begin() + offset; it != params.end(); it++) {
+ for (auto it = params.begin() + offset; it != params.end(); ++it) {
types.push_back(getType(it->get()));
nodes.push_back(it->get());
}
@@ -406,4 +406,6 @@ namespace MathConsts {
bool isFitUselessUnary(Type const* common, Token op);
bool isFitUseless(Type const* left, Type const* right, Type const* common, Token op);
+unsigned short crc16(char const *pcBlock, unsigned short len);
+
} // end solidity::frontend
diff --git a/compiler/libsolidity/codegen/TVMContractCompiler.cpp b/compiler/libsolidity/codegen/TVMContractCompiler.cpp
index 59ae3895..2a673193 100644
--- a/compiler/libsolidity/codegen/TVMContractCompiler.cpp
+++ b/compiler/libsolidity/codegen/TVMContractCompiler.cpp
@@ -99,6 +99,7 @@ TVMContractCompiler::generateContractCode(
PragmaDirectiveHelper const &pragmaHelper
) {
std::vector> functions;
+ std::map getters;
TVMCompilerContext ctx{contract, pragmaHelper};
@@ -116,9 +117,9 @@ TVMContractCompiler::generateContractCode(
for (FunctionDefinition const *_function : c->definedFunctions()) {
if (_function->isConstructor() ||
!_function->isImplemented() ||
- _function->isInline()) {
+ _function->isInline()
+ )
continue;
- }
if (_function->isOnBounce()) {
if (!ctx.isOnBounceGenerated()) {
@@ -142,13 +143,20 @@ TVMContractCompiler::generateContractCode(
functions.emplace_back(TVMFunctionCompiler::generateOnCodeUpgrade(ctx, _function));
} else {
if (!ctx.isStdlib() && _function->isPublic() && !ctx.isBaseFunction(_function)) {
- functions.emplace_back(TVMFunctionCompiler::generatePublicFunction(ctx, _function));
-
- StackPusher pusher{&ctx};
- ChainDataEncoder encoder{&pusher};
- uint32_t functionId = encoder.calculateFunctionIDWithReason(_function,
- ReasonOfOutboundMessage::RemoteCallInternal);
- ctx.addPublicFunction(functionId, _function->name());
+ if (_function->visibility() == Visibility::Getter) {
+ functions.emplace_back(TVMFunctionCompiler::generateGetterFunction(ctx, _function));
+ uint32_t functionId = crc16(_function->name().c_str(), _function->name().length());
+ functionId = (functionId & 0xffff) | 0x10000;
+ bool emplace = getters.emplace(functionId, _function->name()).second;
+ solAssert(emplace, "");
+ } else {
+ functions.emplace_back(TVMFunctionCompiler::generatePublicFunction(ctx, _function));
+ StackPusher pusher{&ctx};
+ ChainDataEncoder encoder{&pusher};
+ uint32_t functionId = encoder.calculateFunctionIDWithReason(_function,
+ ReasonOfOutboundMessage::RemoteCallInternal);
+ ctx.addPublicFunction(functionId, _function->name());
+ }
}
auto const[functionName, id] = ctx.functionInternalName(_function);
functions.emplace_back(TVMFunctionCompiler::generateFunction(ctx, _function, functionName, id));
@@ -274,9 +282,11 @@ TVMContractCompiler::generateContractCode(
}
Pointer c = createNode(
- ctx.isStdlib(), ctx.getPragmaSaveAllFunctions(), pragmaHelper.hasUpgradeFunc(), pragmaHelper.hasUpgradeOldSol(),
- std::string{"sol "} + solidity::frontend::VersionNumber,
- functionOrder, ctx.callGraph().privateFunctions()
+ ctx.isStdlib(), ctx.getPragmaSaveAllFunctions(), pragmaHelper.hasUpgradeFunc(), pragmaHelper.hasUpgradeOldSol(),
+ std::string{"sol "} + solidity::frontend::VersionNumber,
+ functionOrder,
+ ctx.callGraph().privateFunctions(),
+ getters
);
DeleterAfterRet d;
@@ -333,23 +343,23 @@ void TVMContractCompiler::optimizeCode(Pointer& c) {
}
void TVMContractCompiler::fillInlineFunctions(TVMCompilerContext &ctx, ContractDefinition const *contract) {
- std::map inlineFunctions;
+ std::set inlineFunctions;
for (ContractDefinition const *base : contract->annotation().linearizedBaseContracts | boost::adaptors::reversed) {
for (FunctionDefinition const *function : base->definedFunctions()) {
if (function->isInline()) {
- inlineFunctions[functionName(function)] = function;
+ inlineFunctions.insert(function);
}
}
}
TVMInlineFunctionChecker inlineFunctionChecker;
- for (FunctionDefinition const *function : inlineFunctions | boost::adaptors::map_values) {
+ for (FunctionDefinition const *function : inlineFunctions) {
function->accept(inlineFunctionChecker);
}
std::vector order = inlineFunctionChecker.functionOrder();
for (FunctionDefinition const * function : order) {
- const std::string name = functionName(function);
+ const std::string name = ctx.functionInternalName(function).first;
ctx.setCurrentFunction(function, name);
StackPusher pusher{&ctx};
TVMFunctionCompiler::generateFunctionWithModifiers(pusher, function, true);
diff --git a/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp b/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp
index 853d58a4..a65a2130 100644
--- a/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp
+++ b/compiler/libsolidity/codegen/TVMExpressionCompiler.cpp
@@ -617,7 +617,7 @@ void TVMExpressionCompiler::visit2(BinaryOperation const &_binaryOperation) {
return;
}
- if (isAddressOrContractType(lt) || isAddressOrContractType(rt) || (isSlice(lt) && isSlice(rt))) {
+ if (isAddressOrAddressStdOrContractType(lt) || isAddressOrAddressStdOrContractType(rt) || (isSlice(lt) && isSlice(rt))) {
acceptLeft();
acceptRight();
compareSlices(op);
@@ -980,7 +980,8 @@ void TVMExpressionCompiler::visit2(MemberAccess const &_node) {
if (category == Type::Category::Magic) {
return visitMagic(_node);
}
- if (checkForAddressMemberAccess(_node, category)) {
+ if (isIn(category, Type::Category::Address, Type::Category::AddressStd)) {
+ checkForAddressMemberAccess(_node);
return;
}
@@ -993,7 +994,7 @@ void TVMExpressionCompiler::visit2(MemberAccess const &_node) {
if (category == Type::Category::TypeType) {
auto typeType = to(_node.expression().annotation().type);
auto actualType = typeType->actualType();
- if (actualType->category() == Type::Category::Address) {
+ if (isIn(actualType->category(), Type::Category::Address, Type::Category::AddressStd)) {
solAssert(memberName == "addrNone", "");
m_pusher.pushSlice("x2_");
return;
@@ -1023,16 +1024,13 @@ void TVMExpressionCompiler::visit2(MemberAccess const &_node) {
cast_error(_node, "Not supported.");
}
-bool TVMExpressionCompiler::checkForAddressMemberAccess(MemberAccess const &_node, Type::Category category) {
- if (category != Type::Category::Address)
- return false;
+void TVMExpressionCompiler::checkForAddressMemberAccess(MemberAccess const &_node) {
if (_node.memberName() == "balance") {
if (!isAddressThis(to(&_node.expression()))) {
cast_error(_node.expression(), "Only 'address(this).balance' is supported for member balance");
}
m_pusher << "GETPARAM 7";
m_pusher.indexNoexcep(0);
- return true;
}
if (_node.memberName() == "currencies") {
if (!isAddressThis(to(&_node.expression()))) {
@@ -1040,22 +1038,18 @@ bool TVMExpressionCompiler::checkForAddressMemberAccess(MemberAccess const &_nod
}
m_pusher << "GETPARAM 7";
m_pusher.indexNoexcep(1);
- return true;
}
if (_node.memberName() == "wid") {
compileNewExpr(&_node.expression());
m_pusher << "PARSEMSGADDR";
m_pusher.indexWithExcep(2);
- return true;
}
if (_node.memberName() == "value") {
compileNewExpr(&_node.expression());
m_pusher << "PARSEMSGADDR";
m_pusher.indexWithExcep(3);
m_pusher << "PLDU 256";
- return true;
}
- return false;
}
void TVMExpressionCompiler::visitMemberAccessArray(MemberAccess const &_node) {
diff --git a/compiler/libsolidity/codegen/TVMExpressionCompiler.hpp b/compiler/libsolidity/codegen/TVMExpressionCompiler.hpp
index 366570bf..2ce76043 100644
--- a/compiler/libsolidity/codegen/TVMExpressionCompiler.hpp
+++ b/compiler/libsolidity/codegen/TVMExpressionCompiler.hpp
@@ -77,7 +77,7 @@ class TVMExpressionCompiler {
void visitMsgMagic(MemberAccess const& _node);
void visitMagic(MemberAccess const& _node);
void visit2(MemberAccess const& _node);
- bool checkForAddressMemberAccess(MemberAccess const& _node, Type::Category category);
+ void checkForAddressMemberAccess(MemberAccess const& _node);
void visitMemberAccessArray(MemberAccess const& _node);
void visitMemberAccessFixedBytes(MemberAccess const& _node, FixedBytesType const* fbt);
static void indexTypeCheck(IndexAccess const& _node);
diff --git a/compiler/libsolidity/codegen/TVMFunctionCall.cpp b/compiler/libsolidity/codegen/TVMFunctionCall.cpp
index 5d807012..a6468a5d 100644
--- a/compiler/libsolidity/codegen/TVMFunctionCall.cpp
+++ b/compiler/libsolidity/codegen/TVMFunctionCall.cpp
@@ -118,7 +118,7 @@ void FunctionCallCompiler::compile() {
{
// nothing
} else if (category == Type::Category::Magic && ident != nullptr && ident->name() == "tvm") {
- if (m_funcType->kind() == FunctionType::Kind::ABIBuildIntMsg) {
+ if (m_funcType->kind() == FunctionType::Kind::ABIEncodeIntMsg) {
abiBuildIntMsg();
} else if (m_funcType->kind() == FunctionType::Kind::ABIEncodeData) {
abiBuildDataInit();
@@ -145,7 +145,7 @@ void FunctionCallCompiler::compile() {
abiDecodeData();
else if (m_funcType->kind() == FunctionType::Kind::ABIEncodeBody)
abiEncodeBody();
- else if (m_funcType->kind() == FunctionType::Kind::ABIBuildIntMsg)
+ else if (m_funcType->kind() == FunctionType::Kind::ABIEncodeIntMsg)
abiBuildIntMsg();
else if (m_funcType->kind() == FunctionType::Kind::ABIEncodeData)
abiBuildDataInit();
@@ -153,7 +153,7 @@ void FunctionCallCompiler::compile() {
abiFunction();
} else if (category == Type::Category::Magic && ident != nullptr && ident->name() == "math") {
mathFunction(*m_memberAccess);
- } else if (category == Type::Category::Address) {
+ } else if (isIn(category, Type::Category::Address, Type::Category::AddressStd)) {
addressMethod();
} else if (category == Type::Category::TvmCell) {
cellMethods(*m_memberAccess);
@@ -169,7 +169,7 @@ void FunctionCallCompiler::compile() {
// nothing
} else if (to(actualType)) {
userDefinedValueMethods(*m_memberAccess);
- } else if (to(actualType)) {
+ } else if (to(actualType) || to(actualType)) {
addressMethods(*m_memberAccess);
} else {
reportError();
@@ -3152,6 +3152,7 @@ void FunctionCallCompiler::typeConversion() {
}
break;
case Type::Category::Address:
+ case Type::Category::AddressStd:
case Type::Category::Contract:
case Type::Category::FixedBytes:
case Type::Category::Array:
@@ -3164,12 +3165,12 @@ void FunctionCallCompiler::typeConversion() {
}
bool FunctionCallCompiler::checkLocalFunctionOrLibCall(const Identifier *identifier) {
- const string& functionName = identifier->name();
auto functionDefinition = to(identifier->annotation().referencedDeclaration);
if (!functionDefinition)
return false;
pushArgs();
if (functionDefinition->isInline()) {
+ const string& functionName = m_pusher.ctx().functionInternalName(functionDefinition, false).first;
int take = m_funcType->parameterTypes().size();
int ret = m_funcType->returnParameterTypes().size();
m_pusher.pushInlineFunction(functionName, take, ret);
@@ -3349,7 +3350,8 @@ bool FunctionCallCompiler::checkSolidityUnits() {
}
std::string format = formatStr.substr(pos + 1, close_pos - pos - 1);
- if (format[0] == ':') format.erase(0, 1);
+ if (format[0] == ':')
+ format.erase(0, 1);
substrings.emplace_back(formatStr.substr(0, pos), format);
formatStr = formatStr.substr(close_pos + 1);
pos = 0;
@@ -3380,17 +3382,23 @@ bool FunctionCallCompiler::checkSolidityUnits() {
if (cat == Type::Category::Integer || cat == Type::Category::RationalNumber) {
// stack: Stack(TvmBuilder)
std::string format = substrings[it].second;
- bool leadingZeroes = !format.empty() && (format[0] == '0');
+ bool leadingZeroes = !format.empty() && format[0] == '0';
bool isHex = !format.empty() && (format.back() == 'x' || format.back() == 'X');
- bool isLower = isHex && (format.back() == 'x');
+ bool isLower = isHex && !format.empty() && format.back() == 'x';
bool isTon = !format.empty() && format.back() == 't';
if (!isTon) {
while (!format.empty() && (format.back() < '0' || format.back() > '9')) {
- format.erase(format.size() - 1, 1);
+ format.pop_back();
}
int width = 0;
- if (!format.empty())
- width = std::stoi(format);
+ if (!format.empty()) {
+ try {
+ width = boost::lexical_cast(format);
+ } catch (boost::bad_lexical_cast const&) {
+ cast_error(*m_arguments[0], "Invalid format width."
+ " Can not convert \"" + format + "\" to integer.");
+ }
+ }
if (width < 0 || width > 127)
cast_error(m_functionCall, "Width should be in range of 0 to 127.");
// stack: stack x
@@ -3411,7 +3419,7 @@ bool FunctionCallCompiler::checkSolidityUnits() {
m_pusher.pushInt(MathConsts::power10().at(9));
m_pusher.pushFragmentInCallRef(4, 1, "__convertFixedPointToString");
}
- } else if (cat == Type::Category::Address) {
+ } else if (cat == Type::Category::Address || cat == Type::Category::AddressStd) {
m_pusher.pushFragmentInCallRef(2, 1, "__convertAddressToHexString");
} else if (isStringOrStringLiteralOrBytes(argType)) {
m_pusher.pushFragmentInCallRef(2, 1, "__appendStringToStringBuilder");
diff --git a/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp b/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp
index 3859699b..30db6ce6 100644
--- a/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp
+++ b/compiler/libsolidity/codegen/TVMFunctionCompiler.cpp
@@ -19,6 +19,7 @@
#include
#include
+#include
#include
#include
@@ -337,7 +338,7 @@ void TVMFunctionCompiler::decodeFunctionParamsAndInitVars(bool isResponsible) {
// decode function params
// stack: arguments-in-slice
vector types = getParams(m_function->parameters()).first;
- ChainDataDecoder{&m_pusher}.decodeFunctionParameters(types, isResponsible);
+ ChainDataDecoder{&m_pusher}.decodeFunctionParameters(types, isResponsible, ChainDataDecoder::getDecodeType(m_function));
// stack: transaction_id arguments...
m_pusher.getStack().change(-static_cast(m_function->parameters().size()));
for (const ASTPointer& variable: m_function->parameters()) {
@@ -405,6 +406,27 @@ TVMFunctionCompiler::generatePublicFunction(TVMCompilerContext& ctx, FunctionDef
return createNode(3, 0, name, nullopt, type, block);
}
+Pointer
+TVMFunctionCompiler::generateGetterFunction(TVMCompilerContext& ctx, FunctionDefinition const* function) {
+ // stack: function params
+ std::string name = function->name();
+ ctx.setCurrentFunction(function, name);
+
+ StackPusher pusher{&ctx};
+
+ pusher.startOpaque();
+ pusher.pushFragmentInCallRef(0, 0, "c4_to_c7");
+ int paramQty = function->parameters().size();
+ int retQty = function->returnParameters().size();
+ pusher.pushFragmentInCallRef(paramQty, retQty, pusher.ctx().functionInternalName(function).first);
+ pusher.endOpaque(0, 0);
+
+ Pointer block = pusher.getBlock();
+ ctx.resetCurrentFunction();
+
+ return createNode(3, 0, name, nullopt, Function::FunctionType::Fragment, block);
+}
+
void TVMFunctionCompiler::generateFunctionWithModifiers(
StackPusher& pusher,
FunctionDefinition const* function,
@@ -539,22 +561,22 @@ void TVMFunctionCompiler::emitOnPublicFunctionReturn() {
ret = convertArray(m_function->returnParameters());
}
- m_pusher.pushS(m_pusher.stackSize());
- m_pusher.fixStack(-1); // fix stack
+
bool isResponsible = m_pusher.ctx().currentFunction()->isResponsible();
+ auto appendBodyForExtMsg = [&](int builderSize) {
+ ChainDataEncoder{&m_pusher}.createMsgBodyAndAppendToBuilder(
+ ret,
+ ChainDataEncoder{&m_pusher}.calculateFunctionIDWithReason(m_function, ReasonOfOutboundMessage::FunctionReturnExternal),
+ {},
+ builderSize
+ );
+ };
+ m_pusher.pushS(m_pusher.stackSize()); // push selector: ext or int msg
+ m_pusher.fixStack(-1); // fix stack
// emit for ext
m_pusher.startContinuation();
{
- auto appendBody = [&](int builderSize) {
- ChainDataEncoder{&m_pusher}.createMsgBodyAndAppendToBuilder(
- ret,
- ChainDataEncoder{&m_pusher}.calculateFunctionIDWithReason(m_function,
- ReasonOfOutboundMessage::FunctionReturnExternal),
- {},
- builderSize
- );
- };
// ext_in_msg_info$10 src:MsgAddressExt dest:MsgAddressInt
// import_fee:Grams = CommonMsgInfo;
@@ -570,7 +592,7 @@ void TVMFunctionCompiler::emitOnPublicFunctionReturn() {
m_pusher.sendMsg(
{TvmConst::ext_msg_info::dest},
{},
- appendBody,
+ appendBodyForExtMsg,
nullptr,
nullptr,
StackPusher::MsgType::ExternalOut
@@ -578,8 +600,6 @@ void TVMFunctionCompiler::emitOnPublicFunctionReturn() {
m_pusher.fixStack(params.size()); // fix stack
}
m_pusher.endContinuation();
-
-
m_pusher.startContinuation();
if (!isResponsible) {
m_pusher.drop(params.size());
@@ -629,12 +649,11 @@ void TVMFunctionCompiler::emitOnPublicFunctionReturn() {
);
}
m_pusher.endContinuation();
-
m_pusher.ifElse();
m_pusher.endOpaque(ret.size(), 0);
- solAssert(stackSize == int(m_pusher.stackSize()) + int(params.size()), "");
+ m_pusher.ensureSize(stackSize - int(params.size()));
}
void TVMFunctionCompiler::visitModifierOrFunctionBlock(Block const &body, int argQty, int retQty, int nameRetQty) {
@@ -1127,7 +1146,7 @@ bool TVMFunctionCompiler::visit(ForEachStatement const& _forStatement) {
// For bytes:
//
// cell
- // [return flag] - optional. If have return/break/continue.
+ // [return flag] - optional. If we have return/break/continue.
// For array:
//
@@ -1260,7 +1279,8 @@ bool TVMFunctionCompiler::visit(ForEachStatement const& _forStatement) {
// stack: cell value [flag]
solAssert(ss == m_pusher.stackSize(), "");
- }
+ } else if (optValueAsTuple(arrayType->baseType()))
+ m_pusher.untuple(1);
}
};
std::function pushLoopExpression = [&]() {
@@ -1617,7 +1637,8 @@ Pointer TVMFunctionCompiler::generateMainExternal(
if (pusher.ctx().afterSignatureCheck()) {
// ... msg_cell msg_body_slice -1 rest_msg_body_slice
pusher.pushS(3);
- pusher.pushInlineFunction("afterSignatureCheck", 2, 1);
+ auto const name = pusher.ctx().functionInternalName(pusher.ctx().afterSignatureCheck()).first;
+ pusher.pushInlineFunction(name, 2, 1);
} else {
if (pusher.ctx().pragmaHelper().hasTime())
f.defaultReplayProtection();
@@ -2041,7 +2062,7 @@ Pointer TVMConstructorCompiler::generateConstructors() {
} else {
take = constructor->parameters().size();
vector types = getParams(constructor->parameters()).first;
- ChainDataDecoder{&m_pusher}.decodeFunctionParameters(types, false);
+ ChainDataDecoder{&m_pusher}.decodeFunctionParameters(types, false, ChainDataDecoder::getDecodeType(constructor));
m_pusher.getStack().change(-static_cast(constructor->parameters().size()));
for (const ASTPointer& variable: constructor->parameters())
m_pusher.getStack().add(variable.get(), true);
diff --git a/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp b/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp
index bfc74787..8ace7947 100644
--- a/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp
+++ b/compiler/libsolidity/codegen/TVMFunctionCompiler.hpp
@@ -54,6 +54,7 @@ class TVMFunctionCompiler: public ASTConstVisitor, private boost::noncopyable
static Pointer generateFallback(TVMCompilerContext& ctx, FunctionDefinition const* function);
static Pointer generateOnBounce(TVMCompilerContext& ctx, FunctionDefinition const* function);
static Pointer generatePublicFunction(TVMCompilerContext& ctx, FunctionDefinition const* function);
+ static Pointer generateGetterFunction(TVMCompilerContext& ctx, FunctionDefinition const* function);
static void generateFunctionWithModifiers(StackPusher& pusher, FunctionDefinition const* function, bool pushArgs);
static Pointer generateGetter(StackPusher& pusher, VariableDeclaration const* vd);
static Pointer generatePublicFunctionSelector(TVMCompilerContext& pusher, ContractDefinition const *contract);
diff --git a/compiler/libsolidity/codegen/TVMPusher.cpp b/compiler/libsolidity/codegen/TVMPusher.cpp
index 1c9f7b8a..0c31da4c 100644
--- a/compiler/libsolidity/codegen/TVMPusher.cpp
+++ b/compiler/libsolidity/codegen/TVMPusher.cpp
@@ -283,12 +283,10 @@ bool StackPusher::doesDictStoreValueInRef(Type const* keyType, Type const* value
solUnimplemented("");
}
-// false - value isn't in ref
-// true - value is in ref
void StackPusher::recoverKeyAndValueAfterDictOperation(
Type const* keyType,
Type const* valueType,
- bool haveKey,
+ bool hasKey,
bool didUseOpcodeWithRef,
const DecodeType& decodeType,
bool saveOrigKeyAndNoTuple
@@ -302,10 +300,10 @@ void StackPusher::recoverKeyAndValueAfterDictOperation(
// stack: value [key]
auto preloadValue = [&]() {
- if (haveKey) {
+ if (hasKey) {
// stack: value key
if (saveOrigKeyAndNoTuple) {
- pushS(0); // stack: value key key
+ pushS(0); // stack: value key [key]
}
if (keyType->category() == Type::Category::Struct) {
StructCompiler sc{this, to(keyType)};
@@ -420,7 +418,7 @@ void StackPusher::recoverKeyAndValueAfterDictOperation(
startContinuation();
preloadValue();
- if (haveKey) {
+ if (hasKey) {
if (!saveOrigKeyAndNoTuple) {
makeTuple(2);
}
@@ -505,7 +503,7 @@ bool StackPusher::tryPollEmptyPushCont() {
return false;
}
-TVMCompilerContext &StackPusher::ctx() {
+TVMCompilerContext &StackPusher::ctx() const {
return *m_ctx;
}
@@ -1140,6 +1138,7 @@ bool StackPusher::fastLoad(const Type* type) {
}
case Type::Category::Address:
case Type::Category::Contract:
+ case Type::Category::AddressStd:
*this << "LDMSGADDR";
return true;
case Type::Category::Enum:
@@ -1213,14 +1212,6 @@ void StackPusher::preload(const Type *type) {
drop();
break;
}
- case Type::Category::Address:
- case Type::Category::Contract:
- *this << "LDMSGADDR";
- drop(1);
- break;
- case Type::Category::TvmCell:
- *this << "PLDREF";
- break;
case Type::Category::Struct: {
auto structType = to(type);
StructCompiler sc{this, structType};
@@ -1309,6 +1300,7 @@ void StackPusher::loadQ(const Type *type) {
break;
}
case Type::Category::Address:
+ case Type::Category::AddressStd:
case Type::Category::Contract:
pushAsym("LDMSGADDRQ");
break;
@@ -1412,7 +1404,7 @@ void StackPusher::store(const Type *type) {
startContinuation();
// builder value
- if (isIn(optType->valueType()->category(), Type::Category::Optional, Type::Category::Mapping)) {
+ if (optValueAsTuple(optType->valueType())) {
untuple(1);
}
// builder value
@@ -1460,6 +1452,7 @@ void StackPusher::store(const Type *type) {
break;
}
case Type::Category::Address:
+ case Type::Category::AddressStd:
case Type::Category::Contract:
case Type::Category::TvmSlice:
*this << "STSLICE"; // builder slice-value
@@ -1548,6 +1541,7 @@ void StackPusher::storeQ(const Type *type) {
pushAsym("STREFQ");
break;
case Type::Category::Address:
+ case Type::Category::AddressStd:
case Type::Category::Contract:
case Type::Category::TvmSlice:
pushAsym("STSLICEQ");
@@ -1663,7 +1657,7 @@ void StackPusher::pushFragmentInCallRef(int take, int ret, const std::string &fu
void StackPusher::pushCallOrCallRef(
FunctionDefinition const* _functionDef,
const std::optional>& deltaStack,
- bool isCalledByPoint
+ const bool isCalledByPoint
) {
auto [take, ret] = deltaStack.has_value() ?
deltaStack.value() :
@@ -2009,7 +2003,7 @@ void StackPusher::prepareMsg(
appendBody(msgInfoSize);
// stack: builder-with-body
} else {
- appendToBuilder("0"); // there is no body
+ appendToBuilder("0"); // there is no message body
}
// stack: builder'
@@ -2350,6 +2344,7 @@ void StackPusher::pushDefaultValue(Type const* _type) {
switch (cat) {
case Type::Category::Address:
case Type::Category::Contract:
+ case Type::Category::AddressStd:
pushSlice("x2_"); // addr_none$00 = MsgAddressExt;
break;
case Type::Category::Bool:
@@ -2541,6 +2536,7 @@ void TypeConversion::convert(Type const* leftType, Type const* rightType) {
fromStringLiteral(leftType, to(rightType));
break;
case Type::Category::Address:
+ case Type::Category::AddressStd:
case Type::Category::Bool:
case Type::Category::Contract:
case Type::Category::EmptyMap:
@@ -2564,7 +2560,7 @@ void TypeConversion::convert(Type const* leftType, Type const* rightType) {
}
}
-void TypeConversion::integerToInteger(IntegerType const* leftType, IntegerType const* rightType) {
+void TypeConversion::integerToInteger(IntegerType const* leftType, IntegerType const* rightType) const {
if (rightType->isImplicitlyConvertibleTo(*leftType))
return ;
@@ -2591,7 +2587,7 @@ void TypeConversion::integerToInteger(IntegerType const* leftType, IntegerType c
}
}
-void TypeConversion::fixedPointToInteger(IntegerType const* leftType, FixedPointType const* rightType) {
+void TypeConversion::fixedPointToInteger(IntegerType const* leftType, FixedPointType const* rightType) const {
int powerDiff = rightType->fractionalDigits();
if (powerDiff > 0) {
m_pusher.pushInt(MathConsts::power10().at(powerDiff));
@@ -2600,7 +2596,7 @@ void TypeConversion::fixedPointToInteger(IntegerType const* leftType, FixedPoint
integerToInteger(leftType, rightType->asIntegerType());
}
-void TypeConversion::fixedPointToFixedPoint(FixedPointType const* leftType, FixedPointType const* rightType) {
+void TypeConversion::fixedPointToFixedPoint(FixedPointType const* leftType, FixedPointType const* rightType) const {
int powerDiff = leftType->fractionalDigits() - rightType->fractionalDigits();
if (powerDiff != 0) {
if (powerDiff > 0) {
@@ -2614,7 +2610,7 @@ void TypeConversion::fixedPointToFixedPoint(FixedPointType const* leftType, Fixe
integerToInteger(leftType->asIntegerType(), rightType->asIntegerType());
}
-void TypeConversion::integerToFixedPoint(FixedPointType const* leftType, IntegerType const* rightType) {
+void TypeConversion::integerToFixedPoint(FixedPointType const* leftType, IntegerType const* rightType) const {
int powerDiff = leftType->fractionalDigits();
if (powerDiff > 0) {
m_pusher.pushInt(MathConsts::power10().at(powerDiff));
@@ -2623,7 +2619,7 @@ void TypeConversion::integerToFixedPoint(FixedPointType const* leftType, Integer
integerToInteger(leftType->asIntegerType(), rightType);
}
-void TypeConversion::fixedBytesToFixedBytes(FixedBytesType const* leftType, FixedBytesType const* rightType) {
+void TypeConversion::fixedBytesToFixedBytes(FixedBytesType const* leftType, FixedBytesType const* rightType) const {
int diff = 8 * (leftType->numBytes() - rightType->numBytes());
if (diff > 0) {
m_pusher << "LSHIFT " + std::to_string(diff);
@@ -2632,7 +2628,7 @@ void TypeConversion::fixedBytesToFixedBytes(FixedBytesType const* leftType, Fixe
}
}
-void TypeConversion::bytesToFixedBytes(FixedBytesType const* rightType) {
+auto TypeConversion::bytesToFixedBytes(FixedBytesType const *rightType) const -> void {
size_t bits = rightType->numBytes() * 8;
m_pusher.startContinuation();
m_pusher.startOpaque();
@@ -2670,11 +2666,12 @@ void TypeConversion::bytesToFixedBytes(FixedBytesType const* rightType) {
m_pusher.pushRefContAndCallX(1, 1, false);
}
-void TypeConversion::stringLiteralToFixedBytes(FixedBytesType const* leftType, StringLiteralType const* rightType) {
+void TypeConversion::stringLiteralToFixedBytes(FixedBytesType const* leftType, StringLiteralType const* rightType) const {
size_t bytes = 0;
u256 value = 0;
for (char c : rightType->value()) {
- value = value * 256 + c;
+ auto x = static_cast(c);
+ value = value * 256 + x;
++bytes;
}
while (bytes < leftType->numBytes()) {
@@ -2685,7 +2682,7 @@ void TypeConversion::stringLiteralToFixedBytes(FixedBytesType const* leftType, S
m_pusher << "PUSHINT " + toString(value);
}
-void TypeConversion::fromFixedPoint(Type const* leftType, FixedPointType const* rightType) {
+void TypeConversion::fromFixedPoint(Type const* leftType, FixedPointType const* rightType) const {
switch (leftType->category()) {
case Type::Category::FixedPoint:
fixedPointToFixedPoint(to(leftType), rightType);
@@ -2702,7 +2699,7 @@ void TypeConversion::fromFixedPoint(Type const* leftType, FixedPointType const*
}
}
-void TypeConversion::convertIntegerToAddress(Type const* t) {
+void TypeConversion::convertIntegerToAddress(Type const* t) const {
if (auto r = to(t)) {
m_pusher.drop();
m_pusher.pushSlice("x" + StrUtils::binaryStringToSlice(StrUtils::literalToSliceAddress(r->value2())));
@@ -2715,13 +2712,13 @@ void TypeConversion::convertIntegerToAddress(Type const* t) {
}
}
-void TypeConversion::convertIntegerToEnum(EnumType const* leftType, IntegerType const* /*rightType*/) {
+void TypeConversion::convertIntegerToEnum(EnumType const* leftType, IntegerType const* /*rightType*/) const {
int const size = leftType->enumDefinition().members().size();
m_pusher.pushInt(size);
m_pusher << "MOD";
}
-void TypeConversion::fromInteger(Type const* leftType, IntegerType const* rightType) {
+void TypeConversion::fromInteger(Type const* leftType, IntegerType const* rightType) const {
switch (leftType->category()) {
case Type::Category::FixedPoint:
integerToFixedPoint(to(leftType), rightType);
@@ -2743,6 +2740,7 @@ void TypeConversion::fromInteger(Type const* leftType, IntegerType const* rightT
// do nothing here
break;
case Type::Category::Address:
+ case Type::Category::AddressStd:
case Type::Category::Contract:
convertIntegerToAddress(rightType);
break;
@@ -2755,7 +2753,7 @@ void TypeConversion::fromInteger(Type const* leftType, IntegerType const* rightT
}
}
-void TypeConversion::fromRational(Type const* leftType, RationalNumberType const* rightType) {
+void TypeConversion::fromRational(Type const* leftType, RationalNumberType const* rightType) const {
switch (leftType->category()) {
case Type::Category::FixedPoint: {
auto fixedPointLeft = to(leftType);
@@ -2782,6 +2780,7 @@ void TypeConversion::fromRational(Type const* leftType, RationalNumberType const
// do nothing here
break;
case Type::Category::Address:
+ case Type::Category::AddressStd:
case Type::Category::Contract:
convertIntegerToAddress(rightType);
break;
@@ -2804,12 +2803,12 @@ void TypeConversion::tupleFromTuple(TupleType const* leftType, TupleType const*
}
}
-void TypeConversion::fromFixedBytesType(Type const* leftType, FixedBytesType const* rightType) {
+void TypeConversion::fromFixedBytesType(Type const* leftType, FixedBytesType const* rightType) const {
switch (leftType->category()) {
- case Type::Category::Address: {
+ case Type::Category::Address:
+ case Type::Category::AddressStd:
convertIntegerToAddress(rightType);
break;
- }
case Type::Category::FixedBytes: {
fixedBytesToFixedBytes(to(leftType), rightType);
break;
@@ -2841,7 +2840,7 @@ void TypeConversion::fromFixedBytesType(Type const* leftType, FixedBytesType con
}
}
-void TypeConversion::fromArray(Type const* leftType, ArrayType const* rightType) {
+void TypeConversion::fromArray(Type const* leftType, ArrayType const* rightType) const {
auto r = to(rightType);
if (!r->isByteArrayOrString()) {
return;
@@ -2895,7 +2894,7 @@ void TypeConversion::fromOptional(Type const* leftType, OptionalType const* righ
}
}
-void TypeConversion::fromSlice(Type const* leftType) {
+void TypeConversion::fromSlice(Type const* leftType) const {
switch (leftType->category()) {
case Type::Category::TvmSlice:
break;
@@ -2923,7 +2922,7 @@ void TypeConversion::fromTuple(Type const* leftType, TupleType const* rightType)
}
}
-void TypeConversion::fromStringLiteral(Type const* leftType, StringLiteralType const* rightType) {
+void TypeConversion::fromStringLiteral(Type const* leftType, StringLiteralType const* rightType) const {
switch (leftType->category()) {
case Type::Category::FixedBytes:
stringLiteralToFixedBytes(to(leftType), rightType);
diff --git a/compiler/libsolidity/codegen/TVMPusher.hpp b/compiler/libsolidity/codegen/TVMPusher.hpp
index ed687ea6..f50bb9cf 100644
--- a/compiler/libsolidity/codegen/TVMPusher.hpp
+++ b/compiler/libsolidity/codegen/TVMPusher.hpp
@@ -104,7 +104,7 @@ class TVMCompilerContext {
m_currentFunction = _f;
m_currentFunctionName = _name;
}
- FunctionDefinition const* currentFunction() { return m_currentFunction; }
+ FunctionDefinition const* currentFunction() const { return m_currentFunction; }
std::string currentFunctionName() { return m_currentFunctionName.value(); }
void resetCurrentFunction() {
m_currentFunction = nullptr;
@@ -181,7 +181,7 @@ class StackPusher {
bool tryPollEmptyPushCont();
[[nodiscard]]
- TVMCompilerContext& ctx();
+ TVMCompilerContext& ctx() const;
private:
void change(int delta);
void change(int take, int ret);
@@ -317,7 +317,7 @@ class StackPusher {
DataType prepareValueForDictOperations(Type const* keyType, Type const* valueType);
[[nodiscard]]
DataType pushDefaultValueForDict(Type const* keyType, Type const* valueType);
- bool doesDictStoreValueInRef(Type const* keyType, Type const* valueType);
+ static bool doesDictStoreValueInRef(Type const* keyType, Type const* valueType);
enum class DecodeType {
DecodeValue,
@@ -329,7 +329,7 @@ class StackPusher {
void recoverKeyAndValueAfterDictOperation(
Type const* keyType,
Type const* valueType,
- bool haveKey,
+ bool hasKey,
bool didUseOpcodeWithRef,
const DecodeType& decodeType,
bool saveOrigKeyAndNoTuple = false
@@ -412,25 +412,25 @@ class TypeConversion {
TypeConversion(StackPusher& _pusher) : m_pusher{_pusher} { }
void convert(Type const* leftType, Type const* rightType);
private:
- void integerToInteger(IntegerType const* leftType, IntegerType const* rightType);
- void fixedPointToInteger(IntegerType const* leftType, FixedPointType const* rightType);
- void fixedPointToFixedPoint(FixedPointType const* leftType, FixedPointType const* rightType);
- void integerToFixedPoint(FixedPointType const* leftType, IntegerType const* rightType);
- void fixedBytesToFixedBytes(FixedBytesType const* leftType, FixedBytesType const* rightType);
- void bytesToFixedBytes(FixedBytesType const* rightType);
- void stringLiteralToFixedBytes(FixedBytesType const* leftType, StringLiteralType const* rightType);
- void fromFixedPoint(Type const* leftType, FixedPointType const* rightType);
- void convertIntegerToAddress(Type const* t);
- void convertIntegerToEnum(EnumType const* leftType, IntegerType const* rightType);
- void fromInteger(Type const* leftType, IntegerType const* rightType);
- void fromRational(Type const* leftType, RationalNumberType const* rightType);
+ void integerToInteger(IntegerType const* leftType, IntegerType const* rightType) const;
+ void fixedPointToInteger(IntegerType const* leftType, FixedPointType const* rightType) const;
+ void fixedPointToFixedPoint(FixedPointType const* leftType, FixedPointType const* rightType) const;
+ void integerToFixedPoint(FixedPointType const* leftType, IntegerType const* rightType) const;
+ void fixedBytesToFixedBytes(FixedBytesType const* leftType, FixedBytesType const* rightType) const;
+ void bytesToFixedBytes(FixedBytesType const* rightType) const;
+ void stringLiteralToFixedBytes(FixedBytesType const* leftType, StringLiteralType const* rightType) const;
+ void fromFixedPoint(Type const* leftType, FixedPointType const* rightType) const;
+ void convertIntegerToAddress(Type const* t) const;
+ void convertIntegerToEnum(EnumType const* leftType, IntegerType const* rightType) const;
+ void fromInteger(Type const* leftType, IntegerType const* rightType) const;
+ void fromRational(Type const* leftType, RationalNumberType const* rightType) const;
void tupleFromTuple(TupleType const* leftType, TupleType const* rightType);
- void fromFixedBytesType(Type const* leftType, FixedBytesType const* rightType);
- void fromArray(Type const* leftType, ArrayType const* rightType);
+ void fromFixedBytesType(Type const* leftType, FixedBytesType const* rightType) const;
+ void fromArray(Type const* leftType, ArrayType const* rightType) const;
void fromOptional(Type const* leftType, OptionalType const* rightType);
- void fromSlice(Type const* leftType);
+ void fromSlice(Type const* leftType) const;
void fromTuple(Type const* leftType, TupleType const* rightType);
- void fromStringLiteral(Type const* leftType, StringLiteralType const* rightType);
+ void fromStringLiteral(Type const* leftType, StringLiteralType const* rightType) const;
private:
StackPusher& m_pusher;
}; // end TypeConversion
diff --git a/compiler/libsolidity/codegen/TVMTypeChecker.cpp b/compiler/libsolidity/codegen/TVMTypeChecker.cpp
index 866db565..f72fb30a 100644
--- a/compiler/libsolidity/codegen/TVMTypeChecker.cpp
+++ b/compiler/libsolidity/codegen/TVMTypeChecker.cpp
@@ -362,7 +362,7 @@ void TVMTypeChecker::checkDeprecation(FunctionCall const& _functionCall) {
m_errorReporter.warning(4767_error, _functionCall.location(),
"\"tvm.functionId()\" is deprecated. Use: \"abi.functionId()\"");
break;
- case FunctionType::Kind::ABIBuildIntMsg:
+ case FunctionType::Kind::ABIEncodeIntMsg:
if (kind == MagicType::Kind::TVM)
m_errorReporter.warning(4063_error, _functionCall.location(),
"\"tvm.buildIntMsg()\" is deprecated. Use: \"abi.encodeIntMsg()\"");
@@ -445,12 +445,17 @@ bool TVMTypeChecker::visit(FunctionCall const& _functionCall) {
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(
- 7993_error, _functionCall.location(),
- "It is forbidden to call base functions of \"onCodeUpgrade\".");
+ if (auto fd = to(&functionType->declaration())) {
+ if (fd->name() == "onCodeUpgrade") {
+ if (m_inherHelper->isBaseFunction(fd)) {
+ m_errorReporter.typeError(
+ 7993_error, _functionCall.location(),
+ "It is forbidden to call base functions of \"onCodeUpgrade\".");
+ }
+ }
+ if (fd->visibility() == Visibility::Getter) {
+ m_errorReporter.typeError(7162_error, _functionCall.location(),
+ "It is forbidden to call getter from the contract. Only off-chain.");
}
}
}
diff --git a/compiler/libsolidity/codegen/TvmAst.hpp b/compiler/libsolidity/codegen/TvmAst.hpp
index 588d2b69..36c8cfb1 100644
--- a/compiler/libsolidity/codegen/TvmAst.hpp
+++ b/compiler/libsolidity/codegen/TvmAst.hpp
@@ -490,22 +490,24 @@ class Function : public TvmAstNode {
class Contract : public TvmAstNode {
public:
- explicit Contract(
+ Contract(
bool _isLib,
bool _saveAllFunction,
bool _upgradeFunc,
bool upgradeOldSolidity,
std::string _version,
- std::vector> functions,
- std::map _privateFunctions
+ std::vector> _functions,
+ std::map _privateFunctions,
+ std::map _getters
) :
m_isLib{_isLib},
m_saveAllFunction{_saveAllFunction},
m_upgradeFunc{_upgradeFunc},
m_upgradeOldSolidity{upgradeOldSolidity},
m_version{std::move(_version)},
- m_functions{std::move(functions)},
- m_privateFunctions{std::move(_privateFunctions)}
+ m_functions{std::move(_functions)},
+ m_privateFunctions{std::move(_privateFunctions)},
+ m_getters{std::move(_getters)}
{
}
void accept(TvmAstVisitor& _visitor) override;
@@ -517,6 +519,7 @@ class Contract : public TvmAstNode {
std::string const& version() const { return m_version; }
std::vector> const& functions() const { return m_functions; }
std::map const& privateFunctions() const { return m_privateFunctions; }
+ std::map const& getters() const { return m_getters; }
private:
bool m_isLib{};
bool m_saveAllFunction{};
@@ -525,6 +528,7 @@ class Contract : public TvmAstNode {
std::string m_version;
std::vector> m_functions;
std::map m_privateFunctions;
+ std::map m_getters;
};
Pointer gen(const std::string& cmd);
diff --git a/compiler/libsolidity/codegen/TvmAstVisitor.cpp b/compiler/libsolidity/codegen/TvmAstVisitor.cpp
index ef65dcc6..27f1bae1 100644
--- a/compiler/libsolidity/codegen/TvmAstVisitor.cpp
+++ b/compiler/libsolidity/codegen/TvmAstVisitor.cpp
@@ -703,6 +703,40 @@ bool Printer::visit(While &_node) {
return false;
}
+void Printer::printTickTockAndGetters(bool _hasOnTickTock, std::map const& _getters) {
+ if (_hasOnTickTock || !_getters.empty()) {
+ tabs(); m_out << "JMPREF {" << std::endl;
+ {
+ ++m_tab;
+
+ if (_hasOnTickTock) {
+ tabs(); m_out << "DUP" << std::endl;
+ tabs(); m_out << "EQINT -2" << std::endl;
+ tabs(); m_out << "IFJMPREF {" << std::endl;
+ tabs(); m_out << " .inline onTickTock" << std::endl;
+ tabs(); m_out << "}" << std::endl;
+ }
+
+ if (!_getters.empty()) {
+ tabs(); m_out << "DICTPUSHCONST 19" << std::endl;
+ tabs(); m_out << "DICTUGETJMPZ" << std::endl;
+ tabs(); m_out << "THROW 11" << std::endl;
+ tabs(); m_out << ".code-dict-cell 19, {" << std::endl;
+ ++m_tab;
+ for (auto const& [id, name] : _getters) {
+ std::string slice = StrUtils::binaryStringToSlice(StrUtils::toBitString(id, 19, false).value());
+ tabs(); m_out << "x" << slice << " = " << name << "," << std::endl;
+ }
+ --m_tab;
+ tabs(); m_out << "}" << std::endl; // end .code-dict-cell
+ }
+
+ --m_tab;
+ }
+ tabs(); m_out << "}" << std::endl; // end JMPREF
+ }
+}
+
bool Printer::visit(Contract &_node) {
std::map privFuncs = _node.privateFunctions();
for (Pointer const& fun : _node.functions()) {
@@ -724,12 +758,6 @@ bool Printer::visit(Contract &_node) {
}
if (!_node.isLib()) {
- if (!hasOnTickTock) {
- m_out << ".fragment onTickTock, {" << std::endl;
- m_out << "}" << std::endl;
- m_out << std::endl;
- }
-
m_out << "; The code below forms a value of the StateInit type." << std::endl;
m_out << ".blob x4_ ; split_depth = nothing" << std::endl;
m_out << ".blob x4_ ; special = nothing" << std::endl;
@@ -766,15 +794,11 @@ bool Printer::visit(Contract &_node) {
tabs(); m_out << "IFJMPREF {" << std::endl;
tabs(); m_out << " .inline main_external" << std::endl;
tabs(); m_out << "}" << std::endl;
- tabs(); m_out << "DUP" << std::endl;
- tabs(); m_out << "EQINT -2" << std::endl;
- tabs(); m_out << "IFJMPREF {" << std::endl;
- tabs(); m_out << " .inline onTickTock" << std::endl;
- tabs(); m_out << "}" << std::endl;
- tabs(); m_out << "THROW 11" << std::endl;
+ printTickTockAndGetters(hasOnTickTock, _node.getters());
--m_tab;
tabs(); m_out << "}" << std::endl; // end code
};
+
if (_node.upgradeOldSolidity() || _node.upgradeFunc()) {
int func_id = _node.upgradeFunc() ? 1666 : 2;
m_out << ".cell { ; wrapper for code" << std::endl;
diff --git a/compiler/libsolidity/codegen/TvmAstVisitor.hpp b/compiler/libsolidity/codegen/TvmAstVisitor.hpp
index 992d4672..aaecd4e4 100644
--- a/compiler/libsolidity/codegen/TvmAstVisitor.hpp
+++ b/compiler/libsolidity/codegen/TvmAstVisitor.hpp
@@ -89,6 +89,7 @@ class Printer : public TvmAstVisitor {
void tabs();
void printPushInt(std::string const& arg, std::string const& comment = "");
void printPushInt(int i);
+ void printTickTockAndGetters(bool _hasOnTickTock, std::map const& _getters);
private:
std::ostream& m_out;
int m_tab{};
diff --git a/compiler/libsolidity/parsing/Parser.cpp b/compiler/libsolidity/parsing/Parser.cpp
index 068b49ae..1e15d868 100644
--- a/compiler/libsolidity/parsing/Parser.cpp
+++ b/compiler/libsolidity/parsing/Parser.cpp
@@ -480,6 +480,9 @@ Visibility Parser::parseVisibilitySpecifier()
Token token = m_scanner->currentToken();
switch (token)
{
+ case Token::Getter:
+ visibility = Visibility::Getter;
+ break;
case Token::Public:
visibility = Visibility::Public;
break;
diff --git a/compiler/libsolidity/parsing/Parser.h b/compiler/libsolidity/parsing/Parser.h
index c4f982eb..7fb41d4b 100644
--- a/compiler/libsolidity/parsing/Parser.h
+++ b/compiler/libsolidity/parsing/Parser.h
@@ -81,6 +81,7 @@ class Parser: public langutil::ParserBase
bool externalMsg = false;
bool internalMsg = false;
bool assembly = false;
+ bool isGetter = false;
ASTPointer experimentalReturnExpression;
};
diff --git a/compiler/scripts/install_deps.sh b/compiler/scripts/install_deps.sh
index a07d5440..207b7203 100755
--- a/compiler/scripts/install_deps.sh
+++ b/compiler/scripts/install_deps.sh
@@ -71,47 +71,6 @@ case $(uname -s) in
#------------------------------------------------------------------------------
Darwin)
- case $(sw_vers -productVersion | awk -F . '{print $1"."$2}') in
- 10.9)
- echo "Installing solidity dependencies on OS X 10.9 Mavericks."
- ;;
- 10.10)
- echo "Installing solidity dependencies on OS X 10.10 Yosemite."
- ;;
- 10.11)
- echo "Installing solidity dependencies on OS X 10.11 El Capitan."
- ;;
- 10.12)
- echo "Installing solidity dependencies on macOS 10.12 Sierra."
- ;;
- 10.13)
- echo "Installing solidity dependencies on macOS 10.13 High Sierra."
- ;;
- 10.14)
- echo "Installing solidity dependencies on macOS 10.14 Mojave."
- ;;
- 10.15)
- echo "Installing solidity dependencies on macOS 10.15 Catalina."
- ;;
- 11.0 | 11.1 | 11.2 | 11.3 | 11.4)
- echo "Installing solidity dependencies on macOS 11.0 / 11.1 / 11.2 / 11.3 / 11.4 Big Sur."
- ;;
- 12.*)
- echo "Installing solidity dependencies on macOS 12 Monterey."
- ;;
- 13.*)
- echo "Installing solidity dependencies on macOS 13."
- ;;
- 14.*)
- echo "Installing solidity dependencies on macOS 14."
- ;;
- *)
- echo "Unsupported macOS version."
- echo "We only support Mavericks, Yosemite, El Capitan, Sierra, High Sierra, Mojave, Catalina, Big Sur and Monterey."
- exit 1
- ;;
- esac
-
# Check for Homebrew install and abort if it is not installed.
brew -v > /dev/null 2>&1 || { echo >&2 "ERROR - solidity requires a Homebrew install. See https://brew.sh."; exit 1; }
brew update
diff --git a/compiler/solc/CommandLineInterface.cpp b/compiler/solc/CommandLineInterface.cpp
index abcb87a6..7897678d 100644
--- a/compiler/solc/CommandLineInterface.cpp
+++ b/compiler/solc/CommandLineInterface.cpp
@@ -465,7 +465,6 @@ void CommandLineInterface::compile()
SourceReferenceFormatter formatter(serr(false), *m_compiler, coloredOutput(m_options), m_options.formatting.withErrorIds);
- bool successful = true;
try
{
if (m_options.metadata.literalSources)
@@ -547,6 +546,7 @@ void CommandLineInterface::compile()
m_compiler->setOutputFolder(m_options.output.dir.string());
m_compiler->setTVMVersion(m_options.tvmParams.tvmVersion);
+ bool successful = true;
bool didCompileSomething = false;
std::tie(successful, didCompileSomething) = m_compiler->compile();
m_hasOutput |= didCompileSomething;
@@ -557,6 +557,8 @@ void CommandLineInterface::compile()
formatter.printErrorInformation(*error);
}
+ if (!successful)
+ solThrow(CommandLineExecutionError, "");
}
catch (CompilerError const& _exception)
{
@@ -581,22 +583,6 @@ void CommandLineInterface::compile()
solThrow(CommandLineExecutionError, "");
}
}
- catch (util::Exception const& exception)
- {
-
- serr() << exception.what() << std::endl;
- serr() << exception.lineInfo() << std::endl;
- serr() << "Internal error" << std::endl
- << "Please report your bug to https://github.com/everx-labs/TVM-Solidity-Compiler/issues" << std::endl;
- }
- catch (...)
- {
- serr() << "Internal error" << std::endl
- << "Please report your bug to https://github.com/everx-labs/TVM-Solidity-Compiler/issues" << std::endl;
- }
-
- if (!successful)
- solThrow(CommandLineExecutionError, "");
}
void CommandLineInterface::handleAst()
diff --git a/compiler/solc/main.cpp b/compiler/solc/main.cpp
index 4237f9ac..2aa901fc 100644
--- a/compiler/solc/main.cpp
+++ b/compiler/solc/main.cpp
@@ -31,6 +31,11 @@
using namespace solidity;
+namespace {
+void printReportBug() {
+ std::cerr << "Please report your bug to https://github.com/everx-labs/TVM-Solidity-Compiler/issues" << std::endl;
+}
+}
int main(int argc, char** argv)
{
@@ -43,24 +48,28 @@ int main(int argc, char** argv)
{
std::cerr << "SMT logic error:" << std::endl;
std::cerr << boost::diagnostic_information(_exception);
+ printReportBug();
return 2;
}
catch (langutil::UnimplementedFeatureError const& _exception)
{
std::cerr << "Unimplemented feature:" << std::endl;
std::cerr << boost::diagnostic_information(_exception);
+ printReportBug();
return 2;
}
catch (langutil::InternalCompilerError const& _exception)
{
std::cerr << "Internal compiler error:" << std::endl;
std::cerr << boost::diagnostic_information(_exception);
+ printReportBug();
return 2;
}
catch (...)
{
std::cerr << "Uncaught exception:" << std::endl;
std::cerr << boost::current_exception_diagnostic_information() << std::endl;
+ printReportBug();
return 2;
}
}
diff --git a/lib/stdlib.sol b/lib/stdlib.sol
index 2711cbbb..a6ebbedd 100644
--- a/lib/stdlib.sol
+++ b/lib/stdlib.sol
@@ -118,6 +118,24 @@ contract stdlib {
return st;
}
+ // Append slice in hex format with tag _ if needs
+ function __appendSliceDataAsHex(stack(TvmBuilder) st, TvmSlice data) pure private returns(stack(TvmBuilder)) {
+ while (data.bits() >= 4) {
+ uint9 bits = uint9(math.min(data.bits() / 4 * 4, 256));
+ uint value = data.loadUint(bits);
+ st = __convertIntToHexString(st, value, bits / 4, true, true);
+ }
+ if (data.bits() != 0) {
+ uint10 shift = 4 - data.bits();
+ int value = data.loadUint(uint9(data.bits()));
+ value = (value << 1) + 1;
+ value <<= (shift - 1);
+ st = __convertIntToHexString(st, value, 1, true, true);
+ st = __appendBytes1(st, bytes1("_"));
+ }
+ return st;
+ }
+
function __appendSliceToStringBuilder(stack(TvmBuilder) st, TvmSlice s) pure private returns(stack(TvmBuilder)) {
uint10 restBits = st.top().remBits() - 7; // 1023 - 7 = 1016 = 127 * 8
TvmSlice ss = s.loadSlice(math.min(restBits, s.bits()), 0);
@@ -210,15 +228,35 @@ contract stdlib {
return st;
}
- function __convertAddressToHexString(stack(TvmBuilder) st, address addr) private pure returns (stack(TvmBuilder)) {
- (int32 wid, uint value) = addr.unpack();
- st = __convertIntToHexString(st, wid, 0, false, true);
- uint16 remBits = st.top().remBits();
- if (remBits < 8) {
- st.push(TvmBuilder());
+ function __appendAnyCast(stack(TvmBuilder) st, TvmSlice addr) private pure returns (stack(TvmBuilder), TvmSlice) {
+ bool hasAnycast = addr.load(bool);
+ if (hasAnycast) {
+ uint5 depth = addr.load(uint5);
+ st = __appendSliceDataAsHex(st, addr.loadSlice(depth));
+ st = __appendBytes1(st, bytes1(":"));
+ }
+ return (st, addr);
+ }
+
+ function __convertAddressToHexString(stack(TvmBuilder) st, TvmSlice addr) private pure returns (stack(TvmBuilder)) {
+ uint2 addrType = addr.load(uint2);
+ if (addrType == 2) { // addr_std
+ (st, addr) = __appendAnyCast(st, addr);
+ st = __convertIntToString(st, addr.load(int8), 0, false);
+ st = __appendBytes1(st, bytes1(":"));
+ st = __convertIntToHexString(st, addr.load(uint256), 64, true, true);
+ } else if (addrType == 1) { // addr_extern
+ st = __appendBytes1(st, bytes1(":"));
+ addr.load(uint9);
+ st = __appendSliceDataAsHex(st, addr);
+ } else if (addrType == 3) { // addr_var
+ (st, addr) = __appendAnyCast(st, addr);
+ addr.skip(9); // addr_len
+ st = __convertIntToString(st, addr.load(int32), 0, false);
+ st = __appendBytes1(st, bytes1(":"));
+ st = __appendSliceDataAsHex(st, addr);
}
- st.top().store(bytes1(":"));
- return __convertIntToHexString(st, value, 64, true, true);
+ return st;
}
function __convertFixedPointToString(stack(TvmBuilder) st, int257 value, uint16 fractionalDigits, uint fractionPow10) private pure returns (stack(TvmBuilder)) {
diff --git a/lib/stdlib_sol.tvm b/lib/stdlib_sol.tvm
index 48f004bd..a24d00b4 100644
--- a/lib/stdlib_sol.tvm
+++ b/lib/stdlib_sol.tvm
@@ -23,327 +23,6 @@
.loc stdlib.sol, 0
}
-.fragment __appendBytes1NTimes, {
- .loc stdlib.sol, 115
- PUSHCONT {
- .loc stdlib.sol, 116
- DUP2
- CALLREF {
- .inline __appendBytes1
- }
- POP S2
- .loc stdlib.sol, 0
- }
- REPEAT
- .loc stdlib.sol, 118
- DROP
- .loc stdlib.sol, 0
-}
-
-.fragment __appendSliceToStringBuilder, {
- .loc stdlib.sol, 122
- OVER
- FIRST
- BREMBITS
- ADDCONST -7
- .loc stdlib.sol, 123
- PUXCPU S1, S-1, S0
- SBITS
- MIN
- LDSLICEX
- POP S2
- .loc stdlib.sol, 124
- PUSH S2
- UNPAIR
- ROTREV
- STSLICE
- SWAP
- PAIR
- POP S2
- .loc stdlib.sol, 125
- DUP
- SEMPTY
- PUSHCONT {
- .loc stdlib.sol, 127
- DUP
- NEWC
- STSLICE
- .loc stdlib.sol, 128
- PUSH S2
- PAIR
- POP S2
- .loc stdlib.sol, 0
- }
- IFNOT
- .loc stdlib.sol, 130
- DROP
- .loc stdlib.sol, 0
-}
-
-.fragment __appendStringToStringBuilderWithNoShift, {
- .loc stdlib.sol, 134
- DUP
- CTOS
- .loc stdlib.sol, 135
- PUSHCONT {
- .loc stdlib.sol, 136
- PUSH S2
- UNPAIR
- XCPU2 S1, S2, S2
- SBITS
- LDSLICEX
- POP S4
- STSLICER
- SWAP
- PAIR
- POP S3
- .loc stdlib.sol, 137
- DUP
- SEMPTY
- IFRETALT
- .loc stdlib.sol, 139
- NEWC
- PUSH S3
- PAIR
- POP S3
- .loc stdlib.sol, 140
- LDREFRTOS
- NIP
- .loc stdlib.sol, 0
- }
- AGAINBRK
- .loc stdlib.sol, 142
- DROP2
- .loc stdlib.sol, 0
-}
-
-.fragment __appendStringToStringBuilder, {
- .loc stdlib.sol, 146
- NULL
- .loc stdlib.sol, 147
- PUSH S2
- FIRST
- BBITS
- PUSHCONT {
- .loc stdlib.sol, 148
- ROTREV
- CALLREF {
- .inline __appendStringToStringBuilderWithNoShift
- }
- NIP
- .loc stdlib.sol, 0
- }
- IFNOTJMP
- .loc stdlib.sol, 150
- OVER
- CTOS
- .loc stdlib.sol, 151
- PUSHCONT {
- .loc stdlib.sol, 152
- BLKPUSH 2, 0
- SBITS
- LDSLICEX
- POP S2
- PUXC S4, S-1
- .loc stdlib.sol, 153
- CALLREF {
- .inline __appendSliceToStringBuilder
- }
- POP S4
- .loc stdlib.sol, 154
- DUP
- SEMPTY
- IFRETALT
- .loc stdlib.sol, 156
- LDREFRTOS
- NIP
- .loc stdlib.sol, 0
- }
- AGAINBRK
- .loc stdlib.sol, 158
- BLKDROP 3
- .loc stdlib.sol, 0
-}
-
-.fragment __createStringBuilder, {
- .loc stdlib.sol, 90
- NEWC
- NULL
- PAIR
- .loc stdlib.sol, 0
-}
-
-.fragment __makeString, {
- .loc stdlib.sol, 96
- UNPAIR
- SWAP
- .loc stdlib.sol, 97
- PUSHCONT {
- OVER
- ISNULL
- NOT
- }
- PUSHCONT {
- .loc stdlib.sol, 98
- OVER
- UNPAIR
- POP S3
- .loc stdlib.sol, 99
- STBREF
- .loc stdlib.sol, 0
- }
- WHILE
- .loc stdlib.sol, 102
- ENDC
- NIP
- .loc stdlib.sol, 0
-}
-
-.fragment __subCell, {
- .loc stdlib.sol, 353
- PUSH S2
- PUSHINT 127
- DIVMOD
- .loc stdlib.sol, 354
- OVER
- NEQINT 0
- OVER
- EQINT 0
- AND
- PUSHCONT {
- .loc stdlib.sol, 355
- DROP
- DEC
- .loc stdlib.sol, 356
- PUSHINT 127
- .loc stdlib.sol, 0
- }
- IF
- .loc stdlib.sol, 359
- PUSH S5
- CTOS
- .loc stdlib.sol, 360
- PUSH S2
- PUSHCONT {
- .loc stdlib.sol, 361
- DUP
- SREFS
- EQINT 1
- THROWIFNOT 70
- .loc stdlib.sol, 362
- LDREFRTOS
- NIP
- .loc stdlib.sol, 0
- }
- REPEAT
- .loc stdlib.sol, 365
- OVER
- MULCONST 8
- POP S2
- .loc stdlib.sol, 366
- DUP
- SBITS
- PUSH S2
- GEQ
- THROWIFNOT 70
- .loc stdlib.sol, 367
- OVER
- SDSKIPFIRST
- .loc stdlib.sol, 369
- PUSH S4
- MULCONST 8
- POP S5
- .loc stdlib.sol, 370
- CALLREF {
- .inline __createStringBuilder
- }
- .loc stdlib.sol, 371
- PUSHCONT {
- .loc stdlib.sol, 372
- OVER
- SBITS
- PUSH S6
- MIN
- UFITS 10
- .loc stdlib.sol, 373
- PUSH2 S6, S0
- SUB
- POP S7
- PUXC S2, S-1
- .loc stdlib.sol, 374
- LDSLICEX
- POP S3
- .loc stdlib.sol, 375
- CALLREF {
- .inline __appendSliceToStringBuilder
- }
- .loc stdlib.sol, 376
- PUSH S5
- EQINT 0
- PUSH S2
- SEMPTY
- OR
- IFRETALT
- .loc stdlib.sol, 379
- OVER
- LDREFRTOS
- NIP
- POP S2
- .loc stdlib.sol, 0
- }
- AGAINBRK
- .loc stdlib.sol, 381
- BLKSWAP 2, 4
- SWAP
- EQINT 0
- OR
- THROWIFNOT 70
- .loc stdlib.sol, 382
- CALLREF {
- .inline __makeString
- }
- BLKDROP2 5, 1
- .loc stdlib.sol, 0
-}
-
-.fragment __arraySlice, {
- .loc stdlib.sol, 347
- DUP2
- LEQ
- THROWIFNOT 70
- .loc stdlib.sol, 348
- OVER
- SUB
- .loc stdlib.sol, 349
- FALSE
- CALLREF {
- .inline __subCell
- }
- .loc stdlib.sol, 0
-}
-
-.fragment __concatenateStrings, {
- .loc stdlib.sol, 411
- CALLREF {
- .inline __createStringBuilder
- }
- .loc stdlib.sol, 412
- ROT
- CALLREF {
- .inline __appendStringToStringBuilderWithNoShift
- }
- .loc stdlib.sol, 413
- SWAP
- CALLREF {
- .inline __appendStringToStringBuilder
- }
- .loc stdlib.sol, 414
- CALLREF {
- .inline __makeString
- }
- .loc stdlib.sol, 0
-}
-
.fragment __parseInteger, {
.loc stdlib.sol, 73
OVER
@@ -386,35 +65,35 @@
}
.fragment __convertIntToHexString, {
- .loc stdlib.sol, 243
+ .loc stdlib.sol, 281
PUSH S3
LESSINT 0
- .loc stdlib.sol, 244
+ .loc stdlib.sol, 282
ROLL 4
ABS
- .loc stdlib.sol, 245
+ .loc stdlib.sol, 283
PUSH S5
FIRST
BREMBITS
RSHIFT 3
- .loc stdlib.sol, 247
+ .loc stdlib.sol, 285
ROT
PUSHCONT {
- .loc stdlib.sol, 248
+ .loc stdlib.sol, 286
DUP
PUSHCONT {
- .loc stdlib.sol, 249
+ .loc stdlib.sol, 287
NEWC
PUSH S6
PAIR
POP S6
- .loc stdlib.sol, 250
+ .loc stdlib.sol, 288
DROP
PUSHINT 127
.loc stdlib.sol, 0
}
IFNOT
- .loc stdlib.sol, 252
+ .loc stdlib.sol, 290
PUSH S5
UNPAIR
PUSHINT 45
@@ -423,34 +102,34 @@
SWAP
PAIR
POP S6
- .loc stdlib.sol, 253
+ .loc stdlib.sol, 291
DEC
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 256
+ .loc stdlib.sol, 294
SWAP
PUSHINT 16
CALLREF {
.inline __parseInteger
}
- .loc stdlib.sol, 258
+ .loc stdlib.sol, 296
PUSH2 S5, S0
GREATER
PUSHCONT {
- .loc stdlib.sol, 259
+ .loc stdlib.sol, 297
PUSH S4
PUSHINT 48
PUSHINT 32
CONDSEL
- .loc stdlib.sol, 260
+ .loc stdlib.sol, 298
PUSH2 S6, S1
SUB
- .loc stdlib.sol, 261
+ .loc stdlib.sol, 299
PUSH2 S0, S4
MIN
PUSHCONT {
- .loc stdlib.sol, 262
+ .loc stdlib.sol, 300
PUSH S8
UNPAIR
PUXC S3, S1
@@ -461,20 +140,20 @@
.loc stdlib.sol, 0
}
REPEAT
- .loc stdlib.sol, 264
+ .loc stdlib.sol, 302
PUSH2 S0, S4
GREATER
PUSHCONT {
- .loc stdlib.sol, 265
+ .loc stdlib.sol, 303
NEWC
PUSH S9
PAIR
POP S9
- .loc stdlib.sol, 266
+ .loc stdlib.sol, 304
PUSH2 S0, S4
SUB
PUSHCONT {
- .loc stdlib.sol, 267
+ .loc stdlib.sol, 305
PUSH S8
UNPAIR
PUXC S3, S1
@@ -485,12 +164,12 @@
.loc stdlib.sol, 0
}
REPEAT
- .loc stdlib.sol, 269
+ .loc stdlib.sol, 307
PUSH S4
ADDCONST 127
}
PUSHCONT {
- .loc stdlib.sol, 271
+ .loc stdlib.sol, 309
PUSH S4
}
IFELSE
@@ -501,23 +180,23 @@
DROP2
}
IF
- .loc stdlib.sol, 275
+ .loc stdlib.sol, 313
ROLL 3
PUSHINT 97
PUSHINT 65
CONDSEL
ADDCONST -10
- .loc stdlib.sol, 276
+ .loc stdlib.sol, 314
PUSH2 S1, S3
MIN
PUSHCONT {
- .loc stdlib.sol, 278
+ .loc stdlib.sol, 316
PUSH2 S2, S2
ISNULL
THROWIF 63
UNPAIR
POP S4
- .loc stdlib.sol, 279
+ .loc stdlib.sol, 317
PUSH S7
UNPAIR
XCPU S2, S0
@@ -533,26 +212,26 @@
.loc stdlib.sol, 0
}
REPEAT
- .loc stdlib.sol, 281
+ .loc stdlib.sol, 319
PUSH2 S1, S3
GREATER
PUSHCONT {
- .loc stdlib.sol, 282
+ .loc stdlib.sol, 320
NEWC
PUSH S7
PAIR
POP S7
- .loc stdlib.sol, 283
+ .loc stdlib.sol, 321
PUSH2 S1, S3
SUB
PUSHCONT {
- .loc stdlib.sol, 285
+ .loc stdlib.sol, 323
PUSH2 S2, S2
ISNULL
THROWIF 63
UNPAIR
POP S4
- .loc stdlib.sol, 286
+ .loc stdlib.sol, 324
PUSH S7
UNPAIR
XCPU S2, S0
@@ -570,109 +249,466 @@
REPEAT
.loc stdlib.sol, 0
}
- IF
- .loc stdlib.sol, 289
- BLKDROP 6
- .loc stdlib.sol, 0
-}
-
-.fragment __convertAddressToHexString, {
- .loc stdlib.sol, 214
- REWRITESTDADDR
- .loc stdlib.sol, 215
- PUXC S2, S1
- PUSHINT 0
+ IF
+ .loc stdlib.sol, 327
+ BLKDROP 6
+ .loc stdlib.sol, 0
+}
+
+.fragment __appendSliceDataAsHex, {
+ .loc stdlib.sol, 123
+ PUSHCONT {
+ DUP
+ SBITS
+ GTINT 3
+ }
+ PUSHCONT {
+ .loc stdlib.sol, 124
+ DUP
+ SBITS
+ RSHIFT 2
+ MULCONST 4
+ PUSHPOW2 8
+ MIN
+ UFITS 9
+ .loc stdlib.sol, 125
+ DUP2
+ LDUX
+ POP S3
+ PUXC2 S3, S-1, S0
+ .loc stdlib.sol, 126
+ RSHIFT 2
+ TRUE
+ DUP
+ CALLREF {
+ .inline __convertIntToHexString
+ }
+ POP S2
+ .loc stdlib.sol, 0
+ }
+ WHILE
+ .loc stdlib.sol, 128
+ DUP
+ SBITS
+ PUSHCONT {
+ .loc stdlib.sol, 129
+ PUSHINT 4
+ OVER
+ SBITS
+ SUB
+ .loc stdlib.sol, 130
+ PUSH2 S1, S1
+ SBITS
+ UFITS 9
+ LDUX
+ POP S3
+ .loc stdlib.sol, 131
+ LSHIFT 1
+ INC
+ .loc stdlib.sol, 132
+ SWAP
+ DEC
+ LSHIFT
+ .loc stdlib.sol, 133
+ PUXC S2, S-1
+ PUSHINT 1
+ TRUE
+ DUP
+ CALLREF {
+ .inline __convertIntToHexString
+ }
+ .loc stdlib.sol, 134
+ PUSHINT 95
+ CALLREF {
+ .inline __appendBytes1
+ }
+ POP S2
+ .loc stdlib.sol, 0
+ }
+ IF
+ .loc stdlib.sol, 136
+ DROP
+ .loc stdlib.sol, 0
+}
+
+.fragment __appendAnyCast, {
+ .loc stdlib.sol, 232
+ LDI 1
+ SWAP
+ .loc stdlib.sol, 233
+ PUSHCONT {
+ .loc stdlib.sol, 234
+ LDU 5
+ PU2XC S2, S-1, S1
+ .loc stdlib.sol, 235
+ LDSLICEX
+ POP S3
+ CALLREF {
+ .inline __appendSliceDataAsHex
+ }
+ .loc stdlib.sol, 236
+ PUSHINT 58
+ CALLREF {
+ .inline __appendBytes1
+ }
+ POP S2
+ .loc stdlib.sol, 0
+ }
+ IF
+ .loc stdlib.sol, 0
+}
+
+.fragment __appendBytes1NTimes, {
+ .loc stdlib.sol, 115
+ PUSHCONT {
+ .loc stdlib.sol, 116
+ DUP2
+ CALLREF {
+ .inline __appendBytes1
+ }
+ POP S2
+ .loc stdlib.sol, 0
+ }
+ REPEAT
+ .loc stdlib.sol, 118
+ DROP
+ .loc stdlib.sol, 0
+}
+
+.fragment __appendSliceToStringBuilder, {
+ .loc stdlib.sol, 140
+ OVER
+ FIRST
+ BREMBITS
+ ADDCONST -7
+ .loc stdlib.sol, 141
+ PUXCPU S1, S-1, S0
+ SBITS
+ MIN
+ LDSLICEX
+ POP S2
+ .loc stdlib.sol, 142
+ PUSH S2
+ UNPAIR
+ ROTREV
+ STSLICE
+ SWAP
+ PAIR
+ POP S2
+ .loc stdlib.sol, 143
+ DUP
+ SEMPTY
+ PUSHCONT {
+ .loc stdlib.sol, 145
+ DUP
+ NEWC
+ STSLICE
+ .loc stdlib.sol, 146
+ PUSH S2
+ PAIR
+ POP S2
+ .loc stdlib.sol, 0
+ }
+ IFNOT
+ .loc stdlib.sol, 148
+ DROP
+ .loc stdlib.sol, 0
+}
+
+.fragment __appendStringToStringBuilderWithNoShift, {
+ .loc stdlib.sol, 152
+ DUP
+ CTOS
+ .loc stdlib.sol, 153
+ PUSHCONT {
+ .loc stdlib.sol, 154
+ PUSH S2
+ UNPAIR
+ XCPU2 S1, S2, S2
+ SBITS
+ LDSLICEX
+ POP S4
+ STSLICER
+ SWAP
+ PAIR
+ POP S3
+ .loc stdlib.sol, 155
+ DUP
+ SEMPTY
+ IFRETALT
+ .loc stdlib.sol, 157
+ NEWC
+ PUSH S3
+ PAIR
+ POP S3
+ .loc stdlib.sol, 158
+ LDREFRTOS
+ NIP
+ .loc stdlib.sol, 0
+ }
+ AGAINBRK
+ .loc stdlib.sol, 160
+ DROP2
+ .loc stdlib.sol, 0
+}
+
+.fragment __appendStringToStringBuilder, {
+ .loc stdlib.sol, 164
+ NULL
+ .loc stdlib.sol, 165
+ PUSH S2
+ FIRST
+ BBITS
+ PUSHCONT {
+ .loc stdlib.sol, 166
+ ROTREV
+ CALLREF {
+ .inline __appendStringToStringBuilderWithNoShift
+ }
+ NIP
+ .loc stdlib.sol, 0
+ }
+ IFNOTJMP
+ .loc stdlib.sol, 168
+ OVER
+ CTOS
+ .loc stdlib.sol, 169
+ PUSHCONT {
+ .loc stdlib.sol, 170
+ BLKPUSH 2, 0
+ SBITS
+ LDSLICEX
+ POP S2
+ PUXC S4, S-1
+ .loc stdlib.sol, 171
+ CALLREF {
+ .inline __appendSliceToStringBuilder
+ }
+ POP S4
+ .loc stdlib.sol, 172
+ DUP
+ SEMPTY
+ IFRETALT
+ .loc stdlib.sol, 174
+ LDREFRTOS
+ NIP
+ .loc stdlib.sol, 0
+ }
+ AGAINBRK
+ .loc stdlib.sol, 176
+ BLKDROP 3
+ .loc stdlib.sol, 0
+}
+
+.fragment __createStringBuilder, {
+ .loc stdlib.sol, 90
+ NEWC
+ NULL
+ PAIR
+ .loc stdlib.sol, 0
+}
+
+.fragment __makeString, {
+ .loc stdlib.sol, 96
+ UNPAIR
+ SWAP
+ .loc stdlib.sol, 97
+ PUSHCONT {
+ OVER
+ ISNULL
+ NOT
+ }
+ PUSHCONT {
+ .loc stdlib.sol, 98
+ OVER
+ UNPAIR
+ POP S3
+ .loc stdlib.sol, 99
+ STBREF
+ .loc stdlib.sol, 0
+ }
+ WHILE
+ .loc stdlib.sol, 102
+ ENDC
+ NIP
+ .loc stdlib.sol, 0
+}
+
+.fragment __subCell, {
+ .loc stdlib.sol, 391
+ PUSH S2
+ PUSHINT 127
+ DIVMOD
+ .loc stdlib.sol, 392
+ OVER
+ NEQINT 0
+ OVER
+ EQINT 0
+ AND
+ PUSHCONT {
+ .loc stdlib.sol, 393
+ DROP
+ DEC
+ .loc stdlib.sol, 394
+ PUSHINT 127
+ .loc stdlib.sol, 0
+ }
+ IF
+ .loc stdlib.sol, 397
+ PUSH S5
+ CTOS
+ .loc stdlib.sol, 398
+ PUSH S2
+ PUSHCONT {
+ .loc stdlib.sol, 399
+ DUP
+ SREFS
+ EQINT 1
+ THROWIFNOT 70
+ .loc stdlib.sol, 400
+ LDREFRTOS
+ NIP
+ .loc stdlib.sol, 0
+ }
+ REPEAT
+ .loc stdlib.sol, 403
+ OVER
+ MULCONST 8
+ POP S2
+ .loc stdlib.sol, 404
DUP
- TRUE
+ SBITS
+ PUSH S2
+ GEQ
+ THROWIFNOT 70
+ .loc stdlib.sol, 405
+ OVER
+ SDSKIPFIRST
+ .loc stdlib.sol, 407
+ PUSH S4
+ MULCONST 8
+ POP S5
+ .loc stdlib.sol, 408
CALLREF {
- .inline __convertIntToHexString
+ .inline __createStringBuilder
}
- POP S2
- .loc stdlib.sol, 216
- OVER
- FIRST
- BREMBITS
- .loc stdlib.sol, 217
- LESSINT 8
+ .loc stdlib.sol, 409
PUSHCONT {
- .loc stdlib.sol, 218
- NEWC
+ .loc stdlib.sol, 410
+ OVER
+ SBITS
+ PUSH S6
+ MIN
+ UFITS 10
+ .loc stdlib.sol, 411
+ PUSH2 S6, S0
+ SUB
+ POP S7
+ PUXC S2, S-1
+ .loc stdlib.sol, 412
+ LDSLICEX
+ POP S3
+ .loc stdlib.sol, 413
+ CALLREF {
+ .inline __appendSliceToStringBuilder
+ }
+ .loc stdlib.sol, 414
+ PUSH S5
+ EQINT 0
PUSH S2
- PAIR
+ SEMPTY
+ OR
+ IFRETALT
+ .loc stdlib.sol, 417
+ OVER
+ LDREFRTOS
+ NIP
POP S2
.loc stdlib.sol, 0
}
- IF
- .loc stdlib.sol, 220
- OVER
- UNPAIR
- PUSHINT 58
- ROT
- STU 8
+ AGAINBRK
+ .loc stdlib.sol, 419
+ BLKSWAP 2, 4
SWAP
- PAIR
- POP S2
- .loc stdlib.sol, 221
- PUSHINT 64
- TRUE
- DUP
+ EQINT 0
+ OR
+ THROWIFNOT 70
+ .loc stdlib.sol, 420
CALLREF {
- .inline __convertIntToHexString
+ .inline __makeString
}
+ BLKDROP2 5, 1
.loc stdlib.sol, 0
}
-.fragment __convertBoolToStringBuilder, {
- .loc stdlib.sol, 293
- PUSHCONT {
- PUSHREF {
- .blob x74727565
- }
- CTOS
+.fragment __arraySlice, {
+ .loc stdlib.sol, 385
+ DUP2
+ LEQ
+ THROWIFNOT 70
+ .loc stdlib.sol, 386
+ OVER
+ SUB
+ .loc stdlib.sol, 387
+ FALSE
+ CALLREF {
+ .inline __subCell
}
- PUSHCONT {
- PUSHREF {
- .blob x66616c7365
- }
- CTOS
+ .loc stdlib.sol, 0
+}
+
+.fragment __concatenateStrings, {
+ .loc stdlib.sol, 449
+ CALLREF {
+ .inline __createStringBuilder
}
- IFELSE
+ .loc stdlib.sol, 450
+ ROT
CALLREF {
- .inline __appendSliceToStringBuilder
+ .inline __appendStringToStringBuilderWithNoShift
+ }
+ .loc stdlib.sol, 451
+ SWAP
+ CALLREF {
+ .inline __appendStringToStringBuilder
+ }
+ .loc stdlib.sol, 452
+ CALLREF {
+ .inline __makeString
}
.loc stdlib.sol, 0
}
.fragment __convertIntToString, {
- .loc stdlib.sol, 164
+ .loc stdlib.sol, 182
PUSH S2
LESSINT 0
- .loc stdlib.sol, 165
+ .loc stdlib.sol, 183
ROLL 3
ABS
- .loc stdlib.sol, 166
+ .loc stdlib.sol, 184
PUSH S4
FIRST
BREMBITS
RSHIFT 3
- .loc stdlib.sol, 168
+ .loc stdlib.sol, 186
ROT
PUSHCONT {
- .loc stdlib.sol, 169
+ .loc stdlib.sol, 187
DUP
PUSHCONT {
- .loc stdlib.sol, 170
+ .loc stdlib.sol, 188
NEWC
PUSH S5
PAIR
POP S5
- .loc stdlib.sol, 171
+ .loc stdlib.sol, 189
DROP
PUSHINT 127
.loc stdlib.sol, 0
}
IFNOT
- .loc stdlib.sol, 173
+ .loc stdlib.sol, 191
PUSH S4
UNPAIR
PUSHINT 45
@@ -681,34 +717,34 @@
SWAP
PAIR
POP S5
- .loc stdlib.sol, 174
+ .loc stdlib.sol, 192
DEC
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 177
+ .loc stdlib.sol, 195
SWAP
PUSHINT 10
CALLREF {
.inline __parseInteger
}
- .loc stdlib.sol, 179
+ .loc stdlib.sol, 197
PUSH2 S4, S0
GREATER
PUSHCONT {
- .loc stdlib.sol, 180
+ .loc stdlib.sol, 198
PUSH S3
PUSHINT 48
PUSHINT 32
CONDSEL
- .loc stdlib.sol, 181
+ .loc stdlib.sol, 199
PUSH2 S5, S1
SUB
- .loc stdlib.sol, 182
+ .loc stdlib.sol, 200
PUSH2 S0, S4
MIN
PUSHCONT {
- .loc stdlib.sol, 183
+ .loc stdlib.sol, 201
PUSH S7
UNPAIR
PUXC S3, S1
@@ -719,20 +755,20 @@
.loc stdlib.sol, 0
}
REPEAT
- .loc stdlib.sol, 185
+ .loc stdlib.sol, 203
PUSH2 S0, S4
GREATER
PUSHCONT {
- .loc stdlib.sol, 186
+ .loc stdlib.sol, 204
NEWC
PUSH S8
PAIR
POP S8
- .loc stdlib.sol, 187
+ .loc stdlib.sol, 205
PUSH2 S0, S4
SUB
PUSHCONT {
- .loc stdlib.sol, 188
+ .loc stdlib.sol, 206
PUSH S7
UNPAIR
PUXC S3, S1
@@ -743,12 +779,12 @@
.loc stdlib.sol, 0
}
REPEAT
- .loc stdlib.sol, 190
+ .loc stdlib.sol, 208
PUSH S4
ADDCONST 127
}
PUSHCONT {
- .loc stdlib.sol, 192
+ .loc stdlib.sol, 210
PUSH S4
}
IFELSE
@@ -759,15 +795,15 @@
DROP2
}
IF
- .loc stdlib.sol, 196
+ .loc stdlib.sol, 214
PUSH2 S0, S2
MIN
PUSHCONT {
- .loc stdlib.sol, 198
+ .loc stdlib.sol, 216
OVER
UNPAIR
POP S3
- .loc stdlib.sol, 199
+ .loc stdlib.sol, 217
PUSH S6
UNPAIR
XCHG S2
@@ -779,24 +815,24 @@
.loc stdlib.sol, 0
}
REPEAT
- .loc stdlib.sol, 201
+ .loc stdlib.sol, 219
PUSH2 S0, S2
GREATER
PUSHCONT {
- .loc stdlib.sol, 202
+ .loc stdlib.sol, 220
NEWC
PUSH S6
PAIR
POP S6
PUSH2 S0, S2
- .loc stdlib.sol, 203
+ .loc stdlib.sol, 221
SUB
PUSHCONT {
- .loc stdlib.sol, 205
+ .loc stdlib.sol, 223
OVER
UNPAIR
POP S3
- .loc stdlib.sol, 206
+ .loc stdlib.sol, 224
PUSH S6
UNPAIR
XCHG S2
@@ -811,23 +847,150 @@
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 210
+ .loc stdlib.sol, 228
BLKDROP 5
.loc stdlib.sol, 0
}
+.fragment __convertAddressToHexString, {
+ .loc stdlib.sol, 242
+ LDU 2
+ XCPU S1, S0
+ .loc stdlib.sol, 243
+ EQINT 2
+ PUSHCONT {
+ .loc stdlib.sol, 244
+ BLKPUSH 2, 2
+ CALLREF {
+ .inline __appendAnyCast
+ }
+ .loc stdlib.sol, 245
+ LDI 8
+ POP S4
+ PUSHINT 0
+ DUP
+ CALLREF {
+ .inline __convertIntToString
+ }
+ .loc stdlib.sol, 246
+ PUSHINT 58
+ CALLREF {
+ .inline __appendBytes1
+ }
+ .loc stdlib.sol, 247
+ PUSH S2
+ LDU 256
+ POP S4
+ PUSHINT 64
+ TRUE
+ DUP
+ CALLREF {
+ .inline __convertIntToHexString
+ }
+ POP S3
+ }
+ PUSHCONT {
+ DUP
+ EQINT 1
+ PUSHCONT {
+ .loc stdlib.sol, 249
+ PUSH S2
+ PUSHINT 58
+ CALLREF {
+ .inline __appendBytes1
+ }
+ POP S3
+ .loc stdlib.sol, 250
+ OVER
+ LDU 9
+ XCPU2 S3, S4, S3
+ BLKDROP2 2, 2
+ .loc stdlib.sol, 251
+ CALLREF {
+ .inline __appendSliceDataAsHex
+ }
+ POP S3
+ }
+ PUSHCONT {
+ DUP
+ EQINT 3
+ PUSHCONT {
+ .loc stdlib.sol, 253
+ BLKPUSH 2, 2
+ CALLREF {
+ .inline __appendAnyCast
+ }
+ SWAP
+ POP S4
+ .loc stdlib.sol, 254
+ PUSHINT 9
+ SDSKIPFIRST
+ POP S2
+ BLKPUSH 2, 2
+ .loc stdlib.sol, 255
+ LDI 32
+ POP S4
+ PUSHINT 0
+ DUP
+ CALLREF {
+ .inline __convertIntToString
+ }
+ .loc stdlib.sol, 256
+ PUSHINT 58
+ CALLREF {
+ .inline __appendBytes1
+ }
+ .loc stdlib.sol, 257
+ PUSH S2
+ CALLREF {
+ .inline __appendSliceDataAsHex
+ }
+ POP S3
+ .loc stdlib.sol, 0
+ }
+ IF
+ }
+ IFELSE
+ }
+ IFELSE
+ .loc stdlib.sol, 259
+ DROP2
+ .loc stdlib.sol, 0
+}
+
+.fragment __convertBoolToStringBuilder, {
+ .loc stdlib.sol, 331
+ PUSHCONT {
+ PUSHREF {
+ .blob x74727565
+ }
+ CTOS
+ }
+ PUSHCONT {
+ PUSHREF {
+ .blob x66616c7365
+ }
+ CTOS
+ }
+ IFELSE
+ CALLREF {
+ .inline __appendSliceToStringBuilder
+ }
+ .loc stdlib.sol, 0
+}
+
.fragment __convertFixedPointToString, {
- .loc stdlib.sol, 225
+ .loc stdlib.sol, 263
PUSH S2
LESSINT 0
PUSHCONT {
- .loc stdlib.sol, 226
+ .loc stdlib.sol, 264
PUSH S3
FIRST
BREMBITS
LESSINT 8
PUSHCONT {
- .loc stdlib.sol, 227
+ .loc stdlib.sol, 265
NEWC
PUSH S4
PAIR
@@ -835,7 +998,7 @@
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 229
+ .loc stdlib.sol, 267
PUSH S3
UNPAIR
PUSHINT 45
@@ -847,12 +1010,12 @@
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 231
+ .loc stdlib.sol, 269
ROT
ABS
SWAP
DIVMOD
- .loc stdlib.sol, 232
+ .loc stdlib.sol, 270
PUXC S3, S1
PUSHINT 0
DUP
@@ -860,13 +1023,13 @@
.inline __convertIntToString
}
POP S3
- .loc stdlib.sol, 233
+ .loc stdlib.sol, 271
PUSH S2
FIRST
BREMBITS
LESSINT 8
PUSHCONT {
- .loc stdlib.sol, 234
+ .loc stdlib.sol, 272
NEWC
PUSH S3
PAIR
@@ -874,7 +1037,7 @@
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 236
+ .loc stdlib.sol, 274
PUSH S2
UNPAIR
PUSHINT 46
@@ -884,7 +1047,7 @@
PAIR
POP S3
SWAP
- .loc stdlib.sol, 237
+ .loc stdlib.sol, 275
TRUE
CALLREF {
.inline __convertIntToString
@@ -935,16 +1098,16 @@
}
.fragment __stackReverse, {
- .loc stdlib.sol, 606
+ .loc stdlib.sol, 644
NULL
- .loc stdlib.sol, 607
+ .loc stdlib.sol, 645
PUSHCONT {
OVER
ISNULL
NOT
}
PUSHCONT {
- .loc stdlib.sol, 608
+ .loc stdlib.sol, 646
OVER
UNPAIR
POP S3
@@ -953,61 +1116,61 @@
.loc stdlib.sol, 0
}
WHILE
- .loc stdlib.sol, 609
+ .loc stdlib.sol, 647
NIP
.loc stdlib.sol, 0
}
.fragment __stackSort, {
- .loc stdlib.sol, 564
+ .loc stdlib.sol, 602
OVER
ISNULL
PUSHCONT {
- .loc stdlib.sol, 565
+ .loc stdlib.sol, 603
DROP2
NULL
.loc stdlib.sol, 0
}
IFJMP
- .loc stdlib.sol, 568
+ .loc stdlib.sol, 606
NULL
- .loc stdlib.sol, 569
+ .loc stdlib.sol, 607
PUSHINT 0
- .loc stdlib.sol, 570
+ .loc stdlib.sol, 608
PUSHCONT {
PUSH S3
ISNULL
NOT
}
PUSHCONT {
- .loc stdlib.sol, 572
+ .loc stdlib.sol, 610
PUSH S3
UNPAIR
POP S5
NULL
PAIR
- .loc stdlib.sol, 573
+ .loc stdlib.sol, 611
PUSH S2
PAIR
POP S2
- .loc stdlib.sol, 570
+ .loc stdlib.sol, 608
INC
.loc stdlib.sol, 0
}
WHILE
- .loc stdlib.sol, 576
+ .loc stdlib.sol, 614
PUSHCONT {
DUP
GTINT 1
}
PUSHCONT {
- .loc stdlib.sol, 577
+ .loc stdlib.sol, 615
NULL
- .loc stdlib.sol, 578
+ .loc stdlib.sol, 616
OVER
MODPOW2 1
PUSHCONT {
- .loc stdlib.sol, 579
+ .loc stdlib.sol, 617
PUSH S2
UNPAIR
POP S4
@@ -1016,22 +1179,22 @@
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 580
+ .loc stdlib.sol, 618
PUSHCONT {
PUSH S2
ISNULL
NOT
}
PUSHCONT {
- .loc stdlib.sol, 581
+ .loc stdlib.sol, 619
NULL
- .loc stdlib.sol, 582
+ .loc stdlib.sol, 620
PUSH S3
UNPAIR
- .loc stdlib.sol, 583
+ .loc stdlib.sol, 621
UNPAIR
POP S6
- .loc stdlib.sol, 584
+ .loc stdlib.sol, 622
PUSHCONT {
OVER
ISNULL
@@ -1042,7 +1205,7 @@
AND
}
PUSHCONT {
- .loc stdlib.sol, 585
+ .loc stdlib.sol, 623
OVER
FIRST
OVER
@@ -1051,13 +1214,13 @@
PUSH C3
CALLX
PUSHCONT {
- .loc stdlib.sol, 586
+ .loc stdlib.sol, 624
BLKPUSH 2, 2
UNPAIR
POP S4
}
PUSHCONT {
- .loc stdlib.sol, 588
+ .loc stdlib.sol, 626
PUSH2 S2, S0
UNPAIR
POP S3
@@ -1069,14 +1232,14 @@
.loc stdlib.sol, 0
}
WHILE
- .loc stdlib.sol, 590
+ .loc stdlib.sol, 628
PUSHCONT {
OVER
ISNULL
NOT
}
PUSHCONT {
- .loc stdlib.sol, 591
+ .loc stdlib.sol, 629
BLKPUSH 2, 2
UNPAIR
POP S4
@@ -1086,14 +1249,14 @@
.loc stdlib.sol, 0
}
WHILE
- .loc stdlib.sol, 592
+ .loc stdlib.sol, 630
PUSHCONT {
DUP
ISNULL
NOT
}
PUSHCONT {
- .loc stdlib.sol, 593
+ .loc stdlib.sol, 631
PUSH2 S2, S0
UNPAIR
POP S3
@@ -1103,26 +1266,26 @@
.loc stdlib.sol, 0
}
WHILE
- .loc stdlib.sol, 594
+ .loc stdlib.sol, 632
DROP2
CALLREF {
.inline __stackReverse
}
- .loc stdlib.sol, 595
+ .loc stdlib.sol, 633
SWAP
PAIR
.loc stdlib.sol, 0
}
WHILE
- .loc stdlib.sol, 597
+ .loc stdlib.sol, 635
POP S2
- .loc stdlib.sol, 598
+ .loc stdlib.sol, 636
INC
RSHIFT 1
.loc stdlib.sol, 0
}
WHILE
- .loc stdlib.sol, 600
+ .loc stdlib.sol, 638
DROP
UNPAIR
DROP
@@ -1131,28 +1294,28 @@
}
.fragment __strstr, {
- .loc stdlib.sol, 461
+ .loc stdlib.sol, 499
NULL
- .loc stdlib.sol, 462
+ .loc stdlib.sol, 500
PUSH S2
CTOS
- .loc stdlib.sol, 463
+ .loc stdlib.sol, 501
PUSH S2
CTOS
- .loc stdlib.sol, 464
+ .loc stdlib.sol, 502
PUSHINT 0
FALSE ; decl return flag
PUSHCONT {
- .loc stdlib.sol, 465
+ .loc stdlib.sol, 503
OVER2
PUSHCONT {
- .loc stdlib.sol, 437
+ .loc stdlib.sol, 475
OVER
SBITS
- .loc stdlib.sol, 438
+ .loc stdlib.sol, 476
OVER
SBITS
- .loc stdlib.sol, 439
+ .loc stdlib.sol, 477
FALSE ; decl return flag
PUSHCONT {
PUSH S3
@@ -1160,10 +1323,10 @@
NOT
}
PUSHCONT {
- .loc stdlib.sol, 440
+ .loc stdlib.sol, 478
PUSH S2
PUSHCONT {
- .loc stdlib.sol, 441
+ .loc stdlib.sol, 479
PUSH S4
SREFS
PUSHCONT {
@@ -1173,43 +1336,43 @@
RETALT
}
IFNOTJMP
- .loc stdlib.sol, 443
+ .loc stdlib.sol, 481
PUSH S4
LDREFRTOS
XCPU S6, S6
BLKDROP2 2, 1
- .loc stdlib.sol, 444
+ .loc stdlib.sol, 482
SBITS
POP S3
.loc stdlib.sol, 0
}
IFNOT
- .loc stdlib.sol, 446
+ .loc stdlib.sol, 484
OVER
PUSHCONT {
- .loc stdlib.sol, 447
+ .loc stdlib.sol, 485
PUSH S3
LDREFRTOS
XCPU S5, S5
BLKDROP2 2, 1
- .loc stdlib.sol, 448
+ .loc stdlib.sol, 486
SBITS
POP S2
.loc stdlib.sol, 0
}
IFNOT
- .loc stdlib.sol, 450
+ .loc stdlib.sol, 488
BLKPUSH 2, 2
MIN
- .loc stdlib.sol, 451
+ .loc stdlib.sol, 489
PUSH2 S5, S0
LDSLICEX
POP S7
- .loc stdlib.sol, 452
+ .loc stdlib.sol, 490
PUSH2 S5, S1
LDSLICEX
POP S7
- .loc stdlib.sol, 453
+ .loc stdlib.sol, 491
SDEQ
PUSHCONT {
BLKDROP 6
@@ -1218,11 +1381,11 @@
RETALT
}
IFNOTJMP
- .loc stdlib.sol, 455
+ .loc stdlib.sol, 493
PUSH2 S3, S0
SUB
POP S4
- .loc stdlib.sol, 456
+ .loc stdlib.sol, 494
PUSH S2
SUBR
POP S2
@@ -1230,10 +1393,10 @@
}
WHILEBRK
IFRET
- .loc stdlib.sol, 458
+ .loc stdlib.sol, 496
BLKDROP 4
TRUE
- .loc stdlib.sol, 436
+ .loc stdlib.sol, 474
}
CALLX
.loc stdlib.sol, 0
@@ -1244,15 +1407,15 @@
RETALT
}
IFJMP
- .loc stdlib.sol, 467
+ .loc stdlib.sol, 505
PUSH S3
SEMPTY
IFRETALT
- .loc stdlib.sol, 469
+ .loc stdlib.sol, 507
PUSH S3
SBITS
PUSHCONT {
- .loc stdlib.sol, 470
+ .loc stdlib.sol, 508
PUSH S3
LDREFRTOS
NIP
@@ -1260,12 +1423,12 @@
.loc stdlib.sol, 0
}
IFNOT
- .loc stdlib.sol, 471
+ .loc stdlib.sol, 509
PUSH S3
LDU 8
XCPU S5, S3
BLKDROP2 2, 1
- .loc stdlib.sol, 472
+ .loc stdlib.sol, 510
INC
POP S2
.loc stdlib.sol, 0
@@ -1274,15 +1437,15 @@
EQINT 4
IFRET
BLKDROP 6
- .loc stdlib.sol, 474
+ .loc stdlib.sol, 512
NULL
.loc stdlib.sol, 0
}
.fragment __toLowerCase, {
- .loc stdlib.sol, 479
+ .loc stdlib.sol, 517
.inline __createStringBuilder
- .loc stdlib.sol, 480
+ .loc stdlib.sol, 518
SWAP
CTOS
NULL
@@ -1302,18 +1465,18 @@
IFNOT
BLKDROP2 2, 2
XCPU2 S1, S0, S0
- .loc stdlib.sol, 482
+ .loc stdlib.sol, 520
GTINT 64
OVER
LESSINT 91
AND
PUSHCONT {
- .loc stdlib.sol, 483
+ .loc stdlib.sol, 521
ADDCONST 32
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 484
+ .loc stdlib.sol, 522
PUXC S3, S-1
CALLREF {
.inline __appendBytes1
@@ -1323,7 +1486,7 @@
}
WHILE
DROP2
- .loc stdlib.sol, 486
+ .loc stdlib.sol, 524
CALLREF {
.inline __makeString
}
@@ -1331,9 +1494,9 @@
}
.fragment __toUpperCase, {
- .loc stdlib.sol, 491
+ .loc stdlib.sol, 529
.inline __createStringBuilder
- .loc stdlib.sol, 492
+ .loc stdlib.sol, 530
SWAP
CTOS
NULL
@@ -1353,18 +1516,18 @@
IFNOT
BLKDROP2 2, 2
XCPU2 S1, S0, S0
- .loc stdlib.sol, 494
+ .loc stdlib.sol, 532
GTINT 96
OVER
LESSINT 123
AND
PUSHCONT {
- .loc stdlib.sol, 495
+ .loc stdlib.sol, 533
ADDCONST -32
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 496
+ .loc stdlib.sol, 534
PUXC S3, S-1
CALLREF {
.inline __appendBytes1
@@ -1374,7 +1537,7 @@
}
WHILE
DROP2
- .loc stdlib.sol, 498
+ .loc stdlib.sol, 536
CALLREF {
.inline __makeString
}
@@ -1521,20 +1684,20 @@
}
.fragment __stoi, {
- .loc stdlib.sol, 302
+ .loc stdlib.sol, 340
CTOS
- .loc stdlib.sol, 303
+ .loc stdlib.sol, 341
DUP
SBITS
LESSINT 8
PUSHCONT {
- .loc stdlib.sol, 304
+ .loc stdlib.sol, 342
DROP
NULL
.loc stdlib.sol, 0
}
IFJMP
- .loc stdlib.sol, 307
+ .loc stdlib.sol, 345
DUP
SBITS
GTINT 7
@@ -1546,10 +1709,10 @@
EQINT 45
}
IF
- .loc stdlib.sol, 308
+ .loc stdlib.sol, 346
DUP
PUSHCONT {
- .loc stdlib.sol, 309
+ .loc stdlib.sol, 347
OVER
PUSHINT 8
SDSKIPFIRST
@@ -1557,7 +1720,7 @@
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 311
+ .loc stdlib.sol, 349
OVER
SBITS
GTINT 15
@@ -1570,10 +1733,10 @@
EQUAL
}
IF
- .loc stdlib.sol, 312
+ .loc stdlib.sol, 350
DUP
PUSHCONT {
- .loc stdlib.sol, 313
+ .loc stdlib.sol, 351
PUSH S2
PUSHINT 16
SDSKIPFIRST
@@ -1581,36 +1744,36 @@
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 315
+ .loc stdlib.sol, 353
PUSHINT 0
- .loc stdlib.sol, 316
+ .loc stdlib.sol, 354
PUSH S3
SBITS
RSHIFT 3
- .loc stdlib.sol, 317
+ .loc stdlib.sol, 355
FALSE ; decl return flag
ROLL 3
PUSHCONT {
- .loc stdlib.sol, 318
+ .loc stdlib.sol, 356
FALSE ; decl return flag
PUSH S2
PUSHCONT {
- .loc stdlib.sol, 319
+ .loc stdlib.sol, 357
PUSH S5
LDU 8
POP S7
- .loc stdlib.sol, 320
+ .loc stdlib.sol, 358
PUSH S4
MULCONST 16
POP S5
- .loc stdlib.sol, 321
+ .loc stdlib.sol, 359
DUP
GTINT 47
OVER
LESSINT 58
AND
PUSHCONT {
- .loc stdlib.sol, 322
+ .loc stdlib.sol, 360
DUP
ADDCONST -48
PUSH S5
@@ -1625,7 +1788,7 @@
LESSINT 71
AND
PUSHCONT {
- .loc stdlib.sol, 324
+ .loc stdlib.sol, 362
DUP
ADDCONST -55
PUSH S5
@@ -1640,7 +1803,7 @@
LESSINT 103
AND
PUSHCONT {
- .loc stdlib.sol, 326
+ .loc stdlib.sol, 364
DUP
ADDCONST -87
PUSH S5
@@ -1649,7 +1812,7 @@
.loc stdlib.sol, 0
}
PUSHCONT {
- .loc stdlib.sol, 328
+ .loc stdlib.sol, 366
BLKDROP 7
NULL
PUSHINT 4
@@ -1671,15 +1834,15 @@
.loc stdlib.sol, 0
}
PUSHCONT {
- .loc stdlib.sol, 332
+ .loc stdlib.sol, 370
FALSE ; decl return flag
PUSH S2
PUSHCONT {
- .loc stdlib.sol, 333
+ .loc stdlib.sol, 371
PUSH S5
LDU 8
POP S7
- .loc stdlib.sol, 334
+ .loc stdlib.sol, 372
DUP
LESSINT 48
OVER
@@ -1692,7 +1855,7 @@
RETALT
}
IFJMP
- .loc stdlib.sol, 336
+ .loc stdlib.sol, 374
PUSH S4
MULCONST 10
SWAP
@@ -1709,51 +1872,51 @@
}
IFELSE
IFRET
- .loc stdlib.sol, 339
+ .loc stdlib.sol, 377
DROP
SWAP
PUSHCONT {
- .loc stdlib.sol, 340
+ .loc stdlib.sol, 378
NEGATE
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 341
+ .loc stdlib.sol, 379
NIP
.loc stdlib.sol, 0
}
.fragment __compareStrings, {
- .loc stdlib.sol, 389
+ .loc stdlib.sol, 427
SWAP
CTOS
- .loc stdlib.sol, 390
+ .loc stdlib.sol, 428
SWAP
CTOS
- .loc stdlib.sol, 391
+ .loc stdlib.sol, 429
FALSE ; decl return flag
PUSHCONT {
- .loc stdlib.sol, 392
+ .loc stdlib.sol, 430
BLKPUSH 2, 2
SDLEXCMP
- .loc stdlib.sol, 393
+ .loc stdlib.sol, 431
DUP
PUSHCONT {
- .loc stdlib.sol, 394
+ .loc stdlib.sol, 432
BLKDROP2 3, 1
PUSHINT 4
RETALT
.loc stdlib.sol, 0
}
IFJMP
- .loc stdlib.sol, 396
+ .loc stdlib.sol, 434
DROP
PUSH S2
SREFS
- .loc stdlib.sol, 397
+ .loc stdlib.sol, 435
PUSH S2
SREFS
- .loc stdlib.sol, 398
+ .loc stdlib.sol, 436
DUP2
GREATER
PUSHCONT {
@@ -1763,7 +1926,7 @@
RETALT
}
IFJMP
- .loc stdlib.sol, 400
+ .loc stdlib.sol, 438
PUSH2 S0, S1
GREATER
PUSHCONT {
@@ -1773,7 +1936,7 @@
RETALT
}
IFJMP
- .loc stdlib.sol, 402
+ .loc stdlib.sol, 440
ADD
PUSHCONT {
BLKDROP 3
@@ -1782,12 +1945,12 @@
RETALT
}
IFNOTJMP
- .loc stdlib.sol, 404
+ .loc stdlib.sol, 442
PUSH S2
LDREFRTOS
XCPU S4, S3
BLKDROP2 2, 1
- .loc stdlib.sol, 405
+ .loc stdlib.sol, 443
LDREFRTOS
NIP
POP S2
@@ -1795,18 +1958,18 @@
}
AGAINBRK
IFRET
- .loc stdlib.sol, 407
+ .loc stdlib.sol, 445
DROP2
PUSHINT 0
.loc stdlib.sol, 0
}
.fragment __strchr, {
- .loc stdlib.sol, 417
+ .loc stdlib.sol, 455
NULL
- .loc stdlib.sol, 418
+ .loc stdlib.sol, 456
PUSHINT 0
- .loc stdlib.sol, 419
+ .loc stdlib.sol, 457
ROLL 3
CTOS
NULL
@@ -1827,7 +1990,7 @@
IFNOT
BLKDROP2 2, 3
XCPU2 S2, S1, S5
- .loc stdlib.sol, 420
+ .loc stdlib.sol, 458
EQUAL
PUSHCONT {
XCHG S3
@@ -1836,7 +1999,7 @@
RETALT
}
IFJMP
- .loc stdlib.sol, 422
+ .loc stdlib.sol, 460
PUSH S3
INC
POP S4
@@ -1850,11 +2013,11 @@
}
.fragment __strrchr, {
- .loc stdlib.sol, 426
+ .loc stdlib.sol, 464
NULL
- .loc stdlib.sol, 427
+ .loc stdlib.sol, 465
PUSHINT 0
- .loc stdlib.sol, 428
+ .loc stdlib.sol, 466
ROLL 3
CTOS
NULL
@@ -1874,16 +2037,16 @@
IFNOT
BLKDROP2 2, 2
XCPU2 S1, S0, S4
- .loc stdlib.sol, 429
+ .loc stdlib.sol, 467
EQUAL
PUSHCONT {
- .loc stdlib.sol, 430
+ .loc stdlib.sol, 468
PUSH S2
POP S4
.loc stdlib.sol, 0
}
IF
- .loc stdlib.sol, 431
+ .loc stdlib.sol, 469
PUSH S2
INC
POP S3
@@ -1896,21 +2059,21 @@
}
.fragment __stateInitHash, {
- .loc stdlib.sol, 503
+ .loc stdlib.sol, 541
NEWC
- .loc stdlib.sol, 505
+ .loc stdlib.sol, 543
STSLICECONST x020134
- .loc stdlib.sol, 517
+ .loc stdlib.sol, 555
ROT
STUR 16
- .loc stdlib.sol, 518
+ .loc stdlib.sol, 556
STU 16
- .loc stdlib.sol, 520
+ .loc stdlib.sol, 558
ROT
STUR 256
- .loc stdlib.sol, 521
+ .loc stdlib.sol, 559
STU 256
- .loc stdlib.sol, 522
+ .loc stdlib.sol, 560
ENDC
CTOS
SHA256U
@@ -1918,23 +2081,23 @@
}
.fragment __forwardFee, {
- .loc stdlib.sol, 526
+ .loc stdlib.sol, 564
DEPTH
ADDCONST -3
PICK
CTOS
- .loc stdlib.sol, 527
+ .loc stdlib.sol, 565
LDU 1
SWAP
- .loc stdlib.sol, 528
+ .loc stdlib.sol, 566
PUSHCONT {
- .loc stdlib.sol, 539
+ .loc stdlib.sol, 577
DROP
PUSHINT 0
.loc stdlib.sol, 0
}
PUSHCONT {
- .loc stdlib.sol, 533
+ .loc stdlib.sol, 571
LDU 3
LDMSGADDR
LDMSGADDR
@@ -1942,7 +2105,7 @@
LDDICT
LDVARUINT16
BLKDROP2 6, 1
- .loc stdlib.sol, 537
+ .loc stdlib.sol, 575
LDVARUINT16
DROP
.loc stdlib.sol, 0
@@ -1952,28 +2115,28 @@
}
.fragment __importFee, {
- .loc stdlib.sol, 544
+ .loc stdlib.sol, 582
DEPTH
ADDCONST -3
PICK
CTOS
- .loc stdlib.sol, 545
+ .loc stdlib.sol, 583
LDU 2
SWAP
- .loc stdlib.sol, 546
+ .loc stdlib.sol, 584
EQINT 2
PUSHCONT {
- .loc stdlib.sol, 549
+ .loc stdlib.sol, 587
LDMSGADDR
LDMSGADDR
BLKDROP2 2, 1
- .loc stdlib.sol, 550
+ .loc stdlib.sol, 588
LDVARUINT16
DROP
.loc stdlib.sol, 0
}
PUSHCONT {
- .loc stdlib.sol, 552
+ .loc stdlib.sol, 590
DROP
PUSHINT 0
.loc stdlib.sol, 0
@@ -1983,7 +2146,7 @@
}
.fragment __qand, {
- .loc stdlib.sol, 613
+ .loc stdlib.sol, 651
OVER
ISNAN
DUP
@@ -2015,14 +2178,14 @@
QAND
}
IFJMP
- .loc stdlib.sol, 617
+ .loc stdlib.sol, 655
DROP2
PUSHINT 0
.loc stdlib.sol, 0
}
.fragment __qor, {
- .loc stdlib.sol, 621
+ .loc stdlib.sol, 659
OVER
ISNAN
DUP
@@ -2054,7 +2217,7 @@
QOR
}
IFJMP
- .loc stdlib.sol, 625
+ .loc stdlib.sol, 663
DROP2
PUSHINT -1
.loc stdlib.sol, 0
diff --git a/sold/Cargo.toml b/sold/Cargo.toml
index 95e4ffc4..853365e1 100644
--- a/sold/Cargo.toml
+++ b/sold/Cargo.toml
@@ -1,7 +1,7 @@
[package]
edition = '2021'
name = 'sold'
-version = '0.76.0'
+version = '0.77.0'
[[bin]]
name = 'sold'
@@ -16,9 +16,9 @@ serde_json = { features = [ 'unbounded_depth' ], version = '1.0' }
strip-ansi-escapes = '0.2'
clap = { features = [ 'derive' ], version = '4.5' }
serde = { features = [ 'derive' ], version = '1.0' }
-ever_abi = { git = 'https://github.com/everx-labs/ever-abi.git', tag = '2.6.1' }
-ever_block = { git = 'https://github.com/everx-labs/ever-block.git', tag = '1.11.0' }
-ever_assembler = { features = [ 'gosh' ], git = 'https://github.com/everx-labs/ever-assembler.git', tag = '1.6.3' }
+ever_abi = { git = 'https://github.com/everx-labs/ever-abi.git', tag = '2.7.2' }
+ever_block = { git = 'https://github.com/everx-labs/ever-block.git', tag = '1.11.11' }
+ever_assembler = { features = [ 'gosh' ], git = 'https://github.com/everx-labs/ever-assembler.git', tag = '1.6.14' }
[build-dependencies]
cmake = '0.1'
diff --git a/sold/build.rs b/sold/build.rs
index abd3eef2..f6a877b8 100644
--- a/sold/build.rs
+++ b/sold/build.rs
@@ -28,7 +28,7 @@ fn full_lib_name(lib_name: &str, boost_lib_dir: &str) -> String {
let mut file_name = file.unwrap().file_name().to_str().unwrap().to_string();
if file_name.starts_with(lib_name) {
if file_name.ends_with(".lib") {
- file_name = file_name.get(0..file_name.len()-4).unwrap().to_string();
+ file_name = file_name.get(0..file_name.len() - 4).unwrap().to_string();
}
return file_name.to_string();
}
@@ -54,27 +54,45 @@ fn main() {
for lib in ["solc", "solidity", "langutil", "solutil"] {
if cfg!(target_os = "windows") {
- println!("cargo:rustc-link-search=native={}/build/lib{}/{}", sol2tvm.display(), lib, profile);
+ println!(
+ "cargo:rustc-link-search=native={}/build/lib{}/{}",
+ sol2tvm.display(),
+ lib,
+ profile
+ );
} else {
- println!("cargo:rustc-link-search=native={}/build/lib{}", sol2tvm.display(), lib);
+ println!(
+ "cargo:rustc-link-search=native={}/build/lib{}",
+ sol2tvm.display(),
+ lib
+ );
}
println!("cargo:rustc-link-lib=static={}", lib);
}
println!("cargo:rustc-link-search=native={}/lib", sol2tvm.display());
- println!("cargo:rustc-link-search=native={}/build/deps/lib", sol2tvm.display());
+ println!(
+ "cargo:rustc-link-search=native={}/build/deps/lib",
+ sol2tvm.display()
+ );
let boost_lib_dir = "../compiler/deps/boost/lib";
if cfg!(target_os = "windows") {
- println!("cargo:rustc-link-search=native={}", absolute_path(boost_lib_dir));
+ println!(
+ "cargo:rustc-link-search=native={}",
+ absolute_path(boost_lib_dir)
+ );
} else if cfg!(target_os = "macos") {
match std::env::var("HOMEBREW") {
Ok(homebrew) => {
- assert!(std::path::PathBuf::from(homebrew.to_string()).exists(), "Set correct $HOMEBREW!");
+ assert!(
+ std::path::PathBuf::from(homebrew.to_string()).exists(),
+ "Set correct $HOMEBREW!"
+ );
println!("cargo:rustc-link-search=native={}/lib", homebrew)
}
// use default path
- Err(_) => println!("cargo:rustc-link-search=native=/opt/homebrew/lib")
+ Err(_) => println!("cargo:rustc-link-search=native=/opt/homebrew/lib"),
}
println!("cargo:rustc-link-search=native=/usr/local/lib");
} else if cfg!(target_os = "freebsd") {
diff --git a/sold/src/lib.rs b/sold/src/lib.rs
index b902681b..8d2e956c 100644
--- a/sold/src/lib.rs
+++ b/sold/src/lib.rs
@@ -4,12 +4,12 @@ use std::io::Write;
use std::os::raw::{c_char, c_void};
use std::path::Path;
-use clap::{ValueEnum, Parser};
use anyhow::{bail, format_err};
+use clap::{Parser, ValueEnum};
use serde::Deserialize;
-use ever_block::{Result, Status};
use ever_assembler::{DbgInfo, Engine, Units};
+use ever_block::{Result, Status};
mod libsolc;
mod printer;
@@ -26,7 +26,7 @@ unsafe extern "C" fn read_callback(
.into_owned();
if kind != "source" {
*o_error = make_error(format!("Unknown kind \"{}\"", kind));
- return
+ return;
}
let mut success = 0i32;
let contents_ptr = libsolc::file_reader_read(context, data, &mut success);
@@ -55,7 +55,11 @@ fn to_cstr(s: &str) -> Result {
std::ffi::CString::new(s).map_err(|e| format_err!("Failed to convert: {}", e))
}
-fn compile(args: &Args, input: &str, remappings: Vec) -> Result<(String, serde_json::Value)> {
+fn compile(
+ args: &Args,
+ input: &str,
+ remappings: Vec,
+) -> Result<(String, serde_json::Value)> {
let file_reader = unsafe {
let file_reader = libsolc::file_reader_new();
if let Some(base_path) = args.base_path.clone() {
@@ -71,10 +75,12 @@ fn compile(args: &Args, input: &str, remappings: Vec) -> Result<(String,
libsolc::file_reader_add_or_update_file(
file_reader,
to_cstr(input)?.as_ptr(),
- to_cstr(&input_content)?.as_ptr()
+ to_cstr(&input_content)?.as_ptr(),
);
if let Some(path) = dunce::canonicalize(Path::new(&input))?.parent() {
- let path = path.to_str().ok_or_else(|| format_err!("Failed to convert path to string"))?;
+ let path = path
+ .to_str()
+ .ok_or_else(|| format_err!("Failed to convert path to string"))?;
libsolc::file_reader_allow_directory(file_reader, to_cstr(path)?.as_ptr());
}
file_reader
@@ -82,7 +88,9 @@ fn compile(args: &Args, input: &str, remappings: Vec) -> Result<(String,
let source_unit_name = {
let name = unsafe {
std::ffi::CStr::from_ptr(libsolc::file_reader_source_unit_name(
- file_reader, to_cstr(input)?.as_ptr()))
+ file_reader,
+ to_cstr(input)?.as_ptr(),
+ ))
};
&name.to_string_lossy().into_owned()
};
@@ -107,16 +115,15 @@ fn compile(args: &Args, input: &str, remappings: Vec) -> Result<(String,
""
};
let tvm_version = match args.tvm_version {
- None => {
- "".to_string()
- }
+ None => "".to_string(),
Some(version) => {
format!(r#""tvmVersion": "{}","#, version)
}
};
let main_contract = args.contract.clone().unwrap_or_default();
let remappings = remappings_to_json_string(remappings);
- let input_json = format!(r#"
+ let input_json = format!(
+ r#"
{{
"language": "Solidity",
"settings": {{
@@ -136,7 +143,8 @@ fn compile(args: &Args, input: &str, remappings: Vec) -> Result<(String,
}}
}}
}}
- "#);
+ "#
+ );
let output = unsafe {
std::ffi::CStr::from_ptr(libsolc::solidity_compile(
to_cstr(&input_json)?.as_ptr(),
@@ -183,20 +191,20 @@ fn parse_comp_result(
// println!("{}", serde_json::to_string_pretty(&res)?);
if let Some(v) = res.get("errors") {
- let entries = v.as_array()
- .ok_or_else(|| parse_error!())?;
+ let entries = v.as_array().ok_or_else(|| parse_error!())?;
let mut severe = false;
for entry in entries {
- let entry = entry.as_object()
- .ok_or_else(|| parse_error!())?;
- let severity = entry.get("severity")
+ let entry = entry.as_object().ok_or_else(|| parse_error!())?;
+ let severity = entry
+ .get("severity")
.ok_or_else(|| parse_error!())?
.as_str()
.ok_or_else(|| parse_error!())?;
if severity == "error" {
severe = true;
}
- let message = entry.get("humanFormattedMessage")
+ let message = entry
+ .get("humanFormattedMessage")
.ok_or_else(|| parse_error!())?
.as_str()
.ok_or_else(|| parse_error!())?;
@@ -225,26 +233,28 @@ fn parse_comp_result(
if let Some(ref contract) = contract {
if !all.contains_key(contract) {
- Err(format_err!("Source file doesn't contain the desired contract \"{}\"", contract))
+ Err(format_err!(
+ "Source file doesn't contain the desired contract \"{}\"",
+ contract
+ ))
} else {
Ok(all.get(contract).unwrap().clone())
}
} else {
- let mut iter =
- all.iter().filter(|(_, v)| {
- if !compile {
- true
- } else if let Some(v) = v.as_object() {
- let assembly = v.get("assembly");
- if let Some(assembly) = assembly {
- !assembly.is_null()
- } else {
- false
- }
+ let mut iter = all.iter().filter(|(_, v)| {
+ if !compile {
+ true
+ } else if let Some(v) = v.as_object() {
+ let assembly = v.get("assembly");
+ if let Some(assembly) = assembly {
+ !assembly.is_null()
} else {
false
}
- });
+ } else {
+ false
+ }
+ });
let qualification = if compile { "deployable " } else { "" };
let entry = iter.next();
if let Some(entry) = entry {
@@ -263,7 +273,7 @@ static STDLIB: &str = include_str!("../../lib/stdlib_sol.tvm");
fn parse_positional_args(args: Vec) -> Result<(String, Vec)> {
let mut input = None;
- let mut remappings = vec!();
+ let mut remappings = vec![];
for arg in args {
if arg.contains('=') {
remappings.push(arg);
@@ -293,7 +303,10 @@ pub fn build(args: Args) -> Status {
if let Some(ref output_prefix) = args.output_prefix {
if output_prefix.contains(std::path::is_separator) {
- bail!("Invalid output prefix \"{}\". Use option -O to set output directory", output_prefix);
+ bail!(
+ "Invalid output prefix \"{}\". Use option -O to set output directory",
+ output_prefix
+ );
}
}
@@ -305,20 +318,24 @@ pub fn build(args: Args) -> Status {
&res.1,
&res.0,
args.contract,
- !(args.abi_json || args.ast_compact_json || args.userdoc || args.devdoc )
+ !(args.abi_json || args.ast_compact_json || args.userdoc || args.devdoc),
)?;
if args.function_ids {
println!("{}", serde_json::to_string_pretty(&out["functionIds"])?);
- return Ok(())
+ return Ok(());
}
if args.private_function_ids {
- println!("{}", serde_json::to_string_pretty(&out["privateFunctionIds"])?);
- return Ok(())
+ println!(
+ "{}",
+ serde_json::to_string_pretty(&out["privateFunctionIds"])?
+ );
+ return Ok(());
}
- let input_file_stem = input_canonical.file_stem()
+ let input_file_stem = input_canonical
+ .file_stem()
.ok_or_else(|| format_err!("Failed to extract file stem"))?
.to_str()
.ok_or_else(|| format_err!("Failed to get file stem"))?
@@ -335,18 +352,20 @@ pub fn build(args: Args) -> Status {
println!("User Documentation");
println!("{}", serde_json::to_string_pretty(&out["userdoc"])?);
}
- return Ok(())
+ return Ok(());
}
if args.ast_compact_json {
- let all = res.1.as_object()
+ let all = res
+ .1
+ .as_object()
.ok_or_else(|| parse_error!())?
.get("sources")
.ok_or_else(|| parse_error!())?
.as_object()
.ok_or_else(|| parse_error!())?;
- let mut array = vec!();
+ let mut array = vec![];
for (_, val) in all {
let ast = val
.as_object()
@@ -357,7 +376,7 @@ pub fn build(args: Args) -> Status {
}
assert_eq!(array.len(), 1);
println!("{}", serde_json::to_string(&array[0])?);
- return Ok(())
+ return Ok(());
}
let abi = &out["abi"];
@@ -365,7 +384,7 @@ pub fn build(args: Args) -> Status {
let mut abi_file = File::create(output_path.join(abi_file_name))?;
printer::print_abi_json_canonically(&mut abi_file, abi)?;
if args.abi_json {
- return Ok(())
+ return Ok(());
}
let assembly = out["assembly"]
@@ -389,7 +408,8 @@ pub fn build(args: Args) -> Status {
let mut units = Units::new();
for (input, filename) in inputs {
engine.reset(filename);
- units = engine.compile_toplevel(&input)
+ units = engine
+ .compile_toplevel(&input)
.map_err(|e| format_err!("{}", e))?;
}
let (b, d) = units.finalize();
diff --git a/sold/src/main.rs b/sold/src/main.rs
index c0780d1c..3ad16805 100644
--- a/sold/src/main.rs
+++ b/sold/src/main.rs
@@ -11,7 +11,7 @@
*/
use clap::Parser;
-use sold_lib::{Args, VERSION, ERROR_MSG_NO_OUTPUT, build, solidity_version};
+use sold_lib::{build, solidity_version, Args, ERROR_MSG_NO_OUTPUT, VERSION};
mod libsolc;
diff --git a/sold/src/printer.rs b/sold/src/printer.rs
index 50a90c8a..5600cd1c 100644
--- a/sold/src/printer.rs
+++ b/sold/src/printer.rs
@@ -19,7 +19,9 @@ use serde::Serialize;
use ever_block::{Result, Status};
pub fn print_abi_json_canonically(out: &mut File, value: &serde_json::Value) -> Status {
- let root = value.as_object().ok_or_else(|| format_err!("ABI parsing failed"))?;
+ let root = value
+ .as_object()
+ .ok_or_else(|| format_err!("ABI parsing failed"))?;
writeln!(out, "{{")?;
writeln!(out, "\t\"ABI version\": {},", root["ABI version"])?;
if let Some(version) = root.get("version") {
@@ -27,7 +29,9 @@ pub fn print_abi_json_canonically(out: &mut File, value: &serde_json::Value) ->
}
if let Some(header) = root.get("header") {
write!(out, "\t\"header\": [")?;
- let array = header.as_array().ok_or_else(|| format_err!("ABI parsing failed"))?;
+ let array = header
+ .as_array()
+ .ok_or_else(|| format_err!("ABI parsing failed"))?;
for i in 0..array.len() {
write!(out, "{}", array[i])?;
if i + 1 != array.len() {
@@ -41,6 +45,10 @@ pub fn print_abi_json_canonically(out: &mut File, value: &serde_json::Value) ->
print(out, &root["functions"])?;
writeln!(out, "\t],")?;
+ writeln!(out, "\t\"getters\": [")?;
+ print(out, &root["getters"])?;
+ writeln!(out, "\t],")?;
+
writeln!(out, "\t\"events\": [")?;
print(out, &root["events"])?;
writeln!(out, "\t],")?;
@@ -54,7 +62,9 @@ pub fn print_abi_json_canonically(out: &mut File, value: &serde_json::Value) ->
}
fn print_data(out: &mut File, value: &serde_json::Value) -> Status {
- let json = value.as_array().ok_or_else(|| format_err!("ABI parsing failed"))?;
+ let json = value
+ .as_array()
+ .ok_or_else(|| format_err!("ABI parsing failed"))?;
for f in 0..json.len() {
write!(out, "\t\t")?;
@@ -82,9 +92,13 @@ fn print_array(out: &mut File, array: &[serde_json::Value]) -> Status {
}
fn print(out: &mut File, value: &serde_json::Value) -> Status {
- let json = value.as_array().ok_or_else(|| format_err!("ABI parsing failed"))?;
+ let json = value
+ .as_array()
+ .ok_or_else(|| format_err!("ABI parsing failed"))?;
for f in 0..json.len() {
- let function = json[f].as_object().ok_or_else(|| format_err!("ABI parsing failed"))?;
+ let function = json[f]
+ .as_object()
+ .ok_or_else(|| format_err!("ABI parsing failed"))?;
writeln!(out, "\t\t{{")?;
writeln!(out, "\t\t\t\"name\": {},", function["name"])?;
@@ -95,14 +109,18 @@ fn print(out: &mut File, value: &serde_json::Value) -> Status {
writeln!(out, "\t\t\t\"inputs\": [")?;
if let Some(inputs) = function.get("inputs") {
- let array = inputs.as_array().ok_or_else(|| format_err!("ABI parsing failed"))?;
+ let array = inputs
+ .as_array()
+ .ok_or_else(|| format_err!("ABI parsing failed"))?;
print_array(out, array)?;
}
writeln!(out, "\t\t\t],")?;
writeln!(out, "\t\t\t\"outputs\": [")?;
if let Some(outputs) = function.get("outputs") {
- let array = outputs.as_array().ok_or_else(|| format_err!("ABI parsing failed"))?;
+ let array = outputs
+ .as_array()
+ .ok_or_else(|| format_err!("ABI parsing failed"))?;
print_array(out, array)?;
}
writeln!(out, "\t\t\t]")?;
diff --git a/sold/tests/tests.rs b/sold/tests/tests.rs
index 29956eab..071ea493 100644
--- a/sold/tests/tests.rs
+++ b/sold/tests/tests.rs
@@ -10,18 +10,18 @@
* See the GNU General Public License for more details at: https://www.gnu.org/licenses/gpl-3.0.html
*/
-use predicates::prelude::*;
use assert_cmd::Command;
+use predicates::prelude::*;
use sold_lib::ERROR_MSG_NO_OUTPUT;
type Status = Result<(), Box>;
const BIN_NAME: &str = "sold";
fn remove_all_outputs(name: &str) -> Status {
- std::fs::remove_file(format!("tests/{}.abi.json", name))?;
- std::fs::remove_file(format!("tests/{}.code", name))?;
+ std::fs::remove_file(format!("tests/{}.abi.json", name))?;
+ std::fs::remove_file(format!("tests/{}.code", name))?;
std::fs::remove_file(format!("tests/{}.debug.json", name))?;
- std::fs::remove_file(format!("tests/{}.tvc", name))?;
+ std::fs::remove_file(format!("tests/{}.tvc", name))?;
Ok(())
}
@@ -91,8 +91,7 @@ fn test_library() -> Status {
.arg("tests")
.assert()
.success()
- .stderr(predicate::str::contains(ERROR_MSG_NO_OUTPUT))
- ;
+ .stderr(predicate::str::contains(ERROR_MSG_NO_OUTPUT));
Ok(())
}
@@ -147,7 +146,8 @@ fn test_private_function_ids() -> Status {
.arg("--private-function-ids")
.assert()
.success()
- .stdout(predicate::str::contains(r#"[
+ .stdout(predicate::str::contains(
+ r#"[
{
"id": 5581,
"scope": "C",
@@ -168,7 +168,8 @@ fn test_private_function_ids() -> Status {
"scope": "Math",
"sign": "mul(uint256,uint256)"
}
-"#));
+"#,
+ ));
Ok(())
}
@@ -194,7 +195,8 @@ fn test_userdoc_devdoc() -> Status {
.arg("--devdoc")
.assert()
.success()
- .stdout(predicate::str::contains(r#"Developer Documentation
+ .stdout(predicate::str::contains(
+ r#"Developer Documentation
{
"kind": "dev",
"methods": {},
@@ -206,6 +208,7 @@ User Documentation
"methods": {},
"version": 1
}
-"#));
- Ok(())
+"#,
+ ));
+ Ok(())
}