Tech Whims

[59] sUSDe 链上执行自动化

2026-03-26


执行体系 · 共 12 篇

#59 sUSDe 链上执行自动化(Ethena mint/redeem 自动化方案)

tradeSys 研究 #59 | 2026-03-26 前置依赖:#30 (sUSDe 操作指南)、#41 (托管风险) Plan E3-AW 中 sUSDe 占 25%($12,500),需链上自动化执行 实时数据快照:ETH $2,067 | Gas 0.1 Gwei(2026-03-26,ultrasound.money)


核心结论

主要发现

  1. Gas 已不是摩擦成本的主要来源

    • 当前 Gas(0.1 Gwei)下,完整 stake→cooldown→claim 全流程仅需 ~$0.09
    • 真正的摩擦是 DEX 滑点(0.05-0.1%)和 7 天 cooldown 的机会成本(~$8)
  2. 硬件钱包是 $12.5K 仓位的必备安全措施

    • 私钥绝不应存储在 .env 或任何软件中
    • Ledger/Trezor 提供物理隔离和交易确认保护
  3. Cooldown 机制限制了灵活性但提供了安全缓冲

    • 7 天锁定期意味着需要提前规划退出
    • 紧急退出只能走 DEX,需接受 0.5-2% 折价
  4. 当前 sUSDe APY(3.49%)低于替代方案

    • SUSDS 3.75% + 即时流动性 = 更优选择
    • BIL 4.2% + 无 DeFi 风险 = 更安全选择

可执行建议

场景建议
新资金投入投入 SUSDS 或 BIL,不投 sUSDe
已持有 sUSDe继续持有,监控 APY;切换需 4 个月回本
sUSDe APY > SUSDS + 1%增配 sUSDe 至 25%
sUSDe APY < 2%紧急退出至 SUSDS/BIL
USDe peg < $0.990DEX 紧急卖出

1. Ethena 协议智能合约接口

1.1 核心合约地址(Ethereum Mainnet)

合约地址用途来源
USDe0x4c9EDD5852cd905f086C759E8383e09bff1E68B3USDe ERC-20 代币Ethena 官方 / CoinGecko
sUSDe (StakedUSDeV2)0x9D39A5DE30e57443BfF2A8307A4256c8797A3497sUSDe ERC-4626 金库,包含 stake/unstake/cooldown 逻辑Ethena 官方 / DeFiLlama
StakingRewardsDistributor0xf2fa332bd83149c66b09b45670bce64746c6b439收益分发合约,每周向 sUSDe 金库注入收益Ethena 官方文档 (docs.ethena.fi)
USDC0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48Circle USDC ERC-20公知
USDT0xdAC17F958D2ee523a2206206994597C13D831ec7Tether USDT ERC-20公知

验证方法:在 Etherscan 上搜索上述地址,确认合约名称、验证状态和代币信息一致。

1.2 StakedUSDeV2 合约关键函数签名

sUSDe 合约基于 ERC-4626 Tokenized Vault Standard(EIP-4626),叠加 Ethena 自定义的 cooldown 机制

A. Staking(存入 USDe → 获得 sUSDe)

// ERC-4626 标准函数
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
// assets = 存入的 USDe 数量(wei)
// receiver = 接收 sUSDe 的地址
// returns = 获得的 sUSDe 数量

function mint(uint256 shares, address receiver) external returns (uint256 assets);
// shares = 想要获得的 sUSDe 数量
// receiver = 接收 sUSDe 的地址
// returns = 需要存入的 USDe 数量

实际使用推荐 deposit():指定存入多少 USDe,合约自动计算返还多少 sUSDe。

B. Unstaking(发起 Cooldown)

// Ethena 自定义函数 — 启动冷却期
function cooldownAssets(uint256 assets) external returns (uint256 shares);
// assets = 要赎回的 USDe 数量
// 将对应的 sUSDe 锁定并启动 7 天倒计时
// returns = 被锁定的 sUSDe 数量

function cooldownShares(uint256 shares) external returns (uint256 assets);
// shares = 要赎回的 sUSDe 数量
// returns = 到期后可领取的 USDe 数量

注意cooldownAssetscooldownShares 是 Ethena 特有的,不属于 ERC-4626 标准。它们替代了标准的 withdraw()redeem() 在 cooldown 模式下的行为。

C. Claim(冷却期结束后领取)

function unstake(address receiver) external;
// 冷却期结束后调用,将 USDe 发送给 receiver
// 如果冷却期未结束,交易会 revert

D. 查询函数(只读,无 Gas 费)

function convertToShares(uint256 assets) external view returns (uint256);
// 查询 X 个 USDe 能换多少 sUSDe

function convertToAssets(uint256 shares) external view returns (uint256);
// 查询 X 个 sUSDe 值多少 USDe

function cooldowns(address owner) external view returns (uint104 cooldownEnd, uint152 underlyingAmount);
// 查询某地址的冷却期状态
// cooldownEnd = UNIX 时间戳(冷却到期时间)
// underlyingAmount = 到期可领取的 USDe 数量

function cooldownDuration() external view returns (uint24);
// 查询当前冷却期时长(秒)。当前 = 604800(7天 = 7 × 86400)

function totalAssets() external view returns (uint256);
// sUSDe 金库持有的总 USDe 数量

function previewDeposit(uint256 assets) external view returns (uint256 shares);
// 预览存入 assets 个 USDe 能得到多少 sUSDe

function previewRedeem(uint256 shares) external view returns (uint256 assets);
// 预览赎回 shares 个 sUSDe 能得到多少 USDe

1.3 USDe ERC-20 接口(Staking 前需要 Approve)

// 授权 sUSDe 合约花费你的 USDe
function approve(address spender, uint256 amount) external returns (bool);
// spender = sUSDe 合约地址 0x9D39A5DE30e57443BfF2A8307A4256c8797A3497
// amount = 授权金额(建议用 type(uint256).max 做无限授权,或精确数量)

function allowance(address owner, address spender) external view returns (uint256);
// 查询授权额度

function balanceOf(address account) external view returns (uint256);
// 查询余额

1.4 ERC-4626 核心理解

为什么 sUSDe 数量 < USDe 数量?

sUSDe 采用 ERC-4626 Token Vault 模型(与 Rocketpool 的 rETH、Binance 的 WBETH 相同):

来源:Ethena 官方文档 “Rewards Mechanism Explanation” (docs.ethena.fi)

“The protocol does not rehypothecate, lend out, or otherwise utilize deposited USDe for any purpose.” “Users can only receive positive or flat rewards while staking USDe; periods of negative protocol revenue are not passed on to sUSDe.”

收益注入机制(来源:docs.ethena.fi/solution-overview/protocol-revenue-explanation/susde-rewards-mechanism):

2. Python web3.py 自动化脚本框架

2.1 环境配置与依赖

# 推荐 Python 3.10+
pip install web3>=6.0.0 python-dotenv requests

# 可选:硬件钱包支持
pip install ledgereth  # Ledger 签名

# 项目结构
tradeSys/
├── ethena/
│   ├── __init__.py
│   ├── config.py          # 合约地址、ABI、RPC 配置
│   ├── contracts.py       # 合约交互封装
│   ├── gas_optimizer.py   # Gas 估算与优化
│   ├── executor.py        # 交易执行与重试
│   ├── monitor.py         # Funding rate 监控
│   └── scheduler.py       # 自动化调度
├── .env                   # 私钥/RPC URL(绝对不入 git)
└── run.py                 # CLI 入口

.env 文件模板(⚠️ 绝对不能提交到版本控制):

ETH_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY
# 或 Infura: https://mainnet.infura.io/v3/YOUR_KEY
# 免费替代:https://rpc.ankr.com/eth

# ⚠️ 生产环境强烈建议用硬件钱包,不在 .env 存私钥
# 仅用于测试/小额操作
PRIVATE_KEY=0x_YOUR_PRIVATE_KEY_NEVER_COMMIT_THIS

WALLET_ADDRESS=0xYOUR_ADDRESS

2.2 核心配置文件 (config.py)

"""ethena/config.py - 合约地址与 ABI 配置"""

# === 合约地址(Ethereum Mainnet)===
USDE_ADDRESS = "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3"
SUSDE_ADDRESS = "0x9D39A5DE30e57443BfF2A8307A4256c8797A3497"
USDC_ADDRESS = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"

# === sUSDe (StakedUSDeV2) 关键 ABI ===
SUSDE_ABI = [
    # === Staking ===
    {
        "name": "deposit",
        "type": "function",
        "stateMutability": "nonpayable",
        "inputs": [
            {"name": "assets", "type": "uint256"},
            {"name": "receiver", "type": "address"}
        ],
        "outputs": [{"name": "shares", "type": "uint256"}]
    },
    # === Cooldown(发起解锁)===
    {
        "name": "cooldownAssets",
        "type": "function",
        "stateMutability": "nonpayable",
        "inputs": [{"name": "assets", "type": "uint256"}],
        "outputs": [{"name": "shares", "type": "uint256"}]
    },
    {
        "name": "cooldownShares",
        "type": "function",
        "stateMutability": "nonpayable",
        "inputs": [{"name": "shares", "type": "uint256"}],
        "outputs": [{"name": "assets", "type": "uint256"}]
    },
    # === Claim(领取)===
    {
        "name": "unstake",
        "type": "function",
        "stateMutability": "nonpayable",
        "inputs": [{"name": "receiver", "type": "address"}],
        "outputs": []
    },
    # === 查询 ===
    {
        "name": "convertToShares",
        "type": "function",
        "stateMutability": "view",
        "inputs": [{"name": "assets", "type": "uint256"}],
        "outputs": [{"name": "", "type": "uint256"}]
    },
    {
        "name": "convertToAssets",
        "type": "function",
        "stateMutability": "view",
        "inputs": [{"name": "shares", "type": "uint256"}],
        "outputs": [{"name": "", "type": "uint256"}]
    },
    {
        "name": "cooldowns",
        "type": "function",
        "stateMutability": "view",
        "inputs": [{"name": "owner", "type": "address"}],
        "outputs": [
            {"name": "cooldownEnd", "type": "uint104"},
            {"name": "underlyingAmount", "type": "uint152"}
        ]
    },
    {
        "name": "cooldownDuration",
        "type": "function",
        "stateMutability": "view",
        "inputs": [],
        "outputs": [{"name": "", "type": "uint24"}]
    },
    {
        "name": "totalAssets",
        "type": "function",
        "stateMutability": "view",
        "inputs": [],
        "outputs": [{"name": "", "type": "uint256"}]
    },
    {
        "name": "previewDeposit",
        "type": "function",
        "stateMutability": "view",
        "inputs": [{"name": "assets", "type": "uint256"}],
        "outputs": [{"name": "", "type": "uint256"}]
    },
    {
        "name": "previewRedeem",
        "type": "function",
        "stateMutability": "view",
        "inputs": [{"name": "shares", "type": "uint256"}],
        "outputs": [{"name": "", "type": "uint256"}]
    },
    {
        "name": "balanceOf",
        "type": "function",
        "stateMutability": "view",
        "inputs": [{"name": "account", "type": "address"}],
        "outputs": [{"name": "", "type": "uint256"}]
    },
]

# === USDe ERC-20 ABI(仅需 approve + balanceOf + allowance)===
ERC20_ABI = [
    {
        "name": "approve",
        "type": "function",
        "stateMutability": "nonpayable",
        "inputs": [
            {"name": "spender", "type": "address"},
            {"name": "amount", "type": "uint256"}
        ],
        "outputs": [{"name": "", "type": "bool"}]
    },
    {
        "name": "allowance",
        "type": "function",
        "stateMutability": "view",
        "inputs": [
            {"name": "owner", "type": "address"},
            {"name": "spender", "type": "address"}
        ],
        "outputs": [{"name": "", "type": "uint256"}]
    },
    {
        "name": "balanceOf",
        "type": "function",
        "stateMutability": "view",
        "inputs": [{"name": "account", "type": "address"}],
        "outputs": [{"name": "", "type": "uint256"}]
    },
    {
        "name": "decimals",
        "type": "function",
        "stateMutability": "view",
        "inputs": [],
        "outputs": [{"name": "", "type": "uint8"}]
    },
]

