sigmoid
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    1
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    All about Ethereum Gas === 요즘 주변 개발자들 사이에서 흔히 듣리는 소리는, "컨트렉트를 짰는데 제대로 동작하지 않아서 확인해 보니 Gas문제였다." 인 것 같다. 얼마전 facebook에는 EstimateGas만큼 Gas를 설정해서 트렌젝션을 보냈는데, negative gas가 발생하는 트렌젝션이여서 최종 사용량이 적게 계산된것이더라. 그래서 실제 실행시에는 gas limit을 넘어가는 순간이 발생하더라라는 흥미로운 이야기도 들었다. 사실 Gas의 사용량은, 계약의 코드가 소모하는 량 + OnChain state의 변화량이 함께 존재하는 개념이기 때문에, 정확하게 예측하기가 어렵다. 심지어 Web3에서 제공하는 함수이름도 EstimateGas 이지 않은가? 그래서 오늘은 이더리움의 Gas와 EVM 상의 처리 로직을 정리해보고 EsimateGas함수의 동작원리를 파악해보고자 이 글을 시작하였다. ## Gas가 뭐야? 이더리움의 내재가치는 당연히 Ether인데 왜 Gas라는 단어를 만들어 우리를 헷갈리게 할까? 이부분을 먼저 명확하게 이해하고 관리 로직을 들여다 보도록 하자. ### Ethereum에서 Gas의 역할 Ethreum Yellow paper기준으로 Gas는 이더리움 프로토콜상에서 다음의 역할을 부여받았다. 1. 이더리움의 가격 변동성에 대한 버퍼역할 2. 마이너에 대한 보상의 역할(Reward 말고 연산에 대한 Fee) 3. Dos등의 공격을 막는 역할 위의 역할중 1번이 이 글에서 가장 중요한 내용이다.(2번과 3번은 다루지 않는다) 먼저 위 개발자들이 말하는 가스비는 Gas Price와 Gas 사용량(Unit이라는 표현을 빌린다)의 조합이다. Gas Price는 Gas 1 unit당 이더리움 가격이다. Gas Unit은 Ethereum의 EVM operation에서 비용을 책정하는 고유의 단위이다. 그래서 opcode당 실제 비용은 Gast cost * unit/opcode가 된다. 이러한 비용구조는 Action을 생성하는 user가 unit당 Gas price를 조절함으로서 이더리움의 외부가격변동(원, 달러등)으로부터 자유로워 질수있는 기회를 준다. 만약 가스비로 천원을 내고 싶으면, 내 Action이 소모하게될 Gas unit의 수로 천원을 나누고, 유닛당 원화가격이 나오면, 해당 원화가격에 대응되는 Gas Price를 이더리움으로 입력하면 된다. 즉, 이더리움이 비싸지면 Gas price를 적게 적고, 이더리움이 싸지면 p높게 적어 내어서 최종 소비 금액을 천원에 맞출 수 있다 실제 트렌젝션을 생성하는 과정에서 우리는 Gas에 관련한 2개의 field인Gas Cost와 Gas Limit을 입력하게 되는데, Cost는 이더리움과 연결되고, Limit은 opcode가 소모하는 (최대)Unit수로 정의된다. 그래서 최종 지불하는 가스비는 Cost * Unit Limit으로 계산되는 것이다. ### 결국 Gas는 EVM상에서만 존재한다. 이더리움에서는 연산을 하는것도, State를 변경하는 것도 모두 EVM이다. 즉 가스를 소모하고 역할은 모두 EVM에서 한다. 나중에 나오겠지만, Refund할때는 이더리움으로 돌려줘야 하므로 남은 Gas 유닛수 * Gas Cost를 해서 변환된 가치를 돌려준다. ## Ethereum의 Gas 정책 ### 연산당 소모량 EVM은 op code를 실행하는 머신이며, 아래와 같이 op code를 실행할때 마다 Gas Unit을 소모하도록 설계가 되어있다. ![](https://i.imgur.com/LiiyW7x.png) (From: https://github.com/djrtwo/evm-opcode-gas-costs/blob/master/opcode-gas-costs_EIP-150_revision-1e18248_2017-04-12.csv) ### State 변화에 대한 비용과 Negative Gas 돈먹는 하마같으니라고, 메모리나 OnChain에 기록될 Storage를 읽고 쓰는데도 비용이 든다. M은 Memory, S는 Storage이다. 다들 그래서 최종 저장할때 말고는 Memory를 사용한다. ![](https://i.imgur.com/Vd9lYEM.png) Negative Gas가 재미있는 개념인데, 이더리움은 사용하지 않는 스토리지나 어카운트의 삭제를 장려하기 위해, Gas를 돌려주는 정책을 만들었다. 글의 시작부에 언급했던 Negative Gas 문제를 이해하는데 도움을 줄 것이다. * Deleting a contract (SELFDESTRUCT) is worth a refund of 24,000 gas. * Changing a storage address from a nonzero value to zero (SSTORE[x] = 0) is worth a refund of 15,000 gas. > 과연 어떤 문제가 발생하게 될까! ## Gas가 소비 되는 과정. ### Transaction Gas Limit vs. Block Gas Limit 이더리움 상에는 2개의 Gas Limit이 존재한다. 실제 Gas의 소비를 이해하기 위해 두 Gas Limit에 대해 간단히 짚고 넘어가야한다. 윗 챕터에서 트렌젝션을 생성하기 위해 입력하는 2개의 필드중 하나가 Gas Limit이라고 했는데, 이것의 정확한 명칭은 Transaction Gas Limit으로, 이 트렌젝션을 실행하는 과정에서 소모할 최대 unit수를 가리킨다. 이 유닛수를 넘어가면 실행할 opcode가 남아있더라도 EVM의 실행이 멈추게 될 것이다. 두번째 Block Gas Limit은 해당 블록내에서 트렌젝션들이 사용가능한 최대 Gas unit수이다. 즉, 앞선 트렌젝션에서 Block Gas Limit만큼의 unit을 사용했다면, 다른 트렌젝션은 실행 될 수 없다.(실제로 그런일은 발생하지 않는다. 트렌젝션이 블록에 포함되는 과정에서 이미 걸러지기 때문에) ### EVM의 Gas 사용방식 - Gas Pool Gas Pool은 블록의 state를 Processing할때 사용되는 개념이다. 어떤 블록을 처리할때(정확히는 블록내의 transaction을 처리) 사용가능한 가스를 관리하기 위한 pool로서, 블록 처리 시작전 생성되며 BlockGasLimit값으로 초기화된다 (중요!) 아래 함수 호출 구조를 보면, Gas Pool을 생성하고 블록 상의 트렌젝션을 실행하기 위해 매 트렌젝션마다 Gas Pool에서 Transaction Limit만큼 가스를 사고, 사둔 가스에서 opcode의 cost를 소모하는 것을 확인할 수있다. 이후 남은 가스나 환불 될 가스의 unit수는 Pool에 반환된다. ![](https://i.imgur.com/ZcUCMxP.png) 이러한 로직을 통해 트렌젝션이 실제 사용한 Gas unit량만을 고려하여 블록에 트렌젝션을 최대한 가득 채울 수 있게 된다. ### Estimate Gas의 동작방식 EstimateGas함수는 트렌젝션의 사용량을 예측하기 위해 사용하는 함수이다. 이 함수는 최소값을 21000유닛으로, 또 최대값을 현재 가장 최신의 블록(마이닝을 하고있을경우 마이닝되었지만 아직 canonical확정이 되지 않은 블록이 존재할수 있으므로, 최신 마이닝된 블록)의 Block Gas Limit으로 설정한 후 바이너리 서치를 통해 Contract호출시 transaction이 성공하는 경우의 Gas를 반환한다. ![](https://i.imgur.com/g7wkGIE.png) 실제로 Contract호출함수는 이렇게 생겼다 오류가 나지 않도록 임시 balance도 최대로 주고, 가스풀도 최대값으로 준다. ![](https://i.imgur.com/mkwhh6a.png) 이런 호출 방식이라면, Gas Pool을 설명했던 함수 호출 부분에서 이부분을 공통으로 사용하고 있음을 알수 있다. ![](https://i.imgur.com/AbrjTLr.png) 그렇다면 처리로직은 아래와 같이 요약 할 수 있다. 1. 바이너리 서치를 통해 입력한 가스 값만큼 가스풀에서 가스를 산다. 2. 트렌젝션을 실행해본다. 3. 실행결과를 확인한다. 1. halt가 나면 스테이트를 원상복원하고, 다른 입력을 넣는다. 2. 성공했다면 입력한 값을 리턴한다 (!) 이상하다. 실제 사용한 가스값을 리턴하는 거라면, negative gas를 고려하여 실제 peak상황보다 작은 값이 반환되겠지만, 코드 분석에 따르면 이미 산 가스를 가지고 실행이 되는지 안되는지를 검증해보고 해당 가스를 반환하기 때문에 문제가 되면 안된다! ## 다시 문제로 돌아가서. 그럼 언제 문제가 발생한 것일까? 예상되는 부분으로는 예측에 사용된 state가 실행 당시와 다를 경우다. 예측에 사용된 최신 블록의 다음 블록에 내 트렌잭션이 첫번째로 포함된다는 보장이 없기 때문에, 문제가 발생할수 있다. 또한 다음블록에 포함되더라도, 앞쪽의 트렌젝션이 내가 사용하는 state를 변경했을 경우에도, 문제가 발생가능하다. 마지막 Mining한 블록이 uncle블록으로 처리되었을 경우, 바로 다음 블록에 첫번째로 포함된다 하더라도 문제가 발생할수 있을것으로 예상한다. ## 마치며, 실제로 테스트를 해본것은 아니기 때문에, 100% 확신할 순 없지만 최소한 실제 사용된 gas를 리턴하는 것이 아니라, 입력한 GasLimit으로 트렌젝션이 동작하는지를 확인한 값을 리턴하는 로직으로 구현이 되어 있다는 것을 확인하였다. 다만, Estimate Gas로 예측한 가격은 마이닝 상태와, 블록에 포함되는 시간에 따라 언제든 무효해 질수 있다는 것을 확인하였기 때문에, 최초 언급된 제보는 분석이 틀렸을 확률이 높다는것만 확인하고, 글을 마무리 하기로 했다. > 잘못 분석된 내용이 있거나, 수정할 부분이 있다면 > alphabet@hotmail.co.kr로 언제든 연락부탁드립니다.

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully