상세 컨텐츠

본문 제목

UniswapV2-core - UniswapV2Factory.sol 코드 분석

Blockchain/DeFi

by Yongari 2023. 3. 26. 22:07

본문

 

UniswapV2Factory.sol 개요

이 컨트랙트는 유니스왑에서 Pair가 교환하는 기능을 만듭니다. 

 

UniswapV2Factory.soll 핵심함수

함수 설명
allPairsLength
모든 Pair의 길이를 반환하는 함수
createPair
교환하는 Pair의 수를 반환함 
setFeeTo
feeTo 주소를 설정하는 함수
setFeeToSetter
feeToSetter 주소를 설정하는 함수

 

 

 

UniswapV2Factory.sol 코드 분석

pragma solidity =0.5.16;

import './interfaces/IUniswapV2Factory.sol';
import './UniswapV2Pair.sol';

//이 컨트랙트는 페어 교환을 생성합니다.
contract UniswapV2Factory is IUniswapV2Factory {
    // 이러한 상태 변수는 프로토콜 수수료를 구현하는 데 필요합니다(백서, 5페이지 참조). 
    // feeTo 주소는 프로토콜 수수료에 대한 유동성 토큰을 축적하며, feeToSetter는 feeTo를 다른 주소로 변경할 수 있는 주소입니다.
    address public feeTo; //유동성 토큰 축적 
    address public feeToSetter; //feeTo를 다른 주소로 변경할 수 있는 주소 

    // 두 개의 공개 상태 변수가 더 정의되어 있습니다: getPair와 allPairs. 
    mapping(address => mapping(address => address)) public getPair; //getPair는 토큰 주소 Pair을 해당 Pair의 컨트랙트 주소에 매핑하는 것
    address[] public allPairs; // allPairs는 이 컨트랙트에 의해 생성된 모든 Pair의 주소를 포함하는 배열입니다.

    //이벤트는 새 Pair이 생성될 때 발생하도록 정의됩니다. 이벤트에는 Pair이 구성하는 두 토큰의 주소, 새 Pair 컨트랙트의 주소, 새 Pair이 추가된 후 allPairs 배열의 길이가 포함됩니다.
    event PairCreated(address indexed token0, address indexed token1, address pair, uint);

    //생성자는 인자로 전달된 주소로 feeToSetter 주소를 설정하도록 정의됩니다.
    constructor(address _feeToSetter) public {
        feeToSetter = _feeToSetter;
    }


    //모든 Pair 배열의 길이를 반환하는 공용 함수 allPairsLength()가 정의되어 있습니다.
    function allPairsLength() external view returns (uint) {
        return allPairs.length;
    }

    function createPair(address tokenA, address tokenB) external returns (address pair) {

        // CreatePair는 Factory 컨트랙트의 주요함수로 두 개의 ERC-20 토큰간의 Pair 교환을 생성한다.
        // 누구나   이 함수를 호출할 수 있으며  Pair끼리 새롭게 교환할 때 유니스왑의 허가를 필요로하지 않는다. 
        // 토큰 A와 B는 달라야한다. 
        require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');
        // 삼항연산자에 따라 토큰0과 토큰1의 크기를 비교해서 다음값으로 할당한다. 
        (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);

        // 토큰0이 제로 어드레스가 아닌지 체크한다. 
        require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS');

        // getPair 함수를 호출해서 token0과 token1이 이미 있는 Pair가 아닌지 체크한다. 이미 존재하면 이 구문을 통과할 수 없다. 
        require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); // single check is sufficient
  
        // 새 컨트랙트를 생성하려면 컨트랙트를 생성하는 코드가 필요합니다(생성자 함수와 실제 컨트랙트의 EVM 바이트코드를 메모리에 쓰는 코드 모두).
        // 일반적으로 솔리디티에서는 addr = new <컨트랙트 이름>(<생성자 매개변수>)를 사용하면 컴파일러가 모든 것을 처리하지만,
        // 결정론적 컨트랙트 주소를 가지려면 CREATE2 op코드를 사용해야 합니다. 
        // 이 코드를 작성할 당시에는 솔리디티에서 해당 op코드를 아직 지원하지 않았기 때문에 수동으로 코드를 가져와야 했습니다. 이제 솔리디티에서 CREATE2를 지원하므로 더 이상 문제가 되지 않습니다.        
        bytes memory bytecode = type(UniswapV2Pair).creationCode;
        bytes32 salt = keccak256(abi.encodePacked(token0, token1));

        //솔리디티에서 아직 지원되지 않는 op코드는 인라인 어셈블리(새 탭에서 열기)를 사용하여 호출할 수 있습니다.
        assembly {
            pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }
        //초기화 함수를 호출하여 새 거래소에 어떤 두 개의 토큰을 교환할지 알려줍니다.
        IUniswapV2Pair(pair).initialize(token0, token1);

        //새 페어 정보를 상태 변수에 저장하고 이벤트를 발생시켜 새로운 페어 교환을 네트워크에 알립니다..
        getPair[token0][token1] = pair;
        getPair[token1][token0] = pair; 
        //allPair 배열에 삽입 
        allPairs.push(pair);
        //이벤트를 발생 
        emit PairCreated(token0, token1, pair, allPairs.length);
    }
     
    //다음 두 가지 기능을 통해 수수료 설정자는 수수료 수취인을 제어하고 수수료 설정자를 새 주소로 변경할 수 있습니다.

    //프로토콜 수수료로 유동성 토큰을 적립하는 함수 
    function setFeeTo(address _feeTo) external {
        require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
        feeTo = _feeTo;
    }


    //수수료를 변경할 수 있는 주소 함수 
    function setFeeToSetter(address _feeToSetter) external {
        require(msg.sender == feeToSetter, 'UniswapV2: FORBIDDEN');
        feeToSetter = _feeToSetter;
    }
}

출처:

 

https://ethereum.org/en/developers/tutorials/uniswap-v2-annotated-code/#uniswapv2factory

 

관련글 더보기