2.3 Stake(USDe → sUSDe)完整脚本

"""stake_usde.py - 将 USDe stake 为 sUSDe"""
import os, time
from web3 import Web3
from dotenv import load_dotenv
from ethena.config import USDE_ADDRESS, SUSDE_ADDRESS, SUSDE_ABI, ERC20_ABI

load_dotenv()
w3 = Web3(Web3.HTTPProvider(os.getenv("ETH_RPC_URL")))
account = w3.eth.account.from_key(os.getenv("PRIVATE_KEY"))

usde = w3.eth.contract(address=USDE_ADDRESS, abi=ERC20_ABI)
susde = w3.eth.contract(address=SUSDE_ADDRESS, abi=SUSDE_ABI)

def stake_usde(amount_usde: float, max_gas_gwei: float = 10.0):
    """
    将指定数量的 USDe stake 为 sUSDe
    
    Args:
        amount_usde: USDe 数量(人类可读,如 12500.0)
        max_gas_gwei: 最大可接受 gas price(gwei),超过则放弃
    """
    amount_wei = int(amount_usde * 10**18)  # USDe 18 decimals
    
    # === Step 0: Gas 检查 ===
    base_fee = w3.eth.get_block('latest')['baseFeePerGas']
    base_fee_gwei = base_fee / 10**9
    if base_fee_gwei > max_gas_gwei:
        print(f"⚠️ Gas too high: {base_fee_gwei:.1f} gwei > {max_gas_gwei} limit. Aborting.")
        return None
    
    # === Step 1: 检查 USDe 余额 ===
    balance = usde.functions.balanceOf(account.address).call()
    assert balance >= amount_wei, f"USDe 余额不足: {balance/10**18:.2f} < {amount_usde}"
    
    # === Step 2: Approve(如果 allowance 不够)===
    allowance = usde.functions.allowance(account.address, SUSDE_ADDRESS).call()
    if allowance < amount_wei:
        print(f"📝 Approving sUSDe contract to spend {amount_usde} USDe...")
        approve_tx = usde.functions.approve(
            SUSDE_ADDRESS, 
            2**256 - 1  # 无限授权(减少未来 Gas 消耗)
        ).build_transaction({
            'from': account.address,
            'nonce': w3.eth.get_transaction_count(account.address),
            'maxFeePerGas': int(base_fee * 2),
            'maxPriorityFeePerGas': w3.to_wei(0.1, 'gwei'),  # 极低 tip
        })
        signed = account.sign_transaction(approve_tx)
        tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
        assert receipt['status'] == 1, f"Approve failed! tx: {tx_hash.hex()}"
        print(f"✅ Approve success. Gas used: {receipt['gasUsed']}")
    
    # === Step 3: 预览获得的 sUSDe 数量 ===
    shares = susde.functions.previewDeposit(amount_wei).call()
    print(f"📊 预计获得 sUSDe: {shares/10**18:.6f} (汇率: {amount_usde/(shares/10**18):.6f} USDe/sUSDe)")
    
    # === Step 4: Deposit(Stake)===
    print(f"🔄 Staking {amount_usde} USDe → sUSDe...")
    deposit_tx = susde.functions.deposit(
        amount_wei,
        account.address  # receiver = 自己
    ).build_transaction({
        'from': account.address,
        'nonce': w3.eth.get_transaction_count(account.address),
        'maxFeePerGas': int(base_fee * 2),
        'maxPriorityFeePerGas': w3.to_wei(0.1, 'gwei'),
    })
    signed = account.sign_transaction(deposit_tx)
    tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
    receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
    
    if receipt['status'] == 1:
        print(f"✅ Stake success! Gas used: {receipt['gasUsed']}")
        print(f"   TX: https://etherscan.io/tx/{tx_hash.hex()}")
        actual_shares = susde.functions.balanceOf(account.address).call()
        print(f"   sUSDe balance: {actual_shares/10**18:.6f}")
    else:
        print(f"❌ Stake FAILED! TX: https://etherscan.io/tx/{tx_hash.hex()}")
    
    return receipt

# === 使用示例 ===
if __name__ == "__main__":
    # $12,500 的 USDe(实际金额以 USDe 计,≈ $12,500)
    stake_usde(amount_usde=12500.0, max_gas_gwei=5.0)

2.4 Unstake(sUSDe → USDe Cooldown)完整脚本

"""unstake_susde.py - 发起 sUSDe cooldown"""
import os, time, datetime
from web3 import Web3
from dotenv import load_dotenv
from ethena.config import SUSDE_ADDRESS, SUSDE_ABI

load_dotenv()
w3 = Web3(Web3.HTTPProvider(os.getenv("ETH_RPC_URL")))
account = w3.eth.account.from_key(os.getenv("PRIVATE_KEY"))
susde = w3.eth.contract(address=SUSDE_ADDRESS, abi=SUSDE_ABI)

def start_cooldown(shares_to_unstake: float = None, unstake_all: bool = False):
    """
    发起 sUSDe cooldown
    
    Args:
        shares_to_unstake: sUSDe 数量。None + unstake_all=True 则全部 unstake
    """
    balance = susde.functions.balanceOf(account.address).call()
    print(f"当前 sUSDe 余额: {balance/10**18:.6f}")
    
    if unstake_all:
        shares_wei = balance
    else:
        shares_wei = int(shares_to_unstake * 10**18)
    
    assert shares_wei > 0 and shares_wei <= balance, "Invalid amount"
    
    # 预览能拿到多少 USDe
    assets = susde.functions.previewRedeem(shares_wei).call()
    print(f"预计到期可领取 USDe: {assets/10**18:.2f}")
    
    # 查询 cooldown 时长
    duration = susde.functions.cooldownDuration().call()
    unlock_time = datetime.datetime.now() + datetime.timedelta(seconds=duration)
    print(f"Cooldown 时长: {duration}s ({duration/86400:.1f} 天)")
    print(f"预计解锁时间: {unlock_time.strftime('%Y-%m-%d %H:%M')}")
    
    # 发起 cooldown
    base_fee = w3.eth.get_block('latest')['baseFeePerGas']
    tx = susde.functions.cooldownShares(shares_wei).build_transaction({
        'from': account.address,
        'nonce': w3.eth.get_transaction_count(account.address),
        'maxFeePerGas': int(base_fee * 2),
        'maxPriorityFeePerGas': w3.to_wei(0.1, 'gwei'),
    })
    signed = account.sign_transaction(tx)
    tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
    receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
    
    if receipt['status'] == 1:
        print(f"✅ Cooldown started! Gas: {receipt['gasUsed']}")
        print(f"   TX: https://etherscan.io/tx/{tx_hash.hex()}")
        print(f"   ⏰ 请在 {unlock_time.strftime('%Y-%m-%d %H:%M')} 之后执行 claim")
    else:
        print(f"❌ Cooldown FAILED!")
    
    return receipt

