# 표준 게이트웨이

L2와 L3에서 ERC-20 토큰이 유동된다는 것은 두 체인에 각각 ERC-20 토큰 컨트랙트가 존재한다는 것을 의미합니다.&#x20;

따라서 개발자 또는 프로젝트 빌더는 L3에 ERC-20 토큰 컨트랙트를 추가로 배포해야 하며, 게이트웨이 라우터 (GatewayRouter)가 사용자의 요청을 지정된 게이트웨이로 라우팅할 수 있도록 게이트웨이 라우터 컨트랙트에 관련 정보를 별도로 등록해야 합니다.

그러나 표준 게이트웨이 (Standard Gateway)를 사용할 경우, 이러한 일련의 과정이나 추가 작업 없이 즉시 브릿지를 이용할 수 있습니다.

최초 입금 요청 시 L3에 페어링된 ERC-20 컨트랙트가 없다면, 해당 컨트랙트가 자동으로 배포되며, 제공되는 표준 게이트웨이를 통해 라우팅됩니다. 이러한 모든 과정이 최초 입금 요청 시 자동으로 수행되기 때문에 간편하고 효율적인 온보딩을 제공합니다.

{% hint style="info" %}
디카르고가 제공하는 토큰 브릿지는 아비트럼의 Retryable ticket을 활용하여 구축된 디앱 (dApp)입니다.

Retryable ticket은 L2에서 트랜잭션을 생성하고 이를 L3에서 실행할 수 있도록 전달하는 메커니즘입니다.

사용자는 이 과정을 통해 L3에서 원하는 작업을 L2에서 수행할 수 있으며, 트랜잭션 처리에 필요한 수수료는 L2의 ERC-20 DKA로 지불됩니다.
{% endhint %}

## ERC20 입금

입금(Deposit)은 아비트럼 체인(L2)에 보유 중인 ERC-20 토큰을 디카르고 체인(L3)으로 전송하는 과정을 의미합니다.

이 과정은 아비트럼에 배포된 토큰 브릿지 컨트랙트와 디카르고 시퀀서의 협력을 통해 단계 별로 수행됩니다.

### STEP 1 - L2 ERC-20 토큰 승인 & L2 ERC-20 DKA

L2에 보유 중인 ERC-20 토큰을 디카르고 체인으로 전송하려면, 먼저 표준 게이트웨이 컨트랙트가 사용자의 ERC-20 토큰에 접근할 수 있도록 승인을 해야 합니다.

{% code overflow="wrap" %}

```tsx
const depositAmount = parseEther('1');
const res = await tokenBridge.approveToken({
  erc20ParentAddress: parentERC20.address,
  parentSigner,
  amount:depositAmount
});

const receipt = await res.wait();      
console.log(`approve ERC20 token to L2 Standard Gateway Contract tx hash: ${receipt.transactionHash}`)

const allowance = await tokenBridge.allowanceTokenToGateway(
  parentERC20.address,
  parentSigner.address,
  parentProvider
);
console.log(`allowance amount: ${allowance}`
```

{% endcode %}

또한, 입금 과정에서 L3에서 발생하는 트랜잭션 수수료는 L2의 ERC-20 DKA로 지불되기 때문에, 표준 게이트웨이 컨트랙트가 ERC-20 DKA에도 접근할 수 있도록 별도로 승인을 해주어야 합니다.

{% code overflow="wrap" %}

```tsx
const res = await tokenBridge.approveGasToken({
  erc20ParentAddress: parentERC20.address,
  parentSigner,
});

const receipt = await res.wait();      
console.log(`approve DKA token to L2 Standard Gateway Contract tx hash: ${receipt.transactionHash}`)

const allowance = await tokenBridge.allowanceGasTokenToGateway(
  parentERC20.address,
  parentSigner.address,
  parentProvider
);
console.log(`allowance amount: ${allowance}`
```

{% endcode %}

{% hint style="info" %}
파라미터에 <mark style="color:blue;">`depositAmount`</mark> 대신 <mark style="color:blue;">`null`</mark>을 입력하면, 최대 가능한 수량을 승인하게 됩니다.&#x20;

브리지를 사용할 때마다 매번 입금 금액을 개별적으로 승인해야 하지만, 이렇게 설정하면 최초 한 번만 승인하면 되고 이후에는 추가 승인이 필요 없습니다.
{% endhint %}

### STEP 2 - 토큰 입금

승인이 완료되면, L2 게이트웨이 라우터 컨트랙트의 `outboundTransfer()` 메서드를 호출하여 토큰 입금을 진행합니다. L2 게이트웨이 라우터는 사용자의 입금 요청을 L2 표준 게이트웨이로 라우팅합니다.

표준 게이트웨이는 사용자의 입금 요청에 따라 ERC-20 토큰을 자신의 컨트랙트로 전송한 후, 트랜잭션 수수료로 필요한 L2 ERC-20 DKA를 브릿지 컨트랙트로 전송합니다.

{% code overflow="wrap" %}

