WJU 合约

WJU(Wrapped JU)是JuChain原生代币JU的ERC-20包装版本。作为JAMM DEX生态系统的重要组成部分,WJU使得JU代币能够无缝参与所有DeFi活动。WJU合约设计简洁、安全可靠,提供1:1的双向兑换功能。

合约基本信息

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;
}

代币信息

  • 名称: "Wrapped JU"

  • 符号: "WJU"

  • 精度: 18位小数(与JU相同)

  • 兑换比例: 1 JU = 1 WJU

核心功能

包装功能(Deposit)

直接发送JU

receive() external payable {
    deposit();
}

用户可以直接向WJU合约地址发送JU代币,合约会自动调用deposit()函数进行包装。

主动调用包装

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事件

特点

  • 1:1兑换比例

  • 即时生效

  • 无手续费

  • 无最小/最大限制

解包装功能(Withdraw)

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事件

安全检查

  • 余额充足性检查

  • 使用Solidity 0.8.21的内置溢出保护

  • 安全的ETH转账

ERC-20标准实现

授权功能

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

转账功能

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;
}

安全特性

  • 余额充足性检查

  • 自定义错误消息

  • 标准事件发射

授权转账功能

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;
}

双重检查

  • 授权额度检查

  • 余额充足性检查

  • 自动减少授权额度

事件系统

Deposit事件

event Deposit(address indexed sender, uint amount);

记录JU代币包装为WJU的操作,包含:

  • sender: 包装操作的发起者

  • amount: 包装的数量

Withdrawal事件

event Withdrawal(address indexed sender, uint amount);

记录WJU代币解包装为JU的操作,包含:

  • sender: 解包装操作的发起者

  • amount: 解包装的数量

ERC-20标准事件

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功能:

address public immutable override WJU;

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

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

自动包装/解包装

Router在处理JU相关交易时会自动进行包装/解包装:

交换中的自动包装

// 用户调用swapExactETHForTokens时的内部流程
function swapExactETHForTokens(...) external payable {
    // 1. 将接收到的JU包装为WJU
    IWJU(WJU).deposit{value: amounts[0]}();
    
    // 2. 将WJU转入交易对
    assert(IWJU(WJU).transfer(pairAddress, amounts[0]));
    
    // 3. 执行交换
    _swap(amounts, path, fees, to, referrer);
}

交换中的自动解包装

// 用户调用swapExactTokensForETH时的内部流程
function swapExactTokensForETH(...) external {
    // 1. 执行交换得到WJU
    _swap(amounts, path, fees, address(this), referrer);
    
    // 2. 将WJU解包装为JU
    IWJU(WJU).withdraw(amounts[amounts.length - 1]);
    
    // 3. 将JU转给用户
    TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
}

使用示例

基本包装/解包装操作

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

// 方式1: 调用deposit函数包装
const depositTx = await wju.deposit({ 
    value: ethers.utils.parseEther("1.0") 
});
await depositTx.wait();
console.log("包装成功");

// 方式2: 直接发送JU到WJU合约
const directTx = await signer.sendTransaction({
    to: WJU_ADDRESS,
    value: ethers.utils.parseEther("1.0")
});
await directTx.wait();
console.log("直接包装成功");

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

余额查询

// 查询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));

// 查询WJU总供应量
const totalSupply = await wju.totalSupply();
console.log("WJU总供应量:", ethers.utils.formatEther(totalSupply));

ERC-20操作

// 授权
const approveTx = await wju.approve(spenderAddress, ethers.utils.parseEther("10"));
await approveTx.wait();

// 转账
const transferTx = await wju.transfer(recipientAddress, ethers.utils.parseEther("1"));
await transferTx.wait();

// 查询授权额度
const allowance = await wju.allowance(ownerAddress, spenderAddress);
console.log("授权额度:", ethers.utils.formatEther(allowance));

事件监听

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

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

// 监听转账事件
wju.on("Transfer", (from, to, value) => {
    console.log(`转账: ${from} -> ${to}, 数量: ${ethers.utils.formatEther(value)}`);
});

批量操作

// 批量包装多个用户的JU
async function batchWrap(users, amounts) {
    const promises = users.map((user, index) => {
        const userSigner = new ethers.Wallet(user.privateKey, provider);
        const userWJU = wju.connect(userSigner);
        return userWJU.deposit({ value: amounts[index] });
    });
    
    const results = await Promise.all(promises);
    console.log("批量包装完成");
    return results;
}

Last updated