...by Daniel Szego
quote
"On a long enough timeline we will all become Satoshi Nakamoto.."
Daniel Szego
Showing posts with label Solidity. Show all posts
Showing posts with label Solidity. Show all posts

Friday, October 2, 2020

Ethereum solidity security tools summarized

 


Security in solidity - Ethereum has been always one of the most important topic. Some of the current most important tools are the followings:

SWC Registry /  

Smart Contract Weakness Classification and Test Cases

https://swcregistry.io/

Ethereum Smart Contract Security Best Practices 

https://consensys.github.io/smart-contract-best-practices/

MythX - a cool tool for getting information on solidity smart contract vulnerabilities 

https://mythx.io/ 

EthLint - an open source tool for analyzing Ethereum smart contracts. 

https://github.com/duaraghav8/Ethlint

Slither  - for making static code analysis on solidity contracts

https://github.com/crytic/slither

Hydra - framework for security and bug bounties

https://github.com/IC3Hydra/Hydra



Saturday, March 16, 2019

Phases of learning solidity programming

Month 1: Yes, I can program in Solidity ! This is an easy language, similar to Javascript, with some types.

Month 2: Wait, Underflow / overflow ? I thought they can not cause problems.

Month 3: But, I should upgrade my contract ? Because it contains already ether and I forgot to implement an etherTransfer function ?

Month 4: Cool, I have some upgrade patterns, but they cost too much ether.

Month 5: Ooh, msg.sender, tr.origin, contract in the middle attacks ?

Month 6: Or, Fallback function ? Reentrancy ?

Month 7: Hmm, A transaction is always atomic, right ? So what is with address.transfer or address.call.value ?

Month 8: And, Libraries, Delegate calls ?

Month 9: Hence,  Stack, call stack attacks and front running?

Month 10: So, How about just reusing some ready libraries ? Like OpenZeppelin ?

Month 11: Or, Formal verification, bug-bounty, military programming ?

Month 12: No, I can not program in Solidity !

Wednesday, January 2, 2019

Solidity Tips and Tricks - security of the view modifier of a function


Solidity view function modifier means that the function do not modify the storage of the contract, due to the fact that it costs no gas to call this function. However, one might as well assume this feature as a security guarantee, meaning that the function can not modify the storage.  It is important to note however that in the 4. compiler versions there is actually no guarantee for that, the compiler gives a warning, but despite it compiles and deploys the contract without error. As an example, considering the following contracts:

pragma solidity ^0.4.24;

contract ViewImplementation {    
 uint public storageVariable = 0;
    
 function viewFunction() view external returns (uint) {
   storageVariable = 2;
   return 1;
 }
}

contract TestViewImplementation {
    
  address contractAddress =
           0xbbf289d846208c16edc8474705c748aff07732db;
    
 function testView() public {
   ViewImplementation imp =  ViewImplementation(contractAddress);
   imp.viewFunction();
 }  
}

Calling the viewFunction externally implied zero gas consumption and the storageVariable will not be modified. However, calling the function from another contractlike from testView will modifiy the storageVariable to 2.

The situation is fortunately better in the 5+ solidity versions, as there is not only warning but a compiler error as well in such a situations.  

Sunday, December 30, 2018

Solidity Tips and Tricks - struct at local function hack


Solidity has a lot of surprising and actually shitty characteristics. On thing is that a struct can be defined both in memory and in storage as well similarly to arrays. The problem is however that if you define your struct in a local function body, it overwrites the storage variables of the contract itself. On top unfortunately, if you create a struct in a function body without explicitly marking if it is a storage or a memory one, it is created automatically as a storage. So the following example:

contract StructHack {
    uint public myNum = 0;
    
    struct TestStruct {
        uint structNum;
    }
    
    function hackStruct() {
        TestStruct test;
        test.structNum = 22;
    }
}

Surprisingly, if you deploy the contract and call the function hackStruct, the myNum value will be initialized to 22.  

Wednesday, December 26, 2018

