<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>ReasonJun</title>
    <link>https://reasonjun.tistory.com/</link>
    <description>저의 경험/생각/지식을 공유합니다.
https://brunch.co.kr/@iwonyoujun</description>
    <language>ko</language>
    <pubDate>Thu, 18 Jun 2026 14:30:07 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>ReasonJun</managingEditor>
    <image>
      <title>ReasonJun</title>
      <url>https://tistory1.daumcdn.net/tistory/6184127/attach/1b8ba91cfa904af5b6765eebb1d96393</url>
      <link>https://reasonjun.tistory.com</link>
    </image>
    <item>
      <title>Cursor SSH 연결 에러 해결: &amp;quot;Failed to install the Cursor Server&amp;quot;</title>
      <link>https://reasonjun.tistory.com/376</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 발생 :&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cursor에서 AWS EC2로 원격 접속하려고 했더니 이런 에러가 떴다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Connection to Cursor server failed: Failed to install the Cursor Server. Please check the logs for more details.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아니, SSH는 되는데 왜 Cursor만 작동을 하지 않았다.&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;로그 확인&lt;/h2&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;/usr/libexec/grepconf.sh: line 5: grep: command not found
/etc/profile.d/which2.sh: line 4: readlink: command not found
bash: bash: command not found
debug1: Exit status 127
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;grep도 없고, bash도 없다는 것을 알게되었다. AWS Instance에 직접 SSH로 접속해봤다.&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;$ ssh -i ~/.ssh/woori-kubernetes.pem ec2-user@ec2-43-203-153-38.ap-northeast-2.compute.amazonaws.com
-bash: grep: command not found
-bash: readlink: command not found
-bash: basename: command not found
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역시나 기본 명령어들을 못 찾고 있었다.&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 원인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PATH를 확인해보니 범인을 찾았다.&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;/usr/local/cuda-12.2/bin${PATH:+:${PATH}}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;CUDA 설정하면서 실수로 이상한 구문을 넣어놨다. 변수 확장이 제대로 안 되어서 시스템이 명령어를 못 찾는 거였다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1단계: .bash_profile 수정하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 vi를 전체 경로로 실행한다 :&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;/usr/bin/vi ~/.bash_profile
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일이 열리면:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;i 키를 눌러서 입력 모드로 전환&lt;/li&gt;
&lt;li&gt;# User specific environment and startup programs 아래에 이 줄 추가:
&lt;pre class=&quot;elixir&quot;&gt;&lt;code&gt;export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;ESC 키 누르고 :wq 입력해서 저장&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2단계: .bashrc도 수정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cursor는 가끔 non-interactive shell로 접속하기 때문에 .bashrc도 수정해야 한다:&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;/usr/bin/vi ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 맨 끝에 같은 내용 추가:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Shift + G로 파일 끝으로 이동&lt;/li&gt;
&lt;li&gt;o 키 눌러서 새 줄 만들기&lt;/li&gt;
&lt;li&gt;똑같이 추가:
&lt;pre class=&quot;elixir&quot;&gt;&lt;code&gt;export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;저장하고 나오기 (ESC &amp;rarr; :wq)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3단계: 설정 적용하고 확인&lt;/h3&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;source ~/.bash_profile
source ~/.bashrc

# 이제 명령어가 제대로 작동하는지 확인
which grep
which bash
echo $PATH
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4단계: Cursor에서 다시 접속&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSH 세션을 완전히 종료하고:&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;exit
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cursor에서 다시 Remote SSH 연결을 시도했다. 정상적으로 연결되는 것을 확인했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 PATH 설정이 꼬여서 생긴 문제였다. .bash_profile과 .bashrc 둘 다 수정해야 Cursor가 제대로 접속할 수 있다는 게 포인트인것 같다. 이 글이 같은 문제로 고생하는 누군가에게 도움이 되길 바란다.&amp;nbsp;&lt;/p&gt;</description>
      <category>Useful Lib</category>
      <category>aws</category>
      <category>CURSOR</category>
      <category>ec2</category>
      <category>Linux</category>
      <category>SSH</category>
      <category>개발환경</category>
      <category>트러블슈팅</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/376</guid>
      <comments>https://reasonjun.tistory.com/376#entry376comment</comments>
      <pubDate>Thu, 24 Jul 2025 01:32:40 +0900</pubDate>
    </item>
    <item>
      <title>Docker 특정 포트만 외부 접속이 안 될 때: iptables NAT 무한 루프 해결기</title>
      <link>https://reasonjun.tistory.com/375</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  문제 상황&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker로 서비스를 운영하던 중 기묘한 현상을 발견했다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;43001, 43030 포트&lt;/b&gt;: 외부 접속 ✅ 정상&lt;/li&gt;
&lt;li&gt;&lt;b&gt;43000 포트&lt;/b&gt;: 외부 접속 ❌ 불가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;localhost:43000&lt;/b&gt;: 내부 접속 ✅ 정상&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 이상한 건, Docker 컨테이너는 정상 실행 중이고, 포트도 제대로 리스닝하고 있었다는 점이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  진단 과정&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 기본 상태 확인&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;# 포트 리스닝 상태 확인
$ netstat -tuln | grep 43000
tcp6       0      0 :::43000                :::*                    LISTEN

# Docker 컨테이너 상태 확인  
$ docker ps | grep 43000
8a5bce7ee59f   aimfuse-web   &quot;docker-entrypoint.s&amp;hellip;&quot;   Up 5 days (unhealthy)   0.0.0.0:43000-&amp;gt;3000/tcp

# 내부 접속 테스트
$ curl -v http://localhost:43000/api/public/health
&amp;lt; HTTP/1.1 200 OK
{&quot;status&quot;:&quot;ok&quot;}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너는 unhealthy 상태였지만, API는 정상 응답했다.  &lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 방화벽 규칙 확인&lt;/h3&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;# UFW 상태 확인
$ sudo ufw status verbose
Status: active
Default: allow (incoming), allow (outgoing), allow (routed)

# iptables 확인
$ sudo iptables -L -n -v | grep 43000
# 특별한 차단 규칙 없음
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UFW는 기본 정책이 allow라서 문제가 없어 보였다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. NAT 테이블 확인 - 문제 발견!  &lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;$ sudo iptables -t nat -L -n -v --line-numbers | grep -A 10 -B 10 &quot;43000\|3000&quot;

Chain PREROUTING (policy ACCEPT)
num  target     prot opt source    destination
2    REDIRECT   tcp  --  0.0.0.0/0  0.0.0.0/0    tcp dpt:3000 redir ports 43000
3    REDIRECT   tcp  --  0.0.0.0/0  0.0.0.0/0    tcp dpt:43000 redir ports 3000
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  문제 원인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NAT 테이블에서 &lt;b&gt;무한 루프&lt;/b&gt;를 발견했다!&lt;/p&gt;
&lt;pre class=&quot;basic&quot;&gt;&lt;code&gt;3000 포트 &amp;rarr; 43000 포트로 리다이렉트
43000 포트 &amp;rarr; 3000 포트로 리다이렉트
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 규칙이 서로를 계속 호출하면서 무한 루프에 빠져, 결국 43000 포트로의 외부 접속이 불가능했던 것이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  해결 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제가 되는 NAT 규칙들을 제거했다:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 문제가 되는 규칙 제거 (라인 번호 확인 후)
$ sudo iptables -t nat -D PREROUTING 3
$ sudo iptables -t nat -D PREROUTING 2

# 변경사항 확인
$ sudo iptables -t nat -L -n -v | grep -A 5 -B 5 &quot;43000\|3000&quot;
# 이제 Docker의 정상적인 DNAT 규칙만 남음
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;✅ 결과&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;제거된 규칙&lt;/b&gt;: 무한 루프를 만드는 REDIRECT 규칙들&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유지된 규칙&lt;/b&gt;: Docker의 정상적인 포트 포워딩 (43000 &amp;rarr; 172.20.0.6:3000)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;외부 접속&lt;/b&gt;: 정상화!  &lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  교훈과 체크리스트&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 이런 일이 발생했을까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마도 과거에 포트 리다이렉션을 테스트하다가 잘못된 규칙을 추가했고, 이를 제거하지 않았던 것 같다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;향후 방지를 위한 체크리스트&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;포트 문제 발생 시 점검 순서&lt;/b&gt;:&lt;br /&gt;# 1. 포트 리스닝 확인 netstat -tuln | grep [포트번호] &lt;br /&gt;# 2. Docker 상태 확인 docker ps | grep [포트번호] &lt;br /&gt;# 3. 내부 접속 테스트 curl -v http://localhost:[포트번호] &lt;br /&gt;# 4. iptables 일반 규칙 확인 sudo iptables -L -n -v | grep [포트번호] &lt;br /&gt;# 5. NAT 테이블 확인 ⚠️ 중요! sudo iptables -t nat -L -n -v | grep [포트번호]&lt;/li&gt;
&lt;li&gt;&lt;b&gt;iptables 규칙 추가 시 주의사항&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NAT 규칙 추가 전 기존 규칙 확인&lt;/li&gt;
&lt;li&gt;테스트 후 불필요한 규칙은 즉시 제거&lt;/li&gt;
&lt;li&gt;규칙 추가 시 문서화 또는 주석 남기기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정기적인 점검&lt;/b&gt;:&lt;/li&gt;
&lt;li&gt;# NAT 테이블 전체 확인 sudo iptables -t nat -L -n -v --line-numbers&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  핵심 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;특정 포트만 외부 접속이 안 된다면, iptables NAT 테이블을 확인하자!&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 방화벽 규칙뿐만 아니라 NAT 테이블의 REDIRECT 규칙도 반드시 확인해야 한다. 특히 무한 루프를 만들 수 있는 상호 참조 규칙이 있는지 주의 깊게 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 경험을 통해 네트워크 문제 해결 시 NAT 테이블 확인의 중요성을 다시 한번 깨달았다. 같은 실수를 반복하지 않기 위해 이 글을 기록으로 남긴다.  &lt;/p&gt;</description>
      <category>Docker</category>
      <category>iptables</category>
      <category>NAT</category>
      <category>PORT</category>
      <category>방화벽</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/375</guid>
      <comments>https://reasonjun.tistory.com/375#entry375comment</comments>
      <pubDate>Sat, 5 Jul 2025 21:19:44 +0900</pubDate>
    </item>
    <item>
      <title>Understanding the NestJS Request Lifecycle: A Deep Dive</title>
      <link>https://reasonjun.tistory.com/374</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;NestJS, a progressive Node.js framework, implements a sophisticated request lifecycle that ensures proper handling of incoming requests through various layers of processing. In this article, we'll break down each step of this lifecycle and understand how it helps in building robust applications.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;The Request Journey&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Middleware Layer&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Purpose&lt;/b&gt;: Handles common HTTP operations&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Functionality&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Pre-processes requests&lt;/li&gt;
&lt;li&gt;Handles cross-cutting concerns like logging&lt;/li&gt;
&lt;li&gt;Authentication headers processing&lt;/li&gt;
&lt;li&gt;CORS handling&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Key Point&lt;/b&gt;: Executes before route handlers, can modify request/response objects&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Guard Layer&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Purpose&lt;/b&gt;: Authorization and permission checking&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Functionality&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Determines if a request should proceed&lt;/li&gt;
&lt;li&gt;Handles user authentication status&lt;/li&gt;
&lt;li&gt;Role-based access control&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Example Use Case&lt;/b&gt;: Checking if a user is logged in before accessing protected routes&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Interceptor (Pre-Controller)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Purpose&lt;/b&gt;: Request/Response transformation&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Functionality&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Adds custom headers&lt;/li&gt;
&lt;li&gt;Transforms request data&lt;/li&gt;
&lt;li&gt;Handles timing and logging&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Note&lt;/b&gt;: Executes both before and after route handler&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. Pipe Layer&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Purpose&lt;/b&gt;: Data validation and transformation&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Functionality&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Validates input data&lt;/li&gt;
&lt;li&gt;Transforms payload to desired format&lt;/li&gt;
&lt;li&gt;Type conversion&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Common Use&lt;/b&gt;: DTO validation, parameter transformation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. Controller Layer&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Purpose&lt;/b&gt;: Route handling and business logic coordination&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Functionality&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Handles incoming requests&lt;/li&gt;
&lt;li&gt;Coordinates with services&lt;/li&gt;
&lt;li&gt;Returns responses&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Best Practice&lt;/b&gt;: Keep controllers thin, delegate business logic to services&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. Service Layer&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Purpose&lt;/b&gt;: Business logic implementation&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Functionality&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Implements core business rules&lt;/li&gt;
&lt;li&gt;Processes data&lt;/li&gt;
&lt;li&gt;Coordinates with repositories&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Key Point&lt;/b&gt;: Contains reusable business logic&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. Repository Layer&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Purpose&lt;/b&gt;: Data access and persistence&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Functionality&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Database operations&lt;/li&gt;
&lt;li&gt;Data retrieval and storage&lt;/li&gt;
&lt;li&gt;Query handling&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;8. Exception Filter Layer&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Purpose&lt;/b&gt;: Error handling and formatting&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Functionality&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Catches unhandled exceptions&lt;/li&gt;
&lt;li&gt;Formats error responses&lt;/li&gt;
&lt;li&gt;Ensures consistent error handling&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;9. Interceptor (Post-Controller)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Purpose&lt;/b&gt;: Response transformation&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Functionality&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Transforms response data&lt;/li&gt;
&lt;li&gt;Adds metadata&lt;/li&gt;
&lt;li&gt;Handles logging and timing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Best Practices&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Separation of Concerns&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Each layer should have a single responsibility&lt;/li&gt;
&lt;li&gt;Avoid mixing business logic in controllers&lt;/li&gt;
&lt;li&gt;Use appropriate decorators for each layer&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Error Handling&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Implement custom exception filters for specific use cases&lt;/li&gt;
&lt;li&gt;Use built-in HTTP exceptions&lt;/li&gt;
&lt;li&gt;Handle errors at appropriate layers&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Validation&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Use DTOs for request validation&lt;/li&gt;
&lt;li&gt;Implement custom pipes for complex validations&lt;/li&gt;
&lt;li&gt;Validate early in the request lifecycle&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Performance&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Keep middleware light and focused&lt;/li&gt;
&lt;li&gt;Use caching where appropriate&lt;/li&gt;
&lt;li&gt;Implement proper logging strategies&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screenshot 2024-10-30 at 12.52.01 AM.png&quot; data-origin-width=&quot;3400&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r1khv/btsKpEDXRWS/7BesxL6YHkJQXH3bzFLcc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r1khv/btsKpEDXRWS/7BesxL6YHkJQXH3bzFLcc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r1khv/btsKpEDXRWS/7BesxL6YHkJQXH3bzFLcc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr1khv%2FbtsKpEDXRWS%2F7BesxL6YHkJQXH3bzFLcc0%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;3400&quot; height=&quot;674&quot; data-filename=&quot;Screenshot 2024-10-30 at 12.52.01 AM.png&quot; data-origin-width=&quot;3400&quot; data-origin-height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;Conclusion&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Understanding the NestJS request lifecycle is crucial for building efficient and maintainable applications. Each layer serves a specific purpose and, when used correctly, contributes to a well-structured application that's easy to test and maintain.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The lifecycle ensures that requests are properly validated, authorized, and processed while maintaining clean separation of concerns. By following the best practices and understanding how each layer interacts, you can build robust applications that are both performant and maintainable.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Additional Resources&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.nestjs.com/&quot;&gt;NestJS Official Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.nestjs.com/middleware&quot;&gt;Middleware Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.nestjs.com/guards&quot;&gt;Guards Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.nestjs.com/interceptors&quot;&gt;Interceptors Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Backend/Nest.js</category>
      <category>Lifecycle</category>
      <category>NestJS</category>
      <category>request</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/374</guid>
      <comments>https://reasonjun.tistory.com/374#entry374comment</comments>
      <pubDate>Wed, 30 Oct 2024 00:51:32 +0900</pubDate>
    </item>
    <item>
      <title>Tailwindcss : Carousel Dynamic width control</title>
      <link>https://reasonjun.tistory.com/373</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Problem :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;I wrote the Carousel code as shown below. I wanted the width of the carousel to be responsive to the screen size, but it wasn't, so I specified a maximum width for each screen size : &quot;max-w-sm xs:max-w-md sm:max-w-xl md:max-w-3xl lg:max-w-5xl xl:max-w-7xl&quot;. It adjusted well to the screen size, but the problem was that there were often black spaces.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728961764324&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div
        className=&quot;flex overflow-x-scroll overscroll-x-auto scroll-smooth py-12 [scrollbar-width:none]&quot;
        ref={carouselRef}
        onScroll={checkScrollability}
      &amp;gt;
        &amp;lt;div className=&quot;mx-auto flex flex-row justify-start gap-3 pl-4 sm:gap-4&quot;&amp;gt;
          {items.map((item, index) =&amp;gt; (
            &amp;lt;motion.div
              initial={{ opacity: 0, y: 20 }}
              animate={{
                opacity: 1,
                y: 0,
                transition: {
                  duration: 0.5,
                  delay: 0.1 * index,
                  ease: &quot;easeOut&quot;,
                },
              }}
              key={`card${index}`}
              className=&quot;rounded-3xl md:last:pr-[calc(50%-1rem)] lg:last:pr-[33%]&quot;
            &amp;gt;
              {item}
            &amp;lt;/motion.div&amp;gt;
          ))}
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Why :&amp;nbsp;&lt;/b&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;width doesn't move responsively in a carousel for the following reasons :&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Fixed width on items: The code doesn't show how the individual items are styled. If the items have a fixed width, they won't resize responsively.&lt;/li&gt;
&lt;li&gt;Overflow behavior: The carousel is set to overflow-x-scroll, which allows horizontal scrolling but doesn't automatically resize content.&lt;/li&gt;
&lt;/ul&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;b&gt;Solution :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;I wrapped this code and it worked.&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;pre id=&quot;code_1728962126538&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div className=&quot;relative w-[90vw] max-w-7xl&quot;&amp;gt;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Why :&amp;nbsp;&lt;/b&gt;&lt;/h3&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;w-[90vw]: This sets the width to 90% of the viewport width, which makes the container responsive to the screen size.&lt;/li&gt;
&lt;li&gt;max-w-7xl: This sets a maximum width (in Tailwind, this is typically 1280px), preventing the carousel from becoming too wide on large screens.&lt;/li&gt;
&lt;li&gt;relative: This establishes a new positioning context for absolute elements inside the carousel (like the navigation buttons).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Tailwindcss</category>
      <category>Carousel</category>
      <category>responsive</category>
      <category>tailwindcss</category>
      <category>VW</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/373</guid>
      <comments>https://reasonjun.tistory.com/373#entry373comment</comments>
      <pubDate>Tue, 15 Oct 2024 12:16:10 +0900</pubDate>
    </item>
    <item>
      <title>postgresql (Supabase) : security definer set search_path = '' (Security Problem)</title>
      <link>https://reasonjun.tistory.com/372</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Securing&amp;nbsp;PostgreSQL&amp;nbsp;Functions&amp;nbsp;in&amp;nbsp;Supabase:&amp;nbsp;Addressing&amp;nbsp;Search&amp;nbsp;Path&amp;nbsp;Vulnerabilities&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In the world of database management and application development, security is paramount. Recently, while working on a Supabase project utilizing PostgreSQL functions, I encountered a security warning that led us down a path of discovery and improvement. This blog post will walk you through our journey from identifying the problem to implementing a robust solution.&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;b&gt;The&amp;nbsp;Problem:&amp;nbsp;&quot;Search&amp;nbsp;Path&amp;nbsp;Mutable&quot;&amp;nbsp;Warning&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;My story begins with a seemingly innocuous PostgreSQL function in our Supabase project. Upon deployment, we were greeted with a warning from the Supabase advisor:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KxfaF/btsIUVu84z0/oRopSgNQ27qNynmIodA3nK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KxfaF/btsIUVu84z0/oRopSgNQ27qNynmIodA3nK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KxfaF/btsIUVu84z0/oRopSgNQ27qNynmIodA3nK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKxfaF%2FbtsIUVu84z0%2FoRopSgNQ27qNynmIodA3nK%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;721&quot; height=&quot;568&quot; data-origin-width=&quot;721&quot; data-origin-height=&quot;568&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;This&amp;nbsp;cryptic&amp;nbsp;message&amp;nbsp;was&amp;nbsp;our&amp;nbsp;first&amp;nbsp;indication&amp;nbsp;that&amp;nbsp;something&amp;nbsp;wasn't&amp;nbsp;quite&amp;nbsp;right&amp;nbsp;with&amp;nbsp;our&amp;nbsp;function's&amp;nbsp;security&amp;nbsp;posture.&amp;nbsp;The&amp;nbsp;function&amp;nbsp;in&amp;nbsp;question&amp;nbsp;was&amp;nbsp;designed&amp;nbsp;to&amp;nbsp;delete&amp;nbsp;and&amp;nbsp;insert&amp;nbsp;data&amp;nbsp;related&amp;nbsp;to&amp;nbsp;toxic&amp;nbsp;tactics&amp;nbsp;for&amp;nbsp;a&amp;nbsp;given&amp;nbsp;subject.&amp;nbsp;Here's&amp;nbsp;a&amp;nbsp;simplified&amp;nbsp;version&amp;nbsp;of&amp;nbsp;our&amp;nbsp;initial&amp;nbsp;function:&lt;/p&gt;
&lt;pre id=&quot;code_1722925964036&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE OR REPLACE FUNCTION public.delete_and_insert_toxic_tactics_subject(p_subject_id TEXT, p_new_data JSONB)
RETURNS VOID
AS $$
-- Function body
$$ LANGUAGE plpgsql;&lt;/code&gt;&lt;/pre&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;b&gt;Understanding&amp;nbsp;the&amp;nbsp;Vulnerability&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The&amp;nbsp;&quot;search_path&amp;nbsp;mutable&quot;&amp;nbsp;warning&amp;nbsp;points&amp;nbsp;to&amp;nbsp;a&amp;nbsp;potential&amp;nbsp;security&amp;nbsp;vulnerability&amp;nbsp;related&amp;nbsp;to&amp;nbsp;PostgreSQL's&amp;nbsp;search&amp;nbsp;path&amp;nbsp;mechanism.&amp;nbsp;In&amp;nbsp;PostgreSQL,&amp;nbsp;the&amp;nbsp;search&amp;nbsp;path&amp;nbsp;determines&amp;nbsp;the&amp;nbsp;order&amp;nbsp;in&amp;nbsp;which&amp;nbsp;schemas&amp;nbsp;are&amp;nbsp;searched&amp;nbsp;when&amp;nbsp;an&amp;nbsp;unqualified&amp;nbsp;object&amp;nbsp;name&amp;nbsp;is&amp;nbsp;used.&lt;br /&gt;&lt;br /&gt;This&amp;nbsp;vulnerability&amp;nbsp;arises&amp;nbsp;because:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;The search path can be changed by users during their session.&lt;/li&gt;
&lt;li&gt;If the function doesn't explicitly set its search path, it inherits the search path of the calling user.&lt;/li&gt;
&lt;li&gt;This inherited search path could potentially be manipulated to make the function access unintended objects or schemas&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In my case, this was particularly concerning because our function was dealing with sensitive data related to toxic tactics. Any unintended access or manipulation&amp;nbsp;could&amp;nbsp;have&amp;nbsp;serious&amp;nbsp;consequences.&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;b&gt;The&amp;nbsp;Solution:&amp;nbsp;SECURITY&amp;nbsp;DEFINER&amp;nbsp;and&amp;nbsp;Empty&amp;nbsp;Search&amp;nbsp;Path&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;After careful consideration and testing, I arrived at a solution that effectively addresses this vulnerability. Here's my updated function definition :&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1722926614892&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE OR REPLACE FUNCTION public.delete_and_insert_toxic_tactics_subject(p_subject_id TEXT, p_new_data JSONB)
RETURNS VOID
SECURITY DEFINER
SET search_path = ''
AS $$
DECLARE
  uuid_subject_id UUID;
  inserted_count INT := 0;
  expected_count INT;
  current_tactic TEXT;
  log_messages TEXT[] := ARRAY[]::TEXT[];
  total_average FLOAT;
  tactic_scores JSONB;
BEGIN
  -- Function body with fully qualified object names
  -- For example:
  -- INSERT INTO public.&quot;red toxic tactic&quot; (...)
