YIP-6 Change oracle on the uUSD/uBTC pool to the on demand oracle / change reward collector

Author: Markus @m.laeng
First publication date: 2024/09/17
Forum:

Summary

This YIP proposes to change the oracle of the uUSD/uBTC pool KT1Cy1wwHbW1NMawnQCrfXMBtuwXSsidEDg2 from the previous ‘Generic Oracle’ to the new ‘On Demand oracle’. Additionally, it proposed some houskeeping tasks to further reduce maintenance, by changing the reward collecting contract on some contracts to the newest one in use.

Rationale

Change Oracle of the uUSD / uBTC Pool

In an effort to remove technical debt, youves core contributors are working to move all active youves smart contracts from the older ‘generic oracle’ to the new ‘on demand oracle’.

Youves started with an oracle built by Ubinetic. This oracle is still in use for most contracts which need an external price feed in order to function. It is called the ‘Generic Oracle’ as it serves several prices in a generic way. This solution was also the birth seed for Acurast, the decentralized cloud computing solution. Acurast was built on the same basic ideas and principles and has evolved since then.

In the meantime, the oracles which can be built with Acurast are much more advanced and flexible than the existing oracle solution. Therefore core contributors are working to replace the ‘Generic Oracle’ with a newer version, built on Acurast. The newer version already exists and is also in use on some of the newer youves smart contracts. It was referred to as the ‘On Demand Oracle’ in past blog posts, as it is capable of serving prices not only in a predefined frequency, but also on demand.

The current setup means that core contributors need to maintain two oracles. In order to cut down on that maintenance, all contracts are being moved to the On Demand Oracle, which means to set a new oracle contract on engine and swap contracts. While this change can be mostly done by signatures from the youves keyholders, which also have admin rights, some contracts can only be changed by the DAO V2. This YIP aims to change the oracle of one remaining swap which can only be changed by the DAO.

Change reward recipient contract

Buybacks of YOU tokens in favor of the YOU stakers are made by collecting fees from swaps and interest rate from engines. These fees are automatically sent to a reward collecting contract upon user interaction. The reward collector contract comes with some features, which allow for semiautomated buybacks. All engines and swap contracts have an entry which links to the reward collector contract. In the past, several reward collector contracts have been used, each one being more advanced than the previous one. Currently some swaps are still sending their rewards to an older version of the reward collector, causing maintenance works from time to time. In order to reduce technical debt and maintenance, this proposal aims to change these swaps to send to the newest reward collector.

Swaps affected are listed below.

Methodology

Change Oracle of the uUSD / uBTC Pool

In order to change the oracle contract on the uUSD/uBTC swap, the entrypoint setTargetOracle has to be called on the uUSD / uBTC swap contract KT1STLQKxiRtAh1e7DZhu1xUTAJ7KLpV9Rru. The previous proxy oracle contract KT1CUrtJYbZvgTJ9dcBowVZxFQVRHFM6UyiA (which pulled the BTCUSD price from the generic oracle KT1KzdDAVkEwLUhemZBp8asMJ9nvfbp6eV9C) will be replaced with a new proxy oracle contract KT1Cy1wwHbW1NMawnQCrfXMBtuwXSsidEDg2 (which pulls the price from KT1B74ywpG3nX2F3ZgpYi4MnsyuoYyQtQTAn which itself is a proxy oracle contract for the on demand oracle KT1ExbCyFbsvPQTUitHAK7HSfYkJgiCtBGpM).

These proxy oracle contracts act as forwarders for the price data and will allow the administrators, to replace one side of this chain of contracts, with only one change, instead of having to change the oracle on all contracts where it is used (as it is now). This also reduces maintenance tasks in the future.

The future standard setup for such a chain of oracle contracts is:

target contract (where the price is used) ← target proxysource proxysource contract (where the price is stored after being fetched)

Change reward recipient contract

In ordert to change the reward collector contract on these swaps, the entrypoint set_reward_recipient will be called by DAO v2. As parameter, the newest reward collector KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB will be passed in. For one contract the call is a bit different and inclludes more parameters, but does essentially the same (Checker cCHF, the last in teh below list).

Proposal

In the table below you can see what effect this proposal will have on youves contracts.