Solidity Tips and Tricks - transferring ether at fallback logic


There are basically three ways of sending ether from a solidity contract:

- contractAddress.call.value("sent_value")() is the less secure version of all of the possibilities. It opens the door for reentrancy and other attacks. It is usually not proposed to use this contract due to security reasons. However, if you transfer ether for a contract that has a complicated fallback functionality, actually this is the only possibility. If you want to fine-tune the gas price of the executed target logic, it is again the only possibility. 

- contractAddress.send("value") sends the value to the address in a way that only 23000 gas is allocated to a possible fallback logic. The call gives back a true or false value depending result of the logic. So it can not really be used at complicated fallback logic. 

- contractAddress.transfer("value") sends the value to the address in a way that only 23000 gas is allocated to a possible fallback logic. The call throws an exception if something goes wrong, so it is regarded as a more secure way of transferring values. It can not be used at complicated fallback logic either. 

Sunday, November 25, 2018

How to trigger Ethereum smart contract if Solidity event occurs


Well you cannot react to an event in a solidity smart contract, there is no command at all in EVM that checks the event log. Besides, there is no way of starting a smart contract automatically. However, you can use a semi-trusted setup with Oraclize, where similarly to my previous blog, you can periodically check if an event has occurred.

Firstly, you can use an Ethereum explorer API to get information of an event of a contract with the following http get request.

https://api-ropsten.etherscan.io/api?module=logs&action=getLogs
   &fromBlock=<from>
   &toBlock=latest
   &address=<contract address>
   &topic0=<event id>&
   apikey=<YourApiKeyToken>

So, what you have to do is to query this log periodically with Oraclize and check if the necessary information is present.

  // schedule update schedules the next call
 function scheduleUpdate() payable {
   if (oraclize_getPrice("URL") > this.balance) {
       LogNewOraclizeQuery("Not enough fund");
   } else {
       // NEXT UPDATE IS SCHEDULED IN 60 MIN
      oraclize_query(60, "URL", " url explorer API for the event ");
   }
 }

 function __callback(bytes32 myid, string result) {
    // SECURITY CHECK
    if (msg.sender != oraclize_cbAddress()) revert();
        
    // PROCESS INFORMATION
    if (information_not_present){
    // SCHEDULE NEXT UPDATE
       scheduleUpdate();
    }
 }

Certainly this is not the cheapest and most efficient way of triggering a smart contract for an event, but it might work on a small scale. Experimental implementation can be found under EventTriggeredEthereumContract in the following GitHub repo

Saturday, November 24, 2018

Truffle and solidity tips and tricks - test events in unit tests