def check_cooldown_status():
    """检查当前 cooldown 状态"""
    cooldown_end, underlying = susde.functions.cooldowns(account.address).call()
    
    if cooldown_end == 0:
        print("没有进行中的 cooldown")
        return None
    
    end_dt = datetime.datetime.fromtimestamp(cooldown_end)
    now = datetime.datetime.now()
    remaining = end_dt - now
    
    print(f"Cooldown 到期: {end_dt.strftime('%Y-%m-%d %H:%M')}")
    print(f"可领取 USDe: {underlying/10**18:.2f}")
    
    if remaining.total_seconds() <= 0:
        print("✅ Cooldown 已结束,可以 claim!")
        return True
    else:
        print(f"⏳ 还需等待: {remaining.days}{remaining.seconds//3600}小时")
        return False

if __name__ == "__main__":
    check_cooldown_status()
    # start_cooldown(unstake_all=True)

2.5 Claim(Cooldown 结束后领取 USDe)脚本

"""claim_usde.py - cooldown 到期后领取 USDe"""
import os
from web3 import Web3
from dotenv import load_dotenv
from ethena.config import SUSDE_ADDRESS, USDE_ADDRESS, SUSDE_ABI, ERC20_ABI

load_dotenv()
w3 = Web3(Web3.HTTPProvider(os.getenv("ETH_RPC_URL")))
account = w3.eth.account.from_key(os.getenv("PRIVATE_KEY"))
susde = w3.eth.contract(address=SUSDE_ADDRESS, abi=SUSDE_ABI)
usde = w3.eth.contract(address=USDE_ADDRESS, abi=ERC20_ABI)

def claim_usde():
    """cooldown 到期后领取 USDe"""
    # 先检查 cooldown 是否已到期
    cooldown_end, underlying = susde.functions.cooldowns(account.address).call()
    
    import time
    if cooldown_end == 0:
        print("❌ 没有待领取的 cooldown")
        return None
    if time.time() < cooldown_end:
        print(f"❌ Cooldown 未到期,还需 {(cooldown_end - time.time())/3600:.1f} 小时")
        return None
    
    print(f"✅ Cooldown 已到期,领取 {underlying/10**18:.2f} USDe...")
    
    before_balance = usde.functions.balanceOf(account.address).call()
    
    base_fee = w3.eth.get_block('latest')['baseFeePerGas']
    tx = susde.functions.unstake(account.address).build_transaction({
        'from': account.address,
        'nonce': w3.eth.get_transaction_count(account.address),
        'maxFeePerGas': int(base_fee * 2),
        'maxPriorityFeePerGas': w3.to_wei(0.1, 'gwei'),
    })
    signed = account.sign_transaction(tx)
    tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
    receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
    
    if receipt['status'] == 1:
        after_balance = usde.functions.balanceOf(account.address).call()
        received = (after_balance - before_balance) / 10**18
        print(f"✅ Claim success! 收到 {received:.2f} USDe")
        print(f"   Gas: {receipt['gasUsed']}")
        print(f"   TX: https://etherscan.io/tx/{tx_hash.hex()}")
    else:
        print(f"❌ Claim FAILED!")
    
    return receipt

if __name__ == "__main__":
    claim_usde()

2.6 DEX Swap(USDC ↔ USDe)脚本框架

推荐方案:通过 1inch / CowSwap API 路由,而非直接调用 Curve/Uniswap 合约。 原因:聚合器自动选择最优路径 + MEV 保护(CowSwap)。

"""dex_swap.py - USDC ↔ USDe via 1inch API"""
import os, requests, time
from web3 import Web3
from dotenv import load_dotenv

load_dotenv()
w3 = Web3(Web3.HTTPProvider(os.getenv("ETH_RPC_URL")))
account = w3.eth.account.from_key(os.getenv("PRIVATE_KEY"))

USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
USDE = "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3"

def get_1inch_quote(from_token: str, to_token: str, amount_wei: int) -> dict:
    """从 1inch API 获取报价"""
    url = "https://api.1inch.dev/swap/v6.0/1/quote"
    headers = {"Authorization": "Bearer YOUR_1INCH_API_KEY"}
    params = {
        "src": from_token,
        "dst": to_token,
        "amount": str(amount_wei),
    }
    resp = requests.get(url, headers=headers, params=params)
    return resp.json()

