Pundi
Pundi AIPundi X
  • 🤖Pundi AI overview
  • 🈁Pundi AI Data Platform
    • Data stakeholders
    • Data Labelling
    • Pundi AI Data Platform (Alpha Testnet) - User Guide
    • FAQ
  • 🦾Pundi AIFX Omnilayer
    • Pundi AIFX
    • Installation Pundi AIFX
    • Setup Node
      • Full node with Binaries
      • Full node with Docker
      • Snapshot Guide
      • Node Monitoring Device
    • Validators
      • Validator Overview
      • Setting Up a Validator for Pundi AIFX
      • Validator Recovery
      • Validator FAQ
      • Validator Security Notice
      • Migration Best Practices
      • Transfer Validator Permissions
    • Delegators
      • Delegators FAQ
      • Delegator CLI Guide
      • Delegator Security Notice
    • Pundi AIFX Tutorials
      • Pundi AIFX CLI Commands
      • Cloud Setup
      • Testnet faucet
      • Ledger Integration for fxcored
      • Sentry Nodes
      • Account Migration Guide (CLI)
    • Upgrade Instructions
      • Cosmovisor Upgrade Guide v8.5.x
        • Cosmovisor Integration - Binaries
        • Cosmovisor Integration - Docker
      • Manual Upgrade Guide v8.5.x
        • Binaries - Upgrading Your Node
        • Docker - Upgrading Your Node
      • Upgrade Versions
        • v2.2.0 Upgrade Instructions
        • v3.1.0 Upgrade Instructions
        • v4.2.1 Upgrade Instructions
        • v5.0.0 Upgrade Instructions
      • Upgrade FAQ
    • Deploying on Pundi AIFX EVM
      • Products
      • MetaMask
        • Download and Install MetaMask
        • Add Network
        • Configure Custom Tokens
        • Create and Import Accounts
      • Connect Wallet to Dapps
        • Connect using MetaMask
        • Connect using Pundi Wallet (Wallet Connect)
      • With Remix
      • With Truffle
      • With Hardhat
      • Cross-Chain Bridges
        • Bridging Tokens from other networks
        • Pundi Gravity Bridge
    • DApps and Infra
      • Margin X Swap
      • Pundi Wallet
      • PundiScan
      • Baklava Space
      • Safe Multisig
      • PortfolioX
      • Token Factory
    • Developers
      • Pundi AIFX Network
      • Pundi AIFX Modules
      • Pundi AIFX JSON RPC
      • Pundi AIFX REST API
      • Web3 JSON RPC
        • JSON RPC Server
        • Namespaces
        • JSON RPC Methods
        • Events
      • Support Leap
      • Third Party Price Oracles
      • Contract Deployments
      • Pundi AIFX Cross Chain
        • sendToFx
        • f(x)Core
        • ibc
        • Target
      • Precompiled Contracts
        • CrossChain Precompiled
        • Staking-V2 Precompiled
      • Pundi AIFX SDKs
        • Python SDK
        • JavaScript SDK
      • Contract Monitoring
    • Pundi X Chain (under Pundi X)
      • Getting Started
        • Install Pundi X (PundiXChain)
        • Setup Node
          • Full node with Binaries
          • Full node with Docker
          • Snapshot Guide
          • Node Monitoring Device
          • Node Peers
      • Validators
        • Validator Overview
        • Setting Up a Validator for PundiXChain
        • Validator Recovery
        • Validator FAQ
        • Validator Security
        • Sentry Nodes
      • Delegators
        • Delegator FAQ
        • Delegator Overview
        • Delegator CLI Guide
      • Pundi X Tutorials
        • Pundi X CLI Guide
        • Ledger Integration for pundixd
        • Testnet Faucet
        • Cloud Setup
      • Upgrade Instructions
        • Cosmovisor Integration - Binaries
        • Cosmovisor Integration - Docker
        • Support keplr
      • Developers
        • Pundi X Network
        • Pundi X Protobuf
        • Pundi X gRPC & REST
        • Pundi X JSON RPC
        • Pundi X Cross Chain
          • ibc
  • 👛PURSE+
    • Purse Box
      • How many NFTs can I mint?
      • Minting (Etherscan)
      • Minting (Pursetoken.com)
    • PURSE+
      • Links
    • Bridging
      • BSC -> Ethereum
    • Protocols
      • LP Restaking Farms
        • How to Use Farms
        • Contract on BscScan
      • PURSE Staking
      • PURSE Staking Rewards
        • Campaigns
      • PURSE Retroactive Rewards
        • Campaigns
    • Contracts
      • Ethereum
      • Binance
      • Function X
    • IBC
      • PUNDIX Chain
    • PURSE Token
      • Background
      • ERC404 intro
      • Accounting of Balances
      • Minting PURSE NFT(s)
      • Transferring PURSE
      • Maintaining PURSE NFT(s)
      • NFTs in Queue
      • Token IDs
  • 🎡Pundi AI MM Agent
    • Why Market Making
    • Traditional MM vs. AMM
    • AI MM Agent: Bridging the Gap
    • Use Cases
    • Train & Launch (Step 1 & 2)
    • Flywheel (Step 3)
    • How the AI MM Agent Works in Detail
    • Why This is Powerful
  • 🛍️Pundi AI Data Marketplace (soon)
  • 🥇PUNDIAI Token Overview
    • Revenue generation flywheel
    • vePUNDIAI
      • how to bribe with vePUNDIAI
    • Protocol pool
  • Governance
    • Governance Proposal Information
      • EGF Info
      • EGF Grants Program
      • Application Template
      • Successful Grant Applicants
      • Launching an EGF Proposal
  • Links
Powered by GitBook
On this page
  • Example
  • Scenario 5: Transferring PURSE NFT
  • ERC20 Transfers
  • ERC721 Transfers
  • Transfer Guide
  1. PURSE+
  2. PURSE Token

Transferring PURSE

PreviousMinting PURSE NFT(s)NextMaintaining PURSE NFT(s)

Last updated 8 months ago

The upgraded PURSE contract has a number of functions to transfer PURSE as ERC20 or ERC721.

PURSE transfers that are ERC20 related remain mostly the same prior to the upgrade, however there are some important updates. Some of the updates concerning PURSE transfers are: transferFrom is now a function that can be used for both ERC20 and ERC721, depending on the value that is passed as the valueOrId_ argument; and erc20TransferFrom and erc721TransferFrom are functions added as wrappers to emulate what a pure transferFrom would behave in standard ERC20 and ERC721 tokens. A detailed breakdown for each transfer related function is provided below.

During PURSE ERC20 transfers, the contract will first try to use up all the PURSE in an address’s Inactive Balance. Once the Inactive Balance is depleted, the contract will start to use the PURSE in the address’s Active Balance - which represents the PURSE NFTs owned by the address. However, this will result in NFTs being removed from the address to offset the deficit in the Inactive Balance; and each removal of an NFT would result in an increment of 1,000,000 PURSE in the Inactive Balance, but a reduction of 1,000,000 PURSE in the Active Balance. (See as an example)

When a PURSE NFT is successfully transferred from one address to another - regardless of whether the recipient is an Externally Owned Account (EOA) or a smart contract, the ownership of the NFT is transferred to the recipient, and the Active Balances of both the sender and the recipient are updated accordingly. Since 1 PURSE NFT is represented by 1,000,000 PURSE ERC20, the sender’s Active Balance will be deducted by this amount while the recipient’s Active Balance will be increased by the same amount; and the Inactive Balance for both parties will remain unchanged since this is an ERC721 transfer.

When a PURSE NFT is transferred, the transfer is technically moving 1,000,000 PURSE from the sender to the recipient; but instead of the change in balance being accounted for in the Inactive Balance, it is accounted for in the Active Balance. Since the Total Balance is the sum of the Inactive Balance and Active Balance, this change will also be reflected in the current Total Balance of PURSE for both the sender and the recipient.

Example

Scenario 5: Transferring PURSE NFT

With 1,000,000 PURSE in his balance, Bob decides to mint a PURSE NFT. After minting, Bob’s Total Balance (TB) of PURSE is still 1,000,000 PURSE, but the breakdown of his total balance will now be: Inactive Balance (IB) = 0 PURSE and Active Balance (AB) = 1,000,000 PURSE.

Bob determines that he wants to return Alice the PURSE she sent him, but he only has one PURSE NFT in his address which represents all the PURSE in his current balance. Bob transfers the PURSE NFT to Alice, and now his balance of PURSE is completely zero. On the other hand, Alice’s balance has now increased by 1,000,000 PURSE, and she has one PURSE NFT in her address.

Recall at the end of , Alice’s total balance was 900,000 PURSE, where IB = 900,000 and AB = 0, and she didn't have a PURSE NFT. Now after receiving Bob’s PURSE NFT, Alice’s TB is now 1,900,000 PURSE, where IB = 900,000 PURSE and AB = 1,000,000 PURSE, and she has one PURSE NFT.\

ERC20 Transfers

The following are functions that can be used to transfer PURSE as an ERC20 token:

  1. transfer

function transfer(address to_, uint256 value_) public virtual override returns (bool)
  • Pure ERC20 transfer.

  • value_ is strictly treated as ERC20 amounts, even if the amount is a valid ERC721 token id. Assumes the operator is attempting to transfer as ERC20.

  • Updates the Inactive Balance of both the msg.sender and to_.

  • Returns a boolean value indicating operation success.

  1. transferFrom

function transferFrom(address from_, address to_, uint256 valueOrId_) public virtual override returns (bool)
  • Function for mixed transfers using either erc20TransferFrom or erc721TransferFrom, depending on valueOrId_.

  • The function assumes that the operator is attempting to transfer as ERC721 if valueOrId_ is a valid ERC721 token id.

  • If valueOrId_ is not a valid ERC721 token id, it transfers as ERC20.

  • Returns a boolean value indicating operation success.

  1. erc20TransferFrom

function erc20TransferFrom(address from_, address to_, uint256 value_) public virtual returns (bool)
  • Function for ERC20 transferFrom.

  • Moves value_ amount of PURSE from from_ to to_ using the allowance mechanism. Updates only the Inactive Balance of both from_ and to_.

  • value_ is deducted from the operator’s allowance.

  • Updates the Inactive Balance of both from_ and to_.

  • Returns a boolean value indicating operation success.

ERC721 Transfers

The following are functions that can be used to transfer PURSE as an ERC721 token:

  1. transferFrom

function transferFrom(address from_, address to_, uint256 valueOrId_) public virtual override returns (bool)
  • Function for mixed transfers using either erc20TransferFrom or erc721TransferFrom, depending on valueOrId_.

  • The function assumes that the operator is attempting to transfer as ERC721 if valueOrId_ is a valid ERC721 token id.

  • If valueOrId_ is not a valid ERC721 token id, it transfers as ERC20.

  • Returns a boolean value indicating operation success.

  • Use of safeTransferFrom is preferred and highly recommended over transferFrom for ERC721 transfers.

  1. erc721TransferFrom

function erc721TransferFrom(address from_, address to_, uint256 id_) public virtual
  • Function for ERC721 `transferFrom`.

  • Transfers `id_` from `from_` to `to_`.

  • Both `from_` and `to_` cannot be the zero address.

  • `id_` must be owned by `from_`

  • If the operator is not `from_`, the operator must be approved to move the token by either `approve` or `setApprovalForAll`.

  • Updates both Inactive Balance and Active Balance of both `from_` and `to_`.

  • IMPORTANT: The operator is responsible for confirming that the recipient (to_) is capable of receiving ERC721 tokens or else they may be permanently lost. Recommend to use safeTransferFrom but the operator must understand that this adds an external call to the recipient which may create a reentrancy vulnerability.

  1. safeTransferFrom

function safeTransferFrom(address from_, address to_, uint256 id_) public virtual
  • Safely transfers id_ token from from_ to to_, checking first that contract recipients are aware of the ERC721 protocol and returns the magic value to the PURSE contract. This prevents tokens from being locked permanently.

  • Same as erc721TransferFrom.

  • If to_ is a smart contract, it must implement IERC721Receiver.onERC721Received, which is called upon a safe transfer.

  1. safeTransferFrom (with additional bytes)

function safeTransferFrom(address from_, address to_, uint256 id_, bytes memory data_) public virtual
  • Overloaded function of safeTransferFrom.

  • Takes an additional bytes argument: data_.

Transfer Guide

The following table provides recommendations for the different transfer functions to execute based on the circumstances of the transfer.

Scenario
Recommended Function

Send PURSE as ERC20

  • transfer(address,uint256)

  • transferFrom(address,address,uint256)

Send PURSE as ERC721

  • safeTransferFrom(address,address,uint256)

Send PURSE as ERC721, with additional data

  • safeTransferFrom(address,address,uint256,bytes)

Send PURSE as ERC721, without recipient check

  • transferFrom(address,address,uint256)

👛
Scenario 3
Scenario 3