If you use truffle and want to test solidity with javascript unit test, you might want to test the raised events as well. As result gives back the whole transaction including the event log, the easiest way to get the event is to get them directly from the event log:

   return ContractInstance.functionCall({from: accounts[0]});       
   }).then(function(result) {

- result contains the whole transactions
result.logs contains the whole log
- result.logs[0].event contains the first event

So, an assert that checks if an event was raised might simply look like:

assert.equal(result.logs[0].event, "EventName", "Event raised");



Friday, November 23, 2018

Truffle and solidity tips and tricks - error at contract deployment gas amount


If you deploy a contract with the help of truffle possibly on a development environment and you get the following error message: 

"Error encountered, bailing. Network state unknown. Review successful transactions manually 
Error: The contract code couldn't be stored, please check your gas amount."

Well, there might be the problem of the real gas amount at the deployment, but most typically you want to deploy a contract that has an abstract method, or it inherits coincidentally and abstract method that is not implemented. 

Tuesday, November 20, 2018

Truffle and solidity tips and tricks - nonce error with Metamask


If you use truffle development environment with Metamask as well you can often get the following error message: "the tx doesn't have the correct nonce". The problem is that you probably use the same accounts both from truffle development console and from the Metamask UI. Unfortunately, Metamask does not automatically update/refresh the nonce if the transaction was executed by the truffle development console. So what you have to do is to reset the Metamask account: Settings - Reset Account. 

Thursday, November 15, 2018

Solidity and Truffle Tips and Tricks - converting string to byte32


If you want to convert strings in solidity to byte32 and you get different kind of error messages at  explicit or implicit converting or at changing between memory and storage variables, you can use the following function:


function stringToBytes32(string memory source) 
                                        returns (bytes32 result) {
    bytes memory tempEmptyStringTest = bytes(source);
    if (tempEmptyStringTest.length == 0) {
        return 0x0;
    }

    assembly {
        result := mload(add(source, 32))
    }
}

Tuesday, November 6, 2018

Solidity as a consortium blockchain programming language



There are many initiatives of using solidity as a blockchain programming language not just in Ethereum but in many other mostly consortium blockchain solutions. On the one hand, this is a logical direction, as most of the developers who has blockchain programming experience have the experience with solidity - Ethereum. On the other hand, most of the existing blockchain applications are realized with the help of Solidity so they might be migrated this way to a consortium platform without any modification. 

Despite the direction is perhaps not absolutely optimal. On the one hand, Solidity was one of the pure Blockchain oriented programming language and certainly it is good for a first initiative but it is perhaps not so optimal on a long run. It has several "child illnesses" that should be repaired on a long run, like the chaotic type system or payment functions. On the other hand, programming on Ethereum with Solidity supposes indirectly very strong constraints in terms of computation and gas. If the same use case is put on the top of a consortium blockchain, where gas is practically free of charge, the application should be implemented probably totally differently, even if the programming language is the same. 

Wednesday, August 1, 2018

Solidity Tips and Tricks - decentralized maintenance


In a blockchain system, you might sometimes have the problem, that there should some kind of a maintenance job that should be running regularly. For such a problems, you usually implement something as a maintenance or timer job in centralized systems. However considering a fully decentralized system it is pretty much unpractical. What might be a good direction is to create a special decentralized role for maintenance in a way that this role will be rewarded somehow for doing the maintenance. The idea is similar to the idea of the miners. A miner maintain the state of the blockchain and for that activity they are rewarded by the transaction fees and the newly generated coins. The idea can be repeated however, there might be further roles doing kind of a system maintenance jobs for a certain  monetary reward. A very simple solidity code for that can be seen in the followings:

contract DecentralizedOperation {
    mapping(address => uint) balanceOpReward;
    
    function Maintainance() {
        // do maintainance
        balanceOpReward[msg.sender]++;
    }
}

Tuesday, July 31, 2018

Solidity Tips and Tricks - running optimization


Let we imagine the situation that we have to implement a smart contract that needs to have some kind of an external optimization after every call of business logic, like optimizing an IOU graph. What we can do is to set a bool variable and two modifiers indicated if our data structure is optimized or not. If the data structure is optimized we can call any kind of a business logic. If it  is not optimized we should be able to call only the OptimizationLogic function. Certainly, access control rights and roles of such a system are pretty much questionable and need some more fine tuning. 

contract Optimization {
    bool optimized;
    
    constructor() {
        optimized = true;
    }
    
    modifier Optimized {
        require(optimized);
        _;
    }

    modifier NotOptimized {
        require(optimized == false);
        _;
    }
    
    function BusinessLogic() Optimized {
        // doing business business logic
        optimized = false;
    }

    function OptimizationLogic() NotOptimized {
        // doing optimization logic
        optimized = true;
    }
}

Simple IOU contract with optimization possibility on Ethereum

Simple systems administrating IUO contracts can be easily realized on the top of Ethereum. Let we say that accounts can issue new IOU-s that are administrated as credit and debit balance. Someone can issue an IOU to any particular account, but nobody can issue an IOU in the name of somebody else. There is a further external role for optimizing the IOU graph, for the first run optimizing only means reducing the difference of credit and debit balance for a certain node. The role can be at the moment anybody and for the activity there is an extra reward token as an incentive mechanism. A simple code is shown in the following example.

contract SimpleIOUWithOptimization {
    
 mapping(address => uint) creditBalances;
 mapping(address => uint) debitBalances;
 mapping(address => uint) rewardBalances;

    
 function issueCredit(address _to, uint _value) {
  creditBalances[msg.sender] += _value;
  creditBalances[_to] += _value;
    }
    
 function optimizeAccount(address _account){
  if((debitBalances[_account] - creditBalances[_account]) >= 0) {
   rewardBalances[msg.sender]+=  debitBalances[_account] -  
     creditBalances[_account];
   creditBalances[_account] = 0;
   debitBalances[_account] -= debitBalances[_account] -  
     creditBalances[_account]; 
  }
  else{
   rewardBalances[msg.sender] +=  creditBalances[_account] - 
     debitBalances[_account];
   debitBalances[_account] = 0;
   creditBalances[_account] -= creditBalances[_account] -
     debitBalances[_account]; 
  }
 }
}

Certainly in this use case, the optimization could be executed right at the credit issunance, however in more complicated scenarios this might be not the option. 

Tuesday, July 24, 2018

Creating matrix operators with solidity

Solidity is not really meant to store a large amount of data. However it might happen despite that requirements are to store matrixes in our smart contract. If that happens, one of the possibility is to store them as hash tables realized by mappings:

contract Matrix{
    
    mapping(uint => mapping(uint => uint)) _matrix;
    uint public maxi;
    uint public maxj;

    function elementAt(uint i, uint j) public returns (uint) {
        return _matrix[i][j];
    }
    
    function setElement(uint i, uint j, uint _value) public {
        _matrix[i][j] = _value;
        if (i > maxi) {
            maxi = i;
        }
        if (j > maxj) {
            maxj = j;
        }
    }
}

In this way accessing or modifying matrix operators are easy. However, if we have to create operations on the top of the matrixes like, adding or subtracting them, it might become pretty costly very fast, because we have to iterate on the matrixes with nested loops and even if the matrix is spare, meaning that only a couple of elements are filled out, both the iteration and the modification costs money. 

contract MatrixOperator{
    
    function add(Matrix _matrix1, Matrix _matrix2) public {
        // get max elements
        uint maxi = _matrix1.maxi();
        if (_matrix2.maxi() > _matrix1.maxi()){
            maxi = _matrix2.maxi();
        }

        uint maxj = _matrix1.maxj();
        if (_matrix2.maxj() > _matrix1.maxj()){
            maxj = _matrix2.maxj();
        }

        for (uint i=0; i < maxi; i++) {
            for (uint j=0; j < maxj; j++) {
                if ((_matrix1.elementAt(i,j)>0) && (_matrix2.elementAt(i,j)>0)) {
        _matrix1.setElement(i,j,_matrix1.elementAt(i,j) + _matrix2.elementAt(i,j));
                }
            }
        }    
    }
    
    function sub(Matrix _matrix1, Matrix _matrix2) public {
        // get max elements
        uint maxi = _matrix1.maxi();
        if (_matrix2.maxi() > _matrix1.maxi()){
            maxi = _matrix2.maxi();
        }

        uint maxj = _matrix1.maxj();
        if (_matrix2.maxj() > _matrix1.maxj()){
            maxj = _matrix2.maxj();
        }

        for (uint i=0; i < maxi; i++) {
            for (uint j=0; j < maxj; j++) {
                if ((_matrix1.elementAt(i,j)>0) && (_matrix2.elementAt(i,j)>0)) {
        _matrix1.setElement(i,j,_matrix1.elementAt(i,j) - _matrix2.elementAt(i,j));
                }
            }
        }    
    }
}

In practical scenarios, working with matrixes bigger than 10 is pretty much unpractical. Even with matrixes smaller than 10, you have to calculate with a gas cost of 5000 - 20000 for each modified value. 


Friday, July 6, 2018

Comparing Vyper to solidity


Vyper is the brand new language of Ethereum. It aims to repair the problems of solidity especially regarding the security vulnerabilities. It is a simple contract based language, meaning one contract one file without any possibilities for inheritance, or cross-contract communication. The most important elements are the following:

Variables: variables are similar to solidity, the exception is that there is only public or the default visibility which is private. The atomic types are more or less the same, one exception is however that there are no shorthand types, like uint for uint256, or string for a byte array. One advantage is though that there is already decimal.  

publicVariable: public(uint256)
privateVariable: int256

Functions are transactions as usual, one difference is certainly, the syntax is rather similar to the python syntax and not to javascript. Two more differences are that you must always explicitly include the function visibility which is @public or @private. 

@public
def myFunction(_input1: uint256, _unput2: uint256) -> uint256:
    return _input1 - _unput2

self keyword: if you want to refer to a state variable in your function, you can do only do it with explicitely marking with the self.variableName.
Constructor has a special name shown as __init__:

@public
def __init__

Events are similar to solidity events, the only difference is that you define them and raise them with different syntax:

MyEvent: event({_param1: uint256, _param2: uint256})
log.MyEvent(1,2)

Structs are similar to solidity, the only exception is that you can not use them dynamically as types, they are rather types and instantized variables in the same time. 

exampleStruct: {
    value1: int128,
    value2: decimal
}
self.exampleStruct.value1 = 1

Error handling is much simplified. There is an assert that works similarly to solidity, however no other such error handling function is to be found. 

assert 1 == 1

Loops: there are just a special kind of loop in Vyper that guarantees that the loop will end in a certain number of steps.

for i in range(0, 30):

Other elements of the language are pretty much similar to solidity. There aren't fallback functions, the possibility is to call another function of another smart contract is pretty limited (raw_call). There is a low level function to duplicate a code contract, but otherwise there is not really a dynamics contract creation pattern. 


Solidity Tips and Tricks - modifier inheritance


In solidity modifiers are inherited and they always overwrite the modifier of the ancestor. There is no way to call the ancestor class modifier if it has been overwritten, however, you can reference both the ancestor and descendant elements as well in your modifier. As an example:

contract Ancestor {
    uint public number = 11;
    
    modifier IsBig  {
            require (number > 10);
            _;
    }
}

contract Descendant is Ancestor {
    uint public number = 22;

    modifier IsBig  {
            require (Ancestor.number < 20);
            _;
    }
    function testFv() IsBig {
        
    }
}

In testFv() there is no possible to reference on super.IsBig or Acesntor.IsBig, the only thing that you can call is the overwritten IsBig modifier. 

  

Sunday, June 17, 2018

Solidity Tips and Tricks - private variable value


Private variables from solidity are usually not so private as they are expected. Value of a private variable can be read out by someone running a full client node and having a javascript console. As an example, considering the following private variable of a contract:

contract PrivateContract {

    string private Password = "MyPassword123";

    constructor() public {
    }

By knowing the contract address and running a full node on the Ethereum network, you can easily read out the value of the private variable, like with:

 web3.eth.getStorageAt(contractAddress, 0)

which results the following hex value:

'0x4d7950617373776f72643132330000000000000000000000000000000000001a'

after encoding:

MyPassword123

So the message is simple, do not store private information in private variables on the blockchain, because it is not really private !


Monday, May 14, 2018

Solidity and Truffle Tips and Tricks - starting geth --rpc error


If you start to sync a chain with the --rpc parameter and you get different error messages, like: 
"Error starting protocol stack: listen tcp 127.0.0.1:8545: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted." or simply memory null pointer exception that does not say too much, than check if something is running as well that blocks the 8545 port, or any other ports that you were using for geth. For me the problem was that Parity was installed in that machine as well, configured as starting automatically and was using exactly the same port.  

Wednesday, May 9, 2018

Solidity and Truffle Tips and Tricks - Compilation failed


If you have a solidity project that runs in one truffle environment but you get an error message in another installed truffle environment, like "Compilation failed", the problem might be that the truffle environment is not up-to-date. You can simply force a reinstall to make your truffle up-to-date. Like with the following command:  

npm install -g truffle