Contract Name Contract Address Entrypoint called Effect
uUSD/uBTC swap KT1STLQKxiRtAh1e7DZhu1xUTAJ7KLpV9Rru setTargetOracle change target oracle to KT1Cy1wwHbW1NMawnQCrfXMBtuwXSsidEDg2
uBTC/wBTC.e swap KT1WgguedKZWucrdRKQXaRECEPMZennaVPck setRewardRecipient change reward recipient to KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB
uxtz/xtz V1 swap KT1CkpDuwCFrnoqTam6upYiPBiFNsSEVbBei setRewardRecipient change reward recipient to KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB
uxau/uusd target flat curve KT1Ad5yJzoiRRdMJPvhJiPJ7Cq8WbJnCS7bg setRewardRecipient change reward recipient to KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB
uxtz/tez V3 swap KT1SPUvH5khHtirTEVeECiKrnh4FFXxWZ6ui setRewardRecipient change reward recipient to KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB
usdt/tez target flat curve swap KT1PkygK9CqgNLyuJ9iMFcgx1651BrTjN1Q9 setRewardRecipient change reward recipient to KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB
ubtc/uusd target flat curve swap KT1STLQKxiRtAh1e7DZhu1xUTAJ7KLpV9Rru setRewardRecipient change reward recipient to KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB
kUSD/uUSD swap KT1AVbWyM8E7DptyBCu4B5J5B7Nswkq7Skc6 setRewardRecipient change reward recipient to KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB
USDtz/uUSD swap KT1Xbx9pykNd38zag4yZvnmdSNBknmCETvQV setRewardRecipient change reward recipient to KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB
tzBTC/uBTC swap KT1XvH5f2ja2jzdDbv6rxPmecZFU7s3obquN setRewardRecipient change reward recipient to KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB
USDt/uUSD swap KT1UJBvm4hv11Uvu6r4c8zE5K2EfmwiRVgsm setRewardRecipient change reward recipient to KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB
Checker cCHF KT1LrEJsaTR5vMdwjvASTtFPUbk2wnX3P166 set_contracts change reward recipient to KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB

Code

Source code in SmartPy

GitHub repo with the source code

import smartpy as sp
import utils.addresses as addresses

def set_target_swap_oracle(swap, oracle):
    swap_ep = sp.contract(
        sp.TAddress,
        swap,
        entry_point="setTargetOracle"
    ).open_some(message="Invalid entrypoint: setTargetOracle")
    return sp.transfer_operation(oracle, sp.mutez(0), swap_ep)

def execute_set_contracts_checker(
    engine_address,
    ctez,
    ctez_cfmm,
    governance,
    liquidation_tracker,
    oracle,
    reward_pool
):
    engine_contract = sp.contract(
        sp.TPair(
            sp.TPair(
                sp.TPair(sp.TAddress, sp.TAddress),
                sp.TPair(sp.TAddress, sp.TAddress)
            ),
            sp.TPair(sp.TAddress, sp.TAddress)),
        engine_address,
        entry_point="set_contracts"
    ).open_some()

    payload = sp.pair(
        sp.pair(
            sp.pair(ctez, ctez_cfmm),
            sp.pair(governance, liquidation_tracker)
        ),
        sp.pair(oracle, reward_pool)
    )
    return sp.transfer_operation(payload, sp.mutez(0), engine_contract)

def execute_set_reward_recipient(flat_curve_address, reward_recipient):
    flat_curve_contract = sp.contract(
        sp.TAddress, flat_curve_address, entry_point="setRewardRecipient"
    ).open_some()

    return sp.transfer_operation(reward_recipient, sp.mutez(0), flat_curve_contract)

