Authors: Markus @m.laeng
First publication date: 2025/04/17
stXTZ - liquid staked Tezos XTZ from stacy.fi
Refactored proposal
This proposal follows proposal YIP-08 which was accepted by the youves DAO community but could not be executed, due to an error in the submitted lambdas, as outlined in Post Mortem #9 (read more). This governance proposal is a refactored and fully tested governance proposal. It achieves the exact same changes as YIP-08 aimed to do.
Stacy.fi
stacy.fi is a new staking platform, built for the youves DAO, which allows users to earn staking rewards on Tezos while maintaining full liquidity of their funds, by holding stXTZ tokens.
Introduction
Tezos’ Paris B protocol upgrade came with the novelty that holders of XTZ needed to decide if they want to continue using delegation with less rewards than before or to stake their XTZ for full rewards, but then also accept their XTZ being locked for 14 days after unstaking. This protocol upgrade had a big impact on DeFi platforms like youves: smart contracts which lock XTZ would not be able to profit of staking, therefore these products suddenly became a lot less attractive for users.
To counter this, youves core contributors from Ubinetic teamed up with Acurast to come up with a solution similar to staking tokens in other ecosystems, for example stETH (Lido) on Ethereum: Users deposit the native currency (XTZ) and receive a token (stXTZ) which accrues the baking rewards.
stXTZ properties
stXTZ is FA2 compliant token which represents a share of the stXTZ staking pool. stXTZ has a value expressed in XTZ which can easily be calculated by dividing the sum of all staked XTZ in the stXTZ pool by the total supply of stXTZ.
For example, if the solution holds 11000 staked XTZ and stXTZ has a supply of 10000, the value or price of 1 stXTZ is 1.1 XTZ.
As staking rewards are continuously received by the pool of stXTZ bakers, the price of stXTZ slowly increases - staking rewards are accruing in the stXTZ token. A view on the pool contract always returns the current price of stXTZ/XTZ.
For example, if the solution now receives 5 XTZ in rewards, it holds 11005 staked XTZ, but the supply of stXTZ remains at 10000. Therefor the new price of 1 stXTZ is 1.1005 XTZ.
But where there are rewards, there are risks as well: If any of the stXTZ bakers gets slashed for double baking or other punishable events while participating in Tezos validation, the price of stXTZ can suddenly decrease, because slashing immediately reduces the staked balance.
How does it work?
Stacy.fi was built on the following components:
Smart contracts
Pool contract
The pool contract keeps track of the staked balance and the intermediate states between depositing and staking as well as unstaking and withdrawal of funds. It mints or burns stXTZ, when triggered by a manager, an automated signer (read more about their role below). The pool contract also holds a list of allowed managers. The pool mainly consists of queues which ensure to keep track of staking/minting and unstaking/burning processes. If a user decides to unstake stXTZ, the pool ensures that Tezos’ current waiting period for unstaking operations is enforced.
Mainnet deployment: KT1FRN2RmitUkyyovtjRMrU1G9zwKzgESXm8
Token contract
The stXTZ token contract is an FA2 compliant token contract, which can be used in any DeFi protocol on Tezos. stXTZ, which accrues the staking rewards in it’s value, is the token with ID 0. The stXTZ staking pool contract can mint and burn stXTZ tokens.
Mainnet deployment: KT1KXKhkxDezoa8G3WvPtsrgNTs5ZQwhpYZN
Gasstation contract
Additionally youves contributors created a simple gasstation contract, which can be called by a list of allowed entities, like the managers or other future signers or bots. This solves an issue which youves contributors encountered in the past, when using automated signers: they can run dry and it’s easier to monitor and refill one address instead of whole list of signers.
Mainnet deployment: KT1FThqponAJi56EAiotSS64egW2eThGxDA6
Manager contract
The manager contract contains a list of Acurast signers which are sharing the same private key in a secured P2P network. They are acting as one Tezos account towards the protocol. The manager contract also contains the script which runs on the Acurast signers. Only Acurast signers whitelisted in this contract and running this exact script can interact with the protocol.
Mainnet deployment: KT198mB5VXfeftAXbo3dqkEMjR3oWShEoazY
stXTZ/XTZ cpmm
Alongside with the staking pool setup, a CPMM was deployed, which allows users to sell stXTZ directly against XTZ, without having to wait 14 days (under the current Tezos protocol), while other users can buy stXTZ at a discount in order to unstake or use them.
Mainnet deployment: KT1GyHkqPbSkzfkzifxqKgGrsbohAUHK8Utb
Managers
Managers act as bakers towards the protocol, but they are not running Tezos baking nodes, they are using the consensus keys of baking nodes run by third parties. One manager is a cluster of Acurast signers. They observe the pool contract for new deposit or withdrawal requests. If such a request is detected, the manager executes a transaction which triggers staking of XTZ and minting of stXTZ or unstaking of XTZ and burning of stXTZ.
The manager guarantees that these operation pairs (staking+minting or unstaking+burning) are executed in a single atomic transaction. This guarantees that the staking operation takes place at the same time as the mint operation when XTZ is being exchanged for stXTZ. Likewise, the burning of stXTZ takes in the same block as as the unstake operation is injected.
Baking node(s)
Initially the solution starts with one baking node, run by Ubinetic AG, by experienced baking node operators. Mid-Term, this could be developed into a more distributed setup of more operators.
Reward Distribution
As baking rewards are received, managers constantly monitor the balances and update the tracked balances in the pool contract. This means the amount of XTZ backing all stXTZ tokens in circulation is gradually increasing, which, in turn, causes the value of 1 stXTZ token (expressed in XTZ) to rise slowly. In the event of a slashing, the managers also track the balance change in the stXTZ pool contract, and the value of 1 stXTZ token may decrease.
Additionally, each time the signers detect a balance increase due to baking rewards, 20% of these rewards will be immediately minted as stXTZ at the current stXTZ/XTZ price as the pool contract calculates it on every update. These stXTZ tokens will be sent to the Youves DAO reward collector. From there, 50% of the collected stXTZ rewards will be distributed as compensation to the baking node provider, while the other 50% will be retained by the DAO for future YOU token buybacks, in the same way current rewards from engines and swaps are managed. This means that 80% of the staking rewards will be accrued inside the stXTZ token. These initial parameters can be adjusted through a governance vote as the protocol evolves.
Is it safe to interact with this?
All involved smart contracts and Acurast scripts have undergone extensive testing and a security audit by both internal developers and an external third party. The smart contract logic has been simplified as much as possible to ensure safe and predictable operation. However, certain risks may still remain at the code level, system level, and due to the nature of staking on Tezos. Slashings can occur if the baker does not function as intended.
How is the youves DAO involved?
stacy.fi, the stXTZ solution, was developed by the youves core contributors from Ubinetic AG, on behalf of the youves DAO. stXTZ will serve as an additional source of rewards for the youves DAO. If the governance vote is accepted, the youves DAO, which consists of the combined vote weight of all YOU token stakers, will be the sole entity responsible for administering the stXTZ pool contract, the token contract, and the manager contract.
All fees collected by the stXTZ solution are gathered by the reward collecting contract, which is controlled by the Youves DAO and the Youves keyholders.
YIP vote
In order to launch the stacy.fi platform and include it into the youves DAO, the youves DAO is asked to vote on the following proposal:
Summary
Youves DAO members are requested to vote on the addition of the suite of stXTZ smart contracts to the youves DAO. By voting for this proposal, the youves DAO will be the sole entity to administer the stXTZ pool contract, the stXTZ token contract, the stXTZ manager contract, the stXTZ/XTZ CPMM contract and will share administrative rights on the stXTZ gasstation contract. Also, the youves DAO reward collector contract will be set as the reward recipient of the stXTZ pool rewards.
Methodology
stXTZ Pool contract
- Accept the DAO to be administrator on the stXTZ pool contract
- Remove the contract deployer from the list of administrators on the stXTZ pool contract
- Set the youves reward collector contract as the reward recipient
stXTZ Token contract
- Remove the contract deployer as admin from the token contract, so the DAO remains as the sole admin
stXTZ Gasstation contract
- Accept the DAO to be administrator
- Remove the deployer from the list of administrators
stXTZ Manager contract
- Accept the DAO to be administrator
- Remove the deployer from the list of administrators
stXTZ/XTZ CPMM contract
- Accept the DAO to be administrator and replace the deployer
Proposal
This proposal will execute the following operations:
Contract Name | Contract Address | Entrypoint called | Effect |
---|---|---|---|
stXTZ Pool Contract | KT1FRN2RmitUkyyovtjRMrU1G9zwKzgESXm8 | set_administrator | sets the DAO contract as admin |
stXTZ Pool Contract | KT1FRN2RmitUkyyovtjRMrU1G9zwKzgESXm8 | remove_administrator | removes the deployer from admin |
stXTZ Pool Contract | KT1FRN2RmitUkyyovtjRMrU1G9zwKzgESXm8 | set_reward_recipient | sets the DAO reward collector as reward recipient |
stXTZ Token Contract | KT1KXKhkxDezoa8G3WvPtsrgNTs5ZQwhpYZN | set_administrator | sets the DAO as admin and replaces the deployer |
stXTZ Gasstation Contract | KT1FThqponAJi56EAiotSS64egW2eThGxDA6 | set_administrator | sets the DAO contract as admin |
stXTZ Gasstation Contract | KT1FThqponAJi56EAiotSS64egW2eThGxDA6 | remove_administrator | removes the deployer from admin |
stXTZ Manager Contract | KT198mB5VXfeftAXbo3dqkEMjR3oWShEoazY | set_administrator | sets the DAO contract as admin |
stXTZ Manager Contract | KT198mB5VXfeftAXbo3dqkEMjR3oWShEoazY | remove_administrator | removes the deployer from admin |
stXTZ/XTZ CPMM Contract | KT1GyHkqPbSkzfkzifxqKgGrsbohAUHK8Utb | accept_admin_proposal | sets the DAO admin |
Code
Source code in SmartPy
GitHub repo with the source code
import smartpy as sp
def DAO_V2_YIP_9(unit):
sp.result(
sp.list(
[
# script updater
# remove deployer from script updater's admins
execute_remove_admin(
sp.address("KT198mB5VXfeftAXbo3dqkEMjR3oWShEoazY"),
sp.address("tz1LZPp4akY2Cphth1WeXsmXDC8bCt9LrrLG"),
),
# script updater
# set DAO as admin
execute_set_administrator_unit(
sp.address("KT198mB5VXfeftAXbo3dqkEMjR3oWShEoazY")
),
# gas station
# remove deployer from gas station's admins
execute_remove_admin(
sp.address("KT1FThqponAJi56EAiotSS64egW2eThGxDA6"),
sp.address("tz1LZPp4akY2Cphth1WeXsmXDC8bCt9LrrLG"),
),
# gas station
# set DAO as admin
execute_set_administrator_unit(
sp.address("KT1FThqponAJi56EAiotSS64egW2eThGxDA6"),
),
# cpmm
# set reward recipient (cpmm)
execute_set_new_reward_recipient(
sp.address("KT1GyHkqPbSkzfkzifxqKgGrsbohAUHK8Utb"),
sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"),
),
# cpmm
# set DAO as admin
execute_accept_admin_proposal_cash_cpmm(
sp.address("KT1GyHkqPbSkzfkzifxqKgGrsbohAUHK8Utb"),
),
# token
# remove deployer
execute_remove_administrator(
sp.address("KT1KXKhkxDezoa8G3WvPtsrgNTs5ZQwhpYZN"),
sp.address("tz1LZPp4akY2Cphth1WeXsmXDC8bCt9LrrLG"),
sp.nat(0),
),
# pool
# remove deployer from pool's admins
execute_remove_admin(
sp.address("KT1FRN2RmitUkyyovtjRMrU1G9zwKzgESXm8"),
sp.address("tz1LZPp4akY2Cphth1WeXsmXDC8bCt9LrrLG"),
),
# pool
# set reward recipient (pool)
execute_set_new_reward_recipient(
sp.address("KT1FRN2RmitUkyyovtjRMrU1G9zwKzgESXm8"),
sp.address("KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"),
),
# pool
# set DAO admin in pool
execute_set_administrator_unit(
sp.address("KT1FRN2RmitUkyyovtjRMrU1G9zwKzgESXm8"),
),
]
)
)
Compiled Michelson code
GitHub repo with the compiled code
{ DROP; NIL operation; PUSH address "KT1FRN2RmitUkyyovtjRMrU1G9zwKzgESXm8"; CONTRACT %set_administrator unit; IF_NONE { PUSH int 343; FAILWITH } {}; PUSH mutez 0; UNIT; TRANSFER_TOKENS; CONS; PUSH address "KT1FRN2RmitUkyyovtjRMrU1G9zwKzgESXm8"; CONTRACT %set_reward_recipient address; IF_NONE { PUSH int 246; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1FRN2RmitUkyyovtjRMrU1G9zwKzgESXm8"; CONTRACT %remove_administrator address; IF_NONE { PUSH int 300; FAILWITH } {}; PUSH mutez 0; PUSH address "tz1LZPp4akY2Cphth1WeXsmXDC8bCt9LrrLG"; TRANSFER_TOKENS; CONS; PUSH address "KT1KXKhkxDezoa8G3WvPtsrgNTs5ZQwhpYZN"; CONTRACT %remove_administrator (pair address nat); IF_NONE { PUSH int 113; FAILWITH } {}; PUSH mutez 0; PUSH (pair address nat) (Pair "tz1LZPp4akY2Cphth1WeXsmXDC8bCt9LrrLG" 0); TRANSFER_TOKENS; CONS; PUSH address "KT1GyHkqPbSkzfkzifxqKgGrsbohAUHK8Utb"; CONTRACT %accept_admin_proposal unit; IF_NONE { PUSH int 327; FAILWITH } {}; PUSH mutez 0; UNIT; TRANSFER_TOKENS; CONS; PUSH address "KT1GyHkqPbSkzfkzifxqKgGrsbohAUHK8Utb"; CONTRACT %set_reward_recipient address; IF_NONE { PUSH int 246; FAILWITH } {}; PUSH mutez 0; PUSH address "KT1FPmpucXoiX7ZLahj1V1E5tRah1XvcnkZB"; TRANSFER_TOKENS; CONS; PUSH address "KT1FThqponAJi56EAiotSS64egW2eThGxDA6"; CONTRACT %set_administrator unit; IF_NONE { PUSH int 343; FAILWITH } {}; PUSH mutez 0; UNIT; TRANSFER_TOKENS; CONS; PUSH address "KT1FThqponAJi56EAiotSS64egW2eThGxDA6"; CONTRACT %remove_administrator address; IF_NONE { PUSH int 300; FAILWITH } {}; PUSH mutez 0; PUSH address "tz1LZPp4akY2Cphth1WeXsmXDC8bCt9LrrLG"; TRANSFER_TOKENS; CONS; PUSH address "KT198mB5VXfeftAXbo3dqkEMjR3oWShEoazY"; CONTRACT %set_administrator unit; IF_NONE { PUSH int 343; FAILWITH } {}; PUSH mutez 0; UNIT; TRANSFER_TOKENS; CONS; PUSH address "KT198mB5VXfeftAXbo3dqkEMjR3oWShEoazY"; CONTRACT %remove_administrator address; IF_NONE { PUSH int 300; FAILWITH } {}; PUSH mutez 0; PUSH address "tz1LZPp4akY2Cphth1WeXsmXDC8bCt9LrrLG"; TRANSFER_TOKENS; CONS }
SHA256 Hash of the Michelson code
14f68f9698b51e269aa991cf250b60229d12225399922c69ff19f05ae5af1b65