98 lines
4.4 KiB
JavaScript
98 lines
4.4 KiB
JavaScript
// 真实链上交易验证:授权 -> 买入 OT -> 卖出 OT
|
|
// 用法: npx hardhat run scripts/real_trade_test.js --network robinhoodTestnet
|
|
const hre = require("hardhat");
|
|
const { ethers } = hre;
|
|
|
|
const MARKET = "0x048E9a90C25ba2c4410425D282b19A472e076039";
|
|
const CURVE = "0xF0E189974c413506098AFB6Bc6Bf4C6715fBf7B1";
|
|
const COLLATERAL = "0xe776e957953EA69b7Eaa9d7d4098aBC076bDD5E7";
|
|
|
|
const marketAbi = [
|
|
"function mintCollateralToExactOt(address receiver, uint256 tokenId, uint256 otDeltaOut, bytes dataSwap) returns (uint256 collateralIn)",
|
|
"function redeemExactOtToCollateral(address receiver, uint256 tokenId, uint256 otDeltaIn, bytes dataSwap) returns (uint256 collateralOut)",
|
|
"function balanceOf(address owner, uint256 id) view returns (uint256)",
|
|
"function readMarketState() view returns (tuple(address market, address curve, uint128 timestampStart, uint256 totalMarketCap, address treasury, uint256 numOutcomes, uint128 timestampEnd, uint256 answer, bool isFinalised))",
|
|
];
|
|
const curveAbi = [
|
|
"function calMarginalPrice(address market, uint256 tokenId) view returns (uint256)",
|
|
"function calMintCostByOtDelta(address market, uint256 tokenId, uint256 otDelta, bytes data) view returns (uint256 collateralFromUser, uint256 collateralToTreasury)",
|
|
"function calRedeemValueByOtDelta(address market, uint256 tokenId, uint256 otDelta, bytes data) view returns (uint256 collateralToUser, uint256 collateralToTreasury)",
|
|
];
|
|
const erc20Abi = [
|
|
"function balanceOf(address) view returns (uint256)",
|
|
"function allowance(address owner, address spender) view returns (uint256)",
|
|
"function approve(address spender, uint256 amount) returns (bool)",
|
|
"function mint(address to, uint256 amount) external",
|
|
];
|
|
|
|
const OT = 1000n * 10n ** 18n; // 买 1000 OT
|
|
const OUTCOME = 1; // tokenId = 1 << 0 = 1 (YES)
|
|
|
|
async function main() {
|
|
const provider = hre.ethers.provider;
|
|
const [signer] = await hre.ethers.getSigners();
|
|
console.log("Signer:", signer.address);
|
|
console.log("Block:", await provider.getBlockNumber());
|
|
|
|
const market = new hre.ethers.Contract(MARKET, marketAbi, signer);
|
|
const curve = new hre.ethers.Contract(CURVE, curveAbi, provider);
|
|
const wusd = new hre.ethers.Contract(COLLATERAL, erc20Abi, signer);
|
|
|
|
// 1) 水龙头: 余额不足则 mint 100_000 WUSD
|
|
const bal = await wusd.balanceOf(signer.address);
|
|
console.log("WUSD balance:", ethers.formatEther(bal));
|
|
if (bal < ethers.parseEther("10000")) {
|
|
console.log("> minting 100000 WUSD...");
|
|
const tx = await wusd.mint(signer.address, ethers.parseEther("100000"));
|
|
await tx.wait();
|
|
console.log(" minted, tx:", tx.hash);
|
|
}
|
|
|
|
// 2) 授权
|
|
const allowance = await wusd.allowance(signer.address, MARKET);
|
|
console.log("allowance -> market:", ethers.formatEther(allowance));
|
|
if (allowance < ethers.parseEther("100000")) {
|
|
console.log("> approve MaxUint256 to market...");
|
|
const tx = await wusd.approve(MARKET, ethers.MaxUint256);
|
|
await tx.wait();
|
|
console.log(" approved, tx:", tx.hash);
|
|
}
|
|
|
|
// 3) 价格与成本
|
|
const price = await curve.calMarginalPrice(MARKET, OUTCOME);
|
|
console.log("marginalPrice:", ethers.formatEther(price), "WUSD/OT");
|
|
const [cost, treasury] = await curve.calMintCostByOtDelta(MARKET, OUTCOME, OT, "0x");
|
|
console.log("cost for 1000 OT:", ethers.formatEther(cost), "+ treasury fee", ethers.formatEther(treasury));
|
|
|
|
// 4) 真实买入
|
|
console.log("> mintCollateralToExactOt(1000 OT, tokenId=1)...");
|
|
try {
|
|
const tx = await market.mintCollateralToExactOt(signer.address, OUTCOME, OT, "0x", { gasLimit: 2000000 });
|
|
const receipt = await tx.wait();
|
|
console.log(" BUY SUCCESS tx:", tx.hash, "status:", receipt.status);
|
|
console.log(" gasUsed:", receipt.gasUsed.toString());
|
|
} catch (e) {
|
|
console.log(" BUY FAILED:", e.shortMessage || e.message);
|
|
process.exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
// 5) 检查 OT 余额并真实卖出
|
|
const otBal = await market.balanceOf(signer.address, OUTCOME);
|
|
console.log("OT balance:", ethers.formatEther(otBal));
|
|
console.log("> redeemExactOtToCollateral(1000 OT)...");
|
|
try {
|
|
const tx = await market.redeemExactOtToCollateral(signer.address, OUTCOME, OT, "0x", { gasLimit: 2000000 });
|
|
const receipt = await tx.wait();
|
|
console.log(" SELL SUCCESS tx:", tx.hash, "status:", receipt.status);
|
|
} catch (e) {
|
|
console.log(" SELL FAILED:", e.shortMessage || e.message);
|
|
process.exitCode = 1;
|
|
}
|
|
}
|
|
|
|
main().catch((e) => {
|
|
console.error(e);
|
|
process.exitCode = 1;
|
|
});
|