def swap_usdc_to_usde(amount_usdc: float, slippage_pct: float = 0.5):
    """
    USDC → USDe swap via 1inch
    注意:USDC 是 6 decimals,USDe 是 18 decimals
    """
    amount_wei = int(amount_usdc * 10**6)  # USDC = 6 decimals
    
    # Step 1: 获取报价
    quote = get_1inch_quote(USDC, USDE, amount_wei)
    to_amount = int(quote['dstAmount'])
    print(f"报价: {amount_usdc} USDC → {to_amount/10**18:.2f} USDe")
    print(f"汇率: 1 USDC = {to_amount/10**18/amount_usdc:.6f} USDe")
    
    # Step 2: 获取 swap 交易数据
    swap_url = "https://api.1inch.dev/swap/v6.0/1/swap"
    headers = {"Authorization": "Bearer YOUR_1INCH_API_KEY"}
    params = {
        "src": USDC,
        "dst": USDE,
        "amount": str(amount_wei),
        "from": account.address,
        "slippage": str(slippage_pct),
    }
    resp = requests.get(swap_url, headers=headers, params=params)
    swap_data = resp.json()
    
    # Step 3: 需要先 approve USDC 给 1inch router
    # (省略 approve 步骤,与 2.3 类似)
    
    # Step 4: 发送交易
    tx = {
        'from': account.address,
        'to': Web3.to_checksum_address(swap_data['tx']['to']),
        'data': swap_data['tx']['data'],
        'value': int(swap_data['tx']['value']),
        'nonce': w3.eth.get_transaction_count(account.address),
        'maxFeePerGas': int(swap_data['tx'].get('maxFeePerGas', w3.eth.get_block('latest')['baseFeePerGas'] * 2)),
        'maxPriorityFeePerGas': w3.to_wei(0.1, 'gwei'),
        'gas': int(swap_data['tx']['gas']),
    }
    signed = account.sign_transaction(tx)
    tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
    receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
    
    print(f"{'✅' if receipt['status']==1 else '❌'} Swap {'success' if receipt['status']==1 else 'FAILED'}")
    print(f"   Gas: {receipt['gasUsed']}, TX: https://etherscan.io/tx/{tx_hash.hex()}")
    
    return receipt

# === CowSwap 替代方案(MEV 保护,无需 1inch API key)===
# CowSwap SDK: pip install cow-py
# 文档: https://docs.cow.fi/
# 优势:无 MEV + 更好的价格发现 + Ethena dApp 底层用的就是 CowSwap

3. Gas 优化策略

3.1 当前 Gas 环境与历史规律

实时数据(2026-03-26,ultrasound.money):

历史 Gas 规律(来源:Etherscan Gas Tracker 历史、ultrasound.money):

时期典型 Gas (Gwei)背景
2021 牛市峰值100-500DeFi + NFT 狂热
2023 熊市10-30活动减少
2024 EIP-4844 后3-15Blob 交易分流 L2 数据
2025-20260.1-5L2 成熟,L1 活动进一步降低

关键发现:2026 年 L1 gas 处于历史极低水平(0.1-5 Gwei),这意味着链上操作的成本几乎可以忽略不计。这对 $12,500 规模的操作是巨大利好——Gas 不再是摩擦成本的主要来源。

3.2 EIP-1559 vs Legacy 交易

结论:必须用 EIP-1559(Type 2)交易。

维度EIP-1559 (Type 2)Legacy (Type 0)
Gas 价格baseFee + priorityFee固定 gasPrice
多付风险低(baseFee 自动退还差价)高(多付的不退)
打包速度控制通过 maxPriorityFeePerGas 精确控制猜测合适价格
节点支持100% 以太坊节点100%(向后兼容)
推荐始终使用❌ 仅在特殊情况

EIP-1559 参数设置策略(针对非紧急的 sUSDe 操作):

def get_optimal_gas_params(w3, urgency="low"):
    """
    根据紧急程度返回 EIP-1559 Gas 参数
    
    urgency:
      - "low": 不急,等下一个块也行(省钱)
      - "medium": 希望 1-2 个块内打包
      - "high": 紧急,马上打包
    """
    base_fee = w3.eth.get_block('latest')['baseFeePerGas']
    
    configs = {
        "low": {
            "maxPriorityFeePerGas": w3.to_wei(0.05, 'gwei'),  # 极低 tip
            "maxFeePerGas": int(base_fee * 1.5),  # baseFee 1.5倍
        },
        "medium": {
            "maxPriorityFeePerGas": w3.to_wei(0.1, 'gwei'),
            "maxFeePerGas": int(base_fee * 2),
        },
        "high": {
            "maxPriorityFeePerGas": w3.to_wei(1, 'gwei'),
            "maxFeePerGas": int(base_fee * 3),
        },
    }
    return configs[urgency]

3.3 各操作 Gas 消耗实测数据

基于 Etherscan 上 StakedUSDeV2 合约的历史交易分析:

操作Gas Units(估计)费用 @ 0.1 Gwei费用 @ 5 Gwei费用 @ 50 Gwei
USDe approve~46,000$0.010$0.48$4.76
sUSDe deposit (stake)~90,000-120,000$0.019-0.025$0.93-1.24$9.31-12.41
sUSDe cooldownShares~80,000-100,000$0.017-0.021$0.83-1.03$8.27-10.34
sUSDe unstake (claim)~60,000-80,000$0.012-0.017$0.62-0.83$6.20-8.27
DEX swap (USDC→USDe)~150,000-250,000$0.031-0.052$1.55-2.59$15.51-25.84
全流程合计~426,000-596,000$0.09-0.12$4.41-6.17$44.05-61.62

计算公式:费用 = Gas Units × Gas Price (Gwei) × 10⁻⁹ × ETH Price ($2,067)

当前环境下的 So What

3.4 Gas 定时执行策略

最低 Gas 时段(基于历史数据,来源:Etherscan Gas Tracker):

时段 (UTC)对应北京时间典型 Gas 水平推荐度
02:00-06:0010:00-14:00最低⭐⭐⭐
06:00-10:0014:00-18:00⭐⭐
10:00-14:0018:00-22:00中等
14:00-18:0022:00-02:00较高(美国活跃时段)
周末全天-普遍低于工作日⭐⭐⭐

但在 2026 年 Gas 极低环境下,时段选择已不重要。唯一需要注意的是避开:

  1. 重大 NFT/Token 发行事件
  2. 市场剧烈波动时(链上清算活动会推高 Gas)

Gas 上限保护机制(脚本中已内置):

MAX_GAS_GWEI = 10.0  # 超过 10 Gwei 就等待
# 按当前 $2,067 ETH,10 Gwei 下全流程 ~$12,仍远在可接受范围内

4. 安全机制

4.1 硬件钱包(Ledger/Trezor)签名集成

强烈建议:$12,500 仓位必须使用硬件钱包签名,绝不将私钥存储在 .env 文件中。

Ledger 集成方案

"""ledger_signer.py - 硬件钱包签名"""
from web3 import Web3
from ledgereth import create_account, sign_transaction
import os

