---
# System prepended metadata

title: 20230522 - Uniswap

---

# 20230522 - Uniswap 


## createPair 


``` solidity 
    function createPair(address tokenA, address tokenB) external returns (address pair) {
        require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');
        // 會先排序過
        (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        require(token0 != address(0), 'UniswapV2: ZERO_ADDRESS');
        require(getPair[token0][token1] == address(0), 'UniswapV2: PAIR_EXISTS'); // single check is sufficient
        bytes memory bytecode = type(UniswapV2Pair).creationCode;
        // 所以不管 createPair 傳入的token 順序為何，這邊 salt 都是一樣的
        bytes32 salt = keccak256(abi.encodePacked(token0, token1));

        // create2 創造的時候所需要的資訊跟 acconut 的 nonce 無關
        // salt = oxff (constant) + deployer + keccak256(abi.encodePacked(token0, token1)) + init code hash 
        assembly {
            // 因為 bytes 為非固定長度的資料
            // 所以 solidity 在儲存資料時會預留前 32bytes 來表示bytes 的長度
            // 所以這邊要從第 32 byte 開始讀取資料
            // (這個行為針對動態的資料型別，像是字串也是這樣)
            pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }
        
        IUniswapV2Pair(pair).initialize(token0, token1);
        getPair[token0][token1] = pair;
        getPair[token1][token0] = pair; 
        allPairs.push(pair);
        emit PairCreated(token0, token1, pair, allPairs.length);
    }
```

### lock modifier
- 用來預防重送攻擊
``` solidity
 modifier lock() {
        require(unlocked == 1, 'UniswapV2: LOCKED');
        unlocked = 0;
        _;
        unlocked = 1;
    }
```
- 未來如果合約內有要 external call + 更改內部狀態的操作，要先更改內部狀態，再去做 external call (避免重送攻擊)
- 也可使用 [OpenZeppelin-ReentrancyGuard](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)


## UniswapV2Library 
### pairFor 
``` solidity 
    // Create2(value, offset, size, salt)
    function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {
        (address token0, address token1) = sortTokens(tokenA, tokenB);
        pair = address(uint(keccak256(abi.encodePacked(
                hex'ff',
                factory,
                keccak256(abi.encodePacked(token0, token1)),
                // 如果有在 local 改 uniswap contract code ，要注意這邊也需要更新，因為 init code 會不同
                hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f' // init code hash
            ))));
    }

```




