HackenProof Blog / Industry News / 3 ways how you can make your smart contract more secure

3 ways how you can make your smart contract more secure

Securing smart contracts is no easy task. This technology is relatively new and hence, we don’t yet have clear and widely acceptable best practices on how to build secure smart contracts. In this post, we will take a look at an example of a recent smart contract vulnerability and what can companies do to secure their smart contracts.

The story behind the eosbet.io vulnerability

Eosbet is an EOS gambling dapp (decentralized application), basically an online casino. On the 14th of September, eosbet.io has been hacked. An unknown hacker cracked eosbet’s smart contract and was able to place bets, without actually betting any of his funds.

In essence, this hacker could place bets without actually risking his funds. If he lost, the funds would stay in his wallet, if he won, he got all the winnings. In just a few hours he managed to “win” around $200K (here’s a link to his wallet).

Later that day, an EOS developer Tang Hongbo has written a post on Reddit describing the vulnerability and suggested fixes.

Eosbet has responded in comments and released an official statement explaining what has happened with their platform and how they have fixed the vulnerability

Technical description of the “EOSBet Transfer vulnerability”:

EOSBet uses ABI forwarder that helps to listen to contract interactions. A lot of other contracts are using the same ABI forwarder. After discovering this attack, they are in danger of the same vulnerability. This ABI forwards all actions if the calling contract is eosbetdice11(in our case) or eosio.token or if the action is an onerror coming from the eosio system contract.

 

// extend from EOSIO_ABI
#define EOSIO_ABI_EX( TYPE, MEMBERS )
extern “C” {
  void apply( uint64_t receiver, uint64_t code, uint64_t action ) {
     auto self = receiver;
     if( action == N(onerror)) {
        /* onerror is only valid if it is for the “eosio” code account and authorized by “eosio”‘s “active permission */
        eosio_assert(code == N(eosio), “onerror action’s are only valid from the \”eosio\” system account”);
     }
     if( code == self || code == N(eosio.token) || action == N(onerror) ) {
        TYPE thiscontract( self );
        switch( action ) {
           EOSIO_API( TYPE, MEMBERS )
        }
        /* does not allow destructor of this contract to run: eosio_exit(0); */ \
     }
  }}

 

The code below is vulnerable:

    if( code == self || code == N(eosio.token) || action == N(onerror) ) {

It doesn’t check whether transfer was from eosio.token, so attacker can call transfer directly from eosbetdice11, without transferring EOS to the contract. When he was losing bets, he didn’t lose money, but, when he was winning bets, he got all the prize.

Code was updated by the EOSBet team and below is the latest version:

// extend from EOSIO_ABI, because we need to listen to incoming eosio.token transfers
#define EOSIO_ABI_EX( TYPE, MEMBERS ) \
extern “C” { \
void apply( uint64_t receiver, uint64_t code, uint64_t action ) { \
auto self = receiver; \
if( code == self || code == N(eosio.token)) { \
if( action == N(transfer)){ \
eosio_assert( code == N(eosio.token), “Must transfer EOS”); \
} \
TYPE thiscontract( self ); \
switch( action ) { \
EOSIO_API( TYPE, MEMBERS ) \
} \
/* does not allow destructor of thiscontract to run: eosio_exit(0); */ \
} \
} \
}

They have deleted onerror part and added this code:

if( action == N(transfer)){ \
eosio_assert( code == N(eosio.token), “Must transfer EOS”); \
} \

It ensures that eosbetdice11 transfers are not allowed and only eosio.token can make transfers.

How can you make your smart contracts more secure:

You can never guarantee 100% security, but you can significantly reduce the risk of a security incident. Here’s our take on what companies can do, to ensure the security of their smart contracts:

  1. Implement a secure development process
    A company should identify the business and security requirements for their smart contracts (including technical specification). Moreover, a company should implement standardized testing procedures of their code. Having all the technical documentation in order will reduce the probability of a mistake being during the development process.
  2. Conduct two independent smart contract audits
    A security audit is a standard procedure, whereby a security specialist conducts a series of checks based on the known smart contract vulnerabilities. The second audit is required, as an additional layer of security as different security engineers will test a smart contract in a slightly different way.
  3. Host a public bug bounty on a smart contract
    Last but not least – companies should host public bug bounty programs. This allows companies to attract hundreds of researchers with various backgrounds. As time goes by, new vulnerabilities may arise. In order to mitigate this problem – companies should continuously test their products. Bug bounty programs are an efficient way to do that. Moreover, hosting bug bounty programs allows companies to make a public statement that they are serious about the security of their products

Please follow us on twitter and facebook to get the latest news on HackenProof.