Smashing the stake for fun and profit

Smashing the stake for fun and profit

Learn how to stake coins you don’t own and make money

This article is for educational purposes only and does not constitute financial advice.

LSUs and LSULP

A stake operation on a Radix Validator returns a coin called Liquid Stake Unit (LSU); each Validator mints its own LSUs, which are different from those minted by any other Validator.
For this reason, Caviarnine has created the LSU Pool, a pool where you can deposit LSUs from different (but not all) Validators and receive a new coin called LSULP, which is a kind of generalized LSU.
The value of LSUs increases relative to XRD as the Validator collects emissions from the Radix network; the difference in value growth between Validators supported by the LSU Pool is very small, so LSULPs appreciate at the same rate.

Collateralized loans

A few dApps on the Radix network allow to take a load against a collateral that has to be deposited (locked) in the component.
It is interesting to observe that it’s possible to loop loans and borrows; we will use the receipt of lent out coins as a collateral for borrowing XRD from Weft.

The issue with collateralized loans is that the collateral must be available before taking the loan so we can’t just take an XRD loan, stake them and deposit the LSUs as a collateral. This is where flash loans will help.

Flash Loans

The flash loan is an uncollateralized time limited borrow operation that must be returned in the same transaction it was taken.
It is a very powerful feature offered by several components of the Radix ecosystem.
I will show you examples using the flash lending feature offered by Weft, but you can achieve the same result by requesting a flash loan from Ociswap or other dApps.

The component enures that we will return the flash lent coins by giving us a transient NFT too.
The transient NFT is a strange beast: it can’t be burned or deposited in the wallet; you need to return it to the component or the transaction will fail.

The flash allows us to get the XRD before taking the actual loan and stake the flash lent coins. Then we have to repay the flash loan immediately, the collateralized loan will provide the needed XRDs.

9x leveraged stake example

In this example we will do a 9x leveraged staking on the StakingCoins Validator, you can execute it from the developer console by replacing account_… with your actual account address:

CALL_METHOD
  Address("component_rdx1czmr02yl4da709ceftnm9dnmag7rthu0tu78wmtsn5us9j02d9d0xn")
  "take_flash_loan"
  Map<Address,Decimal>(
    Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") => Decimal("80000")
  )
;
CALL_METHOD
  Address("account_...")
  "withdraw"
  Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd")
  Decimal("10000")
;
TAKE_FROM_WORKTOP
  Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd")
  Decimal("0")
  Bucket("weft_fees")
;
TAKE_ALL_FROM_WORKTOP
  Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd")
  Bucket("xrd_to_stake")
;
CALL_METHOD
  Address("validator_rdx1sva6pmkgm5yacumw4p6k0xsfnqg598xkj9p4e2a58dl6gcrqpx7z86")
  "stake"
  Bucket("xrd_to_stake")
;
TAKE_ALL_FROM_WORKTOP
  Address("resource_rdx1t4pl597e7lp6flduhd3a6tp9jsqw2vzgyj9jxtk8y3dawum5aahap0")
  Bucket("lsu")
;
CALL_METHOD
  Address("component_rdx1cppy08xgra5tv5melsjtj79c0ngvrlmzl8hhs7vwtzknp9xxs63mfp")
  "add_liquidity"
  Bucket("lsu")
  Enum<0u8>()
;
TAKE_ALL_FROM_WORKTOP
  Address("resource_rdx1thksg5ng70g9mmy9ne7wz0sc7auzrrwy7fmgcxzel2gvp8pj0xxfmf")
  Bucket("lsulp")
;

CALL_METHOD
  Address("component_rdx1czmr02yl4da709ceftnm9dnmag7rthu0tu78wmtsn5us9j02d9d0xn")
  "deposit"
  Array<Bucket>(
    Bucket("lsulp")
  )
;
TAKE_ALL_FROM_WORKTOP
  Address("resource_rdx1t4p82pms6r20k87rscms728tekujacd0sgxyysk7yvl0jgf56gvjuc")
  Bucket("w2lsulp")
