When the world's largest ICO was launched in June 2018 and frozen for two days due to a software bug, it made the cryptic community skeptical. Leaving him behind, four months later the EOS accounts have more transactions than Ethereum. Therefore, the promise of faster and free transactions, EOS has about 13,000 users active every day compared to Ethereum, which has only 2,000 in most Dapp.
An intelligent EOS security contract
It is clear that an intelligent contract has vulnerabilities that are applied to all platforms. Since we have Ethereum, smart contracts written on EOS require an audition before the steps are posted on the main network. Sometimes fatal mistakes in the deal can be exploited if the offers are not sufficiently tested in battle. With this guide, we're trying to help you avoid the most common pitfalls if you're working on the dApp on EOS.
Before starting to read, you need to know some preliminary information on the development of EOS. Some knowledge of C ++ is mandatory. You can start with the development of the intelligent contract of EOSIO documentation.
How to deal with the ABI Dispatcher
extern "C" {
void apply (uint64_t receiver, uint64_t code, uint64_t action) {
class_name thiscontract (receiver);
if ((code == N (eosio.token)) && (action == N (transfer))) {
execute_action (& thiscontract, & class_name :: transfer);
return;
}
if (code! = recipient) return;
switch (action) {EOSIO_API (class_name, (action_1) (action_n))};
eosio_exit (0);
}
}
The previous example is a code of a modified ABI dispatcher. Below is a simple ABI dispatcher used for a much simpler action in contract management.
EOSIO_ABI (class_name, (action_1) (action_n));
The ABI forwarding / dispatcher allows you to hear EOSIO coming soon. Transfer of tokens and even a regular interaction with the smart contract. To avoid abnormal and illegal calls it is essential to associate each key action and the code to meet all the requirements.
A perfect example is a hack that happened to dApp EOSBet Casino because of a bug when forwarding the source code in their ABI.
EOSIO_ABI (class_name, (action_1) (action_n));
The above check allowed an attacker in the apply action manager of the ABI forward source code to ignore the EOSIO token. So the duty to transfer completely then direct call contract :: transfer right without EOS to transfer to the contract. All this before even placing the bet. For the loss, he received nothing and also did not lose. Again for the winnings as paid with real EOS from the contract.
They solved the previous bug by adding an eosio control. Transfer action of the token contract. All this must happen before the incoming action request is sent to the contract.
Remember that it is very important to use the declaration require_auth (account); just for actions, you want the authorized account to run. require_auth (_self) this is to allow the contract owner to make the transaction.
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)
}
}
Remember that it is very important to use the declaration require_auth (account); just for actions, you want the authorized account to run. require_auth (_self) this is to allow the contract owner to make the transaction.
Authorization in shares
token void :: transfer (account name from, account_name to, amount of resource) { auto sym = quantity.symbol.name (); require_recipient (from); require_recipient (to); auto payer = has_auth (a)? to da; sub_balance (from, quantity); add_balance (to, quantity, payer); }
The sample code above allows anyone to call the action. To solve this problem use require_auth (from); a statement used to authorize the payer of the call to work.
Avoid modifying the EOSIO token contract
Recently a white hacker claimed a billion coins due to a weak method tested to call his own eosio. Token settlement. The inactive Dapp Seis said they arrived with a new method of eosin. Token contract By putting your own tokens in your user accounts. The good part is that the agreement did not call the problem or the transfer move of the eosio. Token contract
The interesting part, regarding the change and, therefore, the fund is magically returned to account users. The second thing, they forgot the verification of the quantity, in the previous method before the transfer. The moment when the hacker required about 1 billion tokens available in the process.
Moving from this, changing the token symbol and the maximum stock is indicated to avoid modifying it to do some custom functions, such as errors in the eosio.token, which can be a fatal contract. To serve a safe airdrop, transfer the airdrop counters to another account, then move it from there. Change the properties of the multi-index table
Now, EOS keeps data in a shared memory database to handle sharing through actions.
transfer void (symbol_name, account_name from, account_names to, uint64_t balance) { require_auth (from); account account; eosio_assert (is_balance_within_range (balance), "invalid balance"); eosio_assert (balance> 0, "must transfer the positive balance"); amount uint64_t = balance * 4; // Multiplying overflow }
The sample code above makes a multi_inde table named people who are well structured on a single row of that table, using only the person struct. At the moment EOS does not allow any type of modification of the characteristics of the table once implemented. The assertion eosio_assert_message is the error that is generated. So far, the properties must be thought immediately after the implementation of the table. Otherwise, you need to create a new table with a different name and take great care when migrating from a previous table to a new one. In the event of a failure to implement it, you may request a loss of data.
Verification of numerical overflow
During an arithmetic operation, sometimes the values may overflow if the boundary conditions are not properly controlled, causing loss of user resources.
transfer void (symbol_name, account_name from, account_names to, uint64_t balance) { require_auth (from); account account; eosio_assert (is_balance_within_range (balance), "invalid balance"); eosio_assert (balance> 0, "must transfer the positive balance"); amount uint64_t = balance * 4; // Multiplying overflow }
The sample code above, using uint64_t presenting the user's balance, can result in overflow when the value is multiplied. Therefore, avoid the use of uint64_t, then indicate the balances and perform arithmetic operations on it. Use the correct asset structure defined in eosiolib for any action, then that balance that is carrying overflowing conditions.
Some care for the hypotheses in the contract
In the process there will be assumptions that require assertions when a contract is executed. If you use eosio_assert you will take care of the conditions in advance and you will avoid any contention. For example:
void assert_roll_under (const uint8_t & roll_under) { eosio_assert (roll_under> = 2 && roll_under <= 96, "roll underflow, must be greater than 2 and less than 96"); }
The previous statement asserts that the whole number roll_under is better than 2 and less than 96. If the above coverage case is not discovered, it can turn into a small disaster for the house that sets the rules.
Creating real Random numbers
Generating real Random numbers for EOS Blockchain can be a real risk that is not perfect. If it is not done correctly it will turn into an opponent who predicts the results, setting the whole system in the process. There are services like Oracle.it existing to share random numbers from an external source.
However, they are very expansive and only have a single point of failure. Individuals used the contextual variables of the blockchain (bloc stamps, block numbers, etc.) in the previous days so that the random number could be created in the smart etereum contract. However, it has been played before. To build it properly, this program must provide a combination of randomness, which the non-party could control alone. For now, the best way is the one suggested by Dan Larimar:
string sha256_to_hex (const checksum256 & sha256) { returns a_hex ((char *) sha256.hash, sizeof (sha256.hash)); } string sha1_to_hex (const checksum160 & sha1) { return a_hex ((char *) sha1.hash, sizeof (sha1.hash)); } templateInline void hash_combine (std :: size_t and seed, const T & v) { std :: hash hasher; seed ^ = hasher (v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); }
The preceding code provides a generation of random numbers updated from 1 to 100. seed1 is the seed of the house and seed2 is the single seed above. If you need a reference check, EOSBetCasino and Dappub have an open sourced their complete contracts. They have managed to use a random number generator that implements a good dice game between the player and the home of origin (developer).
Unfortunately, EOSBet was again compromised only by 65,000 EOS when an opponent tricked their eosio. Token contract to send EOS to his contract all when a transaction was happening. However, the eosio.token contract code informs the sender and recipient of incoming tokens. So, to imitate this behavior and facilitate the hack, the hacker created two accounts, we can hire A & B. A, had a nice and smart contract with an action statement require_recipient (N ( eosbetdice11)).
When A helps the transaction from A to B using the action call, if it informs the transfer function from the contract. Similar to the case in which the call came from eosio. Token settlement. Since there is no real transfer of EOS in the contract, every time the hacker lost a bet, he fell like nothing. However, he received a reward when he won the opportunity. Again, it is not enough to check only the name of the action and the name of the contract.
Some checks in notifications from contracts
To verify the problem, the function must attenuate as long as the contract is actually, so the token recipient does not.
eosio_assert (transfer_data.from == _self || transfer_data.to == _self, "Must be an inbound or outbound transfer");
Are you thinking about some of the best practices while developing an intelligent contract on EOS?
Surely bugs are unavoidable for software. The consequences are amplified in a more decentralized environment, especially when it involves the value transaction. Far from these EOS guards the things above discuses. But here are some of the precautions and good practices that new smart contract developers need to keep in mind.
1 – Independent control of the contract from the third-party smart contract before releasing any mainnet.
2 – Perform the Caveman debugging (the only way to debug the contract) of the contract immediately before the testnet is released. A good point, EOSIO has a good documentation guide for this.
3 – Set your transfer rate at the time of withdrawal, in order to avoid excessive losses, when they are the first days of launch on the mainnet. Use a bounty bug program, perfect for disclosure by white hat hackers.
4 – Make sure you have a killwitch to block the contract when you notice a bug.
For implementation, we keep a flag in the multi_idex table. To set the flag, we use an action called only by the contract owner. So we check every public work if the flag is set to frozen or not. An example that you can find below.
struct st_frozen { uint64_t frozen; }; typedef singletontb_frozen; tb_frozen _frozen; uint64_t getFreezeFlag () { st_frozen frozen_st {.frozen = 0}; return _frozen.get_or_create (_self, frozen_st); } void setFreezeFlag (const uint64_t & pFrozen) { st_frozen frozen_st = getFreezeFlag (); frozen_st.frozen = pFrozen; _frozen.set (frozen_st, _self); } // Public Action void freeze () { require_auth (_self); setFreezeFlag (1); } // Public Action void unfreeze () { require_auth (_self); setFreezeFlag (0); } // any public action void action (...) { eosio_assert (getFreezeFlag (). frozen == 1, "Contract is frozen!"); ... }
5 – Stay up to date on security enhancements, vulnerabilities, or library disclosures on the platform. Be sure to update your libraries if necessary immediately.
6 – Open the contract code at least, in this way the fairness of the game is maintained and the indie developers can perceive the bugs more quickly.
Conclusion: EOS Smart Contract Security
With only five months since EOS was launched, it has grown more than expected. Changing intelligent contracts, trade-offs made, 21 knots of mining and many others, came with a lot of criticism from the minimalism of decentralization. However, it did not stop the dApp on Ethereum from switching to EOS because of the scalability that the platform shares today. Even if it is EOS or Ethereum that wins the war, it will see in the future. However, EOS has certainly won a battle and will remain so until Ethereum fails to achieve the scalability the world needs now.
For real-time business alerts and a daily distribution of encrypted markets, subscribe to Elite membership!
Disclaimer: this article should not be taken as, and is not intended to provide, investment advice. Global Coin Report and its affiliated companies, employees, writers and subcontractors are cryptocurrency investors and may from time to time have holdings in some of the coins or tokens they cover. Please conduct your own in-depth research before investing in any cryptocurrency and read our full disclaimer.
Image courtesy of Pixabay.
[ad_2]Source link