Giter Site home page Giter Site logo

everx-labs / tvm-solidity-compiler Goto Github PK

View Code? Open in Web Editor NEW
116.0 13.0 70.0 6.91 MB

Solidity compiler for TVM

License: GNU General Public License v3.0

CMake 0.84% Makefile 0.08% Python 3.17% Batchfile 0.10% C++ 61.52% C 0.87% Dockerfile 0.21% Shell 3.53% JavaScript 0.15% Solidity 26.50% Rust 0.80% ANTLR 0.38% PowerShell 0.02% Yul 1.85%
everscale blockchain everos compiler smart-contracts solidity venom-blockchain venom-developer-program tvm

tvm-solidity-compiler's Introduction

The TVM Solidity compiler

GitHub Everscale

Port of the Solidity smart-contract compiler generating TVM bytecode for TVM compatible blockchains (Everscale, Venom, Gosh, TON). Please refer to upstream README.md for information on the language itself.

TVM Solidity API reference

API documentation is here

Build and Install

Sold driver

We recommend using sold to compile smart-contracts. Documentation is available at README.md.

Building compiler

Original Instructions about how to build and install the Solidity compiler can be found in the Solidity documentation.

Ubuntu Linux

git clone https://github.com/tonlabs/TVM-Solidity-Compiler
cd TVM-Solidity-Compiler
sh ./compiler/scripts/install_deps.sh
mkdir build
cd build
cmake ../compiler/ -DCMAKE_BUILD_TYPE=Release
cmake --build . -- -j8

Windows 10

Install Visual Studio Build Tools 2019, Git bash, cmake. Run Developer PowerShell for VS 2019

git clone https://github.com/tonlabs/TVM-Solidity-Compiler
cd TVM-Solidity-Compiler
compiler\scripts\install_deps.ps1
mkdir build
cd build
cmake -DBOOST_ROOT="..\compiler\deps\boost\" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded ..\compiler
cmake --build . --config Release -- /m

Links

License

GNU GENERAL PUBLIC LICENSE Version 3

tvm-solidity-compiler's People

Contributors

atomxy avatar borisi avatar bvscd avatar cassandrus avatar cryshado avatar igorkoval avatar pizza-777 avatar silkovalexander avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tvm-solidity-compiler's Issues

Proposal: add onConstructorRetry special contract function.

Hi. In Distributed programming paradigm we have a problem with gas management when we trying to redeploy an already deployed contract.

I'll try to explain it with by using tip-3 architecture. When some application transfers tokens from one wallet to another we always firstly deploy the target wallet, then we send an onAcceptTokensTransfer call with amount of tokens to transfer. If target wallet is already deployed - constructor will throw an error and gas will be bounce back to the contract which one tried to deploy the wallet. But we would like to send remain gas to the user's wallet which one started the transaction.

So we have a constructor like this:

constructor(address remainingGasTo) public
{
  require(msg.sender == root);
  tvm.rawReserve(_reserve(), 0);
  remainingGasTo.transfer({
      value: 0,
      flag: TokenMsgFlag.ALL_NOT_RESERVED + TokenMsgFlag.IGNORE_ERRORS,
      bounce: false
  });
}

If contract already deployed, message will bounce back to the msg.sender. Will be nice to to have an opportunity to declare such special function:

onConstructorRetry(address remainingGasTo) {
    require(msg.sender == root);
    tvm.rawReserve(_reserve(), 0);
    remainingGasTo.transfer({
      value: 0,
      flag: TokenMsgFlag.ALL_NOT_RESERVED + TokenMsgFlag.IGNORE_ERRORS,
      bounce: false
  });
}

Because an attempt to re-deploy is a regular situation for our application.

If you need more details I can try to draw a scheme of some real application.

pragma version error

IMG_20230504_101246_559.jpg
Please consider changing the pragma version "error" to a "warning".

Because if I comment out this line, the contract is compiled successfully. So it's more warning than error.

tvm.rawReserve() issue

Issue: if you use tvm.rawReserve() to split the ton flow (for example - for two calls check example below), strange behavior apper.

Case:
We have a contract, that wants to call two other contracts during one call (otherwise there will be too much additional code):

interface ContractToCall1 {
    function toCall(TvmCell args) external;
}

interface ContractToCall2 {
    function toCall2(TvmCell args) external;
}

contract TestContract {
    function splitTonFlow(TvmCell args1 , TvmCell args2) {
         tvm.rawReserve(msg.value / 2, 0);

         ContractToCall2(knownAddress2).toCall{
         value: msg.value / 2
        }(args1);

        ContractToCall1(knownAddress1).toCall{
             flag: 64
        }(args1);
    }
}

Expected behavior:
Produce two messages with attached value:

  1. For ContractToCall2 - msg.value / 2
  2. For ContractToCall1 - (msg.value / 2 - fees)