class LedgerSigner:
    """使用 Ledger 硬件钱包签名交易"""
    
    def __init__(self, derivation_path="44'/60'/0'/0/0"):
        self.derivation_path = derivation_path
        self.account = create_account(derivation_path)
        self.address = self.account.address
        print(f"Ledger connected: {self.address}")
    
    def sign_and_send(self, w3, tx_dict):
        """签名并发送交易"""
        tx_dict['nonce'] = w3.eth.get_transaction_count(self.address)
        signed_tx = sign_transaction(tx_dict, self.derivation_path)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
        return receipt

硬件钱包 vs 软件钱包对比

维度硬件钱包软件钱包(私钥在 .env)
私钥暴露风险私钥永不离开设备私钥在内存/磁盘
恶意软件防护物理隔离可被 keylogger 窃取
交易确认物理按键确认自动执行
$12.5K 建议必须使用仅用于测试网

4.2 Nonce 管理

class NonceManager:
    """线程安全的 nonce 管理器"""
    
    def __init__(self, w3, address):
        self.w3 = w3
        self.address = address
        self._pending_nonce = None
    
    def get_next_nonce(self):
        if self._pending_nonce is None:
            self._pending_nonce = self.w3.eth.get_transaction_count(
                self.address, 'pending'
            )
        else:
            self._pending_nonce += 1
        return self._pending_nonce

4.3 交易确认与 Reorg 保护

确认策略

def wait_for_confirmation(w3, tx_hash, confirmations=12):
    """等待交易被确认"""
    receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=300)
    if receipt['status'] != 1:
        raise Exception(f"Transaction failed: {tx_hash.hex()}")
    
    initial_block = receipt['blockNumber']
    target_block = initial_block + confirmations
    
    while w3.eth.block_number < target_block:
        time.sleep(12)
    
    return receipt

$12,500 规模的推荐确认数

4.4 失败重试与异常处理

class TransactionExecutor:
    """带重试机制的交易执行器"""
    
    def __init__(self, w3, max_retries=3, gas_bump=1.3):
        self.w3 = w3
        self.max_retries = max_retries
        self.gas_bump = gas_bump
    
    def execute(self, build_tx, signer, confirmations=3):
        for attempt in range(self.max_retries):
            try:
                tx = build_tx()
                signed = signer.sign_transaction(tx)
                tx_hash = self.w3.eth.send_raw_transaction(signed.raw_transaction)
                receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash, 300)
                if receipt['status'] == 1:
                    return receipt
            except Exception as e:
                if attempt == self.max_retries - 1:
                    raise
                time.sleep(5 * (attempt + 1))

5. Ethena 退出机制详解

5.1 Cooldown 机制精确参数

Cooldown 时长604,800 秒 = 7 天 = 168 小时

来源:StakedUSDeV2 合约 cooldownDuration() 函数返回值

function cooldownDuration() external view returns (uint24);
// 当前返回: 604800

Cooldown 数据结构(来源:合约源码):

struct UserCooldown {
    uint104 cooldownEnd;      // 冷却到期时间戳(UNIX timestamp)
    uint152 underlyingAmount; // 到期可领取的 USDe 数量
}

mapping(address => UserCooldown) public cooldowns;

关键约束

  1. 不可提前退出:一旦发起 cooldownAssets/cooldownShares,必须等满 7 天
  2. 无罚金:到期后领取,100% 拿回 underlyingAmount(含累积收益)
  3. 部分 cooldown:支持,可以只 cooldown 一部分 sUSDe
  4. 多个 cooldown:不支持同时存在多个独立的 cooldown。必须先 claim 当前的,才能发起新的
  5. 收益停止:cooldown 期间,被锁定的 sUSDe 不再产生收益

5.2 Cooldown 期间资金状态

状态转换图

┌─────────────┐    deposit()     ┌─────────────┐
│    USDe     │ ───────────────> │   sUSDe     │
│  (钱包中)   │                  │  (生息中)   │
└─────────────┘                  └─────────────┘
                                        │
                                        │ cooldownShares()
                                        ▼
                               ┌─────────────┐
                               │  sUSDe in   │
                               │  Cooldown   │
                               │ (锁定7天,   │
                               │  无收益)    │
                               └─────────────┘
                                        │
                                        │ unstake() (7天后)
                                        ▼
                               ┌─────────────┐
                               │    USDe     │
                               │  (钱包中)   │
                               └─────────────┘

收益损失计算($12,500 仓位):

# 假设当前 APY 3.49%
apy = 0.0349
cooldown_days = 7
principal = 12500

# 7 天收益损失
opportunity_cost = principal * apy * (cooldown_days / 365)
# = $12,500 × 0.0349 × (7/365)
# = $8.36

print(f"7 天 cooldown 的机会成本: ${opportunity_cost:.2f}")

So What:$8.36 的机会成本相对于仓位规模很小(0.067%),但意味着:

5.3 退出策略决策树

需要退出 sUSDe?
│
├─ 紧急程度?
│  │
│  ├─ 非常紧急(< 1 小时)
│  │  └─> 走 DEX 直接卖出 sUSDe
│  │      预期折价: 0.5-2% ($62.5-250)
│  │      时间: 即时
│  │
│  ├─ 比较急(1-24 小时)
│  │  └─> 检查 Curve/Uniswap 流动性
│  │      如果滑点 < 0.5%: 走 DEX
│  │      如果滑点 > 0.5%: 发起 cooldown + 等待
│  │
│  └─ 不着急(> 7 天)
│     └─> 发起 cooldown
│         7 天后 claim,无折价
│
└─ 当前 funding rate 环境?
   │
   ├─ sUSDe APY < SUSDS APY (当前 3.75%)
   │  └─> 考虑切换到 SUSDS
   │      需要: 发起 cooldown → 7 天后 claim → swap 到 USDC → 存入 SUSDS
   │      总时间: 7 天 + swap 时间
   │
   └─ sUSDe APY > SUSDS APY + 1%
      └─> 继续持有 sUSDe

决策阈值总结($12,500 规模):

场景推荐路径预期成本时间
紧急退出DEX 卖出0.5-2% 折价即时
计划退出Cooldown → ClaimGas ~$0.027 天
切换至 SUSDSCooldown → Claim → SUSDSGas ~$0.057 天 + 1 小时
切换至 BILCooldown → Claim → CEX → 证券账户Gas ~$0.05 + 转账费7 天 + 1-2 天

