Skip to content
On this page

L1-6: Rebasing Token(弹性供应代币)⭐

1. 问题

创建类似 AMPL (Ampleforth) 的弹性供应 ERC20 代币。总供应量可以通过 rebase 调整,所有持有者余额按比例变化。

例如:总供应 10M → rebase(-9M) → 总供应 1M,每个持有者余额变为原来的 1/10。

2. 原因

AMPL 的目标是创建「购买力稳定」的货币。通过调整供应量实现价格目标:

  • 价格 > $1 → 正 rebase(增加供应,持有者余额增加)
  • 价格 < $1 → 负 rebase(减少供应,持有者余额减少)

技术上不可能遍历所有持有者修改余额(Gas ∞),需要间接方案。

3. 方案

核心机制:GONs + 缩放因子

内部表示 (GONs):    _gonBalances[addr]     // rebase 不改变
缩放因子:            _gonsPerFragment       // rebase 时改变
外部表示 (显示值):   balanceOf = _gonBalances / _gonsPerFragment

Rebase 操作

solidity
function rebase(int256 amount) external onlyOwner {
    uint256 currentTotal = totalSupply();  // GONs / _gonsPerFragment
    uint256 newTotal = currentTotal + amount;  // (正rebase) 或 currentTotal - decreaseBy (负rebase)
    _gonsPerFragment = _gonTotalSupply / newTotal;
    // 无需修改任何 _gonBalances!
}

为什么有效

  • 正 rebase: 总供应 10M → 11M,_gonsPerFragment 从 1e18 变为 _gonTotalSupply / 11M(变小)
  • balanceOf = _gonBalances / _gonsPerFragment(分子不变,分母变小 = 结果变大)

4. 遇到的陷阱 ⭐

4.1 transfer/transferFrom 金额需转换

用户传入的 amount显示值,内部必须转换为 GONs:

solidity
function transfer(address to, uint256 amount) public override returns (bool) {
    uint256 gonAmount = amount * _gonsPerFragment;
    _transferGon(msg.sender, to, gonAmount);
    emit Transfer(msg.sender, to, amount);
    return true;
}

4.2 allowance 不受 rebase 影响

OZ ERC20 的 allowance 存储的是显示值,不是 GONs。transferFrom 必须正确处理:

solidity
_spendAllowance(from, msg.sender, amount); // 按显示值扣 allowance
_transferGon(from, to, gonAmount);         // 按 GONs 转账

4.3 整数除法精度损失

多次 rebase 后 _gonsPerFragment 可能累积误差。_gonTotalSupply / newTotal 有舍入误差。

5. 陷阱的原因

5.1

如果 transfer 不转换,用户转出 100 tokens,实际只转出 100 GONs。但 _gonsPerFragment 可能 > 1 或 < 1,导致实际金额和预期严重不符。

5.2

allowance 语义:用户授权的是「显示值」,不是 GONs。如果 allowance 也按 GONs 缩放,授权量会随 rebase 变化(不符合预期)。

5.3

Solidity 整数除法截断。每次 rebase 累积舍入误差可能导致 balanceOf 之和 ≠ totalSupply

6. 如何解决陷阱

  • 所有外部接口(transfer/transferFrom/approve)的参数和 events 使用显示值
  • 内部存储和计算使用 GONs
  • allowance 存储和消费使用显示值(调用 _spendAllowance 时传显示值)
  • 对于精度损失:使用高精度(1e18 作为初始 _gonsPerFragment)减小舍入影响

7. 技术要点

要点说明
GONs 模式内部固定单位 + 外部可变比例
AMPL 原理弹性供应实现购买力稳定
ERC20 覆盖balanceOf / totalSupply / transfer / transferFrom 全部重写
Allowance 隔离allowance 不受 rebase 影响
精度处理使用 18 位小数精度 = 1e18 基准

Built with AiAda