END;
$$ LANGUAGE plpgsql;&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;Let's break down the critical components of this solution :&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;b&gt;1.&amp;nbsp;SECURITY&amp;nbsp;DEFINER&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The&amp;nbsp;SECURITY&amp;nbsp;DEFINER&amp;nbsp;clause&amp;nbsp;ensures&amp;nbsp;that&amp;nbsp;the&amp;nbsp;function&amp;nbsp;executes&amp;nbsp;with&amp;nbsp;the&amp;nbsp;privileges&amp;nbsp;of&amp;nbsp;its&amp;nbsp;owner&amp;nbsp;(creator)&amp;nbsp;rather&amp;nbsp;than&amp;nbsp;those&amp;nbsp;of&amp;nbsp;the&amp;nbsp;calling&amp;nbsp;user.&amp;nbsp;This&amp;nbsp;provides&amp;nbsp;a&amp;nbsp;consistent&amp;nbsp;security&amp;nbsp;context&amp;nbsp;for&amp;nbsp;the&amp;nbsp;function's&amp;nbsp;execution.&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;b&gt;2.&amp;nbsp;SET&amp;nbsp;search_path&amp;nbsp;=&amp;nbsp;''&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This is the crux of my solution. By setting the search path to an empty string, we're effectively clearing the search path for this function. This has several important implications :&amp;nbsp;&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;It forces all object references within the function to be fully qualified with their schema names.&lt;/li&gt;
&lt;li&gt;It prevents any possibility of search path-based attacks, as there's no search path to manipulate.&lt;/li&gt;
&lt;li&gt;It ensures predictable behavior regardless of the calling user's search path settings.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.&amp;nbsp;Fully&amp;nbsp;Qualified&amp;nbsp;Object&amp;nbsp;Names&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;With&amp;nbsp;an&amp;nbsp;empty&amp;nbsp;search&amp;nbsp;path,&amp;nbsp;it&amp;nbsp;becomes&amp;nbsp;crucial&amp;nbsp;to&amp;nbsp;use&amp;nbsp;fully&amp;nbsp;qualified&amp;nbsp;names&amp;nbsp;for&amp;nbsp;all&amp;nbsp;database&amp;nbsp;objects&amp;nbsp;within&amp;nbsp;the&amp;nbsp;function&amp;nbsp;body.&amp;nbsp;For&amp;nbsp;example:&lt;/p&gt;
&lt;pre id=&quot;code_1722927132274&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;INSERT INTO public.&quot;red toxic tactic&quot; (column1, column2) VALUES (...);&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;</description>
      <category>Backend/Supabase</category>
      <category>definer</category>
      <category>PostgreSQL</category>
      <category>search_path</category>
      <category>security</category>
      <category>supabase</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/372</guid>
      <comments>https://reasonjun.tistory.com/372#entry372comment</comments>
      <pubDate>Tue, 6 Aug 2024 15:53:31 +0900</pubDate>
    </item>
    <item>
      <title>React : createPortal</title>
      <link>https://reasonjun.tistory.com/371</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Env : &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nextjs 14, shadcn&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;Problem :&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;I want Tooltip to be placed at the top, but the z-index value is not applied due to the rendering order in Dom.&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;Fix :&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;use createPortal&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1164&quot; data-origin-height=&quot;2062&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/R40Mv/btsIx5ZvVvB/TjGrGCeXBgcq5YZ6Qc72BK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/R40Mv/btsIx5ZvVvB/TjGrGCeXBgcq5YZ6Qc72BK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/R40Mv/btsIx5ZvVvB/TjGrGCeXBgcq5YZ6Qc72BK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FR40Mv%2FbtsIx5ZvVvB%2FTjGrGCeXBgcq5YZ6Qc72BK%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;1164&quot; height=&quot;2062&quot; data-origin-width=&quot;1164&quot; data-origin-height=&quot;2062&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;What is createPortal ? (Cluade Sonnet 3.5 Answer)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Certainly.&amp;nbsp;`createPortal`&amp;nbsp;is&amp;nbsp;a&amp;nbsp;powerful&amp;nbsp;feature&amp;nbsp;provided&amp;nbsp;by&amp;nbsp;React&amp;nbsp;that&amp;nbsp;allows&amp;nbsp;you&amp;nbsp;to&amp;nbsp;render&amp;nbsp;a&amp;nbsp;component's&amp;nbsp;children&amp;nbsp;into&amp;nbsp;a&amp;nbsp;different&amp;nbsp;part&amp;nbsp;of&amp;nbsp;the&amp;nbsp;DOM&amp;nbsp;tree,&amp;nbsp;outside&amp;nbsp;of&amp;nbsp;the&amp;nbsp;component's&amp;nbsp;own&amp;nbsp;hierarchy.&amp;nbsp;Here's&amp;nbsp;a&amp;nbsp;detailed&amp;nbsp;explanation:&lt;br /&gt;&lt;br /&gt;1.&amp;nbsp;Purpose:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;`createPortal`&amp;nbsp;is&amp;nbsp;used&amp;nbsp;to&amp;nbsp;render&amp;nbsp;children&amp;nbsp;into&amp;nbsp;a&amp;nbsp;DOM&amp;nbsp;node&amp;nbsp;that&amp;nbsp;exists&amp;nbsp;outside&amp;nbsp;the&amp;nbsp;DOM&amp;nbsp;hierarchy&amp;nbsp;of&amp;nbsp;the&amp;nbsp;parent&amp;nbsp;component.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;It's&amp;nbsp;particularly&amp;nbsp;useful&amp;nbsp;for&amp;nbsp;creating&amp;nbsp;modals,&amp;nbsp;tooltips,&amp;nbsp;pop-ups,&amp;nbsp;or&amp;nbsp;any&amp;nbsp;floating&amp;nbsp;UI&amp;nbsp;elements&amp;nbsp;that&amp;nbsp;need&amp;nbsp;to&amp;nbsp;&quot;break&amp;nbsp;out&quot;&amp;nbsp;of&amp;nbsp;their&amp;nbsp;container's&amp;nbsp;bounds.&lt;br /&gt;&lt;br /&gt;2.&amp;nbsp;Import:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;It's&amp;nbsp;imported&amp;nbsp;from&amp;nbsp;the&amp;nbsp;'react-dom'&amp;nbsp;library:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;```javascript&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;import&amp;nbsp;{&amp;nbsp;createPortal&amp;nbsp;}&amp;nbsp;from&amp;nbsp;'react-dom';&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;```&lt;br /&gt;&lt;br /&gt;3.&amp;nbsp;Basic&amp;nbsp;syntax:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;```javascript&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;createPortal(child,&amp;nbsp;container)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;```&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;`child`:&amp;nbsp;The&amp;nbsp;React&amp;nbsp;element,&amp;nbsp;string,&amp;nbsp;or&amp;nbsp;fragment&amp;nbsp;to&amp;nbsp;render.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;`container`:&amp;nbsp;The&amp;nbsp;DOM&amp;nbsp;element&amp;nbsp;to&amp;nbsp;render&amp;nbsp;the&amp;nbsp;portal&amp;nbsp;into.&lt;br /&gt;&lt;br /&gt;4.&amp;nbsp;Usage&amp;nbsp;example:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;```jsx&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;function&amp;nbsp;Modal({&amp;nbsp;children&amp;nbsp;})&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;createPortal(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;children,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;```&lt;br /&gt;&lt;br /&gt;5.&amp;nbsp;Key&amp;nbsp;benefits:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;Avoids&amp;nbsp;CSS&amp;nbsp;stacking&amp;nbsp;context&amp;nbsp;issues&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;Allows&amp;nbsp;components&amp;nbsp;to&amp;nbsp;render&amp;nbsp;content&amp;nbsp;outside&amp;nbsp;of&amp;nbsp;their&amp;nbsp;own&amp;nbsp;DOM&amp;nbsp;hierarchy&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;Useful&amp;nbsp;for&amp;nbsp;components&amp;nbsp;that&amp;nbsp;need&amp;nbsp;to&amp;nbsp;&quot;escape&quot;&amp;nbsp;containers&amp;nbsp;with&amp;nbsp;`overflow:&amp;nbsp;hidden`&amp;nbsp;or&amp;nbsp;`z-index`&amp;nbsp;stacking&lt;br /&gt;&lt;br /&gt;6.&amp;nbsp;Event&amp;nbsp;bubbling:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;Events&amp;nbsp;from&amp;nbsp;portals&amp;nbsp;will&amp;nbsp;bubble&amp;nbsp;up&amp;nbsp;through&amp;nbsp;the&amp;nbsp;React&amp;nbsp;tree,&amp;nbsp;regardless&amp;nbsp;of&amp;nbsp;where&amp;nbsp;they're&amp;nbsp;rendered&amp;nbsp;in&amp;nbsp;the&amp;nbsp;DOM.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;This&amp;nbsp;maintains&amp;nbsp;React's&amp;nbsp;expected&amp;nbsp;behavior&amp;nbsp;even&amp;nbsp;when&amp;nbsp;using&amp;nbsp;portals.&lt;br /&gt;&lt;br /&gt;7.&amp;nbsp;Use&amp;nbsp;cases:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;Modals&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;Tooltips&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;Floating&amp;nbsp;menus&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;Notification&amp;nbsp;systems&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;Any&amp;nbsp;UI&amp;nbsp;that&amp;nbsp;needs&amp;nbsp;to&amp;nbsp;overlay&amp;nbsp;the&amp;nbsp;main&amp;nbsp;application&amp;nbsp;regardless&amp;nbsp;of&amp;nbsp;DOM&amp;nbsp;structure&lt;br /&gt;&lt;br /&gt;8.&amp;nbsp;Considerations:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;Portals&amp;nbsp;should&amp;nbsp;be&amp;nbsp;used&amp;nbsp;judiciously,&amp;nbsp;as&amp;nbsp;they&amp;nbsp;can&amp;nbsp;complicate&amp;nbsp;the&amp;nbsp;application&amp;nbsp;structure&amp;nbsp;if&amp;nbsp;overused.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;It's&amp;nbsp;important&amp;nbsp;to&amp;nbsp;manage&amp;nbsp;focus&amp;nbsp;and&amp;nbsp;accessibility&amp;nbsp;properly&amp;nbsp;when&amp;nbsp;using&amp;nbsp;portals&amp;nbsp;for&amp;nbsp;modals&amp;nbsp;or&amp;nbsp;dialogs.&lt;br /&gt;&lt;br /&gt;In&amp;nbsp;the&amp;nbsp;context&amp;nbsp;of&amp;nbsp;your&amp;nbsp;tooltip&amp;nbsp;issue,&amp;nbsp;using&amp;nbsp;`createPortal`&amp;nbsp;could&amp;nbsp;help&amp;nbsp;ensure&amp;nbsp;that&amp;nbsp;the&amp;nbsp;tooltip&amp;nbsp;content&amp;nbsp;always&amp;nbsp;renders&amp;nbsp;at&amp;nbsp;the&amp;nbsp;root&amp;nbsp;level&amp;nbsp;of&amp;nbsp;the&amp;nbsp;DOM,&amp;nbsp;avoiding&amp;nbsp;any&amp;nbsp;potential&amp;nbsp;stacking&amp;nbsp;context&amp;nbsp;problems&amp;nbsp;caused&amp;nbsp;by&amp;nbsp;intermediate&amp;nbsp;container&amp;nbsp;elements.&lt;br /&gt;&lt;br /&gt;Here's&amp;nbsp;how&amp;nbsp;you&amp;nbsp;might&amp;nbsp;use&amp;nbsp;it&amp;nbsp;in&amp;nbsp;your&amp;nbsp;Sidebar&amp;nbsp;component:&lt;br /&gt;&lt;br /&gt;```jsx&lt;br /&gt;import&amp;nbsp;{&amp;nbsp;createPortal&amp;nbsp;}&amp;nbsp;from&amp;nbsp;'react-dom';&lt;br /&gt;&lt;br /&gt;//&amp;nbsp;Inside&amp;nbsp;your&amp;nbsp;component's&amp;nbsp;return&amp;nbsp;statement&lt;br /&gt;{SIDEBAR_ITEMS.map((item,&amp;nbsp;idx)&amp;nbsp;=&amp;gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;//&amp;nbsp;...&amp;nbsp;other&amp;nbsp;code&amp;nbsp;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;return&amp;nbsp;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Tooltip&amp;nbsp;key={idx}&amp;nbsp;delayDuration={0}&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;TooltipTrigger&amp;nbsp;asChild&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{/*&amp;nbsp;...&amp;nbsp;*/}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/TooltipTrigger&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{createPortal(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;TooltipContent&amp;nbsp;className=&quot;z-50&quot;&amp;nbsp;side=&quot;right&quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{item.title}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/TooltipContent&amp;gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.body&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Tooltip&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;);&lt;br /&gt;})}&lt;br /&gt;```&lt;br /&gt;&lt;br /&gt;This&amp;nbsp;approach&amp;nbsp;would&amp;nbsp;render&amp;nbsp;the&amp;nbsp;tooltip&amp;nbsp;content&amp;nbsp;directly&amp;nbsp;into&amp;nbsp;the&amp;nbsp;document&amp;nbsp;body,&amp;nbsp;ensuring&amp;nbsp;it's&amp;nbsp;not&amp;nbsp;constrained&amp;nbsp;by&amp;nbsp;any&amp;nbsp;parent&amp;nbsp;elements'&amp;nbsp;stacking&amp;nbsp;contexts.&lt;/p&gt;</description>
      <category>Frontend/React</category>
      <category>createPortal</category>
      <category>REACT</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/371</guid>
      <comments>https://reasonjun.tistory.com/371#entry371comment</comments>
      <pubDate>Sat, 13 Jul 2024 22:30:31 +0900</pubDate>
    </item>
    <item>
      <title>Dual Monitor Development Error: Cursor Pointer and Screen Views</title>
      <link>https://reasonjun.tistory.com/370</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Problem :&amp;nbsp;&lt;/b&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;I&amp;nbsp;am&amp;nbsp;currently&amp;nbsp;using&amp;nbsp;an&amp;nbsp;M1&amp;nbsp;PRO&amp;nbsp;MacBook&amp;nbsp;with&amp;nbsp;dual&amp;nbsp;monitors&amp;nbsp;in&amp;nbsp;FULL-HD&amp;nbsp;quality.&amp;nbsp;I&amp;nbsp;have&amp;nbsp;my&amp;nbsp;code&amp;nbsp;on&amp;nbsp;the&amp;nbsp;MacBook&amp;nbsp;screen&amp;nbsp;and&amp;nbsp;the&amp;nbsp;webview&amp;nbsp;on&amp;nbsp;the&amp;nbsp;dual&amp;nbsp;monitors.&amp;nbsp;I&amp;nbsp;thought&amp;nbsp;it&amp;nbsp;would&amp;nbsp;work&amp;nbsp;fine,&amp;nbsp;but&amp;nbsp;the&amp;nbsp;cursor&amp;nbsp;pointer&amp;nbsp;doesn't&amp;nbsp;work&amp;nbsp;in&amp;nbsp;FULL-HD&amp;nbsp;and&amp;nbsp;the&amp;nbsp;CSS&amp;nbsp;event&amp;nbsp;effects&amp;nbsp;look&amp;nbsp;different.&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;m1 pro macbook screen :&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bJrHyC/btsHO1RmcBe/TzvOvIo6eqMpp7FCDC04W0/Screen%20Recording%202024-06-06%20at%205.15.51%E2%80%AFPM.mov?attach=1&amp;amp;knm=tfile.mov&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;Screen Recording 2024-06-06 at 5.15.51 PM.mov&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;4.53MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&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;full-hd screen :&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/baDJBw/btsHQkCcJNv/f0KxFkHYUEqH5uk4ekgtY1/Screen%20Recording%202024-06-06%20at%205.16.25%E2%80%AFPM.mov?attach=1&amp;amp;knm=tfile.mov&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;Screen Recording 2024-06-06 at 5.16.25 PM.mov&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;2.59MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;GPT 4O says it may have the following issues :&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;h3 data-ke-size=&quot;size23&quot;&gt;Explanation for CSS Event and Cursor Pointer Issues on Dual Full-HD Monitors with M1 Pro MacBook&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Using dual monitors with Full-HD resolution on an M1 Pro MacBook, where the MacBook screen displays code and the dual monitor displays a web view, might seem like it should work without issues. However, if the cursor pointer and CSS event effects do not work correctly on the Full-HD monitors, there could be several reasons for this. Here are some possible explanations:&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Resolution and DPI Settings Issue&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Differences in resolution or DPI settings between the MacBook and the dual monitors can cause CSS effects or cursor pointers to not work as expected. This is especially true when using a Retina display and a non-Retina display together.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Solution&lt;/b&gt;: Check the display settings in System Preferences and adjust the resolution and DPI settings. Try matching the resolution of both monitors or adjusting the scaling.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Browser Compatibility Issue&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSS effects might look different on specific browsers or browser versions. In a dual monitor setup, the browser might render differently on each monitor.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Solution&lt;/b&gt;: Test the web page on different browsers to see if the issue is specific to one browser. Update the browser to the latest version or try using a different browser.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. CSS Code Issue&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;There might be issues within the CSS code itself, causing bugs that appear only at certain resolutions.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Solution&lt;/b&gt;: Use media queries in your CSS to apply styles specific to Full-HD resolution. For example:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;@media (max-width: 1920px) {
  .your-class {
    cursor: pointer;
    /* other styles */
  }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. Hardware Acceleration Issue&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The browser's hardware acceleration feature might cause problems, especially in a dual monitor setup.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Solution&lt;/b&gt;: Turn off or on the hardware acceleration in the browser settings and see if this resolves the issue.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. Operating System and Driver Issue&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;There might be issues with the MacBook's operating system or graphics drivers, particularly after a new OS update.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Solution&lt;/b&gt;: Update macOS and graphics drivers to the latest version. Also, recheck the display settings in System Preferences.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. Specific Web Page Issue&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;If the issue occurs only on a specific web page or web application, there might be a problem with the code of that particular page.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Solution&lt;/b&gt;: Inspect the code of the problematic web page and test if the same issue occurs on other pages.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Try these methods one by one to resolve the issue. If the problem persists, please provide more specific information for further assistance.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Error</category>
      <category>cursor-pointer error</category>
      <category>dual monitor css error</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/370</guid>
      <comments>https://reasonjun.tistory.com/370#entry370comment</comments>
      <pubDate>Thu, 6 Jun 2024 17:19:38 +0900</pubDate>
    </item>
    <item>
      <title>ZKP : Practice and Understand</title>
      <link>https://reasonjun.tistory.com/369</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Overview of Zero-Knowledge Proofs (ZKPs)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Zero-Knowledge Proofs (ZKPs) are cryptographic methods that allow a prover to convince a verifier that a given statement is true without revealing any additional information beyond the validity of the statement itself. Key concepts include:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Statement&lt;/b&gt;: The proposition or computation that needs to be proven.&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;842&quot; data-origin-height=&quot;76&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MmVH5/btsHuMFrb2l/RIDke0iUmTBVhvWiNVRfWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MmVH5/btsHuMFrb2l/RIDke0iUmTBVhvWiNVRfWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MmVH5/btsHuMFrb2l/RIDke0iUmTBVhvWiNVRfWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMmVH5%2FbtsHuMFrb2l%2FRIDke0iUmTBVhvWiNVRfWk%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;421&quot; height=&quot;38&quot; data-origin-width=&quot;842&quot; data-origin-height=&quot;76&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;b&gt;Witness&lt;/b&gt;: The private information that proves the statement.&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;360&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dHnZLh/btsHublppmD/LLv9DhsFjhly8TjXgkjN50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dHnZLh/btsHublppmD/LLv9DhsFjhly8TjXgkjN50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dHnZLh/btsHublppmD/LLv9DhsFjhly8TjXgkjN50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdHnZLh%2FbtsHublppmD%2FLLv9DhsFjhly8TjXgkjN50%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;191&quot; height=&quot;69&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;130&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;b&gt;Prover&lt;/b&gt;: The entity that proves the statement.&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;750&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIhCzm/btsHtdxSqmo/5OBYUIGqkVBf5FLnYfF8U0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIhCzm/btsHtdxSqmo/5OBYUIGqkVBf5FLnYfF8U0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIhCzm/btsHtdxSqmo/5OBYUIGqkVBf5FLnYfF8U0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIhCzm%2FbtsHtdxSqmo%2F5OBYUIGqkVBf5FLnYfF8U0%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;261&quot; height=&quot;140&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;402&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;b&gt;Verifier&lt;/b&gt;: The entity that verifies the proof.&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;968&quot; data-origin-height=&quot;446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Te9am/btsHtgOOnTM/ITKKIdIP84f9xmMSEOhLJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Te9am/btsHtgOOnTM/ITKKIdIP84f9xmMSEOhLJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Te9am/btsHtgOOnTM/ITKKIdIP84f9xmMSEOhLJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTe9am%2FbtsHtgOOnTM%2FITKKIdIP84f9xmMSEOhLJK%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;324&quot; height=&quot;149&quot; data-origin-width=&quot;968&quot; data-origin-height=&quot;446&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Writing the Circuit (Arithmetic Constraints)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Circom is a domain-specific language for defining arithmetic circuits that represent the constraints of a ZKP. The example circuit provided is as follows:&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;pragma circom 2.0.0;

template Demo() {
    signal input x;
    signal input y;
    signal input z;
    signal input out;
    signal T1;
    T1 &amp;lt;== (x - 2) * (y + 3);
    signal T2;
    T2 &amp;lt;== (z + 4) * (z + 5);
    out === T1 * T2 + 6;
}

component main {public [out]} = Demo();

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This circuit takes inputs x, y, and z, and calculates intermediate signals T1 and T2, which are then used to compute the output out. The constraints ensure that the output is correctly derived from the inputs according to the defined arithmetic operations.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Installing Circom and Snarkjs&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Circom and Snarkjs are essential tools for compiling circuits and generating proofs. The installation steps are as follows:&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# Install Circom
git clone &amp;lt;https://github.com/iden3/circom.git&amp;gt;
cd circom
cargo build --release

# Install Snarkjs
git clone &amp;lt;https://github.com/iden3/snarkjs.git&amp;gt;
cd snarkjs
npm install
npm run build

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Circom is a Rust-based compiler for arithmetic circuits, while Snarkjs is a JavaScript library for generating and verifying zk-SNARKs.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Compiling the Circuit&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Once the circuit is written, it needs to be compiled into an R1CS (Rank-1 Constraint System) file, which represents the constraints of the circuit.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;~/circom/target/release/circom --r1cs --sym --json --O0 --output build demo.circom

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This command compiles demo.circom into several files:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;demo.r1cs: The constraints of the circuit.&lt;/li&gt;
&lt;li&gt;demo.sym: Symbolic representation of the circuit.&lt;/li&gt;
&lt;li&gt;demo.json: JSON representation of the circuit.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. Inspecting the Constraints&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Snarkjs can be used to inspect the constraints defined in the R1CS file.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;~/snarkjs/build/cli.cjs r1cs print build/demo.r1cs build/demo.sym

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This command prints out the constraints in a human-readable format, allowing you to verify that the circuit was compiled correctly.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. Calculating the Witness&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The witness is a set of values that satisfy the circuit's constraints given certain inputs. The witness is computed using a WebAssembly (WASM) file generated by Circom.&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;# Generate the witness
node build/demo_js/generate_witness.js build/demo_js/demo.wasm input.json build/demo_js/witness.wtns

# Export the witness to JSON
~/snarkjs/build/cli.cjs wtns export json build/demo_js/witness.wtns wtns.json

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;input.json contains the input values for the circuit, and witness.wtns is the computed witness file.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. Setting Up (Proving and Verification Keys)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Using the Groth16 protocol, you generate proving and verification keys. These keys are essential for creating and verifying proofs.&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;# Generate proving and verification keys
~/snarkjs/build/cli.cjs groth16 setup build/demo.r1cs ptau_file demo.zkey

# Export the verification key
~/snarkjs/build/cli.cjs zkey export verificationkey demo.zkey vk.json

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ptau_file is a Powers of Tau file used for the initial setup. demo.zkey contains the proving and verification keys.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. Generating and Verifying the Proof&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;With the proving key, you can generate a proof, and with the verification key, you can verify it.&lt;/p&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;# Generate the proof
~/snarkjs/build/cli.cjs groth16 prove demo.zkey build/demo_js/witness.wtns proof.json public.json

# Verify the proof
~/snarkjs/build/cli.cjs groth16 verify vk.json public.json proof.json

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;proof.json contains the generated proof, and public.json contains the public inputs. The verification step checks if the proof is valid given the public inputs and the verification key.&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;style7&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1452&quot; data-origin-height=&quot;960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdHrS3/btsHvszIpXO/SHI9n5XwU09Wjt0NKNdt6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdHrS3/btsHvszIpXO/SHI9n5XwU09Wjt0NKNdt6k/img.png&quot; data-alt=&quot;https://hackmd.io/@vTR2f7tjRgKq_E5Vfkw_vw/rJHd5NyHp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdHrS3/btsHvszIpXO/SHI9n5XwU09Wjt0NKNdt6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdHrS3%2FbtsHvszIpXO%2FSHI9n5XwU09Wjt0NKNdt6k%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;1452&quot; height=&quot;960&quot; data-origin-width=&quot;1452&quot; data-origin-height=&quot;960&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://hackmd.io/@vTR2f7tjRgKq_E5Vfkw_vw/rJHd5NyHp&lt;/figcaption&gt;
&lt;/figure&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. Flatten the Problem Polynomial and Construct the Corresponding Circuit&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This step is performed by the upper-level application and involves the following tasks:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Flattening the Problem Polynomial&lt;/b&gt;: This involves transforming the problem into a polynomial form that can be expressed as a circuit. For example, breaking down a complex computation into a series of simple arithmetic operations.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Constructing the Circuit&lt;/b&gt;: Based on the flattened polynomial, a logical circuit is designed. This circuit consists of inputs, outputs, and a series of gates (operations) that perform the necessary computations.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Generate R1CS (Rank-1 Constraint System) According to the Circuit&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;R1CS is a system of constraints that represents the circuit. Each constraint is expressed using three vectors &lt;u&gt;&lt;b&gt;a, b, c&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;and must satisfy the following equation:&lt;/p&gt;
&lt;pre id=&quot;code_1716119577339&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;a,z&amp;gt;&amp;middot;&amp;lt;b,z&amp;gt; = &amp;lt;c,z&amp;gt;&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;where &lt;u&gt;&lt;b&gt;z&lt;/b&gt;&lt;/u&gt; is a vector that includes all&amp;nbsp;variables and 1. In this step, each gate and connection in the circuit is translated into an R1CS constraint, creating a system of equations that the circuit must satisfy.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Convert R1CS to QAP (Quadratic Arithmetic Program)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;QAP is a polynomial-based constraint system derived from R1CS. The conversion process involves:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Traditional Lagrange Interpolation&lt;/b&gt;: This method finds polynomials that pass through a given set of points. However, it can be computationally expensive.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Fast Fourier Transform (FFT)&lt;/b&gt;: FFT is an algorithm that can quickly evaluate and interpolate polynomials. Using FFT, the polynomials &lt;u&gt;&lt;b&gt;A(x), B(x), C(x)&lt;/b&gt;&lt;/u&gt; for the QAP can be generated more efficiently, reducing the computational complexity to &lt;u&gt;&lt;b&gt;O(n log n)&lt;/b&gt;&lt;/u&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. Setup Parameters of the QAP Problem, i.e., CRS (Common Reference Strings)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CRS are common reference strings that include parameters necessary for proof generation and verification. This step involves:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Generating the CRS&lt;/b&gt;: Based on the QAP polynomials, the CRS is generated.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Setting Common Parameters&lt;/b&gt;: The generated CRS is used to establish common parameters that both the prover and verifier will use.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. Create Proof Based on CRS and Input&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In this step, the proof is generated using the CRS and the input values:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Preparing Inputs&lt;/b&gt;: The inputs to the circuit are prepared.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Generating the Proof&lt;/b&gt;: Using the prepared inputs and the CRS, the proof is generated. This involves using the QAP polynomials and the input values to produce proof data.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Proof Data&lt;/b&gt;: The generated proof data is in a format that can be verified by the verifier.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. Verify Proof&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The verification step involves the following tasks:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Receiving Proof Data&lt;/b&gt;: The verifier receives the proof data generated by the prover.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Verification Process&lt;/b&gt;: Using the received proof data and the CRS, the verifier checks the validity of the proof. This involves using the QAP polynomials and the common parameters to ensure the proof is correct.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Result Confirmation&lt;/b&gt;: Based on the verification process, the verifier determines whether the proof is valid. If valid, it confirms that the statement being proven is true.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Summary&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This overall process is designed to securely prove and verify complex computational problems. Each step transforms the problem into a polynomial form, generates a constraint system (R1CS), converts it to a polynomial-based system (QAP), and uses common reference strings (CRS) to efficiently generate and verify proofs. Using Fast Fourier Transform (FFT) reduces computational complexity, making the proof generation and verification process more efficient. The CRS enables both the prover and verifier to use common parameters, ensuring the integrity and security of the proof system.&lt;/p&gt;</description>
      <category>Blockchain/Words</category>
      <category>crs</category>
      <category>FFT</category>
      <category>qap</category>
      <category>ZKP</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/369</guid>
      <comments>https://reasonjun.tistory.com/369#entry369comment</comments>
      <pubDate>Sun, 19 May 2024 20:44:10 +0900</pubDate>
    </item>
    <item>
      <title>Nextjs 14 &amp;amp; Clerk V5 beta &amp;amp; middleware Problem</title>
      <link>https://reasonjun.tistory.com/368</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;error :&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;1982&quot; data-origin-height=&quot;1094&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boLsgy/btsFm1lrddM/SySjygMmUoKdCxif0eO55k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boLsgy/btsFm1lrddM/SySjygMmUoKdCxif0eO55k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boLsgy/btsFm1lrddM/SySjygMmUoKdCxif0eO55k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboLsgy%2FbtsFm1lrddM%2FSySjygMmUoKdCxif0eO55k%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;1982&quot; height=&quot;1094&quot; data-origin-width=&quot;1982&quot; data-origin-height=&quot;1094&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7lTX6/btsFsbNRhXQ/KsxABDHFOABbey6eZ16K2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7lTX6/btsFsbNRhXQ/KsxABDHFOABbey6eZ16K2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7lTX6/btsFsbNRhXQ/KsxABDHFOABbey6eZ16K2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7lTX6%2FbtsFsbNRhXQ%2FKsxABDHFOABbey6eZ16K2K%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;2008&quot; height=&quot;1202&quot; data-origin-width=&quot;2008&quot; data-origin-height=&quot;1202&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;While&amp;nbsp;setting&amp;nbsp;up&amp;nbsp;the&amp;nbsp;middleware&amp;nbsp;to&amp;nbsp;utilize&amp;nbsp;the&amp;nbsp;new&amp;nbsp;clerk,&amp;nbsp;I&amp;nbsp;created&amp;nbsp;the&amp;nbsp;middleware&amp;nbsp;with&amp;nbsp;a&amp;nbsp;different&amp;nbsp;name&amp;nbsp;so&amp;nbsp;that&amp;nbsp;it&amp;nbsp;would&amp;nbsp;not&amp;nbsp;be&amp;nbsp;activated&amp;nbsp;for&amp;nbsp;ease&amp;nbsp;of&amp;nbsp;development.&amp;nbsp;Then&amp;nbsp;the&amp;nbsp;above&amp;nbsp;error&amp;nbsp;occurred.&amp;nbsp;When&amp;nbsp;I&amp;nbsp;checked,&amp;nbsp;the&amp;nbsp;clerk&amp;nbsp;was&amp;nbsp;using&amp;nbsp;its&amp;nbsp;own&amp;nbsp;jwt&amp;nbsp;system&amp;nbsp;and&amp;nbsp;was&amp;nbsp;unable&amp;nbsp;to&amp;nbsp;retrieve&amp;nbsp;session&amp;nbsp;data&amp;nbsp;as&amp;nbsp;a&amp;nbsp;header,&amp;nbsp;so&amp;nbsp;it&amp;nbsp;was&amp;nbsp;relying&amp;nbsp;on&amp;nbsp;the&amp;nbsp;auth&amp;nbsp;system&amp;nbsp;in&amp;nbsp;middleware.&amp;nbsp;Therefore,&amp;nbsp;the&amp;nbsp;server&amp;nbsp;side&amp;nbsp;clerk&amp;nbsp;module&amp;nbsp;could&amp;nbsp;not&amp;nbsp;be&amp;nbsp;used&amp;nbsp;unless&amp;nbsp;middleware&amp;nbsp;was&amp;nbsp;activated.&amp;nbsp;After&amp;nbsp;reactivating&amp;nbsp;middlware,&amp;nbsp;the&amp;nbsp;above&amp;nbsp;code&amp;nbsp;worked&amp;nbsp;normally.&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;2246&quot; data-origin-height=&quot;1210&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDCBf2/btsFs1xrsHw/Bob86sj0Fg5AhQrWsTe5O1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDCBf2/btsFs1xrsHw/Bob86sj0Fg5AhQrWsTe5O1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDCBf2/btsFs1xrsHw/Bob86sj0Fg5AhQrWsTe5O1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDCBf2%2FbtsFs1xrsHw%2FBob86sj0Fg5AhQrWsTe5O1%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;2246&quot; height=&quot;1210&quot; data-origin-width=&quot;2246&quot; data-origin-height=&quot;1210&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Frontend/Next.js</category>
      <category>clerk v5</category>
      <category>nextjs14</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/368</guid>
      <comments>https://reasonjun.tistory.com/368#entry368comment</comments>
      <pubDate>Sat, 2 Mar 2024 00:36:17 +0900</pubDate>
    </item>
    <item>
      <title>Tailwindcss : justify-center and Accordian height Problem</title>
      <link>https://reasonjun.tistory.com/367</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Problem :&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In the CSS code surrounding the outermost tag as shown below, justify-center provided a problem with height when accordian was activated.&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;1374&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbbFLg/btsE934iOtc/ZGIehpXOLXhvtevEo7odHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbbFLg/btsE934iOtc/ZGIehpXOLXhvtevEo7odHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbbFLg/btsE934iOtc/ZGIehpXOLXhvtevEo7odHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbbFLg%2FbtsE934iOtc%2FZGIehpXOLXhvtevEo7odHk%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;1374&quot; height=&quot;122&quot; data-origin-width=&quot;1374&quot; data-origin-height=&quot;122&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;size16&quot;&gt;When justify-center is applied in h-screen, the top component is cut off when Accordian, which provides dynamic height, is activated.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2502&quot; data-origin-height=&quot;1266&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Lox5n/btsFbfDiBzh/9AyYCa5aPAbPQRVMKU4RFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Lox5n/btsFbfDiBzh/9AyYCa5aPAbPQRVMKU4RFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Lox5n/btsFbfDiBzh/9AyYCa5aPAbPQRVMKU4RFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLox5n%2FbtsFbfDiBzh%2F9AyYCa5aPAbPQRVMKU4RFK%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;2502&quot; height=&quot;1266&quot; data-origin-width=&quot;2502&quot; data-origin-height=&quot;1266&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;Solution :&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When justify-center was removed, the height value was modified based on the content, and no components were cut off even when Accordian was activated.&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;2136&quot; data-origin-height=&quot;1804&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d1iiFy/btsE7vAu4lA/7O334PL6iCkdylB9k1K5OK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d1iiFy/btsE7vAu4lA/7O334PL6iCkdylB9k1K5OK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d1iiFy/btsE7vAu4lA/7O334PL6iCkdylB9k1K5OK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd1iiFy%2FbtsE7vAu4lA%2F7O334PL6iCkdylB9k1K5OK%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;2136&quot; height=&quot;1804&quot; data-origin-width=&quot;2136&quot; data-origin-height=&quot;1804&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Frontend/Tailwindcss</category>
      <category>accordian</category>
      <category>justify-center</category>
      <category>shadcn</category>
      <category>tailwindcss</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/367</guid>
      <comments>https://reasonjun.tistory.com/367#entry367comment</comments>
      <pubDate>Wed, 21 Feb 2024 18:48:32 +0900</pubDate>
    </item>
    <item>
      <title>Drizzle ORM - SQL Types</title>
      <link>https://reasonjun.tistory.com/366</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Integer&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Signed 4 Bytes&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1707031222182&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const testTable = pgTable(&quot;testTable&quot;, {
