-
Notifications
You must be signed in to change notification settings - Fork 9
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
Define producer APIs #17
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly ok, but generated messages would contain obsolete _
signed before names.
use cosmwasm_schema::cw_serde; | ||
use cosmwasm_std::Addr; | ||
|
||
/*** state ***/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would personally split this types.rs
into state.rs
(for state types) and msg.rs
(for message-related-types - especially those are actual response messages).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kind of agree.. but when I see lots of files of < 30 lines, it seems easier to join.
Can split them later on when they grow.
// instantiate or call stake on existing | ||
todo!(); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kind of want a query to look up my proxy contract if it exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question. account
seems wrong here, as this proxy handles only one address (that of the owner
) over only one chain (that corresponding to denom
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The native-staking
contract is a look up between owners and proxy contracts (and visa versa).
It will need to store that state, I will add queries for that
/// TODO: can we do that with contract API? | ||
/// Or better they use cosmjs native delegation queries with this proxy address | ||
#[msg(query)] | ||
fn unbonding(&self, _ctx: QueryCtx, _account: String) -> Result<ClaimsResponse, ContractError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need the account
argument? Only one per contract?
} | ||
|
||
/// Returns the maximum percentage that can be slashed | ||
/// TODO: any way to query this from the chain? or we just pass in InstantiateMsg??? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could probably do this with Stargate queries? A bit torn on what to do here... IMO querying it could help reduce edge cases. Perhaps we could make it an enum and have a struct that can handle the query logic?
Just spit-balling here...
pub enum MaxSlashPercentage {
/// A fixed value, this cannot be changed for the life of the contract
Hardcoded { max_slash: Decimal },
/// Queries the max percentage that can be slashed via Stargate
StargateQuery { },
}
pub struct MaxSlash {
max_slash: MaxSlashPercentage
}
impl MaxSlash {
fn get_max_slash_percentage (&self, ctx: ExecCtx) -> Result<Decimal, ContractError> {
match self.max_slash {
// If hardcoded we just return it
MaxSlashPercentage::HardCoded { max_slash } => Ok(max_slash)
// If not we do the stargate query
MaxSlashPercentage::StargateQuery {} => {
// do stargate query and return value
}
}
}
}
My hesitation with Stargate Queries is that they wouldn't work for chains using CosmWasm but not the SDK...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StargateQueries don't work for SDK chains either. They have been disabled for over a year since someone found non-determinism in them and halted Juno.
I will leave it as hardcoded for now, and make an issue for v1 to revisit this
} | ||
|
||
#[cw_serde] | ||
pub struct BalanceResponse { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit on name, but this is returning more info than just a balance. Maybe AccountResponse
and QueryMsg::Account
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few minor comments, but this is the right direction from my perspective.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Reviewed the native-staking-proxy
contract. Will review the rest in another iteration.
@@ -0,0 +1,17 @@ | |||
# Native Staking Proxy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 'proxy' staking contract would be the one referred as 'External Staking' in the Architecture doc, right?
I'll do a small PR on the Arch doc with some clarifications / details.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not yet reflected in that doc. We should probably update the flow charts to include it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just reference "Local Staking" in the doc, which is an interface.
"Native Staking" + "Native Staking Proxy" group would together implement the "Local Staking" functionality.
} | ||
} | ||
|
||
/// The caller of the instantiation will be the native-staking contract. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the Architecture doc, the caller will be the vault contract. Can you clarify?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so the way this works is: vault -> native-staking -> native-staking-proxy
.
The user story behind this is simple: as a user, I want to cross-stake my native asset as well as stake it to secure the native chain.
Why do we have the proxy? Because we want the user to be able to manage their native-stake just like they would normally (with the ability to vote, etc.). If all assets are sitting in one giant contract, this becomes difficult.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The caller of this proxy contract will be the native staking contract.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. It's called 'proxy' because it's an agent that acts on behalf of the user for some actions like unbonding, etc.
Thanks for the clarifications.
&self, | ||
ctx: InstantiateCtx, | ||
denom: String, | ||
owner: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this imply one proxy contract per user / address? This would be the original owner / provider of the funds, if I understand correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. One proxy contract per user.
Flow:
- I deposit 1 $Juno into the vault
- I decided to stake it to secure the Juno chain (not cross-staking yet)
- A proxy account that I control is created for me where by I will be able to manage my stake
ctx: InstantiateCtx, | ||
denom: String, | ||
owner: String, | ||
validator: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is needed because of auto-staking, below. I think it makes sense for robustness, that any initially sent funds here are already being staked. As this is the entire purpose of this impl.
|
||
// set owner as recipient of future withdrawls | ||
let set_withdrawl = DistributionMsg::SetWithdrawAddress { | ||
address: config.parent.into_string(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
address: config.parent.into_string(), | |
address: config.owner.into_string(), |
?
If I understand this properly:
sender
would (typically) be the vault contract, and becomesparent
here.owner
would be (typically) set by the vault to the original user, the provider of the funds.
In principle it should be possible to instantiate one of these contracts directly, and that is not a problem. The vault would be just a convenient way to do it, AFAIK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, typo. And good catch (why we need tests and real implementation). I just started sketching it out
// instantiate or call stake on existing | ||
todo!(); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question. account
seems wrong here, as this proxy handles only one address (that of the owner
) over only one chain (that corresponding to denom
).
Co-authored-by: Mauro Lacy <maurolacy@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Only minor syntax / naming stuff.
@@ -0,0 +1,42 @@ | |||
[package] | |||
name = "mesh-native-staking-proxy" | |||
description = "Per-user proxy contract to manage your stake deposited into native-staking" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼
|
||
The user then interacts directly with the proxy up to the point of a complete unbonding, when they can send the now-liquid tokens | ||
to `native-staking`, which will immediately release those on the vault. This makes `native-staking` more a pass-through node and | ||
"air traffic controller", while logic to interact with staking and governance is placed inside the `native-staking-proxy`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼 Good explanation.
#[error("The leinholder doesn't have any claims")] | ||
UnknownLeinholder, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and elsewhere, do you mean 'lien'?
#[error("The leinholder doesn't have any claims")] | |
UnknownLeinholder, | |
#[error("The lien holder doesn't have any claims")] | |
UnknownLienholder, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems leinholder
is an actual word from a quick search...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, it seems to me that the right or more common expression is 'lien holder'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mauro is correct. Lien is what I intended:
"a right to keep possession of property belonging to another person until a debt owed by that person is discharged"
#[error("The leinholder doesn't have enough claims for the action")] | ||
InsufficientLein, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#[error("The leinholder doesn't have enough claims for the action")] | |
InsufficientLein, | |
#[error("The lien holder doesn't have enough claims for the action")] | |
InsufficientLien, |
pub struct LeinAddr { | ||
pub leinholder: Addr, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub struct LeinAddr { | |
pub leinholder: Addr, | |
pub struct LienAddr { | |
pub lien_holder: Addr, |
pub struct Lein { | ||
pub leinholder: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub struct Lein { | |
pub leinholder: String, | |
pub struct Lien { | |
pub lien_holder: String, |
Co-authored-by: Mauro Lacy <maurolacy@users.noreply.github.com>
Part of #2
Closes #3
Closes #4
Provide Rust APIs for how the contracts interact