# WJU 包装代币

WJU（Wrapped JU）是JuChain原生代币JU的ERC-20包装版本。由于AMM系统需要所有代币都遵循ERC-20标准，WJU合约提供了JU代币与ERC-20代币之间的无缝转换功能，使得JU代币能够参与JAMM DEX的所有交易活动。

### 合约实现

#### 基本信息

```solidity
contract WJU is IWJU {
    string public constant override name = "Wrapped JU";
    string public constant override symbol = "WJU";
    uint8 public constant override decimals = 18;
    uint public override totalSupply;
    mapping(address => uint) public override balanceOf;
    mapping(address => mapping(address => uint)) public override allowance;
}
```

WJU合约完全实现了ERC-20标准，具有以下特性：

* **名称**: "Wrapped JU"
* **符号**: "WJU"
* **精度**: 18位小数
* **1:1兑换**: 1 JU = 1 WJU

### 核心功能

#### 包装功能（Deposit）

用户可以通过两种方式将JU代币包装为WJU：

**方式1：直接发送JU**

```solidity
receive() external payable {
    deposit();
}
```

用户直接向WJU合约地址发送JU代币，合约会自动调用`deposit()`函数。

**方式2：调用deposit函数**

```solidity
function deposit() public payable override {
    balanceOf[msg.sender] += msg.value;
    totalSupply += msg.value;
    emit Deposit(msg.sender, msg.value);
}
```

**包装过程**：

1. 用户发送JU代币到合约
2. 合约增加用户的WJU余额
3. 增加WJU总供应量
4. 触发Deposit事件

#### 解包装功能（Withdraw）

用户可以将WJU代币换回JU代币：

```solidity
function withdraw(uint amount) public override {
    require(balanceOf[msg.sender] >= amount);
    balanceOf[msg.sender] -= amount;
    payable(msg.sender).transfer(amount);
    emit Withdrawal(msg.sender, amount);
}
```

**解包装过程**：

1. 检查用户WJU余额是否足够
2. 减少用户的WJU余额
3. 向用户转账相应数量的JU代币
4. 触发Withdrawal事件

### ERC-20标准实现

#### 转账功能

```solidity
function transfer(address to, uint amount) public override returns (bool) {
    require(balanceOf[msg.sender] >= amount, "WJU: INSUFFICIENT_BALANCE");
    balanceOf[msg.sender] -= amount;
    balanceOf[to] += amount;
    emit Transfer(msg.sender, to, amount);
    return true;
}
```

#### 授权转账功能

```solidity
function transferFrom(
    address from,
    address to,
    uint amount
) public override returns (bool) {
    require(
        allowance[from][msg.sender] >= amount,
        "WJU: INSUFFICIENT_ALLOWANCE"
    );
    require(balanceOf[from] >= amount, "WJU: INSUFFICIENT_BALANCE");
    allowance[from][msg.sender] -= amount;
    balanceOf[from] -= amount;
    balanceOf[to] += amount;
    emit Transfer(from, to, amount);
    return true;
}
```

#### 授权功能

```solidity
function approve(
    address spender,
    uint amount
) public override returns (bool) {
    allowance[msg.sender][spender] = amount;
    emit Approval(msg.sender, spender, amount);
    return true;
}
```

### 事件系统

#### Deposit事件

```solidity
event Deposit(address indexed sender, uint amount);
```

记录JU代币包装为WJU的操作。

#### Withdrawal事件

```solidity
event Withdrawal(address indexed sender, uint amount);
```

记录WJU代币解包装为JU的操作。

#### ERC-20标准事件

```solidity
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
```

### 在JAMM DEX中的应用

#### Router集成

JAMMRouter合约与WJU深度集成，提供便捷的JU代币交易功能：

```solidity
address public immutable override WJU;

constructor(address _factory, address _WJU) {
    factory = _factory;
    WJU = _WJU;
}

receive() external payable {
    assert(msg.sender == WJU); // 只接受来自WJU合约的ETH
}
```

#### JU代币交易

**用JU购买代币**

```solidity
function swapExactETHForTokens(
    uint amountOutMin,
    address[] calldata path,
    uint24[] calldata fees,
    address to,
    address referrer,
    uint deadline
) external payable virtual override ensure(deadline) returns (uint[] memory amounts) {
    require(path[0] == WJU, "JAMMRouter: INVALID_PATH");
    amounts = JAMMLibrary.getAmountsOut(factory, msg.value, path, fees);
    require(
        amounts[amounts.length - 1] >= amountOutMin,
        "JAMMRouter: INSUFFICIENT_OUTPUT_AMOUNT"
    );
    IWJU(WJU).deposit{value: amounts[0]}();
    assert(
        IWJU(WJU).transfer(
            JAMMLibrary.pairFor(factory, path[0], path[1], fees[0]),
            amounts[0]
        )
    );
    _swap(amounts, path, fees, to, referrer);
}
```