qty: integer(&quot;qty&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;Signed 2 Bytes&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1707031226154&quot; class=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;export const testTable = pgTable(&quot;testTable&quot;, {
qty: smallint(&quot;qty&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;Signed 8 Bytes&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1707031247234&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const testTable = pgTable(&quot;testTable&quot;, {
qty: bigint(&quot;qty&quot;, {mode: &quot;number&quot;})
// {mode: &quot;number&quot;} : 2^31 &amp;lt; number &amp;lt; 2^53
// {mode: &quot;bigint&quot;} : 2^63 &amp;lt; number &amp;lt; 2^63
})&lt;/code&gt;&lt;/pre&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;b&gt;serial&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;serial / serial4 : is an auto-incrementing 4-byte integer generally used for creating unique identifiers.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1707031282186&quot; class=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;export const testTable = pgTable(&quot;testTable&quot;, {
id: serial(&quot;id&quot;&quot;).primaryKey(),
})&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;smallserial / serial2 : is an auto-incrementing 2-byte integer&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1707031326048&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const testTable = pgTable(&quot;testTable&quot;, {
id: smallserial(&quot;id&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;bigserial / serial8 : is an auto-incrementing 8-byte integer suitable for larger ranges of integers.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1707031337334&quot; class=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;export const testTable = pgTable(&quot;testTable&quot;, {
id: bigserial(&quot;id&quot;, {mode: &quot;bigint&quot;}).primaryKey(),
})&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;decimal&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The decimal type in Drizzle ORM is an alias for the numeric type, and it is used to represent exact numerics with selectable precision. This means that it can store numbers with a very large number of digits, up to 131072 digits before the decimal point and up to 16383 digits after the decimal point&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1707031388502&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const testTable = pgTable(&quot;testTable&quot;, {
price: decimal(&quot;price&quot;, {precision:7, scale:2}) // 12345.67
===
price: numeric(&quot;price&quot;, {precision:7, scale:2}) // 12345.67
})&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;real / float4&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Single precision floating-point number (4 bytes)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IE-37 to IE+37&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6 decimal digits precision&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;It follows IEEE 754, and some errors may occur when dealing with floating point types.&lt;br /&gt;It&amp;nbsp;cannot&amp;nbsp;be&amp;nbsp;converted&amp;nbsp;accurately&amp;nbsp;and&amp;nbsp;is&amp;nbsp;stored&amp;nbsp;as&amp;nbsp;an&amp;nbsp;approximate&amp;nbsp;value,&amp;nbsp;so&amp;nbsp;it&amp;nbsp;is&amp;nbsp;not&amp;nbsp;suitable&amp;nbsp;for&amp;nbsp;exact&amp;nbsp;calculations.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1707031476098&quot; class=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;export const testTable = pgTable(&quot;testTable&quot;, {
	score: real(&quot;score&quot;)
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;double presition / float8&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;Double precision floating-point number (8 bytes)&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;15 decimal digits precision&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;=&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1707110809269&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const testTable = pgTable(&quot;testTable&quot;, {
	score: doublePrecision(&quot;score&quot;)
})&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>drizzle</category>
      <category>orm</category>
      <category>PostgreSQL</category>
      <category>Type</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/366</guid>
      <comments>https://reasonjun.tistory.com/366#entry366comment</comments>
      <pubDate>Mon, 5 Feb 2024 14:27:44 +0900</pubDate>
    </item>
    <item>
      <title>Defi : Atomic Swap</title>
      <link>https://reasonjun.tistory.com/365</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;What are they?&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;Imagine trading directly with someone holding a different cryptocurrency than yours,&amp;nbsp;without worrying about counterparty risk or needing a trusted third party like an exchange.&amp;nbsp;That's what atomic swaps allow you to do.&lt;/li&gt;
&lt;li&gt;They leverage &quot;Hashed Timelock Contracts (HTLCs),&quot; smart contracts on each blockchain that act as temporary vaults holding both parties' assets.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;How do they work?&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Agreement &amp;amp; Preperation:&lt;/b&gt;&amp;nbsp;Two parties agree on the swap terms (amount,&amp;nbsp;currencies,&amp;nbsp;time limit) and use dedicated wallets or platforms supporting atomic swaps.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Depositing Assets:&lt;/b&gt;&amp;nbsp;Both parties lock their designated amount of crypto into separate HTLCs on their respective blockchains.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Timelock and Exchange:&lt;/b&gt;&amp;nbsp;Each HTLC sets a time limit for the other party to complete the swap.&amp;nbsp;If both deposits happen within the timeframe,&amp;nbsp;the HTLCs release the assets to the recipient's respective blockchain.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Refund or Timeout:&lt;/b&gt;&amp;nbsp;If either party fails to deposit within the set time,&amp;nbsp;the HTLCs automatically return the locked assets to their original owners.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Benefits of Atomic Swaps:&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;&lt;b&gt;Decentralization:&lt;/b&gt;&amp;nbsp;Eliminates the need for centralized exchanges,&amp;nbsp;promoting individual control and trustless peer-to-peer transactions.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Greater Liquidity:&lt;/b&gt;&amp;nbsp;Enables trading between tokens on different blockchains,&amp;nbsp;unlocking previously isolated liquidity pools.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Security:&lt;/b&gt;&amp;nbsp;HTLCs ensure no party loses their assets unless the swap completes successfully,&amp;nbsp;minimizing counterparty risk.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Privacy:&lt;/b&gt;&amp;nbsp;Direct peer-to-peer transactions potentially enhance privacy compared to exchange usage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Challenges and Future:&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;&lt;b&gt;Limited Support:&lt;/b&gt;&amp;nbsp;Atomic swaps are still a relatively new technology,&amp;nbsp;and support for diverse token pairs and platforms is evolving.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Technical Complexity:&lt;/b&gt;&amp;nbsp;Setting up and using atomic swaps can be more complex than traditional exchange trading,&amp;nbsp;requiring some technical knowledge.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Security Considerations:&lt;/b&gt;&amp;nbsp;While secure in principle,&amp;nbsp;vulnerabilities could exist in specific implementations or smart contract code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Despite these challenges, atomic swaps represent a significant step forward in decentralized finance and cross-chain interoperability. As the technology matures and gains wider adoption, it has the potential to revolutionize how we trade and interact with digital assets across different blockchains.&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://chain.link/education-hub/atomic-swaps#:~:text=Atomic%20swaps%20are%20a%20way,the%20multi%2Dchain%20Web3%20ecosystem.&quot;&gt;https://chain.link/education-hub/atomic-swaps#:~:text=Atomic%20swaps%20are%20a%20way,the%20multi%2Dchain%20Web3%20ecosystem.&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;</description>
      <category>Blockchain/Defi</category>
      <category>Atomic swap</category>
      <category>defi</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/365</guid>
      <comments>https://reasonjun.tistory.com/365#entry365comment</comments>
      <pubDate>Thu, 18 Jan 2024 12:28:24 +0900</pubDate>
    </item>
    <item>
      <title>Ethereum : Gas / EIP-1559</title>
      <link>https://reasonjun.tistory.com/364</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Gas&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This&amp;nbsp;refers&amp;nbsp;to&amp;nbsp;the&amp;nbsp;value&amp;nbsp;used&amp;nbsp;for&amp;nbsp;fees&amp;nbsp;in&amp;nbsp;Ethereum.&amp;nbsp;The&amp;nbsp;fee&amp;nbsp;is&amp;nbsp;calculated&amp;nbsp;by&amp;nbsp;converting&amp;nbsp;the&amp;nbsp;Byte&amp;nbsp;Code&amp;nbsp;that&amp;nbsp;appears&amp;nbsp;when&amp;nbsp;the&amp;nbsp;code&amp;nbsp;in&amp;nbsp;the&amp;nbsp;Smart&amp;nbsp;Contract&amp;nbsp;is&amp;nbsp;complied&amp;nbsp;into&amp;nbsp;the&amp;nbsp;Gas&amp;nbsp;value&amp;nbsp;specified&amp;nbsp;in&amp;nbsp;the&amp;nbsp;OP_CODE&amp;nbsp;table.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Gas Limit(Used)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gas&amp;nbsp;Limit&amp;nbsp;is&amp;nbsp;divided&amp;nbsp;into&amp;nbsp;Block&amp;nbsp;Gas&amp;nbsp;Limit&amp;nbsp;and&amp;nbsp;Transaction&amp;nbsp;Gas&amp;nbsp;Used.&amp;nbsp;Block&amp;nbsp;Gas&amp;nbsp;Limit&amp;nbsp;means&amp;nbsp;the&amp;nbsp;sum&amp;nbsp;of&amp;nbsp;the&amp;nbsp;total&amp;nbsp;Transaction&amp;nbsp;Gas&amp;nbsp;Used&amp;nbsp;in&amp;nbsp;the&amp;nbsp;corresponding&amp;nbsp;block,&amp;nbsp;and&amp;nbsp;Transaction&amp;nbsp;Gas&amp;nbsp;Used&amp;nbsp;is&amp;nbsp;the&amp;nbsp;total&amp;nbsp;amount&amp;nbsp;of&amp;nbsp;Gas&amp;nbsp;used&amp;nbsp;in&amp;nbsp;executing&amp;nbsp;the&amp;nbsp;corresponding&amp;nbsp;transaction.&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;b&gt;Gas Price&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gas&amp;nbsp;Price&amp;nbsp;is&amp;nbsp;a&amp;nbsp;value&amp;nbsp;used&amp;nbsp;to&amp;nbsp;determine&amp;nbsp;how&amp;nbsp;quickly&amp;nbsp;the&amp;nbsp;transaction&amp;nbsp;will&amp;nbsp;be&amp;nbsp;executed.&amp;nbsp;The&amp;nbsp;minimum&amp;nbsp;Gas&amp;nbsp;Price&amp;nbsp;value&amp;nbsp;changes&amp;nbsp;dynamically&amp;nbsp;depending&amp;nbsp;on&amp;nbsp;the&amp;nbsp;network&amp;nbsp;status.&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;b&gt;EIP-1559&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EIP-1559, implemented in August 2021, marked a significant upgrade for Ethereum by overhauling how transaction fees, aka &quot;gas fees,&quot; are calculated and processed. Here's a breakdown of its key features and impacts:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Before EIP-1559:&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;&lt;b&gt;Auction-based fees:&lt;/b&gt;&amp;nbsp;Users bid on gas prices,&amp;nbsp;leading to unpredictable costs and favoring miners willing to accept lower fees,&amp;nbsp;potentially delaying transactions.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Volatile fee market:&lt;/b&gt;&amp;nbsp;Difficulty estimating fees,&amp;nbsp;discouraging casual users and hindering ecosystem growth.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Miner-centric:&lt;/b&gt;&amp;nbsp;Miners captured most of the fees,&amp;nbsp;potentially impacting Ethereum's long-term value proposition.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;EIP-1559 introduces a new fee structure:&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;&lt;b&gt;Base fee:&lt;/b&gt;&amp;nbsp;A dynamic,&amp;nbsp;algorithm-determined fee for inclusion in the next block,&amp;nbsp;adjusting based on network congestion.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Max fee:&lt;/b&gt;&amp;nbsp;Users specify the maximum they're willing to pay,&amp;nbsp;including a &quot;tip&quot; for miners for faster processing.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Priority fee:&lt;/b&gt;&amp;nbsp;Optional tip portion of the max fee to incentivize miners.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Burn mechanism:&lt;/b&gt;&amp;nbsp;Portions of the base fee are permanently burned,&amp;nbsp;reducing ETH supply over time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Impacts of EIP-1559:&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;&lt;b&gt;More predictable fees:&lt;/b&gt;&amp;nbsp;Base fee provides a baseline,&amp;nbsp;improving cost estimation and user experience.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Smoother fee market:&lt;/b&gt;&amp;nbsp;Dynamic base fee adjusts to demand,&amp;nbsp;potentially decreasing volatility.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Reduced fee capture for miners:&lt;/b&gt;&amp;nbsp;Transitioning to a more predictable and value-driven fee model.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Potential deflationary effect:&lt;/b&gt;&amp;nbsp;Burning base fees can decrease ETH supply in the long run,&amp;nbsp;impacting its value.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Overall, EIP-1559 aims to achieve:&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;&lt;b&gt;Fairer and more efficient fee market:&lt;/b&gt;&amp;nbsp;Balancing user needs,&amp;nbsp;miner incentives,&amp;nbsp;and network stability.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Enhanced user experience:&lt;/b&gt;&amp;nbsp;Making fee estimation and transaction planning easier.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Sustainable economic model:&lt;/b&gt;&amp;nbsp;Introducing a potential deflationary mechanism for Ethereum.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=MGemhK9t44Q&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=MGemhK9t44Q&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=MGemhK9t44Q&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bsuyhP/hyU5Op41fJ/XYiUQglduY0U9vKpkSqt9K/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Can ETH Become DEFLATIONARY? EIP 1559 Explained&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/MGemhK9t44Q&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Base Fee&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This&amp;nbsp;is&amp;nbsp;the&amp;nbsp;basic&amp;nbsp;fee&amp;nbsp;amount&amp;nbsp;to&amp;nbsp;be&amp;nbsp;provided&amp;nbsp;to&amp;nbsp;miners.&amp;nbsp;The&amp;nbsp;next&amp;nbsp;Base&amp;nbsp;Fee&amp;nbsp;is&amp;nbsp;calculated&amp;nbsp;depending&amp;nbsp;on&amp;nbsp;how&amp;nbsp;many&amp;nbsp;transactions&amp;nbsp;were&amp;nbsp;filled&amp;nbsp;in&amp;nbsp;the&amp;nbsp;previous&amp;nbsp;Block,&amp;nbsp;and&amp;nbsp;can&amp;nbsp;increase&amp;nbsp;or&amp;nbsp;decrease&amp;nbsp;by&amp;nbsp;up&amp;nbsp;to&amp;nbsp;12.5%.&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;b&gt;Max Priority Fee&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This&amp;nbsp;is&amp;nbsp;the&amp;nbsp;amount&amp;nbsp;of&amp;nbsp;fee&amp;nbsp;to&amp;nbsp;be&amp;nbsp;provided&amp;nbsp;to&amp;nbsp;the&amp;nbsp;miner&amp;nbsp;in&amp;nbsp;addition&amp;nbsp;to&amp;nbsp;the&amp;nbsp;base&amp;nbsp;fee.&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;b&gt;Max Fee Per Gas&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This&amp;nbsp;is&amp;nbsp;the&amp;nbsp;maximum&amp;nbsp;Gas&amp;nbsp;Price&amp;nbsp;value&amp;nbsp;that&amp;nbsp;can&amp;nbsp;be&amp;nbsp;provided&amp;nbsp;to&amp;nbsp;miners.&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;b&gt;Fee&amp;nbsp;calculation&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;min ( MaxFee - BaseFee, MaxPriorityFee)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Blockchain/Ethereum</category>
      <category>EIP-1559</category>
      <category>Ethereum</category>
      <category>gas</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/364</guid>
      <comments>https://reasonjun.tistory.com/364#entry364comment</comments>
      <pubDate>Wed, 17 Jan 2024 19:53:57 +0900</pubDate>
    </item>
    <item>
      <title>Ethereum: EIP-2770 (Standardizing Meta Transactions in Ethereum)</title>
      <link>https://reasonjun.tistory.com/363</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;EIP-2770 is a proposed Ethereum Improvement Proposal (EIP) aimed at standardizing the way meta transactions are executed within the Ethereum ecosystem. Meta transactions enable users to sign and submit transactions to the blockchain without having to pay the gas fees themselves. This can be beneficial for various reasons, like:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Reducing barriers to entry&lt;/b&gt;:&amp;nbsp;By removing the gas fee burden,&amp;nbsp;EIP-2770 could make it easier for new users to interact with dApps and experience the benefits of blockchain technology.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Improving accessibility&lt;/b&gt;:&amp;nbsp;EIP-2770 can be particularly helpful for users with limited resources,&amp;nbsp;such as those in developing countries or with low computing power.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Enabling innovative applications&lt;/b&gt;:&amp;nbsp;The ability to offload gas fees opens up possibilities for new dApp functionalities,&amp;nbsp;such as micropayments,&amp;nbsp;loyalty programs,&amp;nbsp;and subscription services.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;How does EIP-2770 work?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EIP-2770 defines a standard interface for &quot;forwarder contracts.&quot; These contracts act as intermediaries between the actual user (signer) and the target smart contract they wish to interact with. When a user wants to initiate a meta transaction:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;They sign the transaction data and a special permit message using their private key.&lt;/li&gt;
&lt;li&gt;The signature and permit message are sent to the forwarder contract.&lt;/li&gt;
&lt;li&gt;The forwarder contract verifies the signature and uses its own funds to pay the gas fees for the transaction.&lt;/li&gt;
&lt;li&gt;The transaction is submitted to the Ethereum blockchain for execution.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Current status of EIP-2770:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;While EIP-2770 was proposed in 2021, it hasn't yet been officially adopted by the Ethereum community. There are ongoing discussions about its technical merits and potential downsides.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Some concerns regarding EIP-2770 include:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Centralization&lt;/b&gt;:&amp;nbsp;Forwarder contracts introduce a centralized point of failure,&amp;nbsp;which could potentially compromise the security and censorship resistance of the Ethereum network.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Security vulnerabilities&lt;/b&gt;:&amp;nbsp;As with any smart contract functionality,&amp;nbsp;there's a risk of bugs or vulnerabilities within the forwarder contracts that could be exploited by attackers.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Potential for abuse&lt;/b&gt;:&amp;nbsp;Malicious actors could potentially use meta transactions to spam the network or engage in other harmful activities.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Despite these concerns, EIP-2770 continues to be a topic of active discussion within the Ethereum community. Its potential benefits for usability and adoption are making it a serious contender for future integration into the Ethereum protocol.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Additional resources:&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;EIP-2770 specification:&amp;nbsp;&lt;a href=&quot;https://github.com/ethereum/EIPs/issues/2585&quot;&gt;https://github.com/ethereum/EIPs/issues/2585&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Discussion on OpenZeppelin forum:&amp;nbsp;&lt;a href=&quot;https://ethereum.stackexchange.com/questions/119462/eip-2771-is-it-possible-to-pay-a-function-with-froms-eth-not-the-forwarder-co&quot;&gt;https://ethereum.stackexchange.com/questions/119462/eip-2771-is-it-possible-to-pay-a-function-with-froms-eth-not-the-forwarder-co&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Article on Medium:&amp;nbsp;&lt;a href=&quot;https://medium.com/biconomy/the-meta-transaction-flow-ed98cd750ef0&quot;&gt;https://medium.com/biconomy/the-meta-transaction-flow-ed98cd750ef0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Blockchain/Ethereum</category>
      <category>eip-2770</category>
      <category>Ethereum</category>
      <category>meta transaction</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/363</guid>
      <comments>https://reasonjun.tistory.com/363#entry363comment</comments>
      <pubDate>Wed, 17 Jan 2024 00:12:39 +0900</pubDate>
    </item>
    <item>
      <title>Ethereum : Transaction Receipt</title>
      <link>https://reasonjun.tistory.com/362</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1858&quot; data-origin-height=&quot;944&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OHPT3/btsDBzvQi12/UDrhJs7mTu7knHIAaA6Bn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OHPT3/btsDBzvQi12/UDrhJs7mTu7knHIAaA6Bn0/img.png&quot; data-alt=&quot;https://github.com/ethereum/go-ethereum/blob/master/core/types/receipt.go&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OHPT3/btsDBzvQi12/UDrhJs7mTu7knHIAaA6Bn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOHPT3%2FbtsDBzvQi12%2FUDrhJs7mTu7knHIAaA6Bn0%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;1858&quot; height=&quot;944&quot; data-origin-width=&quot;1858&quot; data-origin-height=&quot;944&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://github.com/ethereum/go-ethereum/blob/master/core/types/receipt.go&lt;/figcaption&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;b&gt;Type:&lt;/b&gt;&amp;nbsp;The type of transaction (e.g.,&amp;nbsp;LegacyTxType,&amp;nbsp;AccessListTxType).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PostState:&lt;/b&gt;&amp;nbsp;The root hash of the world state after transaction execution.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Status:&lt;/b&gt;&amp;nbsp;The transaction's status (1 for success,&amp;nbsp;0 for failure).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CumulativeGasUsed:&lt;/b&gt;&amp;nbsp;Total gas used by the transaction and its sub-transactions.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Bloom:&lt;/b&gt;&amp;nbsp;A Bloom filter for efficient retrieval of logs matching specific topics.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Logs:&lt;/b&gt;&amp;nbsp;An array of logs emitted during transaction execution.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TxHash:&lt;/b&gt;&amp;nbsp;Hash of the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ContractAddress:&lt;/b&gt;&amp;nbsp;Address of the created contract (if applicable).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GasUsed:&lt;/b&gt;&amp;nbsp;Gas used by the transaction itself.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;EffectiveGasPrice:&lt;/b&gt;&amp;nbsp;Effective gas price paid for the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BlobGasUsed:&lt;/b&gt;&amp;nbsp;Gas used for any internal calls or contract creation (EIP-4399).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BlobGasPrice:&lt;/b&gt;&amp;nbsp;Gas price for blob transactions (EIP-4399).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BlockHash:&lt;/b&gt;&amp;nbsp;Hash of the block containing the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BlockNumber:&lt;/b&gt;&amp;nbsp;Number of the block containing the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TransactionIndex:&lt;/b&gt;&amp;nbsp;Position of the transaction within the block.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Blockchain/Ethereum</category>
      <category>Ethereum</category>
      <category>Receipt</category>
      <category>transaction</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/362</guid>
      <comments>https://reasonjun.tistory.com/362#entry362comment</comments>
      <pubDate>Wed, 17 Jan 2024 00:02:55 +0900</pubDate>
    </item>
    <item>
      <title>Ethereum : Transaction Structure</title>
      <link>https://reasonjun.tistory.com/361</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;1192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FZsXT/btsDuRkYoAR/rdtw8nTgKdUxGHBM8ypNJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FZsXT/btsDuRkYoAR/rdtw8nTgKdUxGHBM8ypNJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FZsXT/btsDuRkYoAR/rdtw8nTgKdUxGHBM8ypNJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFZsXT%2FbtsDuRkYoAR%2Frdtw8nTgKdUxGHBM8ypNJ0%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;1530&quot; height=&quot;1192&quot; data-origin-width=&quot;1530&quot; data-origin-height=&quot;1192&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;Transaction&amp;nbsp;is&amp;nbsp;a&amp;nbsp;structure&amp;nbsp;used&amp;nbsp;when&amp;nbsp;EOA&amp;nbsp;transmits&amp;nbsp;Eth&amp;nbsp;to&amp;nbsp;EOA&amp;nbsp;or&amp;nbsp;when&amp;nbsp;EOA&amp;nbsp;calls&amp;nbsp;CA.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;txType() byte&lt;/b&gt;: This method returns the type ID of the transaction. It is expected to return a byte representing the type of the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;copy() TxData&lt;/b&gt;: This method creates a deep copy of the transaction data, initializing all fields. It allows for the duplication of transaction data.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;chainID() *big.Int&lt;/b&gt;: Returns the chain ID associated with the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;accessList() AccessList&lt;/b&gt;: Returns the access list associated with the transaction. An access list is a list of addresses and storage keys that the transaction plans to access, providing a way to optimize gas calculations.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;data() []byte&lt;/b&gt;: Returns the transaction data as a byte slice.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;gas() uint64&lt;/b&gt;: Returns the amount of gas specified for the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;gasPrice() *big.Int&lt;/b&gt;: Returns the gas price set for the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;gasTipCap() *big.Int&lt;/b&gt;: Returns the maximum gas tip that the transaction is willing to pay.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;gasFeeCap() *big.Int&lt;/b&gt;: Returns the maximum fee (gas price * gas limit) that the transaction is willing to pay.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;value() *big.Int&lt;/b&gt;: Returns the value of ether being transferred with the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;nonce() uint64&lt;/b&gt;: Returns the nonce of the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;to() *common.Address&lt;/b&gt;: Returns the recipient address of the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;rawSignatureValues() (v, r, s *big.Int)&lt;/b&gt;: Returns the raw signature values (v, r, s) of the transaction.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;setSignatureValues(chainID, v, r, s *big.Int)&lt;/b&gt;: Sets the signature values for the transaction, including the chain ID, v, r, and s.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int&lt;/b&gt;: Computes the effective gas price paid by the transaction, given the inclusion block baseFee. The result is returned as a big.Int. The &lt;b&gt;dst&lt;/b&gt; parameter is provided to store the result, and it emphasizes that the returned value should be an independent copy.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;encode(*bytes.Buffer) error&lt;/b&gt;: Encodes the transaction data into a byte buffer. This is likely used for serialization purposes.&lt;/li&gt;
&lt;/ol&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;b&gt;EOA - EOA Transaction&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1890&quot; data-origin-height=&quot;1422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FScD9/btsDAwl2491/Mj4qPWpxqZouftzdWk7kO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FScD9/btsDAwl2491/Mj4qPWpxqZouftzdWk7kO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FScD9/btsDAwl2491/Mj4qPWpxqZouftzdWk7kO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFScD9%2FbtsDAwl2491%2FMj4qPWpxqZouftzdWk7kO0%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;1890&quot; height=&quot;1422&quot; data-origin-width=&quot;1890&quot; data-origin-height=&quot;1422&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;EOA - CA Transaction&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;1568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l3F8q/btsDBtPVBrI/m8xkrUU3oli94wnRxjsFV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l3F8q/btsDBtPVBrI/m8xkrUU3oli94wnRxjsFV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l3F8q/btsDBtPVBrI/m8xkrUU3oli94wnRxjsFV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl3F8q%2FbtsDBtPVBrI%2Fm8xkrUU3oli94wnRxjsFV1%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;1912&quot; height=&quot;1568&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;1568&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Blockchain/Ethereum</category>
      <category>Ethereum</category>
      <category>transaction</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/361</guid>
      <comments>https://reasonjun.tistory.com/361#entry361comment</comments>
      <pubDate>Tue, 16 Jan 2024 23:38:24 +0900</pubDate>
    </item>
    <item>
      <title>Ethereum : Block Structure</title>
      <link>https://reasonjun.tistory.com/360</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;Block&amp;nbsp;represents&amp;nbsp;an&amp;nbsp;Ethereum&amp;nbsp;block.&lt;br /&gt;&lt;br /&gt;Note&amp;nbsp;the&amp;nbsp;Block&amp;nbsp;type&amp;nbsp;tries&amp;nbsp;to&amp;nbsp;be&amp;nbsp;'immutable',&amp;nbsp;and&amp;nbsp;contains&amp;nbsp;certain&amp;nbsp;caches&amp;nbsp;that&amp;nbsp;rely&amp;nbsp;on&amp;nbsp;that.&amp;nbsp;The&amp;nbsp;rules&amp;nbsp;around&amp;nbsp;block&amp;nbsp;immutability&amp;nbsp;are&amp;nbsp;as&amp;nbsp;follows:&lt;br /&gt;&lt;br /&gt;We&amp;nbsp;copy&amp;nbsp;all&amp;nbsp;data&amp;nbsp;when&amp;nbsp;the&amp;nbsp;block&amp;nbsp;is&amp;nbsp;constructed.&amp;nbsp;This&amp;nbsp;makes&amp;nbsp;references&amp;nbsp;held&amp;nbsp;inside&amp;nbsp;the&amp;nbsp;block&amp;nbsp;independent&amp;nbsp;of&amp;nbsp;whatever&amp;nbsp;value&amp;nbsp;was&amp;nbsp;passed&amp;nbsp;in.&lt;br /&gt;&lt;br /&gt;We&amp;nbsp;copy&amp;nbsp;all&amp;nbsp;header&amp;nbsp;data&amp;nbsp;on&amp;nbsp;access.&amp;nbsp;This&amp;nbsp;is&amp;nbsp;because&amp;nbsp;any&amp;nbsp;change&amp;nbsp;to&amp;nbsp;the&amp;nbsp;header&amp;nbsp;would&amp;nbsp;mess&amp;nbsp;up&amp;nbsp;the&amp;nbsp;cached&amp;nbsp;hash&amp;nbsp;and&amp;nbsp;size&amp;nbsp;values&amp;nbsp;in&amp;nbsp;the&amp;nbsp;block.&amp;nbsp;Calling&amp;nbsp;code&amp;nbsp;is&amp;nbsp;expected&amp;nbsp;to&amp;nbsp;take&amp;nbsp;advantage&amp;nbsp;of&amp;nbsp;this&amp;nbsp;to&amp;nbsp;avoid&amp;nbsp;over-allocating!&lt;br /&gt;&lt;br /&gt;When&amp;nbsp;new&amp;nbsp;body&amp;nbsp;data&amp;nbsp;is&amp;nbsp;attached&amp;nbsp;to&amp;nbsp;the&amp;nbsp;block,&amp;nbsp;a&amp;nbsp;shallow&amp;nbsp;copy&amp;nbsp;of&amp;nbsp;the&amp;nbsp;block&amp;nbsp;is&amp;nbsp;returned.&amp;nbsp;This&amp;nbsp;ensures&amp;nbsp;block&amp;nbsp;modifications&amp;nbsp;are&amp;nbsp;race-free.&lt;br /&gt;&lt;br /&gt;We&amp;nbsp;do&amp;nbsp;not&amp;nbsp;copy&amp;nbsp;body&amp;nbsp;data&amp;nbsp;on&amp;nbsp;access&amp;nbsp;because&amp;nbsp;it&amp;nbsp;does&amp;nbsp;not&amp;nbsp;affect&amp;nbsp;the&amp;nbsp;caches,&amp;nbsp;and&amp;nbsp;also&amp;nbsp;because&amp;nbsp;it&amp;nbsp;would&amp;nbsp;be&amp;nbsp;too&amp;nbsp;expensive.&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;892&quot; data-origin-height=&quot;638&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1NyFG/btsDwC1mtVW/Pu112EGJ9b4gGMlVwRPMY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1NyFG/btsDwC1mtVW/Pu112EGJ9b4gGMlVwRPMY0/img.png&quot; data-alt=&quot;https://github.com/ethereum/go-ethereum/blob/master/core/types/block.go&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1NyFG/btsDwC1mtVW/Pu112EGJ9b4gGMlVwRPMY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1NyFG%2FbtsDwC1mtVW%2FPu112EGJ9b4gGMlVwRPMY0%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;892&quot; height=&quot;638&quot; data-origin-width=&quot;892&quot; data-origin-height=&quot;638&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://github.com/ethereum/go-ethereum/blob/master/core/types/block.go&lt;/figcaption&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Header&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;1340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yyuv8/btsDzyKo8Sc/v0ObPcTFYorCKkR1b33zs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yyuv8/btsDzyKo8Sc/v0ObPcTFYorCKkR1b33zs1/img.png&quot; data-alt=&quot;https://github.com/ethereum/go-ethereum/blob/master/core/types/block.go&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yyuv8/btsDzyKo8Sc/v0ObPcTFYorCKkR1b33zs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyyuv8%2FbtsDzyKo8Sc%2Fv0ObPcTFYorCKkR1b33zs1%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;1382&quot; height=&quot;1340&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;1340&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://github.com/ethereum/go-ethereum/blob/master/core/types/block.go&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;ParentHash (common.Hash):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the hash of the parent block's header. It helps establish the chronological order and linkage of blocks in the blockchain.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;UncleHash (common.Hash):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the hash of the uncle blocks. Uncle blocks are valid blocks that are not included in the main blockchain but still contribute to the security of the network.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Coinbase (common.Address):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the address of the miner who successfully mined this block and is entitled to the block reward.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Root (common.Hash):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the root hash of the state trie after all transactions in the block have been executed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TxHash (common.Hash):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the root hash of the Merkle trie containing all transactions in the block.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ReceiptHash (common.Hash):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the root hash of the Merkle trie containing all transaction receipts.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Bloom (Bloom):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents a Bloom filter, a data structure used to efficiently test whether an element is a member of a set. In Ethereum, it's used to filter and quickly query logs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Difficulty (big.Int):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the difficulty of finding a valid hash for the block. It adjusts dynamically to control the rate at which new blocks are added to the blockchain.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Number (big.Int):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the block number, indicating the position of the block in the blockchain.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GasLimit (uint64):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the maximum amount of gas that can be used in this block.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GasUsed (uint64):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the total amount of gas used by all transactions in the block.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Time (uint64):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the timestamp indicating when the block was mined.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Extra ([]byte):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents additional data that miners can include in the block.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MixDigest (common.Hash):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents the mix hash used in Ethash mining.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Nonce (BlockNonce):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Represents a 64-bit hash, used in the mining process to try different combinations to find a valid block hash.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BaseFee (big.Int):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Added by Ethereum Improvement Proposal (EIP)-1559, represents the base fee per gas unit.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;WithdrawalsHash (common.Hash):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Added by EIP-4895, represents the hash of withdrawals from the Ethereum 2.0 beacon chain.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BlobGasUsed (uint64):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Added by EIP-4844, represents the gas used by the Ethereum 2.0 blob.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ExcessBlobGas (uint64):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Added by EIP-4844, represents the excess gas in Ethereum 2.0 blob.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ParentBeaconRoot (common.Hash):&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Added by EIP-4788, represents the root of the parent beacon block in Ethereum 2.0.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&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;b&gt;Block Production&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Mempool Tx choose&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. EVM execution&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Transaction execution ( Receipt, Log produce)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. Block Header Generate&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. Find Nonce, MixHash (ethHash)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. Block Propagation&lt;/p&gt;</description>
      <category>Blockchain/Ethereum</category>
      <category>Block</category>
      <category>Block Production</category>
      <category>Ethereum</category>
      <category>evm</category>
      <category>mempool</category>
      <category>ParentHash</category>
      <category>UncleHash</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/360</guid>
      <comments>https://reasonjun.tistory.com/360#entry360comment</comments>
      <pubDate>Tue, 16 Jan 2024 18:46:15 +0900</pubDate>
    </item>
    <item>
      <title>HTML : IndexedDB</title>
      <link>https://reasonjun.tistory.com/359</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;IndexedDB is a powerful API provided by web browsers for managing a local NoSQL database within client-side applications. Here's a detailed breakdown of its key features and functionalities:&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;Purpose:&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;Persistently store large amounts of structured data in the user's browser,&amp;nbsp;enabling offline-capable web applications.&lt;/li&gt;
&lt;li&gt;Offer rich query capabilities for efficient data retrieval based on indexes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Key Concepts:&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;&lt;b&gt;Object stores:&lt;/b&gt;&amp;nbsp;The fundamental data structure,&amp;nbsp;resembling tables but holding JavaScript objects instead of rows and columns.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Keys:&lt;/b&gt;&amp;nbsp;Unique identifiers used to access individual objects within an object store.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Indexes:&lt;/b&gt;&amp;nbsp;Specialized structures built on top of object stores for fast searching based on specific data properties.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Transactions:&lt;/b&gt;&amp;nbsp;Groups of operations ensuring data consistency by committing all changes or reverting them entirely in case of an error.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Advantages:&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;&lt;b&gt;Large storage capacity:&lt;/b&gt;&amp;nbsp;Compared to Web Storage,&amp;nbsp;IndexedDB allows storing significantly more data (multiple megabytes to gigabytes).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Offline persistence:&lt;/b&gt;&amp;nbsp;Data survives across browser sessions and even device reboots,&amp;nbsp;enabling offline functionality.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Powerful querying:&lt;/b&gt;&amp;nbsp;Supports efficient searches using indexes on various data properties.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Object-oriented:&lt;/b&gt;&amp;nbsp;Stores and retrieves JavaScript objects directly,&amp;nbsp;simplifying data manipulation.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Transactions:&lt;/b&gt;&amp;nbsp;Ensure data consistency and integrity even with complex operations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Considerations:&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;&lt;b&gt;Complexity:&lt;/b&gt;&amp;nbsp;Requires more programming effort compared to simpler storage APIs like Web Storage.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Asynchronous nature:&lt;/b&gt;&amp;nbsp;All operations are asynchronous,&amp;nbsp;demanding understanding of callback-based programming.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Security:&lt;/b&gt;&amp;nbsp;Same-origin principle restricts access to the database,&amp;nbsp;preventing third-party websites from stealing data.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Browser compatibility:&lt;/b&gt;&amp;nbsp;While widely supported,&amp;nbsp;older browsers might lack full functionality.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://web.dev/articles/indexeddb?hl=ko#:~:text=IndexedDB%20is%20a%20low%2Dlevel,larger%20amounts%20of%20structured%20data.&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://web.dev/articles/indexeddb?hl=ko#:~:text=IndexedDB%20is%20a%20low%2Dlevel,larger%20amounts%20of%20structured%20data.&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1704692246736&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;IndexedDB 작업 &amp;nbsp;|&amp;nbsp; Articles &amp;nbsp;|&amp;nbsp; web.dev&quot; data-og-description=&quot;IndexedDB의 기본사항에 관한 가이드입니다.&quot; data-og-host=&quot;web.dev&quot; data-og-source-url=&quot;https://web.dev/articles/indexeddb?hl=ko#:~:text=IndexedDB%20is%20a%20low%2Dlevel,larger%20amounts%20of%20structured%20data.&quot; data-og-url=&quot;https://web.dev/articles/indexeddb?hl=ko&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://web.dev/articles/indexeddb?hl=ko#:~:text=IndexedDB%20is%20a%20low%2Dlevel,larger%20amounts%20of%20structured%20data.&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://web.dev/articles/indexeddb?hl=ko#:~:text=IndexedDB%20is%20a%20low%2Dlevel,larger%20amounts%20of%20structured%20data.&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;IndexedDB 작업 &amp;nbsp;|&amp;nbsp; Articles &amp;nbsp;|&amp;nbsp; web.dev&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;IndexedDB의 기본사항에 관한 가이드입니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;web.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1704692256064&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;IndexedDB API - Web APIs | MDN&quot; data-og-description=&quot;IndexedDB is a low-level API for client-side storage of significant amounts of structured data, including files/blobs. This API uses indexes to enable high-performance searches of this data. While Web Storage is useful for storing smaller amounts of data, &quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API&quot; data-og-url=&quot;https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cD9guj/hyU2iX5dQr/pRiLLIg4V9QMofK0N3P5A1/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cD9guj/hyU2iX5dQr/pRiLLIg4V9QMofK0N3P5A1/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&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;IndexedDB API - Web APIs | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;IndexedDB is a low-level API for client-side storage of significant amounts of structured data, including files/blobs. This API uses indexes to enable high-performance searches of this data. While Web Storage is useful for storing smaller amounts of data,&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.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;</description>
      <category>Frontend/HTML</category>
      <category>HTML</category>
      <category>IndexedDB</category>
      <category>web</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/359</guid>
      <comments>https://reasonjun.tistory.com/359#entry359comment</comments>
      <pubDate>Mon, 8 Jan 2024 15:59:26 +0900</pubDate>
    </item>
    <item>
      <title>Nextjs : Edge Functions</title>
      <link>https://reasonjun.tistory.com/358</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;b&gt;What It Is:&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;A lightweight,&amp;nbsp;serverless runtime environment designed for executing code closer to users,&amp;nbsp;at the edge of the network.&lt;/li&gt;
&lt;li&gt;Built on a subset of standard Web APIs,&amp;nbsp;prioritizing speed,&amp;nbsp;security,&amp;nbsp;and compatibility.&lt;/li&gt;
&lt;li&gt;Integrated into Next.js,&amp;nbsp;offering specific features:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Edge API Routes&lt;/li&gt;
&lt;li&gt;Middleware&lt;/li&gt;
&lt;li&gt;Server components (experimental)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Key Characteristics:&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;&lt;b&gt;Minimal:&lt;/b&gt;&amp;nbsp;Supports a smaller set of APIs compared to the full Node.js runtime.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Fast:&lt;/b&gt;&amp;nbsp;Executes code quickly due to its lightweight nature and edge deployment.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Secure:&lt;/b&gt;&amp;nbsp;Designed with security in mind,&amp;nbsp;mitigating risks associated with traditional server-side rendering.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Interoperable:&lt;/b&gt;&amp;nbsp;Aligns with Web standards for compatibility across environments.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;When to Use It:&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;&lt;b&gt;Low-latency dynamic content:&lt;/b&gt;&amp;nbsp;Ideal for delivering personalized content or data with minimal delays.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Simple server-side logic:&lt;/b&gt;&amp;nbsp;Well-suited for tasks like authentication,&amp;nbsp;authorization,&amp;nbsp;or simple data fetching.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Global distribution:&lt;/b&gt;&amp;nbsp;Optimizes performance and scalability for users worldwide.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Key Features in Next.js:&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;&lt;b&gt;Edge API Routes:&lt;/b&gt;&amp;nbsp;Create API routes that run on the Edge Runtime for fast responses and global distribution.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Middleware:&lt;/b&gt;&amp;nbsp;Intercept requests and responses for tasks like authentication or redirects.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Server Components (experimental):&lt;/b&gt;&amp;nbsp;Server-side components that can fetch data and render on the Edge Runtime.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Limitations:&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;&lt;b&gt;Limited API support:&lt;/b&gt;&amp;nbsp;Doesn't support all Node.js APIs or globals like&amp;nbsp;require.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Code size restrictions:&lt;/b&gt;&amp;nbsp;Deployment platforms often have code size limits for Edge functions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Best Practices:&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;Use it for small,&amp;nbsp;fast functions that don't require extensive Node.js APIs.&lt;/li&gt;
&lt;li&gt;Prioritize Web APIs and ES modules for compatibility.&lt;/li&gt;
&lt;li&gt;Test thoroughly to ensure code functions as expected in the Edge Runtime environment.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://vercel.com/docs/functions/edge-functions&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://vercel.com/docs/functions/edge-functions&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1704553445207&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;Edge Functions Overview&quot; data-og-description=&quot;Vercel's Edge Functions enable you to deliver dynamic, personalized content with the lightweight Edge Runtime. Learn more about Edge Functions here.&quot; data-og-host=&quot;vercel.com&quot; data-og-source-url=&quot;https://vercel.com/docs/functions/edge-functions&quot; data-og-url=&quot;https://vercel.com/docs/functions/edge-functions&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/d0AWvK/hyUXUxwb0W/FK7MNAE72wf0XfNoFUOVNK/img.png?width=843&amp;amp;height=441&amp;amp;face=0_0_843_441,https://scrap.kakaocdn.net/dn/bmpGSH/hyUXKBHbEr/p9BbMKppRRlZ9YwyhT60i0/img.png?width=843&amp;amp;height=441&amp;amp;face=0_0_843_441,https://scrap.kakaocdn.net/dn/48uGU/hyU2h5Ggxj/XomyRVIwk0iSz2rYrzRTBk/img.png?width=843&amp;amp;height=441&amp;amp;face=0_0_843_441&quot;&gt;&lt;a href=&quot;https://vercel.com/docs/functions/edge-functions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://vercel.com/docs/functions/edge-functions&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/d0AWvK/hyUXUxwb0W/FK7MNAE72wf0XfNoFUOVNK/img.png?width=843&amp;amp;height=441&amp;amp;face=0_0_843_441,https://scrap.kakaocdn.net/dn/bmpGSH/hyUXKBHbEr/p9BbMKppRRlZ9YwyhT60i0/img.png?width=843&amp;amp;height=441&amp;amp;face=0_0_843_441,https://scrap.kakaocdn.net/dn/48uGU/hyU2h5Ggxj/XomyRVIwk0iSz2rYrzRTBk/img.png?width=843&amp;amp;height=441&amp;amp;face=0_0_843_441');&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;Edge Functions Overview&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Vercel's Edge Functions enable you to deliver dynamic, personalized content with the lightweight Edge Runtime. Learn more about Edge Functions here.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;vercel.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;</description>
      <category>Frontend/Next.js</category>
      <category>edge function</category>
      <category>edge runtime</category>
      <category>nextJS</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/358</guid>
      <comments>https://reasonjun.tistory.com/358#entry358comment</comments>
      <pubDate>Sun, 7 Jan 2024 00:14:43 +0900</pubDate>
    </item>
    <item>
      <title>Ethereum : Account structure</title>
      <link>https://reasonjun.tistory.com/357</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;In the case of Bitcoin blockchain, state values are managed based on UTXO. The user's balance is managed by updating the UTXO usage status whenever a new block is created.&lt;/li&gt;
&lt;li&gt;In the case of the Ethereum blockchain, the state value of balance data is stored in the Account based on the state, and the balance is updated every time a block is created.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Types of Accounts:&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;There are two main types of accounts in Ethereum:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Externally Owned Accounts (EOA):&lt;/b&gt; These are user-controlled accounts, often accessed through software wallets like MetaMask or MyEtherWallet. EOAs are represented by a public address (derived from the private key) and hold balances in Ether (ETH). They lack their own code and rely on user interaction through private key signatures to initiate transactions.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Contract Accounts:&lt;/b&gt; These are accounts created by deploying smart contracts onto the Ethereum Virtual Machine (EVM). They're controlled by the code embedded within the smart contract and can hold balances, execute their programmed functions, and interact with other accounts. Unlike EOAs, they don't have private keys and can't initiate transactions by themselves.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Account Components:&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Every account (EOA or contract) consists of several key components:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Address:&lt;/b&gt;&amp;nbsp;This is a unique identifier for the account on the Ethereum network,&amp;nbsp;typically represented as a 42-character hexadecimal string.&amp;nbsp;It's derived from the public key of the corresponding key pair.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Balance:&lt;/b&gt;&amp;nbsp;This represents the amount of Ether (ETH) held by the account.&amp;nbsp;Any change in balance occurs through transactions (sending or receiving ETH).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Nonce:&lt;/b&gt; This is a counter that keeps track of the number of transactions sent from the account. It prevents replay attacks and ensures transaction uniqueness. (0 ~ +1)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;StorageRoot: &lt;/b&gt;This&amp;nbsp;is&amp;nbsp;the&amp;nbsp;hash&amp;nbsp;value&amp;nbsp;of&amp;nbsp;the&amp;nbsp;root&amp;nbsp;node&amp;nbsp;of&amp;nbsp;the&amp;nbsp;account&amp;nbsp;Merkle&amp;nbsp;Patricia&amp;nbsp;Trie.&amp;nbsp;The&amp;nbsp;default&amp;nbsp;is&amp;nbsp;empty.&amp;nbsp;Used&amp;nbsp;together&amp;nbsp;with&amp;nbsp;Account&amp;nbsp;Storage.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CodeHash:&lt;/b&gt; This is the bytecode of the smart contract deployed to the account. It defines the logic and functionality of the contract and determines how it interacts with the Ethereum network. In the case of EOA this is empty.&lt;/li&gt;
&lt;/ul&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;b&gt;How to make EOA?&amp;nbsp;&lt;/b&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;Bitcoin&amp;nbsp;and&amp;nbsp;Ethereum&amp;nbsp;use&amp;nbsp;the&amp;nbsp;same&amp;nbsp;ECDSA&amp;nbsp;Alogorithm.&amp;nbsp;=&amp;gt;&amp;nbsp;ECC&amp;nbsp;elliptic&amp;nbsp;curves&amp;nbsp;are&amp;nbsp;also&amp;nbsp;used&amp;nbsp;in&amp;nbsp;the&amp;nbsp;same&amp;nbsp;way.&amp;nbsp;=&amp;gt;&amp;nbsp;The&amp;nbsp;same&amp;nbsp;applies&amp;nbsp;to&amp;nbsp;using&amp;nbsp;secp256k1&amp;nbsp;among&amp;nbsp;elliptic&amp;nbsp;curves.&amp;nbsp;Therefore,&amp;nbsp;if&amp;nbsp;you&amp;nbsp;create&amp;nbsp;an&amp;nbsp;account&amp;nbsp;in&amp;nbsp;Bitcoin&amp;nbsp;and&amp;nbsp;Ethereum&amp;nbsp;with&amp;nbsp;an&amp;nbsp;already&amp;nbsp;created&amp;nbsp;private&amp;nbsp;key,&amp;nbsp;the&amp;nbsp;same&amp;nbsp;address&amp;nbsp;is&amp;nbsp;created.&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;Private Key =&amp;gt; (secp256k1) =&amp;gt; Public Key =&amp;gt;. Keccak-256 Hash (Result&amp;nbsp;value&amp;nbsp;lower&amp;nbsp;20&amp;nbsp;bytes) =&amp;gt; address&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;b&gt;How to make CA?&lt;/b&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;b&gt;1. Network Deploy&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;When&amp;nbsp;EOA&amp;nbsp;creates&amp;nbsp;a&amp;nbsp;CA&amp;nbsp;or&amp;nbsp;uses&amp;nbsp;CREATE&amp;nbsp;(OPCODE)&amp;nbsp;on&amp;nbsp;the&amp;nbsp;contract,&amp;nbsp;the&amp;nbsp;network&amp;nbsp;creates&amp;nbsp;and&amp;nbsp;returns&amp;nbsp;an&amp;nbsp;Address&amp;nbsp;in&amp;nbsp;the&amp;nbsp;same&amp;nbsp;manner&amp;nbsp;as&amp;nbsp;the&amp;nbsp;code&amp;nbsp;below.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1756&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lGI4E/btsC7npCxrS/Y4FKNPPSfdMkMXYKKSxEGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lGI4E/btsC7npCxrS/Y4FKNPPSfdMkMXYKKSxEGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lGI4E/btsC7npCxrS/Y4FKNPPSfdMkMXYKKSxEGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlGI4E%2FbtsC7npCxrS%2FY4FKNPPSfdMkMXYKKSxEGK%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;1756&quot; height=&quot;278&quot; data-origin-width=&quot;1756&quot; data-origin-height=&quot;278&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;size16&quot;&gt;2. Using CREATE2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Using CREATE2, you can know the Contract Address in advance before network distribution.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4qsMj/btsC9zQyqVb/p0gJAtii0ScVKMg3NKcxyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4qsMj/btsC9zQyqVb/p0gJAtii0ScVKMg3NKcxyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4qsMj/btsC9zQyqVb/p0gJAtii0ScVKMg3NKcxyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4qsMj%2FbtsC9zQyqVb%2Fp0gJAtii0ScVKMg3NKcxyK%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;1764&quot; height=&quot;246&quot; data-origin-width=&quot;1764&quot; data-origin-height=&quot;246&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Address Checksum&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In&amp;nbsp;the&amp;nbsp;case&amp;nbsp;of&amp;nbsp;Ethereum&amp;nbsp;Address,&amp;nbsp;unlike&amp;nbsp;Bitcoin,&amp;nbsp;checksum&amp;nbsp;is&amp;nbsp;not&amp;nbsp;included&amp;nbsp;in&amp;nbsp;the&amp;nbsp;creation&amp;nbsp;process,&amp;nbsp;so&amp;nbsp;it&amp;nbsp;is&amp;nbsp;difficult&amp;nbsp;to&amp;nbsp;check&amp;nbsp;whether&amp;nbsp;the&amp;nbsp;address&amp;nbsp;is&amp;nbsp;accurate.&amp;nbsp;To&amp;nbsp;solve&amp;nbsp;this&amp;nbsp;problem,&amp;nbsp;a&amp;nbsp;checksum&amp;nbsp;function&amp;nbsp;is&amp;nbsp;provided&amp;nbsp;by&amp;nbsp;converting&amp;nbsp;the&amp;nbsp;case&amp;nbsp;of&amp;nbsp;the&amp;nbsp;address&amp;nbsp;through&amp;nbsp;EIP-55.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1856&quot; data-origin-height=&quot;1396&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cVjaE2/btsC7oa1EGg/JfuELkXhFT0pxGlyJm3saK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cVjaE2/btsC7oa1EGg/JfuELkXhFT0pxGlyJm3saK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cVjaE2/btsC7oa1EGg/JfuELkXhFT0pxGlyJm3saK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcVjaE2%2FbtsC7oa1EGg%2FJfuELkXhFT0pxGlyJm3saK%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;1856&quot; height=&quot;1396&quot; data-origin-width=&quot;1856&quot; data-origin-height=&quot;1396&quot;/&gt;&lt;/span&gt;&lt;/figure&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;b&gt;Ethereum Naming Service (ENS)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Like&amp;nbsp;DNS,&amp;nbsp;it&amp;nbsp;is&amp;nbsp;registered&amp;nbsp;and&amp;nbsp;used&amp;nbsp;in&amp;nbsp;a&amp;nbsp;language&amp;nbsp;that&amp;nbsp;is&amp;nbsp;easy&amp;nbsp;for&amp;nbsp;users&amp;nbsp;to&amp;nbsp;understand.&amp;nbsp;Purchase&amp;nbsp;the&amp;nbsp;name&amp;nbsp;using&amp;nbsp;Smart&amp;nbsp;Contract.&amp;nbsp;This&amp;nbsp;is&amp;nbsp;a&amp;nbsp;function&amp;nbsp;that&amp;nbsp;automatically&amp;nbsp;converts&amp;nbsp;and&amp;nbsp;delivers&amp;nbsp;the&amp;nbsp;name&amp;nbsp;to&amp;nbsp;the&amp;nbsp;address&amp;nbsp;when&amp;nbsp;you&amp;nbsp;enter&amp;nbsp;the&amp;nbsp;name&amp;nbsp;as&amp;nbsp;the&amp;nbsp;recipient&amp;nbsp;in&amp;nbsp;a&amp;nbsp;supported&amp;nbsp;wallet.&lt;/p&gt;</description>
      <category>Blockchain/Ethereum</category>
      <category>Address checksum</category>
      <category>ca</category>
      <category>ENS</category>
      <category>EoA</category>
      <category>Ethereum</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/357</guid>
      <comments>https://reasonjun.tistory.com/357#entry357comment</comments>
      <pubDate>Fri, 5 Jan 2024 18:12:33 +0900</pubDate>
    </item>
    <item>
      <title>Ethereum : Patricia Merkle Tries</title>
      <link>https://reasonjun.tistory.com/356</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;Ethereum&amp;nbsp;uses&amp;nbsp;a&amp;nbsp;Key-Value&amp;nbsp;based&amp;nbsp;DB&amp;nbsp;(leveldb).&lt;br /&gt;&lt;br /&gt;By using the hashed value of the address as the key and using the address as the path as shown in the picture on the below, you can find out the state value of the account.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1358&quot; data-origin-height=&quot;966&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6CC1W/btsC6ToEIeL/istmKlkOAKvM8cnEOgOe6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6CC1W/btsC6ToEIeL/istmKlkOAKvM8cnEOgOe6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6CC1W/btsC6ToEIeL/istmKlkOAKvM8cnEOgOe6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6CC1W%2FbtsC6ToEIeL%2FistmKlkOAKvM8cnEOgOe6K%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;1358&quot; height=&quot;966&quot; data-origin-width=&quot;1358&quot; data-origin-height=&quot;966&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;size16&quot;&gt;Ethereum Tries&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 Tries used in Ethereum are Storage Trie, State Trie, Transaction Trie, and Receipts Trie.&lt;br /&gt;Among&amp;nbsp;these,&amp;nbsp;the&amp;nbsp;Root&amp;nbsp;Hash&amp;nbsp;value&amp;nbsp;stored&amp;nbsp;in&amp;nbsp;the&amp;nbsp;Block&amp;nbsp;Header&amp;nbsp;is&amp;nbsp;State&amp;nbsp;Trie,&amp;nbsp;Transaction&amp;nbsp;Trie,&amp;nbsp;and&amp;nbsp;Receipts&amp;nbsp;Trie.&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://i.stack.imgur.com/afWDt.jpg&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://i.stack.imgur.com/afWDt.jpg&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;2632&quot; data-origin-height=&quot;1840&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/duMqkL/btsC75h5vL5/LIi0qgHw2Q48DWpMGcTK2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/duMqkL/btsC75h5vL5/LIi0qgHw2Q48DWpMGcTK2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/duMqkL/btsC75h5vL5/LIi0qgHw2Q48DWpMGcTK2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduMqkL%2FbtsC75h5vL5%2FLIi0qgHw2Q48DWpMGcTK2K%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;2632&quot; height=&quot;1840&quot; data-origin-width=&quot;2632&quot; data-origin-height=&quot;1840&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;b&gt;What is Ommers?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.investopedia.com/terms/u/uncle-block-cryptocurrency.asp&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.investopedia.com/terms/u/uncle-block-cryptocurrency.asp&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1704440788881&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;What Is an Ommer (Uncle) Block in Cryptocurrency?&quot; data-og-description=&quot;Ommer blocks are blocks not selected by the Ethereum network to add to the blockchain. Learn more about them and what they do for the network.&quot; data-og-host=&quot;www.investopedia.com&quot; data-og-source-url=&quot;https://www.investopedia.com/terms/u/uncle-block-cryptocurrency.asp&quot; data-og-url=&quot;https://www.investopedia.com/terms/u/uncle-block-cryptocurrency.asp&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bjc6M9/hyU2qVDljX/zVBB4BkMwLWFr7JicsEwU0/img.jpg?width=1500&amp;amp;height=1002&amp;amp;face=0_0_1500_1002,https://scrap.kakaocdn.net/dn/cwtono/hyU2nYUqzO/nrBZebSyAH7PLptR8o6pm0/img.jpg?width=1500&amp;amp;height=1002&amp;amp;face=0_0_1500_1002&quot;&gt;&lt;a href=&quot;https://www.investopedia.com/terms/u/uncle-block-cryptocurrency.asp&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.investopedia.com/terms/u/uncle-block-cryptocurrency.asp&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bjc6M9/hyU2qVDljX/zVBB4BkMwLWFr7JicsEwU0/img.jpg?width=1500&amp;amp;height=1002&amp;amp;face=0_0_1500_1002,https://scrap.kakaocdn.net/dn/cwtono/hyU2nYUqzO/nrBZebSyAH7PLptR8o6pm0/img.jpg?width=1500&amp;amp;height=1002&amp;amp;face=0_0_1500_1002');&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 an Ommer (Uncle) Block in Cryptocurrency?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Ommer blocks are blocks not selected by the Ethereum network to add to the blockchain. Learn more about them and what they do for the network.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.investopedia.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;</description>
      <category>Blockchain/Ethereum</category>
      <category>Ethereum</category>
      <category>Ethereum Tries</category>
      <category>Patricia Merkle Tries</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/356</guid>
      <comments>https://reasonjun.tistory.com/356#entry356comment</comments>
      <pubDate>Fri, 5 Jan 2024 17:13:45 +0900</pubDate>
    </item>
    <item>
      <title>Near DNFT Widget</title>
      <link>https://reasonjun.tistory.com/355</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2454&quot; data-origin-height=&quot;1726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2xTO3/btsCLsqPHwS/iFtIUEw6XzZA2eOd9fDzek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2xTO3/btsCLsqPHwS/iFtIUEw6XzZA2eOd9fDzek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2xTO3/btsCLsqPHwS/iFtIUEw6XzZA2eOd9fDzek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2xTO3%2FbtsCLsqPHwS%2FiFtIUEw6XzZA2eOd9fDzek%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;2454&quot; height=&quot;1726&quot; data-origin-width=&quot;2454&quot; data-origin-height=&quot;1726&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2520&quot; data-origin-height=&quot;1726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cypJHD/btsCLaqb1qH/ZBsuWbSc2SMZyf8Brqd2gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cypJHD/btsCLaqb1qH/ZBsuWbSc2SMZyf8Brqd2gk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cypJHD/btsCLaqb1qH/ZBsuWbSc2SMZyf8Brqd2gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcypJHD%2FbtsCLaqb1qH%2FZBsuWbSc2SMZyf8Brqd2gk%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;2520&quot; height=&quot;1726&quot; data-origin-width=&quot;2520&quot; data-origin-height=&quot;1726&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Product :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://near.org/near/widget/ComponentDetailsPage?src=7649ed19fe15dead3bb479bbbf3acd3a2b337eead0999673d20b9935e4d60d8e/widget/dNFTMinting&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://near.org/near/widget/ComponentDetailsPage?src=7649ed19fe15dead3bb479bbbf3acd3a2b337eead0999673d20b9935e4d60d8e/widget/dNFTMinting&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1703585231584&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;https://near.org/near/widget/ComponentDetailsPage?src=7649ed19fe15dead3bb479bbbf3acd3a2b337eead0999673d20b9935e4d60d8e%2Fwidget%2FdNFTMinting&quot; data-og-description=&quot;&quot; data-og-host=&quot;near.org&quot; data-og-source-url=&quot;https://near.org/near/widget/ComponentDetailsPage?src=7649ed19fe15dead3bb479bbbf3acd3a2b337eead0999673d20b9935e4d60d8e/widget/dNFTMinting&quot; data-og-url=&quot;https://near.org/near/widget/ComponentDetailsPage?src=7649ed19fe15dead3bb479bbbf3acd3a2b337eead0999673d20b9935e4d60d8e%2Fwidget%2FdNFTMinting&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://near.org/near/widget/ComponentDetailsPage?src=7649ed19fe15dead3bb479bbbf3acd3a2b337eead0999673d20b9935e4d60d8e/widget/dNFTMinting&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://near.org/near/widget/ComponentDetailsPage?src=7649ed19fe15dead3bb479bbbf3acd3a2b337eead0999673d20b9935e4d60d8e/widget/dNFTMinting&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;https://near.org/near/widget/ComponentDetailsPage?src=7649ed19fe15dead3bb479bbbf3acd3a2b337eead0999673d20b9935e4d60d8e%2Fwidget%2FdNFTMinting&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;near.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;b&gt;Github :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/YouJun-IWON/BOS-Contest&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/YouJun-IWON/BOS-Contest&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1703585260293&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 - YouJun-IWON/BOS-Contest&quot; data-og-description=&quot;Contribute to YouJun-IWON/BOS-Contest development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/YouJun-IWON/BOS-Contest&quot; data-og-url=&quot;https://github.com/YouJun-IWON/BOS-Contest&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bpXwnE/hyUTGkCurU/0aXb7PTekA34GEBECDDOCK/img.png?width=1200&amp;amp;height=600&amp;amp;face=976_131_1036_196&quot;&gt;&lt;a href=&quot;https://github.com/YouJun-IWON/BOS-Contest&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/YouJun-IWON/BOS-Contest&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bpXwnE/hyUTGkCurU/0aXb7PTekA34GEBECDDOCK/img.png?width=1200&amp;amp;height=600&amp;amp;face=976_131_1036_196');&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 - YouJun-IWON/BOS-Contest&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to YouJun-IWON/BOS-Contest 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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Presentation :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.canva.com/design/DAFvPg38fVQ/Rs0eAU30vNFxPhZWCPcSPQ/edit?utm_content=DAFvPg38fVQ&amp;amp;utm_campaign=designshare&amp;amp;utm_medium=link2&amp;amp;utm_source=sharebutton&quot;&gt;https://www.canva.com/design/DAFvPg38fVQ/Rs0eAU30vNFxPhZWCPcSPQ/edit?utm_content=DAFvPg38fVQ&amp;amp;utm_campaign=designshare&amp;amp;utm_medium=link2&amp;amp;utm_source=sharebutton&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>배포한 서비스</category>
      <category>blockchain</category>
      <category>BOS</category>
      <category>near</category>
      <category>REACT</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/355</guid>
      <comments>https://reasonjun.tistory.com/355#entry355comment</comments>
      <pubDate>Tue, 26 Dec 2023 19:13:38 +0900</pubDate>
    </item>
    <item>
      <title>AAVE Blockchian Report</title>
      <link>https://reasonjun.tistory.com/354</link>
      <description>&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;2262&quot; data-origin-height=&quot;1268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bit6ZA/btsCy7I441F/39rfa1LOqIgl8teGVvtIuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bit6ZA/btsCy7I441F/39rfa1LOqIgl8teGVvtIuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bit6ZA/btsCy7I441F/39rfa1LOqIgl8teGVvtIuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbit6ZA%2FbtsCy7I441F%2F39rfa1LOqIgl8teGVvtIuK%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;2262&quot; height=&quot;1268&quot; data-origin-width=&quot;2262&quot; data-origin-height=&quot;1268&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Presentation :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.canva.com/design/DAFzlnBpAHg/h1Fkw2wP2vyWb4-aOE-jzw/edit?utm_content=DAFzlnBpAHg&amp;amp;utm_campaign=designshare&amp;amp;utm_medium=link2&amp;amp;utm_source=sharebutton&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.canva.com/design/DAFzlnBpAHg/h1Fkw2wP2vyWb4-aOE-jzw/edit?utm_content=DAFzlnBpAHg&amp;amp;utm_campaign=designshare&amp;amp;utm_medium=link2&amp;amp;utm_source=sharebutton&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Report :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://candle-keyboard-dd4.notion.site/AAVE-eb5cad920ac5457994ca156c046e9419?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://candle-keyboard-dd4.notion.site/AAVE-eb5cad920ac5457994ca156c046e9419?pvs=4&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Blockchain At Yonsei</category>
      <category>Aave</category>
      <category>blockchain</category>
      <category>research</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/354</guid>
      <comments>https://reasonjun.tistory.com/354#entry354comment</comments>
      <pubDate>Tue, 26 Dec 2023 18:03:44 +0900</pubDate>
    </item>
    <item>
      <title>Real Estate NFT Platform Report (Blockchain At Yonsei STO Research)</title>
      <link>https://reasonjun.tistory.com/353</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2294&quot; data-origin-height=&quot;1288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cE7weL/btsCAMK4fyX/J6dxLVPYRI1yCLmjpWraK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cE7weL/btsCAMK4fyX/J6dxLVPYRI1yCLmjpWraK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cE7weL/btsCAMK4fyX/J6dxLVPYRI1yCLmjpWraK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcE7weL%2FbtsCAMK4fyX%2FJ6dxLVPYRI1yCLmjpWraK1%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;2294&quot; height=&quot;1288&quot; data-origin-width=&quot;2294&quot; data-origin-height=&quot;1288&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2262&quot; data-origin-height=&quot;1266&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d3yDXr/btsCyKUNTCR/rCZNo5gP8Ygl0BRxDWMwk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d3yDXr/btsCyKUNTCR/rCZNo5gP8Ygl0BRxDWMwk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d3yDXr/btsCyKUNTCR/rCZNo5gP8Ygl0BRxDWMwk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd3yDXr%2FbtsCyKUNTCR%2FrCZNo5gP8Ygl0BRxDWMwk1%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;2262&quot; height=&quot;1266&quot; data-origin-width=&quot;2262&quot; data-origin-height=&quot;1266&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;Real&amp;nbsp;estate&amp;nbsp;can&amp;nbsp;be&amp;nbsp;bought&amp;nbsp;and&amp;nbsp;sold&amp;nbsp;more&amp;nbsp;efficiently&amp;nbsp;and&amp;nbsp;safely&amp;nbsp;through&amp;nbsp;tokenization&amp;nbsp;of&amp;nbsp;real&amp;nbsp;assets&amp;nbsp;rather&amp;nbsp;than&amp;nbsp;paper&amp;nbsp;title&amp;nbsp;deeds&amp;nbsp;that&amp;nbsp;can&amp;nbsp;be&amp;nbsp;lost&amp;nbsp;or&amp;nbsp;altered.&amp;nbsp;This&amp;nbsp;is&amp;nbsp;because&amp;nbsp;all&amp;nbsp;information&amp;nbsp;is&amp;nbsp;recorded&amp;nbsp;in&amp;nbsp;a&amp;nbsp;distributed&amp;nbsp;ledger,&amp;nbsp;so&amp;nbsp;anyone&amp;nbsp;can&amp;nbsp;track&amp;nbsp;ownership&amp;nbsp;history&amp;nbsp;and&amp;nbsp;previous&amp;nbsp;transactions&amp;nbsp;to&amp;nbsp;verify&amp;nbsp;authenticity.&lt;br /&gt;2.&amp;nbsp;Currently,&amp;nbsp;purchasing&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;takes&amp;nbsp;anywhere&amp;nbsp;from&amp;nbsp;a&amp;nbsp;few&amp;nbsp;weeks&amp;nbsp;to&amp;nbsp;several&amp;nbsp;months,&amp;nbsp;including&amp;nbsp;signing&amp;nbsp;and&amp;nbsp;exchanging&amp;nbsp;a&amp;nbsp;contract,&amp;nbsp;but&amp;nbsp;using&amp;nbsp;NFTs,&amp;nbsp;assets&amp;nbsp;are&amp;nbsp;transferred&amp;nbsp;almost&amp;nbsp;instantly.&amp;nbsp;This&amp;nbsp;is&amp;nbsp;because&amp;nbsp;it&amp;nbsp;can&amp;nbsp;be&amp;nbsp;processed&amp;nbsp;automatically&amp;nbsp;if&amp;nbsp;the&amp;nbsp;conditions&amp;nbsp;are&amp;nbsp;met&amp;nbsp;through&amp;nbsp;a&amp;nbsp;smart&amp;nbsp;contract.&amp;nbsp;It&amp;nbsp;simplifies&amp;nbsp;and&amp;nbsp;speeds&amp;nbsp;up&amp;nbsp;the&amp;nbsp;traditionally&amp;nbsp;slow&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;process.&lt;br /&gt;3.&amp;nbsp;Purchasing&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;with&amp;nbsp;smart&amp;nbsp;contract&amp;nbsp;functionality&amp;nbsp;can&amp;nbsp;trigger&amp;nbsp;a&amp;nbsp;variety&amp;nbsp;of&amp;nbsp;automated&amp;nbsp;actions,&amp;nbsp;including&amp;nbsp;payments,&amp;nbsp;leases,&amp;nbsp;maintenance,&amp;nbsp;dividends,&amp;nbsp;etc.&lt;br /&gt;4.&amp;nbsp;By&amp;nbsp;dividing&amp;nbsp;the&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;deed&amp;nbsp;into&amp;nbsp;NFTs,&amp;nbsp;or&amp;nbsp;tokens,&amp;nbsp;ownership&amp;nbsp;of&amp;nbsp;the&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;deed&amp;nbsp;can&amp;nbsp;be&amp;nbsp;shared&amp;nbsp;by&amp;nbsp;multiple&amp;nbsp;investors.&amp;nbsp;However,&amp;nbsp;partial&amp;nbsp;ownership&amp;nbsp;of&amp;nbsp;this&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;deed&amp;nbsp;is&amp;nbsp;managed&amp;nbsp;in&amp;nbsp;a&amp;nbsp;way&amp;nbsp;that&amp;nbsp;bypasses&amp;nbsp;certain&amp;nbsp;legal&amp;nbsp;areas.&lt;br /&gt;5.&amp;nbsp;Many&amp;nbsp;costs&amp;nbsp;can&amp;nbsp;be&amp;nbsp;saved&amp;nbsp;as&amp;nbsp;the&amp;nbsp;existing&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;transaction&amp;nbsp;process&amp;nbsp;is&amp;nbsp;simplified.&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;2274&quot; data-origin-height=&quot;1256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Fgv3v/btsCCy6RCI3/0IvYVdrUb88VX9XnMMV3Z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Fgv3v/btsCCy6RCI3/0IvYVdrUb88VX9XnMMV3Z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Fgv3v/btsCCy6RCI3/0IvYVdrUb88VX9XnMMV3Z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFgv3v%2FbtsCCy6RCI3%2F0IvYVdrUb88VX9XnMMV3Z1%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;2274&quot; height=&quot;1256&quot; data-origin-width=&quot;2274&quot; data-origin-height=&quot;1256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2272&quot; data-origin-height=&quot;1288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYLdzd/btsCJj2a15r/ajS87NaFPRH0GtaJSjH6h0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYLdzd/btsCJj2a15r/ajS87NaFPRH0GtaJSjH6h0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYLdzd/btsCJj2a15r/ajS87NaFPRH0GtaJSjH6h0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYLdzd%2FbtsCJj2a15r%2FajS87NaFPRH0GtaJSjH6h0%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;2272&quot; height=&quot;1288&quot; data-origin-width=&quot;2272&quot; data-origin-height=&quot;1288&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2304&quot; data-origin-height=&quot;1292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UBsIJ/btsCzEzLCH3/0qN3IiKbF8PWpC6XaJbdt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UBsIJ/btsCzEzLCH3/0qN3IiKbF8PWpC6XaJbdt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UBsIJ/btsCzEzLCH3/0qN3IiKbF8PWpC6XaJbdt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUBsIJ%2FbtsCzEzLCH3%2F0qN3IiKbF8PWpC6XaJbdt1%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;2304&quot; height=&quot;1292&quot; data-origin-width=&quot;2304&quot; data-origin-height=&quot;1292&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;However,&amp;nbsp;no&amp;nbsp;national&amp;nbsp;agency&amp;nbsp;or&amp;nbsp;government&amp;nbsp;has&amp;nbsp;yet&amp;nbsp;recognized&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;NFTs.&lt;br /&gt;&lt;br /&gt;So,&amp;nbsp;the&amp;nbsp;current&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;NFT&amp;nbsp;platform&amp;nbsp;is&amp;nbsp;producing&amp;nbsp;and&amp;nbsp;brokering&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;NFTs&amp;nbsp;by&amp;nbsp;tokenizing&amp;nbsp;companies&amp;nbsp;that&amp;nbsp;own&amp;nbsp;real&amp;nbsp;estate.&lt;br /&gt;&lt;br /&gt;So,&amp;nbsp;as&amp;nbsp;follows,&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;brokerages&amp;nbsp;through&amp;nbsp;NFT&amp;nbsp;usually&amp;nbsp;consist&amp;nbsp;of&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;companies&amp;nbsp;that&amp;nbsp;own&amp;nbsp;a&amp;nbsp;lot&amp;nbsp;of&amp;nbsp;land&amp;nbsp;and&amp;nbsp;can&amp;nbsp;independently&amp;nbsp;manage&amp;nbsp;real&amp;nbsp;estate-related&amp;nbsp;assets,&amp;nbsp;or&amp;nbsp;blockchain&amp;nbsp;companies&amp;nbsp;that&amp;nbsp;can&amp;nbsp;safely&amp;nbsp;distribute&amp;nbsp;many&amp;nbsp;digital&amp;nbsp;assets.&amp;nbsp;.&amp;nbsp;In&amp;nbsp;other&amp;nbsp;words,&amp;nbsp;it&amp;nbsp;is&amp;nbsp;carried&amp;nbsp;out&amp;nbsp;by&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;companies&amp;nbsp;or&amp;nbsp;blockchain&amp;nbsp;companies&amp;nbsp;that&amp;nbsp;can&amp;nbsp;build&amp;nbsp;a&amp;nbsp;highly&amp;nbsp;reliable&amp;nbsp;financial&amp;nbsp;system&amp;nbsp;under&amp;nbsp;national&amp;nbsp;law.&lt;br /&gt;&lt;br /&gt;In&amp;nbsp;common,&amp;nbsp;they&amp;nbsp;have&amp;nbsp;a&amp;nbsp;platform&amp;nbsp;that&amp;nbsp;records&amp;nbsp;real&amp;nbsp;estate&amp;nbsp;records&amp;nbsp;on&amp;nbsp;the&amp;nbsp;blockchain&amp;nbsp;and&amp;nbsp;allows&amp;nbsp;them&amp;nbsp;to&amp;nbsp;be&amp;nbsp;bought&amp;nbsp;and&amp;nbsp;sold&amp;nbsp;using&amp;nbsp;cryptocurrency.&amp;nbsp;Partial&amp;nbsp;ownership&amp;nbsp;is&amp;nbsp;possible&amp;nbsp;through&amp;nbsp;stock&amp;nbsp;purchases&amp;nbsp;or&amp;nbsp;NFT&amp;nbsp;purchases&amp;nbsp;through&amp;nbsp;coins.&amp;nbsp;Some&amp;nbsp;operate&amp;nbsp;with&amp;nbsp;national&amp;nbsp;SEC&amp;nbsp;certification,&amp;nbsp;while&amp;nbsp;others&amp;nbsp;do&amp;nbsp;not&amp;nbsp;and&amp;nbsp;operate&amp;nbsp;on&amp;nbsp;their&amp;nbsp;own.&lt;br /&gt;&lt;br /&gt;Its&amp;nbsp;own&amp;nbsp;coins&amp;nbsp;are&amp;nbsp;basically&amp;nbsp;not&amp;nbsp;recognized&amp;nbsp;by&amp;nbsp;external&amp;nbsp;exchanges&amp;nbsp;or&amp;nbsp;banks,&amp;nbsp;but&amp;nbsp;instead&amp;nbsp;enable&amp;nbsp;leverage&amp;nbsp;through&amp;nbsp;decentralized&amp;nbsp;exchanges.&amp;nbsp;There&amp;nbsp;were&amp;nbsp;also&amp;nbsp;places&amp;nbsp;that&amp;nbsp;were&amp;nbsp;operating&amp;nbsp;their&amp;nbsp;own&amp;nbsp;token&amp;nbsp;swaps.&lt;/p&gt;</description>
      <category>Blockchain At Yonsei</category>
      <category>Block Chain</category>
      <category>NFT</category>
      <category>Real Estate</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/353</guid>
      <comments>https://reasonjun.tistory.com/353#entry353comment</comments>
      <pubDate>Tue, 26 Dec 2023 17:24:42 +0900</pubDate>
    </item>
    <item>
      <title>Nextjs Project: Christmas pet ai profile Platform Product / Building Problems</title>
      <link>https://reasonjun.tistory.com/352</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Product :&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.pets-mas.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.pets-mas.com/&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1703577327266&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;메리 댕냥스마스&quot; data-og-description=&quot;우리집 댕냥이로 크리스마스 카드를 만들어 보세요!&quot; data-og-host=&quot;www.pets-mas.com&quot; data-og-source-url=&quot;https://www.pets-mas.com/&quot; data-og-url=&quot;https://www.pets-mas.com/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bcwbYB/hyUTJuNUOe/wT4wrA6PvgtKzvINizqg41/img.png?width=3076&amp;amp;height=1812&amp;amp;face=0_0_3076_1812&quot;&gt;&lt;a href=&quot;https://www.pets-mas.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.pets-mas.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bcwbYB/hyUTJuNUOe/wT4wrA6PvgtKzvINizqg41/img.png?width=3076&amp;amp;height=1812&amp;amp;face=0_0_3076_1812');&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;메리 댕냥스마스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;우리집 댕냥이로 크리스마스 카드를 만들어 보세요!&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.pets-mas.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Video :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/mBvLnZIfWoA&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/mBvLnZIfWoA&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=mBvLnZIfWoA&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/q9S4c/hyUTz6O8y2/IfoOyAOlbcpN7oMAUKmWC1/img.jpg?width=640&amp;amp;height=480&amp;amp;face=0_0_640_480&quot; data-video-width=&quot;640&quot; data-video-height=&quot;480&quot; data-video-origin-width=&quot;640&quot; data-video-origin-height=&quot;480&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Christmas Pet AI Profile Platform&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/mBvLnZIfWoA&quot; width=&quot;640&quot; height=&quot;480&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;problems :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. filter routing problem :&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;=&amp;gt; I set filtering in the layout for each page, but a loop phenomenon was discovered.&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. Libraries&amp;nbsp;that&amp;nbsp;worked&amp;nbsp;normally&amp;nbsp;on&amp;nbsp;desktop&amp;nbsp;did&amp;nbsp;not&amp;nbsp;work&amp;nbsp;on&amp;nbsp;mobile.&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. Depending&amp;nbsp;on&amp;nbsp;the&amp;nbsp;mobile&amp;nbsp;software&amp;nbsp;version,&amp;nbsp;some&amp;nbsp;operations&amp;nbsp;may&amp;nbsp;not&amp;nbsp;work.&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. There&amp;nbsp;were&amp;nbsp;problems&amp;nbsp;with&amp;nbsp;communication&amp;nbsp;between&amp;nbsp;designers&amp;nbsp;and&amp;nbsp;backend,&amp;nbsp;and&amp;nbsp;there&amp;nbsp;was&amp;nbsp;source&amp;nbsp;waste.&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. Problems&amp;nbsp;may&amp;nbsp;occur&amp;nbsp;due&amp;nbsp;to&amp;nbsp;unexpected&amp;nbsp;errors&amp;nbsp;after&amp;nbsp;domain&amp;nbsp;deployment.&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;6.I&amp;nbsp;proceeded&amp;nbsp;without&amp;nbsp;using&amp;nbsp;the&amp;nbsp;state&amp;nbsp;management&amp;nbsp;library&amp;nbsp;and&amp;nbsp;had&amp;nbsp;a&amp;nbsp;lot&amp;nbsp;of&amp;nbsp;trouble&amp;nbsp;with&amp;nbsp;the&amp;nbsp;data&amp;nbsp;streams&amp;nbsp;of&amp;nbsp;each&amp;nbsp;component.&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;b&gt;Solutions :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. If the page continues to be re-rendered, check to see if there are any cases where a loop may occur in the page layout.&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. Don&amp;rsquo;t&amp;nbsp;let&amp;nbsp;your&amp;nbsp;guard&amp;nbsp;down&amp;nbsp;just&amp;nbsp;because&amp;nbsp;it&amp;nbsp;worked&amp;nbsp;normally&amp;nbsp;on&amp;nbsp;the&amp;nbsp;desktop,&amp;nbsp;let&amp;rsquo;s&amp;nbsp;test&amp;nbsp;it&amp;nbsp;on&amp;nbsp;mobile&amp;nbsp;as&amp;nbsp;well.&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. Please&amp;nbsp;note&amp;nbsp;the&amp;nbsp;mobile&amp;nbsp;software&amp;nbsp;version.&amp;nbsp;It&amp;nbsp;is&amp;nbsp;best&amp;nbsp;to&amp;nbsp;avoid&amp;nbsp;using&amp;nbsp;technology&amp;nbsp;that&amp;nbsp;is&amp;nbsp;too&amp;nbsp;cutting-edge.&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. Let&amp;rsquo;s&amp;nbsp;communicate&amp;nbsp;sufficiently&amp;nbsp;with&amp;nbsp;designers&amp;nbsp;and&amp;nbsp;back-end&amp;nbsp;developers&amp;nbsp;and&amp;nbsp;write&amp;nbsp;specifications.&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. After deploying a domain, you should continuously check operational logs. Let&amp;rsquo;s&amp;nbsp;make&amp;nbsp;logs&amp;nbsp;and&amp;nbsp;error&amp;nbsp;handling&amp;nbsp;clear&amp;nbsp;about&amp;nbsp;areas&amp;nbsp;where&amp;nbsp;errors&amp;nbsp;may&amp;nbsp;occur.&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;6. It is best to use the state management library whenever possible. You&amp;nbsp;can&amp;nbsp;receive&amp;nbsp;great&amp;nbsp;help&amp;nbsp;in&amp;nbsp;moving&amp;nbsp;and&amp;nbsp;modifying&amp;nbsp;data.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>배포한 서비스</category>
      <category>building</category>
      <category>certificate</category>
      <category>Christmas ai profile platform</category>
      <category>Deploy</category>
      <category>error</category>
      <category>nextJS</category>
      <category>product</category>
      <category>SSR</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/352</guid>
      <comments>https://reasonjun.tistory.com/352#entry352comment</comments>
      <pubDate>Tue, 26 Dec 2023 16:59:58 +0900</pubDate>
    </item>
    <item>
      <title>Nextjs error : cause: Error: unable to verify the first certificate</title>
      <link>https://reasonjun.tistory.com/351</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Problem :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;I'm&amp;nbsp;using&amp;nbsp;Nextjs&amp;nbsp;14&amp;nbsp;and&amp;nbsp;wanted&amp;nbsp;to&amp;nbsp;utilize&amp;nbsp;the&amp;nbsp;layout&amp;nbsp;folder&amp;nbsp;to&amp;nbsp;automatically&amp;nbsp;load&amp;nbsp;data&amp;nbsp;when&amp;nbsp;accessing&amp;nbsp;the&amp;nbsp;web.&amp;nbsp;&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;1838&quot; data-origin-height=&quot;948&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bR11fB/btsB7RGejNn/umyhuyUaSILdeInqmdGm40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bR11fB/btsB7RGejNn/umyhuyUaSILdeInqmdGm40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bR11fB/btsB7RGejNn/umyhuyUaSILdeInqmdGm40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbR11fB%2FbtsB7RGejNn%2FumyhuyUaSILdeInqmdGm40%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;1838&quot; height=&quot;948&quot; data-origin-width=&quot;1838&quot; data-origin-height=&quot;948&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Why?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This&amp;nbsp;is&amp;nbsp;fine&amp;nbsp;when&amp;nbsp;sending&amp;nbsp;requests&amp;nbsp;from&amp;nbsp;client&amp;nbsp;to&amp;nbsp;server,&amp;nbsp;but&amp;nbsp;when&amp;nbsp;communicating&amp;nbsp;from&amp;nbsp;server&amp;nbsp;to&amp;nbsp;server&amp;nbsp;in&amp;nbsp;Nextjs,&amp;nbsp;the&amp;nbsp;difference&amp;nbsp;between&amp;nbsp;http/https&amp;nbsp;causes&amp;nbsp;problems.&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;Can&amp;nbsp;occur&amp;nbsp;while&amp;nbsp;the&amp;nbsp;Next.js&amp;nbsp;app&amp;nbsp;is&amp;nbsp;establishing&amp;nbsp;an&amp;nbsp;SSL/TLS&amp;nbsp;secure&amp;nbsp;connection.&amp;nbsp;Typically,&amp;nbsp;this&amp;nbsp;error&amp;nbsp;occurs&amp;nbsp;when&amp;nbsp;there&amp;nbsp;is&amp;nbsp;a&amp;nbsp;problem&amp;nbsp;with&amp;nbsp;the&amp;nbsp;certificate&amp;nbsp;chain.&amp;nbsp;Certificate&amp;nbsp;chaining&amp;nbsp;is&amp;nbsp;about&amp;nbsp;ensuring&amp;nbsp;that&amp;nbsp;the&amp;nbsp;SSL&amp;nbsp;certificate&amp;nbsp;for&amp;nbsp;a&amp;nbsp;particular&amp;nbsp;server&amp;nbsp;is&amp;nbsp;linked&amp;nbsp;to&amp;nbsp;a&amp;nbsp;trusted&amp;nbsp;root&amp;nbsp;certificate.&lt;br /&gt;&lt;br /&gt;Possible&amp;nbsp;solutions&amp;nbsp;include&lt;br /&gt;&lt;br /&gt;Review&amp;nbsp;the&amp;nbsp;certificate&amp;nbsp;chain:&amp;nbsp;You&amp;nbsp;need&amp;nbsp;to&amp;nbsp;make&amp;nbsp;sure&amp;nbsp;that&amp;nbsp;the&amp;nbsp;certificate&amp;nbsp;is&amp;nbsp;installed&amp;nbsp;correctly.&amp;nbsp;You&amp;nbsp;can&amp;nbsp;use&amp;nbsp;the&amp;nbsp;SSL&amp;nbsp;Validation&amp;nbsp;tool&amp;nbsp;to&amp;nbsp;do&amp;nbsp;this.&lt;br /&gt;Reinstall&amp;nbsp;the&amp;nbsp;certificate:&amp;nbsp;If&amp;nbsp;there&amp;nbsp;was&amp;nbsp;a&amp;nbsp;problem&amp;nbsp;installing&amp;nbsp;the&amp;nbsp;certificate,&amp;nbsp;you&amp;nbsp;need&amp;nbsp;to&amp;nbsp;reinstall&amp;nbsp;the&amp;nbsp;certificate.&lt;br /&gt;Review&amp;nbsp;your&amp;nbsp;server&amp;nbsp;settings:&amp;nbsp;You&amp;nbsp;need&amp;nbsp;to&amp;nbsp;make&amp;nbsp;sure&amp;nbsp;that&amp;nbsp;your&amp;nbsp;server&amp;nbsp;is&amp;nbsp;set&amp;nbsp;up&amp;nbsp;to&amp;nbsp;handle&amp;nbsp;SSL/TLS&amp;nbsp;connections&amp;nbsp;correctly.&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://www.reddit.com/r/nextjs/comments/pniwti/unable_to_verify_the_first_certificate/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.reddit.com/r/nextjs/comments/pniwti/unable_to_verify_the_first_certificate/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1702918739278&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;From the nextjs community on Reddit: unable to verify the first certificate&quot; data-og-description=&quot;Explore this post and more from the nextjs community&quot; data-og-host=&quot;www.reddit.com&quot; data-og-source-url=&quot;https://www.reddit.com/r/nextjs/comments/pniwti/unable_to_verify_the_first_certificate/&quot; data-og-url=&quot;https://www.reddit.com/r/nextjs/comments/pniwti/unable_to_verify_the_first_certificate/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dASC6T/hyUPBJ9czJ/FRRr7ypVB0oLFZlTRurNFK/img.jpg?width=1120&amp;amp;height=584&amp;amp;face=0_0_1120_584,https://scrap.kakaocdn.net/dn/d670fk/hyUL2ijBw1/gbJUwFMmlKdKp1psG9p7N1/img.jpg?width=1120&amp;amp;height=584&amp;amp;face=0_0_1120_584&quot;&gt;&lt;a href=&quot;https://www.reddit.com/r/nextjs/comments/pniwti/unable_to_verify_the_first_certificate/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.reddit.com/r/nextjs/comments/pniwti/unable_to_verify_the_first_certificate/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dASC6T/hyUPBJ9czJ/FRRr7ypVB0oLFZlTRurNFK/img.jpg?width=1120&amp;amp;height=584&amp;amp;face=0_0_1120_584,https://scrap.kakaocdn.net/dn/d670fk/hyUL2ijBw1/gbJUwFMmlKdKp1psG9p7N1/img.jpg?width=1120&amp;amp;height=584&amp;amp;face=0_0_1120_584');&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;From the nextjs community on Reddit: unable to verify the first certificate&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Explore this post and more from the nextjs community&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.reddit.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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Solution&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=Tjw7evZXsLI&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=Tjw7evZXsLI&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=Tjw7evZXsLI&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bVGDik/hyUL6kLY3g/a07ElgBwGSWxROkE6fFm0k/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;FetchError: request to failed, reason: unable to verify the first certificate nextjs | 100% FIX&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/Tjw7evZXsLI&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Next.js</category>
      <category>certificate</category>
      <category>error</category>
      <category>http</category>
      <category>https</category>
      <category>nextJS</category>
      <category>SSL</category>
      <category>SSR</category>
      <category>TLS</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/351</guid>
      <comments>https://reasonjun.tistory.com/351#entry351comment</comments>
      <pubDate>Tue, 19 Dec 2023 02:11:32 +0900</pubDate>
    </item>
    <item>
      <title>NextJS : Type error: Route &amp;quot;src/app/api/auth/[...nextauth]/route.ts&amp;quot; does not match the required types of a Next.js Route.  &amp;quot;authOptions&amp;quot; is not a valid Route export field.</title>
      <link>https://reasonjun.tistory.com/350</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codevoweb.com/setup-and-use-nextauth-in-nextjs-13-app-directory/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codevoweb.com/setup-and-use-nextauth-in-nextjs-13-app-directory/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1702657225757&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;Setup and Use NextAuth.js in Next.js 13 App Directory - CodevoWeb&quot; data-og-description=&quot;In this tutorial, I&amp;rsquo;ll walk you through setting up authentication in your Next.js 13 app directory using NextAuth.js. It&amp;rsquo;s worth noting that while we use...&quot; data-og-host=&quot;codevoweb.com&quot; data-og-source-url=&quot;https://codevoweb.com/setup-and-use-nextauth-in-nextjs-13-app-directory/&quot; data-og-url=&quot;https://codevoweb.com/setup-and-use-nextauth-in-nextjs-13-app-directory/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/OPhLh/hyUL1Db9Ul/sCGw8rbQrgHIC00rSfmXXK/img.jpg?width=850&amp;amp;height=478&amp;amp;face=0_0_850_478,https://scrap.kakaocdn.net/dn/WKcFt/hyULYzHCo7/l0I3V66N9X6a7kgFAfVWGK/img.jpg?width=850&amp;amp;height=478&amp;amp;face=0_0_850_478,https://scrap.kakaocdn.net/dn/nXpBJ/hyULW9I5bU/fQaUkmjFQoftvo0kyeBkEK/img.jpg?width=850&amp;amp;height=478&amp;amp;face=0_0_850_478&quot;&gt;&lt;a href=&quot;https://codevoweb.com/setup-and-use-nextauth-in-nextjs-13-app-directory/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://codevoweb.com/setup-and-use-nextauth-in-nextjs-13-app-directory/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/OPhLh/hyUL1Db9Ul/sCGw8rbQrgHIC00rSfmXXK/img.jpg?width=850&amp;amp;height=478&amp;amp;face=0_0_850_478,https://scrap.kakaocdn.net/dn/WKcFt/hyULYzHCo7/l0I3V66N9X6a7kgFAfVWGK/img.jpg?width=850&amp;amp;height=478&amp;amp;face=0_0_850_478,https://scrap.kakaocdn.net/dn/nXpBJ/hyULW9I5bU/fQaUkmjFQoftvo0kyeBkEK/img.jpg?width=850&amp;amp;height=478&amp;amp;face=0_0_850_478');&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;Setup and Use NextAuth.js in Next.js 13 App Directory - CodevoWeb&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;In this tutorial, I&amp;rsquo;ll walk you through setting up authentication in your Next.js 13 app directory using NextAuth.js. It&amp;rsquo;s worth noting that while we use...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;codevoweb.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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/vercel/next.js/discussions/50511&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/vercel/next.js/discussions/50511&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1702657765245&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;Why does my NextAuthJS discord login work in the test environment but cannot be built to production? (NextJS 13) &amp;middot; vercel/next.&quot; data-og-description=&quot;Summary I am trying to deploy a NextJS application to vercel. This is a test sign in model using AuthJS. When I run the program using npm run devit works fine and I am able to log in to my discord ...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/vercel/next.js/discussions/50511&quot; data-og-url=&quot;https://github.com/vercel/next.js/discussions/50511&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bDa6WW/hyULWhznjO/bKhjVxTyiLsN2j9ebxBsZK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/vercel/next.js/discussions/50511&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/vercel/next.js/discussions/50511&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bDa6WW/hyULWhznjO/bKhjVxTyiLsN2j9ebxBsZK/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;Why does my NextAuthJS discord login work in the test environment but cannot be built to production? (NextJS 13) &amp;middot; vercel/next.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Summary I am trying to deploy a NextJS application to vercel. This is a test sign in model using AuthJS. When I run the program using npm run devit works fine and I am able to log in to my discord ...&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;</description>
      <category>Frontend/Next.js</category>
      <category>authOptions</category>
      <category>nextJS</category>
      <category>type error</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/350</guid>
      <comments>https://reasonjun.tistory.com/350#entry350comment</comments>
      <pubDate>Sat, 16 Dec 2023 01:29:46 +0900</pubDate>
    </item>
    <item>
      <title>React lib : Upload multiple Image using Cloudinary</title>
      <link>https://reasonjun.tistory.com/349</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;upload setting rule :&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://support.cloudinary.com/hc/en-us/articles/202520662-How-can-I-bulk-upload-my-images-&quot;&gt;https://support.cloudinary.com/hc/en-us/articles/202520662-How-can-I-bulk-upload-my-images-&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;method:&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://cloudinary.com/blog/guest_post/upload-images-with-react-dropzone&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://cloudinary.com/blog/guest_post/upload-images-with-react-dropzone&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1702654615189&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;Upload Images with React-Dropzone&quot; data-og-description=&quot;This post describes how to upload images using the react-dropzone package. We&amp;rsquo;ll go through the implementation process by building a basic Next.js application that lets us select images and upload them to Cloudinary. We&amp;rsquo;ll also look at the various ways&quot; data-og-host=&quot;cloudinary.com&quot; data-og-source-url=&quot;https://cloudinary.com/blog/guest_post/upload-images-with-react-dropzone&quot; data-og-url=&quot;https://cloudinary.com/blog/guest_post/upload-images-with-react-dropzone/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/tBO5m/hyUL4fBFgu/LgEkLODXByWGVAMvWI8aK0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=644_272_696_330,https://scrap.kakaocdn.net/dn/ypbUo/hyULVCY1MG/GGO2JVrSKV1K1DXaP0fSkK/img.jpg?width=560&amp;amp;height=308&amp;amp;face=0_0_560_308,https://scrap.kakaocdn.net/dn/jgKEa/hyULYGqjzm/zC8WYzXZOuBtmzZoMD6zFK/img.jpg?width=2000&amp;amp;height=1100&amp;amp;face=1003_418_1081_502&quot;&gt;&lt;a href=&quot;https://cloudinary.com/blog/guest_post/upload-images-with-react-dropzone&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://cloudinary.com/blog/guest_post/upload-images-with-react-dropzone&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/tBO5m/hyUL4fBFgu/LgEkLODXByWGVAMvWI8aK0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=644_272_696_330,https://scrap.kakaocdn.net/dn/ypbUo/hyULVCY1MG/GGO2JVrSKV1K1DXaP0fSkK/img.jpg?width=560&amp;amp;height=308&amp;amp;face=0_0_560_308,https://scrap.kakaocdn.net/dn/jgKEa/hyULYGqjzm/zC8WYzXZOuBtmzZoMD6zFK/img.jpg?width=2000&amp;amp;height=1100&amp;amp;face=1003_418_1081_502');&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;Upload Images with React-Dropzone&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This post describes how to upload images using the react-dropzone package. We&amp;rsquo;ll go through the implementation process by building a basic Next.js application that lets us select images and upload them to Cloudinary. We&amp;rsquo;ll also look at the various ways&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;cloudinary.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;</description>
      <category>Frontend/Library</category>
      <category>Cloudinary</category>
      <category>multiple image</category>
      <category>nextJS</category>
      <category>upload image</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/349</guid>
      <comments>https://reasonjun.tistory.com/349#entry349comment</comments>
      <pubDate>Sat, 16 Dec 2023 00:37:58 +0900</pubDate>
    </item>
    <item>
      <title>Next.js Error : Hydration failed because the initail UI does not match what was rendered on the server.</title>
      <link>https://reasonjun.tistory.com/348</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Error :&lt;/b&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1950&quot; data-origin-height=&quot;1618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k6ly0/btsAMkhA4Vk/5hsZ3ZGMM55eu0jFEzbdE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k6ly0/btsAMkhA4Vk/5hsZ3ZGMM55eu0jFEzbdE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k6ly0/btsAMkhA4Vk/5hsZ3ZGMM55eu0jFEzbdE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk6ly0%2FbtsAMkhA4Vk%2F5hsZ3ZGMM55eu0jFEzbdE1%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;1950&quot; height=&quot;1618&quot; data-origin-width=&quot;1950&quot; data-origin-height=&quot;1618&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Why :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;While rendering your application, there was a difference between the React tree that was pre-rendered from the server and the React tree that was rendered during the first render in the browser (hydration).&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Solution :&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1700705949827&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useState, useEffect } from 'react'
 
export default function App() {
  const [isClient, setIsClient] = useState(false)
 
  useEffect(() =&amp;gt; {
    setIsClient(true)
  }, [])
 
  return &amp;lt;h1&amp;gt;{isClient ? 'This is never prerendered' : 'Prerendered'}&amp;lt;/h1&amp;gt;
}&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;a href=&quot;https://nextjs.org/docs/messages/react-hydration-error&quot;&gt;https://nextjs.org/docs/messages/react-hydration-error&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1700705955149&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;Text content does not match server-rendered HTML&quot; data-og-description=&quot;Using App Router Features available in /app&quot; data-og-host=&quot;nextjs.org&quot; data-og-source-url=&quot;https://nextjs.org/docs/messages/react-hydration-error&quot; data-og-url=&quot;https://nextjs.org/docs/messages/react-hydration-error&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://nextjs.org/docs/messages/react-hydration-error&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://nextjs.org/docs/messages/react-hydration-error&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;Text content does not match server-rendered HTML&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Using App Router Features available in /app&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;nextjs.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;</description>
      <category>Frontend/Next.js</category>
      <category>error</category>
      <category>Hydration failed</category>
      <category>nextJS</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/348</guid>
      <comments>https://reasonjun.tistory.com/348#entry348comment</comments>
      <pubDate>Thu, 23 Nov 2023 11:19:46 +0900</pubDate>
    </item>
    <item>
      <title>Prisma : Next Auth Google provider error</title>
      <link>https://reasonjun.tistory.com/347</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;When :&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;When implementing login using prisma and nextauth.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Error message :&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[next-auth][error][adapter_error_getUserByAccount]&amp;nbsp;&lt;br /&gt;&lt;a href=&quot;https://next-auth.js.org/errors#adapter_error_getuserbyaccount&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://next-auth.js.org/errors#adapter_error_getuserbyaccount&lt;/a&gt;&amp;nbsp;&lt;br /&gt;Invalid&amp;nbsp;`prisma.account.findUnique()`&amp;nbsp;invocation:&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;b&gt;prisma code :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1699291996204&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;generator client {
  provider = &quot;prisma-client-js&quot;
}

datasource db {
  provider     = &quot;mysql&quot;
  url          = env(&quot;DATABASE_URL&quot;)
  // Add this
  relationMode = &quot;prisma&quot;
}

model Account {
  id                String  @id @default(cuid())
  userId            String
  type              String
  provider          String
  providerAccountId String
  refresh_token     String? @db.Text
  access_token      String? @db.Text
  expires_at        Int?
  token_type        String?
  scope             String?
  id_token          String? @db.Text
  session_state     String?
  user              User    @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
  @@index([userId], map: &quot;Account_userId_fkey&quot;)
}

model Session {
  id           String   @id @default(cuid())
  sessionToken String   @unique
  userId       String
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([userId], map: &quot;Session_userId_fkey&quot;)
}

model User {
  id             String          @id @default(cuid())
  name           String?
  email          String?         @unique
  emailVerified  DateTime?
  active         Boolean         @default(false)
  image          String?
  role           String?
  hashedPassword String?
  userType       UserType        @default(User)
  accounts       Account[]
  sessions       Session[]
  ActivateToken  ActivateToken[]
}

model ActivateToken {
  id    String @id @default(cuid())
  token String @unique

  activatedAt DateTime?
  createdAt   DateTime  @default(now())
  updatedAt   DateTime  @updatedAt

  user   User   @relation(fields: [userId], references: [id])
  userId String

  @@index([userId])
}

enum UserType {
  User
  Admin
  Youtuber
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
}&lt;/code&gt;&lt;/pre&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;b&gt;Solution :&amp;nbsp; remove 'map: &quot;~~~&quot;'&lt;/b&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;Why ?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #444654; color: #d1d5db; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;In the Prisma schema code you provided, the line @@index([userId], map: &quot;Account_userId_fkey&quot;) is defining an index for the &quot;Account&quot; model. Let's break down what this line means:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #444654; color: #d1d5db; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;@@index: This is a Prisma schema decorator that is used to define an index on the database table associated with the &quot;Account&quot; model. Indexes are used to optimize database query performance by allowing faster lookup and retrieval of rows based on the indexed columns.&lt;/li&gt;
&lt;li&gt;([userId], map: &quot;Account_userId_fkey&quot;): This part of the code specifies the index definition. It consists of two components:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;([userId]): This is an array of column names on which the index is defined. In this case, the index is defined on the &quot;userId&quot; column of the &quot;Account&quot; model. This means that the database will create an index on the &quot;userId&quot; column, which will improve query performance for operations that involve searching or filtering by the &quot;userId&quot; column.&lt;/li&gt;
&lt;li&gt;map: &quot;Account_userId_fkey&quot;: The map option provides a name for the index. In this case, the index is named &quot;Account_userId_fkey.&quot; This name is typically used as a reference when working with the database, and it helps in uniquely identifying the index.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #444654; color: #d1d5db; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;In summary, the @@index decorator in your Prisma schema is creating an index on the &quot;userId&quot; column of the &quot;Account&quot; model to improve query performance when searching or filtering records based on the &quot;userId&quot; value. The name of the index is specified as &quot;Account_userId_fkey.&quot;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;For&amp;nbsp;this&amp;nbsp;reason,&amp;nbsp;'findUnique'&amp;nbsp;of&amp;nbsp;the&amp;nbsp;account&amp;nbsp;could&amp;nbsp;not&amp;nbsp;be&amp;nbsp;found.&lt;/b&gt;&lt;/h3&gt;</description>
      <category>Backend/Prisma</category>
      <category>Account</category>
      <category>auth</category>
      <category>findUnique</category>
      <category>google login</category>
      <category>next auth</category>
      <category>Prisma</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/347</guid>
      <comments>https://reasonjun.tistory.com/347#entry347comment</comments>
      <pubDate>Tue, 7 Nov 2023 02:41:31 +0900</pubDate>
    </item>
    <item>
      <title>Nextjs :  Warning: To load an ES module, set &amp;quot;type&amp;quot;: &amp;quot;module&amp;quot; in the package.json or use the .mjs extension. (ts-node)</title>
      <link>https://reasonjun.tistory.com/346</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;What happened?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In the case of ts-node, ts was compiled using the commonJS method. Therefore, an error occurs when you try to run a ts file with ts-node in the app or src subfolder of nextjs, which is compiled with esNext.&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;b&gt;Error :&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/TypeStrong/ts-node/issues/935&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/TypeStrong/ts-node/issues/935&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699245936700&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;&amp;#96;ts-node&amp;#96; fails when ES Modules are in the dependency graph in Node.js 13+ &amp;middot; Issue #935 &amp;middot; TypeStrong/ts-node&quot; data-og-description=&quot;I basically detailed the issue in this comment: #155 (comment) It's a chicken-and-egg-like problem: If we use module: 'commonjs', then if any TS files import ES Modules (indirectly in their depende...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/TypeStrong/ts-node/issues/935&quot; data-og-url=&quot;https://github.com/TypeStrong/ts-node/issues/935&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/34E7q/hyUrEniVNE/iVIq5jKjx9rLJlqWvPQn00/img.png?width=1200&amp;amp;height=600&amp;amp;face=984_133_1032_185&quot;&gt;&lt;a href=&quot;https://github.com/TypeStrong/ts-node/issues/935&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/TypeStrong/ts-node/issues/935&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/34E7q/hyUrEniVNE/iVIq5jKjx9rLJlqWvPQn00/img.png?width=1200&amp;amp;height=600&amp;amp;face=984_133_1032_185');&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;`ts-node` fails when ES Modules are in the dependency graph in Node.js 13+ &amp;middot; Issue #935 &amp;middot; TypeStrong/ts-node&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I basically detailed the issue in this comment: #155 (comment) It's a chicken-and-egg-like problem: If we use module: 'commonjs', then if any TS files import ES Modules (indirectly in their depende...&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Solution :&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/ts-node?activeTab=readme#commonjs&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.npmjs.com/package/ts-node?activeTab=readme#commonjs&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699245929092&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;ts-node&quot; data-og-description=&quot;TypeScript execution environment and REPL for node.js, with source map support. Latest version: 10.9.1, last published: a year ago. Start using ts-node in your project by running &amp;#96;npm i ts-node&amp;#96;. There are 9079 other projects in the npm registry using ts-n&quot; data-og-host=&quot;www.npmjs.com&quot; data-og-source-url=&quot;https://www.npmjs.com/package/ts-node?activeTab=readme#commonjs&quot; data-og-url=&quot;https://www.npmjs.com/package/ts-node&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/USz51/hyUrt0mlxJ/ne9Lu4mFsZOReDD9TVTfuk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/ts-node?activeTab=readme#commonjs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.npmjs.com/package/ts-node?activeTab=readme#commonjs&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/USz51/hyUrt0mlxJ/ne9Lu4mFsZOReDD9TVTfuk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;ts-node&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;TypeScript execution environment and REPL for node.js, with source map support. Latest version: 10.9.1, last published: a year ago. Start using ts-node in your project by running `npm i ts-node`. There are 9079 other projects in the npm registry using ts-n&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.npmjs.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/69870137/running-a-single-ts-file-in-a-next-js-project-with-ts-node-for-testing&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://stackoverflow.com/questions/69870137/running-a-single-ts-file-in-a-next-js-project-with-ts-node-for-testing&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1699246197007&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;Running a single .ts file in a Next.js project with ts-node for testing&quot; data-og-description=&quot;I'm trying to run a single ES module .ts file in a Next.js project with default config for quick debugging: npx ts-node lib/my_module.ts which gives me this error: Warning: To load an ES module, s...&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/69870137/running-a-single-ts-file-in-a-next-js-project-with-ts-node-for-testing&quot; data-og-url=&quot;https://stackoverflow.com/questions/69870137/running-a-single-ts-file-in-a-next-js-project-with-ts-node-for-testing&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dmjvRT/hyUrAd7n2J/jkWFjfJSdLTOhBoX1T1C41/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/69870137/running-a-single-ts-file-in-a-next-js-project-with-ts-node-for-testing&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/69870137/running-a-single-ts-file-in-a-next-js-project-with-ts-node-for-testing&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dmjvRT/hyUrAd7n2J/jkWFjfJSdLTOhBoX1T1C41/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;Running a single .ts file in a Next.js project with ts-node for testing&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I'm trying to run a single ES module .ts file in a Next.js project with default config for quick debugging: npx ts-node lib/my_module.ts which gives me this error: Warning: To load an ES module, s...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.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;</description>
      <category>Frontend/Next.js</category>
      <category>CommonJS</category>
      <category>compiler</category>
      <category>error</category>
      <category>exNext</category>
      <category>nextJS</category>
      <category>TS</category>
      <category>ts-node</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/346</guid>
      <comments>https://reasonjun.tistory.com/346#entry346comment</comments>
      <pubDate>Mon, 6 Nov 2023 13:50:28 +0900</pubDate>
    </item>
    <item>
      <title>Typescript : Zod</title>
      <link>https://reasonjun.tistory.com/345</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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.daleseo.com/zod-schema/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.daleseo.com/zod-schema/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1698940089827&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;Zod를 통한 타입스크립트 친화적인 스키마 정의&quot; data-og-description=&quot;Engineering Blog by Dale Seo&quot; data-og-host=&quot;www.daleseo.com&quot; data-og-source-url=&quot;https://www.daleseo.com/zod-schema/&quot; data-og-url=&quot;https://www.daleseo.com/zod-schema/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/EUUfZ/hyUnMGtQho/F11PknOVZt1YkggMHRURt0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.daleseo.com/zod-schema/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.daleseo.com/zod-schema/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/EUUfZ/hyUnMGtQho/F11PknOVZt1YkggMHRURt0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;Zod를 통한 타입스크립트 친화적인 스키마 정의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Engineering Blog by Dale Seo&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.daleseo.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;</description>
      <category>Frontend/Typescript</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/345</guid>
      <comments>https://reasonjun.tistory.com/345#entry345comment</comments>
      <pubDate>Fri, 3 Nov 2023 00:48:32 +0900</pubDate>
    </item>
    <item>
      <title>Tailwindcss : twMerge, clsx</title>
      <link>https://reasonjun.tistory.com/344</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;b&gt;twMerge&lt;/b&gt; is a JavaScript library that merges Tailwind CSS classes without style conflicts. It is useful when you need to conditionally join Tailwind CSS classes together, or when you need to merge Tailwind CSS classes from different sources.&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;clsx&lt;/b&gt; is a JavaScript library that provides a simple and efficient way to conditionally join CSS classes together. It is useful for creating reusable CSS components and for writing complex CSS rules.&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;Using twMerge and clsx together&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;You can use twMerge and clsx together to create a powerful and flexible way to manage Tailwind CSS classes in JavaScript. For example, you can create a utility function that merges Tailwind CSS classes and resolves any conflicts:&lt;/p&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;import { ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';

export const cn = (...inputs: ClassValue[]) =&amp;gt; {
  return twMerge(clsx(inputs));
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This function takes any number of CSS classes as input and returns a single CSS class string that is merged and conflict-free. You can then use this function in your React components to conditionally join Tailwind CSS classes together:&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React from 'react';
import { cn } from './cn';

const Button = ({ variant, size, children }) =&amp;gt; {
  return (
    &amp;lt;button className={cn({ variant, size })}&amp;gt;
      {children}
    &amp;lt;/button&amp;gt;
  );
};

export default Button;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This component will render a button with the specified variant and size. The cn() function will merge the variant and size classes together and resolve any conflicts.&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;Benefits of using twMerge and clsx together&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;There are several benefits to using twMerge and clsx together:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Efficiency:&lt;/b&gt;&amp;nbsp;twMerge and clsx are both very efficient libraries.&amp;nbsp;This means that you can merge and conditionally join Tailwind CSS classes without any noticeable performance overhead.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Flexibility:&lt;/b&gt;&amp;nbsp;twMerge and clsx give you a lot of flexibility in how you manage Tailwind CSS classes in JavaScript.&amp;nbsp;You can create your own utility functions and components to meet your specific needs.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Consistency:&lt;/b&gt;&amp;nbsp;Using twMerge and clsx together can help to ensure that your code is consistent and easy to read.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Overall, twMerge and clsx are two powerful libraries that can help you to write more efficient, flexible, and consistent Tailwind CSS code.&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://www.youtube.com/watch?v=re2JFITR7TI&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=re2JFITR7TI&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=re2JFITR7TI&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/2B3xz/hyUnRf6vsL/1WWJfeYmFteRS5tOQfokhk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=262_188_492_438&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;cn() - Every Tailwind Coder Needs It (clsx + twMerge)&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/re2JFITR7TI&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Frontend/Tailwindcss</category>
      <category>CLSX</category>
      <category>cn()</category>
      <category>tailwindcss</category>
      <category>twMerge()</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/344</guid>
      <comments>https://reasonjun.tistory.com/344#entry344comment</comments>
      <pubDate>Wed, 1 Nov 2023 17:26:54 +0900</pubDate>
    </item>
    <item>
      <title>Solidity : 0.8.20 PUSH0 ( invalid opcode )</title>
      <link>https://reasonjun.tistory.com/343</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;the new PUSH0 opcode in Solidity 0.8.20. It discusses what the opcode is and why it is needed. It also goes into the benefits of using PUSH0, such as reducing contract size and gas costs. Finally, the article provides a warning about using PUSH0 on other chains besides Ethereum mainnet.&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;Here is a more detailed summary of the article:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PUSH0 is a new opcode in Solidity 0.8.20 that allows developers to push an empty byte string onto the stack.&lt;/li&gt;
&lt;li&gt;This is useful for a variety of reasons, such as initializing arrays and structs, and for passing empty arguments to functions.&lt;/li&gt;
&lt;li&gt;PUSH0 can also be used to reduce contract size and gas costs, as it can eliminate the need to store empty byte strings in the contract code.&lt;/li&gt;
&lt;li&gt;However, it is important to note that PUSH0 should not be used on other chains besides Ethereum mainnet, as it is not supported by all compilers and runtimes.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://medium.com/coinmonks/push0-opcode-a-significant-update-in-the-latest-solidity-version-0-8-20-ea028668028a&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://medium.com/coinmonks/push0-opcode-a-significant-update-in-the-latest-solidity-version-0-8-20-ea028668028a&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1698038064756&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;PUSH0 opcode: A significant update in the latest solidity version 0.8.20&quot; data-og-description=&quot;What is the PUSH0 opcode? An explanation of solidity latest version 0.8.20 changes and EIP-3855.&quot; data-og-host=&quot;medium.com&quot; data-og-source-url=&quot;https://medium.com/coinmonks/push0-opcode-a-significant-update-in-the-latest-solidity-version-0-8-20-ea028668028a&quot; data-og-url=&quot;https://medium.com/coinmonks/push0-opcode-a-significant-update-in-the-latest-solidity-version-0-8-20-ea028668028a&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Ny3tu/hyUkdQlCjo/2bazPZ7QNikkbn3aG20LJk/img.png?width=922&amp;amp;height=532&amp;amp;face=0_0_922_532,https://scrap.kakaocdn.net/dn/Tv0dU/hyUgNsgdlH/Yw95LeEXDoKYR70aR4dFfk/img.jpg?width=1024&amp;amp;height=600&amp;amp;face=0_0_1024_600&quot;&gt;&lt;a href=&quot;https://medium.com/coinmonks/push0-opcode-a-significant-update-in-the-latest-solidity-version-0-8-20-ea028668028a&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://medium.com/coinmonks/push0-opcode-a-significant-update-in-the-latest-solidity-version-0-8-20-ea028668028a&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Ny3tu/hyUkdQlCjo/2bazPZ7QNikkbn3aG20LJk/img.png?width=922&amp;amp;height=532&amp;amp;face=0_0_922_532,https://scrap.kakaocdn.net/dn/Tv0dU/hyUgNsgdlH/Yw95LeEXDoKYR70aR4dFfk/img.jpg?width=1024&amp;amp;height=600&amp;amp;face=0_0_1024_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;PUSH0 opcode: A significant update in the latest solidity version 0.8.20&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What is the PUSH0 opcode? An explanation of solidity latest version 0.8.20 changes and EIP-3855.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;medium.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://eips.ethereum.org/EIPS/eip-3855?ref=zaryabs.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://eips.ethereum.org/EIPS/eip-3855?ref=zaryabs.com&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1698038138949&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;EIP-3855: PUSH0 instruction&quot; data-og-description=&quot;Introduce a new instruction which pushes the constant value 0 onto the stack&quot; data-og-host=&quot;eips.ethereum.org&quot; data-og-source-url=&quot;https://eips.ethereum.org/EIPS/eip-3855?ref=zaryabs.com&quot; data-og-url=&quot;https://eips.ethereum.org/EIPS/eip-3855&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://eips.ethereum.org/EIPS/eip-3855?ref=zaryabs.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://eips.ethereum.org/EIPS/eip-3855?ref=zaryabs.com&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;EIP-3855: PUSH0 instruction&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Introduce a new instruction which pushes the constant value 0 onto the stack&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;eips.ethereum.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;</description>
      <category>Blockchain/Solidity</category>
      <category>0.8.20</category>
      <category>PUSH0</category>
      <category>solidity</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/343</guid>
      <comments>https://reasonjun.tistory.com/343#entry343comment</comments>
      <pubDate>Mon, 23 Oct 2023 14:19:46 +0900</pubDate>
    </item>
    <item>
      <title>Solidity : abi.encodePacked(), super.uri()</title>
      <link>https://reasonjun.tistory.com/342</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;The abi.encodePacked() function is a built-in Solidity function that is used to encode multiple values into a single byte array. The function takes any number of arguments and concatenates them into a single byte array.&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 abi.encodePacked() function is typically used to encode data that is going to be passed to a contract function. For example, the following code would encode the string &quot;Hello, world!&quot; into a byte array:&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;bytes memory data = abi.encodePacked(&quot;Hello, world!&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The data variable would now contain the byte array [0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21].&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 abi.encodePacked() function can also be used to encode multiple values into a single byte array. For example, the following code would encode the values 1, 2, and 3 into a single byte array:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;bytes memory data = abi.encodePacked(1, 2, 3);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The data variable would now contain the byte array [0x01, 0x02, 0x03].&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The abi.encodePacked() function is a useful function for encoding data that is going to be passed to a contract function. The function can be used to encode any type of data, including strings, integers, and booleans.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;function uri(uint256 tokenId) public view virtual override returns (string memory) {
        string memory tokenURI = _tokenURIs[tokenId];

        // If token URI is set, concatenate base URI and tokenURI (via abi.encodePacked).
        return bytes(tokenURI).length &amp;gt; 0 ? string(abi.encodePacked(_baseURI, tokenURI)) : super.uri(tokenId);
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The code string(abi.encodePacked(_baseURI, tokenURI)) is used to cast the byte array returned by the abi.encodePacked() function to a string. The abi.encodePacked() function takes two arguments, _baseURI and tokenURI, and concatenates them into a single byte array. The string() function then casts the byte array to a string.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The resulting string is the token URI for the token. The token URI is a JSON document that contains information about the token, such as its name, description, and image.&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 token URI is used by OpenSea and other NFT marketplaces to display information about the token.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In this case, the _baseURI is the base URI for all tokens. The base URI is a string that is used to generate the token URI for a token. For example, if the base URI is &lt;a href=&quot;https://example.com/tokens/&quot;&gt;https://example.com/tokens/&lt;/a&gt;, then the token URI for token ID 1 would be &lt;a href=&quot;https://example.com/tokens/1&quot;&gt;https://example.com/tokens/1&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;The tokenURI is the token URI for a specific token. The token URI can be set using the setURI() function.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;For example, if the tokenURI for token ID 1 is { &quot;name&quot;: &quot;My Token&quot;, &quot;description&quot;: &quot;This is my token.&quot;, &quot;image&quot;: &quot;&amp;lt;&lt;a href=&quot;https://example.com/tokens/1.jpg&quot;&gt;https://example.com/tokens/1.jpg&lt;/a&gt;&amp;gt;&quot; }, then the resulting string would be:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;&lt;a href=&quot;https://example.com/tokens/&quot;&gt;https://example.com/tokens/&lt;/a&gt;{ &quot;name&quot;: &quot;My Token&quot;, &quot;description&quot;: &quot;This is my token.&quot;, &quot;image&quot;: &quot;&lt;a href=&quot;https://example.com/tokens/1.jpg&quot;&gt;https://example.com/tokens/1.jpg&lt;/a&gt;&quot; }&quot;&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;b&gt;super.uri()&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In the context of the MyERC1155 contract, the super.uri(tokenId) function is used to generate the token URI for a token if a token URI has not been set for the token. The MyERC1155 contract has a setURI() function that can be used to set a token URI for a specific token.&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;If a token URI has been set for a token, then the MyERC1155 contract will return the token URI that was set. Otherwise, the MyERC1155 contract will call the super.uri(tokenId) function to generate the token URI.&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 super.uri(tokenId) function is a useful function for ensuring that all tokens have a token URI. The token URI is used by OpenSea and other NFT marketplaces to display information about the token.&lt;/p&gt;</description>
      <category>Blockchain/Solidity</category>
      <category>abi.encodePacked()</category>
      <category>ERC-1155</category>
      <category>Ethereum</category>
      <category>solidity</category>
      <category>super.uri()</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/342</guid>
      <comments>https://reasonjun.tistory.com/342#entry342comment</comments>
      <pubDate>Sun, 22 Oct 2023 22:06:38 +0900</pubDate>
    </item>
    <item>
      <title>Ethereum : ERC1155</title>
      <link>https://reasonjun.tistory.com/341</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ERC-1155 is a token standard for representing both fungible and non-fungible tokens (NFTs) on the Ethereum blockchain. It is a single standard that can be used to represent a wide variety of assets, such as game items, collectibles, and even real-world 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;ERC-1155 tokens are identified by two values: a token ID and a balance. The token ID is a unique identifier for the type of token, while the balance is the amount of that type of token that an address holds. For example, an ERC-1155 token could represent a game item, such as a sword. The token ID would be the same for all swords, but the balance would be different for each address that holds swords.&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;ERC-1155 tokens can be both fungible and non-fungible. Fungible tokens are interchangeable, meaning that one token is worth the same as any other token of the same type. For example, ERC-20 tokens are fungible, as one Ether (ETH) is worth the same as any other ETH. Non-fungible tokens are not interchangeable, meaning that each token is unique. For example, an ERC-721 token that represents a collectible artwork is non-fungible, as no two artworks are exactly alike.&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;ERC-1155 tokens offer a number of advantages over other token standards. First, they are more efficient, as they can be used to represent a wider variety of assets. Second, they are more flexible, as they can be both fungible and non-fungible. Third, they are more secure, as they are less likely to be subject to fraud or manipulation.&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;ERC-1155 tokens are a powerful tool that can be used to create a wide variety of decentralized applications (dApps). They are a versatile standard that can be used to represent a wide range of assets, and they offer a number of advantages over other token standards.&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;Here are some of the benefits of using ERC-1155 tokens:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Efficiency:&lt;/b&gt;&amp;nbsp;ERC-1155 tokens are more efficient than other token standards, as they can be used to represent a wider variety of assets. For example, a single ERC-1155 contract could be used to represent all of the items in a game, such as weapons, armor, and potions. This would save gas and storage space, as it would not be necessary to create a separate contract for each item.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Flexibility:&lt;/b&gt;&amp;nbsp;ERC-1155 tokens are more flexible than other token standards, as they can be both fungible and non-fungible. This makes them ideal for representing a wide range of assets. For example, an ERC-1155 token could be used to represent both fungible assets, such as game currency, and non-fungible assets, such as unique game items.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Security:&lt;/b&gt;&amp;nbsp;ERC-1155 tokens are more secure than other token standards, as they are less likely to be subject to fraud or manipulation. This is because ERC-1155 tokens use a more robust approval mechanism than other token standards.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Overall, ERC-1155 tokens are a powerful tool that can be used to create a wide variety of dApps. They are a versatile standard that can be used to represent a wide range of assets, and they offer a number of advantages over other token standards.&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;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Feature&lt;/td&gt;
&lt;td&gt;ERC-721&lt;/td&gt;
&lt;td&gt;ERC-1155&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fungibility&lt;/td&gt;
&lt;td&gt;Non-fungible&lt;/td&gt;
&lt;td&gt;Fungible and non-fungible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token ID&lt;/td&gt;
&lt;td&gt;Single token ID per token type&lt;/td&gt;
&lt;td&gt;Single token ID for all tokens of the same type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Balance&lt;/td&gt;
&lt;td&gt;Balance is not tracked&lt;/td&gt;
&lt;td&gt;Balance is tracked for each token type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use cases&lt;/td&gt;
&lt;td&gt;Collectibles, digital art, game items&lt;/td&gt;
&lt;td&gt;Game items, in-game currency, tickets, voting rights&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Examples&lt;/td&gt;
&lt;td&gt;CryptoKitties, Decentraland, NBA Top Shot&lt;/td&gt;
&lt;td&gt;Enjin Coin, Gods Unchained, Decentraland&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Efficiency&lt;/td&gt;
&lt;td&gt;Less efficient, as a separate contract is required for each token type&lt;/td&gt;
&lt;td&gt;More efficient, as a single contract can be used to represent multiple token types&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flexibility&lt;/td&gt;
&lt;td&gt;Less flexible, as tokens can only be non-fungible&lt;/td&gt;
&lt;td&gt;More flexible, as tokens can be both fungible and non-fungible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;More secure, as the approval mechanism is more robust&lt;/td&gt;
&lt;td&gt;Less secure, as the approval mechanism is less robust&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description>
      <category>Blockchain/Solidity</category>
      <category>ERC1155</category>
      <category>Ethereum</category>
      <category>solidity</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/341</guid>
      <comments>https://reasonjun.tistory.com/341#entry341comment</comments>
      <pubDate>Sun, 22 Oct 2023 21:29:08 +0900</pubDate>
    </item>
    <item>
      <title>Openzeppelin : ERC20PresetMinterPauser</title>
      <link>https://reasonjun.tistory.com/340</link>
      <description>&lt;pre id=&quot;code_1697976237039&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/presets/ERC20PresetMinterPauser.sol)

pragma solidity ^0.8.0;

import &quot;../ERC20.sol&quot;;
import &quot;../extensions/ERC20Burnable.sol&quot;;
import &quot;../extensions/ERC20Pausable.sol&quot;;
import &quot;../../../access/AccessControlEnumerable.sol&quot;;
import &quot;../../../utils/Context.sol&quot;;

/**
 * @dev {ERC20} token, including:
 *
 *  - ability for holders to burn (destroy) their tokens
 *  - a minter role that allows for token minting (creation)
 *  - a pauser role that allows to stop all token transfers
 *
 * This contract uses {AccessControl} to lock permissioned functions using the
 * different roles - head to its documentation for details.
 *
 * The account that deploys the contract will be granted the minter and pauser
 * roles, as well as the default admin role, which will let it grant both minter
 * and pauser roles to other accounts.
 *
 * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._
 */
contract ERC20PresetMinterPauser is Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable {
    bytes32 public constant MINTER_ROLE = keccak256(&quot;MINTER_ROLE&quot;);
    bytes32 public constant PAUSER_ROLE = keccak256(&quot;PAUSER_ROLE&quot;);

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
     * account that deploys the contract.
     *
     * See {ERC20-constructor}.
     */
    constructor(string memory name, string memory symbol) ERC20(name, symbol) {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MINTER_ROLE, _msgSender());
        _setupRole(PAUSER_ROLE, _msgSender());
    }

    /**
     * @dev Creates `amount` new tokens for `to`.
     *
     * See {ERC20-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function mint(address to, uint256 amount) public virtual {
        require(hasRole(MINTER_ROLE, _msgSender()), &quot;ERC20PresetMinterPauser: must have minter role to mint&quot;);
        _mint(to, amount);
    }

    /**
     * @dev Pauses all token transfers.
     *
     * See {ERC20Pausable} and {Pausable-_pause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function pause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), &quot;ERC20PresetMinterPauser: must have pauser role to pause&quot;);
        _pause();
    }

    /**
     * @dev Unpauses all token transfers.
     *
     * See {ERC20Pausable} and {Pausable-_unpause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function unpause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), &quot;ERC20PresetMinterPauser: must have pauser role to unpause&quot;);
        _unpause();
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override(ERC20, ERC20Pausable) {
        super._beforeTokenTransfer(from, to, amount);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This is the source code for the ERC20PresetMinterPauser contract. This contract is a preset implementation of the ERC-20 standard that includes the following features:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;The&amp;nbsp;ability for holders to burn (destroy) their tokens&lt;/li&gt;
&lt;li&gt;A minter role that allows for token minting (creation)&lt;/li&gt;
&lt;li&gt;A pauser role that allows to stop all token transfers&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The contract uses the AccessControl library to lock permissioned functions using the different roles. The account that deploys the contract will be granted the minter and pauser roles, as well as the default admin role, which will let it grant both minter and pauser roles to other 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;The mint() function mints a new token and assigns it to the specified address. The caller must have the MINTER_ROLE in order to call this 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;The pause() and unpause() functions pause and unpause all token transfers, respectively. The caller must have the PAUSER_ROLE in order to call these functions.&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 _beforeTokenTransfer() function is called before any token transfer. This function is used to implement the pausable functionality. If the contract is paused, then the transfer will be cancelled.&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 supportsInterface() function returns true if the contract supports the specified interface. The contract supports the following interfaces:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IERC165&lt;/li&gt;
&lt;li&gt;IERC20&lt;/li&gt;
&lt;li&gt;IERC20Metadata&lt;/li&gt;
&lt;li&gt;AccessControlEnumerable&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This contract is a good starting point for anyone who wants to create an ERC-20 token with the features listed above.&lt;/p&gt;</description>
      <category>Blockchain/Solidity</category>
      <category>ERC20PresetMinterPauser</category>
      <category>Openzeppelin</category>
      <category>solidity</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/340</guid>
      <comments>https://reasonjun.tistory.com/340#entry340comment</comments>
      <pubDate>Sun, 22 Oct 2023 21:06:49 +0900</pubDate>
    </item>
    <item>
      <title>Openzeppelin : ERC721PresetMinterPauserAutoId</title>
      <link>https://reasonjun.tistory.com/339</link>
      <description>&lt;pre id=&quot;code_1697975781623&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol)

pragma solidity ^0.8.0;

import &quot;../ERC721.sol&quot;;
import &quot;../extensions/ERC721Enumerable.sol&quot;;
import &quot;../extensions/ERC721Burnable.sol&quot;;
import &quot;../extensions/ERC721Pausable.sol&quot;;
import &quot;../../../access/AccessControlEnumerable.sol&quot;;
import &quot;../../../utils/Context.sol&quot;;
import &quot;../../../utils/Counters.sol&quot;;

/**
 * @dev {ERC721} token, including:
 *
 *  - ability for holders to burn (destroy) their tokens
 *  - a minter role that allows for token minting (creation)
 *  - a pauser role that allows to stop all token transfers
 *  - token ID and URI autogeneration
 *
 * This contract uses {AccessControl} to lock permissioned functions using the
 * different roles - head to its documentation for details.
 *
 * The account that deploys the contract will be granted the minter and pauser
 * roles, as well as the default admin role, which will let it grant both minter
 * and pauser roles to other accounts.
 *
 * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._
 */
contract ERC721PresetMinterPauserAutoId is
    Context,
    AccessControlEnumerable,
    ERC721Enumerable,
    ERC721Burnable,
    ERC721Pausable
{
    using Counters for Counters.Counter;

    bytes32 public constant MINTER_ROLE = keccak256(&quot;MINTER_ROLE&quot;);
    bytes32 public constant PAUSER_ROLE = keccak256(&quot;PAUSER_ROLE&quot;);

    Counters.Counter private _tokenIdTracker;

    string private _baseTokenURI;

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
     * account that deploys the contract.
     *
     * Token URIs will be autogenerated based on `baseURI` and their token IDs.
     * See {ERC721-tokenURI}.
     */
    constructor(
        string memory name,
        string memory symbol,
        string memory baseTokenURI
    ) ERC721(name, symbol) {
        _baseTokenURI = baseTokenURI;

        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());

        _setupRole(MINTER_ROLE, _msgSender());
        _setupRole(PAUSER_ROLE, _msgSender());
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return _baseTokenURI;
    }

    /**
     * @dev Creates a new token for `to`. Its token ID will be automatically
     * assigned (and available on the emitted {IERC721-Transfer} event), and the token
     * URI autogenerated based on the base URI passed at construction.
     *
     * See {ERC721-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function mint(address to) public virtual {
        require(hasRole(MINTER_ROLE, _msgSender()), &quot;ERC721PresetMinterPauserAutoId: must have minter role to mint&quot;);

        // We cannot just use balanceOf to create the new tokenId because tokens
        // can be burned (destroyed), so we need a separate counter.
        _mint(to, _tokenIdTracker.current());
        _tokenIdTracker.increment();
    }

    /**
     * @dev Pauses all token transfers.
     *
     * See {ERC721Pausable} and {Pausable-_pause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function pause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), &quot;ERC721PresetMinterPauserAutoId: must have pauser role to pause&quot;);
        _pause();
    }

    /**
     * @dev Unpauses all token transfers.
     *
     * See {ERC721Pausable} and {Pausable-_unpause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function unpause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), &quot;ERC721PresetMinterPauserAutoId: must have pauser role to unpause&quot;);
        _unpause();
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 firstTokenId,
        uint256 batchSize
    ) internal virtual override(ERC721, ERC721Enumerable, ERC721Pausable) {
        super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(AccessControlEnumerable, ERC721, ERC721Enumerable)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This is the source code for the ERC721PresetMinterPauserAutoId contract. This contract is a preset implementation of the ERC-721 standard that includes the following features:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;The&amp;nbsp;ability for holders to burn (destroy) their tokens&lt;/li&gt;
&lt;li&gt;A minter role that allows for token minting (creation)&lt;/li&gt;
&lt;li&gt;A pauser role that allows to stop all token transfers&lt;/li&gt;
&lt;li&gt;Token ID and URI autogeneration&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The contract uses the AccessControl library to lock permissioned functions using the different roles. The account that deploys the contract will be granted the minter and pauser roles, as well as the default admin role, which will let it grant both minter and pauser roles to other 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;The _baseURI() function returns the base URI for all token URIs. The base URI is the prefix that is added to the token ID to generate the full token URI. For example, if the base URI is &lt;a href=&quot;https://example.com/tokens/&quot;&gt;https://example.com/tokens/&lt;/a&gt;, then the token URI for token ID 1 would be &lt;a href=&quot;https://example.com/tokens/1&quot;&gt;https://example.com/tokens/1&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;The mint() function mints a new token and assigns it to the specified address. The token ID is automatically assigned and the token URI is generated based on the base URI. The caller must have the MINTER_ROLE in order to call this 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;The pause() and unpause() functions pause and unpause all token transfers, respectively. The caller must have the PAUSER_ROLE in order to call these functions.&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 _beforeTokenTransfer() function is called before any token transfer. This function is used to implement the pausable functionality. If the contract is paused, then the transfer will be cancelled.&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 supportsInterface() function returns true if the contract supports the specified interface. The contract supports the following interfaces:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IERC165&lt;/li&gt;
&lt;li&gt;IERC721&lt;/li&gt;
&lt;li&gt;IERC721Enumerable&lt;/li&gt;
&lt;li&gt;IERC721Metadata&lt;/li&gt;
&lt;li&gt;AccessControlEnumerable&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This contract is a good starting point for anyone who wants to create an ERC-721 token with the features listed above.&lt;/p&gt;</description>
      <category>Blockchain/Solidity</category>
      <category>ERC721PresetMinterPauserAutoId</category>
      <category>Openzeppelin</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/339</guid>
      <comments>https://reasonjun.tistory.com/339#entry339comment</comments>
      <pubDate>Sun, 22 Oct 2023 21:01:48 +0900</pubDate>
    </item>
    <item>
      <title>Ethereum : ERC721</title>
      <link>https://reasonjun.tistory.com/338</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ERC-721 is a standard for non-fungible tokens (NFTs) on the Ethereum blockchain. NFTs are unique digital assets that cannot be replicated or replaced. This is in contrast to fungible tokens, such as ERC-20 tokens, which are interchangeable and can be replaced with one another.&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;ERC-721 tokens are often used to represent digital collectibles, such as artwork, music, or game items. They can also be used to represent real-world assets, such as property or ownership rights.&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 ERC-721 standard defines a set of functions that must be implemented by all ERC-721 tokens. These functions allow for the creation, transfer, and ownership of NFTs.&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;Some of the key functions in the ERC-721 standard include:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;balanceOf(address owner): Returns the balance of the owner's account.&lt;/li&gt;
&lt;li&gt;ownerOf(uint256 tokenId): Returns the address of the owner of the given token ID.&lt;/li&gt;
&lt;li&gt;transferFrom(address from, address to, uint256 tokenId): Transfers the ownership of the given token ID from the&amp;nbsp;from&amp;nbsp;address to the&amp;nbsp;to&amp;nbsp;address.&lt;/li&gt;
&lt;li&gt;approve(address to, uint256 tokenId): Approves the&amp;nbsp;to&amp;nbsp;address to transfer the ownership of the given token ID on behalf of the owner.&lt;/li&gt;
&lt;li&gt;setApprovalForAll(address operator, bool approved): Approves the&amp;nbsp;operator&amp;nbsp;address to transfer any of the owner's tokens on their behalf.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The ERC-721 standard is a widely used standard for NFTs. It is supported by most Ethereum wallets and exchanges.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Some of the benefits of using ERC-721 tokens include:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Uniqueness:&lt;/b&gt;&amp;nbsp;ERC-721 tokens are unique and cannot be replicated or replaced. This makes them ideal for representing digital collectibles and other unique assets.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Provable ownership:&lt;/b&gt;&amp;nbsp;The ownership of ERC-721 tokens is stored on the Ethereum blockchain. This makes it possible to prove ownership of an NFT.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Transferability:&lt;/b&gt;&amp;nbsp;ERC-721 tokens can be transferred between addresses. This makes them easy to buy, sell, or trade.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The ERC-721 standard is a powerful tool for creating and managing digital assets. It is a versatile standard that can be used for a wide variety of applications.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Essential function&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgEVRA/btsyWfJiMeO/tQCXkKNabEtjgRs5ksdKpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgEVRA/btsyWfJiMeO/tQCXkKNabEtjgRs5ksdKpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgEVRA/btsyWfJiMeO/tQCXkKNabEtjgRs5ksdKpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgEVRA%2FbtsyWfJiMeO%2FtQCXkKNabEtjgRs5ksdKpK%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;1550&quot; height=&quot;354&quot; data-origin-width=&quot;1550&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Essential event&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1546&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxLkXt/btsyR8ZcDob/dhX4Bq35ylv7A2QRmDLak1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxLkXt/btsyR8ZcDob/dhX4Bq35ylv7A2QRmDLak1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxLkXt/btsyR8ZcDob/dhX4Bq35ylv7A2QRmDLak1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxLkXt%2FbtsyR8ZcDob%2FdhX4Bq35ylv7A2QRmDLak1%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;1546&quot; height=&quot;134&quot; data-origin-width=&quot;1546&quot; data-origin-height=&quot;134&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;</description>
      <category>Blockchain/Ethereum</category>
      <category>erc721</category>
      <category>Ethereum</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/338</guid>
      <comments>https://reasonjun.tistory.com/338#entry338comment</comments>
      <pubDate>Sun, 22 Oct 2023 20:55:04 +0900</pubDate>
    </item>
    <item>
      <title>Etherscan : Verify</title>
      <link>https://reasonjun.tistory.com/337</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;In Etherscan, &quot;Verify&quot; is a process that allows developers to upload the source code of their smart contracts to the Etherscan website. Once the source code is uploaded, Etherscan will match it with the bytecode that is deployed on the Ethereum blockchain. If the source code and bytecode match, the contract will be verified.&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;Verifying a contract has several benefits:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;It provides transparency for users interacting with the contract. By uploading the source code, developers are making it possible for users to see how the contract works. This can help to build trust and confidence in the contract.&lt;/li&gt;
&lt;li&gt;It allows users to analyze the contract. Once the source code is uploaded, users can use Etherscan's tools to analyze the contract. This can help users to identify potential vulnerabilities or problems with the contract.&lt;/li&gt;
&lt;li&gt;It makes it easier to interact with the contract. Once a contract is verified, Etherscan will generate a user interface that makes it easier for users to interact with the contract. This can be helpful for users who are not familiar with how to interact with smart contracts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;To verify a contract, developers can follow these steps:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Go to the Etherscan website.&lt;/li&gt;
&lt;li&gt;Click on the &quot;Verify Contract&quot; tab.&lt;/li&gt;
&lt;li&gt;Enter the contract address in the &quot;Contract Address&quot; field.&lt;/li&gt;
&lt;li&gt;Select the compiler type in the &quot;Compiler Type&quot; field.&lt;/li&gt;
&lt;li&gt;Upload the source code in the &quot;Source Code&quot; field.&lt;/li&gt;
&lt;li&gt;Click on the &quot;Verify and Publish&quot; button.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;If the verification is successful, the contract will be marked as verified on Etherscan.&lt;/p&gt;</description>
      <category>Blockchain/Ethereum</category>
      <category>etherscan</category>
      <category>verify</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/337</guid>
      <comments>https://reasonjun.tistory.com/337#entry337comment</comments>
      <pubDate>Sat, 21 Oct 2023 23:18:15 +0900</pubDate>
    </item>
    <item>
      <title>Hardhat : ethereum-waffle</title>
      <link>https://reasonjun.tistory.com/336</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Ethereum-Waffle is a testing framework for Ethereum smart contracts. It is designed to be easy to use and to provide a comprehensive set of features for testing smart contracts.&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;Waffle provides the following features:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A simple and intuitive API for writing tests&lt;/li&gt;
&lt;li&gt;Support for all of the Solidity features&lt;/li&gt;
&lt;li&gt;A built-in mocking framework&lt;/li&gt;
&lt;li&gt;A built-in snapshotting framework&lt;/li&gt;
&lt;li&gt;A built-in coverage reporting framework&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Waffle is a popular choice for testing Ethereum smart contracts. It is used by many projects, including Uniswap, Aave, and Yearn Finance.&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;Waffle is a great choice for testing Ethereum smart contracts because it is easy to use and provides a comprehensive set of features. It is also a well-maintained project with a large community of 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;Here are some of the benefits of using Waffle:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Easy to use: Waffle has a simple and intuitive API that makes it easy to write tests.&lt;/li&gt;
&lt;li&gt;Comprehensive: Waffle provides support for all of the Solidity features, so you can be sure that your tests are covering all of the code in your smart contracts.&lt;/li&gt;
&lt;li&gt;Built-in mocking: Waffle has a built-in mocking framework that makes it easy to mock external dependencies. This can be helpful for testing code that interacts with other contracts or with the Ethereum network.&lt;/li&gt;
&lt;li&gt;Built-in snapshotting: Waffle has a built-in snapshotting framework that makes it easy to revert the state of the Ethereum blockchain to a previous point in time. This can be helpful for testing code that modifies the state of the blockchain.&lt;/li&gt;
&lt;li&gt;Built-in coverage reporting: Waffle has a built-in coverage reporting framework that makes it easy to see which parts of your code are being covered by your tests.&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;a href=&quot;https://ethereum-waffle.readthedocs.io/en/latest/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ethereum-waffle.readthedocs.io/en/latest/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1697897662110&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;Waffle Documentation &amp;mdash; waffle  documentation&quot; data-og-description=&quot;&amp;copy; Copyright 2020 Ethworks sp z o.o. Revision 0915e727.&quot; data-og-host=&quot;ethereum-waffle.readthedocs.io&quot; data-og-source-url=&quot;https://ethereum-waffle.readthedocs.io/en/latest/&quot; data-og-url=&quot;https://ethereum-waffle.readthedocs.io/en/latest/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://ethereum-waffle.readthedocs.io/en/latest/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ethereum-waffle.readthedocs.io/en/latest/&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;Waffle Documentation &amp;mdash; waffle documentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;copy; Copyright 2020 Ethworks sp z o.o. Revision 0915e727.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ethereum-waffle.readthedocs.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;</description>
      <category>Blockchain/HardHat</category>
      <category>Ethereum</category>
      <category>ethereum-waffle</category>
      <category>hardhat</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/336</guid>
      <comments>https://reasonjun.tistory.com/336#entry336comment</comments>
      <pubDate>Sat, 21 Oct 2023 23:15:36 +0900</pubDate>
    </item>
    <item>
      <title>Hardhat : ethers.constants.AddressZero</title>
      <link>https://reasonjun.tistory.com/335</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;The &lt;b&gt;ethers.constants.AddressZero&lt;/b&gt; constant is a special address that represents the null address. This address is used to represent the address of the contract that is creating tokens.&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 null address is a special address that is not associated with any account. &lt;u&gt;It is used to represent the absence of an address. For example, if a token is transferred to the null address, the token is effectively burned.&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;The &lt;b&gt;null address&lt;/b&gt; is also used to represent the address of the &lt;b&gt;contract that is creating tokens&lt;/b&gt;. &lt;u&gt;This is because the contract itself does not have an address. When a contract creates tokens, the tokens are created with the address of the contract. However, the contract itself does not have an address, so the null address is used instead.&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;The ethers.constants.AddressZero constant is a convenient way to refer to the null address. It is also a safe way to refer to the null address, as it is guaranteed to be the correct address.&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;In the example you provided, the ethers.constants.AddressZero constant is being used to assert that the Transfer event is being emitted with the address of the contract as the sender. This is because the contract is creating the tokens that are being transferred.&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;1620&quot; data-origin-height=&quot;1382&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLb6wz/btsyQRb2Nqp/HnahSoyqno6uDOQr1P1Slk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLb6wz/btsyQRb2Nqp/HnahSoyqno6uDOQr1P1Slk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLb6wz/btsyQRb2Nqp/HnahSoyqno6uDOQr1P1Slk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLb6wz%2FbtsyQRb2Nqp%2FHnahSoyqno6uDOQr1P1Slk%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;1620&quot; height=&quot;1382&quot; data-origin-width=&quot;1620&quot; data-origin-height=&quot;1382&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Blockchain/HardHat</category>
      <category>ethers.constants.AddressZero</category>
      <category>hardhat</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/335</guid>
      <comments>https://reasonjun.tistory.com/335#entry335comment</comments>
      <pubDate>Sat, 21 Oct 2023 18:18:52 +0900</pubDate>
    </item>
    <item>
      <title>Hardhat : ethers.utils.parseUnits()</title>
      <link>https://reasonjun.tistory.com/334</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ethers.utils.parseUnits()&lt;/b&gt; is a utility function provided by the &lt;b&gt;ethers.js&lt;/b&gt; library, which is commonly used for Ethereum development. This function is used to convert a decimal number into its equivalent representation in a specific Ethereum denomination, typically in Wei.&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;In Ethereum, the smallest unit of Ether is Wei. 1 Ether is equal to 10^18 Wei. So, when working with Ether values, it's common to convert them to Wei for precision. The &lt;b&gt;parseUnits()&lt;/b&gt; function simplifies this conversion.&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;Here's the basic usage of &lt;b&gt;ethers.utils.parseUnits()&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const ethers = require('ethers'); // Import the ethers.js library

// Example: Convert 1.5 Ether to Wei
const etherValue = '1.5'; // This is in Ether
const weiValue = ethers.utils.parseUnits(etherValue, 18); // 18 is the number of decimal places in Wei

console.log(weiValue.toString()); // This will output the equivalent value in Wei
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In the example above, &lt;b&gt;ethers.utils.parseUnits()&lt;/b&gt; takes the value &lt;b&gt;1.5&lt;/b&gt; and converts it to its equivalent in Wei, considering 18 decimal places. The result is then represented as a &lt;b&gt;BigNumber&lt;/b&gt; in ethers.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;This function is useful when working with Ethereum values, especially in smart contract development, where precise conversions between different denominations (Wei, Gwei, Ether, etc.) are often required.&lt;/p&gt;</description>
      <category>Blockchain/HardHat</category>
      <category>ethers.utils.parseUnits</category>
      <category>hardhat</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/334</guid>
      <comments>https://reasonjun.tistory.com/334#entry334comment</comments>
      <pubDate>Sat, 21 Oct 2023 18:07:38 +0900</pubDate>
    </item>
    <item>
      <title>Ethereum : ERC-20 (Ethereum Request for Comments 20)</title>
      <link>https://reasonjun.tistory.com/333</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ERC-20 is a technical standard for fungible tokens on the Ethereum blockchain. Fungible tokens are interchangeable with each other, meaning that one token is worth the same as any other token of the same type. This is in contrast to non-fungible tokens (NFTs), which are unique and cannot be replaced.&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 ERC-20 standard defines a set of rules that all ERC-20 tokens must follow. These rules include:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;The ability to transfer tokens from one account to another&lt;/li&gt;
&lt;li&gt;The ability to get the current balance of an account&lt;/li&gt;
&lt;li&gt;The ability to get the total supply of tokens&lt;/li&gt;
&lt;li&gt;The ability to approve an allowance for a third party to spend tokens on behalf of the owner&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The ERC-20 standard is widely used, and most Ethereum wallets and exchanges support ERC-20 tokens. This makes it easy to create and trade ERC-20 tokens.&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;Some of the benefits of using ERC-20 tokens include:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Interoperability: ERC-20 tokens can be used with any wallet or exchange that supports the standard. This makes it easy to move tokens between different platforms.&lt;/li&gt;
&lt;li&gt;Liquidity: ERC-20 tokens are widely traded, which makes it easy to buy and sell them.&lt;/li&gt;
&lt;li&gt;Flexibility: ERC-20 tokens can be used for a variety of purposes, such as representing assets, voting rights, or access to services.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Some of the most popular ERC-20 tokens include:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tether (USDT)&lt;/li&gt;
&lt;li&gt;USD Coin (USDC)&lt;/li&gt;
&lt;li&gt;Binance USD (BUSD)&lt;/li&gt;
&lt;li&gt;Dai (DAI)&lt;/li&gt;
&lt;li&gt;Chainlink (LINK)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ERC-20 is a valuable standard for creating and using tokens on the Ethereum blockchain. It provides a set of rules that ensure that tokens are interoperable and fungible. This makes it easy to create and trade tokens, and it helps to ensure that tokens are widely accepted.&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;Essential function&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1882&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SV2zU/btsyTGAs6HH/ph7fUQNIGtXHC2972f8KBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SV2zU/btsyTGAs6HH/ph7fUQNIGtXHC2972f8KBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SV2zU/btsyTGAs6HH/ph7fUQNIGtXHC2972f8KBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSV2zU%2FbtsyTGAs6HH%2Fph7fUQNIGtXHC2972f8KBK%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;1882&quot; height=&quot;456&quot; data-origin-width=&quot;1882&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Essential event&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsc94n/btsyPY3zk7Z/OOB8kTGnV6kA9ZcbfJ5dTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsc94n/btsyPY3zk7Z/OOB8kTGnV6kA9ZcbfJ5dTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsc94n/btsyPY3zk7Z/OOB8kTGnV6kA9ZcbfJ5dTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbsc94n%2FbtsyPY3zk7Z%2FOOB8kTGnV6kA9ZcbfJ5dTK%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;1382&quot; height=&quot;104&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Blockchain/Ethereum</category>
      <category>ERC-20</category>
      <category>Ethereum</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/333</guid>
      <comments>https://reasonjun.tistory.com/333#entry333comment</comments>
      <pubDate>Fri, 20 Oct 2023 23:11:25 +0900</pubDate>
    </item>
    <item>
      <title>Solidity : sol2uml</title>
      <link>https://reasonjun.tistory.com/332</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Sol2uml is a tool that can be used to generate UML (Unified Modeling Language) diagrams from Solidity smart contracts. UML is a standard language for modeling software systems. By generating UML diagrams from Solidity smart contracts, developers can better understand the structure and design of their contracts.&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;Sol2uml works by parsing the Solidity code and extracting information about the classes, interfaces, and relationships between them. This information is then used to generate UML class diagrams and storage layout diagrams.&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 benefits of using sol2uml include:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Improved understanding of smart contract design: By generating UML diagrams from Solidity smart contracts, developers can better understand the structure and design of their contracts. This can help to identify potential problems with the design and make changes to improve the design.&lt;/li&gt;
&lt;li&gt;Increased communication with stakeholders: UML diagrams are a standard way of communicating software design. By generating UML diagrams from Solidity smart contracts, developers can more easily communicate the design of their contracts to stakeholders who are not familiar with Solidity.&lt;/li&gt;
&lt;li&gt;Improved documentation: UML diagrams can be used to document the design of Solidity smart contracts. This can help to ensure that the design of the contracts is well-understood and that the contracts are maintainable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Overall, sol2uml is a valuable tool that can be used to improve the design, communication, and documentation of Solidity smart contracts.&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;Here are some of the features of sol2uml:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Generates UML class diagrams and storage layout diagrams from Solidity smart contracts&lt;/li&gt;
&lt;li&gt;Supports the latest Solidity syntax&lt;/li&gt;
&lt;li&gt;Can be used to generate diagrams for individual contracts or entire projects&lt;/li&gt;
&lt;li&gt;Can be used to generate diagrams for both deployed and undeployed contracts&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;If you are developing Solidity smart contracts, then I encourage you to use sol2uml to improve the design, communication, and documentation of your contracts.&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;1248&quot; data-origin-height=&quot;662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbI9f8/btsyTufCnvr/D94nGHYiGuwwqZDpyFgRe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbI9f8/btsyTufCnvr/D94nGHYiGuwwqZDpyFgRe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbI9f8/btsyTufCnvr/D94nGHYiGuwwqZDpyFgRe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbI9f8%2FbtsyTufCnvr%2FD94nGHYiGuwwqZDpyFgRe0%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;1248&quot; height=&quot;662&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;662&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Blockchain/Solidity</category>
      <category>hardhat</category>
      <category>sol2uml</category>
      <category>solidity</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/332</guid>
      <comments>https://reasonjun.tistory.com/332#entry332comment</comments>
      <pubDate>Fri, 20 Oct 2023 17:38:10 +0900</pubDate>
    </item>
    <item>
      <title>Hardhat : hardhat-gas-reporter</title>
      <link>https://reasonjun.tistory.com/331</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Hardhat-gas-reporter is a plugin for the Hardhat testing framework that can be used to measure the gas usage of Solidity smart contracts. Gas is a unit of measurement for the computational effort required to execute specific operations on the Ethereum blockchain. By measuring the gas usage of a smart contract, developers can identify areas of the code that are consuming a lot of gas and make changes to optimize the code.&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;Hardhat-gas-reporter works by instrumenting the Solidity code with gas probes. These probes are inserted into the code at strategic points, and they are used to track the gas usage of each line of code. The gas data is then collected and used to generate a report that shows the gas usage for each function in the 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;The benefits of using hardhat-gas-reporter include:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Improved code optimization: By identifying areas of the code that are consuming a lot of gas, hardhat-gas-reporter can help developers to optimize the code and reduce the gas costs.&lt;/li&gt;
&lt;li&gt;Reduced deployment costs: By optimizing the code, developers can reduce the amount of gas that is required to deploy the contract. This can lead to significant savings in deployment costs.&lt;/li&gt;
&lt;li&gt;Increased understanding of gas usage: By providing information about the gas usage of each line of code, hardhat-gas-reporter can help developers to better understand how gas is used in Solidity smart contracts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Overall, hardhat-gas-reporter is a valuable tool that can be used to improve the efficiency of Solidity smart contracts.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Here are some of the features of hardhat-gas-reporter:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Supports multiple testing frameworks, such as Mocha and Hardhat&lt;/li&gt;
&lt;li&gt;Generates gas reports for both unit tests and integration tests&lt;/li&gt;
&lt;li&gt;Can be used to measure the gas usage of individual functions or entire contracts&lt;/li&gt;
&lt;li&gt;Provides detailed information about the gas usage of each line of code&lt;/li&gt;
&lt;li&gt;Can be used to identify areas of the code that are consuming a lot of gas&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;If you are developing Solidity smart contracts, then I encourage you to use hardhat-gas-reporter to improve the efficiency of your code.&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;1836&quot; data-origin-height=&quot;622&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cI6xMr/btsyU4HdMFO/c340y4atUpgtY8Z3fQiZH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cI6xMr/btsyU4HdMFO/c340y4atUpgtY8Z3fQiZH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cI6xMr/btsyU4HdMFO/c340y4atUpgtY8Z3fQiZH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcI6xMr%2FbtsyU4HdMFO%2Fc340y4atUpgtY8Z3fQiZH0%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;1836&quot; height=&quot;622&quot; data-origin-width=&quot;1836&quot; data-origin-height=&quot;622&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Blockchain/HardHat</category>
      <category>hardhat</category>
      <category>hardhat-gas-reporter</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/331</guid>
      <comments>https://reasonjun.tistory.com/331#entry331comment</comments>
      <pubDate>Fri, 20 Oct 2023 17:28:52 +0900</pubDate>
    </item>
    <item>
      <title>Hardhat : Solidity-coverage</title>
      <link>https://reasonjun.tistory.com/330</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Solidity-coverage is a tool that can be used to measure the code coverage of Solidity smart contracts. Code coverage is a measure of how much of the code in a program has been executed. This can be used to identify areas of the code that are not being tested, and to improve the quality of the test suite.&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-coverage works by instrumenting the Solidity code with coverage probes. These probes are inserted into the code at strategic points, and they are used to track which lines of code have been executed. The coverage data is then collected and used to generate a report that shows the code coverage for the 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;Solidity-coverage can be used with a variety of testing frameworks, such as Mocha and Hardhat. It can also be used to generate coverage reports for both unit tests and integration tests.&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 benefits of using solidity-coverage include:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Improved test quality: By identifying areas of the code that are not being tested, solidity-coverage can help to improve the quality of the test suite.&lt;/li&gt;
&lt;li&gt;Reduced debugging time: By providing information about which lines of code have been executed, solidity-coverage can help to reduce the time it takes to debug failing tests.&lt;/li&gt;
&lt;li&gt;Increased confidence in the codebase: By showing how much of the code has been tested, solidity-coverage can help to increase confidence in the codebase.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Overall, solidity-coverage is a valuable tool that can be used to improve the quality of Solidity smart contracts.&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;Here are some of the features of solidity-coverage:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Supports multiple testing frameworks, such as Mocha and Hardhat&lt;/li&gt;
&lt;li&gt;Generates coverage reports for both unit tests and integration tests&lt;/li&gt;
&lt;li&gt;Can be used to measure the coverage of individual contracts or entire projects&lt;/li&gt;
&lt;li&gt;Provides detailed information about which lines of code have been executed&lt;/li&gt;
&lt;li&gt;Can be used to identify areas of the code that are not being tested&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;If you are developing Solidity smart contracts, then I encourage you to use solidity-coverage to improve the quality of your code.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;npm install --save-dev solidity-coverage

npx hardhat coverage
&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;When the test code does not cover all smart contracts.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1458&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9ZVMG/btsyTfJHOjA/fDQ3wdsId9KoyA93TUAF6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9ZVMG/btsyTfJHOjA/fDQ3wdsId9KoyA93TUAF6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9ZVMG/btsyTfJHOjA/fDQ3wdsId9KoyA93TUAF6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9ZVMG%2FbtsyTfJHOjA%2FfDQ3wdsId9KoyA93TUAF6K%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;1458&quot; height=&quot;346&quot; data-origin-width=&quot;1458&quot; data-origin-height=&quot;346&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;When the test code does cover all smart contracts.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ldy7J/btsyTyhOIUX/ownKY5RgnxFjEn0kHzwEp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ldy7J/btsyTyhOIUX/ownKY5RgnxFjEn0kHzwEp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ldy7J/btsyTyhOIUX/ownKY5RgnxFjEn0kHzwEp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fldy7J%2FbtsyTyhOIUX%2FownKY5RgnxFjEn0kHzwEp0%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;1460&quot; height=&quot;350&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Blockchain/HardHat</category>
      <category>coverage</category>
      <category>hardhat</category>
      <category>solidity</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/330</guid>
      <comments>https://reasonjun.tistory.com/330#entry330comment</comments>
      <pubDate>Fri, 20 Oct 2023 17:05:24 +0900</pubDate>
    </item>
    <item>
      <title>Hardhat : Event filtering (attach, getLogs, topic, Interface, getTransactionReceipt, parseLog)</title>
      <link>https://reasonjun.tistory.com/329</link>
      <description>&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import { ethers } from &quot;hardhat&quot;;
const contractAddress = &quot;0x5FbDB2315678afecb367f032d93F642f64180aa3&quot;;

async function purchase(amount: number) {
  const VendingMachine = await ethers.getContractFactory(&quot;VendingMachine&quot;);
  const vendingMachine = await VendingMachine.attach(contractAddress);
  const topic = [vendingMachine.filters.Purchase().topics!].toString();
  const filter = {
    address: contractAddress.toString(),
    fromBlock: 0,
    toBlock: 10000000,
    topics: [topic]    
  };
  const logs = await ethers.provider.getLogs(filter);
  //특정 이벤트만 필터링 하기 위한 로그 값
   //console.log(&quot;logs &amp;gt;&amp;gt;&amp;gt;&quot;, logs)
  let abi = require(&quot;../artifacts/contracts/VendigMachine.sol/VendingMachine.json&quot;).abi;
  let iface = new ethers.utils.Interface(abi);
  //로그를 분석하기 위해서 abi를 가져옴
  logs.forEach(async(logs) =&amp;gt; {
    //실제로 이벤트 로그 내용을 분석하기 위해서는 각각의 트랜잭션 receipt를 가져와서 처리해야 한다.
    const receipt = await ethers.provider.getTransactionReceipt(logs.transactionHash);
    //console.log(&quot;receipt &amp;gt;&amp;gt;&amp;gt;&quot;, receipt);
    //반복문을 통해서 각로그들의 내용 출력 진행
    receipt.logs.forEach((log) =&amp;gt; {
      // console.log(&quot;iface.parseLog(log) &amp;gt;&amp;gt;&quot;, iface.parseLog(log));
      console.log(&quot;purchaser &amp;gt;&amp;gt;&quot;,iface.parseLog(log).args[0]);
      console.log(&quot;amount &amp;gt;&amp;gt;&quot;,iface.parseLog(log).args[1]);
    });
  })
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
purchase(10).catch((error) =&amp;gt; {
  console.error(error);
  process.exitCode = 1;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Here is a breakdown of the script:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;import { ethers } from &quot;hardhat&quot;;&amp;nbsp;imports the&amp;nbsp;ethers&amp;nbsp;library.&lt;/li&gt;
&lt;li&gt;const contractAddress = &quot;0x5FbDB2315678afecb367f032d93F642f64180aa3&quot;;&amp;nbsp;defines the address of the VendingMachine contract.&lt;/li&gt;
&lt;li&gt;async function purchase(amount: number) {&amp;nbsp;defines the&amp;nbsp;purchase()&amp;nbsp;function.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;const VendingMachine = await ethers.getContractFactory(&quot;VendingMachine&quot;);&amp;nbsp;creates a contract factory for the VendingMachine contract.&lt;/li&gt;
&lt;li&gt;const vendingMachine = await VendingMachine.attach(contractAddress);&amp;nbsp;attaches the contract factory to the VendingMachine contract at the specified address.&lt;/li&gt;
&lt;li&gt;const topic = [vendingMachine.filters.Purchase().topics!].toString();&amp;nbsp;defines the topic for the&amp;nbsp;Purchase&amp;nbsp;event.&lt;/li&gt;
&lt;li&gt;const filter = {&amp;nbsp;defines the filter for the&amp;nbsp;getLogs()&amp;nbsp;method.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;address: contractAddress.toString()&amp;nbsp;specifies the address of the VendingMachine contract.&lt;/li&gt;
&lt;li&gt;fromBlock: 0&amp;nbsp;specifies that the logs should be returned from the genesis block.&lt;/li&gt;
&lt;li&gt;toBlock: 10000000&amp;nbsp;specifies that the logs should be returned up to block 10000000.&lt;/li&gt;
&lt;li&gt;topics: [topic]&amp;nbsp;specifies the topic for the&amp;nbsp;Purchase&amp;nbsp;event.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;const logs = await ethers.provider.getLogs(filter);&amp;nbsp;gets the logs for the VendingMachine contract.&lt;/li&gt;
&lt;li&gt;let abi = require(&quot;../artifacts/contracts/VendigMachine.sol/VendingMachine.json&quot;).abi;&amp;nbsp;imports the ABI for the VendingMachine contract.&lt;/li&gt;
&lt;li&gt;let iface = new ethers.utils.Interface(abi);&amp;nbsp;creates an interface object for the VendingMachine contract.&lt;/li&gt;
&lt;li&gt;logs.forEach(async(logs) =&amp;gt; {&amp;nbsp;iterates over the logs.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;const receipt = await ethers.provider.getTransactionReceipt(logs.transactionHash);&amp;nbsp;gets the transaction receipt for the log.&lt;/li&gt;
&lt;li&gt;receipt.logs.forEach((log) =&amp;gt; {&amp;nbsp;iterates over the logs in the transaction receipt.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;console.log(&quot;purchaser &amp;gt;&amp;gt;&quot;,iface.parseLog(log).args[0]);&amp;nbsp;prints the&amp;nbsp;purchaser&amp;nbsp;value of the log.&lt;/li&gt;
&lt;li&gt;console.log(&quot;amount &amp;gt;&amp;gt;&quot;,iface.parseLog(log).args[1]);&amp;nbsp;prints the&amp;nbsp;amount&amp;nbsp;value of the log.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;});&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;});&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;purchase(10).catch((error) =&amp;gt; {&amp;nbsp;calls the&amp;nbsp;purchase()&amp;nbsp;function with an argument of 10.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;console.error(error);&amp;nbsp;prints the error to the console.&lt;/li&gt;
&lt;li&gt;process.exitCode = 1;&amp;nbsp;sets the exit code of the process to 1.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;});&amp;nbsp;ends the&amp;nbsp;purchase()&amp;nbsp;function.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This script can be used to analyze the logs of any contract that emits the Purchase event. By parsing the logs, you can get information about who purchased cupcakes, how many cupcakes were purchased, and when the purchase was made.&lt;/p&gt;</description>
      <category>Blockchain/HardHat</category>
      <category>Attach</category>
      <category>getLogs</category>
      <category>getTransactionReceipt</category>
      <category>hardhat</category>
      <category>Interface</category>
      <category>parseLog</category>
      <category>Topic</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/329</guid>
      <comments>https://reasonjun.tistory.com/329#entry329comment</comments>
      <pubDate>Fri, 20 Oct 2023 17:00:03 +0900</pubDate>
    </item>
    <item>
      <title>Hardhat : .to.emit().withArgs();</title>
      <link>https://reasonjun.tistory.com/328</link>
      <description>&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
import { expect } from 'chai';
import { ethers } from 'hardhat';

describe('VendingMachine', function () {
  // We define a fixture to reuse the same setup in every test.
  // We use loadFixture to run this setup once, snapshot that state,
  // and reset Hardhat Network to that snapshot in every test.
  async function VendingMachineFixture() {
    // Contracts are deployed using the first signer/account by default
    const [owner, otherAccount] = await ethers.getSigners();

    const VendingMachine = await ethers.getContractFactory('VendingMachine');
    const vendingMachine = await VendingMachine.deploy();

    return { vendingMachine, owner, otherAccount };
  }

  describe('VendingMachine', function () {
  

    it('should send cupcakes correctly after purchase', async function () {
      const { vendingMachine, owner, otherAccount } = await loadFixture(
        VendingMachineFixture
      );
      console.log(
        'vendingMachine cupcakeBalances',
        await vendingMachine.cupcakeBalances(vendingMachine.address)
      );
      const accountTwoStartingBalance = (
        await vendingMachine.cupcakeBalances(otherAccount.address)
      ).toNumber();

      console.log('accountTwoStartingBalance &amp;gt;&amp;gt;', accountTwoStartingBalance);
      const amount = 10;
      await expect(
        vendingMachine
          .connect(otherAccount)
          .purchase(amount, { value: (amount * 10 ** 18).toString() })
      )
        .to.emit(vendingMachine, 'Purchase')
        .withArgs(otherAccount.address, amount);

      const accountTwoEndingBalance = (
        await vendingMachine.cupcakeBalances(otherAccount.address)
      ).toNumber();
      console.log('accountTwoEndingBalance &amp;gt;&amp;gt;', accountTwoEndingBalance);
      console.log(
        'vendingMachine cupcakeBalances',
        await vendingMachine.cupcakeBalances(vendingMachine.address)
      );
      expect(accountTwoEndingBalance).to.equal(
        accountTwoStartingBalance + amount
      );
    });

   
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;.to.emit(vendingMachine, 'Purchase')
    .withArgs(otherAccount.address, amount);
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;.to.emit(vendingMachine, 'Purchase')&lt;/b&gt;: This is a Chai assertion statement. It checks that a specific event, in this case, the 'Purchase' event, is emitted when a certain action is performed on the &lt;b&gt;vendingMachine&lt;/b&gt; contract. The &lt;b&gt;.to.emit()&lt;/b&gt; syntax is used to make this assertion.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;.withArgs(otherAccount.address, amount)&lt;/b&gt;: This is an additional part of the assertion. It specifies that the 'Purchase' event should have specific arguments when it is emitted. In this case, it checks that the event should have two arguments: &lt;b&gt;otherAccount.address&lt;/b&gt; and &lt;b&gt;amount&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In your test case, you are verifying that when the &lt;b&gt;purchase&lt;/b&gt; function is called on the &lt;b&gt;vendingMachine&lt;/b&gt; contract, it should emit a 'Purchase' event with the expected arguments - the address of &lt;b&gt;otherAccount&lt;/b&gt; and the specified &lt;b&gt;amount&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>Blockchain/HardHat</category>
      <category>.to.emit</category>
      <category>.withArgs</category>
      <category>Chai</category>
      <category>hardhat</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/328</guid>
      <comments>https://reasonjun.tistory.com/328#entry328comment</comments>
      <pubDate>Fri, 20 Oct 2023 15:53:40 +0900</pubDate>
    </item>
    <item>
      <title>Hardhat : loadFixture(), it(), expect()</title>
      <link>https://reasonjun.tistory.com/327</link>
      <description>&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
import { expect } from 'chai';
import { ethers } from 'hardhat';

describe('VendingMachine', function () {
  // We define a fixture to reuse the same setup in every test.
  // We use loadFixture to run this setup once, snapshot that state,
  // and reset Hardhat Network to that snapshot in every test.
  async function VendingMachineFixture() {
    // Contracts are deployed using the first signer/account by default
    const [owner, otherAccount] = await ethers.getSigners();

    const VendingMachine = await ethers.getContractFactory('VendingMachine');
    const vendingMachine = await VendingMachine.deploy();

    return { vendingMachine, owner, otherAccount };
  }

  describe('VendingMachine', function () {
    it('should make 100 cupcake at constructor', async function () {
      const { vendingMachine } = await loadFixture(VendingMachineFixture);
      expect(
        (
          await vendingMachine.cupcakeBalances(vendingMachine.address)
        ).toNumber()
      ).to.equal(100);
    });

  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The &lt;u&gt;&lt;b&gt;loadFixture()&lt;/b&gt;&lt;/u&gt; function is used to load the state that was setup by the VendingMachineFixture() 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;The&lt;u&gt;&lt;b&gt; it()&lt;/b&gt; &lt;/u&gt;function is used to define a test. In this case, the test is checking that the VendingMachine contract has a correct balance of 100 cupcakes.&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 &lt;u&gt;&lt;b&gt;expect()&lt;/b&gt;&lt;/u&gt; function is used to make assertions about the state of the test. In this case, the expect() function is asserting that the balance of the VendingMachine contract is equal to 100.&lt;/p&gt;</description>
      <category>Blockchain/HardHat</category>
      <category>expect</category>
      <category>hardhat</category>
      <category>It</category>
      <category>loadFixture</category>
      <author>ReasonJun</author>
      <guid isPermaLink="true">https://reasonjun.tistory.com/327</guid>
      <comments>https://reasonjun.tistory.com/327#entry327comment</comments>
      <pubDate>Fri, 20 Oct 2023 15:37:33 +0900</pubDate>
    </item>
  </channel>
</rss>