Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RUNstake: borrow RUN against staked BLD #3788

Closed
8 of 10 tasks
Tracked by #5062
michaelfig opened this issue Sep 2, 2021 · 22 comments · Fixed by #5165
Closed
8 of 10 tasks
Tracked by #5062

RUNstake: borrow RUN against staked BLD #3788

michaelfig opened this issue Sep 2, 2021 · 22 comments · Fixed by #5165
Assignees
Labels
audit-restival Purple Team review of RUN Protocol BLD-Boost Issues relating to the BLD Boost contract and UI Core Economy OBSOLETE in favor of INTER-protocol enhancement New feature or request Inter-protocol Overarching Inter Protocol restival to be done before RUN Protocol Purple Team festival
Milestone

Comments

@michaelfig
Copy link
Member

michaelfig commented Sep 2, 2021

What is the Problem Being Solved?

per RUNStake User Stories section by @rowgraus and co 5 Apr:

As a BLD staker with no RUNstake position, I need to be able to open a position by placing a lien on my staked BLD and receiving RUN

  • Process should feel familiar to vaults
  • Subject to RUN per BLD limits
  • Subject to asset level debt limit

As a BLD staker with an existing RUNStake position, I need to be able to manage it; that is: adjust my RUN debt and BLD lien within the bounds of the contract.

  • Process should feel familiar to vaults

As a BLD staker with an existing RUNStake position, I need to be able to close it entirely

  • May be combined with/handled by the ‘manage’ use case above

Description of the Design

Like vaultFactory, the runStake contract provides loans and charges interest and minting fees; differences include:

  1. The loan is secured by a lien on staked BLD, not by transferring collateral.
  2. There is no liquidation. Instead, the staked BLD generates a stream of RUN rewards which can be used to pay down the debt. (See RUN rewards go first to pay off getRUN balance #4244 for more on that part.)

Design notes in runStake/README.md include a sequence diagram of interactions between a user/dapp, walletBridge, runStake (and attestation), and Cosmos SDK.

We use a semi-fungible copyBag token to represent lien attestations: the items is the address where BLD is staked and the quantity is the lien (delta).

  • add getLiened() to attMaker so the wallet can get it before taking out a loan.

related work:

Security Considerations

  • line of credit involves use of the RUN mint
  • BLD liens merit care

Test Plan

nice to have:

  • generate sequence diagram from a test and check against runstake/README.md
@michaelfig michaelfig added the enhancement New feature or request label Sep 2, 2021
@michaelfig michaelfig added this to the Mainnet: Phase 1 - Treasury Launch milestone Sep 2, 2021
@Chris-Hibbert Chris-Hibbert added Governance Governance Beta Core Economy OBSOLETE in favor of INTER-protocol labels Sep 2, 2021
@dckc
Copy link
Member

dckc commented Oct 25, 2021

With @JimLarson and @Chris-Hibbert , I drew a sequence diagram on a whiteboard. I'm trying to refine it closer to the details of our platform.

IMG_20211021_133921418

@startuml runLoC

treasury -> walletBridge: getPurseBalance("BLD")
walletBridge --> treasury: 5000

treasury -> attestation: getMax(ag123)
attestation -> golang: getAccountState(ag123)
golang --> attestation: "4000 BLD liened"
attestation  --> treasury: "4000 BLD liened"

treasury -> attestation: getReturnableAttestation(450 RUN)
attestation -> golang: setLienedAmount(4500 BLD)
golang --> attestation: yes

treasury -> attestation: give: 0; want: attestation 450
attestation --> walletBridge: attestation 

walletBridge -> runLoC: attestation 

runLoC -> priceAuthority: BLD price?
priceAuthority --> runLoC: 0.50RUN

runLoC -> mintRUN: mintGains(450)
mintRUN --> runLoC: 450RUN

runLoC --> walletBridge: 450RUN

@enduml

runLoC

@dckc
Copy link
Member

dckc commented Oct 27, 2021

refined in discussion...

@startuml runLoC

treasury -> walletBridge: getPurseBalance("BLD")
walletBridge --> treasury: 5000
note right
collateralization rate: 10x
BLD price 0.5RUN
end note

treasury -> attestation: getMaxAvailable(ag123)
attestation -> golang: getAccountState(ag123)
golang --> attestation: "4000 BLD liened"
attestation  --> treasury: "4000 BLD liened"

treasury -> attestation: getReturnableAttestation(500 BLD)

note right
user asks for 25 RUN
end note

attestation -> golang: setLienedAmount(4500 BLD)
golang --> attestation: yes

attestation -> treasury: attestation 500 BLD

treasury -> runLoC: give: attestation 500 BLD; want: 25 RUN
note right
user may "want" less than the full line
end note


runLoC -> mintRUN: mintGains(25)
mintRUN --> runLoC: 25RUN

runLoC --> walletBridge: 25RUN

@enduml

amount borrowed vs. amount liened

amount borrowed should be adjustable independent of amount liened. hm.
nice-to-have

authority to create a lien

in the user bundle?

@dckc
Copy link
Member

dckc commented Nov 15, 2021

@dckc dckc added the BLD-Boost Issues relating to the BLD Boost contract and UI label Dec 10, 2021
@dckc
Copy link
Member

dckc commented Dec 14, 2021

I had the impression that getting a RUN LoC would require the user to accept 2 offers:

  1. to get an attestation (which creates a lien against their BLD)
  2. to trade the attestation for some RUN

and then another 2 to release the lien:

  1. to pay off the line of credit and get the attestation back
  2. to return the attestation and release the lien

After discussion with @Chris-Hibbert and reviewing the code, we determined that getting an attestation doesn't involve an offer. Just like the wallet takes offer descriptions from dapps and makes them into actual offers by filling in payments taken from purses, the wallet should fill in an attestation payment by getting an attestation. (IOU a separate wallet issue.) Bootstrap will have to provide the wallet with an attestationMaker bound to the user's cosmos address.

The attestation contract currently uses invitations / offers to return attestations, but it might as well just have a public API method to do so. Then, just like the wallet takes payouts and puts them in a user's purse, it should recognize attestation payouts and return them using the public method.

cc @samsiegart @michaelfig @rowgraus @dtribble @JimLarson

@dckc dckc added the wallet label Dec 15, 2021
@dckc
Copy link
Member

dckc commented Dec 16, 2021

Brainstorm: Virtual Purses for Extendable Liens

the main limitation of the existing attestation-based design, that the lien has to be paid off before it can be extended, has been escalated to its own issue: #4245

notes from discussion with @samsiegart on novel purse in place of attMaker...

// both do
publicLienableBLDBrand = board.get...;

// wallet does
purse2 = home.myBLDVirtualPurse
purse3 = home.myLienableBLDVirtualPurse

purse3.getCurrentAmount() === { brand: home.myPersonalBrand, value: 6000n };
display(purse3.getCurrentAmount()) // cross golang bridge
// display 0 liened instead of 6000 lienable?

// dapp does
attAmount = {brand: publicLienableBLDBrand, value: 4000n};
walletBridge.suggestOffer({ give: { Attestation: attAmount });

// wallet does
if (amount.brand === publicLienableBLDBrand) { // or: if (invitation is from RunLoC) { ...?
  const myAmount = { brand: home.myPersonalBrand, value: amount.value}
}
pmt = purse3.withdraw(myAmount) // golang setLien(4000)

E(zoe).offer(... { give: { Lien: pmt }, want: { RUN: run(100) }});

purse3.getCurrentAmount() === { brand: home.myPersonalBrand, value: 2000n };

// to release the lien:
purse3.deposit({ brand: home.myPersonalBrand, value: 4000n]})

// to decrease the lien:
purse3.deposit({ brand: home.myPersonalBrand, value: 1500n]})