Contract behavior:
Producing two messages with values:

  1. For ContractToCall2 - msg.value / 2
  2. For ContractToCall1 - (msg.value - fees)

So there is a problem with splitting TON flow. This is a problem if you try to implement complex systems, which are not always pretty with only linear call scheme.

Cannot provide real source code here, for more info - please contact me (tg: @Pafaul)

Proposal: add JSON-like parameters for function call

Hello!

Recently I've been working a lot with contracts written in Solidity for Free-TON blockchain and there is some trouble.
For example, working with popular TIP-3 wallets is pretty hard because to call a function you need to provide 6-7 parameters in specific order, for example I will show function transfer from Broxus TIP-3 wallet:

function transfer(
        address to,
        uint128 tokens,
        uint128 grams,
        address send_gas_to,
        bool notify_receiver,
        TvmCell payload
    ) external;

Seems okay, but in code it looks like this:

TvmCell empty;
ITONTokenWallet(walletAddress).transfer{
    flags: 64
}(
    someAddressVariable,
    tokensToSend,
    0,
    owner,
    true,
    empty
);

Or like this:

TvmCell empty;
ITONTokenWallet(walletAddress).transfer{
    flags: 64
}(
    someAddressVariable, tokensToSend, 0, owner, true, empty
);

And this looks pretty messy if there are a lot of such calls in contracts, especially if function requires more than 5-6 arguments or if you have to modify it later.

There is similar problem with big structures, for example:

struct BigStructure {
    address someAddress;
    uint256 someValue;
    uint256 anotherValue;
    ....
};
...
BigStructure bs = BigStructure(
    someKnownAddress,
    someKnownValue,
    anotherKnownValue,
    ....
);

But you can define structure variables using JSON-like format:

BigStructure bs = BigStructure({
    someAddress: myAddress,
    someValue: myValue,
    anotherValue: myAnotherValue,
    ....
})

It was tested using non-modified solidity compiler v0.47.0 with contract:

pragma ton-solidity >= 0.39.0;
struct TestStruct {
    uint256 value;
    uint256 anotherValue;
}
contract TestContract {
    TestStruct ts;
    constructor() public {
        tvm.accept();
        ts = TestStruct({
            value: 0x1233344,
            anotherValue: 0x1231554664
        });
    }
}

So I think it will be great if such thing as JSON-like parameters for functions will be implemented, so code will look like this:

TvmCell empty;
ITONTokenWallet(walletAddress).transfer{
    flags: 64
}(
    to: someAddressVariable,
    tokens: tokensToSend,
    grams: 0,
    send_gas_to: owner,
    notify_receiver: true,
    payload: empty
);

Which makes it much easier to read and modify. Of course it is only possible assuming that you have interface for smart contract or smart contract source code.

Bug: ะกompiler crashes without error description

If you make a try-catch construct with a syntax error*, then the compiler crashes

*is this a syntax error?


solidity code for testing:

contract Test {
    function testFunc() private {
        try {
            // pass
        } catch {
            // pass
        }
    }
}

message in console:

Segmentation fault (core dumped)

compiler version: 0.69.0

Troubles with optional type decoding

I'm trying to compile the following program

pragma ton-solidity ^0.44.0;

contract Mem {
    constructor() public {
        tvm.accept();
    }

    function test() internal returns (optional(uint256)) {
        TvmSlice data = msg.data;
        return data.decode(optional(uint256));
    }
}

and getting compilation Error: Return argument type optional(optional(uint256)) is not implicitly convertible to expected type (type of first return variable) optional(uint256).
So the type checker for some reason thinks that expression data.decode(optional(uint256)) has type optional(optional(uint256)).

And when compiling this code

pragma ton-solidity ^0.44.0;

contract Mem {
    constructor() public {
        tvm.accept();
    }

    struct Struct {
        optional(uint256) value;
    }

    function test() internal returns (Struct) {
        TvmSlice data = msg.data;
        return data.decode(Struct);
    }
}

I get "Unsupported parameter type for decoding: optional(uint256)". So optional type seems to be TvmBuilder.store'able, but not TvmSlice.decode'able, and that is pretty not convenient.

I hope you will support decoding optional types in a next release.

Unable to deploy contract if contract has a lot of string variables.

Encountered another problem: if there are a lot of string type variables in Solidity contract than it's impossible to deploy contract.
Example of contract:

pragma solidity >= 0.6.0;

pragma AbiHeader pubkey;
pragma AbiHeader expire;
pragma AbiHeader time;

contract Test {
    uint static _randomNonce;

    string a = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string a1 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string a2 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string a3 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string a4 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string a5 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string a6 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string a7 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string a8 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string a9 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string a1o = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string a11 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";

    constructor () public {
        tvm.accept();
    }
}

Strings are just random symbols, content doesn't matter.

It compiles correctly, but when you try to deploy it following error occures:

{
  code: 414,
  message: "Contract execution was terminated with error: compute phase isn't succeeded, exit code: -14 (out of gas). Check account balance. For more information about exit code check the contract source code or ask the contract developer",
  data: {
    core_version: '1.9.0',
    phase: 'computeVm',
    exit_code: -14,
    exit_arg: 10260,
    account_address: '0:bec974fd38ad880a45de4e3c6b60be6d81bc1c94a2422f616c788c48a8e25196',
    gas_used: 0,
    description: 'out of gas',
    transaction_id: '2955686a15c1c2230db770b45fd78de5e3ece16ee3d723134692777833f6f53b',
    config_servers: [ 'http://localhost:3333' ],
    query_url: 'http://localhost:3333/graphql'
  }
}

It can be fixed by adding constant modificator to variables. Maybe there is a problem with Solidity compiler and strings. So, valid contract looks like this:

pragma solidity >= 0.6.0;

pragma AbiHeader pubkey;
pragma AbiHeader expire;
pragma AbiHeader time;

contract Test {
    uint static _randomNonce;

    string constant a = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string constant a1 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string constant a2 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string constant a3 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string constant a4 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string constant a5 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string constant a6 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string constant a7 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string constant a8 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string constant a9 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string constant a1o = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";
    string constant a11 = "asdfasfasjofuahwpiufhawklfhaiwhefiauwhefiwhef;oe;eofhawoefhawe";

    constructor () public {
        tvm.accept();
    }
}

Consider adding unit type to ton-solidity

Suppose we want to store a set of some entries: for example, a set of already presented hashes for reply-protection.
The conventional solidity-way is to make a map like mapping(uint256 => bool) hashUsed and set hashUsed[h] = true whenever hash h is presented. It is quite straight-forward because in Solidity there is no way to check whether a specific key is presented in the map -- they all are presented and initialized with default value.
However, in Ton-Solidity we have .exists() method, so it doesn't make sense to store a boolean value in the map -- we can just store nothing! Thus, using unit type (which unique value serializes to empty builder) in mapping(uint256 => Unit) efficiently allows us to use maps as sets. You can even add a new type set(...), internally represented as mapping with Unit value type. After all, it could allow to write more structured code.

tvm.functionId() for getting constructor id

According to TON Solidity API, I can make something like this for getting public constructor id:
tvm.functionId(Contract)
But compiler return an error This function takes one argument (identifier of public function).
How can I get public constructor id?

('latest' tag of image tonlabs/compilers is used for compilation)

Proposal: Add method for mapping

At the moment, to remove an element from mapping, we can only use

delete mapping[key]

However, in TVM there is an opcode for simultaneous deletion and retrieval of an element - DICTDELGET.

It would be very convenient to use this method to save on gas.


expected syntax:

<map>.getDel(KeyType key) returns (optional(ValueType));

false warning: Function state mutability can be restricted to pure [v0.57.3]

App.sol

pragma ton-solidity = 0.57.3;

contract App {
    uint public owner;

    modifier onlyOwner() {
        require(msg.pubkey() == owner);
        _;
    }

    modifier checkPubKey() {
        require(msg.pubkey() == tvm.pubkey());
        _;
    }

    constructor() public checkPubKey {
        tvm.accept();
        owner = msg.pubkey();
    }

    function foo(string bar) public view onlyOwner returns(string out) {
        tvm.accept();
        out = format('42{}', bar);
    }
}
npx everdev sol set --compiler 0.57.3
npx everdev sol compile --code --output-dir build App.sol
Warning: Function state mutability can be restricted to pure
  --> App.sol:21:5:
   |
