Skip to content

Commit

Permalink
[aptos_account] add transfer FA functions (#15116)
Browse files Browse the repository at this point in the history
* [aptos_account] add transfer FA functions

* reorder input arguments to ensure metadata comes first

---------

Co-authored-by: Greg Nazario <greg@gnazar.io>
  • Loading branch information
lightmark and gregnazario authored Oct 30, 2024
1 parent 347b8f9 commit 1c61db9
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 1 deletion.
148 changes: 148 additions & 0 deletions aptos-move/framework/aptos-framework/doc/aptos_account.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
- [Function `batch_transfer_coins`](#0x1_aptos_account_batch_transfer_coins)
- [Function `transfer_coins`](#0x1_aptos_account_transfer_coins)
- [Function `deposit_coins`](#0x1_aptos_account_deposit_coins)
- [Function `batch_transfer_fungible_assets`](#0x1_aptos_account_batch_transfer_fungible_assets)
- [Function `transfer_fungible_assets`](#0x1_aptos_account_transfer_fungible_assets)
- [Function `deposit_fungible_assets`](#0x1_aptos_account_deposit_fungible_assets)
- [Function `assert_account_exists`](#0x1_aptos_account_assert_account_exists)
- [Function `assert_account_is_registered_for_apt`](#0x1_aptos_account_assert_account_is_registered_for_apt)
- [Function `set_allow_direct_coin_transfers`](#0x1_aptos_account_set_allow_direct_coin_transfers)
Expand All @@ -34,6 +37,9 @@
- [Function `batch_transfer_coins`](#@Specification_1_batch_transfer_coins)
- [Function `transfer_coins`](#@Specification_1_transfer_coins)
- [Function `deposit_coins`](#@Specification_1_deposit_coins)
- [Function `batch_transfer_fungible_assets`](#@Specification_1_batch_transfer_fungible_assets)
- [Function `transfer_fungible_assets`](#@Specification_1_transfer_fungible_assets)
- [Function `deposit_fungible_assets`](#@Specification_1_deposit_fungible_assets)
- [Function `assert_account_exists`](#@Specification_1_assert_account_exists)
- [Function `assert_account_is_registered_for_apt`](#@Specification_1_assert_account_is_registered_for_apt)
- [Function `set_allow_direct_coin_transfers`](#@Specification_1_set_allow_direct_coin_transfers)
Expand Down Expand Up @@ -411,6 +417,100 @@ This would create the recipient account first and register it to receive the Coi



</details>

<a id="0x1_aptos_account_batch_transfer_fungible_assets"></a>

## Function `batch_transfer_fungible_assets`

Batch version of transfer_fungible_assets.


<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_account.md#0x1_aptos_account_batch_transfer_fungible_assets">batch_transfer_fungible_assets</a>(from: &<a href="../../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, metadata: <a href="object.md#0x1_object_Object">object::Object</a>&lt;<a href="fungible_asset.md#0x1_fungible_asset_Metadata">fungible_asset::Metadata</a>&gt;, recipients: <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;<b>address</b>&gt;, amounts: <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;)
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_account.md#0x1_aptos_account_batch_transfer_fungible_assets">batch_transfer_fungible_assets</a>(
from: &<a href="../../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>,
metadata: Object&lt;Metadata&gt;,
recipients: <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;<b>address</b>&gt;,
amounts: <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;
) {
<b>let</b> recipients_len = <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_length">vector::length</a>(&recipients);
<b>assert</b>!(
recipients_len == <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_length">vector::length</a>(&amounts),
<a href="../../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_invalid_argument">error::invalid_argument</a>(<a href="aptos_account.md#0x1_aptos_account_EMISMATCHING_RECIPIENTS_AND_AMOUNTS_LENGTH">EMISMATCHING_RECIPIENTS_AND_AMOUNTS_LENGTH</a>),
);

<a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_enumerate_ref">vector::enumerate_ref</a>(&recipients, |i, <b>to</b>| {
<b>let</b> amount = *<a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_borrow">vector::borrow</a>(&amounts, i);
<a href="aptos_account.md#0x1_aptos_account_transfer_fungible_assets">transfer_fungible_assets</a>(from, metadata, *<b>to</b>, amount);
});
}
</code></pre>



</details>

<a id="0x1_aptos_account_transfer_fungible_assets"></a>

## Function `transfer_fungible_assets`

Convenient function to deposit fungible asset into a recipient account that might not exist.
This would create the recipient account first to receive the fungible assets.


<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_account.md#0x1_aptos_account_transfer_fungible_assets">transfer_fungible_assets</a>(from: &<a href="../../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, metadata: <a href="object.md#0x1_object_Object">object::Object</a>&lt;<a href="fungible_asset.md#0x1_fungible_asset_Metadata">fungible_asset::Metadata</a>&gt;, <b>to</b>: <b>address</b>, amount: u64)
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_account.md#0x1_aptos_account_transfer_fungible_assets">transfer_fungible_assets</a>(from: &<a href="../../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, metadata: Object&lt;Metadata&gt;, <b>to</b>: <b>address</b>, amount: u64) {
<a href="aptos_account.md#0x1_aptos_account_deposit_fungible_assets">deposit_fungible_assets</a>(<b>to</b>, <a href="primary_fungible_store.md#0x1_primary_fungible_store_withdraw">primary_fungible_store::withdraw</a>(from, metadata, amount));
}
</code></pre>



</details>

<a id="0x1_aptos_account_deposit_fungible_assets"></a>

## Function `deposit_fungible_assets`

Convenient function to deposit fungible asset into a recipient account that might not exist.
This would create the recipient account first to receive the fungible assets.


<pre><code><b>public</b> <b>fun</b> <a href="aptos_account.md#0x1_aptos_account_deposit_fungible_assets">deposit_fungible_assets</a>(<b>to</b>: <b>address</b>, fa: <a href="fungible_asset.md#0x1_fungible_asset_FungibleAsset">fungible_asset::FungibleAsset</a>)
</code></pre>



<details>
<summary>Implementation</summary>


<pre><code><b>public</b> <b>fun</b> <a href="aptos_account.md#0x1_aptos_account_deposit_fungible_assets">deposit_fungible_assets</a>(<b>to</b>: <b>address</b>, fa: FungibleAsset) {
<b>if</b> (!<a href="account.md#0x1_account_exists_at">account::exists_at</a>(<b>to</b>)) {
<a href="aptos_account.md#0x1_aptos_account_create_account">create_account</a>(<b>to</b>);
};
<a href="primary_fungible_store.md#0x1_primary_fungible_store_deposit">primary_fungible_store::deposit</a>(<b>to</b>, fa)
}
</code></pre>



</details>

<a id="0x1_aptos_account_assert_account_exists"></a>
Expand Down Expand Up @@ -1024,6 +1124,54 @@ Limit the address of auth_key is not @vm_reserved / @aptos_framework / @aptos_to



<a id="@Specification_1_batch_transfer_fungible_assets"></a>

### Function `batch_transfer_fungible_assets`


<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_account.md#0x1_aptos_account_batch_transfer_fungible_assets">batch_transfer_fungible_assets</a>(from: &<a href="../../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, metadata: <a href="object.md#0x1_object_Object">object::Object</a>&lt;<a href="fungible_asset.md#0x1_fungible_asset_Metadata">fungible_asset::Metadata</a>&gt;, recipients: <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;<b>address</b>&gt;, amounts: <a href="../../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a>&lt;u64&gt;)
</code></pre>




<pre><code><b>pragma</b> verify = <b>false</b>;
</code></pre>



<a id="@Specification_1_transfer_fungible_assets"></a>

### Function `transfer_fungible_assets`


<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_account.md#0x1_aptos_account_transfer_fungible_assets">transfer_fungible_assets</a>(from: &<a href="../../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, metadata: <a href="object.md#0x1_object_Object">object::Object</a>&lt;<a href="fungible_asset.md#0x1_fungible_asset_Metadata">fungible_asset::Metadata</a>&gt;, <b>to</b>: <b>address</b>, amount: u64)
</code></pre>




<pre><code><b>pragma</b> verify = <b>false</b>;
</code></pre>



<a id="@Specification_1_deposit_fungible_assets"></a>

### Function `deposit_fungible_assets`


<pre><code><b>public</b> <b>fun</b> <a href="aptos_account.md#0x1_aptos_account_deposit_fungible_assets">deposit_fungible_assets</a>(<b>to</b>: <b>address</b>, fa: <a href="fungible_asset.md#0x1_fungible_asset_FungibleAsset">fungible_asset::FungibleAsset</a>)
</code></pre>




<pre><code><b>pragma</b> verify = <b>false</b>;
</code></pre>



<a id="@Specification_1_assert_account_exists"></a>

### Function `assert_account_exists`
Expand Down
37 changes: 36 additions & 1 deletion aptos-move/framework/aptos-framework/sources/aptos_account.move
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ module aptos_framework::aptos_account {
use aptos_framework::coin::{Self, Coin};
use aptos_framework::create_signer::create_signer;
use aptos_framework::event::{EventHandle, emit_event, emit};
use aptos_framework::fungible_asset::{Self, Metadata, BurnRef};
use aptos_framework::fungible_asset::{Self, Metadata, BurnRef, FungibleAsset};
use aptos_framework::primary_fungible_store;
use aptos_framework::object;

use std::error;
use std::features;
use std::signer;
use std::vector;
use aptos_framework::object::Object;

friend aptos_framework::genesis;
friend aptos_framework::resource_account;
Expand Down Expand Up @@ -132,6 +133,40 @@ module aptos_framework::aptos_account {
coin::deposit<CoinType>(to, coins)
}

/// Batch version of transfer_fungible_assets.
public entry fun batch_transfer_fungible_assets(
from: &signer,
metadata: Object<Metadata>,
recipients: vector<address>,
amounts: vector<u64>
) {
let recipients_len = vector::length(&recipients);
assert!(
recipients_len == vector::length(&amounts),
error::invalid_argument(EMISMATCHING_RECIPIENTS_AND_AMOUNTS_LENGTH),
);

vector::enumerate_ref(&recipients, |i, to| {
let amount = *vector::borrow(&amounts, i);
transfer_fungible_assets(from, metadata, *to, amount);
});
}

/// Convenient function to deposit fungible asset into a recipient account that might not exist.
/// This would create the recipient account first to receive the fungible assets.
public entry fun transfer_fungible_assets(from: &signer, metadata: Object<Metadata>, to: address, amount: u64) {
deposit_fungible_assets(to, primary_fungible_store::withdraw(from, metadata, amount));
}

/// Convenient function to deposit fungible asset into a recipient account that might not exist.
/// This would create the recipient account first to receive the fungible assets.
public fun deposit_fungible_assets(to: address, fa: FungibleAsset) {
if (!account::exists_at(to)) {
create_account(to);
};
primary_fungible_store::deposit(to, fa)
}

public fun assert_account_exists(addr: address) {
assert!(account::exists_at(addr), error::not_found(EACCOUNT_NOT_FOUND));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,18 @@ spec aptos_framework::aptos_account {
ensures if_exist_coin ==> post_coin_store_to == coin_store_to + coins.value;
}

spec deposit_fungible_assets(to: address, fa: FungibleAsset) {
pragma verify = false;
}

spec transfer_fungible_assets(from: &signer, metadata: Object<Metadata>, to: address, amount: u64) {
pragma verify = false;
}

spec batch_transfer_fungible_assets(from: &signer, metadata: Object<Metadata>, recipients: vector<address>, amounts: vector<u64>) {
pragma verify = false;
}

spec transfer_coins<CoinType>(from: &signer, to: address, amount: u64) {
// TODO(fa_migration)
pragma verify = false;
Expand Down

0 comments on commit 1c61db9

Please sign in to comment.