p.s. switching out the brand wouldn't preserve offer-safety. The dApp would have to use myPersonalBrand too.

@JimLarson
Copy link
Contributor

Note that attempting to decrease or release the lien could fail unless the current debt is low enough. Also, the available-to-lien balance is accountState.Bonded - accountState.Liened, which could be negative in cases of unbonding or slashing. If the balance is limited to a Nat, then there will be the case where the balance is zero, but remains zero after a nonzero deposit. There will have to be an additional information source to show the remaining negative balance.

@dckc dckc changed the title Using the attestation contract for voting and line of credit getRUN: borrow RUN against staked BLD Jan 4, 2022
@dckc dckc removed the Beta label Jan 18, 2022
@rowgraus rowgraus added the MN-1 label Jan 19, 2022
@dckc dckc added the Inter-protocol Overarching Inter Protocol label Jan 24, 2022
@dckc
Copy link
Member

dckc commented Jan 25, 2022

sync'd up with @samsiegart . For a getRUN demo, we have a bunch of pieces missing:

cc @michaelfig @rowgraus

@dckc
Copy link
Member

dckc commented Jan 25, 2022

@michaelfig and I worked out an approach using local-chain mode (hence with the golang bridge). Using the code I just pushed to #4092, we start the chain using decentral-demo-config.json thus:

cd dapp-directory
CHAIN_BOOTSTRAP_VAT_CONFIG=@agoric/vats/decentral-demo-config.json agoric start local-chain --reset -v >,local-chain.log 2>&1 &

That version of bootstrap starts the economy.

Then we start our ag-solo:

agoric start local-solo --reset -v

home.attMaker was added as part of starting the economy, but when we try to make an attestation, we recall that we have no BLD staked:


command[3] E(home.myAddressNameAdmin).getMyAddress()
history[3] "agoric1h5e69sgw9nygtealll0hhkc53pkwxs3vtspt8l"

command[4] home.attMaker
history[4] [Object Alleged: attMaker]{}

command[5] E(home.agoricNames).lookup('brand', 'BLD')
history[5] [Object Alleged: BLD brand]{}

command[6] brand = {BLD: history[5]}
history[6] {"BLD":[Object Alleged: BLD brand]{}}