**交易流程**：

1. 用户发送JU代币
2. Router将JU包装为WJU
3. 将WJU转入交易对
4. 执行交换逻辑
5. 用户收到目标代币

**卖出代币换JU**

```solidity
function swapExactTokensForETH(
    uint amountIn,
    uint amountOutMin,
    address[] calldata path,
    uint24[] calldata fees,
    address to,
    address referrer,
    uint deadline
) external virtual override ensure(deadline) returns (uint[] memory amounts) {
    require(path[path.length - 1] == WJU, "JAMMRouter: INVALID_PATH");
    amounts = JAMMLibrary.getAmountsOut(factory, amountIn, path, fees);
    require(
        amounts[amounts.length - 1] >= amountOutMin,
        "JAMMRouter: INSUFFICIENT_OUTPUT_AMOUNT"
    );
    TransferHelper.safeTransferFrom(
        path[0],
        msg.sender,
        JAMMLibrary.pairFor(factory, path[0], path[1], fees[0]),
        amounts[0]
    );
    _swap(amounts, path, fees, address(this), referrer);
    IWJU(WJU).withdraw(amounts[amounts.length - 1]);
    TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
}
```

**交易流程**：

1. 用户授权并转入代币
2. 执行交换得到WJU
3. Router将WJU解包装为JU
4. 向用户转账JU代币

#### 流动性管理

**添加JU流动性**

```solidity
function addLiquidityETH(
    address token,
    uint24 fee,
    uint amountTokenDesired,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline
) external payable virtual override ensure(deadline) returns (uint amountToken, uint amountETH, uint liquidity) {
    (amountToken, amountETH) = _addLiquidity(
        token,
        WJU,
        fee,
        amountTokenDesired,
        msg.value,
        amountTokenMin,
        amountETHMin
    );
    address pair = JAMMLibrary.pairFor(factory, token, WJU, fee);
    TransferHelper.safeTransferFrom(token, msg.sender, pair, amountToken);
    IWJU(WJU).deposit{value: amountETH}();
    assert(IWJU(WJU).transfer(pair, amountETH));
    liquidity = IJAMMPair(pair).mint(to);
    // 退还多余的JU
    if (msg.value > amountETH)
        TransferHelper.safeTransferETH(msg.sender, msg.value - amountETH);
}
```

**移除JU流动性**

```solidity
function removeLiquidityETH(
    address token,
    uint24 fee,
    uint liquidity,
    uint amountTokenMin,
    uint amountETHMin,
    address to,
    uint deadline
) public virtual override ensure(deadline) returns (uint amountToken, uint amountETH) {
    (amountToken, amountETH) = removeLiquidity(
        token,
        WJU,
        fee,
        liquidity,
        amountTokenMin,
        amountETHMin,
        address(this),
        deadline
    );
    TransferHelper.safeTransfer(token, to, amountToken);
    IWJU(WJU).withdraw(amountETH);
    TransferHelper.safeTransferETH(to, amountETH);
}
```

### 使用示例

#### 基本包装/解包装

```javascript
const wju = new ethers.Contract(WJU_ADDRESS, wjuABI, signer);

// 包装JU为WJU
const depositTx = await wju.deposit({ value: ethers.utils.parseEther("1.0") });
await depositTx.wait();

// 或者直接发送JU到WJU合约地址
const directTx = await signer.sendTransaction({
    to: WJU_ADDRESS,
    value: ethers.utils.parseEther("1.0")
});
await directTx.wait();

// 解包装WJU为JU
const withdrawTx = await wju.withdraw(ethers.utils.parseEther("1.0"));
await withdrawTx.wait();
```

#### 查询余额

```javascript
// 查询WJU余额
const wjuBalance = await wju.balanceOf(userAddress);
console.log("WJU余额:", ethers.utils.formatEther(wjuBalance));

// 查询JU余额
const juBalance = await provider.getBalance(userAddress);
console.log("JU余额:", ethers.utils.formatEther(juBalance));
```

#### 监听事件

```javascript
// 监听包装事件
wju.on("Deposit", (sender, amount, event) => {
    console.log(`${sender} 包装了 ${ethers.utils.formatEther(amount)} JU`);
});

// 监听解包装事件
wju.on("Withdrawal", (sender, amount, event) => {
    console.log(`${sender} 解包装了 ${ethers.utils.formatEther(amount)} WJU`);
});
```

### 安全考虑

#### 合约安全

1. **简单设计**: WJU合约逻辑简单，减少了安全风险
2. **无管理员**: 合约没有管理员功能，完全去中心化
3. **1:1兑换**: 严格的1:1兑换比例，无法被操纵

#### 使用安全

1. **余额检查**: 所有操作都会检查余额是否足够
2. **溢出保护**: 使用Solidity 0.8.21的内置溢出保护
3. **事件记录**: 所有操作都有相应的事件记录
