# Asset deposits and withdrawals

## Asset deposits and withdrawals

Applications may want to enable users to:

* Deposit assets on L1 to L2 (note these <mark style="color:blue;">pre-requisites</mark>)
* Withdraw assets from L2 to L1

For more information and use cases, see our explanatory article, <mark style="color:blue;">Deep dive into deposits and withdrawals</mark>.

**Deposit pre-requisites:**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#deposit-pre-requisites)

* The user depositing the asset must be <mark style="color:blue;">registered with</mark> XpansionChain
* The user must own the asset on L1
* The L1 smart contract holding the asset must be <mark style="color:blue;">registered as a collection</mark>

📝GUIDES

* <mark style="color:blue;">Core SDK</mark>
* <mark style="color:blue;">API</mark>
* Link SDK:
  * <mark style="color:blue;">Deposits</mark>
  * <mark style="color:blue;">Prepare withdrawal and complete withdrawal</mark>

### Core SDK[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#core-sdk) <a href="#core-sdk" id="core-sdk"></a>

#### 1. Initialize the Core SDK[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#1-initialize-the-core-sdk) <a href="#id-1-initialize-the-core-sdk" id="id-1-initialize-the-core-sdk"></a>

In order to use the Core SDK, you need to <mark style="color:blue;">initialize it</mark>.

#### 2. Generate signers[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#2-generate-signers) <a href="#id-2-generate-signers" id="id-2-generate-signers"></a>

Enabling users to transfer assets requires a user's signature, so your application will need to create signers. See the guide on <mark style="color:blue;">how to generate signers</mark>.

#### 3. Deposit assets onto L2 <a href="#id-3-deposit-assets-onto-l2" id="id-3-deposit-assets-onto-l2"></a>

* Typescript Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">deposit</mark>

The function below will deposit ETH from L1 to L2. If you wish to deposit a different asset, you can change `type` to either `ERC20` or `ERC721` and specify the asset address as an additional parameter.

```
(async (): Promise<void> => {
  // Create deposit
  const deposit = await client.deposit(ethSigner, {
    // ethSigner obtained from generating signer

    type: 'ETH', // There are three avaible types: ETH, ERC20, ERC721
    amount: '50000000000000000', // Amount in wei, this currently is 0.05 ETH
  });
  // console.log(deposit); // Uncomment to see the deposit object
})().catch((e) => {
  log.error(component, e);
});
```

#### Example response[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#example-response) <a href="#example-response" id="example-response"></a>

```
{
  type: 2, // Transaction type, currently 2 means EIP-1559
  chainId: 5, // The Chain ID of the network, 5 is the Chain ID for Goerli.
  nonce: 5, // The nonce of the transaction used
  maxPriorityFeePerGas: BigNumber { _hex: '0x59682f00', _isBigNumber: true }, // Maximum fee to bribe miners into giving this transaction priority
  maxFeePerGas: BigNumber { _hex: '0x5968cf94', _isBigNumber: true }, // The maximum fee per gas that the sender is willing to pay
  gasPrice: null, // The gas price of the transaction determined by the network
  gasLimit: BigNumber { _hex: '0x013617', _isBigNumber: true }, // The maximum amount of gas that the transaction can use
  to: '0x7917eDb51ecD6CdB3F9854c3cc593F33de10c623', // The address of the recipient
  value: BigNumber { _hex: '0xb1a2bc2ec50000', _isBigNumber: true }, // The amount of ETH to send in wei
  data: '0x00aeef8a02f9a87a2eae83e024312ea33e2bec5df10cdef1470f6aaf5d5adb23f735a60002705737cd248ac819034b5de474c8f0368224f72a0fda9e031499d519992d9e000000000000000000000000000000000000000000000000000000000001ed7a', // Data included in this log
  accessList: [], // Optional list of addresses and storage keys the transaction can access
  hash: '0x357d6e1c09cf09b5746279bb77377b2353deb1c538eb18c8c9fa9e2363aa3d58', // The hash of the transaction
  v: 0, // The recovery ID of the ECDSA signature
  r: '0xc02c07ff0f80405f34917c9e300abff5da7dda319828fe1843a06f041cd3cbf5', // The first 32 bytes of the ECDSA signature
  s: '0x5c08b76a9ab9f766b82e6f273a1503d064d1604b8e071d7267a6735c5900bb1c', // The second 32 bytes of the ECDSA signature
  from: '0xF656956cA54778056f1191791876db54Aa6eb61B', // The address of the sender
  confirmations: 0, // The number of confirmations that the transaction has received
  wait: [Function (anonymous)] // A function that returns a promise that resolves when the transaction is mined
}
```

* Kotlin (JVM) Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">Deposits API</mark>

* Swift Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">Deposits API</mark>

* Golang Core SDK

📚SDK REFERENCE

* ETH deposit:
  * <mark style="color:blue;">NewETHDeposit</mark>
  * <mark style="color:blue;">(\*ETHDeposit) Deposit</mark>
