본문 바로가기
⛓️ Web3

솔리디티 문해력 특강_5강

by meLR 2023. 9. 19.

디사이퍼에서 진행한 솔리디티 문해력 특강을 개인적으로 기록으로 남기기 위해 정리한 글입니다.

해당 특강은 아래 링크에서 확인 가능합니다. 강의를 진행해주신 안수찬님께 감사드립니다.

 

안수찬님 블로그 : https://solidity.ansuchan.com/

디사이퍼 솔리디티 문해력 특강 유튜브 : https://www.youtube.com/playlist?list=PLOY0jYV3zWiElk6lAXhuyRJ8dMDqelU_r    


UNISWAP

탈중앙거래소 종류

 

1. Order book (EtherDelta)

→ 등록 할때 가스비가 들고 그외에 비효율성이 많음

 

2. AMM - LP, Swap

  • Uniswap(CPMM: x*y=K) : $ETH <> $A , $ETH<>$B
  • Bancor($BNT)

→ 스마트 토큰 개념 도입 v1 $BNT<>$A, $BNT<>$B → v2

  • mStable (CSMM : constant sum market maker x+y=k )
  • Curve (StableSwap =CSMM+CPMM)
  • Balancer(CPMM; xy=k) → CM(Mean)MM xy*z=k

 

AMM 작동방식

 

기울기 = 가격

 

넣는 양과 받는 양의 차이를 슬리피지라고 하며 유동성이 많이 공급될수록 슬리피지가 작아지는 것을 확인 할수있다. 즉, TVL이 많을수록 슬리피지가 적게 거래 할수있다는 것을 의미하게된다.

 

Swap 하는 사람입장에서는 K값이 변하지 않지만 유동성 공급은 K값이 변한다.

AMM의 네가지 기능 구현

Swap

-etherToToken

-tokenToEther

LP

-addLiquidity

-removeLiquidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract TokenA is ERC20 {
constructor() ERC20("TokenA", "A") {
_mint(msg.sender, 50 * 10)
}

contract Exchange is ERC20 {
	address public tokenAddress;
	
	constructor(address _tokenAddress) ERC20("Uniswap LP", "UNI-LP") {
		    tokenAddress = _tokenAddress;
	}
		
    function addLiquidity() public payable {
        uint etherAmount = msg.value;
        uint tokenAmount = etherAmount;
        TokenA tokenContract = TokenA(tokenAddress);
        tokenContract.transferFrom(msg.sender, address(this), tokenAmount);
        _mint(msg.sender, etherAmount);
    }

    function removeLiquidity(uint lpTokenAmount) public {
        _burn(msg.sender, lpTokenAmount);
        uint etherAmount = lpTokenAmount;
        uint tokenAmount = lpTokenAmount;
        payable(msg.sender).transfer(etherAmount);
        TokenA tokenContract = TokenA(tokenAddress);
        tokenContract.transfer(msg.sender, tokenAmount);
    }

    function etherToTokenSwap() public payable {
        uint etherAmount = msg.value;
        uint tokenAmount = etherAmount;
        TokenA tokenContract = TokenA(tokenAddress);
        tokenContract.transfer(msg.sender, tokenAmount);
    }

    function tokenToEtherSwap(uint tokenAmount) public {
        TokenA tokenContract = TokenA(tokenAddress);
        tokenContract.transferFrom(msg.sender, address(this), tokenAmount);
        uint etherAmount = tokenAmount;
        payable(msg.sender).transfer(etherAmount);
    }
}
💡 tokenToEtherSwap 함수에서 중요한점은 컨트랙트는 이 컨트랙트 사용자 토큰에 접근할 권리가 없기에 approve가 되어있는 만큼 transferFrom이라는 함수를 통해 옮길수있다는 것이다.

 

UNISWAP

v1: Eth <> Token pair … factory <> exchange

v2 : ERC20 <> ERC20 Pair

v3 : 집중화된 유동성

v4 : hooks, singleton

 

Factory

pragma solidity 0.8.20;

contract Exchange {
    uint public number;
    constructor(uint _number) {
        number = _number;
    }
}

contract Factory {
    mapping(uint => address) public numberToExchange;
    mapping(address => uint) public exchangeToNumber;

    function createExchange(uint number) public returns (address) {
        Exchange created = new Exchange(number);
        numberToExchange[number] = address(created);
        exchangeToNumber[address(created)] = number;
        return address(created);
    }
}

 

개발 디자인 패턴 설명 사이트

The Catalog of Design Patterns

 

The Catalog of Design Patterns

 

refactoring.guru