6. DEX 替代路径分析

6.1 Curve sUSDe/USDe 池

池地址(来源:Curve.fi 官网、Curve API):

池参数(来源:Curve 合约查询):

参数数值说明
代币数量2sUSDe + USDe
A 参数500放大系数,决定价格曲线陡峭程度
手续费0.04%交易手续费
管理费50%手续费的一半给 veCRV 持有者

流动性深度(估算,来源:Curve UI、DeFiLlama):

滑点计算($12,500 规模):

# Curve 稳定币池滑点估算(简化模型)
def estimate_curve_slippage(amount_in, pool_tvl, A=500):
    """
    amount_in: 交易金额(USD)
    pool_tvl: 池子 TVL(USD)
    A: Curve A 参数
    
    返回: 滑点百分比
    """
    # 简化公式:滑点 ≈ (amount_in / pool_tvl) * (1 / A) * 100
    slippage = (amount_in / pool_tvl) * (1 / A) * 100
    return slippage

# $12,500 交易在 $75M TVL 池子
slippage = estimate_curve_slippage(12500, 75_000_000, A=500)
print(f"Curve 滑点估算: {slippage:.4f}%")  # ≈ 0.0003%

# 加上 0.04% 手续费
total_cost = slippage + 0.04
print(f"总成本: {total_cost:.4f}%")  # ≈ 0.0403%

结论:对于 $12,500 规模,Curve 滑点几乎为零,总成本约 0.04%。

6.2 Uniswap V3 路由

USDe/USDC 池(来源:Uniswap.info):

对比 Curve

维度CurveUniswap V3
专注领域稳定币对通用
手续费0.04%0.05% (USDe/USDC)
$12.5K 滑点~0.0003%~0.001-0.01%
MEV 风险较低较高
推荐度⭐⭐⭐⭐⭐

6.3 滑点对比:协议赎回 vs DEX

路径滑点/折价Gas 成本时间总成本 ($12.5K)
协议 Cooldown0%~$0.027 天$0.02
Curve sUSDe→USDe~0.04%~$0.02即时$5.02
Uniswap sUSDe→USDe~0.05%~$0.02即时$6.27
恐慌时 DEX0.5-2%~$0.02即时$62.5-250

关键发现

6.4 规模阈值:什么时候走 DEX 更优

DEX 优于 Cooldown 的场景

  1. 时间价值 > 滑点成本

    • 如果你需要资金做更高收益的投资
    • 且新投资的年化收益 > 滑点成本 / 等待天数 × 365
    例: 7 天 cooldown 的机会成本 = $8.36
    DEX 滑点成本 = $5
    如果新投资年化 > 0,DEX 更优
    
  2. Funding rate 即将转负

    • 如果预测 funding rate 将在 7 天内转负
    • 立即 DEX 卖出可能比锁定 7 天更好
  3. 仓位规模极小

    • 对于 <$500 的仓位,Gas 成本占比高
    • 但 $12,500 不属于此列

Cooldown 优于 DEX 的场景

  1. 不着急用钱(默认情况)
  2. 市场恐慌,DEX 滑点 > 0.5%
  3. Gas 极高(> 50 Gwei),DEX 需要多笔交易

$12,500 规模的决策规则

def exit_strategy(amount_usd, urgency_hours, dex_slippage_pct):
    """
    返回推荐退出策略
    """
    cooldown_cost = 7.3  # Gas ~$0.02 + 机会成本 ~$8.36
    dex_cost = amount_usd * dex_slippage_pct / 100 + 0.02
    
    if urgency_hours < 1:
        return "DEX", dex_cost
    
    if dex_slippage_pct > 0.5:
        return "COOLDOWN", cooldown_cost
    
    # 比较成本
    if dex_cost < cooldown_cost * 0.5:  # DEX 显著更便宜
        return "DEX", dex_cost
    else:
        return "COOLDOWN", cooldown_cost

# 使用
strategy, cost = exit_strategy(12500, urgency_hours=24, dex_slippage_pct=0.04)
print(f"推荐: {strategy}, 预计成本: ${cost:.2f}")

7. 自动化调度系统

7.1 Funding Rate 监控脚本

"""monitor_funding.py - 监控 sUSDe APY"""
import requests
from datetime import datetime

class FundingRateMonitor:
    def __init__(self):
        self.thresholds = {
            'susde_to_susds': 0.5,
            'susde_min': 2.0,
        }
    
    def fetch_susde_apy(self):
        """从 DeFiLlama API 获取 sUSDe APY"""
        url = "https://yields.llama.fi/pools"
        try:
            resp = requests.get(url, timeout=30)
            data = resp.json()
            for pool in data['data']:
                if pool.get('symbol') == 'sUSDe' and pool.get('chain') == 'Ethereum':
                    return {'apy': pool.get('apy', 0), 'tvl': pool.get('tvlUsd', 0)}
            return None
        except Exception as e:
            print(f"Error: {e}")
            return None
    
    def check_switch_signal(self):
        susde = self.fetch_susde_apy()
        if not susde:
            return {'action': 'ERROR'}
        
        if susde['apy'] < self.thresholds['susde_min']:
            return {'action': 'URGENT_EXIT', 'apy': susde['apy']}
        
        return {'action': 'HOLD', 'apy': susde['apy']}

7.2 sUSDe 切换决策逻辑

条件动作触发阈值
sUSDe APY < 2%紧急退出低于无风险利率太多
sUSDe APY < SUSDS - 0.5%考虑切换风险溢价不足
sUSDe APY > SUSDS + 1%继续持有风险溢价足够
USDe peg < $0.990紧急 DEX 卖出脱锚风险

7.3 launchd 调度配置(macOS)

创建文件 ~/Library/LaunchAgents/com.tradesys.ethena-monitor.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "...">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.tradesys.ethena-monitor</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/python3</string>
        <string>/Users/mac/tradeSys/ethena/monitor_funding.py</string>
    </array>
    <key>StartInterval</key>
    <integer>14400</integer>  <!-- 每4小时 -->
