diff --git a/aptos-framework/doc/delegation_pool.md b/aptos-framework/doc/delegation_pool.md
index ca973d3dc..9cb98422b 100644
--- a/aptos-framework/doc/delegation_pool.md
+++ b/aptos-framework/doc/delegation_pool.md
@@ -145,6 +145,7 @@ transferred to A
- [Function `calculate_and_update_voter_total_voting_power`](#0x1_delegation_pool_calculate_and_update_voter_total_voting_power)
- [Function `calculate_and_update_remaining_voting_power`](#0x1_delegation_pool_calculate_and_update_remaining_voting_power)
- [Function `calculate_and_update_delegator_voter`](#0x1_delegation_pool_calculate_and_update_delegator_voter)
+- [Function `get_expected_stake_pool_address`](#0x1_delegation_pool_get_expected_stake_pool_address)
- [Function `initialize_delegation_pool`](#0x1_delegation_pool_initialize_delegation_pool)
- [Function `enable_partial_governance_voting`](#0x1_delegation_pool_enable_partial_governance_voting)
- [Function `vote`](#0x1_delegation_pool_vote)
@@ -161,6 +162,7 @@ transferred to A
- [Function `get_delegator_active_shares`](#0x1_delegation_pool_get_delegator_active_shares)
- [Function `get_delegator_pending_inactive_shares`](#0x1_delegation_pool_get_delegator_pending_inactive_shares)
- [Function `get_used_voting_power`](#0x1_delegation_pool_get_used_voting_power)
+- [Function `create_resource_account_seed`](#0x1_delegation_pool_create_resource_account_seed)
- [Function `borrow_mut_used_voting_power`](#0x1_delegation_pool_borrow_mut_used_voting_power)
- [Function `update_and_borrow_mut_delegator_vote_delegation`](#0x1_delegation_pool_update_and_borrow_mut_delegator_vote_delegation)
- [Function `update_and_borrow_mut_delegated_votes`](#0x1_delegation_pool_update_and_borrow_mut_delegated_votes)
@@ -1659,6 +1661,34 @@ latest state.
+
+
+
+
+## Function `get_expected_stake_pool_address`
+
+Return the address of the stake pool to be created with the provided owner, and seed.
+
+
+
#[view]
+public fun get_expected_stake_pool_address(owner: address, delegation_pool_creation_seed: vector<u8>): address
+
+
+
+
+
+Implementation
+
+
+public fun get_expected_stake_pool_address(owner: address, delegation_pool_creation_seed: vector<u8>
+): address {
+ let seed = create_resource_account_seed(delegation_pool_creation_seed);
+ account::create_resource_address(&owner, seed)
+}
+
+
+
+
@@ -1691,11 +1721,7 @@ Ownership over setting the operator/voter is granted to owner
who h
assert!(operator_commission_percentage <= MAX_FEE, error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE));
// generate a seed to be used to create the resource account hosting the delegation pool
- let seed = vector::empty<u8>();
- // include module salt (before any subseeds) to avoid conflicts with other modules creating resource accounts
- vector::append(&mut seed, MODULE_SALT);
- // include an additional salt in case the same resource account has already been created
- vector::append(&mut seed, delegation_pool_creation_seed);
+ let seed = create_resource_account_seed(delegation_pool_creation_seed);
let (stake_pool_signer, stake_pool_signer_cap) = account::create_resource_account(owner, seed);
coin::register<AptosCoin>(&stake_pool_signer);
@@ -2244,6 +2270,38 @@ Get the used voting power of a voter on a proposal.
+
+
+
+
+## Function `create_resource_account_seed`
+
+Create the seed to derive the resource account address.
+
+
+fun create_resource_account_seed(delegation_pool_creation_seed: vector<u8>): vector<u8>
+
+
+
+
+
+Implementation
+
+
+fun create_resource_account_seed(
+ delegation_pool_creation_seed: vector<u8>,
+): vector<u8> {
+ let seed = vector::empty<u8>();
+ // include module salt (before any subseeds) to avoid conflicts with other modules creating resource accounts
+ vector::append(&mut seed, MODULE_SALT);
+ // include an additional salt in case the same resource account has already been created
+ vector::append(&mut seed, delegation_pool_creation_seed);
+ seed
+}
+
+
+
+
diff --git a/aptos-framework/doc/staking_contract.md b/aptos-framework/doc/staking_contract.md
index 6b096895e..f8436012f 100644
--- a/aptos-framework/doc/staking_contract.md
+++ b/aptos-framework/doc/staking_contract.md
@@ -52,6 +52,7 @@ pool.
- [Function `staking_contract_amounts`](#0x1_staking_contract_staking_contract_amounts)
- [Function `pending_distribution_counts`](#0x1_staking_contract_pending_distribution_counts)
- [Function `staking_contract_exists`](#0x1_staking_contract_staking_contract_exists)
+- [Function `get_expected_stake_pool_address`](#0x1_staking_contract_get_expected_stake_pool_address)
- [Function `create_staking_contract`](#0x1_staking_contract_create_staking_contract)
- [Function `create_staking_contract_with_coins`](#0x1_staking_contract_create_staking_contract_with_coins)
- [Function `add_stake`](#0x1_staking_contract_add_stake)
@@ -71,6 +72,7 @@ pool.
- [Function `get_staking_contract_amounts_internal`](#0x1_staking_contract_get_staking_contract_amounts_internal)
- [Function `create_stake_pool`](#0x1_staking_contract_create_stake_pool)
- [Function `update_distribution_pool`](#0x1_staking_contract_update_distribution_pool)
+- [Function `create_resource_account_seed`](#0x1_staking_contract_create_resource_account_seed)
- [Function `new_staking_contracts_holder`](#0x1_staking_contract_new_staking_contracts_holder)
- [Specification](#@Specification_1)
- [Function `stake_pool_address`](#@Specification_1_stake_pool_address)
@@ -1027,6 +1029,37 @@ Return true if the staking contract between the provided staker and operator exi
+
+
+
+
+## Function `get_expected_stake_pool_address`
+
+Return the address of the stake pool to be created with the provided staker, operator and seed.
+
+
+#[view]
+public fun get_expected_stake_pool_address(staker: address, operator: address, contract_creation_seed: vector<u8>): address
+
+
+
+
+
+Implementation
+
+
+public fun get_expected_stake_pool_address(
+ staker: address,
+ operator: address,
+ contract_creation_seed: vector<u8>,
+): address {
+ let seed = create_resource_account_seed(staker, operator, contract_creation_seed);
+ account::create_resource_address(&staker, seed)
+}
+
+
+
+
@@ -1821,13 +1854,8 @@ Calculate accumulated rewards and commissions since last update.
contract_creation_seed: vector<u8>,
): (signer, SignerCapability, OwnerCapability) {
// Generate a seed that will be used to create the resource account that hosts the staking contract.
- let seed = bcs::to_bytes(&signer::address_of(staker));
- vector::append(&mut seed, bcs::to_bytes(&operator));
- // Include a salt to avoid conflicts with any other modules out there that might also generate
- // deterministic resource accounts for the same staker + operator addresses.
- vector::append(&mut seed, SALT);
- // Add an extra salt given by the staker in case an account with the same address has already been created.
- vector::append(&mut seed, contract_creation_seed);
+ let seed = create_resource_account_seed(
+ signer::address_of(staker), operator, contract_creation_seed);
let (stake_pool_signer, stake_pool_signer_cap) = account::create_resource_account(staker, seed);
stake::initialize_stake_owner(&stake_pool_signer, 0, operator, voter);
@@ -1896,6 +1924,42 @@ Calculate accumulated rewards and commissions since last update.
+
+
+
+
+## Function `create_resource_account_seed`
+
+Create the seed to derive the resource account address.
+
+
+fun create_resource_account_seed(staker: address, operator: address, contract_creation_seed: vector<u8>): vector<u8>
+
+
+
+
+
+Implementation
+
+
+fun create_resource_account_seed(
+ staker: address,
+ operator: address,
+ contract_creation_seed: vector<u8>,
+): vector<u8> {
+ let seed = bcs::to_bytes(&staker);
+ vector::append(&mut seed, bcs::to_bytes(&operator));
+ // Include a salt to avoid conflicts with any other modules out there that might also generate
+ // deterministic resource accounts for the same staker + operator addresses.
+ vector::append(&mut seed, SALT);
+ // Add an extra salt given by the staker in case an account with the same address has already been created.
+ vector::append(&mut seed, contract_creation_seed);
+ seed
+}
+
+
+
+
diff --git a/aptos-framework/sources/delegation_pool.move b/aptos-framework/sources/delegation_pool.move
index a593a6842..536e5dda3 100644
--- a/aptos-framework/sources/delegation_pool.move
+++ b/aptos-framework/sources/delegation_pool.move
@@ -570,6 +570,14 @@ module aptos_framework::delegation_pool {
)
}
+ #[view]
+ /// Return the address of the stake pool to be created with the provided owner, and seed.
+ public fun get_expected_stake_pool_address(owner: address, delegation_pool_creation_seed: vector
+ ): address {
+ let seed = create_resource_account_seed(delegation_pool_creation_seed);
+ account::create_resource_address(&owner, seed)
+ }
+
/// Initialize a delegation pool of custom fixed `operator_commission_percentage`.
/// A resource account is created from `owner` signer and its supplied `delegation_pool_creation_seed`
/// to host the delegation pool resource and own the underlying stake pool.
@@ -585,11 +593,7 @@ module aptos_framework::delegation_pool {
assert!(operator_commission_percentage <= MAX_FEE, error::invalid_argument(EINVALID_COMMISSION_PERCENTAGE));
// generate a seed to be used to create the resource account hosting the delegation pool
- let seed = vector::empty();
- // include module salt (before any subseeds) to avoid conflicts with other modules creating resource accounts
- vector::append(&mut seed, MODULE_SALT);
- // include an additional salt in case the same resource account has already been created
- vector::append(&mut seed, delegation_pool_creation_seed);
+ let seed = create_resource_account_seed(delegation_pool_creation_seed);
let (stake_pool_signer, stake_pool_signer_cap) = account::create_resource_account(owner, seed);
coin::register(&stake_pool_signer);
@@ -835,6 +839,18 @@ module aptos_framework::delegation_pool {
*smart_table::borrow_with_default(votes, key, &0)
}
+ /// Create the seed to derive the resource account address.
+ fun create_resource_account_seed(
+ delegation_pool_creation_seed: vector,
+ ): vector {
+ let seed = vector::empty();
+ // include module salt (before any subseeds) to avoid conflicts with other modules creating resource accounts
+ vector::append(&mut seed, MODULE_SALT);
+ // include an additional salt in case the same resource account has already been created
+ vector::append(&mut seed, delegation_pool_creation_seed);
+ seed
+ }
+
/// Borrow the mutable used voting power of a voter on a proposal.
inline fun borrow_mut_used_voting_power(governance_records: &mut GovernanceRecords, voter: address, proposal_id: u64): &mut u64 {
let votes = &mut governance_records.votes;
@@ -3891,6 +3907,12 @@ module aptos_framework::delegation_pool {
delegate_voting_power(delegator1, pool_address, signer::address_of(voter1));
}
+ #[test(staker = @0xe256f4f4e2986cada739e339895cf5585082ff247464cab8ec56eea726bd2263)]
+ public entry fun test_get_expected_stake_pool_address(staker: address) {
+ let pool_address = get_expected_stake_pool_address(staker, vector[0x42, 0x42]);
+ assert!(pool_address == @0xe9fc2fbb82b7e1cb7af3daef8c7a24e66780f9122d15e4f1d486ee7c7c36c48d, 0);
+ }
+
#[test_only]
public fun assert_delegation(
delegator_address: address,
diff --git a/aptos-framework/sources/staking_contract.move b/aptos-framework/sources/staking_contract.move
index 9aee05336..1291d6321 100644
--- a/aptos-framework/sources/staking_contract.move
+++ b/aptos-framework/sources/staking_contract.move
@@ -233,6 +233,17 @@ module aptos_framework::staking_contract {
simple_map::contains_key(&store.staking_contracts, &operator)
}
+ #[view]
+ /// Return the address of the stake pool to be created with the provided staker, operator and seed.
+ public fun get_expected_stake_pool_address(
+ staker: address,
+ operator: address,
+ contract_creation_seed: vector,
+ ): address {
+ let seed = create_resource_account_seed(staker, operator, contract_creation_seed);
+ account::create_resource_address(&staker, seed)
+ }
+
/// Staker can call this function to create a simple staking contract with a specified operator.
public entry fun create_staking_contract(
staker: &signer,
@@ -670,13 +681,8 @@ module aptos_framework::staking_contract {
contract_creation_seed: vector,
): (signer, SignerCapability, OwnerCapability) {
// Generate a seed that will be used to create the resource account that hosts the staking contract.
- let seed = bcs::to_bytes(&signer::address_of(staker));
- vector::append(&mut seed, bcs::to_bytes(&operator));
- // Include a salt to avoid conflicts with any other modules out there that might also generate
- // deterministic resource accounts for the same staker + operator addresses.
- vector::append(&mut seed, SALT);
- // Add an extra salt given by the staker in case an account with the same address has already been created.
- vector::append(&mut seed, contract_creation_seed);
+ let seed = create_resource_account_seed(
+ signer::address_of(staker), operator, contract_creation_seed);
let (stake_pool_signer, stake_pool_signer_cap) = account::create_resource_account(staker, seed);
stake::initialize_stake_owner(&stake_pool_signer, 0, operator, voter);
@@ -722,6 +728,22 @@ module aptos_framework::staking_contract {
pool_u64::update_total_coins(distribution_pool, updated_total_coins);
}
+ /// Create the seed to derive the resource account address.
+ fun create_resource_account_seed(
+ staker: address,
+ operator: address,
+ contract_creation_seed: vector,
+ ): vector {
+ let seed = bcs::to_bytes(&staker);
+ vector::append(&mut seed, bcs::to_bytes(&operator));
+ // Include a salt to avoid conflicts with any other modules out there that might also generate
+ // deterministic resource accounts for the same staker + operator addresses.
+ vector::append(&mut seed, SALT);
+ // Add an extra salt given by the staker in case an account with the same address has already been created.
+ vector::append(&mut seed, contract_creation_seed);
+ seed
+ }
+
/// Create a new staking_contracts resource.
fun new_staking_contracts_holder(staker: &signer): Store {
Store {
@@ -1259,6 +1281,12 @@ module aptos_framework::staking_contract {
stake::assert_stake_pool(pool_address, balance_2epoch, 0, 0, with_rewards(unpaid_commission));
}
+ #[test(staker = @0xe256f4f4e2986cada739e339895cf5585082ff247464cab8ec56eea726bd2263, operator= @0x9f0a211d218b082987408f1e393afe1ba0c202c6d280f081399788d3360c7f09)]
+ public entry fun test_get_expected_stake_pool_address(staker: address, operator: address) {
+ let pool_address = get_expected_stake_pool_address(staker, operator, vector[0x42, 0x42]);
+ assert!(pool_address == @0x9d9648031ada367c26f7878eb0b0406ae6a969b1a43090269e5cdfabe1b48f0f, 0);
+ }
+
#[test_only]
public fun assert_staking_contract(
staker: address, operator: address, principal: u64, commission_percentage: u64) acquires Store {