<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>crypt0summer</title>
    <link>https://realapril.tistory.com/</link>
    <description>DEV</description>
    <language>ko</language>
    <pubDate>Thu, 13 Aug 2026 17:52:37 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>_April</managingEditor>
    <image>
      <title>crypt0summer</title>
      <url>https://tistory1.daumcdn.net/tistory/3011801/attach/32392d84a2da4e678f686e5053dab87a</url>
      <link>https://realapril.tistory.com</link>
    </image>
    <item>
      <title>You-Dont-Know-JS - 2</title>
      <link>https://realapril.tistory.com/124</link>
      <description>&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1. Get Started&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;1) What&amp;nbsp;Is&amp;nbsp;JavaScript?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Name&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;This language was originally designed to appeal to an audience of mostly Java programmers, and because the word &quot;script&quot; was popular at the time to refer to lightweight programs.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;So &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;the official name of the language specified by TC39(&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;the technical steering committee that manages JS&lt;/span&gt; ) and formalized by the ECMA standards body is&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;ECMAScript&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; T&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;he JavaScript/JS that runs in your browser or in Node.js, is&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;an&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;implementation of the ES2019 standard.&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-Language spec&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;The official standard as maintained by TC39 and ECMA.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Web and JS&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;How it should be : How JS is implemented for web browsers is, in all practicality, the only reality that matters.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;Reality: &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;Sometimes the JS engines will refuse to conform to a specification-dictated change because it would break that web content.&lt;br /&gt;&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;Solution: &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;Appendix B &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;details out any known mismatches between the official JS specification and the reality of JS on the web.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-Not all web JS&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Web API: alert(..) console.log(..)&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Node.js: fetch(..)&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;getCurrentLocation(..)&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;, and&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;getUserMedia(..)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-Not always JS&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;console/REPL &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;in your browser's Developer Tools &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;as a &quot;JS-friendly&quot; environment. It doesnt' &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;represent&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;exact&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;to-the-letter JS semantics&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;-multi-paradigm&amp;nbsp;language&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;Typical paradigm-level code categories include procedural, object-oriented (OO/classes), and functional (FP)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;JavaScript is most definitely a multi-paradigm language. You can write procedural, class-oriented, or FP-style code&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -backwards compatibility ( &lt;span style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot;&gt;이전 버전과 호환성유지)&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하위호환: &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;웹페이지는 브라우저의 자바스크립트 엔진으로 구동되기 때문에 아주 옛날의 웹페이지도 돌아가게 만들어야 했습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;상위호환: &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;예전의 브라우저들은 상위 버전의 자바스크립트에서 만든 웹페이지들을 구동시킬수 없습니다. 즉 상위 호환이 차단됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Gaps : jumping and filling&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;상위호환을 지원하지 않는 JS에서 이와 비슷한 (하위 버젼에서 돌려야 하는) 상황이 온다면 어떻게 해결해야 할까요? 이런 상황을 겪은 많은 개발자들이 다양한 해결책을 내놓았는데, 대표적으로는 Transpiling과 Polyfill이 있습니다. Transpiling은 작성한 코드를 변환해, Polyfill은 스펙을 비슷하게 구현해 코드에 추가해 구 버젼에서 신 스펙을 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -interpretation&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;scripted or interpreted languages : &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;'top-down', 'line-by-line'&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;compiled languages : Parsing + Compilation + Execution&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&amp;nbsp; &amp;gt;&amp;gt; &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;바이너리 파일로 만드는 과정 중 코드를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;파싱(Parsing)&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;해 추상 문법 트리 (Abstract Syntax Tree)로 변환하는 과정을 거칩니다. 아까 5번째 줄에 에러가 존재하는 상황이 컴파일 언어에 발생된다면, 파싱 과정에서 에러가 발생합니다.&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;JS: compiled lang because &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;JS source code is parsed(compiled) before it is executed.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Web assembly&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;JS's performance is remarkable, &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;it can be parsed/compiled quickly and compiled code can be executed fast.&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;An initial motivation for WASM was clearly the potential performance improvements. While that continues to be a focus, WASM is additionally motivated by the desire to bring more parity for non-JS languages to the web platform.&lt;/span&gt; &lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Strict mode&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Strict mode: &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;a guide to the best way to do things so that the JS engine has the best chance of optimizing and efficiently running the code.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2) Surveying&amp;nbsp;JS&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Each file is a program&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;In JS, each standalone file is its own separate program.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: -webkit-left;&quot;&gt;! Many projects use build process tools that end up combining separate files from the project into a single file to be delivered to a web page. When this happens, JS treats this single combined file as the entire program.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Values&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;a program is a value. Values are data. They're how the program maintains state. Values come in two forms in JS:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;primitive&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;object&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;6 primitives are: &amp;nbsp;literals,&amp;nbsp;booleans,&amp;nbsp;numbers(include&amp;nbsp;bigint),&amp;nbsp;null,&amp;nbsp;undefined,&amp;nbsp;symbol&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;interpolation :``&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;other&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;primitive&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;values in JS programs are&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;null&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;undefined. &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;However, it's safest and best to use only&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;undefined&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;as the single empty value, even though&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;null&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;seems attractive&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Arrays and Objects&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;arrays are a special type of object&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: -webkit-left;&quot;&gt;Functions, like arrays, are a special kind (aka, sub-type) of object.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;Objects are more general: an unordered, keyed collection of any various values.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Value type determination&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;coercion: &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;Converting from one value type to another, such as from string to number&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot; style=&quot;background-color: #f6f8fa; color: #1f2328; text-align: start;&quot;&gt;&lt;code&gt;typeof 42;                  // &quot;number&quot;
typeof &quot;abc&quot;;               // &quot;string&quot;
typeof true;                // &quot;boolean&quot;
typeof undefined;           // &quot;undefined&quot;
typeof null;                // &quot;object&quot; -- oops, bug!
typeof { &quot;a&quot;: 1 };          // &quot;object&quot;
typeof [1,2,3];             // &quot;object&quot;
typeof function hello(){};  // &quot;function&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Declaring&amp;nbsp;and&amp;nbsp;Using&amp;nbsp;Variables&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;var&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;/&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;let&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;/&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;const&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;let&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;allows a more limited access to the variable than&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;var&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;. This is called &quot;block scoping&quot; as opposed to regular or function scoping.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;const&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;. It's like&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;let&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;but has an additional limitation that it must be given a value at the moment it's declared, and cannot be re-assigned a different value later.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;It's ill-advised to use&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;const&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;with object values, because those values can still be changed even though the variable can't be re-assigned.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Functions&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;A procedure is a collection of statements that can be invoked one or more times, may be provided some inputs, and may give back one or more outputs.&lt;/span&gt; &lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;JS functions are a special type of the object value type.&lt;span&gt; It can be assigned and passed around.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Comparisions&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;=== &amp;gt; &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: -webkit-left;&quot;&gt;checking both the value and the type&lt;/span&gt; &lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;JS does not provide a mechanism for structural equality comparison of object values, only reference identity comparison.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; &lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Coercive&amp;nbsp;Comparisons&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;==&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;allows type conversions&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;first:&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&amp;nbsp;instead of&amp;nbsp; &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;loose equality it is called coercive comparisions&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Organization: Classes, Modules&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;A class in a program is a definition of a &quot;type&quot; of custom data structure that includes both data and behaviors that operate on that data. Classes define how such a data structure works, but classes are not themselves concrete values. To get a concrete value that you can use in the program, a class must be&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;instantiated&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;The module pattern has essentially the same goal as the class pattern, which is to group data and behavior together into logical units. Also like classes, modules can &quot;include&quot; or &quot;access&quot; the data and behaviors of other modules&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;I'd recommend sticking with&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;classic modules&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;instead of&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;class&lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3) Digging to the Roots of JS&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - Iteration&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - Closure&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - this keyword&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - Prototypes&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - Object&amp;nbsp;Linkage&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;4) The&amp;nbsp;Bigger&amp;nbsp;Picture&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Scope&amp;nbsp;and&amp;nbsp;Closure&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; -Prototypes&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #666666; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - 3 pillars&lt;/p&gt;</description>
      <category>dev/JS</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/124</guid>
      <comments>https://realapril.tistory.com/124#entry124comment</comments>
      <pubDate>Tue, 9 Jan 2024 17:42:40 +0900</pubDate>
    </item>
    <item>
      <title>You-Dont-Know-JS -1</title>
      <link>https://realapril.tistory.com/123</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed?tab=readme-ov-file&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed?tab=readme-ov-file&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1704788480404&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - getify/You-Dont-Know-JS: A book series on JavaScript. @YDKJS on twitter.&quot; data-og-description=&quot;A book series on JavaScript. @YDKJS on twitter. Contribute to getify/You-Dont-Know-JS development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed?tab=readme-ov-file&quot; data-og-url=&quot;https://github.com/getify/You-Dont-Know-JS&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/rdAe3/hyU2eoaWBf/8nxM5izBbXXPBXyDcagFSK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed?tab=readme-ov-file&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/getify/You-Dont-Know-JS/tree/2nd-ed?tab=readme-ov-file&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/rdAe3/hyU2eoaWBf/8nxM5izBbXXPBXyDcagFSK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - getify/You-Dont-Know-JS: A book series on JavaScript. @YDKJS on twitter.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A book series on JavaScript. @YDKJS on twitter. Contribute to getify/You-Dont-Know-JS development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;INDEX&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Get Started&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Scope&amp;nbsp;&amp;amp;&amp;nbsp;Closures&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Objects&amp;nbsp;&amp;amp;&amp;nbsp;Classes&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Types&amp;nbsp;&amp;amp;&amp;nbsp;Grammar&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Get Started&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;1) What&amp;nbsp;Is&amp;nbsp;JavaScript?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2) Surveying&amp;nbsp;JS&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;3) Digging&amp;nbsp;to&amp;nbsp;the&amp;nbsp;Roots&amp;nbsp;of&amp;nbsp;JS&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;4) The&amp;nbsp;Bigger&amp;nbsp;Picture&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2. Scope&amp;nbsp;&amp;amp;&amp;nbsp;Closures&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;1) What's&amp;nbsp;the&amp;nbsp;Scope?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2) Lexical&amp;nbsp;Scope&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;3) &amp;nbsp;The&amp;nbsp;Scope&amp;nbsp;Chain&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;4) Around&amp;nbsp;the&amp;nbsp;Global&amp;nbsp;Scope&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;5) The&amp;nbsp;(Not&amp;nbsp;So)&amp;nbsp;Secret&amp;nbsp;Lifecycle&amp;nbsp;of&amp;nbsp;Variables&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;6) Limiting&amp;nbsp;Scope&amp;nbsp;Exposure&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;7)&amp;nbsp;Using&amp;nbsp;Closures&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;8) The&amp;nbsp;Module&amp;nbsp;Pattern&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;Objects&amp;nbsp;&amp;amp;&amp;nbsp;Classes&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;1) Object&amp;nbsp;Foundations&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2) How&amp;nbsp;Objects&amp;nbsp;Work&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;3) Classy&amp;nbsp;Objects&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;4) This&amp;nbsp;Works&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;5) Delegation&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;4.&lt;span&gt;&amp;nbsp;&lt;/span&gt;Types&amp;nbsp;&amp;amp;&amp;nbsp;Grammar&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;1) Primitive Values&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2) Primitive&amp;nbsp;Behaviors&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;3) Object&amp;nbsp;Values&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;4) Coercing&amp;nbsp;Values&lt;/p&gt;</description>
      <category>dev/JS</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/123</guid>
      <comments>https://realapril.tistory.com/123#entry123comment</comments>
      <pubDate>Tue, 9 Jan 2024 17:21:31 +0900</pubDate>
    </item>
    <item>
      <title>Git 사용자이름/이메일 설정</title>
      <link>https://realapril.tistory.com/121</link>
      <description>&lt;h2 id=&quot;로컬에서-기본값으로-사용할-git-사용자-이름과-이메일-설정global-옵션&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;로컬에서 기본값으로 사용할 Git 사용자 이름과 이메일 설정(global 옵션)&lt;/h2&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;현재 시스템의 모든 Git 작업에 사용할 사용자 이름과 이메일을 설정하고자 한다면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;global옵션을 사용해&lt;span&gt;&amp;nbsp;&lt;/span&gt;git config&lt;span&gt;&amp;nbsp;&lt;/span&gt;명령어를 실행한다.&lt;/p&gt;
&lt;pre id=&quot;code_1687162721772&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ git config --global user.name &quot;Your Name&quot;
$ git config --global user.email you@example.com&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 설정되었는지 확인하는법&lt;/p&gt;
&lt;pre id=&quot;code_1687162762998&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ git config user.name
$ git config user.email&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;저장소-별로-git-사용자와-이메일-정보-설정하기&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;저장소 별로 Git 사용자와 이메일 정보 설정하기&lt;/h2&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;저장소 디렉터리에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;--global&lt;span&gt;&amp;nbsp;&lt;/span&gt;없이&lt;span&gt;&amp;nbsp;&lt;/span&gt;git config를 사용하면 해당 디렉터리(저장소) 전용 설정을 추가할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1687162801622&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ git config user.name &quot;realapril&quot;
$ git config user.email realapril25@gmail.com&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;global&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;옵션으로 설정한 정보보다 우선적으로 설정된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;git-사용자-이름과-이메일-정보-삭제하기&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Git 사용자 이름과 이메일 정보 삭제하기&lt;/h2&gt;
&lt;pre id=&quot;code_1687162848173&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 전역 설정을 삭제
$ git config --global --unset user.name
$ git config --global --unset user.email

# 개별 저장소의 설정을 삭제
$ git config --unset user.name
$ git config --unset user.email&lt;/code&gt;&lt;/pre&gt;</description>
      <category>dev</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/121</guid>
      <comments>https://realapril.tistory.com/121#entry121comment</comments>
      <pubDate>Mon, 19 Jun 2023 17:21:01 +0900</pubDate>
    </item>
    <item>
      <title>Zero-Knowledge Rollups(1) 배경</title>
      <link>https://realapril.tistory.com/120</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;탈중앙화와 보안이 장점인 이더리움에는 고질적인 문제가 있다. &lt;a href=&quot;https://ethereum.org/en/developers/docs/scaling/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;느리고 비싸다는 것이다.&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이 문제를 해결하기 위한 &quot;scaling solutions&quot; 가 여러가지 제시되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 3가지 방식인데, L1 scaling, L2 scaling, side chain 이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;L1 스케일링 경우에는 샤딩을 이용한 스케일링을 고려중이고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;L2 스케일링의 경우에는 Rollups 솔루션이라고 불리는데 &lt;a href=&quot;https://l2fees.info/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;가스비가 100배까지 싸질수 있다고&lt;/a&gt; 한다.&amp;nbsp; 별개의 네트워크에서 트랜젝션을 이루어지고, 이 트랜젝션들을 배치로 묶어서 이더리움체인(L1) 에서 검증받게 하는것이 요지이다. 검증법은 크게 두가지로 나뉜다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(레이어2란: 이더리움을 연장하지만 이더리움과는 분리된 블록체인으로, 이더리움의 보안을 계승한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;L2 스케일링의 경우 optimistic rollup 과 zk rollup 으로 나뉜다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Optimistic rollup&lt;/b&gt; 의 경우에는 일단 l2에서 이루어진 트랜젝션이 맞다고 가정하고, 검증자들이 &lt;b&gt;fraud proof&lt;/b&gt; 를 증명해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;그래서 생기는 단점이 있는데, fraud proof 를 제공할 시간을 줘야하는데 보통 1주일정도 준다. 즉 L2-&amp;gt;L1로 자산이 돌아오는데 일주일이 걸려버린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴리곤의 플라즈마체인도 fraud proof 를 쓴다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ZK rollup&lt;/b&gt; 의 경우에는 L2 에서 이루어진 배치가 L1 에 있는 컨트랙트를 통과해야한다. &lt;b&gt;validity proof&lt;/b&gt; 를 제출해서 이게 맞다고 인정받아야한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 이렇게하면 즉시(~12 seconds) L2-&amp;gt;L1 이동이 가능하나 대신 (1)개발난이도가 높고(아직 zk가 evm 에서 쓸수있게 만들고있는 상태) (2)이더리움 노드가 걸리는 연산 부하가 높다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 연산 부하쪽은 롤업에 따라 다르게 들긴하는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/7pWxCklcNsU?t=594&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이더리움이 초당 15~45개의 트렌젝션에서 최대 1000~4000 트젝을 처리할수 있어야 자유롭게 사용할수 있다.&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 이렇게까지 나오지 못하는 상태.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://merge.nansen.ai/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://merge.nansen.ai/&lt;/a&gt; 를 살펴봤더니 한 블록에 트젝수 최대 517개까지봤는데 TPS 니까 517/12= 43.. 최저 조건을 맞춘셈이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 이더리움 합의계층을 실행계층과 분리하여 만드는 이유이다(ETH2라는 명칭은 폐기됨)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 zk rollup 에서는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;zksnark(zkSync) 와 starknet(starkware) 가 투탑이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-12-02 at 4.13.06 PM.png&quot; data-origin-width=&quot;1133&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRkXwU/btrSF6ntiNG/iv0A3qC2pEUKGauaDAjcTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRkXwU/btrSF6ntiNG/iv0A3qC2pEUKGauaDAjcTK/img.png&quot; data-alt=&quot;https://ethereum.org/en/layer-2/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRkXwU/btrSF6ntiNG/iv0A3qC2pEUKGauaDAjcTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRkXwU%2FbtrSF6ntiNG%2Fiv0A3qC2pEUKGauaDAjcTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1133&quot; height=&quot;402&quot; data-filename=&quot;Screen Shot 2022-12-02 at 4.13.06 PM.png&quot; data-origin-width=&quot;1133&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://ethereum.org/en/layer-2/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공홈에나와있듯 성숙한 단계는아니다.&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/120</guid>
      <comments>https://realapril.tistory.com/120#entry120comment</comments>
      <pubDate>Thu, 1 Dec 2022 15:59:15 +0900</pubDate>
    </item>
    <item>
      <title>이더리움 스마트컨트랙트 스토리지 이해하기</title>
      <link>https://realapril.tistory.com/119</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://programtheblockchain.com/posts/2018/03/09/understanding-ethereum-smart-contract-storage/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://programtheblockchain.com/posts/2018/03/09/understanding-ethereum-smart-contract-storage/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;를 번역해보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이더리움 스마트컨트랙트는 독특한 스토리지 모델을 사용하고, 이는 뉴비 개발자들을 혼란시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 포스트에서는 스마트컨트랙트 스토리지 모델을 설명하고, 솔리디티 프로그래밍에서 어떻게 사용하는지를 설명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 1개의 천문학적으로 큰 어레이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 고정 크기값 위치하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 다이나믹 사이즈 값들 위치하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1)다이나믹 사이즈 어레이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2)매핑&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3)여러타입들의 조합&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 1개의 천문학적으로 큰 어레이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EVM 에서 작동하는 각각의 스마트컨트랙트는 각각의 영구적인 스토리지를 가진다. (storage hash)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스토리지는 하나의 거대한 어레이이며, 초기값은 0이라고 생각될수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어레이의 하나의 값은 32바이트 크기이며, 이러한 32바이트가 &lt;span style=&quot;background-color: #ffffff;&quot;&gt;2^256개 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;스마트 컨트랙트는 어떤위치의 값이라도 읽거나 쓸수있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;이게 스토리지 인터페이스의 범위이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1189&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Cva5Q/btrStz90uC4/usQjKflSjArdKyTCKYgrq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Cva5Q/btrStz90uC4/usQjKflSjArdKyTCKYgrq1/img.png&quot; data-alt=&quot;이런식의 거대한 하나의 어레이라고 상상해보자.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Cva5Q/btrStz90uC4/usQjKflSjArdKyTCKYgrq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCva5Q%2FbtrStz90uC4%2FusQjKflSjArdKyTCKYgrq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1189&quot; height=&quot;372&quot; data-origin-width=&quot;1189&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이런식의 거대한 하나의 어레이라고 상상해보자.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이더리움의 스토리지는 이렇게 생기지 않았지만, 이렇게 하나의 거대한 어레이라고 생각하는 편이 이해하기 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 스토리지는 극단적으로 희박하여 0까지 저장할 이유가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키/밸류 스토어 매핑으로 충분하다.(키,밸류 모두 32바이드 밸류) 키가 없는 경우에는 0값을 돌려주면 되기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0은 아무런 자리도 차지하지않아서, 값을 0으로 지정한다면 스토리지는 되돌려진다. 이게 스마트컨트랙트에서 &quot;가스 리펀&quot; 을 받는 경우이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 고정된 크기의 값 위치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스토리지 모델에서 값들은 어디로 가는가? 고정된 크기의 알려진 변수들은, 스토리지의 지정된 장소로 주면 된다. 솔리디티언어가 그걸한다.&lt;/p&gt;
