Curve oracle

Curve 풀을 기반으로 토큰 가격 정보를 제공한다.

TWAP

스왑이나 유동성 공급 등의 인터렉션이 발생하면 _update 함수를 호출하고 TWAP 정보를 최신화한다. price_cumulative_last 변수에 누적 금액을 계산한다. 업데이트 시마다 현재 balance * 지난 초 만큼을 누적한다.

사용법

  1. MetaPool.get_price_cumulative_last() 호출하여 최신 누적 금액 정보 조회
  2. MetaPool.block_timestamp_last() 호출하여 최신 누적 금액 업데이트 시점 조회
  3. MetaPool.get_twap_balances(과거 누적 가격 정보, 현재 누적 가격 정보, 과거~현재 지난 시간) 호출하여 TWAP 계산
    @view
    @external
    def get_twap_balances(_first_balances: uint256[N_COINS], _last_balances: uint256[N_COINS], _time_elapsed: uint256) -> uint256[N_COINS]:
        balances: uint256[N_COINS] = empty(uint256[N_COINS])
        for x in range(N_COINS):
            balances[x] = (_last_balances[x] - _first_balances[x]) / _time_elapsed
        return balances
  4. MetaPool.get_dy(보낼 토큰 인덱스, 받을 토큰 인덱스, 보낼 토큰 양, get_twap_balances 결과) 호출해서 보낼 토큰과 같은 가치의 받을 토큰 개수를 리턴받음
    @view
    @external
    def get_dy(i: int128, j: int128, dx: uint256, _balances: uint256[N_COINS] = [0,0]) -> uint256:
        """
        @notice Calculate the current output dy given input dx
        @dev Index values can be found via the `coins` public getter method
        @param i Index value for the coin to send
        @param j Index valie of the coin to recieve
        @param dx Amount of `i` being exchanged
        @param _balances which balance to use, current, previous, or twap
        @return Amount of `j` predicted
        """
        rates: uint256[N_COINS] = [self.rate_multiplier, Curve(BASE_POOL).get_virtual_price()]
        xp: uint256[N_COINS] = _balances
        if _balances[0] == 0:
            xp = self.balances
        xp = self._xp_mem(rates, xp)
     
        x: uint256 = xp[i] + (dx * rates[i] / PRECISION)
        y: uint256 = self.get_y(i, j, x, xp)
        dy: uint256 = xp[j] - y - 1
        fee: uint256 = self.fee * dy / FEE_DENOMINATOR
        return (dy - fee) * PRECISION / rates[j]

주의할점

  • get_twap_balances 호출 시 TWAP window가 너무 짧으면 가격 조작에 취약하다.
  • 누적 가격 정보는 인터렉션이 발생했을 때 (유동성을 공급했거나 스왑을 하는 등) 업데이트 된다. 즉, 인터렉션이 없다면 가격이 오랫동안 업데이트되지 않을 수 있다.
    • remove_liquidity 을 파라미터 0과 함께 호출하여 가격을 최신화할 필요가 있다.
  • 누적 balance 를 직접 사용하는 것보다는 누적 price (TWAP)를 사용해야 가격 조작에 안전하다.

tags: price oracle, twap oracle, curve