* ERC20 deposit:
  * <mark style="color:blue;">NewERC20Deposit</mark>
  * <mark style="color:blue;">(\*ERC20Deposit) Deposit</mark>
* ERC721 deposit:
  * <mark style="color:blue;">NewERC721Deposit</mark>
  * <mark style="color:blue;">(\*ERC721Deposit) Deposit</mark>

#### 4. Withdraw assets to L1[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#4-withdraw-assets-to-l1) <a href="#id-4-withdraw-assets-to-l1" id="id-4-withdraw-assets-to-l1"></a>

* Typescript Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">prepareWithdrawal</mark>

* <mark style="color:blue;">completeWithdrawal</mark>

* Kotlin (JVM) Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">createWithdrawal</mark>

* <mark style="color:blue;">getSignableWithdrawal</mark>

* Swift Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">getSignableWithdrawal</mark>

* <mark style="color:blue;">createwithdrawal</mark>

* Golang Core SDK

📚SDK REFERENCE

* <mark style="color:blue;">PrepareWithdrawal</mark>
* Complete withdrawal for token types:
  * <mark style="color:blue;">(\*EthWithdrawal) CompleteWithdrawal</mark>
  * <mark style="color:blue;">(\*ERC20Withdrawal) CompleteWithdrawal</mark>
  * <mark style="color:blue;">(\*ERC721Withdrawal) CompleteWithdrawal</mark>

💻EXAMPLE

* <mark style="color:blue;">Withdrawal</mark>

### API[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#api) <a href="#api" id="api"></a>

* <mark style="color:blue;">Deposit</mark>
* <mark style="color:blue;">Withdrawal</mark>

#### Deposit[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#deposit) <a href="#deposit" id="deposit"></a>

To understand what is going on under the hood with asset deposits, please see <mark style="color:blue;">this explainer</mark>.

**Steps:**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#steps)

1. <mark style="color:blue;">Get details of the deposit</mark>
2. <mark style="color:blue;">Generate signers</mark>
3. <mark style="color:blue;">Call contract method to deposit tokens</mark>

**1. Get details of the deposit**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#1-get-details-of-the-deposit)

💡ENDPOINT:

* <mark style="color:blue;">getSignableDeposit</mark>

***Javascript example of depositing ETH from L1 to L2:***

```
import fetch from 'node-fetch';

const depositDetails = {
  amount: '0.001',
  token: {
    type: 'ETH',
    data: {
      decimals: 18,
    },
  },
  user: '0x..', // Public L1 Ethereum address
};

fetch('https://api.sandbox.x.XpansionChain.com/v1/signable-deposit-details', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(depositDetails),
})
  .then((response) => {
    console.log(response);
  })
  .catch((err) => {
    console.error(err);
  });
```

**Example response:**

```
{
    "amount": "string", // Amount this user is depositing
    "asset_id": "string", // ID of the asset this user is depositing (applicable only to depositing ERC721)
    "nonce": 0, // Random number generated of this transaction to verify that specific values are not reused
    "stark_key": "string", // Public stark key of the depositing user
    "vault_id": 0 // ID of the vault this user is depositing to
}
```

The following response params are used in the <mark style="color:blue;">depositEth</mark> contract method (see <mark style="color:blue;">Step 3</mark>):

* `stark_key`
* `vault_id`

**2. Generate signers**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#2-generate-signers-1)

Enabling users to deposit assets requires a user's signature, so your application will need to create signers. See the guide on <mark style="color:blue;">how to generate signers</mark>.

**3. Call contract method to deposit tokens**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#3-call-contract-method-to-deposit-tokens)

```
import { Contracts, Config } from '@imtbl/core-sdk';

const config = Config.SANDBOX;

// Get instance of core contract
const contract = Contracts.Core.connect(
  config.ethConfiguration.coreContractAddress,
  ethSigner
);

// Populate and send transaction
const populatedTransaction = await contract.populateTransaction.depositEth(
  starkPublicKey, // Use `stark_key` obtained in previous step
  assetType, // "ETH", "ERC20" or "ERC721"
  vaultId // Use `vault_id` obtained in previous step
);

const transactionResponse = await ethSigner.sendTransaction(
  populatedTransaction
);
```

#### Withdrawal[​](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#withdrawal) <a href="#withdrawal" id="withdrawal"></a>

To understand what is going on under the hood with asset withdrawals, please see <mark style="color:blue;">this explainer</mark>.

**Steps:**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#steps-1)

1. <mark style="color:blue;">Get details of the withdrawal</mark>
2. <mark style="color:blue;">Generate signers</mark>
3. <mark style="color:blue;">Create withdrawal</mark>
4. Call contract to complete withdrawal

**1. Get details of the withdrawal**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#1-get-details-of-the-withdrawal)

💡ENDPOINT:

* <mark style="color:blue;">getSignableWithdrawal</mark>

***Javascript example of withdrawing ETH from L2 to L1:***

