Curve oracle
Curve 풀을 기반으로 토큰 가격 정보를 제공한다.
TWAP
스왑이나 유동성 공급 등의 인터렉션이 발생하면 _update 함수를 호출하고 TWAP 정보를 최신화한다. price_cumulative_last 변수에 누적 금액을 계산한다. 업데이트 시마다 현재 balance * 지난 초 만큼을 누적한다.
사용법
MetaPool.get_price_cumulative_last()호출하여 최신 누적 금액 정보 조회MetaPool.block_timestamp_last()호출하여 최신 누적 금액 업데이트 시점 조회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 balancesMetaPool.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