판게아 풀 생성하기
현재 판게아에 배포되어 있는 모든 풀의 정보를 가져오는 예제입니다. 판게아의 풀은 생성과 예치가 나뉘어져 있습니다. 풀을 먼저 생성한 후 풀에 자산을 예치해야 스왑이 정상적으로 진행됩니다.
주의 생성된 풀은 삭제할 수 없고, 한번 생성한 파라미터(token0/token1/swapFee/tickSpacing)로 재생성은 불가능합니다. Test Network나 local network에서 충분히 테스트하시길 바랍니다.
/// MasterDeployer__factory는 판게아 프로토콜의 types/ 내에 있는 typechain 객체입니다.
/// typechain와 ethers.js를 통해 JS 환경에서 간편하게 interaction할 수 있습니다.
import {ConcentratedLiquidityPoolFactory__factory, MasterDeployer__factory} from "./types";
import {BigNumberish, ethers} from "ethers";
import {BigNumber} from "@ethersproject/bignumber";
/// 주소는 네트워크 별로 달라야 합니다
const masterDeployerAddress = "0xEB4B1CE03bb947Ce23ABd1403dF7C9B86004178d";
const poolFactoryAddress = "0x3d94b5E3b83CbD52B9616930D33515613ADfAd67";
/// web3 Provider (metamask provider / jsonRPC provider 등)
const provider = ethers.getDefaultProvider();
async function createPool(
token0Address:string, /// 풀을 구성할 토큰 0의 주소
token1Address:string, /// 풀을 구성할 토큰 1의 주소
swapFee:number, /// 스왑 수수료 (단위 : 1000 = 0.1%)
tickSpacing:number, /// 틱의 간격
/// 현재 가능한 스왑 수수료와 틱 간격의 조합은 (10_000, 100) / (2_000, 20) / (600, 6) / (100, 1)
amount0:BigNumberish, /// 토큰 가격 산정을 위해, 상대 갯수 지정
amount1:BigNumberish /// amount0 : amount1 = 1 : 10 이면, price = (√10 * 2^96)
) {
const masterDeployer = await MasterDeployer__factory.connect(
masterDeployerAddress, provider
);
const factory = await ConcentratedLiquidityPoolFactory__factory.connect(
poolFactoryAddress, provider
);
// validation rule [1]
// > 풀 생성 시 토큰 주소는 token0Address < token1Address를 만족해야 합니다.
if(token0Address.toLowerCase() > token1Address.toLowerCase()){
throw new Error("invalid token order");
}
// validation rule [2]
// > 현재 가능한 스왑 수수료와 틱 간격의 조합은 아래와 같습니다.
// (1% , 100) (0.2%, 20) (0.06%, 6) (0.01%, 1)
// 틱 간격에 대한 자세한 설명은 https://docs.pangeaswap.com/developers/concept-overview/price-tick
// 에서 참고하시길 바랍니다.
if (! (await factory.availableFeeAndTickSpacing(swapFee, tickSpacing))) {
throw Error("Not ABLE FEE & TICK SPACING");
}
// [1] Price 계산하기
// 풀 형성 시 두 토큰의 상대 가격을 지정해야 합니다.
// 풀에서의 price는 `√(token1/token0*2^192)`의 형태로 관리됩니다.
const price = sqrtValue(
BigNumber.from(2).pow(192).mul(amount1).div(amount0)
);
/// [2] 판게아 풀 생성하기
/// 동일한 페어에 대해, 동일한 swapFee & tickSpacing이 존재하는 경우,
/// 풀 생성은 실패합니다.
const tx = await masterDeployer.deployPool(poolFactoryAddress,
ethers.utils.defaultAbiCoder.encode(
["address", "address", "uint24", "uint160", "uint24"],
[token0Address, token1Address, swapFee, price, tickSpacing]
);
await tx.wait();
/// [3] 생성한 풀의 주소 가져오기
/// (token0Address, token1Address, swapFee, tickSpacing) 별로 unique 합니다.
const poolFactory = await ConcentratedLiquidityPoolFactory__factory.connect(
poolFactoryAddress, provider
);
const poolAddress = poolFactory.configAddress(
ethers.utils.defaultAbiCoder.encode(
["address", "address", "uint24", "uint24"],
[token0Address, token1Address, swapFee, tickSpacing]
);
console.log(`생성한 풀의 주소 : ${poolAddress}`);
}
/**
* 제곱근 계산
*/
function sqrtValue(value) {
const ONE = BigNumber.from(1);
const TWO = BigNumber.from(2);
let x = BigNumber.from(value);
let z = x.add(ONE).div(TWO);
let y = x;
while (z.sub(y).isNegative()) {
y = z;
z = x.div(z).add(z).div(TWO);
}
return y;
}
Last updated