def update_target_flat_curve_oracles(unit):
    sp.set_type(unit, sp.TUnit)
    sp.result(sp.list([
        set_target_swap_oracle(
            addresses.UUSD_UBTC_EXCHANGE,
            sp.address("KT1Cy1wwHbW1NMawnQCrfXMBtuwXSsidEDg2")
        ),
        execute_set_reward_recipient(
            sp.address("KT1CkpDuwCFrnoqTam6upYiPBiFNsSEVbBei"), 
            sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")),
        execute_set_reward_recipient(
            sp.address("KT1WgguedKZWucrdRKQXaRECEPMZennaVPck"), 
            sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")),
        execute_set_reward_recipient(
            sp.address("KT1Ad5yJzoiRRdMJPvhJiPJ7Cq8WbJnCS7bg"), 
            sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")),
        execute_set_reward_recipient(
            sp.address("KT1SPUvH5khHtirTEVeECiKrnh4FFXxWZ6ui"), 
            sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")),
        execute_set_reward_recipient(
            sp.address("KT1PkygK9CqgNLyuJ9iMFcgx1651BrTjN1Q9"), 
            sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")),
        execute_set_reward_recipient(
            sp.address("KT1STLQKxiRtAh1e7DZhu1xUTAJ7KLpV9Rru"),
            sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")),
        execute_set_reward_recipient(
            sp.address("KT1AVbWyM8E7DptyBCu4B5J5B7Nswkq7Skc6"), 
            sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")),
        execute_set_reward_recipient(
            sp.address("KT1Xbx9pykNd38zag4yZvnmdSNBknmCETvQV"), 
            sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")),
        execute_set_reward_recipient(
            sp.address("KT1XvH5f2ja2jzdDbv6rxPmecZFU7s3obquN"),
            sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")),
        execute_set_reward_recipient(
            sp.address("KT1UJBvm4hv11Uvu6r4c8zE5K2EfmwiRVgsm"),
            sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")),
        
        execute_set_contracts_checker(
            engine_address = sp.address("KT1LrEJsaTR5vMdwjvASTtFPUbk2wnX3P166"),
            ctez = sp.address("KT1SjXiUX63QvdNMcM2m492f7kuf8JxXRLp4"),
            ctez_cfmm = sp.address("KT1LpDGYxbpabK3A6rqpVW4TSwVjwg9Zjp7K"),
            governance = sp.address("KT1Ge5usHwAAH12PDxwP8FFYMdbMbXSRXSz4"),
            liquidation_tracker = sp.address("KT1PJkeVGVJAH4LRjWRbLU39D9EY7GkTfibQ"),
            oracle = sp.address("KT1TYSXHmkGu7QSsiQKCahWpKtG3JtFgN2kf"),
            reward_pool = sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")
        )
    ]))
    

Compiled Michelson code

GitHub repo with the compiled code

{ DROP; NIL operation; PUSH address "KT1LrEJsaTR5vMdwjvASTtFPUbk2wnX3P166"; CONTRACT %set_contracts (pair (pair (pair address address) (pair address address)) (pair address address)); IF_NONE { PUSH int 1484; FAILWITH } {}; PUSH mutez 0; PUSH (pair (pair (pair address address) (pair address address)) (pair address address)) (Pair (Pair (Pair "KT1SjXiUX63QvdNMcM2m492f7kuf8JxXRLp4" "KT1LpDGYxbpabK3A6rqpVW4TSwVjwg9Zjp7K") (Pair "KT1Ge5usHwAAH12PDxwP8FFYMdbMbXSRXSz4" "KT1PJkeVGVJAH4LRjWRbLU39D9EY7GkTfibQ")) (Pair "KT1TYSXHmkGu7QSsiQKCahWpKtG3JtFgN2kf" "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB")); TRANSFER_TOKENS; CONS; PUSH address "KT1UJBvm4hv11Uvu6r4c8zE5K2EfmwiRVgsm"; CONTRACT %setRewardRecipient address; IF_NONE { PUSH int 200; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1XvH5f2ja2jzdDbv6rxPmecZFU7s3obquN"; CONTRACT %setRewardRecipient address; IF_NONE { PUSH int 200; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1Xbx9pykNd38zag4yZvnmdSNBknmCETvQV"; CONTRACT %setRewardRecipient address; IF_NONE { PUSH int 200; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1AVbWyM8E7DptyBCu4B5J5B7Nswkq7Skc6"; CONTRACT %setRewardRecipient address; IF_NONE { PUSH int 200; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1STLQKxiRtAh1e7DZhu1xUTAJ7KLpV9Rru"; CONTRACT %setRewardRecipient address; IF_NONE { PUSH int 200; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1PkygK9CqgNLyuJ9iMFcgx1651BrTjN1Q9"; CONTRACT %setRewardRecipient address; IF_NONE { PUSH int 200; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1SPUvH5khHtirTEVeECiKrnh4FFXxWZ6ui"; CONTRACT %setRewardRecipient address; IF_NONE { PUSH int 200; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1Ad5yJzoiRRdMJPvhJiPJ7Cq8WbJnCS7bg"; CONTRACT %setRewardRecipient address; IF_NONE { PUSH int 200; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1WgguedKZWucrdRKQXaRECEPMZennaVPck"; CONTRACT %setRewardRecipient address; IF_NONE { PUSH int 200; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1CkpDuwCFrnoqTam6upYiPBiFNsSEVbBei"; CONTRACT %setRewardRecipient address; IF_NONE { PUSH int 200; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1STLQKxiRtAh1e7DZhu1xUTAJ7KLpV9Rru"; CONTRACT %setTargetOracle address; IF_NONE { PUSH string "Invalid entrypoint: setTargetOracle"; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1Cy1wwHbW1NMawnQCrfXMBtuwXSsidEDg2"; TRANSFER_TOKENS; CONS }

SHA256 Hash of the Michelson code

a4c210d0708fe845341a4d203717518a91ba5b192df6ee8decad393b579d3d8b

Will YIP-6 lead to the uBTC/uUSD swapping pool be redeployed? The liquidity TVL will restart from zero?

hey @bitxia,

No, that is not necessary. The price source was just replaced.