푸티안 센트럴 키친도 폐쇄되었고, 싱가포르에서 식중독에 걸린 바이트댄스 직원의 수는 130명으로 늘어났습니다.
싱가포르의 바이트댄스에서는 식중독 사고가 발생해 직원 130명이 입원했고, 푸티안의 중앙 주방과 나푸청의 윤난스는 운영 중단 명령을 받았습니다.
![image ZeZheng](https://image.coinlive.com/24x24/cryptotwits-static/114175ee33b9405fa7b20683ba586a74.png)
출처: 그리피스 아카데미
이 연구 논문은 유니스왑V2 프로토콜의 작동 방식, 구성 요소, 소스 코드 분석 방법 등을 자세히 설명합니다. 프로젝트 구성 섹션에서는 유동성 풀을 생성하고 관리하는 과정과 유동성 제공을 통해 수수료를 얻는 방법에 대해 설명하고, 주요 계약(예: 팩토리 계약, 거래소 계약)과 그 기능을 포함한 UniswapV2의 아키텍처에 대한 개요를 제공하며, 소스 분석 섹션에서는 UniswapV2의 스마트 계약의 소스 코드를 분석하여 주요 기능을 설명하고 주요 기능에 대해 설명합니다. 컨트랙트 소스 코드를 분석하여 주요 기능 및 데이터 구조의 설계 개념을 설명합니다.
유니스왑V2는 이더 블록체인 기반의 탈중앙화 거래소 프로토콜로, 사용자가 중개자를 신뢰하지 않고도 암호화폐를 거래할 수 있습니다. 기존의 중앙화된 거래소와 달리 유니스왑V2는 스마트 컨트랙트를 통해 거래와 유동성 풀을 관리하는 자동화된 시장 조성자(AMM) 모델을 사용하여 완전히 탈중앙화되어 있습니다.
유니스왑V2의 핵심은 상수 곱 공식(x * y = k)으로, 여기서 x 와 y 는 유동성 풀의 두 가지 자산 수량을 나타내고 k 는 상수입니다. 이 공식은 각 거래 후 풀에 있는 자산의 비율을 재조정하여 사용자에게 유동성을 제공합니다. 이러한 설계는 거래 프로세스를 투명하고 공정하게 만들어 사용자가 언제든지 유동성을 추가하거나 제거하고 거래 수수료를 통해 수익을 얻을 수 있도록 합니다.
유니스왑V2 프로토콜은 여러 스마트 콘트랙트로 구성되며, 특히 팩토리 콘트랙트와 거래소 콘트랙트가 대표적입니다. 팩토리 컨트랙트는 유동성 풀을 생성하고 관리하는 역할을 담당하며, 각 거래소 컨트랙트는 특정 거래 쌍(예: ETH/DAI)에 해당합니다.
또한, 유니스왑V2는 라우터 컨트랙트와 라이브러리 기능을 도입하여 거래 효율성과 보안을 개선합니다. 유니스왑V2는 이전 버전인 유니스왑V1에 비해 몇 가지 중요한 개선점을 제공합니다. 첫 번째는 라이트닝 스왑 기능으로, 사용자가 한 번의 트랜잭션으로 자산을 빌린 후 거래가 끝나기 전에 간단히 반환할 수 있습니다. 두 번째는 가격 예측 기능으로, 가격의 시간 가중 평균(TWAP)을 누적하여 보다 신뢰할 수 있는 가격 데이터를 제공합니다.
또한, 유니스왑V2는 이더리움이 중개자 역할을 할 필요 없이 모든 ERC-20 토큰의 직접 거래를 지원합니다.유니스왑V2의 성공은 기술 혁신뿐만 아니라 개방성과 커뮤니티 중심 개발 모델에 있습니다. 누구나 자유롭게 유니스왑 프로토콜을 사용하고 확장할 수 있으며, 이는 탈중앙화 금융(DeFi) 생태계에 무한한 가능성을 열어줍니다. 대출 플랫폼과 스테이블코인 프로토콜 등 다양한 탈중앙 금융 프로젝트가 유니스왑 위에 구축되어 번성하는 생태계를 만들어가고 있습니다.
전반적으로 유니스왑V2는 혁신적인 프로토콜 설계와 탈중앙화된 운영 모델을 통해 암호화폐 거래 방식에 혁신을 가져왔으며, 탈중앙화 금융 공간의 핵심 초석이 되고 있습니다. 기술이 계속 발전하고 커뮤니티가 계속 혁신함에 따라 유니스왑V2의 영향력은 더욱 확대되어 전 세계 사용자에게 더 많은 금융 자유와 기회를 제공할 것입니다.
유니스왑v1은 이더(ETH)를 전환 통화로 사용합니다. 즉, 사용자가 토큰A를 토큰B로 교환하려면 먼저 토큰A를 이더로 교환한 다음 나중에 토큰B로 교환해야 합니다. 토큰B. 이러한 조치는 유동성 파편화를 줄이지만 유동성 공급자에게 상당한 비용 부담을 줍니다. 각 유동성 공급자는 이더와 교환할 수 있는 인터페이스를 갖춰야 하며, 유동성 공급자가 보유한 자산의 가치는 이더의 가격 변동에 따라 변동하므로 심각한 손실을 초래할 수 있습니다.
두 자산인 ABC와 XYZ가 상관관계가 있는 경우(예: 둘 다 USD 스테이블코인인 경우), 유니스왑의 유동성 공급자는 일반적으로 ABC/ETH 또는 XYZ/ETH 쌍에 비해 ABC/XYZ 쌍에서 영구 손실이 더 작을 수 있습니다. 또한 ETH를 필수 전환 통화로 사용하면 트레이더의 비용이 증가합니다. 트레이더는 ABC/XYZ 쌍을 직접 매수할 때보다 두 배의 비용을 지불하고 두 개의 슬리피지 포인트를 잃게 됩니다.
유동성 공급자는 유니스왑V2에서 두 개의 ERC-20 토큰에 대한 페어 계약을 생성할 수 있습니다. ERC-20 토큰 간의 거래 쌍이 확산되면 특정 자산 거래 경로를 찾는 것이 복잡해질 수 있지만, 이 문제는 오프체인 또는 온체인 라우터 또는 애그리게이터를 통해 상위 레벨 라우팅으로 해결할 수 있습니다.
유니스왑V1의 가격은 시간 t에서 유니스왑이 제공하는 한계 가격(수수료 제외)을 다음과 같이 계산할 수 있도록 계산됩니다. 자산 A의 준비금을 자산 B의 준비금으로 나눕니다. 정확한 공식은 다음과 같습니다:
그러나 유니스왑V1은 조작이 매우 쉽기 때문에 온체인 가격 예측 머신으로 사용하기에는 안전하지 않습니다. 조작자는 블록 시작 시점에 특정 자산 A를 대량으로 매도하여 가격에 영향을 준 다음, 변동하는 가격에 따라 블록 중간에 다른 계약 행위(비유니스왑 페어 계약)를 수행하고, 블록 종료 시점에 같은 양의 자산 A를 다시 매수하여 가격을 정상 수준으로 되돌리는데, 유니스왑 V2는 제3자가 특정 구간 평균 가격을 사용할 수 있는 가격 누적 메커니즘을 도입하여 가격 조작의 위험을 크게 증가시켰습니다. 이는 가격 조작의 난이도를 크게 높이고 조작을 불가능하게 만듭니다.
특히, 유니스왑 v2는 계약과 사람의 상호작용을 통해 각 블록이 시작될 때 누적된 가격 합계를 기록하여 가격을 누적합니다. 각 가격은 블록 타임스탬프를 기준으로 마지막 블록 업데이트 이후 경과한 시간에 따라 가중치가 부여됩니다. 즉, 특정 시점(업데이트 이후)에 어큐뮬레이터 값은 계약 기록의 매초마다 현물 가격의 합이 되어야 합니다.
시간 t₁부터 t₂까지의 시간 가중 평균 가격을 추정하려면 외부 호출자는 t₁에서 누산기 값을 확인한 다음 다시 t₂에서 첫 번째 값을 뺀 다음 를 경과한 시간(초)으로 나눕니다. (컨트랙트 자체는 이 누산기의 과거 값을 저장하지 않으며, 호출자는 이 값을 읽고 저장하기 위해 사이클이 시작될 때 컨트랙트를 호출해야 합니다.)
이미지 src="https://img.jinse.cn/7249538_image3.png">
예측자 사용자는 주기의 시작과 종료 시점을 선택할 수 있습니다. 기간을 길게 선택하면 공격자가 시간 가중 평균 가격(TWAP)을 조작하는 데 더 많은 비용이 들지만, 최신 가격이 덜 나오게 됩니다. 평균화 결과, 일정 기간 동안의 A/B와 B/A의 평균은 더 이상 반비례 관계가 아니므로 Uniswap V2는 두 가격을 모두 제공합니다.
솔리디티는 정수가 아닌 숫자 데이터 유형을 지원하지 않기 때문에, 유니스왑V2는 가격 계산의 정확도를 높이기 위해 UQ112.112 데이터 형식과 한 쌍의 자산 수를 저장하는 uint112, 현재 블록의 생성 시간을 기록하는 32비트를 사용하며, 가격 계산 정확도를 향상시킵니다. 이러한 방식으로 시간을 기록하면 100년 후, 즉 2106년 2월 7일에 유닉스 타임스탬프 오버플로가 발생하게 되는데, 이는 유닉스 타임스탬프가 단일 비트를 기반으로 하기 때문입니다. 유닉스 타임스탬프는 1970년 1월 1일(유닉스 시대) 이후 경과한 시간을 초 단위로 나타내며, uint32가 나타낼 수 있는 범위는 0에서 2^{32} - 1초(약 136년)까지이기 때문입니다.
2106년 2월 7일 이후에도 시스템이 계속 작동하도록 보장하기 위해 UniswapV2는 오버플로 주기(약 136년)마다 최소 한 번씩 예후 예측자가 가격을 확인하도록 설계되었습니다. 이러한 설계에서는 타임스탬프가 오버플로되더라도 가격을 누적하는 방식이 오버플로에 안전하며, 거래가 오버플로 주기에 걸쳐 있더라도 가격 변동이 정확하게 계산될 수 있기 때문입니다. 이러한 방식으로 시스템은 오랜 기간 동안 정확성과 신뢰성을 유지할 수 있습니다.
라이트닝 거래소는 블록체인 플랫폼에서 사용자가 여러 블록 확인을 기다릴 필요 없이 서로 다른 암호화폐 간의 거래를 빠르게 완료할 수 있는 일종의 인스턴트 암호화폐 거래소입니다. 이러한 거래는 일반적으로 거래 양 당사자가 동시에 교환 약속을 이행하도록 보장하는 스마트 컨트랙트에 의해 자동으로 실행되므로 거래 위험을 줄이고 효율성을 높일 수 있습니다. 간단히 말해, 플래시 거래는 상환하기 전에 빚을 지는 거래이며, 플래시 거래소를 통해 제로 코스트 차익거래를 달성할 수 있습니다.
실제적인 예를 통해 플래시 거래소를 설명해 보겠습니다. 유니스왑V2에 A/B 쌍이 있다고 가정하면, 유니스왑에서 A를 빌려 B를 얻은 다음 B를 사용해 다른 탈중앙화 거래소에서 A0를 얻은 다음 같은 양의 A를 유니스왑에 반환할 수 있습니다. 이 과정을 통해 우리는 0의 비용으로 A0-A 스프레드를 차익거래할 수 있습니다. 자본이 필요하지 않고 가스 수수료만 지불하면 됩니다. 체인에서 다른 덱스 간의 스프레드를 발견하면 동일한 방법으로 제로 비용으로 차익거래를 할 수 있습니다.
유니스왑V2는 켜고 끌 수 있는 0.05%의 프로토콜 수수료를 도입했습니다. 켜면 이 수수료는 공장 계약에 명시된 feeTo 주소로 전송됩니다. 처음에 feeTo는 설정되지 않으므로 수수료가 부과되지 않습니다. 미리 지정된 주소인 feeToSetter는 UniswapV2 팩토리 컨트랙트에서 setFeeTo 함수를 호출하여 feeTo를 다른 값으로 설정할 수 있습니다. 또한 feeToSetter는 setFeeToSetter를 호출하여 수수료 주소 자체를 변경할 수도 있습니다.
feeTo 주소가 설정되면 프로토콜은 유동성 공급자가 벌어들인 30 베이시스 포인트의 \frac{1}{6}인 5 베이시스 포인트의 수수료를 부과하기 시작합니다. 즉, 트레이더는 전체 거래 수수료의 0.30%를 계속 지불하게 되며, 이 중 83.3%(즉, 0.25%)는 유동성 공급자에게, 16.6%(즉, 0.05%)는 수수료 주소에 지불하게 됩니다. 각 거래에 0.05%의 수수료를 부과하면 가스 비용이 추가됩니다. 이를 방지하기 위해 누적 수수료는 유동성이 입금 또는 출금될 때만 부과됩니다. 콘트랙트는 누적 수수료를 계산하고 토큰이 발행되거나 소멸되기 직전에 수수료 수혜자에게 새로운 유동성 토큰을 발행합니다.
누적 수수료는 마지막 수수료가 부과된 이후 √k(즉, √(x-y) )의 증가를 측정하여 계산할 수 있습니다. 이 공식은 t₁와 t₂ 사이의 누적 수수료를 t₂ 시점의 유동성 풀에 있는 유동성의 백분율로 나타냅니다:
t₁ 이전에 수수료가 활성화된 경우, 수수료To 주소는 다음과 같아야 합니다. 활성화된 경우, 수수료 주소는 t₁ 과 t₂ 에서 ⅙까지 누적된 수수료를 캡처해야 합니다. 따라서 Φ-f₁,₂의 풀을 나타내는 수수료 주소에 새로운 유동성 토큰을 발행하고자 합니다(여기서 Φ=⅙).
즉, 다음 관계를 만족하도록 sₘ를 선택하고자 하며, 여기서 s₁는 t₁ 시점에 유통되는 총 주식 수입니다:
f₁,₂를 1-로 바꾸고 sₘ를 푸는 등 몇 가지 연산을 거친 후 다음과 같이 다시 작성할 수 있습니다.
Φ를 ⅙로 설정하면 다음 방정식을 얻을 수 있습니다
자, 구체적인 예를 통해 설명해 보겠습니다. 최초 입금자가 100 다이와 1 이더를 한 쌍으로 입금하고 10 주식을 받았다고 가정해 봅시다. 일정 시간이 지난 후(해당 쌍에 다른 예금자가 없을 때) 자금을 인출하려고 하는데, 이때 해당 쌍에는 96 DAI와 1.5 ETH가 있습니다. 이 값을 위의 공식에 대입하면 다음과 같은 결과를 얻을 수 있습니다.
유니스왑V1 거래 수수료는 다음과 같은 공식으로 계산됩니다
이 공식은 일정한 상품을 실행하기 전에 먼저 지불 횟수를 줄이는 것임을 의미합니다. 공식; UniswapV2 릴리스에서는 플래시 스왑 메커니즘으로 인해 거래 수수료 공식이 다음과 같이 조정되었습니다.
sync()는 주로 불균형이 발생하고 유동성 공급자가 없는 상황에서 계약의 보유 자산 수를 실제 현재 가치로 업데이트하는 데 사용됩니다. skim()은 계약의 특정 자산 수가 최대값인 uint112를 초과할 때 사용되며, 사용자가 최대값인 uint112를 초과하는 자산 부분을 인출할 수 있도록 합니다.
표준 ERC20 토큰 컨트랙트는 토큰 전송 후 전송 성공 여부를 나타내는 부울 값을 반환해야 하지만, 모든 토큰이 이를 수행하는 것은 아닙니다. 일부 토큰은 값을 반환하지 않습니다. 유니스왑V1에서는 반환값이 없는 토큰 전송은 기본적으로 실패로 간주되며 전체 트랜잭션이 리셋됩니다. 유니스왑 V2에서는 반환값이 없는 토큰 전송은 성공한 것으로 간주됩니다.
또한 유니스왑V1은 토큰 전송이 쌍의 재진입을 트리거하지 않는다고 가정하지만, ERC777 후크를 지원하는 일부 ERC20 토큰은 이 가정을 깨뜨립니다. 이러한 토큰을 지원하기 위해 UniswapV2는 모든 공개 상태 변수 수정 기능에 재진입 방지 잠금을 추가하고, 플래시 스왑에서 사용자 정의 콜백의 재진입을 차단합니다.
사용자가 이미 존재하는 거래 쌍 A/B에 유동성을 공급하는 경우, A와 B의 현재 비율에 따라 A와 B를 얼마나 공급할지 계산할 수 있습니다. 그러나 쌍이 초기화되면 참조할 비율이 없으므로 어떻게 해야 할까요? 유니스왑V1 버전에서는 새로운 유동성 공급자가 기존 유니스왑 토큰 쌍에 토큰을 입금하면 기존 토큰 수를 기준으로 발행되는 유동성 토큰 수가 계산됩니다. 공식은 다음과 같습니다:
첫 번째 유동성 공급자의 경우, 공식은 0에서 Xstarting입니다. 이 경우, 발행되는 토큰 수는 기존 토큰 수를 기준으로 계산됩니다. 이 초기 유동성 제공의 문제점은 쌍의 가치가 초기 유동성 비율에 의해 결정되지만, 이 비율이 실제 가치라는 것을 보장하는 메커니즘이 없다는 것입니다. 유니스왑V2에서는 다음 공식을 사용하여 유동성을 초기화할 수 있습니다
이 공식은 주조된, 즉 지급될 유동성 토큰의 개수를 의미합니다. 수량, Xdeposited 첫 번째로 입금한 토큰의 수량입니다. 예를 들어 이더리움을 입금한 경우 Xdeposited는 입금한 이더리움의 양입니다. Ydeposited 두 번째로 입금한 토큰의 금액입니다.
예를 들어, DAI를 입금한 경우 Ydeposited은 입금한 DAI의 양입니다. 이 공식은 유동성 풀의 점유율이 풀의 기하평균 아래로 떨어지지 않도록 보장하지만, 풀의 토큰 수가 변경되면 이 공식의 값도 변경됩니다. 풀의 토큰 수 변경의 영향을 완화하기 위해 UniswapV2는 최소 유동성 1e- ¹⁵ 유동성 값인 초기 1e- ¹⁵ 유동성을 파괴합니다. 값은 최소 유동성 1e-¹⁸ 의 1000배입니다. 이는 모든 거래 쌍에 대해 사소한 것이지만, 공격자가 이 메커니즘을 통해 이익을 얻는 데 드는 비용을 크게 증가시킵니다.
이더의 기축 통화인 ETH를 거래하는 인터페이스는 ERC20 토큰을 거래하는 인터페이스와 다르기 때문에 많은 프로토콜이 ETH를 직접 지원하지 않고 대신 대체 수단인 WETH(패키지 ETH 토큰)를 사용합니다. UniswapV1은 이 규칙에서 예외이며, 거래 쌍에 직접 ETH를 포함하므로 사용자는 다음을 수행할 수 있습니다. 이더로 직접 거래할 수 있습니다. 그러나 유니스왑 V2는 모든 ERC20 토큰 간의 쌍을 지원하도록 설계되었으며, ETH를 직접 지원하면 시스템이 복잡해지고 위험이 증가합니다.
따라서 유니스왑V2에서 ETH는 직접 지원되지 않으며, 사용자는 쌍을 사용하기 전에 ETH를 WETH로 변환해야 합니다. 실제로 유니스왑V2는 내부적으로 사용자가 제공한 ETH를 WETH로 자동 변환하므로 사용자가 수동으로 변환할 필요가 없고 프로세스가 간소화됩니다. 이 변환은 모든 거래 쌍에 대해 사소한 일이지만 시스템의 보안과 단순성을 효과적으로 향상시킵니다.
유니스왑V1이든 유니스왑V2이든 모든 페어는 단일 팩토리 컨트랙트를 사용하여 생성됩니다. 유니스왑V1에서는 생성 옵코드가 사용되며, 페어 컨트랙트의 주소는 생성 순서에 따라 영향을 받습니다. 유니스왑V2에서는 새로운 옵코드 create2가 사용되며, 이 방법으로 생성된 주소는 결정론적입니다. 즉, 체인 상태를 쿼리할 필요 없이 오프체인에서 미리 쌍의 주소를 계산할 수 있습니다.
유니스왑 V2는 예언 머신 기능을 효율적으로 구현하기 위해 uint112를 사용하여 토큰 수를 보유하며, 이는 지원하는 최대 토큰 수가 2¹¹² - 1이라는 것을 의미합니다. 정밀도가 18인 토큰의 경우 이 값이면 충분하며 대략 5192296858534828 (5.19e¹⁵) 토큰, 즉 5조 1900조 개의 토큰이 됩니다. 컨트랙트에 기록된 값이 이 한도를 초과하면 트랜잭션이 실패하고 재설정됩니다. 앞서 언급했듯이 누구나 유동성 풀에서 초과 자산을 제거하여 문제를 해결하는 skim() 함수를 사용하여 이 문제를 복구할 수 있습니다.
유니스왑은 일정한 상품 공식으로 구동되는 자동화된 유동성 프로토콜로, 이더 블록체인의 확장 불가능한 스마트 콘트랙트 시스템에서 구현됩니다. 신뢰할 수 있는 중개자가 필요 없으며 탈중앙화, 검열 저항성, 보안을 우선시합니다. 각 유니스왑 스마트 콘트랙트 또는 통화 쌍은 두 개의 ERC-20 토큰 보유로 구성된 유동성 풀을 관리합니다. 누구나 풀 토큰과 교환하여 각 기본 토큰의 동등한 가치를 예치함으로써 풀의 유동성 공급자(LP)가 될 수 있습니다. 이 토큰은 전체 풀에서 LP가 차지하는 비율에 비례하여 추적되며 언제든지 기초 자산으로 상환할 수 있습니다.
먼저 유니스왑의 자동화된 시장 조성자(AMM) 메커니즘에 대한 소개부터 시작하겠습니다. 다음은 다음 공식에 기반한 유니스왑V2 자동화된 시장 조성자(AMM) 모델의 기능 이미지를 보여줍니다:
여기서 x 는 토큰 A의 수, y 는 토큰 B의 수, k 는 풀에 있는 두 토큰 수의 곱이 일정하게 유지된다는 것을 나타내는 상수입니다. 트레이더는 유니스왑에서 거래할 때 풀에 토큰을 추가하거나 제거하여 풀에 있는 토큰 수를 변경합니다. 상수 제품 공식에 따르면, 다른 토큰의 토큰 수는 그에 따라 변경되어 제품 k 를 일정하게 유지합니다. 이 변화에 따라 거래 가격이 결정됩니다.
예를 들어, 트레이더가 토큰 A를 토큰 B로 교환하려면 풀에 일정량의 토큰 A를 추가해야 하며, 이로 인해 풀에 있는 토큰 B의 양이 감소하여 가격이 변경됩니다. 트레이더의 행동은 이 곡선을 따라 움직이며 토큰의 수와 가격을 변화시킵니다. 곡선의 어느 지점에서든 상수 제품 관계가 만족됩니다.
이미지 src="https://img.jinse.cn/7249561_image3.png">
유니스왑V2의 작동은 크게 유동성 공급자, 유니스왑 풀, 유니스왑 풀의 세 부분으로 나눌 수 있습니다. 유니스왑 풀과 트레이더. 유동성 공급자의 역할은 유동성 공급자가 유니스왑 풀에 두 개의 토큰(예: 토큰 A와 토큰 B)을 예치하는 것입니다.
그림에 표시된 예시에서 유동성 공급자는 토큰 A 10개와 토큰 B 1개를 예치하고, 유니스왑 풀에는 토큰 A 100개와 토큰 B 10개가 있습니다.
풀의 유동성 비중은 유동성 토큰으로 표시되며, 그림과 같이 12개입니다; 트레이더트레이더는 풀에 토큰을 제출하고 필요한 다른 토큰으로 교환할 수 있습니다. 예를 들어 트레이더는 10 토큰 A를 예치하고 0.3% 수수료를 지불하면 풀에서 1 토큰 B를 받을 수 있습니다.
유동성 공급자(LP)가 어떻게 유동성을 제공하는지 먼저 살펴봅시다. 유동성을 제공합니다. 아래에서 볼 수 있듯이 LP는 토큰을 유니스왑 풀에 예치하여 유동성을 추가합니다.
예를 들어, 다이어그램에서 LP는 토큰 A 3개와 토큰 B 1개를 예치합니다. LP가 토큰을 예치하면 유동성이 증가합니다. 유동성 공급자는 토큰을 예치하면 자신의 유동성 지분을 나타내는 풀 토큰을 받습니다. 다이어그램에서 유동성 공급자는 12.4개의 풀 토큰을 받습니다. 예를 들어, 다이어그램에서 풀 토큰 풀은 1210 토큰 A와 399 토큰 B가 되며, 풀 토큰 풀의 풀 토큰도 증가합니다. 유동성이 증가하면 가격 변동이 줄어들고 거래가 더 안정적으로 이루어집니다.
유니스왑은 가격 곡선을 결정하기 위해 상수 제품 공식 x - y = k 를 사용합니다. 유동성이 추가되면 슬리피지가 낮은 영역이 확장되고 거래의 가격 안정성이 향상됩니다. 유동성 공급자는 토큰을 예치하여 풀의 유동성을 늘리고 그 대가로 그에 상응하는 유동성 토큰을 받습니다. 이는 트레이더가 보다 안정적인 가격을 달성하는 데 도움이 될 뿐만 아니라 유동성 공급자에게도 거래 수수료의 형태로 수익을 창출합니다.
이미지 src="https://img.jinse.cn/7249563_image3.png">
다음으로 트레이더가 토큰을 교환하는 방법과 거래 행위가 유니스왑 풀에 미치는 영향을 트레이더의 관점에서 살펴봅시다.
아래 그림에서 볼 수 있듯이 트레이더는 유니스왑에서 토큰을 교환하고자 합니다. 예를 들어, 그림에서 트레이더는 토큰 A 3개를 교환하려고 합니다. 트레이더는 토큰 A 3개를 입력하고 0.3%의 수수료를 지불합니다. 결국 트레이더는 약 0.997 토큰 B를 출력으로 받게 됩니다. 거래로 인해 풀의 준비금 잔액이 변경되어 새로운 가격이 형성됩니다. 거래 전에는 풀에 1200개의 토큰 A와 400개의 토큰 B가 있었습니다.
상수 곱 공식에 따르면 거래 후 풀에는 약 1203.009개의 토큰 A와 약 399.003개의 토큰 B가 존재하게 됩니다. 유니스왑은 가격 곡선을 정의하기 위해 x-y = k라는 상수 곱 공식을 사용합니다. 트레이더가 거래를 교환하면 풀에 있는 토큰 수가 변경되고 가격 곡선이 조정되어 새로운 가격이 결정됩니다.
<
이 섹션에서는 유동성 추가, 유동성 제거, 토큰 교환 등 유니스왑V2에서 가장 많이 사용되는 세 가지 작업에 대해 소개합니다. 그리고 이들이 호출하는 컨트랙트와 호출하는 함수를 순서도를 통해 분석하여 유니스왑V2 소스 코드에 대해 더 깊이 이해할 수 있도록 하겠습니다.
4.1.1 유동성 추가
사용자가 유동성을 추가할 때, 사용자는 먼저 토큰 A와 토큰 B의 양을 제공하기 위해 UniswapV2Router.sol 컨트랙트를 호출합니다. 추가 유동성 함수는 사용자의 요청을 받아 이를 처리합니다.
추가 유동성 추가 함수는 다시 UniswapV2Pair.sol 컨트랙트를 호출하고, 여기서 실제 유동성 추가 작업을 수행하기 위해 mint 함수가 호출됩니다. mint는 사용자가 제공한 토큰 A와 토큰 B의 수를 기반으로 발행해야 하는 유동성 토큰(LP 토큰)의 수를 계산합니다. (사용자가 제공한 토큰 A와 토큰 B의 개수를 기반으로 mint 함수는 발행할 유동성 토큰(LP 토큰)의 개수를 계산하여 사용자에게 할당합니다. 유동성 추가 연산이 완료되면 mint 함수는 _update 함수를 호출하여 준비금을 업데이트합니다.
4.1.2 토큰 교환
사용자가 토큰을 교환하고자 할 때, 먼저 UniswapV2Router를 호출합니다. sol 컨트랙트를 호출하여 입력 토큰의 수와 최소 출력 토큰의 수를 제공합니다.
그런 다음 UniswapV2Router 컨트랙트의 swapExactTokensForTokens 함수가 사용자의 요청을 받아 처리하고, swapExactTokensForTokens 함수는 다시 UniswapV2Pair.sol 컨트랙트를 호출하여 입력 토큰 수량과 최소 출력 토큰 수량을 제공합니다. 실제 토큰 교환을 실행하기 위해 swap 함수를 호출합니다. swap 함수는 입력 토큰과 준비금에 따라 출력할 토큰 수를 계산하고 교환을 실행하며, 교환이 완료되면 swap 함수는 _update 함수를 호출하여 준비금과 누적된 수수료를 업데이트합니다. 프로세스는 다음과 같습니다:
4.1.3 유동성 출금
사용자는 먼저 UniswapV2Router를 호출합니다. sol 컨트랙트를 호출하여 출금할 LP 토큰의 수를 제공하고, UniswapV2Router.sol 컨트랙트의 removeLiquidity 함수는 사용자의 요청을 받아 처리하며, removeLiquidity 함수는 다시 UniswapV2Pair.sol 컨트랙트를 호출합니다. sol 컨트랙트를 호출하여 실제 유동성 출금을 수행하고, 소각 함수는 제공된 LP 토큰 수에 따라 반환해야 하는 토큰 A와 토큰 B의 양을 계산하여 해당 토큰을 사용자에게 반환합니다.
유니스왑V2 코어 컨트랙트는 탈중앙화 거래 플랫폼인 유니스왑의 핵심이며 자동화된 시장 메이커(AMM) 기능의 구현을 책임지고 있습니다. (AMM) 기능을 구현합니다. 기존 오더북과 달리 유니스왑은 유동성 풀과 일정한 상품 공식 x-y = k를 통해 거래할 수 있습니다. 유동성 공급자는 풀에 두 개의 토큰을 예치하고 유동성 토큰을 자격 증명으로 받습니다. 사용자가 거래할 때, 컨트랙트는 풀의 토큰 수와 상수 제품 공식을 기반으로 거래 가격을 계산합니다. uniswapV2는 직접 거래를 위한 ERC20 페어, 가격 예측 기계 개선, 플래시 크레딧, 계약 수수료 조정 등 여러 가지 개선 사항을 도입했습니다. 핵심 컨트랙트의 핵심 구성 요소는 다음 세 가지 파일로 구성됩니다.
UniswapV2Pair.sol: 각 쌍의 유동성 풀을 관리하고 토큰 스왑, 유동성 추가 및 제거를 처리
UniswapV2Factory.sol: 쌍의 생성 및 관리를 담당
UniswapV2ERM: 쌍의 생성 및 관리를 담당
UniswapV2ERM: 쌍의 생성과 관리
4.2.1 유니스왑V2 팩토리.sol
유니스왑V2 팩토리 컨트랙트의 역할은 거래 쌍(유동성 풀)의 생성 및 관리를 처리하는 것입니다. 사용자는 컨트랙트를 통해 새로운 트레이딩 페어를 생성하고 생성된 모든 트레이딩 페어를 추적할 수 있습니다. 또한 거래 수수료 수취인 주소와 설정자 주소를 관리합니다.UniswapV2Factory.sol에는 다섯 가지 함수가 있으며, 각 함수를 살펴보겠습니다
생성자 함수: 생성자 함수, 초기화하는 데 사용되는 컨트랙트를 초기화하는 데 사용되는 생성자 함수입니다. 입력은 트랜잭션 수수료 설정자 주소 _feeToSetter이고 출력은 없음입니다.
allPairsLength 함수: 생성된 모든 쌍의 수를 반환합니다. 입력은 none이고 출력은 모든 쌍의 단위입니다.
createPair 함수: 새 쌍을 생성합니다. 입력은 토큰A와 토큰B의 주소이고, 출력은 생성된 쌍의 주소입니다.
setFeeTo 함수: 수수료 수락 주소를 설정합니다. 입력은 새 트랜잭션 수수료 수락 주소 _feeTo이며, 출력은 없음입니다.
setFeeToSetter 함수: 새 트랜잭션 수수료 설정자 주소를 설정합니다. 입력값은 새 트랜잭션 수수료 설정자 주소 _feeToSetter이고, 출력값은 none입니다.
구문 분석된 구체적인 코드는 다음과 같습니다:
createPair 함수
createPair 함수의 기능은 TokenA와 TokenB의 쌍을 생성하는 것으로, 프론트엔드에 TokenA와 TokenB가 입력되면 TokenA와 TokenB가 동일한 통화인지 확인한 후, TokenA와 TokenB의 TokenA와 TokenB는 간단한 정렬을 수행한 다음 Token0의 주소를 확인합니다, require Token0의 주소는 0일 수 없습니다;
이후에는 require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS') ; 를 통해 TokenA와 TokenB의 주소를 확인한 다음 Token0의 주소를 확인합니다, require Token0. EXISTS') ; 이 토큰 쌍이 존재하는지 확인하고 존재하는 경우에만 진행할 수 있습니다; 그 후, creationCode를 통해 UniswapV2Pair 컨트랙트의 생성 바이트코드를 얻습니다;
그 후, 토큰0과 토큰1의 해시값을 소금으로 사용하여 각 토큰 쌍의 주소가 고유하다는 것을 확인합니다. 토큰 쌍의 주소가 고유하지 않은 경우 유동성을 추가하는 트레이더가 잘못된 풀에 추가할 수 있으므로, 인라인 어셈블리에서 create2 명령을 사용하여 컨트랙트 주소의 고유성과 예측 가능성을 보장하기 위해 컨트랙트를 생성하고, 그 후 새로 생성된 토큰 쌍의 컨트랙트를 초기화하고 매핑 테이블을 업데이트하여 이 토큰 쌍의 계약 주소를 기록한 다음 모든 쌍의 계약에 새로 생성된 계약 주소를 추가하고
그 후 새로 생성된 쌍의 계약이 초기화되고 맵핑 테이블이 이 계약의 주소를 기록하도록 업데이트합니다. 주소가 모든 쌍의 목록에 추가되고, 마지막으로 새 쌍이 생성되었음을 외부에 알리기 위해 PairCreated 이벤트가 트리거됩니다.
4.2.2 UniswapV2 ERC20.sol
유니스왑V2ERC20.sol의 주요 기능은 ERC-20 토큰을 구현하는 것입니다. 이는 특히 유니스왑V2 유동성 풀을 위한 ERC20 표준 토큰 기능을 구현합니다. 컨트랙트에는 발행, 소각, 승인, 전송과 같은 기본 작업이 포함됩니다. 또한 서명을 사용해 토큰 전송을 승인할 수 있는 허가 기능도 지원합니다. 포함된 함수를 하나씩 살펴봅시다:
생성자 함수: 컨트랙트를 초기화하고, 허가 함수에 사용할 DOMAIN_SEPARATOR를 설정합니다. 입력 없음, 출력 없음.
_mint 함수: 새 토큰을 발행, 입력은 수신 주소 "to", 발행 수량 "value", 출력 없음
_burn 함수 : 토큰 소각, 입력은 소각 주소와 소각 수량 값, 출력은 없음.
_approve 함수: 토큰 전송 승인, 소유자 주소 소유자, 승인 주소 발신자 및 승인 수량 값, 출력 없음.
_transfer 함수: 토큰 전송, 입력은 발신자, 수신자 및 값, 출력은 없음.
approve 함수: 공개 승인 함수, 역할은 _approve 함수를 호출하는 것이고, 입력은 승인 함수에 의해 공개된 승인 함수, 출력은 작업의 성공을 나타내는 부울 값 true를 반환하는 것.
_approve 함수: 공개 승인 함수, 역할은 승인 함수에 의해 공개된 승인 함수, 입력은 승인 함수, 출력은 승인 함수.
전송 함수: 역할은 _transfer 함수를 호출하는 것이고, 입력은 주소를 수락하고 값의 수를 전송하는 것이며, 출력은 작업이 성공했다는 부울 참을 반환하는 것입니다
transferFrom 함수: 공개 함수 전송에 대한 승인 함수입니다. 입력은 from, to, value이며, 출력은 작업의 성공을 나타내는 부울 참입니다
permit 함수: 서명을 사용하여 토큰 전송을 승인하고 서명의 유효성을 검사하고 _approve 함수를 호출하며, 입력은 소유자, 스펜서, 값, 마감일, 서명이며 출력은 작업의 성공을 나타내는 부울 참입니다
transferFrom 함수: 공개 승인 전송 함수입니다
. 입력은 소유자 주소, 승인 주소 발신자, 승인 수량 값, 기한, 서명 매개변수 v, r, s, 출력 없음입니다.
공식 소스 코드 파싱은 아래와 같습니다:
4.2.3 유니스왑V2 페어.sol
거래 페어 컨트랙트인 유니스왑V2페어(UniswapV2Pair)는 각 거래 쌍의 유동성 풀을 관리하고 조작하는 유니스왑 v2의 핵심 기능을 구현합니다. 이 계약은 토큰 교환, 유동성 추가 및 제거, 가격 누적 계산을 처리합니다. 각 거래 후 쌍의 준비금과 가격 정보를 업데이트하고 적절한 이벤트 알림을 트리거합니다. 아래 표에 나열된 11가지 기능이 UniswapV2Pair.sol에 있습니다:
<
공식 UniswapV2Pair.sol 코드와 설명은 다음과 같습니다:
UniswapV2Pair는 IUniswapV2Pair, UniswapV2ERC20에서 상속받았습니다. 우선, IUniswapV2Pair의 소스 코드를 살펴보고 인터페이스를 어떻게 정의하는지 확인하세요:
글로벌 변수와 수정자는 그 뒤에 정의됩니다
위의 MINIMUM_LIQUIDITY는 유동성 공급자가 유동성 고갈을 방지하기 위해 항상 일정량 이상의 토큰을 보유하도록 유동성 풀에 보유해야 하는 최소 유동성 토큰 수를 설정하는 상수로, 10의 3승의 값으로 초기 공급 시 소각됩니다. 유동성은 소각됩니다; 셀렉터는 스마트 컨트랙트에서 다른 컨트랙트의 전송 함수를 정확하게 식별하고 호출하여 토큰 전송을 수행할 때 올바른 함수 서명이 사용되도록 하는 데 사용되는 토큰 전송 함수에 대한 ABI (Application Binary Interface) 셀렉터를 저장합니다;
factory는 거래 쌍 계약의 트랜잭션 쌍 계약을 저장합니다. 유니스왑 V2 팩토리는 컨트랙트의 주소를 저장하는 데 사용되며, Token0과 Token1은 토큰의 주소를 저장하는 데 사용되며, 세 가지 상태 변수인 reserve0, reserve1 및 blockTimestampLast는 두 자산의 최신 상수 상품 수와 거래 당시 블록이 생성된 시간을 기록합니다.
그리고 price0CumulativeLast 및 price1CumulativeLast 변수는 쌍 내 두 가격의 누적값을 기록하는 데 사용되며, kLast는 유동성 풀의 가격 안정성을 유지하고 거래 수수료를 계산하는 데 주로 사용되는 핵심 파라미터로서 UniswapV2 쌍 내 두 토큰 보유량의 가장 최근 상태를 추적하는 데 사용됩니다. 팀 처리 수수료 계산에 주로 사용됩니다.
다음 수정자는 재진입 공격을 방지하기 위한 잠금 메커니즘을 제공하며, 다음과 같이 세분화됩니다.
이미지 src="https://img.jinse.cn/7249610_image3.png">
위 코드에서 _; 는 수정되는 함수 본문을 나타냅니다. 이 코드의 일반적인 로직은 잠금 수정자를 정의하여 잠금 해제된 변수의 상태를 변경하여 수정된 함수가 실행되는 동안 컨트랙트가 다시 입력되지 않도록 함으로써 재진입 공격과 경쟁 조건을 방지한다는 것입니다.
아래 getReserves 함수의 목적은 두 개의 현재 토큰 보유량과 유니스왑V2 페어 컨트랙트의 마지막 업데이트 타임스탬프에 대한 정보를 공개적으로 쿼리하고 반환하는 방법을 제공하는 것입니다.
_ safeTransfer 함수는 스마트 컨트랙트 내에서 토큰 전송 작업을 수행하며 전송 성공 여부를 확인하고 실패할 경우 예외를 발생시켜 컨트랙트의 보안과 토큰 전송의 신뢰성을 보장하며, 이 코드의 자세한 주석은 다음과 같습니다:
다음 생성자는 팩토리를 초기화하는 데 간단히 사용됩니다:
초기화 함수의 는 쌍 컨트랙트에 포함된 두 토큰의 주소를 설정하는 데 사용되며, 쌍을 배포하는 팩토리 컨트랙트에서만 호출할 수 있어 쌍의 초기화가 안전하고 제어되도록 보장합니다.
이미지 src="https://img.jinse.cn/7249615_image3.png">
_update 함수의 주요 목적은 현재 블록의 타임스탬프와 마지막 업데이트의 타임스탬프를 비교하여 페어 콘트랙트의 준비금과 가격 누산기가 가장 최신 상태를 반영하도록 하는 것입니다. 현재 블록의 타임스탬프와 마지막 업데이트의 타임스탬프를 비교하여 최신 상태를 반영합니다. 업데이트 함수의 네 가지 입력 매개변수는 쌍에 있는 두 토큰의 현재 잔액을 나타내는 balance0과 balance1, 함수가 호출되기 전 두 토큰의 보유량을 나타내는 _reserve0과 _reserve1입니다. 글머리 기호를 사용하여 _update 함수가 어떻게 구현되는지 설명하겠습니다.
잔액 값으로 인해 오버플로가 발생할 수 있는지 확인: require 문을 사용하여 balance0 및 balance1 값이 최대 uint112 값을 초과하지 않는지 확인합니다. reserve0과 reserve1은 uint112 타입을 사용하여 저장되므로 데이터 타입 변환 시 안전해야 하므로 최대값인 uint112를 초과하지 않습니다.
현재 블록 시간 기록하기: 현재 블록의 타임스탬프를 가져와서 blockTimestampLast로 모듈로-2^32 연산을 수행하여 blockTimestamp를 얻습니다. 이더넷 블록 타임스탬프는 32비트이고 절대 시간이 아닌 블록 내의 시간 차이만 중요하기 때문에 이 연산을 수행합니다.
시간 차이 계산하기: 현재 블록 시간과 마지막 업데이트 시간인 timeElapsed 사이의 차이를 계산합니다. 시간 경과가 0이면 동일한 블록 내 연속 호출이므로 가격 누적값이 업데이트되지 않음을 의미합니다.
가격 누적 업데이트: timeElapsed가 0보다 크고 예비금이 0이 아닌 경우, 고정점 수학 라이브러리 UQ112x112를 사용하여 가격 비율을 계산하고 price0CumulativeLast와 price1CumulativeLast를 업데이트합니다. 여기서 "오버플로가 발생하지 않음"이란 시간 간격 timeElapsed가 uint32 유형이므로 여기에 가격 누적 값(uint224)을 곱해도 오버플로가 발생하지 않는다는 의미입니다. "+ 오버플로우가 필요합니다"는 가격 계산 시 절대값이 아닌 델타를 사용하기 때문에 가격 누적값의 오버플로우가 허용되며, 오버플로우가 발생하더라도 평균 가격 계산에 사용되는 변동폭은 여전히 정확하다는 의미입니다.
예비금 업데이트: 예비금0과 예비금1에 새 잔액을 할당하면 유동성 풀의 예비금이 업데이트됩니다.
타임스탬프 업데이트: 다음 업데이트를 준비하기 위해 현재 블록 타임스탬프를 블록타임스탬프Last에 할당합니다.
동기화 이벤트 트리거: 외부 리스너에게 리저브가 업데이트되었음을 알리기 위해 emit 키워드를 통해 동기화 이벤트를 발신합니다.
이러한 설계를 통해 UniswapV2는 많은 수의 거래를 처리할 때 가격 연속성과 정확성을 유지하고 블록 타임스탬프 또는 가격 누적 값에서 잠재적인 오버플로가 발생하는 경우에도 변동량으로부터 평균 거래 가격을 정확하게 계산할 수 있습니다. 이는 고정 소수점 수학과 시차를 영리하게 사용함으로써 달성할 수 있습니다.
이미지 src="https://img.jinse.cn/7249616_image3.png">
이미지 src="https://img.jinse.cn/7249617_image3.png">
내부에서 유니스왑V2에서는 거래당 0.3%의 수수료가 부과됩니다. 이 수수료의 6분의 1은 개발팀에 할당되고, 나머지 6분의 5는 유동성 공급자에게 보상으로 제공됩니다. 그러나 수수료가 트랜잭션당 한 번만 계산되면 사용자의 가스 비용이 필연적으로 증가하게 됩니다.
따라서 유니스왑V2에서는 수수료가 누적되며, 유동성이 변경될 때만 수수료가 할당됩니다. _mintFee 함수는 먼저 트랜잭션 수수료가 켜져 있는지 확인하고 수수료 수취 주소를 결정합니다. 트랜잭션 수수료가 켜져 있지 않고 이전에 수수료가 캐스팅된 적이 있는 경우(_kLast가 0이 아닌 경우), kLast 값이 초기화됩니다. 이 수수료 캐스팅 메커니즘은 유동성 공급자에게 추가 인센티브를 제공하는 데 사용되는 UniswapV2의 일부이며, 거래 수수료가 켜진 경우 수수료 값은 다음 공식에 따라 계산됩니다.
Sₘ는 발행해야 하는 수수료 유동성 토큰의 수를 나타내고, k₁는 마지막 유동성 이벤트 k 이후 보유량의 곱, k₂는 현재 보유량 k의 곱, S₁는 마지막 유동성 이벤트 이후 유동성 토큰의 총 공급량을 나타냅니다.
유니스왑V2 주변 계약은 외부 계정과 코어 계약 사이의 다리 역할을 하며 인터페이스 정의, 도구 라이브러리, 라우터, 샘플 구현의 네 부분으로 구성됩니다.
4.3.1 라이브러리
라이브러리 폴더에는 4개의 파일이 포함되어 있습니다
SafeMath.sol
UniswapV2Library.sol
UniswapV2LiquidityMathLibrary. sol
UniswapV2OracleLibrary.sol
이 네 가지 sol 파일을 각각 자세히 분석해 보겠습니다
SafeMath.sol
. SafeMath.sol은 특히 블록체인과 스마트 컨트랙트 개발에서 정수 오버플로 및 언더플로 오류를 방지하는 데 중요한 오버플로 안전 수학 연산을 수행하는 데 사용됩니다. 주로 세 가지 함수가 포함되어 있습니다.
add 함수: 부호가 없는 두 정수의 덧셈을 안전하게 수행하는 데 사용됩니다
sub 함수: 부호가 없는 두 정수의 뺄셈을 안전하게 수행하는 데 사용됩니다
mul 함수: 부호가 없는 두 정수의 곱셈을 안전하게 수행하는 데 사용
구체적인 코드 주석은 다음과 같습니다
UniswapV2Library.sol
UniswapV2Library.sol은 Uniswap v2 스왑 쌍(페어)과 상호 작용하고 조작하기 위한 여러 가지 유틸리티 함수를 제공합니다.
이 함수들은 주로 거래 경로를 계산하고, 준비금을 가져오고, 가격을 계산하고, 체인 계산을 수행하는 데 사용됩니다. 이 라이브러리는 SafeMath라는 라이브러리를 사용하여 정수 오버플로우와 언더플로우로부터 수학 연산을 안전하게 보호합니다. 이 파일에는 8개의 함수가 포함되어 있습니다.
sortTokens 함수: 주소별로 정렬된 두 개의 토큰 주소를 반환합니다. 입력은 두 개의 토큰 주소 tokenA와 tokenB입니다. 출력은 정렬된 토큰 주소 token0과 token1입니다.
pairFor 함수: 외부 호출 없이 주어진 공장 주소와 두 토큰 주소의 쌍의 주소를 계산합니다. 입력은 팩토리 주소 팩토리와 두 토큰 주소 tokenA와 tokenB이며, 출력은 쌍의 주소입니다
getReserves 함수: 한 쌍의 리저브를 가져와서 정렬합니다. 입력은 팩토리 주소, 두 토큰 주소 tokenA와 tokenB, 출력은 두 토큰 reserveA와 reserveB의 보유량입니다
quote 함수: 주어진 자산 금액과 쌍의 보유량에 따라 다른 자산의 동등한 금액을 반환합니다. 입력: 자산 금액A, 준비금 reserveA 및 준비금B의 금액입니다. 출력은 다른 자산의 금액인 금액B입니다.
getAmountOut 함수: 입력 자산의 금액과 쌍의 준비금이 주어질 때 다른 자산의 최대 출력 금액을 반환합니다. 입력은 입력 자산의 금액인 amountIn과 준비금인 reserveIn 및 reserveOut이고 출력은 출력 자산의 금액인 amountOut입니다.
getAmountIn 함수: 출력 자산의 금액과 쌍의 준비금을 기준으로 입력해야 할 다른 자산의 필요 금액을 반환합니다. 입력은 출력 자산 수량 amountOut, 준비금 reserveIn 및 reserveOut입니다.
getAmountsOut 함수: 임의의 수의 페어에 대해 연쇄적인 getAmountsOut 계산을 수행하며, 입력은 공장 주소 공장, 입력 자산 수량 amountIn, 경로 경로이고 출력은 각 경로입니다.
getAmountsIn 함수: 임의의 수의 쌍에 대해 연쇄 getAmountsIn 계산을 수행하고, 입력은 공장 주소 공장, 출력은 자산 금액Out, 경로 경로; 출력은 경로 노드별 금액 배열입니다.
getAmountsIn 함수: 임의의 수의 쌍에 대해 연쇄 getAmountsIn 계산을 수행하고, 입력은 공장 주소 공장, 출력은 자산 금액Out, 경로 경로; 출력은 각 경로입니다. 출력은 각 경로 노드 금액에 대한 자산 수 배열입니다
UniswapV2Libray 소스 코드는 다음과 같이 상세하게 주석 처리되어 있습니다:
UniswapV2OracleLibrary.sol
유니스왑V2OracleLibrary.sol 파일은 예측자의 평균 가격 계산과 관련하여 사용할 수 있는 여러 도우미 메서드를 제공합니다. 연산과 관련하여 사용할 수 있는 여러 도우미 메서드를 제공합니다. 이 라이브러리에는 가스 비용을 절약하고 잦은 동기화 호출을 피하기 위해 현재 블록 타임스탬프를 가져오고 누적 가격을 계산하는 메서드가 포함되어 있습니다. 다음과 같은 두 가지 함수가 포함되어 있습니다.
currentBlockTimestamp 함수: 현재 블록 타임스탬프를 반환합니다. 입력은 없음, 출력은 현재 블록 타임스탬프, 유형은 uint32입니다.
currentCumulativePrices 함수: 누적 가격을 계산하여 반환합니다. 입력은 쌍의 주소, 출력은 누적 가격 가격0Cumulative와 가격1Cumulative, 현재 블록 타임스탬프 블록타임스탬프입니다.
UniswapV2OracleLibrary.sol 공식 소스 코드는 다음과 같이 상세하게 주석 처리되어 있습니다. 는 다음과 같습니다:
<>< strong>UniswapV2LiquidityMathLibrary.sol
유니스왑 V2 유동성 수학 라이브러리 공식 소스 코드는 다음과 같습니다
computeProfitMaximisingTrade 함수: 수익을 극대화하기 위해 거래의 방향과 규모를 계산합니다.
겟리저브애프터아비트라지 함수: 차익거래 후 유동성 풀의 보유량을 관찰된 "실제 가격"으로 가져옵니다.
computeLiquidityValue 함수: 유동성 풀의 모든 매개변수가 주어지면 유동성 값을 계산합니다.
getLiquidityValue 함수: 모든 현재 매개변수를 가져와 유동성 금액의 값을 계산합니다.
getLiquidityValueAfterArbitrageToPrice 함수: 두 토큰과 해당 토큰의 "실제 가격", 유동성 금액이 주어지면 유동성의 가치를 반환합니다.
AfterArbitrageToPrice 함수. >
UniswapV2Router02.sol
생성자와 수정자, 이더리움을 받는 함수, 유동성 추가, 유동성 제거, 토큰 스와핑, 라이브러리 함수 등 크게 6가지로 나눌 수 있는 UniswapV2Router02의 소스 코드를 살펴 보겠습니다.
생성자 및 수정자
생성자(주소 _factory, 주소 _WETH): 팩토리 컨트랙트 주소와 WETH 컨트랙트 주소를 초기화합니다.
modifier ensure(uint deadline): 트랜잭션이 기한 전에 완료되었는지 확인합니다.
ETH를 받는 함수
receive() external payable: WETH 컨트랙트에서만 호출할 수 있는 ETH를 받습니다.
addLiquidity
_addLiquidity: 유동성을 추가하는 내부 함수로, 기존 보유량을 기반으로 최적의 토큰 수를 계산합니다.
addLiquidity: 두 개의 ERC-20 토큰에 대한 유동성을 추가합니다.
addLiquidityETH: ERC-20 토큰과 이더리움에 대한 유동성을 추가합니다.
removeLiquidity
removeLiquidity: 두 ERC-20 토큰에 대한 유동성을 제거합니다.
removeLiquidityETH: ERC-20 토큰과 ETH 모두에서 유동성을 제거합니다.
removeLiquidityWithPermit: 허가를 받아 두 ERC-20 토큰의 유동성을 제거합니다.
removeLiquidityETHWithPermit: 허가를 받아 ERC-20 토큰과 ETH의 유동성을 제거합니다.
removeLiquidityETH지원수수료토큰: 수수료 토큰을 지원하는 ERC-20 토큰과 ETH의 유동성을 제거합니다.
removeLiquidityETHWithPermitSupportingFeeOnTransferTokens: 허가를 받아 ERC-20 토큰과 ETH 유동성을 제거하며 수수료 토큰을 지원합니다.
토큰 스왑
_swap: 토큰 스왑 로직을 수행하는 내부 함수입니다.
swapExactTokensForTokens: 토큰의 정확한 개수를 다른 토큰으로 교환합니다.
swapTokensForExactTokens: 토큰을 정확한 양의 다른 토큰으로 스왑합니다.
swapExactETHForTokens: 토큰을 정확한 금액의 이더로 교환합니다.
swapTokensForExactETH: 토큰을 정확한 금액의 이더로 스왑합니다.
swapExactTokensForETH: 토큰을 정확한 금액의 이더로 스왑합니다.
swapETHForExactTokensForETH. swapETHForExactTokens: 정확한 수의 토큰을 ETH로 교환합니다.
swapExactTokensForTokensSupportingFeeOnTransferTokens: 수수료 토큰을 지원하여 정확한 수의 토큰을 다른 토큰으로 교환합니다.
swapExactETHForTokensSupporting수수료온토큰: 수수료 토큰을 지원하면서 토큰을 정확한 수의 ETH 토큰으로 교환합니다.
swapExactTokensForETHSupportingFeeOnTransferTokens: 정확한 양의 토큰을 사용하여 ETH를 토큰으로 교환하고 수수료 토큰을 지원합니다.
라이브러리 함수
quote: 보유량을 기준으로 주어진 토큰 A에 해당하는 토큰 B의 개수를 계산합니다.
getAmountOut: 입력 수와 준비금이 주어졌을 때 얻을 수 있는 출력량을 계산합니다.
getAmountIn: 출력 수와 예비금이 주어졌을 때 필요한 입력 수를 계산합니다.
getAmountsOut: 경로와 입력 개수를 기준으로 출력 개수를 계산합니다.
getAmountsIn: 경로와 출력 개수를 기준으로 입력 개수를 계산합니다.
구체적으로 우리 아래 기능별로 살펴보면, UniswapV2Router02.sol의 컨트랙트는 다음 코드를 통해 IUniswapV2Router02에서 상속됩니다.
. 유니스왑V2라우터02 콘트랙트는 아이유니스왑V2라우터02 인터페이스를 구현하며 다음과 같은 주요 기능을 제공합니다.
유동성 추가: 사용자가 유동성 공급자 토큰과 교환하여 유동성 풀에 2개의 토큰을 추가할 수 있습니다.
이동성 제거: 이동성 공급자가 자신의 이동성 공급자 토큰을 두 개의 토큰으로 다시 교환할 수 있습니다.
거래: 사용자가 토큰 간 거래를 할 수 있으며, 직접 거래와 여러 쌍의 경로를 통한 거래를 모두 지원합니다.
호가 계산: 주어진 입력 또는 출력량에 대한 거래의 세부 사항을 계산하는 일련의 기능을 제공합니다.
확보 한정자는 현재 블록 시간이 최신 트랜잭션의 블록 시간이 최신 트랜잭션 시간을 초과하는지 확인하여 사용자가 지정한 트랜잭션이 시간 초과로 인해 실패하지 않도록 하여 트랜잭션의 보안과 안정성을 향상시키는 데 도움이 됩니다.
컨트랙트 생성자는 프로젝트 컨트랙트 주소와 웨스 컨트랙트 주소를 초기화하며, 이는 컨트랙트 수명 내내 일정하게 유지됩니다.
수신 함수 는 일반적으로 컨트랙트가 함수 호출을 통하지 않고 직접 이더를 받을 수 있도록 하는 데 사용됩니다. 이 예시에서 수신 함수는 오직 WETH 컨트랙트만 어서트 문을 통해 이더를 전송할 수 있도록 합니다.
이미지 src="https://img.jinse.cn/7249678_image3.png">
_addLiquidity 함수의 목적은 사용자가 유동성을 추가할 때 입금해야 하는 두 토큰의 최적 금액을 계산하는 것입니다. 이 함수는 6개의 매개변수를 허용합니다. tokenA와 tokenB는 유동성에 추가할 두 토큰의 주소, amountADesired와 amountBDesired는 사용자가 추가하고자 하는 두 토큰의 초기 금액, amountAMin과 amountBMin은 사용자가 유동성에 추가할 수 있는 최소 금액으로 슬리피를 방지하기 위해 허용할 수 있는 금액입니다. 이 함수는 두 개의 매개변수, 즉 실제 추가된 토큰 수인 amountA와 amountB를 반환합니다.
이 계산은 사용자가 추가한 유동성의 균형을 맞추기 위해 유동성 풀에 이미 있는 토큰의 양을 고려합니다. 유동성 풀이 신규이고 기존 준비금이 없는 경우 사용자는 원하는 만큼만 추가하면 됩니다. 풀에 이미 준비금이 있는 경우, 기능은 현재 비율에 따라 추가할 최적의 양을 계산하여 유동성을 추가한 후에도 풀의 토큰 비율이 동일하게 유지되도록 보장합니다.
지정된 유동성 풀에 토큰을 추가하는 addLiquidity의 공용 함수입니다. 두 개의 토큰(토큰A와 토큰B)으로 구성된 유동성 풀
addLiquidityETH 함수는 사용자가 비이더 토큰과 이더리움 토큰의 비이더 토큰과 이더를 해당 유동성 토큰과 교환하여 UniswapV2 유동성 풀에 추가할 수 있습니다. 이 함수에는 6개의 허용 매개변수가 있으며, token은 유동성을 추가할 비이더 토큰의 주소, mountTokenDesired는 사용자가 추가하고자 하는 비이더 토큰의 수, mountTokenMin은 사용자가 풀에 추가하는 것을 허용할 수 있는 최소 비이더 토큰 수, 다음을 위해 사용됩니다. 미끄러짐을 방지하는 데 사용되며, 마운트ETHMin은 추가할 수 있는 최소 이더 토큰 수로 미끄러짐을 방지하는 데 사용되며, to는 새로 발행된 유동성 토큰을 받을 주소이고, deadline은 트랜잭션의 타임아웃을 방지하는 데 사용되는 트랜잭션의 마감 시간입니다.
함수는 세 가지 매개변수를 반환합니다. amountToken과 amountETH는 유동성 풀에 실제로 추가된 비이더 토큰과 이더 토큰의 수이며, 유동성은 새로 발행된 유동성 토큰의 수입니다.
유동성 제거 기능을 통해 사용자는 유동성에서 유동성을 제거할 수 있습니다. removeLiquidity 함수를 사용하면 사용자가 이전에 추가한 유동성을 풀에서 제거하고 두 토큰의 비례 금액을 받을 수 있습니다. 소각 함수는 실제 유동성 소멸 및 토큰 할당 작업을 수행하는 IUniswapV2Pair 유동성 풀 컨트랙트의 기본 기능입니다.
removeLiquidityETH 기능을 사용하면 사용자가 UniswapV2 유동성 풀에서 이전에 이더로 추가한 유동성을 제거하고 그에 상응하는 비이더와 이더 코인을 각각 가져옵니다. 이 함수는 먼저 removeLiquidity를 호출한 다음, 안전한 전송을 통해 해당 토큰을 추출한 다음, 소각된 유동성에서 추출한 WETH를 이더로 교환한 다음, 변환된 이더를 수신자에게 전송합니다.
removeLiquidityWithPermit 함수는 사용자가 ECDSA 서명으로 승인할 수 있도록 하여 사용자가 이전에 승인 함수로 승인할 필요 없이 컨트랙트가 사용자를 대신하여 유동성을 제거할 수 있도록 합니다.
removeLiquidityETHWithPermit 함수는 removeLiquidityETH와 허가 승인 메커니즘을 결합하여 사용자가 표준 승인 모드를 사용할 필요 없이 일회성 승인 계약에 서명하여 유동성을 제거할 수 있도록 합니다. 이를 통해 트랜잭션의 가스 비용을 절감하는 동시에 더 나은 사용자 경험과 보안을 제공합니다.
이미지 src="https://img.jinse.cn/7249698_image3.png">
이미지 src="https://img.jinse.cn/7249699_image3.png">
이미지 src=" https://img.jinse.cn/7249700_image3.png">
removeLiquidityETH지원수수료온트랜스퍼토큰 기능을 사용하면 특정 토큰 및 이더리움과 관련된 이전에 추가한 토큰을 UniswapV2 유동성 풀에서 제거할 수 있습니다. 및 이더 유동성에서 일부 토큰이 전송 시 수수료를 부과할 수 있다는 점을 고려합니다.
이 함수는 먼저 removeLiquidity를 호출하여 유동성 제거를 수행한 다음, 토큰 전송을 처리하여 사용자가 자격이 있는 토큰 수를 받도록 하고, 마지막으로 WETH를 다시 이더로 변환하여 사용자에게 전송합니다. 전체 프로세스는 사용자가 지정한 거래 마감일 전에 완료되어야 합니다.
removeLiquidityETHWithPermitSupportingFeeOnTransferTokens 함수는 제거유동성ETH와 토큰 전송 시 수수료가 부과될 수 있는 토큰을 처리하는 동안 일회성 승인 계약을 체결하여 유동성을 제거할 수 있도록 하는 허가 승인 메커니즘을 결합한 것입니다.
이 접근 방식은 승인 모드를 사용하지 않고도 사용자의 자산을 조작하기 위해 계약을 승인하는 방법을 제공하여 가스 비용을 절감하고 사용자 경험을 개선합니다.
이미지 src="https://img.jinse.cn/7249704_image3.png">
이미지 src="https://img.jinse.cn/7249705_image3.png">
_swap 함수는 일련의 토큰 스왑 작업을 수행하는 내부 함수입니다. 최종 토큰에 도달할 때까지 지정된 경로와 토큰 수에 따라 한 토큰에서 다른 토큰으로 스왑합니다. 이 기능은 유동성 풀 상호 작용의 핵심 부분이며 토큰 스왑과 유동성 풀 업데이트를 구현하는 데 사용됩니다.
swapExactTokensForTokens 함수는 사용자가 최소한의 출력 토큰에 대해 정확한 양의 입력을 교환할 수 있도록 하는 UniswapV2 라우터의 핵심 기능입니다. 이 기능은 먼저 전체 교환 경로에 대한 출력을 계산한 다음 최종 출력이 사용자의 최소 요구 사항을 충족하는지 확인한 다음 사용자로부터 유동성 풀로 토큰을 안전하게 전송하고 교환 작업을 수행합니다.
swapTokensForExactTokens 함수를 사용하면 사용자가 받고자 하는 토큰의 양을 지정하고 교환할 토큰의 최대량을 넘지 않도록 할 수 있습니다. 이 함수는 먼저 amountOut을 얻는 데 필요한 최대 입력을 계산한 다음 이 입력이 사용자가 지정한 amountInMax를 초과하지 않는지 확인합니다.
swapExactETHForTokens 함수는 사용자가 정확한 금액의 이더를 일정 금액 이상의 다른 토큰으로 교환할 수 있도록 합니다. 이 함수는 먼저 스왑 경로가 유효한지 확인한 다음 필요한 WETH의 양을 계산하고, ETH를 WETH 컨트랙트에 입금한 다음 스왑을 수행하고 결과 토큰을 사용자가 지정한 주소로 보냅니다. 전체 프로세스는 사용자가 지정한 거래 마감일 전에 완료되어야 합니다.
swapExactETHForTokens 함수는 정해진 양의 이더를 다른 토큰으로 판매하는 데 사용됩니다. 먼저 경로 유효성 검사를 수행하여 경로 배열의 첫 번째 요소가 WETH 주소인지 확인합니다(Uniswap 쌍은 ERC20/ERC20 쌍이므로).
다음으로 사용자가 전송한 ETH 금액, msg.getAmountsOut 함수를 사용하여 출력 금액을 계산합니다(UniswapV2Library.getAmountsOut 함수). 값과 토큰 경로를 전달받아 사용자가 받을 수 있는 각 토큰의 양을 계산하고 그 결과를 금액 배열에 저장합니다. 다음 단계는 최소 출력 검증으로, 이 함수는 금액 배열의 마지막 요소(즉, 목표 토큰 수)가 사용자가 설정한 최소 출력량인 amountOutMin을 충족하는지 여부를 확인합니다. 그렇지 않으면 에러가 발생하고, 다음 단계는 WETH 토큰 컨트랙트의 입금 함수를 호출하여 msg.value의 ETH를 WETH 컨트랙트에 입금하고, WETH 컨트랙트가 지정된 상대방 컨트랙트의 주소로 amounts[0] 양의 WETH를 전송하는지 확인하고, 실패하면 거래를 롤백하며, 마지막 단계는 실제 토큰 교환을 수행하는 내부 함수 _ swap을 호출하는 것입니다. 실제 토큰 교환 프로세스를 수행하는 내부 함수 _스왑을 호출합니다.
swapTokensForExactETH는 일정량의 ETH를 받고 다른 토큰을 판매하는 프로세스입니다. 이 함수는 얻을 것으로 예상되는 ETH, 사용자가 제공하고자 하는 최대 토큰 양인 amountOut, 토큰 교환 경로인 amountInMax, ETH를 받을 주소, 거래 기한 등 5개의 파라미터를 받습니다. 시간 기한;
첫 번째는 경로 유효성 검사로, 거래소 경로의 마지막 요소가 WETH 주소인지 확인하고, 그렇지 않은 경우 예외가 발생하며, 다음은 입력 금액 계산으로, UniswapV2Library.getAmountsIn 함수를 사용하여 금액아웃 금액을 얻기 위해 사용자가 토큰 수를 제공해야 하며, 토큰 수 계산을 보장하기 위해 UniswapV2Library.getAmountsIn 함수를 사용하여 ETH의 amountOut 수량을 얻기 위해 사용자가 제공해야 하는 토큰의 양을 계산하고, 계산된 토큰의 양이 사용자가 설정한 최대 금액을 초과하지 않는지 확인하고, 초과할 경우 예외를 발생시키고, TransferHelper의 safeTransferFrom 함수를 사용하여 msg.sender 주소에서 유동성 풀로 토큰을 안전한 방식으로 전송합니다.
다음, _swap 함수가 호출됩니다.
이미지 src="https://img.jinse.cn/7249718_image3.png">
이미지 src="https://img.jinse.cn/7249719_image3.png">
swapExactTokensForETH 함수는 정해진 수의 토큰을 최소 amountOutMin 이상의 이더리움으로 교환하는 데 사용됩니다. 이 함수는 사용자가 제공하려는 토큰 수량, 예상되는 최소 이더리움 수량인 amountIn, 토큰 교환 경로, 이더리움을 받을 주소, 거래 주소 등 5개의 파라미터를 받습니다. 이 함수는 사용자가 제공하고자 하는 토큰 수량, 예상되는 최소 ETH 수량, 토큰을 받을 경로, ETH를 교환할 주소, 거래 기한 등 5개의 매개 변수를 받습니다.
ETH를 사용하여 정해진 수의 토큰을 교환할 수 있는 swapETHForExactTokens 함수는 위의 swapExactTokensForETH, swapTokensForExactETH와 유사한 로직으로 구현되어 있습니다.
이미지 src="https://img.jinse.cn/7249722_image3.png">
_swapSupportingFeeOnTransferTokens 함수는 토큰 경로를 추적하고 각 토큰에 대해 스왑해야 하는 토큰 수를 계산하여 거래 수수료에 대한 토큰 스왑 로직을 지원합니다. 유동성 풀에 교환할 토큰 수를 풀링하고 교환 작업을 수행합니다.
swapExactTokensForTokensSupportingFeeOnTransferTokens 거래 수수료 토큰의 경우를 처리하면서 정해진 수의 토큰을 원하는 수 이상의 다른 토큰으로 정확히 교환합니다.
swapExactETHForTokensSupportingFeeOnTransferTokens는 특정 수의 ETH를 다른 토큰
swapExactTokensForETHSupportingFeeOnTransferTokens 기능을 통해 사용자는 정해진 수의 토큰을 최소 원하는 양의 이더리움으로 정확하게 교환하는 동시에 거래 수수료 토큰의 경우를 처리하고 이더리움이 정확하게 전송되도록 보장합니다.
이미지 src="https://img.jinse.cn/7249729_image3.png">
이미지 src="https://img.jinse.cn/7249730_image3.png">
Quote 함수는 다음을 구현합니다. 이 함수는 사용자가 지정한 토큰 수와 유동성 풀에 있는 두 토큰의 보유량에 따라 사용자가 다른 토큰으로 교환할 수 있는 토큰 수를 계산하여 반환합니다.
이미지 src="https://img.jinse.cn/7249731_image3.png">
<이미지 src="https://img.jinse.cn/7249732_image3.png">
getAmountOut 함수는 getAmountOut 함수와 동일합니다. getAmountOut 함수와 getAmountsOut 함수는 모두 상수 곱셈 알고리즘을 기반으로 합니다. 주어진 입력 금액과 준비금 후 사용자가 얻을 수 있는 출력 금액을 계산하려면 getAmountOut 함수를 정의하고, 주어진 입력 금액과 교환 경로 후 사용자가 얻을 수 있는 일련의 출력 금액을 계산하려면 getAmountsOut 함수를 정의합니다.
getAmountIn과 getAmountsIn의 계산 원리는 상수 곱 알고리즘을 기반으로 하며, 이를 통해 매수할 자산의 양이 주어지면 매도할 자산의 양을 계산할 수 있습니다.
4.3.2 유니스왑V2 마이그레이터.sol
유니스왑V2 마이그레이터.sol은 유니스왑 v1에서 유니스왑 v2로 유동성을 이전하는 데 사용됩니다. 이 계약에는 이더를 받을 수 있는 기능이 포함되며 유니스왑 v1 및 v2 라우터와 교환 계약을 사용하여 다음과 같은 작업을 수행합니다. 이 컨트랙트에는 이더를 받을 수 있는 기능이 포함되어 있으며, 유니스왑 v1 및 v2 라우터와 교환 컨트랙트를 사용하여 마이그레이션을 수행합니다. 이를 통해 사용자는 유니스왑 v1에서 유니스왑 v2로 유동성을 안전하게 이전할 수 있습니다. 세 가지 함수가 있으며, 각각 다음과 같은 특정 기능을 가지고 있습니다:
생성자 함수: 생성자 함수는 UniswapV2Migrator 컨트랙트를 초기화하는 함수입니다. 입력은 v1 공장 주소 _factoryV1과 v2 라우터 주소 _router, 출력은 없음
수신 함수: 컨트랙트가 모든 v1 스위치와 라우터에서 이더리움을 받을 수 있도록 하는 수신 함수. 입력은 없음, 출력은 없음입니다.
migrate 함수: 입력은 토큰 주소 token, 최소 토큰 금액 amountTokenMin, 최소 ETH 금액 amountETHMin, 수신 주소 to, 마감일, 출력은 없음
유니스왑V2 마이그레이터의 공식 소스코드는 다음과 같이 자세히 분석되어 있습니다:
4.3.3 인터페이스 폴더
4.3.3 인터페이스 폴더에는 인터페이스 폴더와 통신하는 데 사용되는 파일 집합이 포함되어 있습니다. 인터페이스 폴더에는 UniswapV1 및 V2 스위치, 라우터, 팩토리, WETH 및 ERC20 컨트랙트와의 상호작용을 위한 인터페이스 정의가 포함되어 있습니다. 주요 기능으로는 유동성 관리 및 마이그레이션, 토큰 거래 처리, 유동성 추가 및 제거, 이더리움 랩핑 및 랩핑 해제 등이 있으며, 이러한 인터페이스는 컨트랙트 간의 표준화된 상호작용을 보장합니다. 각 문서를 자세히 살펴보겠습니다.
이 파일은 유니스왑V1 거래소 컨트랙트와 상호 작용하는 데 사용되는 인터페이스인 IUniswapV1Exchange를 정의합니다. 교환 컨트랙트는 토큰과 이더리움 간의 거래 처리와 유동성 관리를 담당합니다. 다음 네 가지 함수가 포함되어 있습니다.
balanceOf 함수: 거래소 컨트랙트에 있는 주소의 잔액을 반환합니다.
transferFrom 함수: 한 주소에서 다른 주소로 토큰을 전송합니다.
tokenToEthSwapInput 함수: 토큰을 이더로 스왑하는 데 사용됩니다.
ethToTokenSwapInput 함수: 이더를 토큰으로 스왑하는 데 사용됩니다.
IUniswapV1Factory.sol
IUniswapV1Factory.sol은 UniswapV1의 팩토리 컨트랙트와 상호 작용하는 데 사용됩니다. 코드는 다음과 같이 구문 분석됩니다.
IERC20.sol
IERC20.sol은 다음과 같은 이름의 인터페이스를 정의합니다. 이더넷 토큰 표준(ERC-20)을 따르는 IERC20이라는 인터페이스를 정의합니다
싱가포르의 바이트댄스에서는 식중독 사고가 발생해 직원 130명이 입원했고, 푸티안의 중앙 주방과 나푸청의 윤난스는 운영 중단 명령을 받았습니다.
7월 30일, 바이트댄스 싱가포르 사무소에서 집단 식중독 의심 사고가 발생하여 약 60명의 직원이 영향을 받았으며, 이 중 57명이 입원 치료를 받았습니다. 공급업체인 YUN NANS는 영업을 중단했습니다.
바이트댄스 싱가포르 사무소에서 식중독 의심 사고가 발생해 41명이 입원 치료를 받았습니다. 바이트댄스와 현지 당국은 원인을 조사하고 있으며, 해당 직원들에게 즉각적인 지원을 제공하고 있습니다.
SEC,게리 겐슬러,유니스왑,SEC, 유니스왑 골든 파이낸스 고소 계획,게리, 디파이 전쟁에 대비하다.
NFT 스왑 주문은 일반적으로 거래되는 자산에 대한 정보, 관련 수량 및 추가 약관을 포함하여 당사자 간에 합의된 사전 정의된 매개변수를 기반으로 이루어집니다.
법안이 바이트댄스를 압박합니다: 보안 문제 해결을 위해 TikTok을 매각하지 않으면 미국의 금지 조치에 직면할 수 있습니다.
2월 23일 저녁, 유니스왑 재단의 거버넌스 책임자인 에린 코엔은 유니스왑 거버넌스 포럼에 토큰을 위탁하고 담보로 제공한 UNI 토큰 보유자에게 보상하는 수수료 메커니즘을 제안하는 제안을 발표했습니다.
최근 유니스왑 재단의 제안은 실제로 어떤 내용인가요? 이를 통해 단기간에 UNI 가격이 7달러에서 12달러로 70퍼센트 이상 상승할 수 있었습니다.
Cisco는 AI 기반 솔루션과 간소화된 정책 구성 및 암호화된 트래픽 분석과 같은 혁신적인 기능으로 사이버 보안을 혁신하는 보안용 AI 어시스턴트를 출시합니다. 광범위한 데이터 활용에 중점을 둔 이 발전은 사이버 방어 환경을 강화하는 데 중요한 이정표가 될 것입니다.
Blockchain.com은 목요일에 전 세계 인력의 4분의 1을 삭감한다고 발표했다고 여러 소식통이 밝혔습니다. 룩셈부르크에 본사를 둔 ...