Tuesday, June 23, 2026
The BLOCKCHAIN Page
No Result
View All Result
  • Home
  • Cryptocurrency
  • Blockchain
  • Bitcoin
  • Market & Analysis
  • Altcoins
  • DeFi
  • Ethereum
  • Dogecoin
  • XRP
  • Regulations
  • NFTs
The BLOCKCHAIN Page
No Result
View All Result
Home Ethereum

Smart Contract Security | Ethereum Foundation Blog

by admin
December 20, 2023
in Ethereum
0
Dodging a bullet: Ethereum State Problems
0
SHARES
21
VIEWS
Share on FacebookShare on Twitter


Solidity was began in October 2014 when neither the Ethereum community nor the digital machine had any real-world testing, the gasoline prices at the moment have been even drastically totally different from what they’re now. Moreover, among the early design choices have been taken over from Serpent. Over the last couple of months, examples and patterns that have been initially thought-about best-practice have been uncovered to actuality and a few of them truly turned out to be anti-patterns. Because of that, we lately up to date among the Solidity documentation, however as most individuals in all probability don’t observe the stream of github commits to that repository, I wish to spotlight among the findings right here.

I cannot discuss in regards to the minor points right here, please learn up on them within the documentation.

Sending Ether

Sending Ether is meant to be one of many easiest issues in Solidity, but it surely seems to have some subtleties most individuals don’t realise.

It is necessary that at greatest, the recipient of the ether initiates the payout. The next is a BAD instance of an public sale contract:

// THIS IS A NEGATIVE EXAMPLE! DO NOT USE!
contract public sale {
  handle highestBidder;
  uint highestBid;
  operate bid() {
    if (msg.worth < highestBid) throw;
    if (highestBidder != 0)
      highestBidder.ship(highestBid); // refund earlier bidder
    highestBidder = msg.sender;
    highestBid = msg.worth;
  }
}

Due to the maximal stack depth of 1024 the brand new bidder can all the time improve the stack dimension to 1023 after which name bid() which is able to trigger the ship(highestBid) name to silently fail (i.e. the earlier bidder is not going to obtain the refund), however the brand new bidder will nonetheless be highest bidder. One option to examine whether or not ship was profitable is to examine its return worth:

/// THIS IS STILL A NEGATIVE EXAMPLE! DO NOT USE!
if (highestBidder != 0)
  if (!highestBidder.ship(highestBid))
    throw;

The

throw

assertion causes the present name to be reverted. This can be a dangerous thought, as a result of the recipient, e.g. by implementing the fallback operate as

operate() { throw; }

can all the time drive the Ether switch to fail and this could have the impact that no person can overbid her.

The one option to forestall each conditions is to transform the sending sample right into a withdrawing sample by giving the recipient management over the switch:

/// THIS IS STILL A NEGATIVE EXAMPLE! DO NOT USE!
contract public sale {
  handle highestBidder;
  uint highestBid;
  mapping(handle => uint) refunds;
  operate bid() {
    if (msg.worth < highestBid) throw;
    if (highestBidder != 0)
      refunds[highestBidder] += highestBid;
    highestBidder = msg.sender;
    highestBid = msg.worth;
  }
  operate withdrawRefund() {
    if (msg.sender.ship(refunds[msg.sender]))
      refunds[msg.sender] = 0;
  }
}
 

Why does it nonetheless say “destructive instance” above the contract? Due to gasoline mechanics, the contract is definitely effective, however it’s nonetheless not instance. The reason being that it’s unimaginable to stop code execution on the recipient as a part of a ship. Which means whereas the ship operate remains to be in progress, the recipient can name again into withdrawRefund. At that time, the refund quantity remains to be the identical and thus they’d get the quantity once more and so forth. On this particular instance, it doesn’t work, as a result of the recipient solely will get the gasoline stipend (2100 gasoline) and it’s unimaginable to carry out one other ship with this quantity of gasoline. The next code, although, is weak to this assault: msg.sender.name.worth(refunds[msg.sender])().

Having thought-about all this, the next code ought to be effective (after all it’s nonetheless not a whole instance of an public sale contract):

contract public sale {
  handle highestBidder;
  uint highestBid;
  mapping(handle => uint) refunds;
  operate bid() {
    if (msg.worth < highestBid) throw;
    if (highestBidder != 0)
      refunds[highestBidder] += highestBid;
    highestBidder = msg.sender;
    highestBid = msg.worth;
  }
  operate withdrawRefund() {
    uint refund = refunds[msg.sender];
    refunds[msg.sender] = 0;
    if (!msg.sender.ship(refund))
     refunds[msg.sender] = refund;
  }
}

Observe that we didn’t use throw on a failed ship as a result of we’re in a position to revert all state adjustments manually and never utilizing throw has rather a lot much less side-effects.

Utilizing Throw

The throw assertion is commonly fairly handy to revert any adjustments made to the state as a part of the decision (or entire transaction relying on how the operate is named). It’s a must to bear in mind, although, that it additionally causes all gasoline to be spent and is thus costly and can probably stall calls into the present operate. Due to that, I wish to advocate to make use of it solely within the following conditions:

1. Revert Ether switch to the present operate

If a operate just isn’t meant to obtain Ether or not within the present state or with the present arguments, you need to use throw to reject the Ether. Utilizing throw is the one option to reliably ship again Ether due to gasoline and stack depth points: The recipient may need an error within the fallback operate that takes an excessive amount of gasoline and thus can not obtain the Ether or the operate may need been referred to as in a malicious context with too excessive stack depth (even perhaps previous the calling operate).

Observe that by chance sending Ether to a contract just isn’t all the time a UX failure: You possibly can by no means predict by which order or at which era transactions are added to a block. If the contract is written to solely settle for the primary transaction, the Ether included within the different transactions needs to be rejected.

