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

auto-compound staking #139

Merged
merged 8 commits into from
Jan 23, 2022
Merged

auto-compound staking #139

merged 8 commits into from
Jan 23, 2022

Conversation

ben2x4
Copy link
Contributor

@ben2x4 ben2x4 commented Jan 18, 2022

Implementation to allow for auto-compounding staking rewards. Currently no test, but passes all existing tests so behavior is equivalent when not compounding.

Compouding will work by users being assigned an ownership percentage of the pool. If tokens are sent to the adress and not staked they are adding to the pools assets. When the user withdraws their funds they receive their share of the pool.

Math works as follows:

Stake Ownership = Staked Amount * (Total ownership / Contract Balance)

Unstaking Amount = (Ustaked Ownership / Total Ownership) * Contract Balance

Not feeling so well today, so my apologies if explanation is not great.

@ben2x4
Copy link
Contributor Author

ben2x4 commented Jan 19, 2022

Pushed query functions and tests. I think names for queries could be worked on but current implementation should not break any existing contracts that query this contract.

@JakeHartnell JakeHartnell requested a review from Callum-A January 19, 2022 20:17
|bal| -> StdResult<Uint128> { Ok(bal.unwrap_or_default().checked_sub(amount)?) },
)?;
STAKED_TOTAL.update(
deps.storage,
_env.block.height,
env.block.height,
|total| -> StdResult<Uint128> { Ok(total.unwrap_or_default().checked_sub(amount)?) },
)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think there may be a bug here :)

Setup

  • Alice has one token staked
  • Bob has one token staked
  • The contract a two token balance
  • The contract has a one day unstaking duration

Unstaking

  • Alice unstakes her token
    • Alice is entitled to 1 token (1 token unstaking / 2 staked tokens * 2 tokens in contract)
    • There is now one token staked
    • The contract has a balance of two tokens until 1 day passes and Alice can claim her token
  • Bob sees that Alice has unstaked her token and also unstakes his
    • Bob is entitled to 2 tokens (1 token unstaking / 1 staked tokens * 2 tokens in contract)
    • There are now zero tokens staked

Claiming

  • Alice claims her one token - success. Contract balance is now 1.
  • Bob claims his two tokens - failure. The contract has one token remaining.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the event that the contract does have the funds to cover Bob's withdrawal here Bob is taking money from the pool I believe :)

Could be entirely off base / not understanding something here though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch, this issue should be resolve. The contract now tracks its balance internally. When funding the contract the sender must use a cw20 send msg with a new message type fund

Copy link
Contributor

@0xekez 0xekez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just need to use BALANCE in the queries and then I think we're good to go.

amount: Uint128::new(100),
release_at: AtHeight(12349)
}]
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome to have this as a test. Thanks!

pub fn query_staked_value(deps: Deps, env: Env, address: String) -> StdResult<StakedValueResponse> {
let config = CONFIG.load(deps.storage)?;
let address = deps.api.addr_validate(&address)?;
let balance: cw20::BalanceResponse = deps.querier.query_wasm_smart(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think we need to move to using BALANCE here as well


pub fn query_total_value(deps: Deps, env: Env) -> StdResult<TotalValueResponse> {
let config = CONFIG.load(deps.storage)?;
let balance: cw20::BalanceResponse = deps.querier.query_wasm_smart(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

query_wasm_smart -> BALANCE :)

let _env = mock_env();
let amount = Uint128::new(100);
unstake_tokens(&mut app, &staking_addr, info, amount).unwrap();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worthwhile to add a query here to make sure that ADDR2 has the appropriate staked value.

@ben2x4
Copy link
Contributor Author

ben2x4 commented Jan 22, 2022

Great suggestions, all point should be resolved

@JakeHartnell
Copy link
Member

Great suggestions, all point should be resolved

@ezekiiel have another look?

Copy link
Contributor

@0xekez 0xekez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! This is a super nice design.

@JakeHartnell JakeHartnell merged commit af5d264 into main Jan 23, 2022
@JakeHartnell JakeHartnell deleted the compound-staking branch January 23, 2022 06:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants