Transfers

Transfers can be either of a native asset (such as ETH, Matic, or SOL) or of a token (ERC-20/ERC-721/ERC-1155 on EVM chains, SPL tokens on Solana chains).

When creating a transfer transaction, a value must be set. The value can be:

  • Exact amount or
  • Maximum amount

While the exact amount is as its name suggests, the maximum amount behaves differently, depending on the asset being transferred and the type of the blockchain.

EVM

  • Native asset: Recall that on EVM chains, the fee is paid using native currency, a transfer of the entire native currency holdings will be rejected since there are not enough funds to pay for the fee. Therefore, Fordefi system will estimate the amount needed for paying the fee and will transfer the remaining amount. This may leave some native currency β€œdust” (a very small amount) in the vault. See an example.
  • ERC-20: Will transfer the entire holding amount. See an example.
  • ERC-721: Will transfer the specific token ID, it is equivalent to setting the exact amount of β€œ1”. See an example.
  • ERC-1155: Sending max is currently not supported. An explicit value to transfer must be provided. See an example.

Solana

  • Native asset: Recall that on Solana chains, the fee is paid using native currency, a transfer of the entire native currency holdings will be rejected since there are not enough funds to pay for the fee. As of the time of writing this document, the fee for an SOL transfer is 5000 lamports, therefore choosing max amount will empty the entire vault, transferring the entire amount, except for the fee. See an example.
  • SPL Token Transfer: Will transfer the entire holding amount. See an example.

Examples showcasing the max capability are provided below.

πŸ“˜

Note

API users must strongly authenticate transaction requests that are created programmatically by signing them. Learn more.

EVM

Native currency transfer

On EVM-based chains, the fee is paid using native currency, hence, the lack of native currency in a wallet will prevent you from doing any transaction. Transferring native currency should be done cautiously, to leave enough funds for future transactions, and in case of emptying the vault of funds, transferring native currency out of the vault should be done as the last transaction.

Following is an example of the body of a Create Transaction request for a native EVM currency transfer. The general details of creating the request appear here.

{
    "signer_type": "api_signer",
    "type": "evm_transaction",
    "details": {
        "type": "evm_transfer",
        "gas": {
            "gas_limit": "26304",
            "type": "custom",
            "details": {
                "type": "dynamic",
                "max_priority_fee_per_gas": "1",
                "max_fee_per_gas": "21000000000"
            }
        },
        "to": "0xB572Cf029bD939B260b16A97036456d6165F2222",
        "asset_identifier": {
             "type": "evm",
             "details": {
                 "type": "native",
                 "chain": "ethereum_mainnet"
             }
        },
        "value": {
           "type": "value",
           "value": "10000000000"
        }
    },
    "note": "Transferring 10000000000 WEI (ETH)",
    "vault_id": "8988893a-cf29-4a02-acc7-5bb723c74f47"
}

Following is an example of the body of a Create Transaction request for a max native EVM currency transfer. The general details of creating the request appear here.

{
    "signer_type": "api_signer",
    "type": "evm_transaction",
    "details": {
        "type": "evm_transfer",
        "gas": {
            "gas_limit": "26304",
            "type": "custom",
            "details": {
                "type": "dynamic",
                "max_priority_fee_per_gas": "1",
                "max_fee_per_gas": "21000000000"
            }
        },
        "to": "0xB572Cf029bD939B260b16A97036456d6165F2222",
        "asset_identifier": {
             "type": "evm",
             "details": {
                 "type": "native",
                 "chain": "ethereum_mainnet"
             }
        },
        "value": {
           "type": "max"
        }
    },
    "note": "Emptying ETH",
    "vault_id": "8988893a-cf29-4a02-acc7-5bb723c74f47"
}

Token transfer

ERC-20

Following is an example of the body of a Create Transaction request for an ERC-20 token transfer. The general details of creating the request appear here.

{
    "signer_type": "api_signer",
    "type": "evm_transaction",
    "details": {
        "type": "evm_transfer",
        "gas": {
            "gas_limit": "26304",
            "type": "custom",
            "details": {
                "type": "dynamic",
                "max_priority_fee_per_gas": "1",
                "max_fee_per_gas": "21000000000"
            }
        },
        "to": "0xB572Cf029bD939B260b16A97036456d6165F2222",
        "value": {
           "type": "value",
           "value": "10000000000"
        },
        "asset_identifier": {
             "type": "evm",
             "details": {
                 "type": "erc20",
                 "token": {
                     "chain": "ethereum_mainnet",
                     "hex_repr": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
                 }
             }
        }
    },
    "note": "Transferring 10,000 USDC",
    "vault_id": "8988893a-cf29-4a02-acc7-5bb723c74f47"
}

Following is an example of the body of a Create Transaction request for a max ERC-20 token transfer. The general details of creating the request appear here.

{
    "signer_type": "api_signer",
    "type": "evm_transaction",
    "details": {
        "type": "evm_transfer",
        "gas": {
            "gas_limit": "26304",
            "type": "custom",
            "details": {
                "type": "dynamic",
                "max_priority_fee_per_gas": "1",
                "max_fee_per_gas": "21000000000"
            }
        },
        "to": "0xB572Cf029bD939B260b16A97036456d6165F2222",
        "value": {
           "type": "max"
        },
        "asset_identifier": {
             "type": "evm",
             "details": {
                 "type": "erc20",
                 "token": {
                     "chain": "ethereum_mainnet",
                     "hex_repr": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
                 }
             }
        }
    },
    "note": "Emptying USDC",
    "vault_id": "8988893a-cf29-4a02-acc7-5bb723c74f47"
}

ERC-721

Following is an example of the body of a Create Transaction request for an ERC-721 token transfer. The general details of creating the request appear here.

{
    "signer_type": "api_signer",
    "type": "evm_transaction",
    "details": {
        "type": "evm_transfer",
        "gas": {
            "gas_limit": "26304",
            "type": "custom",
            "details": {
                "type": "dynamic",
                "max_priority_fee_per_gas": "1",
                "max_fee_per_gas": "21000000000"
            }
        },
        "to": "0xB572Cf029bD939B260b16A97036456d6165F2222",
        "value": {
           "type": "value",
           "value": "1"
        },        
        "asset_identifier": {
             "type": "evm",
             "details": {
                 "type": "erc721",
                 "token": {
                     "chain": "ethereum_mainnet",
                     "hex_repr": "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D"
                 },
                 "token_id": "1337"
             }
        }
    },
    "note": "Transferring BoredApe #1337",
    "vault_id": "8988893a-cf29-4a02-acc7-5bb723c74f47"
}

Note that when the maximum value is set for an ERC-721 transfer, it is essentially the same as setting the value to 1. Therefore, providing an example for the maximum value is redundant.

ERC-1155

Following is an example of the body of a Create Transaction request for an ERC-1155 token transfer. The general details of creating the request appear here.

{
    "signer_type": "api_signer",
    "type": "evm_transaction",
    "details": {
        "type": "evm_transfer",
        "gas": {
            "gas_limit": "26304",
            "type": "custom",
            "details": {
                "type": "dynamic",
                "max_priority_fee_per_gas": "1",
                "max_fee_per_gas": "21000000000"
            }
        },
        "to": "0xB572Cf029bD939B260b16A97036456d6165F2222",
        "value": {
           "type": "value",
           "value": "1"
        },        
        "asset_identifier": {
             "type": "evm",
             "details": {
                 "type": "erc1155",
                 "token": {
                     "chain": "ethereum_mainnet",
                     "hex_repr": "0xe70659b717112AC4e14284d0db2f5d5703dF8e43"
                 },
                 "token_id": "1337"
             }
        }
    },
    "note": "Transferring NFT #1337",
    "vault_id": "8988893a-cf29-4a02-acc7-5bb723c74f47"
}

Solana

On Solana chains, each account must hold enough SOL balance for rent. Currently, all accounts are required to be rent-exempt (meaning they hold at least two years' rent). The rent cost is a function of the size of the account (in bytes) and therefore differs between different types of accounts (for example SOL account vs. SPL account). See more about rent exemption.

Native currency transfer

In case the destination account does not exist, the transfer will also create it. Therefore, in that case, the amount must exceed the rent exemption value.

Following is an example of the body of a Create Transaction request for a native Solana currency transfer. The general details of creating the request appear here.

{
    "signer_type": "api_signer",
    "type": "solana_transaction",
    "details": {
        "type": "solana_transfer",
        "to": "2d3RofCcy5Jvyi2b6SxtUdd8N7JuRmopXWTUpGGZNSyq",
        "value": {
            "type": "value",
            "value": "10000000000"
        },
        "asset_identifier": {
            "type": "solana",
            "details": {
                "type": "native",
                "chain": "solana_mainnet"
            }
        }
    },
    "note": "Transferring 10 SOL",
    "vault_id": "8988893a-cf29-4a02-acc7-5bb723c74f47"
}

Following is an example of the body of a Create Transaction request for a max native Solana currency transfer. The general details of creating the request appear here.

{
    "signer_type": "api_signer",
    "type": "solana_transaction",
    "details": {
        "type": "solana_transfer",
        "to": "2d3RofCcy5Jvyi2b6SxtUdd8N7JuRmopXWTUpGGZNSyq",
        "value": {
            "type": "max"
        },
        "asset_identifier": {
            "type": "solana",
            "details": {
                "type": "native",
                "chain": "solana_mainnet"
            }
        }
    },
    "note": "Emptying SOL",
    "vault_id": "8988893a-cf29-4a02-acc7-5bb723c74f47"
}

SPL token transfer

In case the destination account does not exist, the transfer will also create it. Therefore, in that case, the source vault will also pay SOL for the rent exemption.

Following is an example of the body of a Create Transaction request for an SPL token transfer. The general details of creating the request appear here.

{
    "signer_type": "api_signer",
    "type": "solana_transaction",
    "details": {
        "type": "solana_transfer",
        "to": "2d3RofCcy5Jvyi2b6SxtUdd8N7JuRmopXWTUpGGZNSyq",
        "value": {
            "type": "value",
            "value": "10000000000"
        },
        "asset_identifier": {
            "type": "solana",
            "details": {
                "type": "spl_token",
                "token": {
                    "chain": "solana_mainnet",
                    "base58_repr": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                }
            }
        }
    },
    "note": "Transferring 10000 USDC",
    "vault_id": "8988893a-cf29-4a02-acc7-5bb723c74f47"
}

Following is an example of the body of a Create Transaction request for a max SPL token transfer. The general details of creating the request appear here.

{
    "signer_type": "api_signer",
    "type": "solana_transaction",
    "details": {
        "type": "solana_transfer",
        "to": "2d3RofCcy5Jvyi2b6SxtUdd8N7JuRmopXWTUpGGZNSyq",
        "value": {
            "type": "max"
        },
        "asset_identifier": {
            "type": "solana",
            "details": {
                "type": "spl_token",
                "token": {
                    "chain": "solana_mainnet",
                    "base58_repr": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
                }
            }
        }
    },
    "note": "Emptying USDC",
    "vault_id": "8988893a-cf29-4a02-acc7-5bb723c74f47"
}