command[7] E(home.attMaker).makeAttestation({brand: brand.BLD, value: 100n})
history[7]
Promise.reject("Error: Only (an object) was bonded and unliened, but an attestation was attempted for (an object)")

We get provisioned with 13BLD (13_000_000 ubld). We stake 9BLD:

# put agd in our path
export PATH=~/projects/agoric/agoric-sdk/golang/cosmos/build/:$PATH

# get our local key name (ag-solo)
agd keys list --home=_agstate/agoric-servers/local-solo-8000/ag-cosmos-helper-statedir --keyring-backend=test

# get validator address:
agd --home=_agstate/agoric-servers/local-solo-8000/ag-cosmos-helper-statedir query staking validators

# stake 9BLD:
agd --home=_agstate/agoric-servers/local-solo-8000/ag-cosmos-helper-statedir --keyring-backend=test tx staking delegate  agoricvaloper1jnvutw68khpeshvcrxychpz9y8ztp4nfwyl8dt 9000000ubld --from ag-solo --gas auto --gas-adjustment 1.5 -b block --chain-id agoric

Now we can get an attestation in the REPL:

command[8] E(home.attMaker).makeAttestation({brand: brand.BLD, value: 6000000n})
history[8] [Object Alleged: BldLienAtt payment]{}

@dckc
Copy link
Member

dckc commented Mar 11, 2022

I spent a little time this week with @andrey-kuprianov of @informalsystems building a diagram. Thanks, @arirubinstein , for transcribing it to mermaid:
https://gist.github.com/arirubinstein/8a87ded49744a38861b6ec8697a6191e

cc @jessysaurusrex

@jessysaurusrex
Copy link
Contributor

My new security pitch about diagramming in five words:

Agoric: We have art projects 🎨

@dckc dckc changed the title getRUN: borrow RUN against staked BLD RUNstake: borrow RUN against staked BLD Mar 14, 2022
@turadg
Copy link
Member

turadg commented Mar 22, 2022

Another diagrams (from #4741 (comment) )

sequenceDiagram
    actor dapp
    participant walletBridge
    participant attestation
    participant runStake
    participant golang

    note right of dapp: How dapp finds the current state

    note right of walletBridge: walletBridge is provided to dapps and controlled by Wallet UI
    dapp ->>+ walletBridge: getPurseBalance("BLD")
    dapp -->> walletBridge: 5000

    note right of attestation: ag123 is a cosmos address
    dapp ->> attestation: getMax(ag123)
    attestation ->> golang: getAccountState(ag123)
    note right of golang: Cosmos supports lien
    golang -->> attestation: account status in which 4000 BLD liened
    attestation  -->> dapp: account status in which 4000 BLD liened
    note right of dapp: Treasury now knows

    note right of dapp: Want to get 450 RUN by liening 500 BLD
    dapp ->> walletBridge: getReturnableAttestation(want: 450 RUN, give: 500 BLD-Att)
    note right of walletBridge: Blocks on user approval in wallet
    walletBridge ->> attestation: makeAttestation(500 BLD)
    attestation ->> golang: setLienedAmount(4000 + 500 BLD)
    golang -->> attestation: ACK or throws

    attestation -->> walletBridge: Payment of 500 BLD-Att liened on ag123

    walletBridge ->> runStake: offer w/payment for {give: 500 BLD-Att, want: 450 RUN} 

    runStake --> walletBridge: Payment for 450RUN and offerResult
    walletBridge --> dapp: notifiers from offerResult
Loading

@Tartuffo Tartuffo added this to the Mainnet 1 milestone Mar 23, 2022
@Tartuffo
Copy link
Contributor

Tartuffo commented Apr 5, 2022

@dckc is #3991 no longer a blocker? What more needs to be done to close this out?

@dckc
Copy link
Member

dckc commented Apr 5, 2022

@dckc is #3991 no longer a blocker?

I don't think so, but that's a product requirements question; it's not my role to decide.

What more needs to be done to close this out?

Good question. I'm struggling to figure out the scope of this issue. It could be as small as the contract component (which is done, or at least: merged to master) or it could include integration with the wallet and bootstrap.

More later...

@samsiegart
Copy link
Contributor

Good question. I'm struggling to figure out the scope of this issue. It could be as small as the contract component (which is done, or at least: merged to master) or it could include integration with the wallet and bootstrap.

+1 for smaller scoped issues, it's easier to understand what is and isn't done that way

@dckc
Copy link
Member

dckc commented Apr 15, 2022

empty bug: https://gist.github.com/samsiegart/da0a5a519cc20ec343d962abae1317ef

notifiers need to look like:

    publicNotifiers: {
      vault: vault.getNotifier(),
      asset: assetNotifier,
    },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
audit-restival Purple Team review of RUN Protocol BLD-Boost Issues relating to the BLD Boost contract and UI Core Economy OBSOLETE in favor of INTER-protocol enhancement New feature or request Inter-protocol Overarching Inter Protocol restival to be done before RUN Protocol Purple Team festival
Projects
None yet
9 participants