;
CALL_METHOD
  Address("component_rdx1cpy6putj5p7937clqgcgutza7k53zpha039n9u5hkk0ahh4stdmq4w")
  "create_cdp"
  Bucket("weft_fees")
  Enum<1u8>("leveraged_staking")
  Enum<1u8>("")
  Enum<1u8>("")
  Array<Bucket>(Bucket("w2lsulp"))
  Array<Bucket>()
  Map<Address,Decimal>(
    Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") => Decimal("80016")
  )
;
TAKE_ALL_FROM_WORKTOP
  Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd")
  Bucket("flash_loan_repayment")
;
TAKE_ALL_FROM_WORKTOP
  Address("resource_rdx1nfeyk5cmjep98zae9vhg067elm2necwsvdnngp3je62ahqstsa8x2x")
  Bucket("flash_loan_nft")
;
CALL_METHOD
  Address("component_rdx1czmr02yl4da709ceftnm9dnmag7rthu0tu78wmtsn5us9j02d9d0xn")
  "repay_flash_loan"
  Array<Bucket>(Bucket("flash_loan_repayment"))
  Bucket("flash_loan_nft")
;
CALL_METHOD
    Address("account_...")
    "deposit_batch"
    Expression("ENTIRE_WORKTOP")
;

Let’s analyze it step by step:

  1. The first method call requests a flash loan of XRD 80,000 to the Weft pool.
  2. The second call takes XRD 10,000 out of your wallet.
  3. The first TAKE_FROM_WORKTOP instruction creates an empty bucket that is required by Weft when creating a collateralized loan.
  4. TAKE_ALL_FROM_WORKTOP moves the 90,000 XRD in a bucket called xrd_to_stake.
  5. Next it sends all of the XRDs to the Validator which will mint an equivalent value in its LSUs.
  6. The next TAKE_ALL_FROM_WORKTOP moves the LSUs in a bucket called lsu.
  7. Next it deposits the LSUs in the LSU Pool and receives the LSULPs. The LSU Pool will also mint a receipt, you can safely ignore it.
  8. The following TAKE_ALL_FROM_WORKTOP moves the LSULP in a bucket called lsulp.
  9. Deposit the LSULPs on Weft. You get back w2-LSULP coins representing them.
  10. Put all of the w2-LSULP coins in a bucket called w2lsulp.
  11. Now it’s time to create a collateralized loan on Weft byt passing the component the empty bucket and the w2-LSULP bucket with will be deposited as a collateral. At the same time the transaction requests an XRD 80,016 loan against that collateral.
  12. Move the lent XRDs into the flash_loan_repayment bucket.
  13. Move the transient NFT in a bucket called flash_loan_nft.
  14. Return the flash lent XRDs (plus a small interest) and the flash loan NFT to the pool.
  15. Deposit both the Wefty (that represents the collateralized loan) and the receipt by the LSU Pool in the wallet.

Some of these steps are not strictly need since Weft directly accepts any LSU as a collateral. These extra steps will improve your performance in the Radix incentive campaign.

Profit?

We staked 90,000 XRD and obtained a loan of 80,016 XRD, withdrawing only 10,000 XRD from the wallet.
At the time of writing, the APY for staking is approximately 7%, while the interest payable on the XRD loan on Weft is approximately 4%.
The APY for this operation is (90,000 * 7% - 80,016 * 4%) / 10,000. This is bigger than 30%!

Many steps in the transaction add Activity Points to your position in the Radix incentives; probably the biggest one is step (9) that impacts the Lend XRD / LSUs category.

Radix incentives will also include in your Capital at work the LSULP deposited in Weft so your Multiplier will improve too.

Are there any risks?

As usual, when there’s a risk connected with all of the smart contracts you use (the Weft pool and the LSU pool); both are audited and quite battle tested.

Staking APY and loan interest rate change over time, should the loan interest rate get bigger than staking APY you can a loss. So you better keep an eye on the XRD loan interests on Weft.

As long as staking APY is bigger than loan interest rate there’s no liquidation risk since the value of the collateral grows faster than the interests.

How to unstake?

If you own 80,016 XRD + interests, you can simply return the loan, withdraw the collateral and unstake.