</dict>
</plist>

加载:launchctl load ~/Library/LaunchAgents/com.tradesys.ethena-monitor.plist

7.4 告警与通知机制

"""notify.py - 发送告警通知"""
import requests

def send_alert(message: str, webhook_url: str = None):
    """通过 Discord/Slack webhook 发送告警"""
    if webhook_url:
        requests.post(webhook_url, json={"content": message})
    print(f"[ALERT] {message}")

# 使用
if decision['action'] in ['URGENT_EXIT', 'EMERGENCY_EXIT']:
    send_alert(f"⚠️ sUSDe 需要操作: {decision['reason']}")

8. $12,500 规模具体操作手册

8.1 Day0 建仓:完整步骤

前置准备

步骤操作说明
1准备硬件钱包Ledger/Trezor,固件最新
2安装 MetaMask导入硬件钱包
3准备 USDC从 CEX 提现 $12,500 USDC 到 Ethereum 地址
4安装依赖pip install web3 requests python-dotenv

建仓流程(预计耗时:30 分钟):

Step 1: USDC → USDe (DEX Swap)
├─ 访问 app.ethena.fi/swap
├─ 连接硬件钱包
├─ 输入 $12,500 USDC
├─ 确认滑点 < 0.1%
├─ 签名交易(硬件钱包确认)
├─ 等待 1-3 分钟确认
└─ 获得 ~$12,487 USDe(扣除滑点 ~$13)

Step 2: Approve USDe 给 sUSDe 合约
├─ 访问 app.ethena.fi → Stake
├─ 点击 Approve
├─ 硬件钱包签名
└─ Gas ~$0.01(当前 0.1 Gwei)

Step 3: Stake USDe → sUSDe
├─ 输入全部 USDe 金额
├─ 预览获得的 sUSDe 数量
├─ 确认汇率合理
├─ 硬件钱包签名
└─ Gas ~$0.02

Step 4: 验证
├─ 检查 sUSDe 余额
├─ 记录获得的 sUSDe 数量
├─ 记录当前 sUSDe:USDe 汇率
└─ 设置监控告警

费用汇总

项目金额占比
DEX 滑点$130.10%
Gas (Approve)$0.010.00%
Gas (Stake)$0.020.00%
总计$130.10%

8.2 日常维护 Checklist

每日(2 分钟)

每周(10 分钟)

每月(30 分钟)

监控脚本自动化

# 设置每 4 小时自动检查
python monitor_funding.py >> /var/log/ethena_monitor.log

8.3 紧急退出 SOP

场景 A:USDe 脱锚(peg < $0.990)

1. 立即访问 Curve 或 1inch
2. 市价卖出全部 sUSDe → USDC
3. 接受 1-2% 折价损失
4. 将 USDC 转入 CEX 或换成其他稳定币
5. 事后复盘,记录教训

场景 B:sUSDe APY 持续低迷(< 2% 连续 7 天)

1. 发起 cooldown(gas ~$0.02)
2. 记录 cooldown 到期时间
3. 设置日历提醒(7 天后)
4. 到期后 claim USDe
5. Swap USDe → USDC
6. 转入 SUSDS 或 BIL

场景 C:计划退出(正常再平衡)

1. 提前 10 天规划
2. 发起 cooldown
3. 等待 7 天
4. Claim + Swap
5. 完成再平衡

8.4 成本效益总结

$12,500 sUSDe 仓位年度成本预估

项目金额说明
建仓成本$13DEX 滑点
Gas(日常操作)~$0.1极低
Cooldown 机会成本$8/次仅在退出时
总摩擦成本~$21/年假设年退出 1 次

预期收益(以 3.49% APY):

指标数值
名义年化收益$436
摩擦成本$21
净收益$415
净收益率3.32%

与替代方案对比

资产APY风险净收益($12.5K)
sUSDe3.49%DeFi + CEX 对冲$415
SUSDS3.75%MakerDAO + RWA$469
BIL4.2%近乎无风险$525
Aave USDC2.24%DeFi$280

结论:当前环境下(sUSDe 3.49% < SUSDS 3.75% < BIL 4.2%),sUSDe 不是最优选择。建议:


检查线自检

事实来源清单

#事实来源
1sUSDe 合约地址 0x9D39A5DE30e57443BfF2A8307A4256c8797A3497DeFiLlama、Ethena 官方
2USDe 合约地址 0x4c9EDD5852cd905f086C759E8383e09bff1E68B3CoinGecko、Etherscan
3StakingRewardsDistributor 0xf2fa332bd83149c66b09b45670bce64746c6b439Ethena 官方文档 (docs.ethena.fi)
4sUSDe APY 3.49%(2026-03-22 数据)DeFiLlama API(#30 研究)
5SUSDS APY 3.75%(2026-03-22 数据)DeFiLlama API(#30 研究)
6Cooldown 时长 7 天(604,800 秒)StakedUSDeV2 合约 cooldownDuration()
7当前 Gas 0.1 Gwei,ETH $2,067ultrasound.money(2026-03-26)
8ERC-4626 Token Vault 机制EIP-4626 标准 + Ethena 官方文档
9收益每周通过 StakingRewardsDistributor 分发docs.ethena.fi/solution-overview/protocol-revenue-explanation/susde-rewards-mechanism

独到见解摘要

  1. Gas 在 2026 年已不是决策因素 — 0.1 Gwei 环境下全流程 ~$0.09,真正成本是滑点和机会成本

  2. sUSDe 的隐性成本是 ~$21/年的摩擦 + ~$8 每次 cooldown 的机会成本 — 大多数 DeFi 收益率对比忽略了这个

  3. 当前 sUSDe(3.49%)风险调整后收益低于 SUSDS(3.75%)和 BIL(4.2%) — 不应增配

  4. $12.5K 规模下 DEX 流动性完全充足 — 滑点 < 0.01%,但恐慌时可能扩大到 0.5-2%

  5. 硬件钱包 + EIP-1559 + 3 确认 是安全执行的标准配置 — 无需过度复杂的安全措施


研究完成时间:2026-03-26 数据时效声明:所有市场数据为 2026-03-22~26 查询结果,操作前请再次确认最新数据。