```
import fetch from 'node-fetch';

const withdrawalDetails = {
  amount: '0.001',
  token: {
    type: 'ETH',
    data: {
      decimals: 18,
    },
  },
  user: '0x..', // Public L1 Ethereum address
};

fetch('https://api.sandbox.x.XpansionChain.com/v1/signable-withdrawal-details', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(withdrawalDetails),
})
  .then((response) => {
    console.log(response);
  })
  .catch((err) => {
    console.error(err);
  });
```

**Example response:**

```
{
    "amount": "string",
    "asset_id": "string",
    "nonce": 0,
    "payload_hash": "string",
    "signable_message": "string",
    "stark_key": "string",
    "vault_id": 0
}
```

Explanation:

<table data-header-hidden><thead><tr><th width="216.33333333333331"></th><th></th><th></th></tr></thead><tbody><tr><td>Response param</td><td>Description</td><td>How is it used in the <mark style="color:blue;">createWithdrawal</mark> request?<br>(See <mark style="color:blue;">Step 3)</mark></td></tr><tr><td><code>amount</code></td><td>Amount of token to be withdrawn to L1</td><td>As <code>amount</code> in the request body</td></tr><tr><td><code>asset_id</code></td><td>ID of the asset this user is withdrawing (applicable only to <code>ERC721</code> asset type)</td><td>As <code>asset_id</code> in the request body</td></tr><tr><td><code>nonce</code></td><td>Random number generated of this transaction to verify that specific values are not reused</td><td>As <code>nonce</code> in the request body</td></tr><tr><td><code>payload_hash</code></td><td>Encoded payload hash</td><td>Used to generate the <code>stark_signature</code> in the request body by using the Stark (L2) signer to sign the <code>payload_hash</code>.</td></tr><tr><td><code>signable_message</code></td><td>Message to sign with L1 wallet to verity withdrawal request</td><td>Used to generate the <code>x-imx-eth-signature</code> header by using the Ethereum (L1) signer to sign the <code>signable_message</code></td></tr><tr><td><code>stark_key</code></td><td>Public stark key of the withdrawing user</td><td>As <code>stark_key</code> in the request body</td></tr><tr><td><code>vault_id</code></td><td>The ID of the vault the asset belong to</td><td>As <code>vault_id</code> in the request body</td></tr></tbody></table>

**2. Generate signers**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#2-generate-signers-2)

Enabling users to withdraw assets requires a user's signature, so your application will need to create signers. See the guide on <mark style="color:blue;">how to generate signers</mark>.

**3. Create withdrawal**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#3-create-withdrawal)

💡ENDPOINT:

* <mark style="color:blue;">createWithdrawal</mark>

***Javascript example of withdrawing ETH from L2 to L1:***

```
import fetch from 'node-fetch';

// See previous step for how to generate signers
const ethSignature = ethSigner.sign(signable_message);
const starkSignature = starkSigner.sign(payload_hash);

const withdrawalBody = {
  amount: 'string',
  asset_id: 'string',
  nonce: 'string',
  stark_key: 'string',
  stark_signature: starkSignature,
  vauld_id: 'string',
};

fetch('https://api.sandbox.x.XpansionChain.com/v1/withdrawals', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-imx-eth-address': '0x..', // Public Ethereum address of the withdrawing user
    'x-imx-eth-signature': ethSignature,
  },
  body: JSON.stringify(withdrawalBody),
})
  .then((response) => {
    console.log(response);
  })
  .catch((err) => {
    console.error(err);
  });
```

**4. Get the `assetType` value**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#4-get-the-assettype-value)

This value is required in the next step to complete the withdrawal.

```
import fetch from 'node-fetch';

const assetType = 'asset'; // "mintable-asset" if you are withdrawing an ERC721 token that was minted on L2 to L1 for the first time

const encodeAssetBody = {
  token: {
    data: {
      blueprint: 'string',
      id: 'string',
      token_address: 'string',
      token_id: 'string',
    },
    type: 'ETH', // Or "ERC20" or "ERC721"
  },
};

fetch(`https://api.sandbox.x.XpansionChain.com/v1/encode/${assetType}`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-imx-eth-address': '0x..', // Public Ethereum address of the withdrawing user
    'x-imx-eth-signature': ethSignature,
  },
  body: JSON.stringify(encodeAssetBody),
})
  .then((response) => {
    console.log(response);

    // Example response
    // {
    //     "asset_id": "string",
    //     "asset_type": "string"
    // }
  })
  .catch((err) => {
    console.error(err);
  });
```

**5. Call contract to complete withdrawal**[**​**](https://docs.x.immutable.com/docs/x/how-to-enable-deposits-withdrawals#5-call-contract-to-complete-withdrawal)

```
import { Contracts, Config } from '@imtbl/core-sdk';

const config = Config.SANDBOX;

// Get instance of core contract
const contract = Contracts.Core.connect(
  config.ethConfiguration.coreContractAddress,
  ethSigner
);

// Populate and send transaction
const populatedTransaction = await contract.populateTransaction.withdraw(
  starkPublicKey, // Use `stark_key` obtained in previous step
  assetType // Use the `asset_type` value returned in the response object in step 4
);

const transactionResponse = await ethSigner.sendTransaction(
  populatedTransaction
);
```
