Skip to content
This repository has been archived by the owner on Jan 11, 2024. It is now read-only.

Commit

Permalink
ipc-345: add unstake command
Browse files Browse the repository at this point in the history
  • Loading branch information
adlrocha committed Oct 25, 2023
1 parent 25e0607 commit d42370a
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions ipc/cli/src/commands/subnet/join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,43 @@ pub struct StakeSubnetArgs {
)]
pub collateral: f64,
}

/// The command to unstake in a subnet from validator
pub struct UnstakeSubnet;

#[async_trait]
impl CommandLineHandler for UnstakeSubnet {
type Arguments = UnstakeSubnetArgs;

async fn handle(global: &GlobalArguments, arguments: &Self::Arguments) -> anyhow::Result<()> {
log::debug!("join subnet with args: {:?}", arguments);

let mut provider = get_ipc_provider(global)?;
let subnet = SubnetID::from_str(&arguments.subnet)?;
let from = match &arguments.from {
Some(address) => Some(Address::from_str(address)?),
None => None,
};
provider
.unstake(subnet, from, f64_to_token_amount(arguments.collateral)?)
.await
}
}

#[derive(Debug, Args)]
#[command(
name = "unstake",
about = "Remove collateral to an already joined subnet"
)]
pub struct UnstakeSubnetArgs {
#[arg(long, short, help = "The address that unstakes in the subnet")]
pub from: Option<String>,
#[arg(long, short, help = "The subnet to release collateral from")]
pub subnet: String,
#[arg(
long,
short,
help = "The collateral to unstake from the subnet (in whole FIL units)"
)]
pub collateral: f64,
}
4 changes: 3 additions & 1 deletion ipc/cli/src/commands/subnet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::commands::subnet::send_value::{SendValue, SendValueArgs};
use crate::{CommandLineHandler, GlobalArguments};
use clap::{Args, Subcommand};

use self::join::{StakeSubnet, StakeSubnetArgs};
use self::join::{StakeSubnet, StakeSubnetArgs, UnstakeSubnet, UnstakeSubnetArgs};
use self::leave::{Claim, ClaimArgs};

pub mod create;
Expand Down Expand Up @@ -44,6 +44,7 @@ impl SubnetCommandsArgs {
Commands::Kill(args) => KillSubnet::handle(global, args).await,
Commands::SendValue(args) => SendValue::handle(global, args).await,
Commands::Stake(args) => StakeSubnet::handle(global, args).await,
Commands::Unstake(args) => UnstakeSubnet::handle(global, args).await,
Commands::Claim(args) => Claim::handle(global, args).await,
}
}
Expand All @@ -59,5 +60,6 @@ pub(crate) enum Commands {
Kill(KillSubnetArgs),
SendValue(SendValueArgs),
Stake(StakeSubnetArgs),
Unstake(UnstakeSubnetArgs),
Claim(ClaimArgs),
}
18 changes: 18 additions & 0 deletions ipc/provider/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,24 @@ impl IpcProvider {
conn.manager().stake(subnet, sender, collateral).await
}

pub async fn unstake(
&mut self,
subnet: SubnetID,
from: Option<Address>,
collateral: TokenAmount,
) -> anyhow::Result<()> {
let parent = subnet.parent().ok_or_else(|| anyhow!("no parent found"))?;
let conn = match self.connection(&parent) {
None => return Err(anyhow!("target parent subnet not found")),
Some(conn) => conn,
};

let subnet_config = conn.subnet();
let sender = self.check_sender(subnet_config, from)?;

conn.manager().unstake(subnet, sender, collateral).await
}

pub async fn leave_subnet(
&mut self,
subnet: SubnetID,
Expand Down
28 changes: 27 additions & 1 deletion ipc/provider/src/manager/evm/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ impl SubnetManager for EthSubnetManager {
let collateral = collateral
.atto()
.to_u128()
.ok_or_else(|| anyhow!("invalid min validator stake"))?;
.ok_or_else(|| anyhow!("invalid collateral amount"))?;

let address = contract_address_from_subnet(&subnet)?;
log::info!(
Expand All @@ -334,6 +334,32 @@ impl SubnetManager for EthSubnetManager {
Ok(())
}

async fn unstake(
&self,
subnet: SubnetID,
from: Address,
collateral: TokenAmount,
) -> Result<()> {
let collateral = collateral
.atto()
.to_u128()
.ok_or_else(|| anyhow!("invalid collateral amount"))?;

let address = contract_address_from_subnet(&subnet)?;
log::info!(
"interacting with evm subnet contract: {address:} with collateral: {collateral:}"
);

let signer = Arc::new(self.get_signer(&from)?);
let contract =
subnet_actor_manager_facet::SubnetActorManagerFacet::new(address, signer.clone());

let txn = call_with_premium_estimation(signer, contract.unstake(collateral.into())).await?;
txn.send().await?.await?;

Ok(())
}

async fn leave_subnet(&self, subnet: SubnetID, from: Address) -> Result<()> {
let address = contract_address_from_subnet(&subnet)?;
log::info!("leaving evm subnet: {subnet:} at contract: {address:}");
Expand Down
5 changes: 5 additions & 0 deletions ipc/provider/src/manager/subnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ pub trait SubnetManager: Send + Sync + TopDownCheckpointQuery + BottomUpCheckpoi
/// and increase their power in the subnet
async fn stake(&self, subnet: SubnetID, from: Address, collateral: TokenAmount) -> Result<()>;

/// Allows validators that have already joined the subnet to unstake collateral
/// and reduce their power in the subnet
async fn unstake(&self, subnet: SubnetID, from: Address, collateral: TokenAmount)
-> Result<()>;

/// Sends a request to leave a subnet from a wallet address.
async fn leave_subnet(&self, subnet: SubnetID, from: Address) -> Result<()>;

Expand Down

0 comments on commit d42370a

Please sign in to comment.