WJU Contract
Overview
WJU (Wrapped JU) is the ERC-20 wrapped version of JuChain's native token JU. As an important component of the JAMM DEX ecosystem, WJU enables JU tokens to seamlessly participate in all DeFi activities. The WJU contract is designed to be simple and secure, providing 1:1 bidirectional exchange functionality.
Contract Basic Information
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;
}
Token Information:
Name: "Wrapped JU"
Symbol: "WJU"
Decimals: 18 decimal places (same as JU)
Exchange Rate: 1 JU = 1 WJU
Core Functions
Wrapping Function (Deposit)
Direct JU Transfer
receive() external payable {
deposit();
}
Users can directly send JU tokens to the WJU contract address, and the contract will automatically call the deposit()
function for wrapping.
Active Wrapping Call
function deposit() public payable override {
balanceOf[msg.sender] += msg.value;
totalSupply += msg.value;
emit Deposit(msg.sender, msg.value);
}
Wrapping Process:
Receive JU tokens sent by user
Increase user's WJU balance
Increase WJU total supply
Emit Deposit event
Features:
1:1 exchange rate
Instant execution
No fees
No minimum/maximum limits
Unwrapping Function (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);
}
Unwrapping Process:
Check if user has sufficient WJU balance
Decrease user's WJU balance
Transfer corresponding amount of JU tokens to user
Emit Withdrawal event
Security Checks:
Balance sufficiency check
Uses Solidity 0.8.21's built-in overflow protection
Safe ETH transfer
ERC-20 Standard Implementation
Approval Function
function approve(
address spender,
uint amount
) public override returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
Transfer Function
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;
}
Security Features:
Balance sufficiency check
Custom error messages
Standard event emission
Authorized Transfer Function
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;
}
Double Checks:
Allowance amount check
Balance sufficiency check
Automatic allowance reduction
Event System
Deposit Event
event Deposit(address indexed sender, uint amount);
Records JU token wrapping to WJU operations, containing:
sender
: Initiator of wrapping operationamount
: Amount wrapped
Withdrawal Event
event Withdrawal(address indexed sender, uint amount);
Records WJU token unwrapping to JU operations, containing:
sender
: Initiator of unwrapping operationamount
: Amount unwrapped
ERC-20 Standard Events
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
Integration in JAMM DEX
Router Integration
JAMMRouter contract deeply integrates WJU functionality:
address public immutable override WJU;
constructor(address _factory, address _WJU) {
factory = _factory;
WJU = _WJU;
}
receive() external payable {
assert(msg.sender == WJU); // Only accept ETH from WJU contract
}
Automatic Wrapping/Unwrapping
Router automatically performs wrapping/unwrapping when handling JU-related transactions:
Automatic Wrapping in Swaps
// Internal process when user calls swapExactETHForTokens
function swapExactETHForTokens(...) external payable {
// 1. Wrap received JU to WJU
IWJU(WJU).deposit{value: amounts[0]}();
// 2. Transfer WJU to trading pair
assert(IWJU(WJU).transfer(pairAddress, amounts[0]));
// 3. Execute swap
_swap(amounts, path, fees, to, referrer);
}
Automatic Unwrapping in Swaps
// Internal process when user calls swapExactTokensForETH
function swapExactTokensForETH(...) external {
// 1. Execute swap to get WJU
_swap(amounts, path, fees, address(this), referrer);
// 2. Unwrap WJU to JU
IWJU(WJU).withdraw(amounts[amounts.length - 1]);
// 3. Transfer JU to user
TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
}
Usage Examples
Basic Wrapping/Unwrapping Operations
const wju = new ethers.Contract(WJU_ADDRESS, wjuABI, signer);
// Method 1: Call deposit function for wrapping
const depositTx = await wju.deposit({
value: ethers.utils.parseEther("1.0")
});
await depositTx.wait();
console.log("Wrapping successful");
// Method 2: Directly send JU to WJU contract
const directTx = await signer.sendTransaction({
to: WJU_ADDRESS,
value: ethers.utils.parseEther("1.0")
});
await directTx.wait();
console.log("Direct wrapping successful");
// Unwrap WJU to JU
const withdrawTx = await wju.withdraw(ethers.utils.parseEther("1.0"));
await withdrawTx.wait();
console.log("Unwrapping successful");
Balance Queries
// Query WJU balance
const wjuBalance = await wju.balanceOf(userAddress);
console.log("WJU Balance:", ethers.utils.formatEther(wjuBalance));
// Query JU balance
const juBalance = await provider.getBalance(userAddress);
console.log("JU Balance:", ethers.utils.formatEther(juBalance));
// Query WJU total supply
const totalSupply = await wju.totalSupply();
console.log("WJU Total Supply:", ethers.utils.formatEther(totalSupply));
ERC-20 Operations
// Approve
const approveTx = await wju.approve(spenderAddress, ethers.utils.parseEther("10"));
await approveTx.wait();
// Transfer
const transferTx = await wju.transfer(recipientAddress, ethers.utils.parseEther("1"));
await transferTx.wait();
// Query allowance
const allowance = await wju.allowance(ownerAddress, spenderAddress);
console.log("Allowance:", ethers.utils.formatEther(allowance));
Event Listening
// Listen to wrapping events
wju.on("Deposit", (sender, amount) => {
console.log(`${sender} wrapped ${ethers.utils.formatEther(amount)} JU`);
});
// Listen to unwrapping events
wju.on("Withdrawal", (sender, amount) => {
console.log(`${sender} unwrapped ${ethers.utils.formatEther(amount)} WJU`);
});
// Listen to transfer events
wju.on("Transfer", (from, to, value) => {
console.log(`Transfer: ${from} -> ${to}, Amount: ${ethers.utils.formatEther(value)}`);
});
Batch Operations
// Batch wrap JU for multiple users
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("Batch wrapping completed");
return results;
}
Last updated