Hands-On Blockchain for Python Developers
上QQ阅读APP看书,第一时间看更新

Motivations behind Vyper

Writing a smart contract is different than developing a normal web application. When developing a normal web application, the motto is move fast and break things. The speed of developing a web application is paramount. If there is a bug in the application, you can always upgrade the application later. Alternatively, if the bug is catastrophic, you can patch it online or take the application offline before introducing a fix. There is a very popular word to describe the ideal mindset in developing a normal web application—agile. You need to be flexible in order to change the software as the requirements change.

However, writing a smart contract requires a different mindset. The application of smart contracts can range from writing a financial application to launching a rocket into space. Fixing an error once a smart contract is deployed is very difficult. You cannot replace a smart contract because once it is deployed, it is deployed. You can destroy a smart contract if you write a function to do so, but the only way to fix a faulty smart contract is to deploy a new smart contract that has the fix to the error in a new address, and then communicate this situation to all concerned parties. But you cannot replace a smart contract.

So, the ideal situation would be a smart contract deployed on the blockchain with no bugs, or at least without malignant bugs. However, bugs still appear in smart contracts that are released in the real world.

So, what kind of bugs can appear in smart contracts? The first kind is the one that will make your money disappear. Let’s say you are writing a smart contract for an initial coin offering (ICO). An ICO is the accumulation of capital by selling tokens that you have created on top of an Ethereum blockchain. So basically, people buy your token with ethers. You can set the price as you like—for example, 1 ETH = 100 YOURTOKEN. This means that people would get 100 of your tokens if they pay you 1 ether.

The first bug that you can introduce is that people can send money (ethers) to your smart contract, but you cannot withdraw it (either you forgot to implement the withdrawal method or the withdrawal method is faulty). This would mean that you could check your smart contract’s balance, and the ether balance could well be worth $1 million, but it would be stuck there forever and no one would be able to claim it.

Another bug could be that you forgot to secure the method to destroy a smart contract. In Ethereum, you are incentivized to remove stuff from the blockchain because storage is expensive. So if you deploy a smart contract, you will pay a gas fee because your smart contract will be kept. You can experiment with it, and then if you get bored with your smart contract, you can destroy it. To do that, Ethereum will give some gas back to your account. This is to discourage spamming the Ethereum blockchain. So, going back to our case of the smart contract’s bug, imagine that you have accumulated $1 million worth of ether in your smart contract, and then someone destroys your smart contract account by accessing a function to destroy it. In this case, your ether balance will be destroyed as well.

The last type of bug is one that allows a hacker to steal your ether balance and move it to their account. This could occur under many different circumstances. For example, maybe you forgot to the set correct permissions in the withdrawal function, or maybe the permission in the withdrawal function is too open.

Of course, all of these bugs can be traced back to the fault of the programmers. To avoid these kinds of bugs, a new kind of job was born—a smart contract auditor, who audits your smart contract to make sure it does not have bugs. However, Vitalik Buterin (the inventor of Ethereum) then looked at the tool (the programming language, in this case) and wondered whether this situation could be mitigated by improving the tool itself. The culprit in this case is the Solidity programming language. Vitalik argued that Solidity has some features that are powerful, but have the potential to create bugs. Although the developers of Solidity had a plan to improve the safety of Solidity, Vitalik wanted some freedom to experiment with a fresh perspective. From this, Vyper was born.

Say that you created a parent class that has an important function. In your current or child class, you use this function without checking its definition. Perhaps the parent class was written by someone else in your team. Programmers are sometimes too lazy to check function definitions in other files; they will scroll up and down in a source code file to read the code, but programmers often will not check code in other files enabled by the inheritance feature.

Another Solidity feature that could really make a smart contract complicated and hard to read is a modifier, which is like a preliminary function. The following code shows how a modifier is used in Solidity:

modifier onlyBy(address _account)
{
require(msg.sender == _account, "Sender not authorized.");
_;
}
function withdraw() public onlyBy(owner)
{
//withdraw money;
}

If we want to use the withdraw() method, the smart contract will execute the onlyBy() modifier method first. The require phrase is used to ensure that msg.sender (which calls this method) is the same as the account variable that was sent as a parameter. This example is simple. You can read all of the code in the blink of an eye. However, consider the fact that these functions are separated by many lines, or even defined in another file. Programmers have a tendency to overlook the definition of the onlyBy() method.

Function overloading is one of the most powerful features in programming languages. This is a feature that enables you to send different parameters to get different functions, as shown in the following code:

    function flexible_function(uint _in) public {
        other_balance = _in;
    }

    function flexible_function(uint _in, uint _in2) public {
        other_balance = _in + _in2;
    }

function flexible_function(uint _in, uint _in2, uint _in3) public { other_balance = _in + _in2 - _in3; }

However, the function overloading feature can mislead programmers, causing them to execute a function with a different intention. A programmer might only remember that the flexible_function function does this, but could innocently execute a different kind of function than flexible_function.

Consequently, some smart people decided that while all of these features make it possible to create a really complex program, these features should be limited to developing a smart contract. Perhaps they got this idea from those who write programs on spacecraft, where there are rules as to which features of C++ are forbidden to be used. Alternatively, they could have been inspired by the reason why Java was created to replace C++. In Java, direct manipulation of the memory feature was not possible. Bjarne Stroustoup (the creator of C++) said that C++ is so powerful that with C++, people can shoot themselves in their foot.

These smart people decided to create a new programming language that is simpler than Solidity. Python is their main inspiration because the syntax of this programming language is derived from Python. This programming language is called Vyper. In Vyper, features such as inheritance, function overloading, modifiers, and many others are removed. The creator of the Vyper programming language argued that the removal of these features can make the development of a smart contract easier. Importantly, it also makes the code easier to read. Code is read much more than it is written. With all of these factors, they hope that programmers could create fewer bugs when using the Vyper programming language to create a smart contract.