If not, you can:

  1. take a flash loan
  2. repay the loan
  3. withdraw the collateral
  4. swap the w2-LSULP for LSULP
  5. swap the LSULP for any LSU
  6. instant unstake on Caviarnine
  7. repay the flash loan

Not financial advise

Why this title?

In 1996, Aleph1 wrote the article “Smashing The Stack For Fun And Profit,” which remains a cornerstone of hacker culture.

Is it possible to apply this strategy to the ADDIX+FOMO Validator?

The ADDIX+FOMO Validator LSUs are not accepted by the LSU Pool so you must skip some steps of the procedure when doing leveraged staking on this Validator.

Due to 100% fees, this Validator LSUs are always 1:1 pegged to XRD.
Because of this, the deposited collateral will not increase its value against the borrowed XRDs, so there’s a bigger and bigger liquidation risk as interests are accrued.
This risk can be addressed by reducing leverage and monitoring the Total loans / Total collaterals ratio in this page; if this ratio exceeds 0.93 liquidation may occur.

5x leveraged staking on the ADDIX+FOMO Validator

CALL_METHOD
  Address("component_rdx1czmr02yl4da709ceftnm9dnmag7rthu0tu78wmtsn5us9j02d9d0xn")
  "take_flash_loan"
  Map<Address,Decimal>(
    Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") => Decimal("40000")
  )
;
CALL_METHOD
  Address("account_...")
  "withdraw"
  Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd")
  Decimal("10000")
;
TAKE_FROM_WORKTOP
  Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd")
  Decimal("0")
  Bucket("weft_fees")
;
TAKE_ALL_FROM_WORKTOP
  Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd")
  Bucket("xrd_to_stake")
;
CALL_METHOD
  Address("validator_rdx1swez5cqmw4d6tls0mcldehnfhpxge0mq7cmnypnjz909apqqjgx6n9")
  "stake"
  Bucket("xrd_to_stake")
;
TAKE_ALL_FROM_WORKTOP
  Address("resource_rdx1t4d3ka2x2j35e30gh75j6hma6fccwdsft88h2v2ul4qmqshnwjmxf7")
  Bucket("lsu")
;
CALL_METHOD
  Address("component_rdx1cpy6putj5p7937clqgcgutza7k53zpha039n9u5hkk0ahh4stdmq4w")
  "create_cdp"
  Bucket("weft_fees")
  Enum<1u8>("leveraged_staking")
  Enum<1u8>("")
  Enum<1u8>("")
  Array<Bucket>(Bucket("lsu"))
  Array<Bucket>()
  Map<Address,Decimal>(
    Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") => Decimal("40008")
  )
;
TAKE_ALL_FROM_WORKTOP
  Address("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd")
  Bucket("flash_loan_repayment")
;
TAKE_ALL_FROM_WORKTOP
  Address("resource_rdx1nfeyk5cmjep98zae9vhg067elm2necwsvdnngp3je62ahqstsa8x2x")
  Bucket("flash_loan_nft")
;
CALL_METHOD
  Address("component_rdx1czmr02yl4da709ceftnm9dnmag7rthu0tu78wmtsn5us9j02d9d0xn")
  "repay_flash_loan"
  Array<Bucket>(Bucket("flash_loan_repayment"))
  Bucket("flash_loan_nft")
;
CALL_METHOD
    Address("account_...")
    "deposit_batch"
    Expression("ENTIRE_WORKTOP")
;

How to unstake?

Caviarnine instant unstake is not applicable to this Validator so you can’t use a flash loan to close this position.
Because of this, you really need 40008 + interest XRD to unstake in one single step.

A multi step alternative is possible but it may require months:

  1. return part of the loan
  2. withdraw part of the collateral
  3. unstake it
  4. wait for the unstake to complete
  5. use the unstaked XRDs to go back to step (1)

Another alternative is to sell the Wefty on Trove.
A buyer can use XRDVision (the second to last button in the top bar) to know what’s inside a Wefty.

Not financial advise

It’s now possible to perform instant unstake from the ADDIX+FOMO Validator thanks to the Liquify dApp.

This makes it possible to use a flash loan to unstake from a leveraged position for this Validator too.