&lt;pre id=&quot;code_1669778196999&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract StorageTest {
    uint256 a;
    uint256[2] b;

    struct Entry {
        uint256 id;
        uint256 value;
    }
    Entry c;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 코드가 있다고 치자.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;a는 슬랏 0 에 저장된다&lt;/li&gt;
&lt;li&gt;b는 슬랏 1, 2에 저장된다&lt;/li&gt;
&lt;li&gt;c는 슬랏 3,4에 저장된다. Entry 내에 32바이트 값이 두개 있기 때문이다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mMCtL/btrSrtWScl7/pub4NxiVZu97eCq73XB01K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mMCtL/btrSrtWScl7/pub4NxiVZu97eCq73XB01K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mMCtL/btrSrtWScl7/pub4NxiVZu97eCq73XB01K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmMCtL%2FbtrSrtWScl7%2Fpub4NxiVZu97eCq73XB01K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;580&quot; height=&quot;327&quot; data-origin-width=&quot;1028&quot; data-origin-height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 슬랏들은 컴파일될때 결정되고, 컨트랙트에 쓰여진 순서대로 할당된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 다이나믹 사이즈 값들 위치하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다이나믹사이즈 어레이와 매핑의 경우엔 몇개의 슬랏을 사용하게 될지 모르기때문에 선지정할수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;램이나 하드를 예시로 생각해보면, 빈 공간을 사용하기 위해 할당하는 단계와 사용중인 공간을 릴리즈하는 단계가 있을것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 스마트컨트랙트 스토리지경우엔 천문학적 규모때문에 그럴필요가없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스토리지에는 2^256 개의 위치가있는데, 이게 얼마나 큰 수냐면 관찰 가능한 우주의 원자의 수와 비슷할 정도다. 아무 위치를 랜덤으로 찍어도 충돌할 확률이 몹시 작다는 뜻이다. 심지어 이렇게 찍은 위치간에 멀리 떨어져있어서 다이나믹한 데이터를 얼마나 넣던 충돌할 가능성도 적다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 위치를 진짜로 랜덤으로 설정하지는 않는다. 이러면 나중에 데이터를 찾을수가 없기때문이다. 솔리디티는 해시 펑션을 이용해 다이나믹 사이즈의 값의 위치를 통일성있게, 반복적으로 정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;(1) 다이나믹 사이즈 어레이&lt;/h4&gt;
&lt;pre id=&quot;code_1669783368536&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract StorageTest {
    uint256 a;     // slot 0
    uint256[2] b;  // slots 1-2

    struct Entry {
        uint256 id;
        uint256 value;
    }
    Entry c;       // slots 3-4
    Entry[] d;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다이나믹 사이즈 어레이 d는 5번째 슬롯에 저장되지만, 정확히 5번째 슬롯에는 d의 크기만 저장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어레이의 값은 슬롯의 해시 (hash(5)) 슬롯부터 순서대로 저장된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;509&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvTjVs/btrSsRcuas2/bqKSFEXQm9zMKN1ysTk6mk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvTjVs/btrSsRcuas2/bqKSFEXQm9zMKN1ysTk6mk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvTjVs/btrSsRcuas2/bqKSFEXQm9zMKN1ysTk6mk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvTjVs%2FbtrSsRcuas2%2FbqKSFEXQm9zMKN1ysTk6mk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;996&quot; height=&quot;509&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;509&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔리디티에서는 다음과 같이 위치를찾는다&lt;/p&gt;
&lt;pre id=&quot;code_1669785424953&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function arrLocation(uint256 slot, uint256 index, uint256 elementSize)
    public
    pure
    returns (uint256)
{
    return uint256(keccak256(slot)) + (index * elementSize);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;(2) Mappings&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매핑은 주어진 키에 대응하는 위치를 찾을 효율적인 방법을 요구한다. 키를 해싱하는것은 좋은 시작이지만, 다른 매핑이 다른 위치를 생성하도록 신경써야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1669784475497&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract StorageTest {
    uint256 a;     // slot 0
    uint256[2] b;  // slots 1-2

    struct Entry {
        uint256 id;
        uint256 value;
    }
    Entry c;       // slots 3-4
    Entry[] d;     // slot 5 for length, keccak256(5)+ for data

    mapping(uint256 =&amp;gt; uint256) e;
    mapping(uint256 =&amp;gt; uint256) f;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;e 슬롯의 위치는 6, f슬롯의 위치는 7이다. 그러나 6,7에 실제 데이터가 저장되지않는다. 이번엔 저장될 길이도 없고, 각개 데이터는 다른 어딘가에 저장되어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매핑의 경우에는 키와 매핑의 슬롯이 함께 해시된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1336&quot; data-origin-height=&quot;476&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqYhCz/btrSvAnNFlZ/ZXke4vK3JQe9jao9jEbSS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqYhCz/btrSvAnNFlZ/ZXke4vK3JQe9jao9jEbSS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqYhCz/btrSvAnNFlZ/ZXke4vK3JQe9jao9jEbSS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqYhCz%2FbtrSvAnNFlZ%2FZXke4vK3JQe9jao9jEbSS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1336&quot; height=&quot;476&quot; data-origin-width=&quot;1336&quot; data-origin-height=&quot;476&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매핑의 위치와 키가 함께 해싱되기때문에 충돌을 방지할수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔리디티에서는 다음과 같이 위치를찾는다.&lt;/p&gt;
&lt;pre id=&quot;code_1669785405424&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function mapLocation(uint256 slot, uint256 key) public pure returns (uint256) {
    return uint256(keccak256(key, slot));
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;(3) 복잡한 타입들의 컴비네이션&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다이나믹사이즈 어레이와 매핑은 서로 재귀적 중첩이 가능하다. 이게 발생하면 위의 계산이 재귀적으로 발생한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1669785325508&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract StorageTest {
    uint256 a;     // slot 0
    uint256[2] b;  // slots 1-2

    struct Entry {
        uint256 id;
        uint256 value;
    }
    Entry c;       // slots 3-4
    Entry[] d;     // slot 5 for length, keccak256(5)+ for data

    mapping(uint256 =&amp;gt; uint256) e;    // slot 6, data at h(k . 6)
    mapping(uint256 =&amp;gt; uint256) f;    // slot 7, data at h(k . 7)

    mapping(uint256 =&amp;gt; uint256[]) g;  // slot 8
    mapping(uint256 =&amp;gt; uint256)[] h;  // slot 9
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런게있으면 g[123][0]을 찾고자하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;g[123]을 먼저 찾고 -&amp;gt; g의 슬롯인 8과 키값으로 위치를 찾는다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 arr[0]을 찾게된다. -&amp;gt; g[123]값을 해싱하면 첫 위치가 나온다. g[123]에는 어레이의 길이가 들어있으므로 길이만큼 값을 가져오면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;h[2][456]을 찾고자하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;h[2] 는 슬롯9번을 해싱한 위치에 있고, 그중 2번째인 값을 가져온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-각 스마트컨트랙트는 2^256개의- 한 슬랏은 32바이트가 들어가는- 형태의 어레이이며 모두 0으로 초기화된 셈이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-0은 명시적으로 저장되어있지않으므로 값을 0으로 세팅하는것은 그 스토리지를 요구하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-솔리디티는 고정된 사이즈의 값을 &quot;슬롯&quot;이라는 지정된위치에 지정시킨다. 이 슬랏은 0부터 시작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-솔리디티는 다이나믹 사이즈 값들을 균일하고 안전히 저장하기 위해 해시 결과값을 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/119</guid>
      <comments>https://realapril.tistory.com/119#entry119comment</comments>
      <pubDate>Wed, 30 Nov 2022 15:55:05 +0900</pubDate>
    </item>
    <item>
      <title>calling another contract : interface vs call vs delegate call</title>
      <link>https://realapril.tistory.com/118</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;솔리디티 컨트랙트에서 다른 컨트랙트를 부르는방식은 여러가지가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;interface, call, delegate call 에 대해 살펴보자. (static call은 일단 제외)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 코드상(사용방법상) 차이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 소모되는 가스 unit 차이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) Low / High level function&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4) 최종 컨트랙트의 msg. sender, 데이터 저장위치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(packing, unpacking 때문에 한가지 contract 사용보단 무조건 비쌈)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 세가지에 대해 정리, 테스트해본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1 코드상(사용방법상) 차이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(0) 불릴 코드 (Callee)&lt;/p&gt;
&lt;pre id=&quot;code_1661501094977&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

contract Callee {
    uint public value1;
    uint public value2;

    struct template {
        uint256 tCount;
        uint256 tValue;
    }

    mapping(uint256 =&amp;gt; template) templateList;

    function setV1(uint _value1) external returns (uint) {
        value1 = _value1;
        return value1;
    }

    function setV1andV2(uint _value1, uint _value2) external payable returns (uint, uint) {
        value1 = _value1;
        value2 = _value2;

        return (value1, value2);
    }

    function setTemplate(uint256 idx , template memory _template) external returns (bool) {
        templateList[idx] = _template;
        return true;
    }

    function setTemplateForJS(uint256 idx , uint256 _val1, uint256 _val2) external returns (bool) {
        template memory _template = template({
            tCount: _val1,
            tValue: _val2
        });
        templateList[idx] = _template;
        return true;
    }

    function getTemplate(uint256 idx) external view returns (template memory) {
        return templateList[idx];
    }

    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 컨트랙트에서 불릴수도있고, js 에서도 바로 불릴수 있는 코드이다(setTemplateForJS)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) interface&lt;/p&gt;
&lt;pre id=&quot;code_1661501140398&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// contracts/Box.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
import &quot;hardhat/console.sol&quot;;

interface ICallee {
    struct template {
        uint256 tCount;
        uint256 tValue;
    }

    function setV1(uint256 _value1) external returns (uint256);

    function setV1andV2(uint256 _value1, uint256 _value2)
        external
        payable
        returns (uint256, uint256);

    function setTemplate(uint256 idx, template memory _template)
        external
        returns (bool);

    function getTemplate(uint256 idx) external view returns (template memory);
}

contract Caller_interface {
    address internal _calleeAddr;

    constructor(address _calleeAddr_) {
        _calleeAddr = _calleeAddr_;
    }

    function setV1(uint256 _v1) public {
        uint256 x = ICallee(_calleeAddr).setV1(_v1);
        console.log(&quot;setV1: %s&quot;, x);
    }

    function setV1andV2(uint256 _v1, uint256 _v2) public {
        (uint256 x, uint256 y) = ICallee(_calleeAddr).setV1andV2(_v1, _v2);
        console.log(&quot;setV1andV2: %s, %s&quot;, x, y);
    }

    function setTemplate(
        uint256 idx,
        uint256 _val1,
        uint256 _val2
    ) public {
        ICallee.template memory temp = ICallee.template({
            tCount: _val1,
            tValue: _val2
        });
        bool x = ICallee(_calleeAddr).setTemplate(idx, temp);
    }


    function getTemplate(uint256 _idx) public {
        ICallee.template memory temp = ICallee(_calleeAddr).getTemplate(_idx);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스로 부를수있는 코드이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) call&lt;/p&gt;
&lt;pre id=&quot;code_1661504943161&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
import &quot;hardhat/console.sol&quot;;

contract Caller_call {
    address internal _calleeAddr;

    constructor(address _calleeAddr_) {
        _calleeAddr = _calleeAddr_;
    }

    function setV1(uint256 _v1) public {
        (bool success, bytes memory result) = _calleeAddr.call(
            abi.encodeWithSignature(&quot;setV1(uint256)&quot;, _v1)
        );
        if(success){
            uint x = abi.decode(result, (uint));
            console.log(&quot;setV1: %s&quot;, x);
        }
    }

    function setV1andV2(uint256 _v1, uint256 _v2) public {
        (bool success, bytes memory result) = _calleeAddr.call(
            abi.encodeWithSignature(&quot;setV1andV2(uint256,uint256)&quot;, _v1, _v2)
        );
        (uint256 x, uint256 y) = abi.decode(result, (uint256, uint256));
        console.log(&quot;setV1andV2: %s, %s&quot;, x, y);
    }

    function setTemplate(
        uint256 idx,
        uint256 _val1,
        uint256 _val2
    ) public {
        
        (bool success, bytes memory result) = _calleeAddr.call(
            abi.encodeWithSignature(&quot;setTemplate(uint256,(uint256,uint256))&quot;,idx,  _val1, _val2)
        );
        console.logBytes(result);
    }


    function getTemplate(uint256 _idx) public {
     

        (bool success, bytes memory result) = _calleeAddr.call(
            abi.encodeWithSignature(&quot;getTemplate(uint256)&quot;,_idx)
        );
        console.logBytes(result);

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3) delegate call&lt;/p&gt;
&lt;pre id=&quot;code_1661504955670&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
import &quot;hardhat/console.sol&quot;;

contract Caller_delegateCall {
    address internal _calleeAddr;

    constructor(address _calleeAddr_) {
        _calleeAddr = _calleeAddr_;
    }

    function setV1(uint256 _v1) public {
        (bool success, bytes memory result) = _calleeAddr.delegatecall(
            abi.encodeWithSignature(&quot;setV1(uint256)&quot;, _v1)
        );
        if(success){
            uint x = abi.decode(result, (uint));
            console.log(&quot;setV1: %s&quot;, x);
        }
    }

    function setV1andV2(uint256 _v1, uint256 _v2) public {
        (bool success, bytes memory result) = _calleeAddr.delegatecall(
            abi.encodeWithSignature(&quot;setV1andV2(uint256,uint256)&quot;, _v1, _v2)
        );
        (uint256 x, uint256 y) = abi.decode(result, (uint256, uint256));
        console.log(&quot;setV1andV2: %s, %s&quot;, x, y);
    }

    function setTemplate(
        uint256 idx,
        uint256 _val1,
        uint256 _val2
    ) public {
        
        (bool success, bytes memory result) = _calleeAddr.delegatecall(
            abi.encodeWithSignature(&quot;setTemplate(uint256,(uint256,uint256))&quot;,idx,  _val1, _val2)
        );
        console.logBytes(result);
    }


    function getTemplate(uint256 _idx) public {
     

        (bool success, bytes memory result) = _calleeAddr.delegatecall(
            abi.encodeWithSignature(&quot;getTemplate(uint256)&quot;,_idx)
        );
        console.logBytes(result);

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2 가스비 차이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸알기 위해 이 모든 테스트를 시작했다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 다음과 같다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-08-26 at 6.09.57 PM.png&quot; data-origin-width=&quot;841&quot; data-origin-height=&quot;666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9Uf1l/btrKGO1rgbl/LKLhriZNPfZ67M1bAKcwo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9Uf1l/btrKGO1rgbl/LKLhriZNPfZ67M1bAKcwo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9Uf1l/btrKGO1rgbl/LKLhriZNPfZ67M1bAKcwo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9Uf1l%2FbtrKGO1rgbl%2FLKLhriZNPfZ67M1bAKcwo0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;841&quot; height=&quot;666&quot; data-filename=&quot;Screen Shot 2022-08-26 at 6.09.57 PM.png&quot; data-origin-width=&quot;841&quot; data-origin-height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Callee 에서 직접 js 로 부르기 &amp;lt;&amp;lt;&amp;lt;&amp;lt; Interface &amp;lt;&amp;lt; delegate call &amp;lt; call&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의외로 인터페이스로 부르는게 제일 효율적이었다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;i&gt;다음엔.. 꼭 이더리움 황서 읽는법을 익혀서 계산하고싶다.. 전수 테스트 말고&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 call, delegate call은 왜 존재하고 차이가 뭐길래 가스비가 차이가 나는걸까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 좋은점이 있어서 비싼것일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3 Low / High level function&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;call 과 delegate call 은 Low level function 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1)로우레벨 펑션이 뭐가 좋냐면 컨트랙트의 펑션을 dynamic하게 발동할수 있게한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 자바의 reflection 과 비슷한데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바의 reflection 이란 구체적인 클래스 타입을 알지 못해도 그 클래스의 메소드, 타입, 변수들에 접근할 수 있도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 코딩에서는 필요없지만 &lt;a href=&quot;https://medium.com/upstate-interactive/solidity-how-to-know-when-to-use-abstract-contracts-vs-interfaces-874cab860c56&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;나중에 패턴을 도입하면 필요할수 있다.&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 와닿는지 않는다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2) Low 는 실패시 무조건 revert 시키지 않고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성공결과가 bool 로 리턴된다. false를 리턴받으면 실패인것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 false 를 받았을때 재시도하기 등의 여러 작업을 해볼수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4 최종 컨트랙트의 msg. sender, 데이터 저장위치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;call, interface를 통한 호출의 경우에는 callee 를 부른 주소가 (msg.sender)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 &lt;span&gt;delegate call&lt;span&gt; 의 경우에는 callee를 부른주소가 최초의 eoa 이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;Callee.sol 에 로그 추가해주고 각 caller의 setV1 에도 로그를 찍는다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1661740000479&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function setV1(uint256 _value1) external returns (uint256) {
        console.log('callee address: %s', msg.sender);
        
        value1 = _value1;
        return value1;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;이제 로그를 찍어보면&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-08-29 at 11.17.03 AM.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;71&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bX8JKh/btrKK9rv1U1/2MPtiBxPI2xlpZcNvBb5ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bX8JKh/btrKK9rv1U1/2MPtiBxPI2xlpZcNvBb5ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bX8JKh/btrKK9rv1U1/2MPtiBxPI2xlpZcNvBb5ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbX8JKh%2FbtrKK9rv1U1%2F2MPtiBxPI2xlpZcNvBb5ik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;467&quot; height=&quot;71&quot; data-filename=&quot;Screen Shot 2022-08-29 at 11.17.03 AM.png&quot; data-origin-width=&quot;467&quot; data-origin-height=&quot;71&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-08-29 at 11.16.54 AM.png&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;72&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ELFld/btrKHU9CgVK/Wk0kyXCZGhN5DIW547bcr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ELFld/btrKHU9CgVK/Wk0kyXCZGhN5DIW547bcr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ELFld/btrKHU9CgVK/Wk0kyXCZGhN5DIW547bcr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FELFld%2FbtrKHU9CgVK%2FWk0kyXCZGhN5DIW547bcr0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;416&quot; height=&quot;72&quot; data-filename=&quot;Screen Shot 2022-08-29 at 11.16.54 AM.png&quot; data-origin-width=&quot;416&quot; data-origin-height=&quot;72&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-08-29 at 11.16.48 AM.png&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;64&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mZ3Jh/btrKOg4Mr3O/9AdVf6czurO3I5aCL4mjJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mZ3Jh/btrKOg4Mr3O/9AdVf6czurO3I5aCL4mjJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mZ3Jh/btrKOg4Mr3O/9AdVf6czurO3I5aCL4mjJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmZ3Jh%2FbtrKOg4Mr3O%2F9AdVf6czurO3I5aCL4mjJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;445&quot; height=&quot;64&quot; data-filename=&quot;Screen Shot 2022-08-29 at 11.16.48 AM.png&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;64&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0xf39fd... 가 EOA 다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맨처음 delegatecall의 경우 EOA 가 최종 컬리와 딜리게이트콜 컨트랙트를 모두 부름을 알수있다.&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;call, interface 의 경우 배포된 주소(CA)로 callee address를 부르게된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;99A41F465B06EC060F.png&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;434&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xk6TR/btrKOI1axAf/viUPgDNTGYc4G9IeqOgJdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xk6TR/btrKOI1axAf/viUPgDNTGYc4G9IeqOgJdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xk6TR/btrKOI1axAf/viUPgDNTGYc4G9IeqOgJdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxk6TR%2FbtrKOI1axAf%2FviUPgDNTGYc4G9IeqOgJdk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;758&quot; height=&quot;434&quot; data-filename=&quot;99A41F465B06EC060F.png&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;434&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;&lt;span&gt;저장위치&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;delegate call 이용시 데이터는 Caller_delegateCall.sol 에 저장되고 Callee.sol 은 함수만 제공한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;-&amp;gt; 이걸 upgradeble smart contract 라고함&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/118</guid>
      <comments>https://realapril.tistory.com/118#entry118comment</comments>
      <pubDate>Mon, 29 Aug 2022 11:45:08 +0900</pubDate>
    </item>
    <item>
      <title>solidity 에러 - stack too deep</title>
      <link>https://realapril.tistory.com/117</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;여러 기능을 넣는데 갑자기 이런 에러가 떴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&quot;CompilerError:&amp;nbsp;Stack&amp;nbsp;too&amp;nbsp;deep.&amp;nbsp;Try&amp;nbsp;compiling&amp;nbsp;with&amp;nbsp;`--via-ir`&amp;nbsp;(cli)&amp;nbsp;or&amp;nbsp;the&amp;nbsp;equivalent&amp;nbsp;`viaIR:&amp;nbsp;true`&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;... Otherwise,&amp;nbsp;try&amp;nbsp;removing&amp;nbsp;local&amp;nbsp;variables.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 다들 겪는 일이었다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고통은 나누면 반이된다,,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1830&quot; data-origin-height=&quot;1014&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnZmLS/btrKq5o8Pc0/HpLK87opC1QEcA64OJkoM0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnZmLS/btrKq5o8Pc0/HpLK87opC1QEcA64OJkoM0/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnZmLS/btrKq5o8Pc0/HpLK87opC1QEcA64OJkoM0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnZmLS%2FbtrKq5o8Pc0%2FHpLK87opC1QEcA64OJkoM0%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1830&quot; height=&quot;1014&quot; data-origin-width=&quot;1830&quot; data-origin-height=&quot;1014&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;에러의 이유&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EVM 스택에는 16 variable 밖에 못올라간다. 이 variable 은 &lt;span style=&quot;background-color: #f9f9f9; color: #3c3e3e;&quot;&gt;input and output arguments &lt;/span&gt;&lt;span style=&quot;color: #3c3e3e;&quot;&gt;모두를 포함한다&lt;/span&gt;-&amp;gt; 너무나 황당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확히는 16슬랏이긴한데, 보통 1슬랏 1 variable 쓰니까....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 취향껏 고쳐보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해결법&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. variable 갯수 줄이기 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. internal function 쓰기 ( 실행 다 되면 메모리가 해제되니까 ㅇㅇ )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. block scoping&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. struct 활용하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들면 이런 문제코드가 있다. 이 코드를 1~4번방식으로 고쳐보자.&lt;/p&gt;
&lt;pre id=&quot;code_1661309859041&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract StackTooDeepTest {
    function addUints(
        uint256 a,uint256 b,uint256 c,uint256 d,uint256 e,uint256 f,uint256 g,uint256 h,uint256 i
    ) external pure returns(uint256) {
        
        return a+b+c+d+e+f+g+h+i;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러나는이유: 로컬변수가 너무많아서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;-&amp;gt; 여기 이해가안감 로컬변수 a~i 까지 9개에 리턴시 1개 추가 해서 10개아닌가? &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;return 내의 객체가 하나씩 다르게 잡혀서 18개로 잡히나?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 이경우 variable 갯수를 더 줄일수 없다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. &lt;span&gt;internal function 쓰기&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1661313830897&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract StackTooDeepTest {
   function addUints(
        uint256 a,uint256 b,uint256 c,uint256 d,uint256 e,uint256 f,uint256 g,uint256 h,uint256 i
    ) external pure returns(uint256) {
        
        return _addThreeUints(a,b,c) + _addThreeUints(d,e,f) + _addThreeUints(g,h,i);
    }
    
    function _addThreeUints(uint256 a, uint256 b, uint256 c) private pure returns(uint256) {
        return a+b+c;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 더하는 함수를 새로 만들면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a~i까지 9개에 리턴에 로컬변수 3개로 잡혀서 총 12개로 잡히는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기능따라 펑션을 분리하는 것은 좋은 습관이므로 좋은 코딩법에도 기여한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. block scoping&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;uniswap 에서 쓴방법&lt;/p&gt;
&lt;pre id=&quot;code_1661313976385&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract StackTooDeepTest {
    function addUints(
        uint256 a,uint256 b,uint256 c,uint256 d,uint256 e,uint256 f,uint256 g,uint256 h,uint256 i
    ) external pure returns(uint256) {
        
        uint256 result = 0;
        
        {
            result = a+b+c+d+e;
        }
        
        {
            result = result+f+g+h+i;
        }

        return result;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;js 의 block scoping 과 같아보인다.&lt;/p&gt;
&lt;div id=&quot;exacc_-qMFY_WnEtHP2roPm-iRiAQ5&quot; data-ved=&quot;2ahUKEwj1jOiKzd75AhXRp1YBHRt0BEEQ7NUEegQIKRAD&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;_-qMFY_WnEtHP2roPm-iRiAQ37&quot; data-hveid=&quot;CCkQBA&quot; data-ved=&quot;2ahUKEwj1jOiKzd75AhXRp1YBHRt0BEEQu04oAHoECCkQBA&quot;&gt;
&lt;div id=&quot;-qMFY_WnEtHP2roPm-iRiAQ__27&quot;&gt;
&lt;div data-md=&quot;61&quot;&gt;
&lt;div data-attrid=&quot;wa:/description&quot; data-hveid=&quot;CCEQAA&quot;&gt;&lt;span&gt;&lt;span&gt;Block scoped variables: A block scoped variable means that&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;the variable defined within a block will not be accessible from outside the block&lt;/b&gt;. A block can reside inside a function, and a block scoped variable will not be available outside the block even if the block is inside a function.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 처음 로컬변수 9개&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;result 까지 10개&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;result = a+b+c+d+e; 때 총 15개&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째 block scope 가 끝나면 다시 10개&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째 block scope 안에서 14개&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째 scope 끝나면 다시 10개...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 관리가 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수로 분리하기 애매할때 사용하면 좋아보임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. Use Structs&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 쓰자 객체&lt;/p&gt;
&lt;pre id=&quot;code_1661314585748&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract StackTooDeepTest {
    struct UintPair {
        uint256 value1;
        uint256 value2;
    }
    
    function addUints(
        UintPair memory a, UintPair memory b, UintPair memory c, UintPair memory d, uint256 e
    ) external pure returns(uint256) {
        
        return a.value1+a.value2+b.value1+b.value2+c.value1+c.value2+d.value1+d.value2+e;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a~i 까지 변수 9개가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수 a~e 5개로 줄었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 작동한다는 것은 return 때도 객체가 struct 채로 메모리가 할당됨을 알수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 평화롭게끝나면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔리디티가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아니지&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;671&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEGfoD/btrKuIfycjV/4ngrPx85N0ACQkgufkaLO1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEGfoD/btrKuIfycjV/4ngrPx85N0ACQkgufkaLO1/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEGfoD/btrKuIfycjV/4ngrPx85N0ACQkgufkaLO1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEGfoD%2FbtrKuIfycjV%2F4ngrPx85N0ACQkgufkaLO1%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;671&quot; height=&quot;372&quot; data-origin-width=&quot;671&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 16 slot 변수까지 된다면..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런코드도 되어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1661317440857&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract TestStackError {

  event LogValue(uint);

  function logArg(
    uint a1, uint a2, uint a3, uint a4,
    uint a5, uint a6, uint a7, uint a8,
    uint a9, uint a10, uint a11, uint a12,
    uint a13, uint a14, uint a15, uint a16
  ) public {
    emit LogValue(a16);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인풋 아규먼트가 16개잖아&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;되야맞다 ㅇㅇ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 결과는?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-08-24 at 2.04.26 PM.png&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;61&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ch0Y4L/btrKuvns7fx/M7L3KnMx3faYNJHWV1UYN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ch0Y4L/btrKuvns7fx/M7L3KnMx3faYNJHWV1UYN0/img.png&quot; data-alt=&quot;ptsd 담당&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ch0Y4L/btrKuvns7fx/M7L3KnMx3faYNJHWV1UYN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fch0Y4L%2FbtrKuvns7fx%2FM7L3KnMx3faYNJHWV1UYN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;702&quot; height=&quot;61&quot; data-filename=&quot;Screen Shot 2022-08-24 at 2.04.26 PM.png&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;61&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ptsd 담당&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한참찾아보니&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 오랜 에러였고&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔리디티 버전 0.8.13 부터 IR 파이프라인을 개선함으로서 고쳤다고 주장했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://twitter.com/solidity_lang/status/1506215112507633668&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;출처1&lt;/a&gt;&amp;nbsp; &lt;a href=&quot;https://blog.soliditylang.org/2022/03/16/solidity-0.8.13-release-announcement/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;출처2&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 고쳤다고 하니 실제로 옵션을 바꾸라는대로 바꿔보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-08-24 at 2.06.44 PM.png&quot; data-origin-width=&quot;178&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q2mJi/btrKuHOLpsA/Pbp9lGXqKbgKGJrQSH0clk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q2mJi/btrKuHOLpsA/Pbp9lGXqKbgKGJrQSH0clk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q2mJi/btrKuHOLpsA/Pbp9lGXqKbgKGJrQSH0clk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq2mJi%2FbtrKuHOLpsA%2FPbp9lGXqKbgKGJrQSH0clk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;178&quot; height=&quot;192&quot; data-filename=&quot;Screen Shot 2022-08-24 at 2.06.44 PM.png&quot; data-origin-width=&quot;178&quot; data-origin-height=&quot;192&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드 고고고&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-08-24 at 2.07.14 PM.png&quot; data-origin-width=&quot;406&quot; data-origin-height=&quot;89&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0VBjo/btrKtAP9nBJ/Z4B1FilPyMzDHR6gyJMUgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0VBjo/btrKtAP9nBJ/Z4B1FilPyMzDHR6gyJMUgk/img.png&quot; data-alt=&quot;안돼&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0VBjo/btrKtAP9nBJ/Z4B1FilPyMzDHR6gyJMUgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0VBjo%2FbtrKtAP9nBJ%2FZ4B1FilPyMzDHR6gyJMUgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;406&quot; height=&quot;89&quot; data-filename=&quot;Screen Shot 2022-08-24 at 2.07.14 PM.png&quot; data-origin-width=&quot;406&quot; data-origin-height=&quot;89&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;안돼&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ethereum/solidity/issues/13259&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이 에러 6월에 고치고있었잖아..&lt;/a&gt; 이후에 솔리디티 버전도 업데이트 됐잖아.. 왜 이 에러는 아직도 fix 가 안됐어..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하여튼 에러고쳐질때까지 16개 slot 꽉채워 못쓴다가 결론이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://soliditydeveloper.com/stacktoodeep&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://soliditydeveloper.com/stacktoodeep&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://medium.com/coinmonks/stack-too-deep-error-in-solidity-608d1bd6a1ea&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://medium.com/coinmonks/stack-too-deep-error-in-solidity-608d1bd6a1ea&lt;/a&gt;&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/117</guid>
      <comments>https://realapril.tistory.com/117#entry117comment</comments>
      <pubDate>Wed, 24 Aug 2022 14:18:31 +0900</pubDate>
    </item>
    <item>
      <title>[Solidity]String 과 용량, 가스비</title>
      <link>https://realapril.tistory.com/116</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가스비를 계산하는데 뭔가 계속 이상했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://realapril.tistory.com/112&quot;&gt;https://realapril.tistory.com/112&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1659080969417&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Storing Structs is costing you gas&quot; data-og-description=&quot;Storing Structs is costing you gas 라는 글을 보고 가스를 측정해 보았다. 2018년 글 wow 여러 시나리오가 테스트되어있다. 가스비가 그냥 state 여러개 저장 &amp;gt;&amp;gt;&amp;gt;construct &amp;gt; construct 내 변수 최적화&amp;gt;&amp;gt;+알파&amp;nbsp;..&quot; data-og-host=&quot;realapril.tistory.com&quot; data-og-source-url=&quot;https://realapril.tistory.com/112&quot; data-og-url=&quot;https://realapril.tistory.com/112&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ji3L8/hyPf7np0NY/BUfGtDYVSUYuth5Gqt8Ar1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/tWCUl/hyPf02VcWH/aCD3ARYxqkkhH9saqqiUP1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://realapril.tistory.com/112&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://realapril.tistory.com/112&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ji3L8/hyPf7np0NY/BUfGtDYVSUYuth5Gqt8Ar1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/tWCUl/hyPf02VcWH/aCD3ARYxqkkhH9saqqiUP1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Storing Structs is costing you gas&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Storing Structs is costing you gas 라는 글을 보고 가스를 측정해 보았다. 2018년 글 wow 여러 시나리오가 테스트되어있다. 가스비가 그냥 state 여러개 저장 &amp;gt;&amp;gt;&amp;gt;construct &amp;gt; construct 내 변수 최적화&amp;gt;&amp;gt;+알파&amp;nbsp;..&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;realapril.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에 따르면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1659081045968&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    struct A{
        address sideWallet1;
        address sideWallet2;
        address sideWallet3;
    }

    struct B {
        string cid;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;struct 하나를 저장할때 struct A가스비가 struct B 보다 비싸야한다고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는 address 는 하나당 20 바이트이므로 저장할 때  slot 3개를 사용하기때문이다. (1 slot = 32 바이트)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 내 cid 는 46바이트인데, 저장하는데 slot 2개가 필요하기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 로그를 찍어보면 저장할때 소모되는 가스비가 거의 비슷했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜..? 왜???&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;열심히 검색해본결과 &quot;정상&quot;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ethereum.stackexchange.com/questions/107282/storage-and-memory-layout-of-strings&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ethereum.stackexchange.com/questions/107282/storage-and-memory-layout-of-strings&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1659081162348&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Storage and memory layout of strings&quot; data-og-description=&quot;How exactly are strings stored in storage? And, how does that differ from the way they're stored in memory when loaded from storage into a memory variable?&quot; data-og-host=&quot;ethereum.stackexchange.com&quot; data-og-source-url=&quot;https://ethereum.stackexchange.com/questions/107282/storage-and-memory-layout-of-strings&quot; data-og-url=&quot;https://ethereum.stackexchange.com/questions/107282/storage-and-memory-layout-of-strings&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/d9WFGR/hyPeGkGbY9/3fK59yTq6yyfygRiJCNcpk/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;a href=&quot;https://ethereum.stackexchange.com/questions/107282/storage-and-memory-layout-of-strings&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ethereum.stackexchange.com/questions/107282/storage-and-memory-layout-of-strings&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/d9WFGR/hyPeGkGbY9/3fK59yTq6yyfygRiJCNcpk/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Storage and memory layout of strings&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;How exactly are strings stored in storage? And, how does that differ from the way they're stored in memory when loaded from storage into a memory variable?&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ethereum.stackexchange.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bytes&lt;span&gt;&amp;nbsp;&lt;/span&gt;and&lt;span&gt;&amp;nbsp;&lt;/span&gt;string&lt;span&gt;&amp;nbsp;&lt;/span&gt;are encoded identically. In general, the encoding is similar to&lt;span&gt;&amp;nbsp;&lt;/span&gt;bytes1[], in the sense that there is a slot for the array itself and a data area that is computed using a&lt;span&gt;&amp;nbsp;&lt;/span&gt;keccak256&lt;span&gt;&amp;nbsp;&lt;/span&gt;hash of that slot&amp;rsquo;s position. However, for short values (shorter than 32 bytes) the array elements are stored together with the length in the same slot.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In particular: if the data is at most&lt;span&gt;&amp;nbsp;&lt;/span&gt;31&lt;span&gt;&amp;nbsp;&lt;/span&gt;bytes long, the elements are stored in the higher-order bytes (left aligned) and the lowest-order byte stores the value&lt;span&gt;&amp;nbsp;&lt;/span&gt;length * 2. For byte arrays that store data which is&lt;span&gt;&amp;nbsp;&lt;/span&gt;32&lt;span&gt;&amp;nbsp;&lt;/span&gt;or more bytes long, the main slot&lt;span&gt;&amp;nbsp;&lt;/span&gt;p&lt;span&gt;&amp;nbsp;&lt;/span&gt;stores&lt;span&gt;&amp;nbsp;&lt;/span&gt;length * 2 + 1&lt;span&gt;&amp;nbsp;&lt;/span&gt;and the data is stored as usual in&lt;span&gt;&amp;nbsp;&lt;/span&gt;keccak256(p). This means that you can distinguish a short array from a long array by checking if the lowest bit is set: short (not set) and long (set).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;So for example a string&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;abcd&quot;&lt;span&gt;&amp;nbsp;&lt;/span&gt;will use the short format and take up a single slot with the upper four bytes being characters&lt;span&gt;&amp;nbsp;&lt;/span&gt;a,&lt;span&gt;&amp;nbsp;&lt;/span&gt;b,&lt;span&gt;&amp;nbsp;&lt;/span&gt;c,&lt;span&gt;&amp;nbsp;&lt;/span&gt;d&lt;span&gt;&amp;nbsp;&lt;/span&gt;and remaining bytes being zeros.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;On the other hand&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;0123456789012345678901234567890123456789&quot;, which has more than 32 characters will take 3 slots. A single slot placed at the normal location between other storage variables &lt;b&gt;will only contain the length (40)&lt;/b&gt; shifted left by one bit &lt;b&gt;and will have the last bit set to indicate that it's the long format.&lt;/b&gt; I.e. its value will be 81. The other two slots will store the characters of the string (with unused space being filled with zeros) and the compiler will place them at a location computed by hashing the address of the slot containing length with&lt;span&gt;&amp;nbsp;&lt;/span&gt;keccak256().&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를&amp;nbsp;들어&amp;nbsp;문자열&amp;nbsp;&quot;abcd&quot;는&amp;nbsp;짧은&amp;nbsp;형식을&amp;nbsp;사용하고&amp;nbsp;상위&amp;nbsp;4바이트는&amp;nbsp;문자&amp;nbsp;a,&amp;nbsp;b,&amp;nbsp;c,&amp;nbsp;d이고&amp;nbsp;나머지&amp;nbsp;바이트는&amp;nbsp;0인&amp;nbsp;단일&amp;nbsp;슬롯을&amp;nbsp;차지합니다.&lt;br /&gt;&lt;br /&gt;반면&amp;nbsp;32자&amp;nbsp;이상인&amp;nbsp;&quot;0123456789012345678901234567890123456789&quot;는&amp;nbsp;&lt;b&gt;3슬롯을&amp;nbsp;차지한다.&lt;/b&gt;&amp;nbsp;다른&amp;nbsp;저장&amp;nbsp;변수&amp;nbsp;사이의&amp;nbsp;일반&amp;nbsp;위치에&amp;nbsp;있는&amp;nbsp;단일&amp;nbsp;슬롯은&amp;nbsp;왼쪽으로&amp;nbsp;1비트&amp;nbsp;이동한&amp;nbsp;길이(40)만&amp;nbsp;포함하고&amp;nbsp;마지막&amp;nbsp;비트가&amp;nbsp;긴&amp;nbsp;형식임을&amp;nbsp;나타내기&amp;nbsp;위해&amp;nbsp;설정됩니다.&amp;nbsp;즉.&amp;nbsp;값은&amp;nbsp;81이&amp;nbsp;됩니다.&amp;nbsp;다른&amp;nbsp;두&amp;nbsp;슬롯은&amp;nbsp;문자열의&amp;nbsp;문자를&amp;nbsp;저장하고(사용하지&amp;nbsp;않은&amp;nbsp;공간은&amp;nbsp;0으로&amp;nbsp;채워짐)&amp;nbsp;컴파일러는&amp;nbsp;keccak256()으로&amp;nbsp;길이를&amp;nbsp;포함하는&amp;nbsp;슬롯의&amp;nbsp;주소를&amp;nbsp;해싱하여&amp;nbsp;계산된&amp;nbsp;위치에&amp;nbsp;배치합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;= 첫 슬롯은 길이(40글자 짜리다)와 긴 스트링 양식이다 라는 정보값만 저장하고, 나머지 2 슬롯 에 실제 데이터가 나누어져서 저장된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 더나아가서, string 을 불러올때는 메모리를 자주 사용한다. 근데,, 내가 생각하는것과 용량이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #232629;&quot;&gt;In memory&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&quot;abcd&quot;&lt;span style=&quot;background-color: #ffffff; color: #232629;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;will occupy two consecutive 32-byte slots. The first will store the length and the other the characters.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;0123456789012345678901234567890123456789&quot;&lt;span&gt;&amp;nbsp;&lt;/span&gt;will occupy 3 consecutive slots with the first containing the length (40) and the other two storing the characters. There's no short/long format in memory so the length is not shifted like it would be in storage.&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-post-id=&quot;107321&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;놀라운걸&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/116</guid>
      <comments>https://realapril.tistory.com/116#entry116comment</comments>
      <pubDate>Fri, 29 Jul 2022 17:00:37 +0900</pubDate>
    </item>
    <item>
      <title>opensea 및 NFT market 매매 흐름(setApprovalForAll, safeTransferFrom)</title>
      <link>https://realapril.tistory.com/114</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. 매도자가 매도 신청을함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오픈씨는 이때 setApprovalForAll 에 대한 허가를 매도자에게 받음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://etherscan.io/tx/0x89b6b30c30f05a56daeb1d499ce8e57ffec1522cc9cfdf138453154066a316c5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://etherscan.io/tx/0x89b6b30c30f05a56daeb1d499ce8e57ffec1522cc9cfdf138453154066a316c5&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658477890833&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Ethereum Transaction Hash (Txhash) Details | Etherscan&quot; data-og-description=&quot;Ethereum (ETH) detailed transaction info for txhash 0x89b6b30c30f05a56daeb1d499ce8e57ffec1522cc9cfdf138453154066a316c5. The transaction status, block confirmation, gas fee, Ether (ETH), and token transfer are shown.&quot; data-og-host=&quot;etherscan.io&quot; data-og-source-url=&quot;https://etherscan.io/tx/0x89b6b30c30f05a56daeb1d499ce8e57ffec1522cc9cfdf138453154066a316c5&quot; data-og-url=&quot;http://etherscan.io/tx/0x89b6b30c30f05a56daeb1d499ce8e57ffec1522cc9cfdf138453154066a316c5&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Kp8a5/hyPbXdQ5lV/Bu3IcrQkVfeX6zTo1br7l0/img.jpg?width=294&amp;amp;height=294&amp;amp;face=0_0_294_294,https://scrap.kakaocdn.net/dn/clDNvC/hyPbTJioiK/UROtNBgw5xvkITVXYWBdsk/img.png?width=101&amp;amp;height=70&amp;amp;face=0_0_101_70,https://scrap.kakaocdn.net/dn/dvMAGS/hyPbO823Eo/DckygutPcG9jIajRqxTCT0/img.jpg?width=294&amp;amp;height=294&amp;amp;face=0_0_294_294&quot;&gt;&lt;a href=&quot;https://etherscan.io/tx/0x89b6b30c30f05a56daeb1d499ce8e57ffec1522cc9cfdf138453154066a316c5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://etherscan.io/tx/0x89b6b30c30f05a56daeb1d499ce8e57ffec1522cc9cfdf138453154066a316c5&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Kp8a5/hyPbXdQ5lV/Bu3IcrQkVfeX6zTo1br7l0/img.jpg?width=294&amp;amp;height=294&amp;amp;face=0_0_294_294,https://scrap.kakaocdn.net/dn/clDNvC/hyPbTJioiK/UROtNBgw5xvkITVXYWBdsk/img.png?width=101&amp;amp;height=70&amp;amp;face=0_0_101_70,https://scrap.kakaocdn.net/dn/dvMAGS/hyPbO823Eo/DckygutPcG9jIajRqxTCT0/img.jpg?width=294&amp;amp;height=294&amp;amp;face=0_0_294_294');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Ethereum Transaction Hash (Txhash) Details | Etherscan&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Ethereum (ETH) detailed transaction info for txhash 0x89b6b30c30f05a56daeb1d499ce8e57ffec1522cc9cfdf138453154066a316c5. The transaction status, block confirmation, gas fee, Ether (ETH), and token transfer are shown.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;etherscan.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;2. 시간이 지나 매수자가 매수 신청을함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 opensea의 Seaport contract와 상호작용을 하게된다. opensea에 이더리움을 보내고, 수수료를 떼고, 대금을 매도자에게 보내는것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-07-22 at 5.21.20 PM.png&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;121&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0yfZ8/btrHZkJv3pb/AezuRWvazgQ6raqUTkfwYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0yfZ8/btrHZkJv3pb/AezuRWvazgQ6raqUTkfwYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0yfZ8/btrHZkJv3pb/AezuRWvazgQ6raqUTkfwYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0yfZ8%2FbtrHZkJv3pb%2FAezuRWvazgQ6raqUTkfwYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;615&quot; height=&quot;121&quot; data-filename=&quot;Screen Shot 2022-07-22 at 5.21.20 PM.png&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;121&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대금지불이 완료되면 오픈씨는 Transfer() 함수를 통해 매도자의 NFT 를 매수자에게 보낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스팅을 올렸다고 &lt;u&gt;NFT를 오픈씨가 가져가거나 사용을 제한하지 않는다&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setApprovalForAll 하나만 활성화할뿐..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-07-22 at 5.25.49 PM.png&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;161&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zwNhl/btrH0trIZd5/B4LNYaV3pXJK7ukJGtCWF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zwNhl/btrH0trIZd5/B4LNYaV3pXJK7ukJGtCWF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zwNhl/btrH0trIZd5/B4LNYaV3pXJK7ukJGtCWF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzwNhl%2FbtrH0trIZd5%2FB4LNYaV3pXJK7ukJGtCWF1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;694&quot; height=&quot;161&quot; data-filename=&quot;Screen Shot 2022-07-22 at 5.25.49 PM.png&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;161&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오픈씨에 등록이 되어있는건 그냥 웹2.0적인 리스팅이기 때문에&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매도자는 그 NFT를 팔겠다고 해놓고 실제로는 burn 할수도있고 transfer 도 할수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이런 invalid 한 NFT 는 매수시 당연히 실패할것이고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오픈씨가 서버상황이 원활하다면 금방 매도 리스팅에서 제거되기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 큰문제는 생기지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://etherscan.io/tx/0x7110f12c3a13f039affb946b14c29c4b0b3a44c8689278f6885c5f30f2b0791b&quot;&gt;https://etherscan.io/tx/0x7110f12c3a13f039affb946b14c29c4b0b3a44c8689278f6885c5f30f2b0791b&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658478028562&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Ethereum Transaction Hash (Txhash) Details | Etherscan&quot; data-og-description=&quot;Ethereum (ETH) detailed transaction info for txhash 0x7110f12c3a13f039affb946b14c29c4b0b3a44c8689278f6885c5f30f2b0791b. The transaction status, block confirmation, gas fee, Ether (ETH), and token transfer are shown.&quot; data-og-host=&quot;etherscan.io&quot; data-og-source-url=&quot;https://etherscan.io/tx/0x7110f12c3a13f039affb946b14c29c4b0b3a44c8689278f6885c5f30f2b0791b&quot; data-og-url=&quot;http://etherscan.io/tx/0x7110f12c3a13f039affb946b14c29c4b0b3a44c8689278f6885c5f30f2b0791b&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/pvb3l/hyPaqaU0Jx/zA7BCtJeWmAD4QAuobJxfk/img.jpg?width=294&amp;amp;height=294&amp;amp;face=0_0_294_294,https://scrap.kakaocdn.net/dn/Or92s/hyPaszMcUO/jVu6q42ZM6QLiOqsDAkaAk/img.png?width=101&amp;amp;height=70&amp;amp;face=0_0_101_70,https://scrap.kakaocdn.net/dn/D5s9Q/hyPbMckRJ4/RIEwgM9oOPi3k7NhITgDo0/img.jpg?width=294&amp;amp;height=294&amp;amp;face=0_0_294_294&quot;&gt;&lt;a href=&quot;https://etherscan.io/tx/0x7110f12c3a13f039affb946b14c29c4b0b3a44c8689278f6885c5f30f2b0791b&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://etherscan.io/tx/0x7110f12c3a13f039affb946b14c29c4b0b3a44c8689278f6885c5f30f2b0791b&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/pvb3l/hyPaqaU0Jx/zA7BCtJeWmAD4QAuobJxfk/img.jpg?width=294&amp;amp;height=294&amp;amp;face=0_0_294_294,https://scrap.kakaocdn.net/dn/Or92s/hyPaszMcUO/jVu6q42ZM6QLiOqsDAkaAk/img.png?width=101&amp;amp;height=70&amp;amp;face=0_0_101_70,https://scrap.kakaocdn.net/dn/D5s9Q/hyPbMckRJ4/RIEwgM9oOPi3k7NhITgDo0/img.jpg?width=294&amp;amp;height=294&amp;amp;face=0_0_294_294');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Ethereum Transaction Hash (Txhash) Details | Etherscan&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Ethereum (ETH) detailed transaction info for txhash 0x7110f12c3a13f039affb946b14c29c4b0b3a44c8689278f6885c5f30f2b0791b. The transaction status, block confirmation, gas fee, Ether (ETH), and token transfer are shown.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;etherscan.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트랜젝션을 일으킨것은 매수자이므로 매수자의 지갑에 nonce 가 생성된다.(Nonce: 2455)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리해보니 단순한데 이해하기 힘들었음..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/114</guid>
      <comments>https://realapril.tistory.com/114#entry114comment</comments>
      <pubDate>Fri, 22 Jul 2022 17:27:30 +0900</pubDate>
    </item>
    <item>
      <title>Storing Structs is costing you gas</title>
      <link>https://realapril.tistory.com/112</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://medium.com/@novablitz/storing-structs-is-costing-you-gas-774da988895e&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Storing Structs is costing you gas&lt;/a&gt; 라는 글을 보고 가스를 측정해 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2018년 글 wow&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 시나리오가 테스트되어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가스비가 &lt;b&gt;그냥 state 여러개 저장 &amp;gt;&amp;gt;&amp;gt;construct &amp;gt; construct 내 변수 최적화&amp;gt;&amp;gt;+알파&lt;/b&gt;&amp;nbsp;순으로 든다는 주장인데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 실험해보았다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;In Solidity (the programming language used for Ethereum smart contracts), you have &amp;ldquo;memory&amp;rdquo;, (think RAM on a computer), and &amp;ldquo;storage&amp;rdquo; (think the hard drive). Both are set up in &lt;b&gt;chunks of 32 bytes&lt;/b&gt; (a byte is roughly a letter, so &amp;ldquo;are set up in chunks of 32 bytes&amp;rdquo; is 32 bytes of data). &lt;br /&gt;In Solidity, &lt;b&gt;memory&lt;/b&gt; is inexpensive (&lt;b&gt;3 gas to store or update a value&lt;/b&gt;). &lt;br /&gt;&lt;b&gt;Storage&lt;/b&gt; is expensive &lt;b&gt;(20,000 gas to store a value, 5,000 gas to update one)&lt;/b&gt;.&amp;nbsp; -&amp;gt; SSTORE&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시나리오 1&amp;nbsp; -&amp;nbsp; struct 아예 사용 안함&lt;/p&gt;
&lt;pre id=&quot;code_1655738678775&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Type1
    address owner;
    uint64 creationTime;
    uint256 dna;
    uint16 strength;
    uint16 race;
    uint16 class;
    mapping(uint256 =&amp;gt; address) owners;
    mapping(uint256 =&amp;gt; uint64) creationTimes;
    mapping(uint256 =&amp;gt; uint256) dnas;
    mapping(uint256 =&amp;gt; uint16) strengths;
    mapping(uint256 =&amp;gt; uint16) races;
    mapping(uint256 =&amp;gt; uint16) classes;

    function save1(
        uint64 _creationTime,
        uint256 _dna,
        uint16 _strength,
        uint16 _race,
        uint16 _class
    ) external {
        owners[dna] = msg.sender;
        creationTimes[dna] = _creationTime;
        dnas[dna] = _dna;
        strengths[dna] = _strength;
        races[dna] = _race;
        classes[dna] = _class;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 ts에서 테스트해보자&lt;/p&gt;
&lt;pre id=&quot;code_1655738698106&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;it(&quot;Should success1 - gas test&quot;, async function () {
    const tx = await gasTest
      .connect(account1)
      .save1(Date.now(), 123123, 8, 0, 3);
    const receipt = await tx.wait();
    console.log(receipt.gasUsed);
  });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과 : BigNumber&amp;nbsp;{&amp;nbsp;value:&amp;nbsp;&quot;139052&quot;&amp;nbsp;}&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시나리오 1&amp;nbsp; -&amp;nbsp; struct&amp;nbsp;사용&lt;/p&gt;
&lt;pre id=&quot;code_1655738731704&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Type 2
    struct GameCharacter2 {
        address owner;
        uint64 creationTime;
        uint256 dna;
        uint16 strength;
        uint16 race;
        uint16 class;
    }
    mapping(uint256 =&amp;gt; GameCharacter2) characters2;

    function save2(
        uint64 _creationTime,
        uint256 _dna,
        uint16 _strength,
        uint16 _race,
        uint16 _class
    ) external {
        characters2[_dna] = GameCharacter2({
            owner: msg.sender,
            creationTime: _creationTime,
            dna: _dna,
            strength: _strength,
            race: _race,
            class: _class
        });
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 테스트할차례&lt;/p&gt;
&lt;pre id=&quot;code_1655738744136&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;it(&quot;Should success2 - gas test&quot;, async function () {
    const tx = await gasTest
      .connect(account1)
      .save2(Date.now(), 123123, 8, 0, 3);
    const receipt = await tx.wait();
    console.log(receipt.gasUsed);
  });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과 : BigNumber { value: &quot;90709&quot; }&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진짜 가스가 줄었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시나리오 1에서는 스토리지에 저장이 6번이루어졌으므로 &lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;120,000가스가 들것이다. (실제로는 139052)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시나리오 2에서는 슬롯이 줄어들어 &lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;75,000 gas가 든다. (왜 80000이 아니고 75000인지모르겠음 )&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;&amp;nbsp; &amp;nbsp;연달아 나오는 데이터가 32바이트가안되면 컴파일러가 알아서 합쳐서 패키징한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;&amp;nbsp; &amp;nbsp;owner, creationTime을 같은 슬랏에 패키징하고, dna는 따로, strength,&amp;nbsp;race,&amp;nbsp;and&amp;nbsp;class도 같은 슬랏에 패키징한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;시나리오3 - 패키징 용량을 더 줄여보자&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1655740005164&quot; class=&quot;properties&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; //Type3
    struct GameCharacter3 {
        address owner;
        uint48 creationTime;
        uint16 strength;
        uint16 race;
        uint16 class;
        uint256 dna;
    }
    mapping(uint256 =&amp;gt; GameCharacter3) characters3;

    function save3(
        uint48 _creationTime,
        uint256 _dna,
        uint16 _strength,
        uint16 _race,
        uint16 _class
    ) external {
        characters3[_dna] = GameCharacter3({
            owner: msg.sender,
            creationTime: _creationTime,
            dna: _dna,
            strength: _strength,
            race: _race,
            class: _class
        });
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두가지변화가있는데, 시간의 데이터타입이 uint48이 되었고 dna는 맨끝으로 옮겼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;uint 의 크기는 꼭 8, 16, 64 가 아니라 그냥 8의 배수기만하면된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 장점은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;owner~class 까지 모두 하나의 32바이트 청크에 저장이된다. (20+6+2+2+2)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;uint256 인 dna 는 이미 혼자 32바이트 청크를 차지한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 저장에 &lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;60,000 gas만든다.&amp;nbsp; (owner~class, dna, 맵저장인듯)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;실제로 ts 에서 돌려보면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;BigNumber&amp;nbsp;{&amp;nbsp;value:&amp;nbsp;&quot;68837&quot;&amp;nbsp;}&lt;br /&gt;많이줄었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;마지막방식은 들이는 공수에비해 가스비가 그렇게 줄지않았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;그리고 40000가스가 든다고하는데,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터가 1슬랏을 차지하고 characters 맵과 dnaRecords맵에 저장할때 각각 슬랏을 하나씩 차지해서 결국 비슷하게 들지않나?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 테스트결과&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BigNumber { value: &quot;68364&quot; }로 유의미하게 감소하지 않았다... 뭔가 바뀐걸까&lt;/p&gt;
&lt;pre id=&quot;code_1655741471865&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Type4
    struct GameCharacter4 {
        address owner;
        uint256 creationTime;
        uint256 strength;
        uint256 race;
        uint256 class;
        uint256 dna;
    }

    mapping(uint256 =&amp;gt; uint256) characters4;
    mapping(uint256 =&amp;gt; uint256) dnaRecords4;

    function setCharacter(
        uint256 _id,
        address owner,
        uint256 creationTime,
        uint256 strength,
        uint256 race,
        uint256 class,
        uint256 dna
    ) external {
        uint256 character = uint256(uint160(owner));
        character |= creationTime &amp;lt;&amp;lt; 160;
        character |= strength &amp;lt;&amp;lt; 208;
        character |= race &amp;lt;&amp;lt; 224;
        character |= class &amp;lt;&amp;lt; 240;
        characters4[_id] = character;
        dnaRecords4[_id] = dna;
    }

    function getCharacter(uint256 _id)
        external
        view
        returns (
            address owner,
            uint256 creationTime,
            uint256 strength,
            uint256 race,
            uint256 class,
            uint256 dna
        )
    {
        uint256 character = characters4[_id];
        dna = dnaRecords4[_id];
        owner = address(uint160(character)); 
        creationTime = uint256(uint40(character &amp;gt;&amp;gt; 160));
        strength = uint256(uint16(character &amp;gt;&amp;gt; 208));
        race = uint256(uint16(character &amp;gt;&amp;gt; 224));
        class = uint256(uint16(character &amp;gt;&amp;gt; 240));
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본요지는 어차피 uint256가 하나의 슬랏을 차지하니까&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 안에 메모리 위치를 지정헤서 데이터를 다 넣어버리자는거다.&lt;/p&gt;
&lt;pre id=&quot;code_1655741490321&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;it(&quot;Should success4 - gas test&quot;, async function () {
    const tx = await gasTest
      .connect(account1)
      .setCharacter(0, account1.getAddress(), Date.now(), 8, 0, 3, 123123);
    const receipt = await tx.wait();
    console.log(receipt.gasUsed);
  });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별로 안주는데 왜 블로그글에서는 많이 주는척했는지?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쓰고 읽을때 예외처리까지 해야해서 작성시 생산성도 떨어지는데 왜 과시하는지?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나를 이해시켜줄분 구함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gist.github.com/crypt0summer/7aeae440e5592edbd43d23ea688591fe&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gist.github.com/crypt0summer/7aeae440e5592edbd43d23ea688591fe&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1655747329237&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Ethreum-Storing Structs is costing you gas&quot; data-og-description=&quot;Ethreum-Storing Structs is costing you gas. GitHub Gist: instantly share code, notes, and snippets.&quot; data-og-host=&quot;gist.github.com&quot; data-og-source-url=&quot;https://gist.github.com/crypt0summer/7aeae440e5592edbd43d23ea688591fe&quot; data-og-url=&quot;https://gist.github.com/crypt0summer/7aeae440e5592edbd43d23ea688591fe&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bhaSNn/hyOOxVNthx/u4Vuay7aXsG7gdPtdVkaK0/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://gist.github.com/crypt0summer/7aeae440e5592edbd43d23ea688591fe&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://gist.github.com/crypt0summer/7aeae440e5592edbd43d23ea688591fe&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bhaSNn/hyOOxVNthx/u4Vuay7aXsG7gdPtdVkaK0/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Ethreum-Storing Structs is costing you gas&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Ethreum-Storing Structs is costing you gas. GitHub Gist: instantly share code, notes, and snippets.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;gist.github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에있다.&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/112</guid>
      <comments>https://realapril.tistory.com/112#entry112comment</comments>
      <pubDate>Mon, 20 Jun 2022 23:35:50 +0900</pubDate>
    </item>
    <item>
      <title>interact with existing deployed contracts, raw calls</title>
      <link>https://realapril.tistory.com/111</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;외부 컨트랙트를 부를때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 인터페이스로 부르는 방식이 있고&lt;/p&gt;
&lt;pre id=&quot;code_1655372857017&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//1
interface IVault {
    function createVault(uint256 gameId) external payable;
    function addAmount(uint256 gameId) external payable;
    function withdraw(uint256 gameId, address payable winner) external payable;
    function claim(uint256 gameId, address payable user) external payable;
}
//2
address vaultAddr;
//3
    function setVault(address _vaultAddr) external {
        vaultAddr = _vaultAddr;
    }
//4
...
	IVault(vaultAddr).addAmount{value: msg.value}(gameId);
...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ABI 로 부르는 방식이 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1655372951111&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import &quot;./Vault.sol&quot;; //외부컨트랙트 abi 불러옴

address vaultContract;

function setVault(address vaultAddr) external {
        vaultContract = vaultAddr;
    }
    
    ...
    
    (bool success, ) = vaultContract.call{value: msg.value}(
            abi.encodeWithSignature(&quot;createVault(uint256)&quot;, gameId)
        );
        require(success, &quot;Failed to createVault vault&quot;);
        
    ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;나는 인터페이스 작성하기가 귀찮아서ㅠ ABI 로 불렀는데..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;생각해보니 ABI 로 콜함으로서 전부 raw call로 함수를 불렀어야했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;걍&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #7aa2f7;&quot;&gt;IVault&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt;vaultAddr&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;).&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt;addAmount&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f7768e;&quot;&gt;msg&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;}(&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt;gameId&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;); &lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px; color: #333333;&quot;&gt;라고 쓰면될걸&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #0db9d7;&quot;&gt;bool&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt; success&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt; vaultAddr&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt;call&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f7768e;&quot;&gt;msg&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;}(&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f7768e;&quot;&gt;abi&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #7aa2f7;&quot;&gt;encodeWithSignature&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #9ece6a;&quot;&gt;&quot;addAmount(uint256)&quot;&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt; gameId&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #bb9af7;&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt;success&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #a9b1d6;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #9ece6a;&quot;&gt;&quot;Failed to addAmount vault&quot;&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;라고 써야해서&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;결과적으로는  남이 코드를 읽기 더어렵게 만들었을 뿐...&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;그럼 raw call 은 언제 쓰는가?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/external-calls/#dont-use-transfer-or-send&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;consensys 베스트 프랙티스에 따르면&lt;/a&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;It's recommended to stop using&amp;nbsp;.transfer()&amp;nbsp;and&amp;nbsp;.send()&amp;nbsp;and instead use&amp;nbsp;.call().&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;송금 시 raw call을 쓰라고한다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;One of the changes included in EIP 1884 is an increase to the gas cost of the&amp;nbsp;&lt;br /&gt;SLOAD&amp;nbsp;operation, causing a contract's fallback function to cost more than 2300 gas.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&amp;nbsp;&lt;/span&gt;.transfer()&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&amp;nbsp;and&amp;nbsp;&lt;/span&gt;.send()&lt;span style=&quot;background-color: #ffffff;&quot;&gt; 은 2300 가스로 픽스가되어있어 이스탄불 업데이트 이후 (2019) 해당 펑션 이용시 가스비가 부족하기 때문이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;아니 근데, 예제는 transfer 이나 send 하는 상황이아니잖아? raw call 의 이점이 뭐냐니까?&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/external-calls/#handle-errors-in-external-calls&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Raw call 의 이점: 에러 핸들링&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;address.call을 하면 성공/실패 여부를 bool로 받을수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;실패시 내가 케이스 관리를 해야한다/할수있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1655374382731&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// good
(bool success, ) = someAddress.call.value(55)(&quot;&quot;);
if(!success) {
    // handle failure code
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;컨트랙트.function() 도 당연히 성공, 실패 여부를 알수 있지만 실패시&amp;nbsp;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;throw an exception이어서 다음 코드가 실행되지 않는다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt; 내가 실패 케이스를 따로 관리(재시도를 한다거나)하는 시나리오가 아니라면&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;컨트랙트.function() 를 사용하는게&amp;nbsp;나을수 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;일단 심플하다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 raw call을 하던 contract.call을 하던 외부 컨트랙트를 부를 때 더 신경써야하는 부분이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드는 옥션 입찰에 상위입찰이 들어오면 그 전의 1등에게 출금을 해주려한다.&lt;/p&gt;
&lt;pre id=&quot;code_1655434541469&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// bad
contract auction {
    address highestBidder;
    uint highestBid;

    function bid() payable {
        require(msg.value &amp;gt;= highestBid);

        if (highestBidder != address(0)) {
            (bool success, ) = highestBidder.call.value(highestBid)(&quot;&quot;);
            require(success); // if this call consistently fails, no one else can bid
        }

       highestBidder = msg.sender;
       highestBid = msg.value;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 외부 컨트랙트에서 실패가 뜨면, require(success); 에 막혀서 bid()함수 자체가 작동하지 않게된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 컨트랙트 탓이 아닌 외부 컨트랙트의 상태에 따라 좌지우지되는것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 컨트랙트를 부르는 기능을 분리하자.&lt;/p&gt;
&lt;pre id=&quot;code_1655434846557&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// good
contract auction {
    address highestBidder;
    uint highestBid;
    mapping(address =&amp;gt; uint) refunds;

    function bid() payable external {
        require(msg.value &amp;gt;= highestBid);

        if (highestBidder != address(0)) {
            refunds[highestBidder] += highestBid; // record the refund that this user can claim
        }

        highestBidder = msg.sender;
        highestBid = msg.value;
    }

    function withdrawRefund() external {
        uint refund = refunds[msg.sender];
        refunds[msg.sender] = 0;
        (bool success, ) = msg.sender.call.value(refund)(&quot;&quot;);
        require(success);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상위입찰자가 갱신되면 매핑에 환불할 지갑과 주소를 저장하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전 입찰자들이 withdrawRefund()로 환불을 요청하면 그때 외부 함수를 부르는식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 외부 컨트랙트에 문제가 생겨도 입찰함수는 영향을 받지않고 출금함수만 영향을 받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 UI 단에 출금버튼이 하나 더생겨야한다. 기존에는 신청 안하고 가만히 있어도 알아서지갑에 환불되는방식이었음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지화하면 이런식이다. (딱맞진않음 그냥 add claim 분리한다는의미)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;595&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kI0To/btrEZE5aGqr/NRLg7Kva8ZuUa8LXCAVukk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kI0To/btrEZE5aGqr/NRLg7Kva8ZuUa8LXCAVukk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kI0To/btrEZE5aGqr/NRLg7Kva8ZuUa8LXCAVukk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkI0To%2FbtrEZE5aGqr%2FNRLg7Kva8ZuUa8LXCAVukk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1400&quot; height=&quot;595&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;595&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(근데 withdrawRefund() 내에 refund금액이 0인지 확인안하고 그냥 송금해도되나?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하긴 다른 컨트랙트에서 예외처리해놨을수도)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 이렇게하면 가스비가 추가로든다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심지어 매핑에 저장하는것은 스토리지 저장이어서 비싸다. 저장에(&lt;span style=&quot;background-color: #ffffff; color: #232629;&quot;&gt;SSTORE&lt;/span&gt;) 대략 &lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;20,000 gas, 업데이트에 5,000 gas&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;그니까 외부 컨트랙트를 부른다고 전부 매핑으로 저장하는게 아니고 돈과 관련된 필수 기능만 매핑해서 저장하는게 옳아보인다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #292929;&quot;&gt;가스비&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;20000 per 32 bytes with an overhead of 20000 for the length.&lt;/li&gt;
&lt;li&gt;Plus 68 gas per byte (2176 gas per 32 bytes) for storing the calldata&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/111</guid>
      <comments>https://realapril.tistory.com/111#entry111comment</comments>
      <pubDate>Thu, 16 Jun 2022 19:30:19 +0900</pubDate>
    </item>
    <item>
      <title>Hardhat vs Truffle</title>
      <link>https://realapril.tistory.com/110</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;하드햇과 트러플은 모두 블록체인, 이더리움을 개발할때 환경설정을 도와주는 툴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구체적으로는 테스트 노드의 EVM에서 스마트컨트랙트를 compile, run, test 하는과정을 도와준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘다 Javascript 기반 환경을 제공하는데, 예전 튜토리얼을 보면 대부분 트러플을 추천하는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요새 튜토리얼은 대부분 하드햇을 추천한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 차이와 장단점이 있는지 정리해보려한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Remix도 좋은 툴이지만 둘과는 완전히 맥락이 다르므로 이번에는 패스.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Github&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Hardhat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.3k stars, 마지막 업데이트 1시간 전&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Truffle&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;13.2k stars, 마지막 업데이트 1달 전&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것만보면 하드햇을 쓰는건 모험처럼 보일수도 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;a href=&quot;https://blog.soliditylang.org/2022/02/07/solidity-developer-survey-2021-results/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Solidity2021 survey&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;eth_ide.png&quot; data-origin-width=&quot;1860&quot; data-origin-height=&quot;1045&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzc8Yp/btrDEpIZ2hI/2jZGgcS94bVQgyTDgKG3wK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzc8Yp/btrDEpIZ2hI/2jZGgcS94bVQgyTDgKG3wK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzc8Yp/btrDEpIZ2hI/2jZGgcS94bVQgyTDgKG3wK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbzc8Yp%2FbtrDEpIZ2hI%2F2jZGgcS94bVQgyTDgKG3wK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1860&quot; height=&quot;1045&quot; data-filename=&quot;eth_ide.png&quot; data-origin-width=&quot;1860&quot; data-origin-height=&quot;1045&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2020년엔 분명 하드햇-트러플 유저가 반반이었는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드햇유저수가 트러플을 완전히 추월해버렸다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;제작사&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Hardhat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://nomiclabs.io/&quot;&gt;Nomics Labs&lt;/a&gt;에서 만들었다. 여기도 계속 개발할 사람을 고용중인것을 보니  팀의 상황은 좋아보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Truffle&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Metamask로도 유명하고, 이번에 텍사스 컨센시스 행사를 여는 그 Consensys 사가 만들었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확히는 만든게아니라 트러플팀을 인수한건데, 2020년에 인수해서 계속 트러플을 개선할 인력을 고용중이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ganache라는 스마트컨트랙트를 테스트용 로컬 이더리움 블록체인을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hardhat.org/getting-started&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;하드햇문서&lt;/a&gt;는 심플하고 명료하고 잘된다. 특히 튜토리얼 문서를 따로 제공하는데, 정말 고맙다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://trufflesuite.com/docs/truffle/quickstart/&quot;&gt;트러플문서&lt;/a&gt;도 꼼꼼하게 잘나와있다. 그런데 아마 한번 장벽에 부딪힐텐데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가나슈를 이용해 로컬 이더리움 네트워크를 환경설정 세팅하는 예제가 기본예제이기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 컨트랙트를 개발하는사람한테는 좀 어려운 개념이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 초보 개발자는 로컬 이더리움 네트워크 / 가나슈를 돌리기 원하지않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔드포인트를 Infura나 alchemy걸 쓰지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 트러플은 기본설정을 가나슈로 잡아버리면서&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1654113575889&quot; class=&quot;dts&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;module.exports = {
  // See &amp;lt;http://truffleframework.com/docs/advanced/configuration&amp;gt;
  // for more about customizing your Truffle configuration!
  networks: {
    development: {
      host: &quot;127.0.0.1&quot;,
      port: 7545,
      network_id: &quot;*&quot; // Match any network id
    },
    develop: {
      port: 8545
    }
  }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 디폴트로 로컬연결 정보를 제공하기때문에 초보 개발자들은 혼란스러워하다가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드햇으로 탈주해버린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생태계 유지도 좋지만 옵션으로 둬야지(알케미나나 인푸라 연결문서도 병기했어야한다고봄)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든문서에서 가나슈 원툴을 강권하면 겁먹은 초보개발자들이 이탈한다고요~!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드햇에서는 설정이 없을시 하드햇자체 이더리움 네트워크를 기본으로 제공하기때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더욱 대비되는 부분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;커뮤니티&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘다 Stackoverflow 나 Stackexchange 에서 물어보는게 보통이고,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아니면 깃허브에 가서 이슈나 커뮤니티탭에 가면 대답을 잘해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Hardhat 은 커뮤니티탭만 지원하고 (이슈는 정말 업무정리용으로만 사용)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Truffle 은 깃허브의 모든탭이 오픈되어있다. 따로 커뮤니티도 운영했던것 같은데 깃허브로 통합됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 커뮤니티탭만 지원하는 곳은 소통이 덜된다 느낀적이 많긴한데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 문제는 결국 다 해결되곤 했기에...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트러플이 더 오래되어서 그런가 커뮤니티는 좀더 잘되어있는 느낌이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Hardhat&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 Ethers.js&amp;nbsp; + Waffle(Mocha&amp;amp;chai) 조합을 쓴다. 당연히 Ethers.js 대신 web3.js를 써도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Truffle&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 web3.js + Waffle(Mocha&amp;amp;chai) 조합을 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Library&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드햇은 여러 라이브러리를 제공한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://hardhat.org/advanced/hardhat-runtime-environment&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;HRE - Hardhat Runtime Environment&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드햇 네트워크 위에서 작동하는 web3 object를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;web3 object 은 blockchain과 상호작용하려면 필요한데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hre 위에서 쉽게 Ethers.js 나 web3.js 를 부를수있다.&lt;/p&gt;
&lt;pre id=&quot;code_1654111442063&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { ethers, web3 } from &quot;hardhat&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 하드햇에서는 컨트랙트 내에서도 console.log 를 찍을수 있다!! &lt;b&gt;(하드햇 자체 네트워크만 지원함)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+이뿐만이 아니라 하드햇에서는 바로 이더스캔에 verify 가 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+hardhat 플러그인인 Typechain을 이용해서 타입스크립트사용도 편하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기본 파일&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tP6TV/btrDHd80T8Y/uk2fzrLH0zEUm2dD3JNUD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tP6TV/btrDHd80T8Y/uk2fzrLH0zEUm2dD3JNUD0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;418&quot; data-origin-height=&quot;604&quot; data-filename=&quot;스크린샷 2022-06-02 오전 4.48.23.png&quot; style=&quot;width: 57.9948%; margin-right: 10px;&quot; data-widthpercent=&quot;58.68&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tP6TV/btrDHd80T8Y/uk2fzrLH0zEUm2dD3JNUD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtP6TV%2FbtrDHd80T8Y%2Fuk2fzrLH0zEUm2dD3JNUD0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;418&quot; height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eJE9R8/btrDLWZwomg/9Ofopo04ALiLWfrAmsgI5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eJE9R8/btrDLWZwomg/9Ofopo04ALiLWfrAmsgI5k/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;386&quot; data-origin-height=&quot;792&quot; data-filename=&quot;스크린샷 2022-06-02 오전 5.01.27.png&quot; style=&quot;width: 40.8424%;&quot; data-widthpercent=&quot;41.32&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eJE9R8/btrDLWZwomg/9Ofopo04ALiLWfrAmsgI5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeJE9R8%2FbtrDLWZwomg%2F9Ofopo04ALiLWfrAmsgI5k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;386&quot; height=&quot;792&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드햇은 만들면 바로 왼쪽같이 기본컨트랙트, 배포 스크립트, 테스트폴더와 파일이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트러플은 빈파일이 생기기 때문에 튜토리얼에 나온대로 truffle box 를 사용해 권장 예제를 받아왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드햇과 비슷한 모양새이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;migration이 script 와 같은 역할, 즉 deploy기능을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭘써도 상관없지만 민심은 하드햇으로 기운듯 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드햇 = 트러플+가나슈 라고 추천하는 곳도 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금부터 배운다면 하드햇을 선택하는게 더 편하지 않을까 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬이더리움 안돌리고 하드햇 이더리움 네트워크를 무노력으로 쓸수있다니 너무나 꿀인것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;외전&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 트러플이 비호감인 이유&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글링하면 자꾸 요리법이 나온다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이름을 잘못지었다ㅠㅠ 구글링이 너무 힘들다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드햇보다 더 힘들다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/110</guid>
      <comments>https://realapril.tistory.com/110#entry110comment</comments>
      <pubDate>Thu, 2 Jun 2022 05:07:15 +0900</pubDate>
    </item>
    <item>
      <title>deploying contract,  Compiler specific version warnings</title>
      <link>https://realapril.tistory.com/109</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;첫 NFT 를 이더리움 메인넷에  배포했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 코인값도 떨어지고 가스비도 낮아서(15그웨이 고맙다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적은부담으로 할수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨트랙트도 올리고 민팅도 잘되고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인도 이쁘게 나오고&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-19 오후 9.42.58.png&quot; data-origin-width=&quot;1734&quot; data-origin-height=&quot;1706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oT7fr/btrCEdgEalF/NkXS0s2siTSMblOQTrQG10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oT7fr/btrCEdgEalF/NkXS0s2siTSMblOQTrQG10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oT7fr/btrCEdgEalF/NkXS0s2siTSMblOQTrQG10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoT7fr%2FbtrCEdgEalF%2FNkXS0s2siTSMblOQTrQG10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1734&quot; height=&quot;1706&quot; data-filename=&quot;스크린샷 2022-05-19 오후 9.42.58.png&quot; data-origin-width=&quot;1734&quot; data-origin-height=&quot;1706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이더스캔에도 컨트랙도 잘 올렸는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 뭐람?&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-19 오후 9.48.38.png&quot; data-origin-width=&quot;1578&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxRV08/btrCDbXUIlE/1bxSFmhPdlTqJUmSSSVeAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxRV08/btrCDbXUIlE/1bxSFmhPdlTqJUmSSSVeAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxRV08/btrCDbXUIlE/1bxSFmhPdlTqJUmSSSVeAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxRV08%2FbtrCDbXUIlE%2F1bxSFmhPdlTqJUmSSSVeAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1578&quot; height=&quot;426&quot; data-filename=&quot;스크린샷 2022-05-19 오후 9.48.38.png&quot; data-origin-width=&quot;1578&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;느낌표가 있길래 눌러봤더니&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-19 오후 9.48.46.png&quot; data-origin-width=&quot;972&quot; data-origin-height=&quot;468&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ci46QT/btrCDdg7SfX/kohfxhd0dyVbxo9WjF9to1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ci46QT/btrCDdg7SfX/kohfxhd0dyVbxo9WjF9to1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ci46QT/btrCDdg7SfX/kohfxhd0dyVbxo9WjF9to1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fci46QT%2FbtrCDdg7SfX%2Fkohfxhd0dyVbxo9WjF9to1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;972&quot; height=&quot;468&quot; data-filename=&quot;스크린샷 2022-05-19 오후 9.48.46.png&quot; data-origin-width=&quot;972&quot; data-origin-height=&quot;468&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가능한 버그가 세개나? 이럴수가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;열심히 디버깅한다고 했는데 이런 참사가..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;싶어서 3개를 들여다 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 very low-severity 라고 떠서 사소하긴하지만 신경쓰이잖아.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(1)DataLocationChangeInInternalOverride&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(2)NestedCallataArrayAbiReencodingSizeValidation&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(3)&lt;b&gt;SignedImmutables&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #77838f;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3종류가 떴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시나하고 다른 nft 프로젝트의 컨트랙트를봤는데&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-20 오전 12.03.17.png&quot; data-origin-width=&quot;2706&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cofgc3/btrCB0bUAhX/88va5Klc2fz77ydOwS4xy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cofgc3/btrCB0bUAhX/88va5Klc2fz77ydOwS4xy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cofgc3/btrCB0bUAhX/88va5Klc2fz77ydOwS4xy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcofgc3%2FbtrCB0bUAhX%2F88va5Klc2fz77ydOwS4xy0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2706&quot; height=&quot;658&quot; data-filename=&quot;스크린샷 2022-05-20 오전 12.03.17.png&quot; data-origin-width=&quot;2706&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안-심&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;낮은 심각성의 warning 은 괜찮은듯 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심지어 2종류는 나와 같다. 나는 (3)사인드이뮤터블즈가 더 있고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 간략하게 맛보기를해보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(1)DataLocationChangeInInternalOverride&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;It was possible to change the data location of the parameters or return variables from ``calldata`` to ``memory`` and vice- versa while overriding internal and public functions.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This caused invalid code to be generated when calling such a function internally through virtual function calls.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어렵다. 더 긴설명을 보자...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;외부 함수를 호출할 때 매개 변수의 데이터 위치가 &quot;call data&quot; 또는 &quot;memory&quot;인 경우 데이터의 인코딩은 변경되지 않습니다. 따라서 외부 기능을 재정의할 때 데이터 위치를 변경할 수 있습니다. 컴파일러는 또한 공개 및 내부 함수를 재정의하기 위해 데이터 위치의 변경을 잘못 허용하였다. 공용 함수는 내부뿐만 아니라 외부에서도 호출될 수 있기 때문에, 이렇게 잘못 재정의된 함수가 기본 계약을 통해 내부적으로 호출될 때 유효하지 않은 코드가 생성된다. 호출자는 메모리 포인터를 제공하지만 호출된 함수는 호출 데이터 포인터로 해석하거나 그 반대로 해석한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;먼소리고? 하고 예시를봤다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;&lt;a href=&quot;https://blog.soliditylang.org/2022/05/17/data-location-inheritance-bug/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.soliditylang.org/2022/05/17/data-location-inheritance-bug/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1652965433134&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Bug Concerning Data Location during Inheritance&quot; data-og-description=&quot;On February 5th 2021, Nicolas Venturo reported a bug that allows overriding functions to change the data location of parameters from memory to calldata. The bug was introduced in Solidity 0.6.9 together with the ability to use calldata data location for al&quot; data-og-host=&quot;blog.soliditylang.org&quot; data-og-source-url=&quot;https://blog.soliditylang.org/2022/05/17/data-location-inheritance-bug/&quot; data-og-url=&quot;https://blog.soliditylang.org/2022/05/17/data-location-inheritance-bug/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/NGvug/hyOs1Btrks/1TegERqwYtqz3zgJc8RYr0/img.png?width=636&amp;amp;height=636&amp;amp;face=0_0_636_636,https://scrap.kakaocdn.net/dn/K4BHY/hyOs1g92B7/8PJyzSKBDM5ak2C3Npjxpk/img.png?width=192&amp;amp;height=192&amp;amp;face=0_0_192_192&quot;&gt;&lt;a href=&quot;https://blog.soliditylang.org/2022/05/17/data-location-inheritance-bug/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.soliditylang.org/2022/05/17/data-location-inheritance-bug/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/NGvug/hyOs1Btrks/1TegERqwYtqz3zgJc8RYr0/img.png?width=636&amp;amp;height=636&amp;amp;face=0_0_636_636,https://scrap.kakaocdn.net/dn/K4BHY/hyOs1g92B7/8PJyzSKBDM5ak2C3Npjxpk/img.png?width=192&amp;amp;height=192&amp;amp;face=0_0_192_192');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Bug Concerning Data Location during Inheritance&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;On February 5th 2021, Nicolas Venturo reported a bug that allows overriding functions to change the data location of parameters from memory to calldata. The bug was introduced in Solidity 0.6.9 together with the ability to use calldata data location for al&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.soliditylang.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;pre id=&quot;code_1652965508742&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract contract I {
    // The base contract uses &quot;calldata&quot;
    function f(uint[] calldata x) virtual internal;
}
contract C is I {
    // The derived contract uses &quot;memory&quot; and the compiler
    // does not complain - this is the bug in the compiler.
    function f(uint[] memory x)  override internal {
        // If you use `x`, it will access memory
        // even if `D.g` passed us a calldata pointer.
        // This leads to the wrong data being accessed.
    }
}
abstract contract D is I {
    function g(uint[] calldata x)  external {
        // Since D only &quot;knows&quot; `I`, the signature of `f`
        // uses calldata, while the virtual lookup ends
        // up with `C.f`, which uses memory. This results
        // in the calldata pointer `x` being passed and
        // interpreted as a memory pointer.
        f(x);
    }
}
contract X is C, D { }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;이경우 C 가 잘못된 오버라이드를 했는데,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;잘못된 C 를 extend 한 X 도 해당 에러가 난다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;나의경우 상속을 하지 않았기때문에.. C 처럼 잘못된 오버라이드를 했을거란 생각이 들었다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652966446877&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    function _baseURI() internal view virtual override returns (string memory) {
        return _baseTokenURI;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내경우 오버라이드가 이뤄진 펑션은 이거 하나뿐이었는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;openzeplin ERC721.sol 에 들어가서 오리지널을보았더니&lt;/p&gt;
&lt;pre id=&quot;code_1652966489245&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; function _baseURI() internal view virtual returns (string memory) {
        return &quot;&quot;;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은데..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(2)NestedCallataArrayAbiReencodingSizeValidation&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;ABI-re encoding of nested dynamic calldata arrays did not always perform &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000;&quot;&gt;proper size checks against the size of calldata and could read beyond ``calldatasize()``.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.soliditylang.org/2022/05/17/calldata-reencode-size-check-bug/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.soliditylang.org/2022/05/17/calldata-reencode-size-check-bug/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #404040;&quot;&gt;You might be affected if you pass a nested array directly to another external function call or use&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;abi.encode&lt;span style=&quot;background-color: #ffffff; color: #404040;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;on it.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #404040;&quot;&gt;원인: merkleProof 변수가 nested array 형태인데 그걸 그대로 external function call 에서 불러서..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #404040;&quot;&gt;머클트리는 양보 못한다. 패스 ㅠ&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #404040;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(3)&lt;b&gt;SignedImmutables&lt;/b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Immutable variables of signed integer type shorter than 256 bits can lead to values with invalid higher order bits if inline assembly is used.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://blog.soliditylang.org/2021/09/29/signed-immutables-bug/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.soliditylang.org/2021/09/29/signed-immutables-bug/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;황당하다.. 256보다 짧은 사인드 인티저를 써서 문제가되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 일어났는가?: &lt;span style=&quot;background-color: #ffffff; color: #404040;&quot;&gt;So the only way (to our knowledge) to obtain the &amp;ldquo;unclean&amp;rdquo; value of the immutable is to first assign it to a local variable and then read from that local variable inside inline assembly.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내경우엔 어샘블리를 딱히 쓰지않았기때문에 이것도 미스테리&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내생각엔 rinkeby 테스트넷에도 verify 를 했다면 이 버그들이 나왔을거라고 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디플로이 전 verify 하는 습관을 들이자&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/109</guid>
      <comments>https://realapril.tistory.com/109#entry109comment</comments>
      <pubDate>Fri, 20 May 2022 00:27:21 +0900</pubDate>
    </item>
    <item>
      <title>Merkle Tree - 솔리디티 화이트리스트 관리하기</title>
      <link>https://realapril.tistory.com/108</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NFT 민팅할때 보통 화이트리스트에게 먼저 NFT를 민팅할 권리를 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔리디티에서 이부분을 구현할때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리나 맵에 올리면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가스비로 아주 큰 비용을 지불해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하는것이 머클트리이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/merkletreejs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Merkle Tree&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://medium.com/@ItsCuzzo/using-merkle-trees-for-nft-whitelists-523b58ada3f9&quot;&gt;https://medium.com/@ItsCuzzo/using-merkle-trees-for-nft-whitelists-523b58ada3f9&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간략하게말하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;js단:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1) WL 리스트를 암호화해서(keccak256쓰던 SHA쓰던 본인선택) 머클트리에 넣는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 암호화된 전체 노드가 나오는데 Root Node만 키처럼 들고있음&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1650777318071&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        const leaves = whitelistAddresses.map(addr =&amp;gt; keccak256(addr));
        tree = new MerkleTree(leaves, keccak256, { sort: true });
        const root_merkle = tree.getRoot();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;(2) 실제로 민팅할때는 주소를 암호화한 값을 머클트리에 넣었을때 proof값을 받아서,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;컨트랙트로 보낸다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1650777436287&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        const hexProof = tree.getHexProof(keccak256(addr1.address));
        // console.log('hex: '+hexProof.toString());
        await nft_contract.connect(addr1).whitelistMint(hexProof);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;솔리디티&lt;/b&gt;: &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;Root Node의 값과 머클트리 proof 값, 그리고 지갑주소값이 필요하다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;MerkleProof 라이브러리로 두 값이 verify되는지 확인한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1650777686311&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract Merkle is Ownable{
    bytes32 public merkleRoot;

    mapping(address =&amp;gt; bool) public whitelistClaimed;

    function whitelistMint(bytes32[] calldata _merkleProof) external{
        require(!whitelistClaimed[msg.sender], &quot;Address has already claimed.&quot;);

        bytes32 leaf = keccak256(abi.encodePacked(msg.sender));

        //Verify the provided _merkleProof
        require(MerkleProof.verify(_merkleProof, merkleRoot, leaf), &quot;Invalid Proof, No WL&quot;);

        whitelistClaimed[msg.sender] = true;

        //실제민팅하는곳
    }


    function setMerkleRoot(bytes32 _merkleRoot) public {
        merkleRoot = _merkleRoot;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꼭 이런순서로 짤 필요는 없지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 구성요소가 필요한지 보고 시작하면 편하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/108</guid>
      <comments>https://realapril.tistory.com/108#entry108comment</comments>
      <pubDate>Sun, 24 Apr 2022 14:28:29 +0900</pubDate>
    </item>
    <item>
      <title>Storage, Memory and Calldata</title>
      <link>https://realapril.tistory.com/106</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Variables are declared as either&amp;nbsp;storage,&amp;nbsp;memory&amp;nbsp;or&amp;nbsp;calldata&amp;nbsp;to explicitly specify the location of the data.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;storage&amp;nbsp;- variable is a state variable (store on blockchain)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;memory&amp;nbsp;- variable is in memory and it exists while a function is being called&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;calldata&amp;nbsp;- special data location that contains function arguments&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-스토리지가 당연히 가스비가 제일 많이든다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-메모리&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때 말하는 메모리는 evm의 메모리&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;607&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t1KPB/btrxkf7bqej/k1T8HQFEm51lA1AWZSAfkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t1KPB/btrxkf7bqej/k1T8HQFEm51lA1AWZSAfkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t1KPB/btrxkf7bqej/k1T8HQFEm51lA1AWZSAfkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft1KPB%2Fbtrxkf7bqej%2Fk1T8HQFEm51lA1AWZSAfkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1080&quot; height=&quot;607&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;607&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://ethereum.org/en/developers/docs/evm/#evm-instructions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ethereum.org/en/developers/docs/evm/#evm-instructions&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;During execution, the EVM maintains a transient&amp;nbsp;memory&amp;nbsp;(as a word-addressed byte array), which does not persist between transactions.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-color=&quot;&quot;&gt;&lt;span style=&quot;--darkreader-inline-bgcolor: #121415;&quot; data-darkreader-inline-bgcolor=&quot;&quot;&gt;evm이 실행되면 임시메모리를 유지한다. 이 메모리는 임시이기 때문에 트젝간 유지/공유되지 않는다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-color=&quot;&quot;&gt;&lt;span style=&quot;--darkreader-inline-bgcolor: #121415;&quot; data-darkreader-inline-bgcolor=&quot;&quot;&gt;-calldata&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;The&amp;nbsp;Calldata&amp;nbsp;is a read-only byte-addressable space where the &lt;u&gt;data parameter of a transaction or call&lt;/u&gt; is held&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;데이터 파라미터 = 아규먼트&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;calldata&amp;nbsp;is where data from external calls to functions is stored.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;When such an external call happens, the data of that call is stored in&amp;nbsp;calldata.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.soliditylang.org/en/v0.8.13/types.html#data-location&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.soliditylang.org/en/v0.8.13/types.html#data-location&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 복합 타입은 자신이&amp;nbsp;메모리&amp;nbsp;나&amp;nbsp;스토리지&amp;nbsp;중 어디에 저장되었는지를 나타내는 &quot;데이터 위치&quot;가 추가적으로 존재합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;Calldata is a non-modifiable, non-persistent area where function arguments are stored, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;and behaves mostly like memory.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅If you can, try to use&amp;nbsp;calldata&amp;nbsp;as data location because it will &lt;b&gt;avoid copies&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;and also makes sure that &lt;b&gt;the data cannot be modified. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Arrays and structs with&amp;nbsp;calldata&amp;nbsp;data location can also be returned from functions, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;but it is not possible to allocate such types.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;&lt;b&gt;가능하면 콜데이터를 써라&lt;/b&gt;. 카피를 피하고, 데이터 변경을 막기 때문임&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;-&amp;gt;콜데이터 타입의 어레이와 스트럭(데이터) 는 펑션으로부터 리턴될수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;&lt;i&gt;그러나 그런타입을 할당할 수 없다...?&lt;/i&gt; 무슨말이지..?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅Prior to version 0.6.9 data location for reference-type arguments was limited to&amp;nbsp;calldata&amp;nbsp;in external functions,&amp;nbsp;memory&amp;nbsp;in public functions and either&amp;nbsp;memory&amp;nbsp;or&amp;nbsp;storage&amp;nbsp;in internal and private ones. Now&amp;nbsp;memory&amp;nbsp;and&amp;nbsp;calldata&amp;nbsp;are allowed in all functions regardless of their visibility.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;옛날엔 콜데이터와 메모리, 스토리지의 사용처가 엄격하게 제한되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제는 콜데이터와 메모리를 모든 visibility 상관없이 모든 펑션에서 쓸수있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;✅Prior to version 0.5.0 the data location could be omitted, and would default to different locations depending on the kind of variable, function type, etc., but all complex types must now give an explicit data location.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;옛날엔 데이터 로케이션 지정을 안해도 됐다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;변수 종류/ 펑션 타입따라 기본 로케이션이 있었기 때문이었음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;그러나 모든 컴플렉스타입은 data location 을 꼭 지정해야함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;Complex types, i.e. types which do not always fit into 256 bits have to be handled more carefully than the value-types we have already seen.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;솔리디티 기본 데이터타입(bool, integer, comparison 이런거..) 말고&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Arrays&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Structs&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Mapping&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이런거의 경우 꼭 지정하라는말임&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 위치와 assignment(배치)행위&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 위치설정은 -데이터의 지속성, -할당의 의미 와 관계가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Assignments between&amp;nbsp;storage&amp;nbsp;and&amp;nbsp;memory&amp;nbsp;(or from&amp;nbsp;calldata) always create an independent copy.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Assignments from&amp;nbsp;memory&amp;nbsp;to&amp;nbsp;memory&amp;nbsp;only create references. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;This means that changes to one memory variable are also visible in all other memory variables &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;that refer to the same data.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Assignments from&amp;nbsp;storage&amp;nbsp;to a&amp;nbsp;&lt;b&gt;local&lt;/b&gt;&amp;nbsp;storage variable also only assign a reference.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;All other assignments to&amp;nbsp;storage&amp;nbsp;always copy. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Examples for this case are assignments to state variables or &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;to members of local variables of storage struct type, even if the local variable itself is just a reference.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전역변수는 무조건 스토리지에 저장됨. 데이터 로케이션 생략 가능&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;633&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TqITK/btrxqcakHzG/jf6L6vFrwD9cEscr3gYPT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TqITK/btrxqcakHzG/jf6L6vFrwD9cEscr3gYPT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TqITK/btrxqcakHzG/jf6L6vFrwD9cEscr3gYPT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTqITK%2FbtrxqcakHzG%2Fjf6L6vFrwD9cEscr3gYPT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;769&quot; height=&quot;633&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;633&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Assignments between&amp;nbsp;storage&amp;nbsp;and&amp;nbsp;memory&amp;nbsp;(or from&amp;nbsp;calldata) always create an independent copy.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스토리지-메모리(콜데이터)간 배치는 무조건 독립된 카피를 야기한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;-스토리지데이터 x= 메모리어레이 줄에서 어레이의 카피가 일어남&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Assignments from&amp;nbsp;memory&amp;nbsp;to&amp;nbsp;memory&amp;nbsp;only create references.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;This means that changes to one memory variable are also visible in all other memory variables&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;that refer to the same data.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메모리-메모리간 assignment는 레퍼런스만 만든다. (포인터를 지정해서 메모리 참조만 한다는 뜻인듯)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 한쪽 메모리할당된 값을 변경하면 다른쪽에서도 변경된 값을 볼수있음&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;- 예시가 좀 이상함.. 메모리- 메모리 간이라고 해놓고 예시는 스토리지- 스토리지간임&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp;스토리지에 저장된 x와 스토리지에 저장된 y 를같다고 assign 하면 포인터로 가리키게됨&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;- 예시로 y를 pop하든, x를 del하든 상호 값이 동기화됨을 보여줌&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;-스토리지-스토리지 간 assignment도 레퍼런스만 만드나봄..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Assignments from&amp;nbsp;storage&amp;nbsp;to a&amp;nbsp;&lt;b&gt;local&lt;/b&gt;&amp;nbsp;storage variable also only assign a reference.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스토리지 - 로컬스토리지간 어사인먼트도 포인터만만듬&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;-functiong g 얘기인듯&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;-&lt;a style=&quot;color: #000000;&quot; href=&quot;https://ethereum.stackexchange.com/questions/24937/local-storage-variable&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;local storage variable&lt;/a&gt; is a variable defined inside a function. (The scope of the variable is limited to the function)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;All other assignments to&amp;nbsp;storage&amp;nbsp;always copy.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Examples for this case are assignments to state variables or&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;to members of local variables of storage struct type, even if the local variable itself is just a reference.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;다른 경우의 storage 어사인먼트는 무조건 카피를 발생시킨다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;이 경우 로컬 변수 자체가 참조에 불과하더라도 상태 변수 또는 스토리지 구조 유형의 로컬 변수 멤버에 대한 할당이 해당됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://eattheblocks.com/graph-memory-locations-in-solidity/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2019자료 확인필요&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;472&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOKinK/btrxlqf8Ywc/1bolt3as8JNEKx6iQAW9M1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOKinK/btrxlqf8Ywc/1bolt3as8JNEKx6iQAW9M1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOKinK/btrxlqf8Ywc/1bolt3as8JNEKx6iQAW9M1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOKinK%2Fbtrxlqf8Ywc%2F1bolt3as8JNEKx6iQAW9M1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;472&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;472&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-darkreader-inline-bgcolor=&quot;&quot; data-darkreader-inline-color=&quot;&quot;&gt;어렵넹&lt;/span&gt;&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/106</guid>
      <comments>https://realapril.tistory.com/106#entry106comment</comments>
      <pubDate>Sun, 27 Mar 2022 03:57:44 +0900</pubDate>
    </item>
    <item>
      <title>Events</title>
      <link>https://realapril.tistory.com/105</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 이벤트 내뿜기(Emitting events)&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 실행하기, 부르기인가 싶었는데 그건 invoke임..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2단계가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 우선 이벤트를 선언한다&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;event ExampleEvent(uint _exampleArgument);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- function 바디 안에서 선언한 이벤트를 emit한다.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;function exampleFunction() external {
    emit ExampleEvent(5);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;emit를 한 후에 이벤트를 invoke할수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; &lt;/b&gt;이벤트는 주로 어퍼카멜케이스를 쓰고, 펑션은 주로 로워카멜케이스를 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 naming convention (작명관례)라한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트를 emit한 컨트랙트를 &lt;span style=&quot;background-color: #12151e; color: #f9f9f9;&quot;&gt;eth_getLogs&lt;/span&gt;&amp;nbsp; 를 통해 로그를 찍으면&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;469&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caMDcp/btrv11UtWaX/Pcka9nlJkEUhACQgeOpE6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caMDcp/btrv11UtWaX/Pcka9nlJkEUhACQgeOpE6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caMDcp/btrv11UtWaX/Pcka9nlJkEUhACQgeOpE6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaMDcp%2Fbtrv11UtWaX%2FPcka9nlJkEUhACQgeOpE6k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;497&quot; height=&quot;469&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;469&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 값을 리턴받는데, 데이터와 토픽에대해 논해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DATA&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;만약 주소 하나를 넣어서 이벤트를 선언, emit해보자. 그러면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;463&quot; data-origin-height=&quot;44&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzbgpI/btrvUB4JC77/lDBpMVwKNnaIYVb4Edak8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzbgpI/btrvUB4JC77/lDBpMVwKNnaIYVb4Edak8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzbgpI/btrvUB4JC77/lDBpMVwKNnaIYVb4Edak8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzbgpI%2FbtrvUB4JC77%2FlDBpMVwKNnaIYVb4Edak8K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;463&quot; height=&quot;44&quot; data-origin-width=&quot;463&quot; data-origin-height=&quot;44&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 emit하는 부분은 이런 형태가되는데, 이 주소가 data안에 실제로 들어가있는 것을 볼수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TOPIC&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트는 보통 최소 1개의 토픽을 가지는데, 보통 이벤트 시그네쳐 해쉬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Deployed(address)의 Keccak-256해시값은 f40f...인데 토픽안에 그 값이 들어가있는것을 볼수있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #12151e; color: #f9f9f9;&quot;&gt;anonymous&lt;/span&gt; 키워드를 넣으면 익명이벤트를 만들수도있고, 가스도 세이브되지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트간 분간이 힘들어짐.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;multiple-arguments&quot; data-ke-size=&quot;size26&quot;&gt;2 Multiple Arguments&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;펑션처럼 이벤트에도 여러개의 arguments 를 넣을수있다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #626466;&quot;&gt;require(msg.sender&amp;nbsp;==&amp;nbsp;owner);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지정된조건이 없으면 종료됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;indexed&quot; data-ke-size=&quot;size26&quot;&gt;3. Indexed&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 arguments에 &lt;span style=&quot;background-color: #12151e; color: #f9f9f9;&quot;&gt;indexed&lt;/span&gt;&amp;nbsp; 키워드를 넣으면 필터링이 쉬워진다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;event HighScore(address indexed player);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스 디테일 읽어도이해가안감&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어드레스부터 다시 돌아야할것같음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsdZ3y/btrvZ21lU4u/kxSJFky0NYZb6oJXeYNmyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsdZ3y/btrvZ21lU4u/kxSJFky0NYZb6oJXeYNmyk/img.png&quot; data-alt=&quot;다했지만 address부터 다시해야할듯&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsdZ3y/btrvZ21lU4u/kxSJFky0NYZb6oJXeYNmyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsdZ3y%2FbtrvZ21lU4u%2FkxSJFky0NYZb6oJXeYNmyk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;927&quot; height=&quot;568&quot; data-origin-width=&quot;927&quot; data-origin-height=&quot;568&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다했지만 address부터 다시해야할듯&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/105</guid>
      <comments>https://realapril.tistory.com/105#entry105comment</comments>
      <pubDate>Tue, 15 Mar 2022 02:37:00 +0900</pubDate>
    </item>
    <item>
      <title>Contract to Contract</title>
      <link>https://realapril.tistory.com/104</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;체인샷 기본강의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 다른 스마트컨트랙을 부르는 법을 배운다&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Enum&lt;/h3&gt;
&lt;pre id=&quot;code_1647167438938&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract Player {
	enum Directions { Up, Down, Left, Right }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;pure: function is isolated, does not read from anything outside itself and promises not to modify contract state.&lt;/li&gt;
&lt;li&gt;view: function can read contract state but promises not to modify contract state.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뷰도 컨트랙트의 데이터를 바꾸지 않는다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/104</guid>
      <comments>https://realapril.tistory.com/104#entry104comment</comments>
      <pubDate>Tue, 15 Mar 2022 00:08:25 +0900</pubDate>
    </item>
    <item>
      <title>2. Mint your own NFT collection and ship a Web3 app</title>
      <link>https://realapril.tistory.com/99</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://app.buildspace.so/projects/CO961ddb5f-f428-4608-9949-a9a2f461eb3f&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://app.buildspace.so/projects/CO961ddb5f-f428-4608-9949-a9a2f461eb3f&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1645068943043&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;buildspace&quot; data-og-description=&quot;Start building cool web3 projects, earn NFTs, access secret work opportunities in crypto.&quot; data-og-host=&quot;buildspace.so&quot; data-og-source-url=&quot;https://app.buildspace.so/projects/CO961ddb5f-f428-4608-9949-a9a2f461eb3f&quot; data-og-url=&quot;https://buildspace.so/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/spyHG/hyNrxnZqoY/2Y27OHeBajNx17lFJWNKzK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/RLyhp/hyNqu0IGqZ/iFHxeuCKCVhsR5ezyfnhQ0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512&quot;&gt;&lt;a href=&quot;https://app.buildspace.so/projects/CO961ddb5f-f428-4608-9949-a9a2f461eb3f&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://app.buildspace.so/projects/CO961ddb5f-f428-4608-9949-a9a2f461eb3f&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/spyHG/hyNrxnZqoY/2Y27OHeBajNx17lFJWNKzK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/RLyhp/hyNqu0IGqZ/iFHxeuCKCVhsR5ezyfnhQ0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;buildspace&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Start building cool web3 projects, earn NFTs, access secret work opportunities in crypto.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;buildspace.so&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메마 지갑 연결, 트젝, 펀딩등을 해보았으니 nft민팅 차례이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이과제는 3단계로 이루어졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. NFT 로직관련 스마트 컨트랙트 짜기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 스마트컨트랙트 deploy&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 프론트에 컨트랙트 연결하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제는 &lt;a href=&quot;https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;오픈제플린 erc721&lt;/a&gt;을 사용한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 요새는 &lt;a href=&quot;https://github.com/chiru-labs/ERC721A/blob/main/contracts/ERC721A.sol&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;아주키가 만든 erc721a&lt;/a&gt;를 사용하는게 대세&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Solidity 개념&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;상태변수 (State Variable)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;상태 변수&lt;/b&gt;는 DB안에 있는 데이터처럼, 컨트랙트 저장소(이더리움 블록체인)에 영구적으로 저장되는 변수를 의미한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1645089355737&quot; class=&quot;angelscript&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pragma solidity ^0.4.19;

contract ZombieFactory {

	uint a = 1;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tokenUri 는 &lt;b&gt;links&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;to a JSON file called the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;metadata&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.opensea.io/docs/metadata-standards&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;오픈씨 기준&lt;/a&gt;을 맞출것&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;785&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNOflB/btrtBPphj5X/yKgK1j2Z5Xrh99m7vEqgl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNOflB/btrtBPphj5X/yKgK1j2Z5Xrh99m7vEqgl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNOflB/btrtBPphj5X/yKgK1j2Z5Xrh99m7vEqgl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNOflB%2FbtrtBPphj5X%2FyKgK1j2Z5Xrh99m7vEqgl1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;785&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;785&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨트랙/오픈씨/레리블 테스트 조회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://rinkeby.etherscan.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://rinkeby.etherscan.io/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://testnets.opensea.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://testnets.opensea.io/&lt;/a&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Head to&lt;span&gt;&amp;nbsp;&lt;/span&gt;rinkeby.rarible.com.&lt;/li&gt;
&lt;li&gt;Create this url:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://rinkeby.rarible.com/token/INSERT_DEPLOY_CONTRACT_ADDRESS_HERE:INSERT_TOKEN_ID_HERE.&quot;&gt;https://rinkeby.rarible.com/token/INSERT_DEPLOY_CONTRACT_ADDRESS_HERE:INSERT_TOKEN_ID_HERE.&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;json 바로 디코딩해서 nft 보여주는사이트&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://nftpreview.0xdev.codes/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://nftpreview.0xdev.codes/&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NFT데이터 저장법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. url - 쿨캣이 이렇게하지만 json/이미지 서버에 문제가 생기면 내려감&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. on chain - Loot가 이렇게함. 이더리움체인이 사는한 영원하나 저용량만 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;온체인시 SVG를 사용한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;json 데이터는 링크 대신 base64 인코딩을한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1645112027067&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;data:application/json;base64,베이스64인코딩내용

_setTokenURI(newItemId, &quot;data:application/json;base64,ewogICAgIm5hbWUiOiAiRXBpY0xvcmRIYW1idXJnZXIiLAogICAgImRlc2NyaXB0aW9uIjogIkFuIE5GVCBmcm9tIHRoZSBoaWdobHkgYWNjbGFpbWVkIHNxdWFyZSBjb2xsZWN0aW9uIiwKICAgICJpbWFnZSI6ICJkYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LFBITjJaeUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSEJ5WlhObGNuWmxRWE53WldOMFVtRjBhVzg5SW5oTmFXNVpUV2x1SUcxbFpYUWlJSFpwWlhkQ2IzZzlJakFnTUNBek5UQWdNelV3SWo0TkNpQWdJQ0E4YzNSNWJHVStMbUpoYzJVZ2V5Qm1hV3hzT2lCM2FHbDBaVHNnWm05dWRDMW1ZVzFwYkhrNklITmxjbWxtT3lCbWIyNTBMWE5wZW1VNklERTBjSGc3SUgwOEwzTjBlV3hsUGcwS0lDQWdJRHh5WldOMElIZHBaSFJvUFNJeE1EQWxJaUJvWldsbmFIUTlJakV3TUNVaUlHWnBiR3c5SW1Kc1lXTnJJaUF2UGcwS0lDQWdJRHgwWlhoMElIZzlJalV3SlNJZ2VUMGlOVEFsSWlCamJHRnpjejBpWW1GelpTSWdaRzl0YVc1aGJuUXRZbUZ6Wld4cGJtVTlJbTFwWkdSc1pTSWdkR1Y0ZEMxaGJtTm9iM0k5SW0xcFpHUnNaU0krUlhCcFkweHZjbVJJWVcxaWRYSm5aWEk4TDNSbGVIUStEUW84TDNOMlp6ND0iCn0=&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 넣으면됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 랜덤화 하는법&lt;/p&gt;
&lt;pre id=&quot;code_1645113703731&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;random(string(abi.encodePacked(&quot;FIRST_WORD&quot;, Strings.toString(tokenId))));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;The actual string&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;FIRST_WORD&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and a stringified version of the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;tokenId&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;. I combine these two strings using&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;abi.encodePacked&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and then that combined string is what I use as the source of randomness.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;근데 abi.encodePacked(a,b)라는 함수가 진짜 단순해서&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt; b = string(abi.encodePacked(&quot;hello&quot;, &quot; world&quot;));
    // b string: hello world&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이정도라 이걸로안됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ipfs&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.ipfs.io/concepts/what-is-ipfs/#participation&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.ipfs.io/concepts/what-is-ipfs/#participation&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1645286830886&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;What is IPFS? | IPFS Docs&quot; data-og-description=&quot;What is IPFS? Let's just start with a one-line definition of IPFS: IPFS is a distributed system for storing and accessing files, websites, applications, and data. What does that mean, exactly? Let's say you're doing some research on aardvarks. (Just roll w&quot; data-og-host=&quot;docs.ipfs.io&quot; data-og-source-url=&quot;https://docs.ipfs.io/concepts/what-is-ipfs/#participation&quot; data-og-url=&quot;https://docs.ipfs.io/concepts/what-is-ipfs/#participation&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.ipfs.io/concepts/what-is-ipfs/#participation&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.ipfs.io/concepts/what-is-ipfs/#participation&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;What is IPFS? | IPFS Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What is IPFS? Let's just start with a one-line definition of IPFS: IPFS is a distributed system for storing and accessing files, websites, applications, and data. What does that mean, exactly? Let's say you're doing some research on aardvarks. (Just roll w&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.ipfs.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;events (솔리디티)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.soliditylang.org/en/v0.4.21/contracts.html#events&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.soliditylang.org/en/v0.4.21/contracts.html#events&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1645286842638&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Contracts &amp;mdash; Solidity 0.4.21 documentation&quot; data-og-description=&quot;Docs &amp;raquo; Solidity in Depth &amp;raquo; Contracts Edit on GitHub Contracts Contracts in Solidity are similar to classes in object-oriented languages. They contain persistent data in state variables and functions that can modify these variables. Calling a function on &quot; data-og-host=&quot;docs.soliditylang.org&quot; data-og-source-url=&quot;https://docs.soliditylang.org/en/v0.4.21/contracts.html#events&quot; data-og-url=&quot;https://docs.soliditylang.org/en/v0.4.21/contracts.html#events&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.soliditylang.org/en/v0.4.21/contracts.html#events&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.soliditylang.org/en/v0.4.21/contracts.html#events&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Contracts &amp;mdash; Solidity 0.4.21 documentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Docs &amp;raquo; Solidity in Depth &amp;raquo; Contracts Edit on GitHub Contracts Contracts in Solidity are similar to classes in object-oriented languages. They contain persistent data in state variables and functions that can modify these variables. Calling a function on&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.soliditylang.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ethereum.org/en/developers/docs/gas/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ethereum.org/en/developers/docs/gas/&lt;/a&gt;&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/99</guid>
      <comments>https://realapril.tistory.com/99#entry99comment</comments>
      <pubDate>Sun, 20 Feb 2022 01:06:45 +0900</pubDate>
    </item>
    <item>
      <title>1. Buildspace : Intro to web3 -- build a web3 version of Twitter:</title>
      <link>https://realapril.tistory.com/98</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://app.buildspace.so/projects/CO02cf0f1c-f996-4f50-9669-cf945ca3fb0b&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://app.buildspace.so/projects/CO02cf0f1c-f996-4f50-9669-cf945ca3fb0b&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644826369755&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;buildspace&quot; data-og-description=&quot;Start building cool web3 projects, earn NFTs, access secret work opportunities in crypto.&quot; data-og-host=&quot;buildspace.so&quot; data-og-source-url=&quot;https://app.buildspace.so/projects/CO02cf0f1c-f996-4f50-9669-cf945ca3fb0b&quot; data-og-url=&quot;https://buildspace.so/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/qQBZ4/hyNqyGOrqm/8Ma0QaQ8uXjQ4f1UPWKJU0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bspKyh/hyNqu5tUv1/3k24sAgJhCxD2jNsbkCyk0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512&quot;&gt;&lt;a href=&quot;https://app.buildspace.so/projects/CO02cf0f1c-f996-4f50-9669-cf945ca3fb0b&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://app.buildspace.so/projects/CO02cf0f1c-f996-4f50-9669-cf945ca3fb0b&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/qQBZ4/hyNqyGOrqm/8Ma0QaQ8uXjQ4f1UPWKJU0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bspKyh/hyNqu5tUv1/3k24sAgJhCxD2jNsbkCyk0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;buildspace&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Start building cool web3 projects, earn NFTs, access secret work opportunities in crypto.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;buildspace.so&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코스는 web3 페이지를 만든다. 그런데 그냥 만드는게 아니고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1)이더리움 컨트랙트를 작성/ 테스트하고(run)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2)컨트랙트를 온체인에 배포하고(deploy)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3)프론트만들기- 아까 배포한 온체인을 적용해서 프론트만들기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 구조로 이루어져있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;이렇게 웹3 앱과, 이더리움 스마트컨트랙트를 배포하는 절차를&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;&lt;b&gt;Shipping&lt;/b&gt;이라고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;(1)스마트컨트랙 작성: 서버코드 짜는것과 비슷하게 로직을 짠다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;(2)컨트랙트 온체인에 배포: 원칙적으로는 모두가 배포된 스마트컨트랙에 접속하고, run할수 있게됨.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;(3)클라 웹사이트만들기: 실제로 유저들이 활동하고 스마트컨트랙과 상호작용하는 단&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;강의를 따라 렛츠고&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;필요한 툴:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;Hardhat, VSCode, replit (레플릿 진짜 편하다 진짜!! 코테 공부할때도 편했는데 js는 배포까지 해줌)&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;1. Hardhat&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;local Ethereum network를 쉽게 가동(spin up)하게 도와줌&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;-로컬 이더리움 네트워크 돌릴때(run) 씀&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;-테스트넷 이더리움도 줌&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;-테스트 어카운트도 줌&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;-테스트넷 배포도 도와줌(deploy)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jbzang2000.medium.com/solidity-hardhat-%EB%8F%84%EC%9E%85-%ED%9B%84%EA%B8%B0-5a6174612a9&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;디테일한 장점 (로그도 쓰게 도와줌)&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 npx hardhat run scripts/run.js&amp;nbsp; 돌리면 자동으로 모르는 지갑이 뭔가 실행해줄건데 그게 다 하드햇 계정임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #2d2d2d; color: #f8f8f2;&quot;&gt;hre.&lt;/span&gt;&lt;span style=&quot;background-color: #2d2d2d; color: #f8f8f2;&quot;&gt;ethers&lt;/span&gt;&lt;span style=&quot;background-color: #2d2d2d; color: #f8f8f2;&quot;&gt;.&lt;/span&gt; 계열 코드도 다 하드햇에서지원함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파일시 hre&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.VSCode&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파일/빌드/디플로이는 하드햇으로해도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 편집기가 필요하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3.Replit&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트 편집/배포 도와줌 그저 갓갓&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.Alchemy&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;gives us a simple way to deploy to the real Ethereum blockchain.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292e;&quot;&gt;hardhat.config.js 에 알케미 API URL과 배포할 지갑 프라이빗키를 제공해야함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 이더스캔, 테스트넷&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://rinkeby.etherscan.io/&quot;&gt;https://rinkeby.etherscan.io/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 이더스캔에서 테스트넷으로 바꿔도 잘 검색이안되는데 아예여기서 하면 잘됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 하는것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-프론트에 메마 연결확인 및 연결&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-컨트랙트 Deploy시 프론트 연결단 변경&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp; contractAddress&amp;nbsp;in&amp;nbsp;App.js바꾸기&lt;/li&gt;
&lt;li&gt;&amp;nbsp; ABI 변경 : artifacts 파일의 json 파일 복사해서 replit의 src/utils/WavePortal.json에 붙여넣기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-컨트랙트에 데이터 읽기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-컨트랙트에 데이터 쓰기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-컨트랙트에 funding&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-돈보내기(트랜젝션)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-랜덤 만들기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-쿨타임 만들기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다 완성된 예제 코드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gist.github.com/adilanchian/93fbd2e06b3b5d3acb99b5723cebd925&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gist.github.com/adilanchian/93fbd2e06b3b5d3acb99b5723cebd925&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;솔리디티 개념&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://caileb.tistory.com/137&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;constructor&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;emit&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;require&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;js 개념&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useEffect&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체코드&lt;/p&gt;
&lt;script src=&quot;https://gist.github.com/realapril/55c57dd517719dc6f19dac99257af6b6.js&quot;&gt;&lt;/script&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/98</guid>
      <comments>https://realapril.tistory.com/98#entry98comment</comments>
      <pubDate>Tue, 15 Feb 2022 00:39:30 +0900</pubDate>
    </item>
    <item>
      <title>0. Buildspace 로 솔리디티 공부하기</title>
      <link>https://realapril.tistory.com/97</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;전엔 크립토 좀비를 했는데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개념을 세세하고 꼼꼼하게 (정석이니까) 설명해서 좋은 교육자료였지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 빌드하지 않고 웹에서 예제를 돌려보는 정도여서 아쉬웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 클래식이어서 탄탄하긴 하지만 최신자료가 아니라서 또 아쉬웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 (1)최신자료이고 (2)환경설정-빌드까지 하는 교육자료가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://buildspace.so/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://buildspace.so/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644399637684&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;buildspace&quot; data-og-description=&quot;Start building cool web3 projects, earn NFTs, access secret work opportunities in crypto.&quot; data-og-host=&quot;buildspace.so&quot; data-og-source-url=&quot;https://buildspace.so/&quot; data-og-url=&quot;https://buildspace.so/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bRYcR9/hyNmAywy7W/LyIs8iaXqYKwN0n9wY8jvK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/6Kr6D/hyNmL7TmTk/QyUtErmIOqaQEMId84S5I0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512&quot;&gt;&lt;a href=&quot;https://buildspace.so/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://buildspace.so/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bRYcR9/hyNmAywy7W/LyIs8iaXqYKwN0n9wY8jvK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/6Kr6D/hyNmL7TmTk/QyUtErmIOqaQEMId84S5I0/img.png?width=1024&amp;amp;height=512&amp;amp;face=0_0_1024_512');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;buildspace&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Start building cool web3 projects, earn NFTs, access secret work opportunities in crypto.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;buildspace.so&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교육프로그램치곤 진짜 독특하게 디스코드로 바로 연결이되고&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;662&quot; data-origin-height=&quot;705&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNtXt3/btrsY8vDzfd/nNqVmZUIMc5wtlhGQ6cH30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNtXt3/btrsY8vDzfd/nNqVmZUIMc5wtlhGQ6cH30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNtXt3/btrsY8vDzfd/nNqVmZUIMc5wtlhGQ6cH30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNtXt3%2FbtrsY8vDzfd%2FnNqVmZUIMc5wtlhGQ6cH30%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;662&quot; height=&quot;705&quot; data-origin-width=&quot;662&quot; data-origin-height=&quot;705&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커리큘럼이 디코에 떠있음..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거 5개를 제한기간내에 다 수료하면 nft도 줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 교육 사이트에 가입할때 메마주소랑 이메일주소 둘다 입력해야함&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;face&quot; data-emoticon-name=&quot;071&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/face/large/071.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/face/large/071.png&quot; width=&quot;80&quot; /&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 시작 렛츠고 렛츠고&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/97</guid>
      <comments>https://realapril.tistory.com/97#entry97comment</comments>
      <pubDate>Wed, 9 Feb 2022 22:58:51 +0900</pubDate>
    </item>
    <item>
      <title>LV.1 crypto zombies - 6 ERC721 &amp;amp; Crypto-Collectibles</title>
      <link>https://realapril.tistory.com/96</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;솔리디티에서는 프론트와 연결하는 라이브러리를제공한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그걸 Web3 Provider.라고함(Web3.js안에 있음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1)Web3 Provider&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ethereum&amp;nbsp;is&amp;nbsp;made&amp;nbsp;up&amp;nbsp;of&amp;nbsp;nodes&amp;nbsp;that&amp;nbsp;all&amp;nbsp;share&amp;nbsp;a&amp;nbsp;copy&amp;nbsp;of&amp;nbsp;the&amp;nbsp;same&amp;nbsp;data.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Setting&amp;nbsp;a&amp;nbsp;Web3&amp;nbsp;Provider&amp;nbsp;in&amp;nbsp;Web3.js&amp;nbsp;tells&amp;nbsp;our&amp;nbsp;code&amp;nbsp;which&amp;nbsp;node&amp;nbsp;we&amp;nbsp;should&amp;nbsp;be&amp;nbsp;talking&amp;nbsp;to&amp;nbsp;handle&amp;nbsp;our&amp;nbsp;reads&amp;nbsp;and&amp;nbsp;writes.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;It's kind of like setting the URL of the remote web server for your API calls in a traditional web app.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오.. 어느 노드에 연결할지 직접 고를수 있다고합니다.&lt;br /&gt;&lt;br /&gt;You&amp;nbsp;could&amp;nbsp;host&amp;nbsp;your&amp;nbsp;own&amp;nbsp;Ethereum&amp;nbsp;node&amp;nbsp;as&amp;nbsp;a&amp;nbsp;provider.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;However, there's a third party service that makes your life easier so you don't need to&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;maintain your own Ethereum node in order to provide a DApp for your users &amp;mdash; Infura. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디앱을 만든다고 이더리움 노드를 채굴하진 않습니다. Infura가 노드 연결을 도와줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Infura &lt;br /&gt;Infura&amp;nbsp;is&amp;nbsp;a&amp;nbsp;service&amp;nbsp;that&amp;nbsp;maintains&amp;nbsp;a&amp;nbsp;set&amp;nbsp;of&amp;nbsp;Ethereum&amp;nbsp;nodes&amp;nbsp;with&amp;nbsp;a&amp;nbsp;caching&amp;nbsp;layer&amp;nbsp;for&amp;nbsp;fast&amp;nbsp;reads,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;which&amp;nbsp;you&amp;nbsp;can&amp;nbsp;access&amp;nbsp;for&amp;nbsp;free&amp;nbsp;through&amp;nbsp;their&amp;nbsp;API.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Using&amp;nbsp;Infura&amp;nbsp;as&amp;nbsp;a&amp;nbsp;provider,&amp;nbsp;you&amp;nbsp;can&amp;nbsp;reliably&amp;nbsp;send&amp;nbsp;and&amp;nbsp;receive&amp;nbsp;messages&amp;nbsp;to/from&amp;nbsp;the&amp;nbsp;Ethereum&amp;nbsp;blockchain&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;without&amp;nbsp;needing&amp;nbsp;to&amp;nbsp;set&amp;nbsp;up&amp;nbsp;and&amp;nbsp;maintain&amp;nbsp;your&amp;nbsp;own&amp;nbsp;node. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;infura는 노드에 접속하고 캐싱까지 제공합니다. 대박..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;var&amp;nbsp;web3&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Web3(new&amp;nbsp;Web3.providers.WebsocketProvider(&quot;wss://mainnet.infura.io/ws&quot;));&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹소켓으로 연결하는군요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 디앱은 동시에 여러사람이 사용하고, 읽기랑 쓰기가 동시에 일어나므로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유저가 프라이빗키로 트랜젝션에 사인을 해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Note: Ethereum (and blockchains in general) use a public / private key pair to digitally sign transactions.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;If I change some data on the blockchain, I can prove via my public key that I was the one who signed it &amp;mdash;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;but since no one knows my private key, no one can forge a transaction for me.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 프라이빗키를 관리하는게 메타마스크같은 지갑임.&lt;br /&gt;&lt;br /&gt;Metamask &lt;br /&gt;Metamask is a browser extension for Chrome and Firefox that lets users securely manage their&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ethereum accounts and private keys, and use these accounts to interact with websites that are using Web3.js.&lt;br /&gt;&lt;br /&gt;Note:&amp;nbsp;Metamask&amp;nbsp;uses&amp;nbsp;Infura's&amp;nbsp;servers&amp;nbsp;under&amp;nbsp;the&amp;nbsp;hood&amp;nbsp;as&amp;nbsp;a&amp;nbsp;web3&amp;nbsp;provider,&amp;nbsp;just&amp;nbsp;like&amp;nbsp;we&amp;nbsp;did&amp;nbsp;above&amp;nbsp;&amp;mdash;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;but&amp;nbsp;it&amp;nbsp;also&amp;nbsp;gives&amp;nbsp;the&amp;nbsp;user&amp;nbsp;the&amp;nbsp;option&amp;nbsp;to&amp;nbsp;choose&amp;nbsp;their&amp;nbsp;own&amp;nbsp;web3&amp;nbsp;provider.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;So&amp;nbsp;by&amp;nbsp;using&amp;nbsp;Metamask's&amp;nbsp;web3&amp;nbsp;provider,&amp;nbsp;you're&amp;nbsp;giving&amp;nbsp;the&amp;nbsp;user&amp;nbsp;a&amp;nbsp;choice,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;and&amp;nbsp;it's&amp;nbsp;one&amp;nbsp;less&amp;nbsp;thing&amp;nbsp;you&amp;nbsp;have&amp;nbsp;to&amp;nbsp;worry&amp;nbsp;about&amp;nbsp;in&amp;nbsp;your&amp;nbsp;app. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹3프로바이더 선택권을 준다는게 무슨소리지..? 잘이해안감&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하여튼 지갑이 대부분 web3 js 를 쓰기때문에 넣기 쉽다.&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/96</guid>
      <comments>https://realapril.tistory.com/96#entry96comment</comments>
      <pubDate>Tue, 30 Nov 2021 23:52:21 +0900</pubDate>
    </item>
    <item>
      <title>LV.1 crypto zombies - 5 ERC721 &amp;amp; Crypto-Collectibles</title>
      <link>https://realapril.tistory.com/95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;tokens, the ERC721 standard, and crypto-collectible assets에대해 다룬다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1)Tokens&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A&amp;nbsp;token&amp;nbsp;on&amp;nbsp;Ethereum&amp;nbsp;is&amp;nbsp;basically&amp;nbsp;just&amp;nbsp;a&amp;nbsp;smart&amp;nbsp;contract&amp;nbsp;that&amp;nbsp;follows&amp;nbsp;some&amp;nbsp;common&amp;nbsp;rules&amp;nbsp;&amp;mdash;&amp;nbsp;namely&amp;nbsp;it&amp;nbsp;implements&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a&amp;nbsp;standard&amp;nbsp;set&amp;nbsp;of&amp;nbsp;functions&amp;nbsp;that&amp;nbsp;all&amp;nbsp;other&amp;nbsp;token&amp;nbsp;contracts&amp;nbsp;share,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;such&amp;nbsp;as&amp;nbsp;transferFrom(address&amp;nbsp;_from,&amp;nbsp;address&amp;nbsp;_to,&amp;nbsp;uint256&amp;nbsp;_tokenId)&amp;nbsp;and&amp;nbsp;balanceOf(address&amp;nbsp;_owner).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 erc20 토큰 찍어내는것은 쉬운편이다. 스마트 컨트랙을 따르면 되기때문&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;So&amp;nbsp;basically&amp;nbsp;a&amp;nbsp;token&amp;nbsp;is&amp;nbsp;just&amp;nbsp;a&amp;nbsp;contract&amp;nbsp;that&amp;nbsp;keeps&amp;nbsp;track&amp;nbsp;of&amp;nbsp;who&amp;nbsp;owns&amp;nbsp;how&amp;nbsp;much&amp;nbsp;of&amp;nbsp;that&amp;nbsp;token,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;and&amp;nbsp;some&amp;nbsp;functions&amp;nbsp;so&amp;nbsp;those&amp;nbsp;users&amp;nbsp;can&amp;nbsp;transfer&amp;nbsp;their&amp;nbsp;tokens&amp;nbsp;to&amp;nbsp;other&amp;nbsp;addresses.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;All ERC20 tokens share the same set of functions with the same names, they can all be interacted with in the same ways.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 기존 코인과 달리 코인을 쪼갤수없이 하나의 아이템을 올리고싶다면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 각각의 아이템을 다르게 만들고싶다면?=NFT&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게바로 ERC721토큰이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ERC721&amp;nbsp;tokens&amp;nbsp;are&amp;nbsp;&lt;b&gt;not&amp;nbsp;interchangeable&lt;/b&gt;&amp;nbsp;since&amp;nbsp;each&amp;nbsp;one&amp;nbsp;is&amp;nbsp;assumed&amp;nbsp;to&amp;nbsp;be&amp;nbsp;unique,&amp;nbsp;and&amp;nbsp;are&amp;nbsp;&lt;b&gt;not&amp;nbsp;divisible&lt;/b&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;You&amp;nbsp;can&amp;nbsp;only&amp;nbsp;trade&amp;nbsp;them&amp;nbsp;in&amp;nbsp;whole&amp;nbsp;units,&amp;nbsp;and&amp;nbsp;each&amp;nbsp;one&amp;nbsp;has&amp;nbsp;a&amp;nbsp;unique&amp;nbsp;ID.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1284&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciDdiY/btrmhZGMiSg/Y0NTDBESNkl7vWxqAvjhPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciDdiY/btrmhZGMiSg/Y0NTDBESNkl7vWxqAvjhPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciDdiY/btrmhZGMiSg/Y0NTDBESNkl7vWxqAvjhPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciDdiY%2FbtrmhZGMiSg%2FY0NTDBESNkl7vWxqAvjhPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1284&quot; height=&quot;268&quot; data-origin-width=&quot;1284&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 nft도 트잭을 찍어보면 토큰갯수로 찍힌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1jdc토큰 = 1nft&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2)ERC721&amp;nbsp;Standard,&amp;nbsp;Multiple&amp;nbsp;Inheritance&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1638098566822&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract ERC721 {
  event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
  event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

  function balanceOf(address _owner) external view returns (uint256);
  function ownerOf(uint256 _tokenId) external view returns (address);
  function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
  function approve(address _approved, uint256 _tokenId) external payable;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이만큼 기능을 구현해주면 erc721이라 할수있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부는 개발자가 알아서 개발을 해줘야함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;balanceOf :returns how many tokens that address owns. 주소주인이 가진 nft갯수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ownerOf : takes a token ID (in our case, a Zombie ID), and returns the address of the person who owns it&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;nft 주소로 주인 주소 찾기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;transferFrom:&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;approve:&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이두개는 세트인데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;the&amp;nbsp;token's&amp;nbsp;owner&amp;nbsp;first&amp;nbsp;calls&amp;nbsp;&lt;b&gt;approve&lt;/b&gt;&amp;nbsp;with&amp;nbsp;the&amp;nbsp;address&amp;nbsp;he&amp;nbsp;wants&amp;nbsp;to&amp;nbsp;transfer&amp;nbsp;to,&amp;nbsp;and&amp;nbsp;the&amp;nbsp;_tokenID&amp;nbsp;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The&amp;nbsp;contract&amp;nbsp;then&amp;nbsp;stores&amp;nbsp;who&amp;nbsp;is&amp;nbsp;approved&amp;nbsp;to&amp;nbsp;take&amp;nbsp;a&amp;nbsp;token,&amp;nbsp;usually&amp;nbsp;in&amp;nbsp;a&amp;nbsp;mapping&amp;nbsp;(uint256&amp;nbsp;=&amp;gt;&amp;nbsp;address).&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Then,&amp;nbsp;when&amp;nbsp;the&amp;nbsp;owner&amp;nbsp;or&amp;nbsp;the&amp;nbsp;approved&amp;nbsp;address&amp;nbsp;calls&amp;nbsp;transferFrom,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;the&amp;nbsp;contract&amp;nbsp;checks&amp;nbsp;if&amp;nbsp;that&amp;nbsp;msg.sender&amp;nbsp;is&amp;nbsp;the&amp;nbsp;owner&amp;nbsp;or&amp;nbsp;is&amp;nbsp;approved&amp;nbsp;by&amp;nbsp;the&amp;nbsp;owner&amp;nbsp;to&amp;nbsp;take&amp;nbsp;the&amp;nbsp;token,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;and&amp;nbsp;if&amp;nbsp;so&amp;nbsp;it&amp;nbsp;transfers&amp;nbsp;the&amp;nbsp;token&amp;nbsp;to&amp;nbsp;him.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 transfer은 ERC721.sol의&amp;nbsp; emit Transfer(_from, _to, _tokenId); 통해 이루어짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;approve의 경우 2단계임&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;You, the owner, call&lt;span&gt;&amp;nbsp;&lt;/span&gt;approve&lt;span&gt;&amp;nbsp;&lt;/span&gt;and give it the&lt;span&gt;&amp;nbsp;&lt;/span&gt;_approved&lt;span&gt;&amp;nbsp;&lt;/span&gt;address of the new owner, and the&lt;span&gt;&amp;nbsp;&lt;/span&gt;_tokenId&lt;span&gt;&amp;nbsp;&lt;/span&gt;you want him to take.&lt;/li&gt;
&lt;li&gt;The new owner calls&lt;span&gt;&amp;nbsp;&lt;/span&gt;transferFrom&lt;span&gt;&amp;nbsp;&lt;/span&gt;with the&lt;span&gt;&amp;nbsp;&lt;/span&gt;_tokenId. Next, the contract checks to make sure the new owner has been already approved, and then transfers him the token.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 다 체크하고 실제 어프루브는 ERC721.sol의 emit&amp;nbsp;Approval(msg.sender,&amp;nbsp;_approved,&amp;nbsp;_tokenId);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3) Preventing Overflows&amp;nbsp;and&amp;nbsp;Underflows&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안한거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;such&amp;nbsp;as&amp;nbsp;some&amp;nbsp;extra&amp;nbsp;checks&amp;nbsp;to&amp;nbsp;make&amp;nbsp;sure&amp;nbsp;users&amp;nbsp;don't&amp;nbsp;accidentally&amp;nbsp;transfer&amp;nbsp;their&amp;nbsp;zombies&amp;nbsp;to&amp;nbsp;address&amp;nbsp;0&amp;nbsp;(which&amp;nbsp;is&amp;nbsp;called&amp;nbsp;&quot;burning&quot;&amp;nbsp;a&amp;nbsp;token&amp;nbsp;&amp;mdash;&amp;nbsp;basically&amp;nbsp;it's&amp;nbsp;sent&amp;nbsp;to&amp;nbsp;an&amp;nbsp;address&amp;nbsp;that&amp;nbsp;no&amp;nbsp;one&amp;nbsp;has&amp;nbsp;the&amp;nbsp;private&amp;nbsp;key&amp;nbsp;of,&amp;nbsp;essentially&amp;nbsp;making&amp;nbsp;it&amp;nbsp;unrecoverable).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토큰소각은 찐소각이아니라 없는주소/못쓰는주소로 보내는거였군..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨트랙 보안강화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;uint8 는 십진수 0~255까지저장할수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1638104329662&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;uint8 number = 255;
number++;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 이래버리면 다시 0으로 돌아간다. 이게 overflow&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;underflow는 음수 지정하면 나는 에러.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런걸 검증하는 라이브러리가 SafeMath&lt;/p&gt;
&lt;pre id=&quot;code_1638104475720&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import &quot;./safemath.sol&quot;;

contract ZombieOwnership is ZombieAttack, ERC721 {

  using SafeMath for uint256;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 넣으면 커버됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 ++ -- 대신 .add .sub이런식으로 쓰면 라이브러리 사용가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(4)주석&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The&amp;nbsp;standard&amp;nbsp;in&amp;nbsp;the&amp;nbsp;Solidity&amp;nbsp;community&amp;nbsp;is&amp;nbsp;to&amp;nbsp;use&amp;nbsp;a&amp;nbsp;format&amp;nbsp;called&amp;nbsp;natspec,&amp;nbsp;which&amp;nbsp;looks&amp;nbsp;like&amp;nbsp;this:&lt;/p&gt;
&lt;pre id=&quot;code_1638105371924&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/// @title A contract for basic math operations
/// @author H4XF13LD MORRIS  
/// @notice For now, this contract just adds a multiply function
contract Math {
  /// @notice Multiplies 2 numbers together
  /// @param x the first uint.
  /// @param y the second uint.
  /// @return z the product of (x * y)
  /// @dev This function does not currently check for overflows
  function multiply(uint x, uint y) returns (uint z) {
    // This is just a normal comment, and won't get picked up by natspec
    z = x * y;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@notice&amp;nbsp;explains&amp;nbsp;to&amp;nbsp;a&amp;nbsp;user&amp;nbsp;what&amp;nbsp;the&amp;nbsp;contract&amp;nbsp;/&amp;nbsp;function&amp;nbsp;does.&amp;nbsp;@dev&amp;nbsp;is&amp;nbsp;for&amp;nbsp;explaining&amp;nbsp;extra&amp;nbsp;details&amp;nbsp;to&amp;nbsp;developers.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;all&amp;nbsp;tags&amp;nbsp;are&amp;nbsp;optional.&amp;nbsp;But&amp;nbsp;at&amp;nbsp;the&amp;nbsp;very&amp;nbsp;least,&amp;nbsp;leave&amp;nbsp;a&amp;nbsp;@dev&amp;nbsp;note&amp;nbsp;explaining&amp;nbsp;what&amp;nbsp;each&amp;nbsp;function&amp;nbsp;does.&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/95</guid>
      <comments>https://realapril.tistory.com/95#entry95comment</comments>
      <pubDate>Sun, 28 Nov 2021 22:17:01 +0900</pubDate>
    </item>
    <item>
      <title>LV.1 crypto zombies - 4 Zombie Battle System</title>
      <link>https://realapril.tistory.com/94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;(1)Payable&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;visibility modifiers&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;when&amp;nbsp;and&amp;nbsp;where&amp;nbsp;the&amp;nbsp;function&amp;nbsp;can&amp;nbsp;be&amp;nbsp;called&amp;nbsp;from&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;private: it's only callable from other functions inside the contract;&lt;/li&gt;
&lt;li&gt;internal: like private but can also be called by contracts that inherit from this one&lt;/li&gt;
&lt;li&gt;external: can only be called outside the contract&lt;/li&gt;
&lt;li&gt;public: can be called anywhere, both internally and externally.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;state&amp;nbsp;modifiers&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;how&amp;nbsp;the&amp;nbsp;function&amp;nbsp;interacts&amp;nbsp;with&amp;nbsp;the&amp;nbsp;BlockChain&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;view: running the function, no data will be saved/changed.&lt;/li&gt;
&lt;li&gt;pure: the function not save any data to the blockchain, it also doesn't read any data from the blockchain.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Both&amp;nbsp;of&amp;nbsp;these&amp;nbsp;don't&amp;nbsp;cost&amp;nbsp;any&amp;nbsp;gas&amp;nbsp;to&amp;nbsp;call&amp;nbsp;if&amp;nbsp;they're&amp;nbsp;called&amp;nbsp;externally&amp;nbsp;from&amp;nbsp;outside&amp;nbsp;the&amp;nbsp;contract&amp;nbsp;(but&amp;nbsp;they&amp;nbsp;do&amp;nbsp;cost&amp;nbsp;gas&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if&amp;nbsp;called&amp;nbsp;internally&amp;nbsp;by&amp;nbsp;another&amp;nbsp;function)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;payable&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a&amp;nbsp;special&amp;nbsp;type&amp;nbsp;of&amp;nbsp;function&amp;nbsp;that&amp;nbsp;can&amp;nbsp;receive&amp;nbsp;Ether.&lt;/p&gt;
&lt;pre id=&quot;code_1637981862358&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract OnlineStore {
  function buySomething() external payable {
    // Check to make sure 0.001 ether was sent to the function call:
    require(msg.value == 0.001 ether);
    // If so, some logic to transfer the digital item to the caller of the function:
    transferThing(msg.sender);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;msg.value&amp;nbsp;is&amp;nbsp;a&amp;nbsp;way&amp;nbsp;to&amp;nbsp;see&amp;nbsp;how&amp;nbsp;much&amp;nbsp;Ether&amp;nbsp;was&amp;nbsp;sent&amp;nbsp;to&amp;nbsp;the&amp;nbsp;contract&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;돈전송할땐 무조건 payable 모디파이어를 사용해야함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안그럼reject됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2)Withdraws&lt;/p&gt;
&lt;pre id=&quot;code_1637988613759&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract GetPaid is Ownable {
  function withdraw() external onlyOwner {
    address payable _owner = address(uint160(owner()));
    _owner.transfer(address(this).balance);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Or in a contract with a buyer and a seller, you could save the seller's address in storage, then when someone&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;purchases his item, transfer him the fee paid by the buyer:&lt;span&gt;&amp;nbsp;&lt;/span&gt;seller.transfer(msg.value).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;These are some examples of what makes Ethereum programming really cool &amp;mdash; you can have decentralized&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;marketplaces like this that aren't controlled by anyone.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1,2번 잘 이해잘안가서 다시해봐야할듯..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아님 다른예제를 좀더보거나..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩은 따라칠수있는데 뭘하는건지 잘모르겠음&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3)난수생성하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Random number generation via keccak256 -&amp;gt;보안문제가있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이유&lt;/b&gt;: 컨트랙트상에서 펑션을 부르면 네트워크의 노드들에게 트렌젝션을 broadcast한다. POW에 따라 노드들은 이 브로드캐스트된 트젝들을 모아서 빨리 문제를 풀려고한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 한노드가 문제를 풀면, 다풀었다고 네트워크의 다른 노드들에게 퍼블리시함. 그러면 다른 노드들은 문제풀기를 중단하고 다른 노드가 제출한 트랜젝션이 유효한지만 인증한다. 유효하다고 확인되면 인증하고 다같이 다음 블락의 문제풀기로 넘어감. 근데 이과정이 랜덤번호 만들기를 악용할수 있게되는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들면 동전뒤집기가 있음.&lt;br /&gt;Let's say we had a coin flip contract &amp;mdash; heads you double your money, tails you lose everything.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Let's say it used the above random function to determine heads or tails.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(random &amp;gt;= 50 is heads, random &amp;lt; 50 is tails).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노드를 돌리는 입장에선, 문제를 푼다음 다른노드에 결과를 공유할지 말지 정할수가 있다. 그래서 실패하면 공유하지않고 다시 계산할수있다. 그래서 성공하는값이나오면 다른 노드에 공유하는것이다. 그런다음 다음블록 문제풀기로 넘어갈수가 있다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt;근데 이럴려면 해당노드가 다른 노드보다 빠르게 일을해야 가능한거아닌가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 노드가 재수가없어서 6번씩 false가 나오면 7번 연산해야하는데 그동안 딴노드는 1번만 계산해서 먼저 끝냈다고 퍼블리시할수도있잖아.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라고생각했더니 뒤에 이얘기가나옴ㅋㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Of&amp;nbsp;course,&amp;nbsp;since&amp;nbsp;tens&amp;nbsp;of&amp;nbsp;thousands&amp;nbsp;of&amp;nbsp;Ethereum&amp;nbsp;nodes&amp;nbsp;on&amp;nbsp;the&amp;nbsp;network&amp;nbsp;are&amp;nbsp;competing&amp;nbsp;to&amp;nbsp;solve&amp;nbsp;the&amp;nbsp;next&amp;nbsp;block,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;my&amp;nbsp;odds&amp;nbsp;of&amp;nbsp;solving&amp;nbsp;the&amp;nbsp;next&amp;nbsp;block&amp;nbsp;are&amp;nbsp;extremely&amp;nbsp;low.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;It&amp;nbsp;would&amp;nbsp;take&amp;nbsp;me&amp;nbsp;a&amp;nbsp;lot&amp;nbsp;of&amp;nbsp;time&amp;nbsp;or&amp;nbsp;computing&amp;nbsp;resources&amp;nbsp;to&amp;nbsp;exploit&amp;nbsp;this&amp;nbsp;profitably&amp;nbsp;&amp;mdash;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;but&amp;nbsp;if&amp;nbsp;the&amp;nbsp;reward&amp;nbsp;were&amp;nbsp;high&amp;nbsp;enough&amp;nbsp;(like&amp;nbsp;if&amp;nbsp;I&amp;nbsp;could&amp;nbsp;bet&amp;nbsp;$100,000,000&amp;nbsp;on&amp;nbsp;the&amp;nbsp;coin&amp;nbsp;flip&amp;nbsp;function),&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;it&amp;nbsp;would&amp;nbsp;be&amp;nbsp;worth&amp;nbsp;it&amp;nbsp;for&amp;nbsp;me&amp;nbsp;to&amp;nbsp;attack.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역시 그럴 확률은 적지만, 보상이 클경우 분명 악용을 시도하는 사람이 있을거라는것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨌거나! 해결법:&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;we&amp;nbsp;may&amp;nbsp;cover&amp;nbsp;using&amp;nbsp;oracles&amp;nbsp;(a&amp;nbsp;secure&amp;nbsp;way&amp;nbsp;to&amp;nbsp;pull&amp;nbsp;data&amp;nbsp;in&amp;nbsp;from&amp;nbsp;outside&amp;nbsp;of&amp;nbsp;Ethereum)&amp;nbsp;to&amp;nbsp;generate&amp;nbsp;secure&amp;nbsp;random&amp;nbsp;numbers&amp;nbsp;from&amp;nbsp;outside&amp;nbsp;the&amp;nbsp;blockchain.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하여튼 이더리움체인상에서 난수를 생성하지 말라고..&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(4)refactory&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;require을 modifier로 바꾸기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번챕터는 무난했음&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/94</guid>
      <comments>https://realapril.tistory.com/94#entry94comment</comments>
      <pubDate>Sun, 28 Nov 2021 17:46:52 +0900</pubDate>
    </item>
    <item>
      <title>LV.1 crypto zombies - 3 Advanced Solidity Concepts</title>
      <link>https://realapril.tistory.com/93</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;contract ownership, gas costs, code optimization, and security 등 중요한걸 배운다고한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;궁금했다. 가보자고&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1)Immutability&amp;nbsp;of&amp;nbsp;Contracts&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇지 이더리움에 한번 올리면 못고치지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;after you deploy a contract to Ethereum, it&amp;rsquo;s immutable, which means that it can never be modified or updated again.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;his&amp;nbsp;is&amp;nbsp;one&amp;nbsp;reason&amp;nbsp;security&amp;nbsp;is&amp;nbsp;such&amp;nbsp;a&amp;nbsp;huge&amp;nbsp;concern&amp;nbsp;in&amp;nbsp;Solidity.&amp;nbsp;If&amp;nbsp;there's&amp;nbsp;a&amp;nbsp;flaw&amp;nbsp;in&amp;nbsp;your&amp;nbsp;contract&amp;nbsp;code,&amp;nbsp;there's&amp;nbsp;no&amp;nbsp;way&amp;nbsp;for&amp;nbsp;you&amp;nbsp;to&amp;nbsp;patch&amp;nbsp;it&amp;nbsp;later.&amp;nbsp;You&amp;nbsp;would&amp;nbsp;have&amp;nbsp;to&amp;nbsp;tell&amp;nbsp;your&amp;nbsp;users&amp;nbsp;to&amp;nbsp;start&amp;nbsp;using&amp;nbsp;a&amp;nbsp;different&amp;nbsp;smart&amp;nbsp;contract&amp;nbsp;address&amp;nbsp;that&amp;nbsp;has&amp;nbsp;the&amp;nbsp;fix.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스마트컨트랙을 ㅠ 나중에 ㅠ 바꾸는서비스가 ㅠ 어딨어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한번에 잘해야한다..가 얼마나 불가능한일인지 개발자들은 알것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;For&amp;nbsp;this&amp;nbsp;reason,&amp;nbsp;it&amp;nbsp;often&amp;nbsp;makes&amp;nbsp;sense&amp;nbsp;to&amp;nbsp;have&amp;nbsp;functions&amp;nbsp;that&amp;nbsp;will&amp;nbsp;allow&amp;nbsp;you&amp;nbsp;to&amp;nbsp;update&amp;nbsp;key&amp;nbsp;portions&amp;nbsp;of&amp;nbsp;the&amp;nbsp;DApp.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가능한한 유연하게, 고칠수있게 만들어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;For&amp;nbsp;example,&amp;nbsp;instead&amp;nbsp;of&amp;nbsp;hard&amp;nbsp;coding&amp;nbsp;the&amp;nbsp;CryptoKitties&amp;nbsp;contract&amp;nbsp;address&amp;nbsp;into&amp;nbsp;our&amp;nbsp;DApp,&amp;nbsp;we&amp;nbsp;should&amp;nbsp;probably&amp;nbsp;have&amp;nbsp;a&amp;nbsp;setKittyContractAddress&amp;nbsp;function&amp;nbsp;that&amp;nbsp;lets&amp;nbsp;us&amp;nbsp;change&amp;nbsp;this&amp;nbsp;address&amp;nbsp;in&amp;nbsp;the&amp;nbsp;future&amp;nbsp;in&amp;nbsp;case&amp;nbsp;something&amp;nbsp;happens&amp;nbsp;to&amp;nbsp;the&amp;nbsp;CryptoKitties&amp;nbsp;contract.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2)Ownable&amp;nbsp;Contracts&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ownable&amp;nbsp;&amp;mdash;&amp;nbsp;meaning&amp;nbsp;they&amp;nbsp;have&amp;nbsp;an&amp;nbsp;owner&amp;nbsp;(you)&amp;nbsp;who&amp;nbsp;has&amp;nbsp;special&amp;nbsp;privileges.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;external이어도 내가만든 컨트랙이 아니면 그 함수 가져다 쓸수없게함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OpenZeppelin&amp;nbsp;is&amp;nbsp;a&amp;nbsp;library&amp;nbsp;of&amp;nbsp;secure&amp;nbsp;and&amp;nbsp;community-vetted&amp;nbsp;smart&amp;nbsp;contracts&amp;nbsp;that&amp;nbsp;you&amp;nbsp;can&amp;nbsp;use&amp;nbsp;in&amp;nbsp;your&amp;nbsp;own&amp;nbsp;DApps&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속할때처럼 is Ownable하면 됨&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3)Modifier&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수에&amp;nbsp;붙어서&amp;nbsp;함수에&amp;nbsp;어떤&amp;nbsp;제약을&amp;nbsp;걸어주기도&amp;nbsp;하고&amp;nbsp;부가적인&amp;nbsp;기능을&amp;nbsp;만들어준다.(함수를&amp;nbsp;꾸며준다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;modifier는 함수를 꾸며주는데 꾸며준 다음에 본래 함수를 어디서 실행할지 결정해야 한다. 이 때 이 &amp;lsquo;어디서 실행할 지' 결정해주는 것이&amp;nbsp; _ 이다. (placeholder라고도 함)&lt;/p&gt;
&lt;pre id=&quot;code_1637909347664&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  modifier onlyOwner() {
    require(isOwner());
    _;
  }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제를 보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;require(isOwner()); 를 통해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 컨트랙트의 함수를 실행한 어드레스의 주소(msg.sender)가 이 컨트랙트에 owner라고 정의된 주소와 같느냐를 물어본다. 그 후에 언더스코어 _; 가 등장한다. 이 때 바로 이 언더스코어 부분에서 onlyOwner가 꾸며준 함수가 실행되는 구조로 동작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언제쓰냐:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;100개의 함수가 있는데, 그 100개의 함수들은 나이가 성인인지 아닌지 체크를 해야하는 require가 필요 하다고 가정해보자. &lt;br /&gt;&amp;nbsp;각 함수마다 당연히 require(_age&amp;gt;17, &quot;You are under 18 years old&quot;)를 하나하나 일일히 써야한다. &lt;br /&gt;즉 reqire문을 100 번 써야한다. (100번의반복)&lt;br /&gt;&amp;nbsp;&lt;br /&gt;19세 미만이 아니라 15세 미만으로 나이제한이 바뀌면?&lt;br /&gt;각 함수의 require 마다&amp;nbsp;&amp;nbsp;require(_age&amp;gt;14, &quot;You are under 15 years old&quot;) 라고 고쳐야하는데&lt;br /&gt;100 번이나 고쳐야한다. &lt;br /&gt;&lt;br /&gt;이러한 불편함을 극복하기 위해서&amp;nbsp; Modifier을 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(4)Gas&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그치 뭐할때마다 이더를 가스로 내야하져&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In&amp;nbsp;Solidity,&amp;nbsp;your&amp;nbsp;users&amp;nbsp;have&amp;nbsp;to&amp;nbsp;pay&amp;nbsp;every&amp;nbsp;time&amp;nbsp;they&amp;nbsp;execute&amp;nbsp;a&amp;nbsp;function&amp;nbsp;on&amp;nbsp;your&amp;nbsp;DApp&amp;nbsp;using&amp;nbsp;a&amp;nbsp;currency&amp;nbsp;called&amp;nbsp;gas.&amp;nbsp;Users&amp;nbsp;buy&amp;nbsp;gas&amp;nbsp;with&amp;nbsp;Ether&amp;nbsp;(the&amp;nbsp;currency&amp;nbsp;on&amp;nbsp;Ethereum),&amp;nbsp;so&amp;nbsp;your&amp;nbsp;users&amp;nbsp;have&amp;nbsp;to&amp;nbsp;spend&amp;nbsp;ETH&amp;nbsp;in&amp;nbsp;order&amp;nbsp;to&amp;nbsp;execute&amp;nbsp;functions&amp;nbsp;on&amp;nbsp;your&amp;nbsp;DApp.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;How&amp;nbsp;much&amp;nbsp;gas&amp;nbsp;is&amp;nbsp;required&amp;nbsp;to&amp;nbsp;execute&amp;nbsp;a&amp;nbsp;function&amp;nbsp;depends&amp;nbsp;on&amp;nbsp;how&amp;nbsp;complex&amp;nbsp;that&amp;nbsp;function's&amp;nbsp;logic&amp;nbsp;is.&amp;nbsp;Each&amp;nbsp;individual&amp;nbsp;operation&amp;nbsp;has&amp;nbsp;a&amp;nbsp;gas&amp;nbsp;cost&amp;nbsp;based&amp;nbsp;&lt;b&gt;roughly&amp;nbsp;on&amp;nbsp;how&amp;nbsp;much&amp;nbsp;computing&amp;nbsp;resources&amp;nbsp;will&amp;nbsp;be&amp;nbsp;required&amp;nbsp;to&amp;nbsp;perform&amp;nbsp;that&amp;nbsp;operation&lt;/b&gt;&amp;nbsp;(e.g.&amp;nbsp;writing&amp;nbsp;to&amp;nbsp;storage&amp;nbsp;is&amp;nbsp;much&amp;nbsp;more&amp;nbsp;expensive&amp;nbsp;than&amp;nbsp;adding&amp;nbsp;two&amp;nbsp;integers).&amp;nbsp;&lt;b&gt;The&amp;nbsp;total&amp;nbsp;gas&amp;nbsp;cost&amp;nbsp;of&amp;nbsp;your&amp;nbsp;function&amp;nbsp;is&amp;nbsp;the&amp;nbsp;sum&amp;nbsp;of&amp;nbsp;the&amp;nbsp;gas&amp;nbsp;costs&amp;nbsp;of&amp;nbsp;all&amp;nbsp;its&amp;nbsp;individual&amp;nbsp;operations.&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;Because&amp;nbsp;running&amp;nbsp;functions&amp;nbsp;costs&amp;nbsp;real&amp;nbsp;money&amp;nbsp;for&amp;nbsp;your&amp;nbsp;users,&amp;nbsp;code&amp;nbsp;optimization&amp;nbsp;is&amp;nbsp;much&amp;nbsp;more&amp;nbsp;important&amp;nbsp;in&amp;nbsp;Ethereum&amp;nbsp;than&amp;nbsp;in&amp;nbsp;other&amp;nbsp;programming&amp;nbsp;languages.&amp;nbsp;If&amp;nbsp;your&amp;nbsp;code&amp;nbsp;is&amp;nbsp;sloppy,&amp;nbsp;your&amp;nbsp;users&amp;nbsp;are&amp;nbsp;going&amp;nbsp;to&amp;nbsp;have&amp;nbsp;to&amp;nbsp;pay&amp;nbsp;a&amp;nbsp;premium&amp;nbsp;to&amp;nbsp;execute&amp;nbsp;your&amp;nbsp;functions&amp;nbsp;&amp;mdash;&amp;nbsp;and&amp;nbsp;this&amp;nbsp;could&amp;nbsp;add&amp;nbsp;up&amp;nbsp;to&amp;nbsp;millions&amp;nbsp;of&amp;nbsp;dollars&amp;nbsp;in&amp;nbsp;unnecessary&amp;nbsp;fees&amp;nbsp;across&amp;nbsp;thousands&amp;nbsp;of&amp;nbsp;users.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최적화가 곧 돈이다.. 무써운 세계군요&lt;/p&gt;
&lt;h2 id=&quot;why-is-gas-necessary-&quot; data-ke-size=&quot;size26&quot;&gt;Why is gas necessary?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ethereum is like a big, slow, but extremely secure computer. 이 비유 좋은듯. When you execute a function, every single node on the network needs to run that same function to verify its output &amp;mdash; thousands of nodes verifying every function execution is what makes Ethereum decentralized, and its data immutable and censorship-resistant.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The&amp;nbsp;creators&amp;nbsp;of&amp;nbsp;Ethereum&amp;nbsp;wanted&amp;nbsp;to&amp;nbsp;make&amp;nbsp;sure&amp;nbsp;someone&amp;nbsp;couldn't&amp;nbsp;clog&amp;nbsp;up&amp;nbsp;the&amp;nbsp;network&amp;nbsp;with&amp;nbsp;an&amp;nbsp;infinite&amp;nbsp;loop,&amp;nbsp;or&amp;nbsp;hog&amp;nbsp;all&amp;nbsp;the&amp;nbsp;network&amp;nbsp;resources&amp;nbsp;with&amp;nbsp;really&amp;nbsp;intensive&amp;nbsp;computations.&amp;nbsp;So&amp;nbsp;they&amp;nbsp;made&amp;nbsp;it&amp;nbsp;so&amp;nbsp;transactions&amp;nbsp;aren't&amp;nbsp;free,&amp;nbsp;and&amp;nbsp;users&amp;nbsp;have&amp;nbsp;to&amp;nbsp;pay&amp;nbsp;for&amp;nbsp;computation&amp;nbsp;time&amp;nbsp;as&amp;nbsp;well&amp;nbsp;as&amp;nbsp;storage.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이래서 가스비 폭발할때마다 비탈릭이 욕을 바가지로 먹는거군요..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 기본 uint대신(256)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;uint8, uint16, uint32 쓸수있음 써서최소화 시키라는것임. 완전 몇메가바이트밖에 없던 씨-씨쁠쁠 시절과 똑같은.. 접근이네요..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 헬인게 씨쁠쁠은 나중에 숫자가생각보다 커지면 타입바꾸면되는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔리디티는 바꾸지도못함.. wow&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 황당한거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;You'll&amp;nbsp;also&amp;nbsp;want&amp;nbsp;to&amp;nbsp;cluster&amp;nbsp;identical&amp;nbsp;data&amp;nbsp;types&amp;nbsp;together&amp;nbsp;(i.e.&amp;nbsp;put&amp;nbsp;them&amp;nbsp;next&amp;nbsp;to&amp;nbsp;each&amp;nbsp;other&amp;nbsp;in&amp;nbsp;the&amp;nbsp;struct)&amp;nbsp;so&amp;nbsp;that&amp;nbsp;Solidity&amp;nbsp;can&amp;nbsp;minimize&amp;nbsp;the&amp;nbsp;required&amp;nbsp;storage&amp;nbsp;space.&amp;nbsp;For&amp;nbsp;example,&amp;nbsp;a&amp;nbsp;struct&amp;nbsp;with&amp;nbsp;fields&amp;nbsp;uint&amp;nbsp;c;&amp;nbsp;uint32&amp;nbsp;a;&amp;nbsp;uint32&amp;nbsp;b;&amp;nbsp;will&amp;nbsp;cost&amp;nbsp;less&amp;nbsp;gas&amp;nbsp;than&amp;nbsp;a&amp;nbsp;struct&amp;nbsp;with&amp;nbsp;fields&amp;nbsp;uint32&amp;nbsp;a;&amp;nbsp;uint&amp;nbsp;c;&amp;nbsp;uint32&amp;nbsp;b;&amp;nbsp;because&amp;nbsp;the&amp;nbsp;uint32&amp;nbsp;fields&amp;nbsp;are&amp;nbsp;clustered&amp;nbsp;together.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;???&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건왠지모르겠는데 데이터유형 맞춰야 가스비가 덜든다고함. 솔리디티 최적화 난이도 무엇&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(5)Time Units&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 native unit이 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The&amp;nbsp;variable&amp;nbsp;&lt;b&gt;now&lt;/b&gt;&amp;nbsp;will&amp;nbsp;return&amp;nbsp;the&amp;nbsp;current&amp;nbsp;unix&amp;nbsp;timestamp&amp;nbsp;of&amp;nbsp;the&amp;nbsp;latest&amp;nbsp;block&amp;nbsp;(&lt;u&gt;the&amp;nbsp;number&amp;nbsp;of&amp;nbsp;seconds&amp;nbsp;that&amp;nbsp;have&amp;nbsp;passed&amp;nbsp;since&amp;nbsp;January&amp;nbsp;1st&amp;nbsp;1970&lt;/u&gt;).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Note: Unix time is traditionally stored in a 32-bit number. This will lead to the &quot;Year 2038&quot; problem, when 32-bit unix timestamps will overflow and break a lot of legacy systems. So if we wanted our DApp to keep running 20 years from now, we could use a 64-bit number instead &amp;mdash; but our users would have to spend more gas to use our DApp in the meantime. Design decisions! ㅋㅋ장난하나용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지 시간유닛은 seconds,&amp;nbsp;minutes,&amp;nbsp;hours,&amp;nbsp;days,&amp;nbsp;weeks&amp;nbsp;and&amp;nbsp;years&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(6)Function&amp;nbsp;modifiers&amp;nbsp;with&amp;nbsp;arguments&lt;/p&gt;
&lt;pre id=&quot;code_1637927534525&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// A mapping to store a user's age:
mapping (uint =&amp;gt; uint) public age;

// Modifier that requires this user to be older than a certain age:
modifier olderThan(uint _age, uint _userId) {
  require(age[_userId] &amp;gt;= _age);
  _;
}

// Must be older than 16 to drive a car (in the US, at least).
// We can call the `olderThan` modifier with arguments like so:
function driveCar(uint _userId) public olderThan(16, _userId) {
  // Some function logic
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거 좋아보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Note:&amp;nbsp;calldata&amp;nbsp;is&amp;nbsp;somehow&amp;nbsp;similar&amp;nbsp;to&amp;nbsp;memory,&amp;nbsp;but&amp;nbsp;it's&amp;nbsp;only&amp;nbsp;available&amp;nbsp;to&amp;nbsp;external&amp;nbsp;functions.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;calldata&amp;nbsp;must&amp;nbsp;be&amp;nbsp;used&amp;nbsp;when&amp;nbsp;declaring&amp;nbsp;an&amp;nbsp;external&amp;nbsp;function's&amp;nbsp;dynamic&amp;nbsp;parameters.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(7) View&amp;nbsp;functions&amp;nbsp;don't&amp;nbsp;cost&amp;nbsp;gas&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This&amp;nbsp;is&amp;nbsp;because&amp;nbsp;view&amp;nbsp;functions&amp;nbsp;don't&amp;nbsp;actually&amp;nbsp;change&amp;nbsp;anything&amp;nbsp;on&amp;nbsp;the&amp;nbsp;blockchain&amp;nbsp;&amp;ndash;&amp;nbsp;they&amp;nbsp;only&amp;nbsp;read&amp;nbsp;the&amp;nbsp;data.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(8)Storage is Expensive&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;One of the more expensive operations in Solidity is using storage &amp;mdash; particularly writes.&lt;br /&gt;This&amp;nbsp;is&amp;nbsp;because&amp;nbsp;every&amp;nbsp;time&amp;nbsp;you&amp;nbsp;write&amp;nbsp;or&amp;nbsp;change&amp;nbsp;a&amp;nbsp;piece&amp;nbsp;of&amp;nbsp;data,&amp;nbsp;it&amp;rsquo;s&amp;nbsp;written&amp;nbsp;permanently&amp;nbsp;to&amp;nbsp;the&amp;nbsp;blockchain.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Avoid writing data to storage except when absolutely necessary. Sometimes this involves seemingly inefficient programming logic &amp;mdash; like rebuilding an array in memory every time a function is called instead of simply saving that array in a variable for quick lookups. &lt;br /&gt;&lt;br /&gt;In&amp;nbsp;most&amp;nbsp;programming&amp;nbsp;languages,&amp;nbsp;looping&amp;nbsp;over&amp;nbsp;large&amp;nbsp;data&amp;nbsp;sets&amp;nbsp;is&amp;nbsp;expensive.&amp;nbsp;But&amp;nbsp;in&amp;nbsp;Solidity,&amp;nbsp;&lt;b&gt;this&amp;nbsp;is&amp;nbsp;way&amp;nbsp;cheaper&amp;nbsp;than&amp;nbsp;using&amp;nbsp;storage&amp;nbsp;if&amp;nbsp;it's&amp;nbsp;in&amp;nbsp;an&amp;nbsp;external&amp;nbsp;view&amp;nbsp;function&lt;/b&gt;,&amp;nbsp;since&amp;nbsp;view&amp;nbsp;functions&amp;nbsp;don't&amp;nbsp;cost&amp;nbsp;your&amp;nbsp;users&amp;nbsp;any&amp;nbsp;gas.&amp;nbsp;(And&amp;nbsp;gas&amp;nbsp;costs&amp;nbsp;your&amp;nbsp;users&amp;nbsp;real&amp;nbsp;money!).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쩐지 블록체인 느리더라..... big O를 이기는 &quot;가스비원칙&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 memory를쓰는게 훨싸고, 만약 view안에서 불렀다면 완전 공짜&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;memory arrays must be created with a length argument. They currently cannot be resized like storage arrays can with array.push(),&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(9)Loops&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건그냥 루프문&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/93</guid>
      <comments>https://realapril.tistory.com/93#entry93comment</comments>
      <pubDate>Fri, 26 Nov 2021 21:54:34 +0900</pubDate>
    </item>
    <item>
      <title>LV.1 crypto zombies - 2 Zombies Attack Their Victims</title>
      <link>https://realapril.tistory.com/92</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;생각보다 강의가 길다?&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(1)Mappings&amp;nbsp;and&amp;nbsp;Addresses&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new data types: mapping and address.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이더주소 자체가 데이터타입이라니..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Address&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;an&amp;nbsp;address&amp;nbsp;is&amp;nbsp;owned&amp;nbsp;by&amp;nbsp;a&amp;nbsp;specific&amp;nbsp;user&amp;nbsp;(or&amp;nbsp;a&amp;nbsp;smart&amp;nbsp;contract).&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The&amp;nbsp;Ethereum&amp;nbsp;blockchain&amp;nbsp;is&amp;nbsp;made&amp;nbsp;up&amp;nbsp;of&amp;nbsp;accounts,&amp;nbsp;which&amp;nbsp;you&amp;nbsp;can&amp;nbsp;think&amp;nbsp;of&amp;nbsp;like&amp;nbsp;bank&amp;nbsp;accounts.&amp;nbsp;An&amp;nbsp;account&amp;nbsp;has&amp;nbsp;a&amp;nbsp;balance&amp;nbsp;of&amp;nbsp;Ether&amp;nbsp;(the&amp;nbsp;currency&amp;nbsp;used&amp;nbsp;on&amp;nbsp;the&amp;nbsp;Ethereum&amp;nbsp;blockchain),&amp;nbsp;and&amp;nbsp;you&amp;nbsp;can&amp;nbsp;send&amp;nbsp;and&amp;nbsp;receive&amp;nbsp;Ether&amp;nbsp;payments&amp;nbsp;to&amp;nbsp;other&amp;nbsp;accounts,&amp;nbsp;just&amp;nbsp;like&amp;nbsp;your&amp;nbsp;bank&amp;nbsp;account&amp;nbsp;can&amp;nbsp;wire&amp;nbsp;transfer&amp;nbsp;money&amp;nbsp;to&amp;nbsp;other&amp;nbsp;bank&amp;nbsp;accounts.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mapping&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A mapping is essentially a key-value store for storing and looking up data.&lt;/p&gt;
&lt;pre id=&quot;code_1637845619800&quot; class=&quot;python&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// For a financial app, storing a uint that holds the user's account balance:
mapping (address =&amp;gt; uint) public accountBalance;
// Or could be used to store / lookup usernames based on userId
mapping (uint =&amp;gt; string) userIdToName;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In the first example, the key is an address and the value is a uint, and in the second example the key is a uint and the value a string.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2)Msg.sender&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;there are certain global variables that are available to all functions. One of these is msg.sender, which refers to the&amp;nbsp; address of the person (or smart contract) who called the current function. &lt;br /&gt;&lt;br /&gt;Note:&amp;nbsp;In&amp;nbsp;Solidity,&amp;nbsp;function&amp;nbsp;execution&amp;nbsp;always&amp;nbsp;needs&amp;nbsp;to&amp;nbsp;start&amp;nbsp;with&amp;nbsp;an&amp;nbsp;external&amp;nbsp;caller.&amp;nbsp;A&amp;nbsp;contract&amp;nbsp;will&amp;nbsp;just&amp;nbsp;sit&amp;nbsp;on&amp;nbsp;the&amp;nbsp;blockchain&amp;nbsp;doing&amp;nbsp;nothing&amp;nbsp;until&amp;nbsp;someone&amp;nbsp;calls&amp;nbsp;one&amp;nbsp;of&amp;nbsp;its&amp;nbsp;functions.&amp;nbsp;So&amp;nbsp;there&amp;nbsp;will&amp;nbsp;always&amp;nbsp;be&amp;nbsp;a&amp;nbsp;msg.sender.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3)Require&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if else대신 require을 쓴다..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;the&amp;nbsp;function&amp;nbsp;will&amp;nbsp;throw&amp;nbsp;an&amp;nbsp;error&amp;nbsp;and&amp;nbsp;stop&amp;nbsp;executing&amp;nbsp;if&amp;nbsp;some&amp;nbsp;condition&amp;nbsp;is&amp;nbsp;not&amp;nbsp;true:&lt;/p&gt;
&lt;pre id=&quot;code_1637846487373&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function sayHiToVitalik(string memory _name) public returns (string memory) {
  // Compares if _name equals &quot;Vitalik&quot;. Throws an error and exits if not true.
  // (Side note: Solidity doesn't have native string comparison, so we
  // compare their keccak256 hashes to see if the strings are equal)
  require(keccak256(abi.encodePacked(_name)) == keccak256(abi.encodePacked(&quot;Vitalik&quot;)));
  // If it's true, proceed with the function:
  return &quot;Hi!&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔리디티 스트링 비교없는거 몹시 신박하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비교를위한 암호화..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 참이아니면 뭘리턴한다는거임? 리턴할거없어서 에러날거같은뎅&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(4)Inheritance&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;솔리디티는 예제도 &quot;도지&quot;다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;693&quot; data-origin-height=&quot;331&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dOYegN/btrl9lb0uuL/4wAckxK1rWOKKKwk6Nd0Q1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dOYegN/btrl9lb0uuL/4wAckxK1rWOKKKwk6Nd0Q1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dOYegN/btrl9lb0uuL/4wAckxK1rWOKKKwk6Nd0Q1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdOYegN%2Fbtrl9lb0uuL%2F4wAckxK1rWOKKKwk6Nd0Q1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;693&quot; height=&quot;331&quot; data-origin-width=&quot;693&quot; data-origin-height=&quot;331&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;투더문~~&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(5)Import&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거야뭐.. 설마 파이썬처럼 제가 직접 넣어야할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에디터가 넣어줄거라 굳게믿습니다&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(6)Storage&amp;nbsp;vs&amp;nbsp;Memory&amp;nbsp;(Data&amp;nbsp;location)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In&amp;nbsp;Solidity,&amp;nbsp;there&amp;nbsp;are&amp;nbsp;two&amp;nbsp;locations&amp;nbsp;you&amp;nbsp;can&amp;nbsp;store&amp;nbsp;variables&amp;nbsp;&amp;mdash;&amp;nbsp;in&amp;nbsp;storage&amp;nbsp;and&amp;nbsp;in&amp;nbsp;memory.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Storage&amp;nbsp;refers&amp;nbsp;to&amp;nbsp;variables&amp;nbsp;stored&amp;nbsp;permanently&amp;nbsp;on&amp;nbsp;the&amp;nbsp;blockchain.&amp;nbsp;Memory&amp;nbsp;variables&amp;nbsp;are&amp;nbsp;temporary,&amp;nbsp;and&amp;nbsp;are&amp;nbsp;erased&amp;nbsp;between&amp;nbsp;external&amp;nbsp;function&amp;nbsp;calls&amp;nbsp;to&amp;nbsp;your&amp;nbsp;contract.&amp;nbsp;Think&amp;nbsp;of&amp;nbsp;it&amp;nbsp;like&amp;nbsp;your&amp;nbsp;computer's&amp;nbsp;hard&amp;nbsp;disk&amp;nbsp;vs&amp;nbsp;RAM.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 건드릴필요는없다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Most&amp;nbsp;of&amp;nbsp;the&amp;nbsp;time&amp;nbsp;you&amp;nbsp;don't&amp;nbsp;need&amp;nbsp;to&amp;nbsp;use&amp;nbsp;these&amp;nbsp;keywords&amp;nbsp;because&amp;nbsp;Solidity&amp;nbsp;handles&amp;nbsp;them&amp;nbsp;by&amp;nbsp;default.&amp;nbsp;State&amp;nbsp;variables&amp;nbsp;(variables&amp;nbsp;declared&amp;nbsp;outside&amp;nbsp;of&amp;nbsp;functions)&amp;nbsp;are&amp;nbsp;by&amp;nbsp;default&amp;nbsp;storage&amp;nbsp;and&amp;nbsp;written&amp;nbsp;permanently&amp;nbsp;to&amp;nbsp;the&amp;nbsp;blockchain,&amp;nbsp;while&amp;nbsp;variables&amp;nbsp;declared&amp;nbsp;inside&amp;nbsp;functions&amp;nbsp;are&amp;nbsp;memory&amp;nbsp;and&amp;nbsp;will&amp;nbsp;disappear&amp;nbsp;when&amp;nbsp;the&amp;nbsp;function&amp;nbsp;call&amp;nbsp;ends.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언제 건드리냐면 : structs&amp;nbsp;and&amp;nbsp;arrays&lt;/p&gt;
&lt;pre id=&quot;code_1637851127486&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;contract SandwichFactory {
  struct Sandwich {
    string name;
    string status;
  }

  Sandwich[] sandwiches;

  function eatSandwich(uint _index) public {
    // Sandwich mySandwich = sandwiches[_index];

    // ^ Seems pretty straightforward, but solidity will give you a warning
    // telling you that you should explicitly declare `storage` or `memory` here.

    // So instead, you should declare with the `storage` keyword, like:
    Sandwich storage mySandwich = sandwiches[_index];
    // ...in which case `mySandwich` is a pointer to `sandwiches[_index]`
    // in storage, and...
    mySandwich.status = &quot;Eaten!&quot;;
    // ...this will permanently change `sandwiches[_index]` on the blockchain.

    // If you just want a copy, you can use `memory`:
    Sandwich memory anotherSandwich = sandwiches[_index + 1];
    // ...in which case `anotherSandwich` will simply be a copy of the 
    // data in memory, and...
    anotherSandwich.status = &quot;Eaten!&quot;;
    // ...will just modify the temporary variable and have no effect 
    // on `sandwiches[_index + 1]`. But you can do this:
    sandwiches[_index + 1] = anotherSandwich;
    // ...if you want to copy the changes back into blockchain storage.
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(7)More&amp;nbsp;on&amp;nbsp;Function&amp;nbsp;Visibility&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In addition to public and private, Solidity has two more types of visibility for functions: internal and external. &lt;br /&gt;&lt;br /&gt;internal is the same as private, except that it's also accessible to contracts that inherit from this contract.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;external is similar to public, except that these functions can ONLY be called outside the contract &amp;mdash; they can't be called by other functions inside that contract. We'll talk about why you might want to use external vs public later.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(8)Interacting&amp;nbsp;with&amp;nbsp;other&amp;nbsp;contracts&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오 이런게된다고..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;first&amp;nbsp;we&amp;nbsp;need&amp;nbsp;to&amp;nbsp;define&amp;nbsp;an&amp;nbsp;interface.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공개된 다른플젝 인터페이스 긁어와서 init할때 이더 주소 넣으면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 fav address라고 되어있어서 그 플젝주소넣어야하는지 홀더주소 넣어야하는지 잘모르겠음&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(9)Handling&amp;nbsp;Multiple&amp;nbsp;Return&amp;nbsp;Values&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;난 멀티플리턴되는게 좋더라.. 클래스로 커버안되는 그런게있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/92</guid>
      <comments>https://realapril.tistory.com/92#entry92comment</comments>
      <pubDate>Fri, 26 Nov 2021 01:36:00 +0900</pubDate>
    </item>
    <item>
      <title>LV.1 crypto zombies - 1 Making the Zombie Factory</title>
      <link>https://realapril.tistory.com/91</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;(1) Lesson Overview&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DNA따라 캐릭터 조형이 바뀜을보여줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nft는 실제로 이렇게 조형되서 예제를 이렇게 보여준듯&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;655&quot; data-origin-height=&quot;754&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dTHtxy/btrl56ZerXE/te4kK9Kp39hXqQLwSg22Uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dTHtxy/btrl56ZerXE/te4kK9Kp39hXqQLwSg22Uk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dTHtxy/btrl56ZerXE/te4kK9Kp39hXqQLwSg22Uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdTHtxy%2Fbtrl56ZerXE%2Fte4kK9Kp39hXqQLwSg22Uk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;655&quot; height=&quot;754&quot; data-origin-width=&quot;655&quot; data-origin-height=&quot;754&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(2)&amp;nbsp;Contracts&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Solidity's&amp;nbsp;code&amp;nbsp;is&amp;nbsp;encapsulated&amp;nbsp;in&amp;nbsp;contracts.&amp;nbsp;A&amp;nbsp;contract&amp;nbsp;is&amp;nbsp;the&amp;nbsp;fundamental&amp;nbsp;building&amp;nbsp;block&amp;nbsp;of&amp;nbsp;Ethereum&amp;nbsp;applications&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맞다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 컨트랙만봐도 러그 50퍼는 피할수있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸위해 나는 이 강의를 시작한것이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-Version Pragma&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;All&amp;nbsp;solidity&amp;nbsp;source&amp;nbsp;code&amp;nbsp;should&amp;nbsp;start&amp;nbsp;with&amp;nbsp;a&amp;nbsp;&quot;version&amp;nbsp;pragma&quot;&amp;nbsp;&amp;mdash;&amp;nbsp;a&amp;nbsp;declaration&amp;nbsp;of&amp;nbsp;the&amp;nbsp;version&amp;nbsp;of&amp;nbsp;the&amp;nbsp;Solidity&amp;nbsp;compiler&amp;nbsp;this&amp;nbsp;code&amp;nbsp;should&amp;nbsp;use.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸이렇게 명시하다니 독특하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통은 메타데이터에 쓰면 컴파일러가 관리해주는데..&lt;/p&gt;
&lt;pre id=&quot;code_1637766836728&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pragma solidity &amp;gt;=0.5.0 &amp;lt;0.6.0;

contract HelloWorld {

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 명시해야 헬로월드 컨트랙이 작동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(3)State&amp;nbsp;Variables&amp;nbsp;&amp;amp;&amp;nbsp;Integers&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 데이터에 대해 배운다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;State&amp;nbsp;variables&amp;nbsp;are&amp;nbsp;permanently&amp;nbsp;stored&amp;nbsp;in&amp;nbsp;contract&amp;nbsp;storage.&amp;nbsp;This&amp;nbsp;means&amp;nbsp;they're&amp;nbsp;written&amp;nbsp;to&amp;nbsp;the&amp;nbsp;Ethereum&amp;nbsp;blockchain.&amp;nbsp;Think&amp;nbsp;of&amp;nbsp;them&amp;nbsp;like&amp;nbsp;writing&amp;nbsp;to&amp;nbsp;a&amp;nbsp;DB.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터가 체인에영원히 남는다이거야.. 정말작은 nft파일은&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;737&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chDapx/btrl56rpHb9/X3KBFFnBFRERfL3h5u9U80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chDapx/btrl56rpHb9/X3KBFFnBFRERfL3h5u9U80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chDapx/btrl56rpHb9/X3KBFFnBFRERfL3h5u9U80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchDapx%2Fbtrl56rpHb9%2FX3KBFFnBFRERfL3h5u9U80%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;551&quot; height=&quot;500&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;737&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 아예 이더리움체인 자체에 올릴수있다. 진정한 탈중앙화&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 state variable의 데이터타입 중에는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;uint가있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The uint data type is an &lt;u&gt;unsigned integer&lt;/u&gt;, meaning its value must be &lt;b&gt;non negative&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본형: uint256 짧은거 uint8,&amp;nbsp;uint16,&amp;nbsp;uint32&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;There's also an int data type for signed integers.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터타입 다 알려줘 감질나..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 데이터타입 세분화된이유는 코드 양에따라 이더리움 가스비가 다르기때문임 (이거 주워들은거라 확실치않음) =&amp;gt;코드양 최소화 마치 c++같군요&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(4)Math&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Addition:&amp;nbsp;x&amp;nbsp;+&amp;nbsp;y &lt;br /&gt;Subtraction:&amp;nbsp;x&amp;nbsp;-&amp;nbsp;y, &lt;br /&gt;Multiplication:&amp;nbsp;x&amp;nbsp;*&amp;nbsp;y &lt;br /&gt;Division:&amp;nbsp;x&amp;nbsp;/&amp;nbsp;y &lt;br /&gt;Modulus&amp;nbsp;/&amp;nbsp;remainder:&amp;nbsp;x&amp;nbsp;%&amp;nbsp;y&amp;nbsp;(for&amp;nbsp;example,&amp;nbsp;13&amp;nbsp;%&amp;nbsp;5&amp;nbsp;is&amp;nbsp;3,&amp;nbsp;because&amp;nbsp;if&amp;nbsp;you&amp;nbsp;divide&amp;nbsp;5&amp;nbsp;into&amp;nbsp;13,&amp;nbsp;3&amp;nbsp;is&amp;nbsp;the&amp;nbsp;remainder)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 수식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;exponential&amp;nbsp;operator &lt;br /&gt;uint&amp;nbsp;x&amp;nbsp;=&amp;nbsp;5&amp;nbsp;**&amp;nbsp;2;&amp;nbsp;//&amp;nbsp;equal&amp;nbsp;to&amp;nbsp;5^2&amp;nbsp;=&amp;nbsp;25&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(5)Structs&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스대신 스트럭이라고 하는군요&lt;/p&gt;
&lt;pre id=&quot;code_1637768494181&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;struct Person {
  uint age;
  string name;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Structs&amp;nbsp;allow&amp;nbsp;you&amp;nbsp;to&amp;nbsp;create&amp;nbsp;more&amp;nbsp;complicated&amp;nbsp;data&amp;nbsp;types&amp;nbsp;that&amp;nbsp;have&amp;nbsp;multiple&amp;nbsp;properties.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체랑은 다른듯함 객체는 속성과 동작인데 이건 속성(데이터)만 있는듯&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(6) Arrays&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fixed&amp;nbsp;arrays&amp;nbsp;and&amp;nbsp;dynamic&amp;nbsp;arrays&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다이나믹만있으면 나는 행복합니다&lt;/p&gt;
&lt;pre id=&quot;code_1637768661708&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Array with a fixed length of 2 elements:
uint[2] fixedArray;
// another fixed Array, can contain 5 strings:
string[5] stringArray;
// a dynamic Array - has no fixed size, can keep growing:
uint[] dynamicArray;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1637770592746&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Person[] public people;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퍼블릭으로 만들면 Solidity&amp;nbsp;will&amp;nbsp;automatically&amp;nbsp;create&amp;nbsp;a&amp;nbsp;getter&amp;nbsp;method&amp;nbsp;for&amp;nbsp;it.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Other contracts would then be able to read from,(퍼블릭이니까) but not write to, this array. So this is a useful pattern for storing public data in your contract.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(7)Function&amp;nbsp;Declarations&lt;/p&gt;
&lt;pre id=&quot;code_1637770694906&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function eatHamburgers(string memory _name, uint _amount) public {

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퍼블릭붙이는 위치가 독특하네.. variables뒤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플러터도 그러더니 솔리디티도 private는 변수명을 _로시작함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Note&amp;nbsp;that&amp;nbsp;we're&amp;nbsp;specifying&amp;nbsp;the&amp;nbsp;function&amp;nbsp;visibility&amp;nbsp;as&amp;nbsp;&lt;b&gt;public&lt;/b&gt;.&amp;nbsp;We're&amp;nbsp;also&amp;nbsp;providing&amp;nbsp;instructions&amp;nbsp;about&amp;nbsp;where&amp;nbsp;the&amp;nbsp;_name&amp;nbsp;variable&amp;nbsp;should&amp;nbsp;be&amp;nbsp;stored-&amp;nbsp;in&amp;nbsp;&lt;b&gt;memory.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 memory 안붙이면 메모리에 안둔다는건지..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;By&amp;nbsp;value,&amp;nbsp;which&amp;nbsp;means&amp;nbsp;that&amp;nbsp;the&amp;nbsp;Solidity&amp;nbsp;compiler&amp;nbsp;creates&amp;nbsp;a&amp;nbsp;new&amp;nbsp;copy&amp;nbsp;of&amp;nbsp;the&amp;nbsp;parameter's&amp;nbsp;value&amp;nbsp;and&amp;nbsp;passes&amp;nbsp;it&amp;nbsp;to&amp;nbsp;your&amp;nbsp;function.&amp;nbsp;This&amp;nbsp;allows&amp;nbsp;your&amp;nbsp;function&amp;nbsp;to&amp;nbsp;modify&amp;nbsp;the&amp;nbsp;value&amp;nbsp;without&amp;nbsp;worrying&amp;nbsp;that&amp;nbsp;the&amp;nbsp;value&amp;nbsp;of&amp;nbsp;the&amp;nbsp;initial&amp;nbsp;parameter&amp;nbsp;gets&amp;nbsp;changed.&lt;/li&gt;
&lt;li&gt;By reference, which means that your function is called with a... reference to the original variable. Thus, if your function changes the value of the variable it receives, the value of the original variable gets changed.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(8) Working&amp;nbsp;With&amp;nbsp;Structs&amp;nbsp;and&amp;nbsp;Arrays&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥뻔함 새 struct만들어서 dynamic array에넣음&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(9)Private&amp;nbsp;/&amp;nbsp;Public&amp;nbsp;Functions&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;It's good practice to mark your functions as private by default, and then only make public the functions you want to expose to the world.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(10)More&amp;nbsp;on&amp;nbsp;Functions&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;return value,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Function&amp;nbsp;modifiers&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;view&amp;nbsp;function&lt;/b&gt;, meaning it's only viewing the data but not modifying it.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;pure functions&lt;/b&gt;, which means you're not even accessing any data in the app.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(11)Keccak256&amp;nbsp;and&amp;nbsp;Typecasting&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ethereum&amp;nbsp;has&amp;nbsp;the&amp;nbsp;hash&amp;nbsp;function&amp;nbsp;keccak256&amp;nbsp;built&amp;nbsp;in,&amp;nbsp;which&amp;nbsp;is&amp;nbsp;a&amp;nbsp;version&amp;nbsp;of&amp;nbsp;SHA3.&amp;nbsp;A&amp;nbsp;hash&amp;nbsp;function&amp;nbsp;basically&amp;nbsp;maps&amp;nbsp;an&amp;nbsp;input&amp;nbsp;into&amp;nbsp;a&amp;nbsp;random&amp;nbsp;256-bit&amp;nbsp;hexadecimal&amp;nbsp;number.&amp;nbsp;A&amp;nbsp;slight&amp;nbsp;change&amp;nbsp;in&amp;nbsp;the&amp;nbsp;input&amp;nbsp;will&amp;nbsp;cause&amp;nbsp;a&amp;nbsp;large&amp;nbsp;change&amp;nbsp;in&amp;nbsp;the&amp;nbsp;hash.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 다양하게 쓸수있는데 랜덤만들때도 씀..&lt;/p&gt;
&lt;pre id=&quot;code_1637772055814&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//6e91ec6b618bb462a4a6ee5aa2cb0e9cf30f7a052bb467b0ba58b8748c00d2e5
keccak256(abi.encodePacked(&quot;aaaab&quot;));
//b1f078126895a1424524de5321b339ab00408010b7cf0e6ed451514981e58aa9
keccak256(abi.encodePacked(&quot;aaaac&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의: Secure random-number generation in blockchain is a very difficult problem. 보안문제 있을수있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Typecasting&lt;/p&gt;
&lt;pre id=&quot;code_1637772092319&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;uint8 a = 5;
uint b = 6;
// throws an error because a * b returns a uint, not uint8:
uint8 c = a * b;
// we have to typecast b as a uint8 to make it work:
uint8 c = a * uint8(b);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;살짝 c++의 악몽이..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12는 복습이라 생략&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(13)Events&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Events&amp;nbsp;are&amp;nbsp;a&amp;nbsp;way&amp;nbsp;for&amp;nbsp;your&amp;nbsp;contract&amp;nbsp;to&amp;nbsp;communicate&amp;nbsp;that&amp;nbsp;something&amp;nbsp;happened&amp;nbsp;on&amp;nbsp;the&amp;nbsp;blockchain&amp;nbsp;to&amp;nbsp;your&amp;nbsp;app&amp;nbsp;front-end,&amp;nbsp;which&amp;nbsp;can&amp;nbsp;be&amp;nbsp;'listening'&amp;nbsp;for&amp;nbsp;certain&amp;nbsp;events&amp;nbsp;and&amp;nbsp;take&amp;nbsp;action&amp;nbsp;when&amp;nbsp;they&amp;nbsp;happen.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스너대신 events와 emit사용&lt;/p&gt;
&lt;pre id=&quot;code_1637772865524&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// declare the event
event IntegersAdded(uint x, uint y, uint result);

function add(uint _x, uint _y) public returns (uint) {
  uint result = _x + _y;
  // fire an event to let the app know the function was called:
  emit IntegersAdded(_x, _y, result);
  return result;
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(14)Web3.js&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Now we need to write a javascript frontend that interacts with the contract.&lt;br /&gt;Ethereum has a Javascript library called Web3.js.&lt;br /&gt;In&amp;nbsp;a&amp;nbsp;later&amp;nbsp;lesson,&amp;nbsp;we'll&amp;nbsp;go&amp;nbsp;over&amp;nbsp;in&amp;nbsp;depth&amp;nbsp;how&amp;nbsp;to&amp;nbsp;deploy&amp;nbsp;a&amp;nbsp;contract&amp;nbsp;and&amp;nbsp;set&amp;nbsp;up&amp;nbsp;Web3.js.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아예 자바스크립트를 세트로가르치는군...&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <category>solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/91</guid>
      <comments>https://realapril.tistory.com/91#entry91comment</comments>
      <pubDate>Thu, 25 Nov 2021 01:54:48 +0900</pubDate>
    </item>
    <item>
      <title>Solidity 입문 | crypto zombies 크립토 좀비</title>
      <link>https://realapril.tistory.com/90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;요새 민팅을 많이하는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러그도 몇번 당하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;민팅도 선착순에서 밀리고 개발자로서 부끄러운일이 한두개가아니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 그때그때 배우지말고 간단하게라도 공부해서 제대로 격파하기로 결정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 nft의 근본은 이더리움=솔리디티라 솔리디티로 결정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 솔리디티 초급강의를 제공하는곳이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://cryptozombies.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://cryptozombies.io/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1637765992646&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;#1 Solidity Tutorial &amp;amp; Ethereum Blockchain Programming Course | CryptoZombies&quot; data-og-description=&quot;CryptoZombies is The Most Popular, Interactive Solidity Tutorial That Will Help You Learn Blockchain Programming on Ethereum by Building Your Own Fun Game with Zombies &amp;mdash; Master Blockchain Development with Web3, Infura, Metamask &amp;amp; Ethereum Smart Contracts&quot; data-og-host=&quot;cryptozombies.io&quot; data-og-source-url=&quot;https://cryptozombies.io/&quot; data-og-url=&quot;https://cryptozombies.io/OGURL&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/m98uD/hyMtvrqc97/7QCkJ7stuaaxftk3Qkhfnk/img.png?width=192&amp;amp;height=287&amp;amp;face=0_0_192_287&quot;&gt;&lt;a href=&quot;https://cryptozombies.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://cryptozombies.io/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/m98uD/hyMtvrqc97/7QCkJ7stuaaxftk3Qkhfnk/img.png?width=192&amp;amp;height=287&amp;amp;face=0_0_192_287');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;#1 Solidity Tutorial &amp;amp; Ethereum Blockchain Programming Course | CryptoZombies&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;CryptoZombies is The Most Popular, Interactive Solidity Tutorial That Will Help You Learn Blockchain Programming on Ethereum by Building Your Own Fun Game with Zombies &amp;mdash; Master Blockchain Development with Web3, Infura, Metamask &amp;amp; Ethereum Smart Contracts&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;cryptozombies.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카테고리따라 빠르게 격파할예정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LV.1 Beginner to Intermediate Smart Contracts&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This&amp;nbsp;course&amp;nbsp;will&amp;nbsp;teach&amp;nbsp;you&amp;nbsp;how&amp;nbsp;to&amp;nbsp;build&amp;nbsp;a&amp;nbsp;game&amp;nbsp;on&amp;nbsp;Ethereum.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 Making the Zombie Factory&lt;br /&gt;2 Zombies Attack Their Victims&lt;br /&gt;3 Advanced Solidity Concepts&lt;br /&gt;4 Zombie Battle System&lt;br /&gt;5 ERC721 &amp;amp; Crypto-Collectibles&lt;br /&gt;6 App Front-ends &amp;amp; Web3.js&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LV.2 Advanced&amp;nbsp;Solidity&amp;nbsp;Path:&amp;nbsp;Get&amp;nbsp;In-depth&amp;nbsp;Knowledge&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1 Deploying DApps with Truffle&lt;br /&gt;2 Testing Smart Contracts with Truffle&lt;br /&gt;3 How to Build an Oracle&lt;br /&gt;4 How to Build an Oracle - Part 2&lt;br /&gt;5 How to Build an Oracle - Part 3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LV.3 Beyond&amp;nbsp;Ethereum:&amp;nbsp;Explore&amp;nbsp;the&amp;nbsp;Blockchain&amp;nbsp;Ecosystem&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Libra Basics&lt;br /&gt;All About Binance Chain&lt;br /&gt;Intro to zkSync&lt;br /&gt;Advanced&amp;nbsp;zkSync&amp;nbsp;Concepts&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레벨3 코스는 좀 올드함. 바낸체인은 nft에선 천대받는곳인데...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근코스는 SOL, polygon, luna 하다못해 klay가나음&lt;/p&gt;</description>
      <category>dev/Solidity</category>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/90</guid>
      <comments>https://realapril.tistory.com/90#entry90comment</comments>
      <pubDate>Thu, 25 Nov 2021 00:07:00 +0900</pubDate>
    </item>
    <item>
      <title>컴파일러 언어와 인터프리터언어</title>
      <link>https://realapril.tistory.com/32</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;659&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nE79M/btqzQUF6r0o/pMXciqbu8WappJpHpJKCdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nE79M/btqzQUF6r0o/pMXciqbu8WappJpHpJKCdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nE79M/btqzQUF6r0o/pMXciqbu8WappJpHpJKCdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnE79M%2FbtqzQUF6r0o%2FpMXciqbu8WappJpHpJKCdk%2Fimg.png&quot; data-origin-width=&quot;940&quot; data-origin-height=&quot;659&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;컴퓨터는 1과 0으로 말하고(기계어, low level language), 인간은 컴퓨터와 대화하기 위해 코드(high level language)를 사용한다.&lt;/p&gt;
&lt;p&gt;그래서 컴퓨터가 인간의 언어를 알아듣게 변환하는 과정이 필요한데,&lt;/p&gt;
&lt;p&gt;그 방식은 컴파일과 인터프리터이다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;컴파일러언어의 예: C&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot;&gt;인터프리터 언어의 예: javascript, python&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이 방식에 따라 언어간 실행 속도의 차가 존재한다. 한번 컴파일되면 컴파일러 언어가 실행속도가 더 빠르다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;우리가 외국어 영상을 보는 상황이라고 하자.&lt;/p&gt;
&lt;p&gt;컴파일언어는 자막을 달아+인코딩 되어 업로딩 된 영상을 보는것이다. 한번 업로드되면 멈추지않고 빠르게 영상을 볼수있다.&lt;/p&gt;
&lt;p&gt;이 자막+인코딩+영상 세트를 목적파일이라고 한다(object file, .o파일형태이다)&lt;/p&gt;
&lt;p&gt;반면 인터프리터는 옆에서 그때 그때 통역가가 번역을 해주는것이다.&lt;/p&gt;
&lt;p&gt;따라서 소리가 겹치지 않게 하기 위해 가끔 영상을 일시 정지해야할때도 있다.&lt;/p&gt;
&lt;p&gt;어쩌면 번역할 시간을 벌기위해 영상을 0.5배속으로 봐야할수도 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이 비유는 다른 항목에도 적용된다.&lt;/p&gt;
&lt;p&gt;1.에러의경우&lt;/p&gt;
&lt;p&gt;컴파일러는 자막을 만들때 뜻이 통하지않는/ 모르는 문장이 있는지 확인하고 영상 업로드전에 작업을 중지한다.&lt;/p&gt;
&lt;p&gt;따라서 컴파일언어는 에러가 있으면 빌드가 되지 않아 실행할 수 없다. &lt;span style=&quot;color: #333333;&quot;&gt;반면 컴파일이 끝났다면 오류가 없다는것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;바면 인터프리터는 한참 통역을 하다가 갑자기 어? 나 이뜻모르겠어 미안! 하고 통역을 멈춰버릴것이다. 사전을 준비하거나 다른 인터프리터를 구하거나 이건 차후의 문제가 되어버린다.&lt;/p&gt;
&lt;p&gt;즉 에러가 있건 없건 프로그램은 실행되나, 실행 중 오류가 있는 곳에서 프로그램이 멈춘다..&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2.준비 시간&lt;/p&gt;
&lt;p&gt;실행시 컴파일이 시간이 좀더 걸리는것도 마찬가지다. 프로그램 실행시 컴파일언어는 빌드 시간이 걸린다.&lt;/p&gt;
&lt;p&gt;빌드시간은 즉 자막을 달아 인코딩하는 시간이다. 따라서 소스코드의 크기가 클수록 컴파일시간이 오래걸린다.&lt;/p&gt;
&lt;p&gt;반면 인터프리터언어는 바로 실행된다. 준비된 통역가가 바로 나오기만 하면 되기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;인터프리터 언어가 코드실행에 걸리는 시간은 조금더 느리지만, 많이쓰이는 이유는 다음과 같다.&lt;/p&gt;
&lt;p&gt;1. high-level language여서 기계의 언어보다는 인간의 언어에 가깝다. 즉 습득하기 더 쉽다.&lt;/p&gt;
&lt;p&gt;2. 유지보수 생산성이 높다. 빌드시간이 짧아서 바로바로 코딩하며 확인하기도 쉽고, 대부분의 인터프리터 언어(c이상의 고급언어)를 사용할때는 메모리관리를 할필요가 없어지기 때문이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/32</guid>
      <comments>https://realapril.tistory.com/32#entry32comment</comments>
      <pubDate>Wed, 20 Nov 2019 00:38:04 +0900</pubDate>
    </item>
    <item>
      <title>npm설치한 프로그램이 뭘해도 command not found가 뜰때</title>
      <link>https://realapril.tistory.com/27</link>
      <description>&lt;p&gt;mac, 리눅스 공통&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;npm global 설치한후 실행시 계속 command not found 가 뜰때&lt;/p&gt;
&lt;p&gt;보통 경로문제다. 하지만 .bash 파일을 수정하다 잘돌아가던것까지 박살나기 쉽다. 우회하자.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;터미널에서 경로 세팅을 다시해주자&lt;/p&gt;
&lt;pre id=&quot;code_1568081386532&quot; class=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm config set prefix /usr/local&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;npm 통해 설치되는 파일 경로가 로컬파일이된다. 숨김파일이다.&lt;/p&gt;
&lt;p&gt;기존에 npm 글로벌로 깔았더라도 새로 받는다. 기존 npm 파일받은건 잊자.(저는 서버리스 받고있었음)&lt;/p&gt;
&lt;pre id=&quot;code_1568081432338&quot; class=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm i -g serverless&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그다음 프로그램명을 치면 잘된다&lt;/p&gt;
&lt;p&gt;기본 패스 설정이 이상했던것!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;출처&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/a/45132080&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://stackoverflow.com/a/45132080&lt;/a&gt;&lt;/p&gt;</description>
      <author>_April</author>
      <guid isPermaLink="true">https://realapril.tistory.com/27</guid>
      <comments>https://realapril.tistory.com/27#entry27comment</comments>
      <pubDate>Tue, 10 Sep 2019 11:11:15 +0900</pubDate>
    </item>
  </channel>
</rss>