```tsx
const res = await tokenBridge.deposit({
  amount: depositAmount,
  erc20ParentAddress: parentERC20.address,
  parentSigner,
  childProvider,
});

const receipt = await res.wait();      
console.log(`deposit erc20 token L2 tx hash: ${receipt.transactionHash}`)
```

{% endcode %}

입금된 ERC-20 토큰은 아비트럼에 배포된 표준 게이트웨이 컨트랙트에 보관되며, 해당 토큰 자산은 잠기게(lock) 됩니다.

{% hint style="info" %}
최초로 입금이 시도된 경우, L3에 ERC-20 컨트랙트가 자동으로 배포됩니다.&#x20;

배포된 ERC-20 컨트랙트는 [**StandardArbERC20.sol**](https://github.com/OffchainLabs/token-bridge-contracts/blob/main/contracts/tokenbridge/arbitrum/StandardArbERC20.sol)을 기반으로 구현되어 있습니다.
{% endhint %}

### STEP 3 - 입금 상태

표준 게이트웨이로 ERC-20 토큰을 전송했다고 해서 L3에 즉시 입금되지는 않습니다. 입금 상태는 "대기"로 표시되며, 약 10분의 시간이 지난 후 최종적으로 디카르고 체인 계정으로 토큰이 발행(mint) 됩니다.

```tsx
// 메시지가 디카르고 체인에서 호출될 때까지 대기합니다.
await receipt.waitForChildTransactionReceipt(childProvider);
```

입금 상태는 [dScanner의 L2 ➔ L3 Transactions 페이지](https://warehouse.dscanner.io/txs-deposits)에서 확인할 수 있습니다.

{% hint style="info" %}
사용자가 L2의 표준 게이트웨이로 전송한 입금 요청에는 L3 ERC-20의 <mark style="color:blue;">`bridgeMint()`</mark>를 호출하는 메시지가 포함되어 있습니다. 이 메시지는 시퀀서에 의해 검증된 후 L3의 표준 게이트웨이를 통해 실행되어 토큰이 발행되며, 최종적으로 사용자의 계정에 입금됩니다.
{% endhint %}

## ERC-20 출금

출금(Withdraw)은 디카르고 체인(L3)에 보유 중인 ERC-20 토큰을 아비트럼 체인(L2)으로 전송하는 과정을 의미합니다. 이 과정은 아비트럼에 배포된 토큰 브릿지 컨트랙트와 디카르고 시퀀서가 협력하여 단계적으로 수행됩니다.

### STEP 1 - **ERC-20 출금**

ERC-20 토큰 출금은 L3 게이트웨이 라우터 (GatewayRouter)의 <mark style="color:blue;">`outboundTransfer()`</mark> 메서드를 호출하여 진행됩니다.&#x20;

L3 게이트웨이 라우터는 사용자의 출금 요청을 L3 표준 게이트웨이로 라우팅합니다.

L3 표준 게이트웨이는 출금 요청에 따라 ERC-20 토큰을 소각하며, L2 표준 게이트웨이에 보관된 L2 ERC-20 토큰이 이후 절차를 통해 소각된 만큼 사용자에게 반환됩니다.

```tsx
const res = await tokenBridge.withdraw({
  erc20ParentAddress: parentERC20.address,
  childSigner,
  amount,
  destinationAddress: parentSigner.address,
});

const receipt = await res.wait();
console.log(`withdraw erc20 token L3 tx hash: ${receipt.transactionHash}`)
```

{% hint style="info" %}
사용자가 L3 표준 게이트웨이로 전송한 출금 요청에는 L3 ERC-20의 <mark style="color:blue;">`bridgeBurn()`</mark> 메서드를 호출하는 메시지가 포함되어 있습니다. 이 메시지를 통해 출금 요청된 L3 토큰은 소각되며, 동시에 L2 표준 게이트웨이에 잠긴 L2 토큰을 소각된 만큼 해제(release)할 수 있는 권한이 부여됩니다.
{% endhint %}

### STEP 2: 출금 상태

출금 요청 후 L2에서 ERC-20 토큰을 수령하려면 약 6.4일의 분쟁 기간이 경과해야 하며, 그 기간 동안은 대기 상태로 유지됩니다.

```tsx
const message = await receipt.getChildToParentMessages(parentProvider);

// 6.4일의 분쟁 기간 지날때 까지 대기합니다.
await message[0].waitUntilReadyToExecute(childProvider);
```

출금 상태는 [dScanner의 L3 ➔ L2 Transactions 페이지](https://warehouse.dscanner.io/txs-exit)에서 확인할 수 있습니다.

### STEP 3: **ERC-20 청구**

분쟁 기간이 종료되면, 사용자는 L2 표준 게이트웨이에서 출금을 요청한 ERC-20 토큰을 청구할 수 있는 자격을 얻게 됩니다. 사용자는 outbox 컨트랙트를 통해 출금 요청한 ERC-20 토큰을 청구할 수 있습니다.

```jsx
const message = await receipt.getChildToParentMessages(parentSigner);
const res = await message[0].execute(childProvider);
const executeReceipt = await res.wait();
console.log(`claim erc20 token L2 tx hash: ${executeReceipt.transactionHash}`)
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.dkargo.io/erc-20/undefined.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