2. Revert results of referred to as capabilities

Should you name capabilities on different contracts, you possibly can by no means know the way they’re applied. Which means the consequences of those calls are additionally not know and thus the one option to revert these results is to make use of throw. After all you need to all the time write your contract to not name these capabilities within the first place, if you recognize you’ll have to revert the consequences, however there are some use-cases the place you solely know that after the very fact.

Loops and the Block Fuel Restrict

There’s a restrict of how a lot gasoline will be spent in a single block. This restrict is versatile, however it’s fairly arduous to extend it. Which means each single operate in your contract ought to keep under a certain quantity of gasoline in all (cheap) conditions. The next is a BAD instance of a voting contract:

/// THIS IS STILL A NEGATIVE EXAMPLE! DO NOT USE!
contract Voting {
  mapping(handle => uint) voteWeight;
  handle[] yesVotes;
  uint requiredWeight;
  handle beneficiary;
  uint quantity;
  operate voteYes() { yesVotes.push(msg.sender); }
  operate tallyVotes() {
    uint yesVotes;
    for (uint i = 0; i < yesVotes.size; ++i)
      yesVotes += voteWeight[yesVotes[i]];
    if (yesVotes > requiredWeight)
      beneficiary.ship(quantity);
  }
}

The contract truly has a number of points, however the one I wish to spotlight right here is the issue of the loop: Assume that vote weights are transferrable and splittable like tokens (consider the DAO tokens for instance). This implies you can create an arbitrary variety of clones of your self. Creating such clones will improve the size of the loop within the tallyVotes operate till it takes extra gasoline than is obtainable inside a single block.

This is applicable to something that makes use of loops, additionally the place loops aren’t explicitly seen within the contract, for instance while you copy arrays or strings inside storage. Once more, it’s effective to have arbitrary-length loops if the size of the loop is managed by the caller, for instance in case you iterate over an array that was handed as a operate argument. However by no means create a state of affairs the place the loop size is managed by a celebration that might not be the one one affected by its failure.

As a facet observe, this was one purpose why we now have the idea of blocked accounts contained in the DAO contract: Vote weight is counted on the level the place the vote is forged, to stop the truth that the loop will get caught, and if the vote weight wouldn’t be mounted till the top of the voting interval, you would forged a second vote by simply transferring your tokens after which voting once more.

Receiving Ether / the fallback operate

If you need your contract to obtain Ether by way of the common ship() name, you must make its fallback operate low-cost. It could solely use 2300, gasoline which neither permits any storage write nor operate calls that ship alongside Ether. Mainly the one factor you need to do contained in the fallback operate is log an occasion in order that exterior processes can react on the very fact. After all any operate of a contract can obtain ether and isn’t tied to that gasoline restriction. Capabilities truly need to reject Ether despatched to them if they don’t wish to obtain any, however we’re enthusiastic about probably inverting this behaviour in some future launch.



Source link

Tags: BlogcontractEthereumFoundationSecuritySmart
admin

admin

Recommended

53.7% of investors favor memecoins over Bitcoin, AMBCrypto’s exclusive report finds

53.7% of investors favor memecoins over Bitcoin, AMBCrypto’s exclusive report finds

2 years ago
Best Buy just cut the prices for dozens of Black Friday deals – I hand-picked 20+ early discounts live now

Best Buy just cut the prices for dozens of Black Friday deals – I hand-picked 20+ early discounts live now

7 months ago

Popular News

  • Protocol-Owned Liquidity: A Sustainable Path for DeFi

    Protocol-Owned Liquidity: A Sustainable Path for DeFi

    0 shares
    Share 0 Tweet 0
  • Cryptocurrency for College: Exploring DeFi Scholarship Models

    0 shares
    Share 0 Tweet 0
  • What are rebase tokens, and how do they work?

    0 shares
    Share 0 Tweet 0
  • What is Velodrome Finance (VELO): why it’s a next-gen AMM

    0 shares
    Share 0 Tweet 0
  • $10 XRP Price Envisioned By Fund Manager As Ripple Mounts Trillion-Dollar Payment Markets ⋆ ZyCrypto

    0 shares
    Share 0 Tweet 0

Latest

This 4TB Samsung external SSD is the last one you’ll ever need – and it’s 32% off

This 4TB Samsung external SSD is the last one you’ll ever need – and it’s 32% off

June 23, 2026
Best Buy Gaming Deals might be better than Amazon’s early Prime Day sale

Best Buy Gaming Deals might be better than Amazon’s early Prime Day sale

June 22, 2026

Categories

  • Altcoins
  • Bitcoin
  • Blockchain
  • Cryptocurrency
  • DeFi
  • Dogecoin
  • Ethereum
  • Market & Analysis
  • NFTs & Metaverse
  • Regulations
  • XRP

Follow us

Recommended

  • This 4TB Samsung external SSD is the last one you’ll ever need – and it’s 32% off
  • Best Buy Gaming Deals might be better than Amazon’s early Prime Day sale
  • Sony WH-1000XM6 vs. Sennheiser Momentum 5: I used both pairs for months, and here’s my pick
  • How I set up this $17 solar panel to give my doorbell camera unlimited battery life
  • I flew 2,700 miles with Apple, Sony, and Sennheiser headphones – this pair had the best audio
  • About us
  • Privacy Policy
  • Terms & Conditions

© 2023 TheBlockchainPage | All Rights Reserved

No Result
View All Result
  • Home
  • Cryptocurrency
  • Blockchain
  • Bitcoin
  • Market & Analysis
  • Altcoins
  • DeFi
  • Ethereum
  • Dogecoin
  • XRP
  • Regulations
  • NFTs

© 2023 TheBlockchainPage | All Rights Reserved