21 |     function foo(string bar) public view onlyOwner returns(string out) {
   |     ^ (Relevant source part starts here and spans across multiple lines).

Contract doesn't compile

Hello there!
Here I have an example of contract that will compile using real eth-solc, but does not compile with this compiler.

pragma solidity ^0.5.0;

contract Simple {
    bytes byteArray;

    function not_working() public {
        /* Require with text */
        require(true, "This message can be string in soliditiy");

        /* String <-> Bytes interop */
        byteArray = "string";

        /* Inline assembly */
        string memory str = "another string";
        uint ptr;
        assembly {
            ptr := add(str, 0x20)
        }

        /* Two-dimensional array */
        uint[][] memory testArray = new uint[][](10);
        require(testArray.length == 0);
    }
}

There are four sections (marked with a block comment each). Each section by itself produces a different error message (sometimes empty).

Is there a bug tracker, where I can submit these bugs, somewhere?
When can we expect these bugs to be fixed?
Is there a plan to make this compiler fully compatible with eth-solc (and if there is, when you expect it happen)?

Proposal: force users to explicitly specify responsible answer flags.

Hi there,

I will start with two problems with default responsible.

Problem #1, default responsible has flag: 0 and he send value depend on pragma msgValue? 7_500_000 or 9_500_000.

Simple contract:

contract SimpleContract {
    address static owner;

    constructor() public {
        tvm.accept();
    }

    function get_owner() external pure responsible returns (address) {
        return owner;
    }
}

Get owner will be compiled to

function get_owner() external pure responsible returns (address) {
    return {flag: 0, value: 7_500_00, bounce: true} owner;
 } 

Also it can be used to make money. If attacker find contract with such responsible he can pay for call responsible < 7_500_00 evers and get back 7_500_00 evers. So he can drain balance. This will getting worse if gas price will be lower in future.

Problem #2, default responsible has bounce: true, and it is really bad.

Example of vulnerable contract (pseudocode):

pragma ton-solidity >= 0.39.0;
pragma AbiHeader expire;
pragma AbiHeader pubkey;


contract VulnerableContract  {
    uint128 balance;

    function get_balance() override external view responsible returns (uint32) {
        return{flag: 64, value: 0} balance;
    }

    function transfer(uint128 _amount_tokens, uint256 _to_pubkey) external {
        require(tvm.pubkey() == msg.pubkey());
        require(balance > _amount_tokens);

        tvm.accept();
        address reciever = _getExpectedAddress(_to_pubkey); 
        balance -= _amount_tokens;
        VulnerableContract(reciever).recieve{value: 7_500_000, flag: 0, bounce: true}(_amount_tokens, tvm.pubkey());
    }

    function recieve(uint128 _amount_tokens, uint256 _from_pubkey) {
        address expected_sender = _getExpectedAddress(_from_pubkey)
        require(msg.sender == expected_sender);
        balance += _amount_tokens
    }

    onBounce(TvmSlice body) external {
        tvm.accept();
        uint32 functionId = body.decode(uint32);
        if (functionId == tvm.functionId(VulnerableContract.transfer)) {
            uint128 amount_tokens = body.decode(uint128);
            balance += amount_tokens;
        }
    }
}

Attacker can call get_balance with answerID = tvm.functionId(VulnerableContract.transfer) and throw exception in callback. In this case VulnerableContract will receive unexpected onBounce and will double their tokens.

To solve this problems my suggestion is to force users to set ALL three params explicitly. Just throw compile time error if one of (value, flag, bounce) is not set.

Error: failed to recognize selector form linker v0.17.3

npx everdev sol set --compiler 0.64.0 --linker 0.17.3 # or 0.18.1 or 0.18.0 
npx everdev sol create App
npx everdev sol compile App.sol
$HOME/.everdev/solidity/tvm_linker disasm text App.tvc

Out:

Error: failed to recognize selector
Error: 1

Segmentation fault when using format function

If you use format function to insert values, if you provide empty string, it results in Segmentation fault error.
If you provide non-empty string without placeholders than you get message that number of placeholders is invalid:

Error: Number of arguments is not equal to the number of placeholders!
 --> TEST.sol:8:9:
  |
8 |         format("asdfadfa", 1, 2, 3);
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^

But empty string results in Segmentation fault.

Test contract:

pragma ton-solidity >= 0.39.0;
pragma AbiHeader expire;
pragma AbiHeader pubkey;
pragma AbiHeader time;

contract TEST {
    function someFunction() {
        format("", 1, 2, 3);
    }
}

Tested with v0.39.0 compiler and v0.43.0 compiler.

Segmentation fault: 11 for numbers more than 2**256 - 1 inside math.muldiv()

Explanation:

code math.muldiv(2**256, 123, 2); throws runtime exception of solc

[ERROR] /bin/sh: line 1: 54600 Segmentation fault: 11 /Users/fairyfromalfeya/Library/Caches/locklift-nodejs/compiler/0_61_2/solc_0_61_2_darwin

Correct behavior:

The user will receive a compilation error with message like: first argument 2**256 is more than max possible value for uint256

Missed elements in AST tree

The responsible function has specific returns with {parameters} like this:

return { value: 0, bounce: false, flag: MsgFlag.REMAINING_GAS } (left_wallet, right_wallet, lp_wallet);

( source DexPair.sol )

I generate an AST tree with the command

everdev sol ast --format compact-json DexPair.sol

But the AST tree doesn't have these parameters.

Internal compiler error when using two modificators with local variables

Hello!
Discovered new compiler issue recently:
When you try to compile contract with fucntion that has two similar modiifcators with local variables, compilator will fail.
Example similar to (cannot provide smart contract's source code):

modificator checkSum(uint sum) {
uint controlValue = 123;
require(sum > controlValue, 101);
_;
}
function testFunction() public checkSum(1234) checkSum(2345) {}

This will fail with error:

Internal compiler error during compilation:
/opt/TON-Solidity-Compiler/compiler/libsolidity/codegen/TVMPusher.cpp(1865): Throw in function void solidity::frontend::TVMStack::add(const solidity::frontend::Declaration*, bool)
Dynamic exception type: boost::exception_detail::clone_impl<solidity::langutil::InternalCompilerError>
std::exception::what:
[solidity::util::tag_comment*] =

Compiler version: 0.36.0+commit.a0771a7a

Proposal: encodeFunctionParam

Will be good to have encodeFunctionParam function by analogy with decodeFunctionParams,

Simple use case - contract upgrade:

function stateParams(
    uint32 _version,
    address _root,
    mapping (address => uint128) _balances,
    mapping (address => uint128) _approvedAddresses,
) public {}

function codeUpgrade(TvmCell _code) override external onlyRoot {
    TvmCell data = tvm.encodeFunctionParam(stateParams, version,  root, balances, approvedAddresses);

    tvm.setcode(_code);
    tvm.setCurrentCode(_code);

    onCodeUpgrade(data);
}

function onCodeUpgrade(TvmCell _data) private {
    tvm.resetStorage();
    TvmSlice state = _data.toSlice();
    (stateParams, version,  root, balances, approvedAddresses) = state.decodeFunctionParams(stateParams);
}

Also there can be more complicated use cases, like encode params for call in contract A, send it to contract B to approve by multisig/dao, and then call contract C with this TvmCell.

Segmentation fault on using library functions

Here is what I get:

line 29:   733 Segmentation fault      (core dumped) 

With this code:

pragma ton-solidity >=0.38.2;

library B {     

    function B2(uint128 value) public pure returns (uint128) {        
        return 20;
    }     

    // GOOD
    function B1(uint128 amountIn) public pure returns (uint128 outAmountX, uint128 outAmountY) {
        outAmountX = 10;
        outAmountY = B2(10);
    }   
}

contract A {

    struct SomeVal {
        uint128 amountX; 
        uint128 amountY;
    }       

    mapping(uint256 => SomeVal) list1_;    

    function func1(address _tokenAddress, uint256 _senderKey, address _senderOwner, uint128 _tokens) public {
        list1_.add(_senderKey,SomeVal(uint128(10),uint128(20)));
        SomeVal trans = list1_.fetch(_senderKey).get();
        (trans.amountX, trans.amountY) = B.B1(10);
    }          

}

Proposal: Add variables to msg namespace

Adding these two variables will allow:

  1. Find out how many coins were spent on forward (gas management)
  2. Implement custom logic with message cell. (flexibility)

msg.forwardFee

msg.forwardFee (varUint16)

Returns:

  • forward fee of the message for internal message.
  • import fee of the message for external message.

msg.cell

msg.cell (TvmCell)

Returns:

  • Message X cell

Segmentation fault during contract compilation

This error occured during compilation of contract lilbot.sol (attached in zip archive).
solc_bug
Used debot interfaces: https://github.com/tonlabs/ton-labs-contracts/tree/master/debots
Code was written at Windows 10 machine, then transferred to Ubuntu 18.04 server machine using SFTP (in case it is encoding issue).
Used solidity compiler version: 0.36.0+commit.5914224a.mod.Linux.g++

Problem is repeatable. If you need additional info - please contact me.

lilbot_bug.zip

Wrong function ID using contract interfaces for external function calls

Issue:
There is problem with using interfaces for calling contract's external function in spite of providing correct interface.

Example:
We have files ITestInterfaces.sol, TestInterfaces.sol, ICaller.sol and Caller.sol, their's content:

// ITestInterfaces.sol
interface Interface1 {
  function f1(...args) external;
}

interface Interface2 {
  function f2(...args) external;
}

interface Interface3 {
  function f3(...args) external;
}

interface Interface4 {
  function f4(...args) external;
}

interface Interface5 {
  function f5(...args) external;
}
// TestInterfaces.sol
contract TestInterfaces is Interface1, Interface2, Interface3, Interface4, Interface5 {
  ....
}
// ICaller.sol
contract ICaller {
  function call1(...args) external;
  function call2(...args) external;
...
}
// Caller.sol
contract Caller is ICaller {
  function call1(...args) external override {
    Interface1(knownContract).f1(..args);
  }

  function call2(...args) external override {
   Interface2(knownContract).f2(...args);
  }
  ...
}

Case:
Contracts will compile correctly, but sometimes during onchain execution of call1 or call2 call chain will fail with error 60, which means that function ID is wrong. This problem can be solved by using Contract instead of Interfaces for calls:

// Caller.sol
contract Caller is ICaller {
  function call1(...args) external override {
    TestInterfaces(knownContract).f1(..args);
  }

  function call2(...args) external override {
   TestInterfaces(knownContract).f2(...args);
  }
  ...
}

Sometimes it's not possible to use contract itself (may cause cyclic imports or some other problems).
This problem also appears if signature of function is changed. In my case - addition of another function parameter caused 60 error during onchain execution.

--ast-json doesn't work with --output-dir

For example, I run this command in terminal:
./solc --ast-json contracts/HelloWallet.sol --output-dir contracts

As a result, I see a huge ast-json code in my terminal. But I didn't receive it in the contracts folder.

Make generator json for solidity

Hello. I have a problem with generating json objects onchain. For example with tip4_2 we can change json on chain but for now its a bit hard
_json = '{"type": "Basic Nft", "name": "Opened nft lootbox","preview": {"source":"' + format("{}",_img.link) +'","mimetype":"' + format("{}", _img.mimetype) + '"}}';
we need to do such constructions where we can easily put a mistake. Probably, json generators like in python could help with this problems?

Pure function from lib potentially modifies the state

Here is what I get:

Error: Function declared as view, but this expression (potentially) modifies the state and thus requires the default.

File (ErrorA.sol):

pragma ton-solidity >=0.38.2;

library A {

    function calc(uint128 value) public pure returns (uint128) {
        return value++;
    }
}

contract B {

    uint128 constant VAL = 1;

    function make() external view {
        A.calc(VAL);
    }
}

As you can see there are:

  • no state variables that can be modified
  • all vars are constants
  • library function is pure itself.

Still, compiler shows error. Tested with 0.38.2.

TvmSlice.decode can't decode large structures

tvm.encodeBody works fine with large structures which don't fit into one cell, but slice.decodeFunctionParams gets cell underflow exception when trying to decode such body. So this case breaks the invariant that I can encode some message payload with tvm.encodeBody(), then decode it with TvmSlice.decodeFunctionParams() and get the same result.

Here is some sample code.

pragma ton-solidity ^0.44.0;

contract Mem {
    constructor() public {
        tvm.accept();
    }

    struct BigStruct {
      uint256 a;
      uint256 b;
      uint256 c;
      uint256 d;
    }

    BigStruct really_big;

    function set(BigStruct me_also_big) public {}

    // gets cell underflow
    function get() public returns (BigStruct, BigStruct) {
        TvmCell hm = tvm.encodeBody(Mem.set, really_big);
        TvmSlice slice = hm.toSlice();
        BigStruct me_also_big = slice.decodeFunctionParams(Mem.set);
        return (really_big, me_also_big);
    }
}

The same issue also holds for TvmBuilder.store() and TvmSlice.decode();

Internal compiler error when inherit static attribute from contract in a separate file

Here is the compiler error when inheriting static value from separate file:

Internal compiler error during compilation:
/solidity/libsolidity/codegen/TVMFunctionCall.cpp(275): Throw in function solidity::frontend::FunctionCallCompiler::generateDataSection(std::function<void()>, bool&, solidity::frontend::ASTPointer<const solidity::frontend::Expression>, bool&, solidity::frontend::ASTPointer<const solidity::frontend::Expression>)::<lambda()>::<lambda(const string&)>
Dynamic exception type: boost::wrapexcept<solidity::langutil::InternalCompilerError>
std::exception::what:

Child contract (ErrorB.sol):

pragma ton-solidity >= 0.36.0;

import "ErrorA.sol";

contract B is A {
    function getCode()  external view returns (uint256 num) {
        num = num_;
    }
}

Parent contract (ErrorA.sol):

pragma ton-solidity >= 0.36.0;

contract A {
        uint256 static num_;  
}

Important! If we place contract A in the same file, there will be no error.

Proposal: Add the ability to attach stateinit when calling contract interface

Adding stateinit when calling the contract interface will allow you to "deploy" contracts without using a constructor. This will make it possible to create more flexible systems using more blockchain features (in TVM-based blockchains there is no concept of "deploy" as such)

expected syntax:

IContract(address).testFunction{ value: 1 ever, stateInit: cell }();

or

IContract(address).testFunction{ value: 1 ever, stateInit: builder }();

or

IContract(address).testFunction{ value: 1 ever, stateInit: slice }();

API doesn't describe mapping limitations

API.md states the following on mappings:

Address, bytes, string, bool, contract, enum, fixed bytes, integer and struct types can
be used as a KeyType. Struct type can be used as KeyType only if it contains only
integer, boolean, fixed bytes or enum types and fits ~1023 bit
.

You can read the rest & example here.

Still the code from API.md example works only for mapping declaration, if you use such mapping (with struct key) as a function param, this happens:

Error: Key type of the mapping must be any of int<M>/uint<M> types with M from 8 to 256 or std address.
  --> \contracts-core\src\main\solidity\SomeContract.sol:40:44:
   |
40 |     function setExample(uint128 minStake_, mapping(Point => address) checkMap_) external externalMsg checkExtOwnerAndAccept {
   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Would be great to describe limitations in API.md

JSON AST encoding for a cycle over mapping type

Hi!

The sample is as follows:

pragma ton-solidity ^0.44.0;

contract Sample {
    struct Info {
        uint id;
        uint val;
    }
    mapping (address => Info) public _addrs;
    
    function calcsum() external view returns (uint) {
        uint sum;
        for ((, Info oi) : _addrs) {
            sum += oi.val;
        }
        return sum;
    }
}

I compile it using

$ solc --compact-ast-json ./Sample.sol

The resulting JSON file map the for statement into an ordinary ExpressionStatement, without any clue regarding
the nature of this statement, i.e. cycle over a mapping.

Is it intentionally done this way?

I would expect it to be at least a ForStatement. It would be even better to distinguish it with a special ForOverMappingStatement, because it has different syntax/AST nodes.

contract constructor can't be external

When I try to compile the following code:

pragma ton-solidity >=0.59.4;

contract Test {
    constructor() external internalMsg { }
}   

I get an error: Error: Constructor must be public or internal. I want to allow deploy my smart contract by internal message without making the constructor call available inside the contract, but I can't do that. I think this seems to be an issue.

Bug: invalid abi.encode for lot of params

Description:

abi.encode passes, but transaction reverts with code 7 after abi.decode (with valid types)

TvmCell:

Tuple (Tuple (124711402, 0, 0, 1666614155, 31787919000007, 31787919000007, 0, Tuple (2955743846, Null), Slice x8018dd1229cd5e8f662163fcd0876ec56085305d3537aca261aeedc985317b5710d_, Cell x0a9fb4949d9bd5a2633a2e375fe4e96fe962d55830edd84242b55e09376782b2 xcd4_, Cell xddf73f1108c1a2c69e415165f834139ee986c7a6840c496b4eb55fe23e0a1b33 x8aed5320e30320c0ffe30220c0fee302f20b), Null, 0, 0, Tuple (Null, -1, 10000000, Null, 0), Null, -1, Null, Null, Slice x80109d345cdd81be52021a54e306f3f0e6019effe0ed2929bf6c716efd3065d3745_, Slice x8000000000000000000000000000000000000000000000000000000000000000001_, Slice x8000000000000000000000000000000000000000000000000000000000000000001_, 0, Cell x96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7 x, Cell x96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7 x, 0, Slice x8000000000000000000000000000000000000000000000000000000000000000001_, Slice x8000000000000000000000000000000000000000000000000000000000000000001_, 0, 0, 0, 0, 0, 0, 0, 0, 0, Null, Null, Null, 0, 0, 0, 0, 0, 1000000000000000000, 1000000000000000000, 1666613441, 0, 0, Null, Null, Null, 0)

Transaction: d1381282ee1999a46186ab60aa4e900dd03cbd3f4b05f4d39b2f5e8d867a166e

Move around solution:

Pack some variables to structure and pass this structure to abi.encode & abi.decode

Bug or incorrect docs on <string>.append() - type check error

Sequence like this works like a charm:

string str = "STR1";
bytes bytStr = bytes(str);

Then we add append step...

string str = "STR1";
str.append("-STR2");
bytes bytStr = bytes(str);

And get this runtime error:

Error: Failed: {
  "code": 414,
  "message": "Contract execution was terminated with error: compute phase isn't succeeded, exit code: -8 (type check error). For more information about exit code check the contract source code or ask the contract developer",
  "data": {
    "core_version": "1.10.0",
    "phase": "computeVm",
    "exit_code": -8,
    "exit_arg": null,
    "account_address": "0:41ed43a28f2b1aee5066081c2aa940f9a79370b978545c80ad38618a46ee06d2",
    "gas_used": 10553,
    "description": "type check error",

I'm not sure if this a bug or append() just returns some unusual type that I need to parse first. Perhaps, API doc is misleading.
Tested with 0.38.2.

Add constants for flags and error codes

Usual solidity contracts are full of numeric flags like 64.
It's inconvenient to look those up each time, but you'd want yo make sure you are not mistaken.
I suggest to add compile time constants with meaningful names.

So for example instead of:

msg.sender.transfer({value:0, flag:64, bounce:false})

You would have:

msg.sender.transfer({value:0, flag:flags.REMAINING_GAS, bounce:false})

Error when trying to get ast from debot smart contract

When I try to get ast from not debot contracts it works well! But with debot contract I have this error:

$ everdev sol ast gameDebot.sol
Exception during output generation: C:\jenkins\workspace\Builder\services\Sol2TVM\sol2tvm-8631\sol2tvm\pub\compiler\libsolidity\interface\CompilerStack.cpp(1148): Throw in function const struct solidity::frontend::CompilerStack::Source &__cdecl solidity::frontend::CompilerStack::source(const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &) const
Dynamic exception type: class boost::exception_detail::clone_impl<struct solidity::langutil::CompilerError>
std::exception::what: Given source file not found.
[struct solidity::util::tag_comment * __ptr64] = Given source file not found.

Error

P.S. Error was on Windows. On Ubuntu working fine.

Proposal: change tx.timestamp naming

At the moment the variable which is logical time is named timestamp (tx.timestamp)

Although another variable, which is also a logical time, is named logicaltime (block.logicaltime)


I propose to change the current naming:

tx.timestamp returns (uint64);

to correct naming:

tx.logicaltime returns (uint64);

(or create an alias)

cmake --build . -- -j8

cmake --build . -- -j8
[ 37%] Built target jsoncpp-project
[ 37%] Built target solidity_BuildInfo.h
Consolidate compiler generated dependencies of target solutil
[ 37%] Built target solutil
Consolidate compiler generated dependencies of target langutil
[ 37%] Built target langutil
Consolidate compiler generated dependencies of target solidity
[ 37%] Building CXX object libsolidity/CMakeFiles/solidity.dir/codegen/TVMContractCompiler.cpp.o
/Users/lexzandr/TON-Solidity-Compiler/compiler/libsolidity/codegen/TVMContractCompiler.cpp:192:12: error: implicit instantiation of undefined template 'std::basic_ofstream'
ofstream ofile;
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/iosfwd:151:32: note: template is declared here
class _LIBCPP_TEMPLATE_VIS basic_ofstream;
^
/Users/lexzandr/TON-Solidity-Compiler/compiler/libsolidity/codegen/TVMContractCompiler.cpp:211:14: error: implicit instantiation of undefined template 'std::basic_ofstream'
ofstream ofile;
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.3.sdk/usr/include/c++/v1/iosfwd:151:32: note: template is declared here
class _LIBCPP_TEMPLATE_VIS basic_ofstream;
^
2 errors generated.
make[2]: *** [libsolidity/CMakeFiles/solidity.dir/codegen/TVMContractCompiler.cpp.o] Error 1
make[1]: *** [libsolidity/CMakeFiles/solidity.dir/all] Error 2
make: *** [all] Error 2

Cannot compile contract with external function as callback.

When you try to specify callback function and it's visibility is external, following error occures:

Error: Undeclared identifier. "testFunction" is not (or not yet) visible at this point.
  --> testContract.sol:12:59:
   |
12 |         CallbackTest(a).thisWillReturnSomething{callback: testFunction}(123);
   |                                                           ^^^^^^^^^^^^

Test contract:

pragma solidity >= 0.6.0;

import './TestInterface.sol';

contract SetCode { 
    uint c;
    constructor() public {
        tvm.accept();
    }

    function callExternalFunction(address a) external {
        CallbackTest(a).thisWillReturnSomething{callback: testFunction}(123);
    }

    function testFunction(uint b) external {
        c = b + b;
    }
}

Used test interface:

pragma solidity >= 0.6.0;

interface CallbackTest {
    function thisWillReturnSomething(uint param) external returns(uint);
}

Contract will compile if you change visibility of testFunction to public:

pragma solidity >= 0.6.0;

import './TestInterface.sol';

contract SetCode { 
    uint c;
    constructor() public {
        tvm.accept();
    }

    function callExternalFunction(address a) external {
        CallbackTest(a).thisWillReturnSomething{callback: testFunction}(123);
    }

    function testFunction(uint b) public {
        c = b + b;
    }
}

Make true JSON for AST

solc --ast-compact-json A.sol

Actual:

JSON AST:


======= absolutePathA.sol =======
{"absolutePath": "absolutePathA.sol"}
======= absolutePathB.sol =======
{"absolutePath": "absolutePathB.sol"}

Expect:

[
  {"absolutePath": "absolutePathA.sol"},
  {"absolutePath": "absolutePathB.sol"}
]

Proposal: add warning in case of using msg.pubkey() without AbiHeader pubkey

Hi!

Today, I spent several hours trying to find out why the message I sign with some key fail to pass the signature check in my contract, until found the reason, stated in the API documentation:

"Returns sender's public key, obtained from the body of the external inbound message. If the message is not signed, msg.pubkey() returns 0. If the message is signed and message header (pragma AbiHeader) does not contain pubkey then msg.pubkey() is equal to tvm.pubkey()."

As for me, this behavior feels a bit counter intuitive. Maybe it would be better to show a warning in case of using the msg.pubkey() without pragma AbiHeader pubkey?

Potential Optimizations in TON Solidity Compiler

This issue aims to identify and address potential optimizations in the TON Solidity Compiler, specifically focusing on areas in the generated assembly code that can be optimized.

The objective of this issue is to improve the performance and efficiency of the TON Solidity Compiler by identifying specific areas within the generated assembly code that can be optimized. By optimizing the code, we can enhance the overall execution speed and reduce the gas consumption of smart contracts deployed on TVM-based blockchains.


Checklist of optimisations:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.