编译器
0.8.28+commit.7893614a
文件 1 的 46:512Math.sol
pragma solidity =0.8.28;
import {Panic} from "./Panic.sol";
import {UnsafeMath} from "./UnsafeMath.sol";
type uint512 is bytes32;
function alloc() pure returns (uint512 r) {
assembly ("memory-safe") {
r := mload(0x40)
mstore(0x40, add(0x40, r))
}
}
function tmp() pure returns (uint512 r) {}
library Lib512MathAccessors {
function from(uint512 r, uint256 x) internal pure returns (uint512 r_out) {
assembly ("memory-safe") {
mstore(r, 0x00)
mstore(add(0x20, r), x)
r_out := r
}
}
function from(uint512 r, uint256 x_hi, uint256 x_lo) internal pure returns (uint512 r_out) {
assembly ("memory-safe") {
mstore(r, x_hi)
mstore(add(0x20, r), x_lo)
r_out := r
}
}
function from(uint512 r, uint512 x) internal pure returns (uint512 r_out) {
assembly ("memory-safe") {
mstore(r, mload(x))
mstore(add(0x20, r), mload(add(0x20, x)))
r_out := r
}
}
function into(uint512 x) internal pure returns (uint256 r_hi, uint256 r_lo) {
assembly ("memory-safe") {
r_hi := mload(x)
r_lo := mload(add(0x20, x))
}
}
}
using Lib512MathAccessors for uint512 global;
library Lib512MathComparisons {
function isZero(uint512 x) internal pure returns (bool r) {
(uint256 x_hi, uint256 x_lo) = x.into();
assembly ("memory-safe") {
r := iszero(or(x_hi, x_lo))
}
}
function isMax(uint512 x) internal pure returns (bool r) {
(uint256 x_hi, uint256 x_lo) = x.into();
assembly ("memory-safe") {
r := iszero(not(and(x_hi, x_lo)))
}
}
function eq(uint512 x, uint256 y) internal pure returns (bool r) {
(uint256 x_hi, uint256 x_lo) = x.into();
assembly ("memory-safe") {
r := and(iszero(x_hi), eq(x_lo, y))
}
}
function gt(uint512 x, uint256 y) internal pure returns (bool r) {
(uint256 x_hi, uint256 x_lo) = x.into();
assembly ("memory-safe") {
r := or(gt(x_hi, 0x00), gt(x_lo, y))
}
}
function lt(uint512 x, uint256 y) internal pure returns (bool r) {
(uint256 x_hi, uint256 x_lo) = x.into();
assembly ("memory-safe") {
r := and(iszero(x_hi), lt(x_lo, y))
}
}
function ne(uint512 x, uint256 y) internal pure returns (bool) {
return !eq(x, y);
}
function ge(uint512 x, uint256 y) internal pure returns (bool) {
return !lt(x, y);
}
function le(uint512 x, uint256 y) internal pure returns (bool) {
return !gt(x, y);
}
function eq(uint512 x, uint512 y) internal pure returns (bool r) {
(uint256 x_hi, uint256 x_lo) = x.into();
(uint256 y_hi, uint256 y_lo) = y.into();
assembly ("memory-safe") {
r := and(eq(x_hi, y_hi), eq(x_lo, y_lo))
}
}
function gt(uint512 x, uint512 y) internal pure returns (bool r) {
(uint256 x_hi, uint256 x_lo) = x.into();
(uint256 y_hi, uint256 y_lo) = y.into();
assembly ("memory-safe") {
r := or(gt(x_hi, y_hi), and(eq(x_hi, y_hi), gt(x_lo, y_lo)))
}
}
function lt(uint512 x, uint512 y) internal pure returns (bool r) {
(uint256 x_hi, uint256 x_lo) = x.into();
(uint256 y_hi, uint256 y_lo) = y.into();
assembly ("memory-safe") {
r := or(lt(x_hi, y_hi), and(eq(x_hi, y_hi), lt(x_lo, y_lo)))
}
}
function ne(uint512 x, uint512 y) internal pure returns (bool) {
return !eq(x, y);
}
function ge(uint512 x, uint512 y) internal pure returns (bool) {
return !lt(x, y);
}
function le(uint512 x, uint512 y) internal pure returns (bool) {
return !gt(x, y);
}
}
using Lib512MathComparisons for uint512 global;
function __eq(uint512 x, uint512 y) pure returns (bool) {
return x.eq(y);
}
function __gt(uint512 x, uint512 y) pure returns (bool) {
return x.gt(y);
}
function __lt(uint512 x, uint512 y) pure returns (bool r) {
return x.lt(y);
}
function __ne(uint512 x, uint512 y) pure returns (bool) {
return x.ne(y);
}
function __ge(uint512 x, uint512 y) pure returns (bool) {
return x.ge(y);
}
function __le(uint512 x, uint512 y) pure returns (bool) {
return x.le(y);
}
using {__eq as ==, __gt as >, __lt as <, __ne as !=, __ge as >=, __le as <=} for uint512 global;
library Lib512MathArithmetic {
using UnsafeMath for uint256;
function oadd(uint512 r, uint256 x, uint256 y) internal pure returns (uint512) {
uint256 r_hi;
uint256 r_lo;
assembly ("memory-safe") {
r_lo := add(x, y)
r_hi := lt(r_lo, x)
}
return r.from(r_hi, r_lo);
}
function oadd(uint512 r, uint512 x, uint256 y) internal pure returns (uint512) {
(uint256 x_hi, uint256 x_lo) = x.into();
uint256 r_hi;
uint256 r_lo;
assembly ("memory-safe") {
r_lo := add(x_lo, y)
r_hi := add(x_hi, lt(r_lo, x_lo))
}
return r.from(r_hi, r_lo);
}
function iadd(uint512 r, uint256 y) internal pure returns (uint512) {
return oadd(r, r, y);
}
function _add(uint256 x_hi, uint256 x_lo, uint256 y_hi, uint256 y_lo)
private
pure
returns (uint256 r_hi, uint256 r_lo)
{
assembly ("memory-safe") {
r_lo := add(x_lo, y_lo)
r_hi := add(add(x_hi, y_hi), lt(r_lo, x_lo))
}
}
function oadd(uint512 r, uint512 x, uint512 y) internal pure returns (uint512) {
(uint256 x_hi, uint256 x_lo) = x.into();
(uint256 y_hi, uint256 y_lo) = y.into();
(uint256 r_hi, uint256 r_lo) = _add(x_hi, x_lo, y_hi, y_lo);
return r.from(r_hi, r_lo);
}
function iadd(uint512 r, uint512 y) internal pure returns (uint512) {
return oadd(r, r, y);
}
function _sub(uint256 x_hi, uint256 x_lo, uint256 y) private pure returns (uint256 r_hi, uint256 r_lo) {
assembly ("memory-safe") {
r_lo := sub(x_lo, y)
r_hi := sub(x_hi, gt(r_lo, x_lo))
}
}
function osub(uint512 r, uint512 x, uint256 y) internal pure returns (uint512) {
(uint256 x_hi, uint256 x_lo) = x.into();
(uint256 r_hi, uint256 r_lo) = _sub(x_hi, x_lo, y);
return r.from(r_hi, r_lo);
}
function isub(uint512 r, uint256 y) internal pure returns (uint512) {
return osub(r, r, y);
}
function _sub(uint256 x_hi, uint256 x_lo, uint256 y_hi, uint256 y_lo)
private
pure
returns (uint256 r_hi, uint256 r_lo)
{
assembly ("memory-safe") {
r_lo := sub(x_lo, y_lo)
r_hi := sub(sub(x_hi, y_hi), gt(r_lo, x_lo))
}
}
function osub(uint512 r, uint512 x, uint512 y) internal pure returns (uint512) {
(uint256 x_hi, uint256 x_lo) = x.into();
(uint256 y_hi, uint256 y_lo) = y.into();
(uint256 r_hi, uint256 r_lo) = _sub(x_hi, x_lo, y_hi, y_lo);
return r.from(r_hi, r_lo);
}
function isub(uint512 r, uint512 y) internal pure returns (uint512) {
return osub(r, r, y);
}
function irsub(uint512 r, uint512 y) internal pure returns (uint512) {
return osub(r, y, r);
}
function sub(uint512 x, uint256 y) internal pure returns (uint256 r) {
assembly ("memory-safe") {
r := sub(mload(add(0x20, x)), y)
}
}
function sub(uint512 x, uint512 y) internal pure returns (uint256 r) {
assembly ("memory-safe") {
r := sub(mload(add(0x20, x)), mload(add(0x20, y)))
}
}
function _mul(uint256 x, uint256 y) private pure returns (uint256 r_hi, uint256 r_lo) {
assembly ("memory-safe") {
let mm := mulmod(x, y, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
r_lo := mul(x, y)
r_hi := sub(sub(mm, r_lo), lt(mm, r_lo))
}
}
function omul(uint512 r, uint256 x, uint256 y) internal pure returns (uint512) {
(uint256 r_hi, uint256 r_lo) = _mul(x, y);
return r.from(r_hi, r_lo);
}
function _mul(uint256 x_hi, uint256 x_lo, uint256 y) private pure returns (uint256 r_hi, uint256 r_lo) {
assembly ("memory-safe") {
let mm := mulmod(x_lo, y, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
r_lo := mul(x_lo, y)
r_hi := add(mul(x_hi, y), sub(sub(mm, r_lo), lt(mm, r_lo)))
}
}
function omul(uint512 r, uint512 x, uint256 y) internal pure returns (uint512) {
(uint256 x_hi, uint256 x_lo) = x.into();
(uint256 r_hi, uint256 r_lo) = _mul(x_hi, x_lo, y);
return r.from(r_hi, r_lo);
}
function imul(uint512 r, uint256 y) internal pure returns (uint512) {
return omul(r, r, y);
}
function _mul(uint256 x_hi, uint256 x_lo, uint256 y_hi, uint256 y_lo)
private
pure
returns (uint256 r_hi, uint256 r_lo)
{
assembly ("memory-safe") {
let mm := mulmod(x_lo, y_lo, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
r_lo := mul(x_lo, y_lo)
r_hi := add(add(mul(x_hi, y_lo), mul(x_lo, y_hi)), sub(sub(mm, r_lo), lt(mm, r_lo)))
}
}
function omul(uint512 r, uint512 x, uint512 y) internal pure returns (uint512) {
(uint256 x_hi, uint256 x_lo) = x.into();
(uint256 y_hi, uint256 y_lo) = y.into();
(uint256 r_hi, uint256 r_lo) = _mul(x_hi, x_lo, y_hi, y_lo);
return r.from(r_hi, r_lo);
}
function imul(uint512 r, uint512 y) internal pure returns (uint512) {
return omul(r, r, y);
}
function mod(uint512 n, uint256 d) internal pure returns (uint256 r) {
if (d == 0) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
(uint256 n_hi, uint256 n_lo) = n.into();
assembly ("memory-safe") {
r := mulmod(n_hi, sub(0x00, d), d)
r := addmod(n_lo, r, d)
}
}
function _mul768(uint256 x_hi, uint256 x_lo, uint256 y)
private
pure
returns (uint256 r_ex, uint256 r_hi, uint256 r_lo)
{
assembly ("memory-safe") {
let mm0 := mulmod(x_lo, y, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
r_lo := mul(x_lo, y)
let mm1 := mulmod(x_hi, y, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
let r_partial := mul(x_hi, y)
r_ex := sub(sub(mm1, r_partial), lt(mm1, r_partial))
r_hi := add(r_partial, sub(sub(mm0, r_lo), lt(mm0, r_lo)))
r_ex := add(r_ex, lt(r_hi, r_partial))
}
}
function _roundDown(uint256 x_hi, uint256 x_lo, uint256 d) private pure returns (uint256 r_hi, uint256 r_lo) {
assembly ("memory-safe") {
let rem := mulmod(x_hi, sub(0x00, d), d)
rem := addmod(x_lo, rem, d)
r_hi := sub(x_hi, gt(rem, x_lo))
r_lo := sub(x_lo, rem)
}
}
function _twos(uint256 x) private pure returns (uint256 twos, uint256 twosInv) {
assembly ("memory-safe") {
twos := and(sub(0x00, x), x)
twosInv := add(div(sub(0x00, twos), twos), 0x01)
}
}
function _toOdd256(uint256 x_hi, uint256 x_lo, uint256 y) private pure returns (uint256 rx_lo, uint256 ry) {
(uint256 twos, uint256 twosInv) = _twos(y);
assembly ("memory-safe") {
ry := div(y, twos)
rx_lo := or(div(x_lo, twos), mul(x_hi, twosInv))
}
}
function _toOdd256Multi(uint256 x_hi, uint256 x_lo, uint256 y_hi, uint256 y_lo, uint256 d)
private
pure
returns (uint256 rx_lo, uint256 ry_lo, uint256 rd)
{
(uint256 twos, uint256 twosInv) = _twos(d);
assembly ("memory-safe") {
rd := div(d, twos)
rx_lo := or(div(x_lo, twos), mul(x_hi, twosInv))
ry_lo := or(div(y_lo, twos), mul(y_hi, twosInv))
}
}
function _toOdd512(uint256 x_hi, uint256 x_lo, uint256 y)
private
pure
returns (uint256 rx_hi, uint256 rx_lo, uint256 ry)
{
(uint256 twos, uint256 twosInv) = _twos(y);
assembly ("memory-safe") {
ry := div(y, twos)
rx_hi := div(x_hi, twos)
rx_lo := or(div(x_lo, twos), mul(x_hi, twosInv))
}
}
function _invert256(uint256 d) private pure returns (uint256 inv) {
assembly ("memory-safe") {
inv := xor(mul(0x03, d), 0x02)
inv := mul(inv, sub(0x02, mul(d, inv)))
inv := mul(inv, sub(0x02, mul(d, inv)))
inv := mul(inv, sub(0x02, mul(d, inv)))
inv := mul(inv, sub(0x02, mul(d, inv)))
inv := mul(inv, sub(0x02, mul(d, inv)))
inv := mul(inv, sub(0x02, mul(d, inv)))
}
}
function _invert512(uint256 d) private pure returns (uint256 inv_hi, uint256 inv_lo) {
inv_lo = _invert256(d);
(uint256 tmp_hi, uint256 tmp_lo) = _mul(d, inv_lo);
(tmp_hi, tmp_lo) = _sub(0, 2, tmp_hi, tmp_lo);
assembly ("memory-safe") {
let mm := mulmod(inv_lo, tmp_lo, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
inv_hi := add(mul(inv_lo, tmp_hi), sub(sub(mm, inv_lo), lt(mm, inv_lo)))
}
}
function div(uint512 n, uint256 d) internal pure returns (uint256) {
if (d == 0) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
(uint256 n_hi, uint256 n_lo) = n.into();
if (n_hi == 0) {
return n_lo.unsafeDiv(d);
}
(n_hi, n_lo) = _roundDown(n_hi, n_lo, d);
(n_lo, d) = _toOdd256(n_hi, n_lo, d);
d = _invert256(d);
unchecked {
return n_lo * d;
}
}
function divMulti(uint512 n0, uint512 n1, uint256 d) internal pure returns (uint256, uint256) {
if (d == 0) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
(uint256 n0_hi, uint256 n0_lo) = n0.into();
(uint256 n1_hi, uint256 n1_lo) = n1.into();
{
bool condition;
assembly ("memory-safe") {
condition := iszero(or(n0_hi, n1_hi))
}
if (condition) {
return (n0_lo.unsafeDiv(d), n1_lo.unsafeDiv(d));
}
}
(n0_hi, n0_lo) = _roundDown(n0_hi, n0_lo, d);
(n1_hi, n1_lo) = _roundDown(n1_hi, n1_lo, d);
(n0_lo, n1_lo, d) = _toOdd256Multi(n0_hi, n0_lo, n1_hi, n1_lo, d);
d = _invert256(d);
unchecked {
return (n0_lo * d, n1_lo * d);
}
}
function _gt(uint256 x_hi, uint256 x_lo, uint256 y_hi, uint256 y_lo) private pure returns (bool r) {
assembly ("memory-safe") {
r := or(gt(x_hi, y_hi), and(eq(x_hi, y_hi), gt(x_lo, y_lo)))
}
}
function odiv(uint512 r, uint512 x, uint256 y) internal pure returns (uint512) {
if (y == 0) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
(uint256 x_hi, uint256 x_lo) = x.into();
if (x_hi == 0) {
return r.from(0, x_lo.unsafeDiv(y));
}
(x_hi, x_lo) = _roundDown(x_hi, x_lo, y);
(x_hi, x_lo, y) = _toOdd512(x_hi, x_lo, y);
(uint256 inv_hi, uint256 inv_lo) = _invert512(y);
(uint256 r_hi, uint256 r_lo) = _mul(x_hi, x_lo, inv_hi, inv_lo);
return r.from(r_hi, r_lo);
}
function idiv(uint512 r, uint256 y) internal pure returns (uint512) {
return odiv(r, r, y);
}
function _gt(uint256 x_ex, uint256 x_hi, uint256 x_lo, uint256 y_ex, uint256 y_hi, uint256 y_lo)
private
pure
returns (bool r)
{
assembly ("memory-safe") {
r :=
or(
or(gt(x_ex, y_ex), and(eq(x_ex, y_ex), gt(x_hi, y_hi))),
and(and(eq(x_ex, y_ex), eq(x_hi, y_hi)), gt(x_lo, y_lo))
)
}
}
function _correctQ(uint256 q, uint256 r, uint256 x_next, uint256 y_next, uint256 y_whole)
private
pure
returns (uint256 q_out)
{
assembly ("memory-safe") {
let c1 := mul(q, y_next)
let c2 := or(shl(0x80, r), x_next)
q_out := sub(q, shl(gt(sub(c1, c2), y_whole), gt(c1, c2)))
}
}
function _algorithmD(uint256 x_hi, uint256 x_lo, uint256 y_hi, uint256 y_lo) private pure returns (uint256 q) {
if (y_hi >> 128 != 0) {
uint256 d = uint256(1 << 128).unsafeDiv((y_hi >> 128).unsafeInc());
uint256 x_ex;
(x_ex, x_hi, x_lo) = _mul768(x_hi, x_lo, d);
(y_hi, y_lo) = _mul(y_hi, y_lo, d);
uint256 n_approx = (x_ex << 128) | (x_hi >> 128);
uint256 d_approx = y_hi >> 128;
q = n_approx.unsafeDiv(d_approx);
uint256 r_hat = n_approx.unsafeMod(d_approx);
q = _correctQ(q, r_hat, x_hi & type(uint128).max, y_hi & type(uint128).max, y_hi);
{
(uint256 tmp_ex, uint256 tmp_hi, uint256 tmp_lo) = _mul768(y_hi, y_lo, q);
bool neg = _gt(tmp_ex, tmp_hi, tmp_lo, x_ex, x_hi, x_lo);
assembly ("memory-safe") {
q := sub(q, neg)
}
}
} else {
uint256 d = uint256(1 << 128).unsafeDiv(y_hi.unsafeInc());
(y_hi, y_lo) = _mul(y_hi, y_lo, d);
uint256 y_next = y_lo >> 128;
uint256 y_whole = (y_hi << 128) | y_next;
if (x_hi >> 128 != 0) {
uint256 x_ex;
(x_ex, x_hi, x_lo) = _mul768(x_hi, x_lo, d);
uint256 n_approx = (x_ex << 128) | (x_hi >> 128);
uint256 q_hat = n_approx.unsafeDiv(y_hi);
uint256 r_hat = n_approx.unsafeMod(y_hi);
q_hat = _correctQ(q_hat, r_hat, x_hi & type(uint128).max, y_next, y_whole);
q = q_hat << 128;
{
(uint256 tmp_hi, uint256 tmp_lo) = _mul(y_hi, y_lo, q_hat);
uint256 tmp_ex = tmp_hi >> 128;
tmp_hi = (tmp_hi << 128) | (tmp_lo >> 128);
tmp_lo <<= 128;
bool neg = _gt(tmp_ex, tmp_hi, tmp_lo, x_ex, x_hi, x_lo);
(x_hi, x_lo) = _sub(x_hi, x_lo, tmp_hi, tmp_lo);
if (neg) {
unchecked {
q -= 1 << 128;
}
(x_hi, x_lo) = _add(x_hi, x_lo, y_whole, y_lo << 128);
}
}
q_hat = x_hi.unsafeDiv(y_hi);
r_hat = x_hi.unsafeMod(y_hi);
q_hat = _correctQ(q_hat, r_hat, x_lo >> 128, y_next, y_whole);
{
(uint256 tmp_hi, uint256 tmp_lo) = _mul(y_hi, y_lo, q_hat);
bool neg = _gt(tmp_hi, tmp_lo, x_hi, x_lo);
assembly ("memory-safe") {
q_hat := sub(q_hat, neg)
}
}
q |= q_hat;
} else {
(x_hi, x_lo) = _mul(x_hi, x_lo, d);
q = x_hi.unsafeDiv(y_hi);
uint256 r_hat = x_hi.unsafeMod(y_hi);
q = _correctQ(q, r_hat, x_lo >> 128, y_next, y_whole);
{
(uint256 tmp_hi, uint256 tmp_lo) = _mul(y_hi, y_lo, q);
bool neg = _gt(tmp_hi, tmp_lo, x_hi, x_lo);
assembly ("memory-safe") {
q := sub(q, neg)
}
}
}
}
}
function _clzLower(uint256 x) private pure returns (uint256 r) {
assembly ("memory-safe") {
r := shl(0x06, lt(0xffffffffffffffff, x))
r := or(r, shl(0x05, lt(0xffffffff, shr(r, x))))
r := or(r, shl(0x04, lt(0xffff, shr(r, x))))
r := or(r, shl(0x03, lt(0xff, shr(r, x))))
r :=
xor(
r,
byte(
and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
0x7879797a797d7a7b797d7c7d7a7b7c7e797a7d7a7c7c7b7e7a7a7c7b7f7f7f7f
)
)
}
}
function _clzUpper(uint256 x) private pure returns (uint256) {
return _clzLower(x >> 128);
}
function _shl(uint256 x_hi, uint256 x_lo, uint256 s) private pure returns (uint256 r_hi, uint256 r_lo) {
assembly ("memory-safe") {
r_hi := or(shl(s, x_hi), shr(sub(0x100, s), x_lo))
r_lo := shl(s, x_lo)
}
}
function _shl768(uint256 x_hi, uint256 x_lo, uint256 s)
private
pure
returns (uint256 r_ex, uint256 r_hi, uint256 r_lo)
{
assembly ("memory-safe") {
let neg_s := sub(0x100, s)
r_ex := shr(neg_s, x_hi)
r_hi := or(shl(s, x_hi), shr(neg_s, x_lo))
r_lo := shl(s, x_lo)
}
}
function _shr(uint256 x_hi, uint256 x_lo, uint256 s) private pure returns (uint256 r_hi, uint256 r_lo) {
assembly ("memory-safe") {
r_hi := shr(s, x_hi)
r_lo := or(shl(sub(0x100, s), x_hi), shr(s, x_lo))
}
}
function _algorithmDRemainder(uint256 x_hi, uint256 x_lo, uint256 y_hi, uint256 y_lo)
private
pure
returns (uint256, uint256)
{
uint256 s;
if (y_hi >> 128 != 0) {
s = _clzUpper(y_hi);
uint256 x_ex;
(x_ex, x_hi, x_lo) = _shl768(x_hi, x_lo, s);
(y_hi, y_lo) = _shl(y_hi, y_lo, s);
uint256 n_approx = (x_ex << 128) | (x_hi >> 128);
uint256 d_approx = y_hi >> 128;
uint256 q_hat = n_approx.unsafeDiv(d_approx);
uint256 r_hat = n_approx.unsafeMod(d_approx);
q_hat = _correctQ(q_hat, r_hat, x_hi & type(uint128).max, y_hi & type(uint128).max, y_hi);
{
(uint256 tmp_ex, uint256 tmp_hi, uint256 tmp_lo) = _mul768(y_hi, y_lo, q_hat);
bool neg = _gt(tmp_ex, tmp_hi, tmp_lo, x_ex, x_hi, x_lo);
(x_hi, x_lo) = _sub(x_hi, x_lo, tmp_hi, tmp_lo);
if (neg) {
(x_hi, x_lo) = _add(x_hi, x_lo, y_hi, y_lo);
}
}
} else {
s = _clzLower(y_hi);
(y_hi, y_lo) = _shl(y_hi, y_lo, s);
uint256 y_next = y_lo >> 128;
uint256 y_whole = (y_hi << 128) | y_next;
if (x_hi >> 128 != 0) {
uint256 x_ex;
(x_ex, x_hi, x_lo) = _shl768(x_hi, x_lo, s);
uint256 n_approx = (x_ex << 128) | (x_hi >> 128);
uint256 q_hat = n_approx.unsafeDiv(y_hi);
uint256 r_hat = n_approx.unsafeMod(y_hi);
q_hat = _correctQ(q_hat, r_hat, x_hi & type(uint128).max, y_next, y_whole);
{
(uint256 tmp_hi, uint256 tmp_lo) = _mul(y_hi, y_lo, q_hat);
uint256 tmp_ex = tmp_hi >> 128;
tmp_hi = (tmp_hi << 128) | (tmp_lo >> 128);
tmp_lo <<= 128;
bool neg = _gt(tmp_ex, tmp_hi, tmp_lo, x_ex, x_hi, x_lo);
(x_hi, x_lo) = _sub(x_hi, x_lo, tmp_hi, tmp_lo);
if (neg) {
(x_hi, x_lo) = _add(x_hi, x_lo, y_whole, y_lo << 128);
}
}
q_hat = x_hi.unsafeDiv(y_hi);
r_hat = x_hi.unsafeMod(y_hi);
q_hat = _correctQ(q_hat, r_hat, x_lo >> 128, y_next, y_whole);
{
(uint256 tmp_hi, uint256 tmp_lo) = _mul(y_hi, y_lo, q_hat);
bool neg = _gt(tmp_hi, tmp_lo, x_hi, x_lo);
(x_hi, x_lo) = _sub(x_hi, x_lo, tmp_hi, tmp_lo);
if (neg) {
(x_hi, x_lo) = _add(x_hi, x_lo, y_hi, y_lo);
}
}
} else {
(x_hi, x_lo) = _shl(x_hi, x_lo, s);
uint256 q_hat = x_hi.unsafeDiv(y_hi);
uint256 r_hat = x_hi.unsafeMod(y_hi);
q_hat = _correctQ(q_hat, r_hat, x_lo >> 128, y_next, y_whole);
{
(uint256 tmp_hi, uint256 tmp_lo) = _mul(y_hi, y_lo, q_hat);
bool neg = _gt(tmp_hi, tmp_lo, x_hi, x_lo);
(x_hi, x_lo) = _sub(x_hi, x_lo, tmp_hi, tmp_lo);
if (neg) {
(x_hi, x_lo) = _add(x_hi, x_lo, y_hi, y_lo);
}
}
}
}
return _shr(x_hi, x_lo, s);
}
function odiv(uint512 r, uint512 x, uint512 y) internal pure returns (uint512) {
(uint256 y_hi, uint256 y_lo) = y.into();
if (y_hi == 0) {
return odiv(r, x, y_lo);
}
(uint256 x_hi, uint256 x_lo) = x.into();
if (y_lo == 0) {
uint256 r_lo = x_hi.unsafeDiv(y_hi);
return r.from(0, r_lo);
}
if (_gt(y_hi, y_lo, x_hi, x_lo)) {
return r.from(0, 0);
}
{
uint256 r_lo = _algorithmD(x_hi, x_lo, y_hi, y_lo);
return r.from(0, r_lo);
}
}
function idiv(uint512 r, uint512 y) internal pure returns (uint512) {
return odiv(r, r, y);
}
function irdiv(uint512 r, uint512 y) internal pure returns (uint512) {
return odiv(r, y, r);
}
function div(uint512 x, uint512 y) internal pure returns (uint256) {
(uint256 y_hi, uint256 y_lo) = y.into();
if (y_hi == 0) {
return div(x, y_lo);
}
(uint256 x_hi, uint256 x_lo) = x.into();
if (y_lo == 0) {
return x_hi.unsafeDiv(y_hi);
}
if (_gt(y_hi, y_lo, x_hi, x_lo)) {
return 0;
}
return _algorithmD(x_hi, x_lo, y_hi, y_lo);
}
function omod(uint512 r, uint512 x, uint512 y) internal pure returns (uint512) {
(uint256 y_hi, uint256 y_lo) = y.into();
if (y_hi == 0) {
uint256 r_lo = mod(x, y_lo);
return r.from(0, r_lo);
}
(uint256 x_hi, uint256 x_lo) = x.into();
if (y_lo == 0) {
uint256 r_hi = x_hi.unsafeMod(y_hi);
return r.from(r_hi, x_lo);
}
if (_gt(y_hi, y_lo, x_hi, x_lo)) {
return r.from(x_hi, x_lo);
}
{
(uint256 r_hi, uint256 r_lo) = _algorithmDRemainder(x_hi, x_lo, y_hi, y_lo);
return r.from(r_hi, r_lo);
}
}
function imod(uint512 r, uint512 y) internal pure returns (uint512) {
return omod(r, r, y);
}
function irmod(uint512 r, uint512 y) internal pure returns (uint512) {
return omod(r, y, r);
}
}
using Lib512MathArithmetic for uint512 global;
library Lib512MathUserDefinedHelpers {
function checkNull(uint512 x, uint512 y) internal pure {
unchecked {
if (uint256(uint512.unwrap(x)) * uint256(uint512.unwrap(y)) == 0) {
Panic.panic(Panic.ASSERT_FAIL);
}
}
}
}
function __add(uint512 x, uint512 y) pure returns (uint512 r) {
Lib512MathUserDefinedHelpers.checkNull(x, y);
r.oadd(x, y);
}
function __sub(uint512 x, uint512 y) pure returns (uint512 r) {
Lib512MathUserDefinedHelpers.checkNull(x, y);
r.osub(x, y);
}
function __mul(uint512 x, uint512 y) pure returns (uint512 r) {
Lib512MathUserDefinedHelpers.checkNull(x, y);
r.omul(x, y);
}
function __mod(uint512 x, uint512 y) pure returns (uint512 r) {
Lib512MathUserDefinedHelpers.checkNull(x, y);
r.omod(x, y);
}
function __div(uint512 x, uint512 y) pure returns (uint512 r) {
Lib512MathUserDefinedHelpers.checkNull(x, y);
r.odiv(x, y);
}
using {__add as +, __sub as -, __mul as *, __mod as %, __div as / } for uint512 global;
struct uint512_external {
uint256 hi;
uint256 lo;
}
library Lib512MathExternal {
function from(uint512 r, uint512_external memory x) internal pure returns (uint512) {
assembly ("memory-safe") {
mstore(r, mload(x))
mstore(add(0x20, r), mload(add(0x20, x)))
}
return r;
}
function into(uint512_external memory x) internal pure returns (uint512 r) {
assembly ("memory-safe") {
r := x
}
}
function toExternal(uint512 x) internal pure returns (uint512_external memory r) {
assembly ("memory-safe") {
if iszero(eq(mload(0x40), add(0x40, r))) { revert(0x00, 0x00) }
mstore(0x40, r)
r := x
}
}
}
using Lib512MathExternal for uint512 global;
using Lib512MathExternal for uint512_external global;
文件 2 的 46:BasisPoints.sol
pragma solidity ^0.8.28;
import {UnsafeMath} from "../lib/UnsafeMath.sol";
type BasisPoints is uint256;
BasisPoints constant ZERO = BasisPoints.wrap(0);
BasisPoints constant BASIS = BasisPoints.wrap(10_000);
library BasisPointsArithmetic {
using UnsafeMath for uint256;
function mul(BasisPoints x, uint256 y) internal pure returns (BasisPoints) {
unchecked {
return BasisPoints.wrap(BasisPoints.unwrap(x) * y);
}
}
function div(BasisPoints n, uint256 d) internal pure returns (BasisPoints) {
return BasisPoints.wrap(BasisPoints.unwrap(n).unsafeDiv(d));
}
}
using BasisPointsArithmetic for BasisPoints global;
function __sub(BasisPoints a, BasisPoints b) pure returns (BasisPoints) {
unchecked {
return BasisPoints.wrap(BasisPoints.unwrap(a) - BasisPoints.unwrap(b));
}
}
using {__sub as -} for BasisPoints global;
function __eq(BasisPoints a, BasisPoints b) pure returns (bool) {
return BasisPoints.unwrap(a) == BasisPoints.unwrap(b);
}
function __lt(BasisPoints a, BasisPoints b) pure returns (bool) {
return BasisPoints.unwrap(a) < BasisPoints.unwrap(b);
}
function __gt(BasisPoints a, BasisPoints b) pure returns (bool) {
return BasisPoints.unwrap(a) > BasisPoints.unwrap(b);
}
function __ne(BasisPoints a, BasisPoints b) pure returns (bool) {
return BasisPoints.unwrap(a) != BasisPoints.unwrap(b);
}
function __le(BasisPoints a, BasisPoints b) pure returns (bool) {
return BasisPoints.unwrap(a) <= BasisPoints.unwrap(b);
}
function __ge(BasisPoints a, BasisPoints b) pure returns (bool) {
return BasisPoints.unwrap(a) >= BasisPoints.unwrap(b);
}
using {__eq as ==, __lt as <, __gt as >, __ne as !=, __le as <=, __gt as >=} for BasisPoints global;
function scale(uint256 x, BasisPoints bp) pure returns (uint256) {
unchecked {
return x * BasisPoints.unwrap(bp) / BasisPoints.unwrap(BASIS);
}
}
function scaleUp(uint256 x, BasisPoints bp) pure returns (uint256) {
unchecked {
return UnsafeMath.unsafeDivUp(x * BasisPoints.unwrap(bp), BasisPoints.unwrap(BASIS));
}
}
文件 3 的 46:Checkpoints.sol
pragma solidity ^0.8.28;
import {IERC5805} from "../interfaces/IERC5805.sol";
import {Settings} from "./Settings.sol";
import {Votes, ZERO as ZERO_VOTES} from "../types/Votes.sol";
struct Checkpoint {
uint48 key;
uint56 _pad;
uint152 value;
}
struct Checkpoints {
mapping(address => Checkpoint[]) each;
Checkpoint[] total;
}
library LibCheckpoints {
function transfer(Checkpoints storage checkpoints, address from, address to, Votes incr, Votes decr, uint48 clock)
internal
{
if (from == address(0)) {
if (to == address(0)) {
return;
}
return _mint(checkpoints, to, incr, clock);
}
if (to == address(0)) {
return _burn(checkpoints, from, decr, clock);
}
if (from == to) {
if (incr > decr) {
_mint(checkpoints, from, incr - decr, clock);
} else if (incr < decr) {
_burn(checkpoints, to, decr - incr, clock);
}
return;
}
if (incr > decr) {
_mint(checkpoints, incr - decr, clock);
} else if (incr < decr) {
_burn(checkpoints, decr - incr, clock);
}
_burn(checkpoints.each[from], from, decr, clock);
_mint(checkpoints.each[to], to, incr, clock);
}
function mint(Checkpoints storage checkpoints, address to, Votes incr, uint48 clock) internal {
if (to == address(0)) {
return;
}
return _mint(checkpoints, to, incr, clock);
}
function burn(Checkpoints storage checkpoints, address from, Votes decr, uint48 clock) internal {
if (from == address(0)) {
return;
}
return _burn(checkpoints, from, decr, clock);
}
function burn(Checkpoints storage checkpoints, address from0, Votes decr0, address from1, Votes decr1, uint48 clock)
internal
{
if (from0 == address(0)) {
return burn(checkpoints, from1, decr1, clock);
}
if (from1 == address(0)) {
return _burn(checkpoints, from0, decr0, clock);
}
return _burn(checkpoints, from0, decr0, from1, decr1, clock);
}
function _load(Checkpoint[] storage arr)
private
view
returns (Votes value, uint256 len, uint256 key, bytes32 slotValue)
{
assembly ("memory-safe") {
slotValue := sload(arr.slot)
key := shr(0xd0, slotValue)
len := and(0xffffffffffffff, shr(0x98, slotValue))
value := and(0x1ffffffffffffffffffffffffffffffffffff, slotValue)
}
}
function _get(Checkpoint[] storage arr, uint256 clock) private returns (Votes value, uint256 len) {
uint256 key;
bytes32 slotValue;
(value, len, key, slotValue) = _load(arr);
assembly ("memory-safe") {
if mul(key, gt(clock, key)) {
mstore(0x00, arr.slot)
sstore(
add(keccak256(0x00, 0x20), len),
and(0xffffffffffff0000000000000001ffffffffffffffffffffffffffffffffffff, slotValue)
)
len := add(0x01, len)
}
}
}
function _set(Checkpoint[] storage arr, uint256 clock, Votes value, uint256 len) private {
assembly ("memory-safe") {
sstore(
arr.slot, or(shl(0x98, len), or(shl(0xd0, clock), and(0x1ffffffffffffffffffffffffffffffffffff, value)))
)
}
}
function _mintUpdateState(Checkpoints storage checkpoints, Votes incr, uint256 clock) private {
Checkpoint[] storage arr = checkpoints.total;
(Votes oldValue, uint256 len) = _get(arr, clock);
_set(arr, clock, oldValue + incr, len);
}
function _mint(Checkpoints storage checkpoints, Votes incr, uint256 clock) private {
if (incr == ZERO_VOTES) {
return;
}
_mintUpdateState(checkpoints, incr, clock);
}
function _mintUpdateState(Checkpoint[] storage array, address to, Votes incr, uint256 clock) private {
(Votes oldValue, uint256 len) = _get(array, clock);
Votes newValue = oldValue + incr;
_set(array, clock, newValue, len);
emit IERC5805.DelegateVotesChanged(to, oldValue.toExternal(), newValue.toExternal());
}
function _mint(Checkpoint[] storage array, address to, Votes incr, uint256 clock) private {
if (incr == ZERO_VOTES) {
return;
}
_mintUpdateState(array, to, incr, clock);
}
function _mint(Checkpoints storage checkpoints, address to, Votes incr, uint256 clock) private {
if (incr == ZERO_VOTES) {
return;
}
_mintUpdateState(checkpoints, incr, clock);
_mintUpdateState(checkpoints.each[to], to, incr, clock);
}
function _burnUpdateState(Checkpoints storage checkpoints, Votes decr, uint256 clock) private {
Checkpoint[] storage arr = checkpoints.total;
(Votes oldValue, uint256 len) = _get(arr, clock);
_set(arr, clock, oldValue - decr, len);
}
function _burn(Checkpoints storage checkpoints, Votes decr, uint256 clock) private {
if (decr == ZERO_VOTES) {
return;
}
_burnUpdateState(checkpoints, decr, clock);
}
function _burnUpdateState(Checkpoint[] storage array, address from, Votes decr, uint256 clock) private {
(Votes oldValue, uint256 len) = _get(array, clock);
Votes newValue = oldValue - decr;
_set(array, clock, newValue, len);
emit IERC5805.DelegateVotesChanged(from, oldValue.toExternal(), newValue.toExternal());
}
function _burn(Checkpoint[] storage array, address from, Votes decr, uint256 clock) private {
if (decr == ZERO_VOTES) {
return;
}
_burnUpdateState(array, from, decr, clock);
}
function _burn(Checkpoints storage checkpoints, address from, Votes decr, uint256 clock) private {
if (decr == ZERO_VOTES) {
return;
}
_burnUpdateState(checkpoints, decr, clock);
_burnUpdateState(checkpoints.each[from], from, decr, clock);
}
function _burn(
Checkpoints storage checkpoints,
address from0,
Votes decr0,
address from1,
Votes decr1,
uint256 clock
) private {
Votes decr = decr0 + decr1;
if (decr == ZERO_VOTES) {
return;
}
_burnUpdateState(checkpoints, decr, clock);
_burn(checkpoints.each[from0], from0, decr0, clock);
_burn(checkpoints.each[from1], from1, decr1, clock);
}
function current(Checkpoints storage checkpoints, address account) internal view returns (Votes value) {
Checkpoint[] storage each = checkpoints.each[account];
assembly ("memory-safe") {
value := and(0x1ffffffffffffffffffffffffffffffffffff, sload(each.slot))
}
}
function currentTotal(Checkpoints storage checkpoints) internal view returns (Votes value) {
Checkpoint[] storage total = checkpoints.total;
assembly ("memory-safe") {
value := and(0x1ffffffffffffffffffffffffffffffffffff, sload(total.slot))
}
}
function _bisect(Checkpoint[] storage arr, uint256 query) private view returns (Votes value) {
uint256 len;
{
uint256 key;
(value, len, key,) = _load(arr);
if (key <= query) {
return value;
}
}
uint256 initialWindow = Settings.BISECT_WINDOW_DEFAULT;
assembly ("memory-safe") {
mstore(0x00, arr.slot)
let start := keccak256(0x00, 0x20)
let hi := add(start, len)
let lo := sub(hi, initialWindow)
for {} true {} {
if lt(lo, start) {
lo := start
value := 0x00
break
}
value := sload(lo)
if iszero(gt(shr(0xd0, value), query)) {
lo := add(0x01, lo)
break
}
let newLo := sub(lo, shl(0x01, sub(hi, lo)))
hi := lo
lo := newLo
}
for {} xor(hi, lo) {} {
let mid := add(shr(0x01, sub(hi, lo)), lo)
let newValue := sload(mid)
if gt(shr(0xd0, newValue), query) {
hi := mid
continue
}
value := newValue
lo := add(0x01, mid)
}
value := and(0x1ffffffffffffffffffffffffffffffffffff, value)
}
}
function get(Checkpoints storage checkpoints, address account, uint48 timepoint) internal view returns (Votes) {
return _bisect(checkpoints.each[account], timepoint);
}
function getTotal(Checkpoints storage checkpoints, uint48 timepoint) internal view returns (Votes) {
return _bisect(checkpoints.total, timepoint);
}
}
文件 4 的 46:ChecksumAddress.sol
pragma solidity ^0.8.28;
library ChecksumAddress {
function toChecksumAddress(address addr) internal pure returns (string memory r) {
assembly ("memory-safe") {
r := mload(0x40)
mstore(0x40, add(0x60, r))
mstore(0x0f, 0x30313233343536373839616263646566)
mstore(add(0x02, r), 0x3078)
mstore(r, 0x2a)
addr := shl(0x60, addr)
let o := add(0x22, r)
for { let i } true {} {
let p := add(o, add(i, i))
let temp := byte(i, addr)
mstore8(add(0x01, p), mload(and(0x0f, temp)))
mstore8(p, mload(shr(0x04, temp)))
i := add(0x01, i)
if eq(i, 0x14) { break }
}
let hash := and(0x8888888888888888888888888888888888888888000000000000000000000000, keccak256(o, 0x28))
for { let i } true {} {
mstore(add(i, i), mul(0x88000000000000000000000000000000000000000000000000000000000000, byte(i, hash)))
i := add(0x01, i)
if eq(i, 0x14) { break }
}
let mask := 0x4040404040404040404040404040404040404040404040404040404040404040
mstore(o, xor(mload(o), shr(0x01, and(mload(0x00), and(mload(o), mask)))))
o := add(0x20, o)
mstore(o, xor(mload(o), shr(0x01, and(mload(0x20), and(mload(o), mask)))))
}
}
}
文件 5 的 46:Context.sol
pragma solidity ^0.8.28;
abstract contract AbstractContext {
function _msgSender() internal view virtual returns (address);
function _msgData() internal view virtual returns (bytes calldata);
function _isForwarded() internal view virtual returns (bool);
}
abstract contract Context is AbstractContext {
function _msgSender() internal view virtual override returns (address) {
return msg.sender;
}
function _msgData() internal view virtual override returns (bytes calldata) {
return msg.data;
}
function _isForwarded() internal view virtual override returns (bool) {
return false;
}
}
文件 6 的 46:CrazyBalance.sol
pragma solidity ^0.8.28;
import {Settings} from "../core/Settings.sol";
import {Math} from "../lib/Math.sol";
import {Shares} from "./Shares.sol";
import {Tokens} from "./Tokens.sol";
import {tmp, SharesToTokens} from "./TokensXShares.sol";
type CrazyBalance is uint256;
library CrazyBalanceAccessors {
function toExternal(CrazyBalance x) internal pure returns (uint256) {
return CrazyBalance.unwrap(x);
}
function isMax(CrazyBalance x) internal pure returns (bool) {
return ~CrazyBalance.unwrap(x) == 0;
}
}
using CrazyBalanceAccessors for CrazyBalance global;
function toCrazyBalance(uint256 x) pure returns (CrazyBalance) {
return CrazyBalance.wrap(x);
}
CrazyBalance constant ZERO = CrazyBalance.wrap(0);
CrazyBalance constant MAX = CrazyBalance.wrap(type(uint256).max);
function __sub(CrazyBalance a, CrazyBalance b) pure returns (CrazyBalance) {
unchecked {
return CrazyBalance.wrap(CrazyBalance.unwrap(a) - CrazyBalance.unwrap(b));
}
}
function __eq(CrazyBalance a, CrazyBalance b) pure returns (bool) {
return CrazyBalance.unwrap(a) == CrazyBalance.unwrap(b);
}
function __lt(CrazyBalance a, CrazyBalance b) pure returns (bool) {
return CrazyBalance.unwrap(a) < CrazyBalance.unwrap(b);
}
function __gt(CrazyBalance a, CrazyBalance b) pure returns (bool) {
return CrazyBalance.unwrap(a) > CrazyBalance.unwrap(b);
}
function __ne(CrazyBalance a, CrazyBalance b) pure returns (bool) {
return CrazyBalance.unwrap(a) != CrazyBalance.unwrap(b);
}
function __le(CrazyBalance a, CrazyBalance b) pure returns (bool) {
return CrazyBalance.unwrap(a) <= CrazyBalance.unwrap(b);
}
function __ge(CrazyBalance a, CrazyBalance b) pure returns (bool) {
return CrazyBalance.unwrap(a) >= CrazyBalance.unwrap(b);
}
using {__sub as -, __eq as ==, __lt as <, __gt as >, __ne as !=, __le as <=, __ge as >=} for CrazyBalance global;
library CrazyBalanceArithmetic {
using SharesToTokens for Shares;
function saturatingAdd(CrazyBalance x, CrazyBalance y) internal pure returns (CrazyBalance r) {
return CrazyBalance.wrap(Math.saturatingAdd(CrazyBalance.unwrap(x), CrazyBalance.unwrap(y)));
}
function saturatingSub(CrazyBalance x, CrazyBalance y) internal pure returns (CrazyBalance r) {
return CrazyBalance.wrap(Math.saturatingSub(CrazyBalance.unwrap(x), CrazyBalance.unwrap(y)));
}
function toCrazyBalance(Shares shares, address account, Tokens totalSupply, Shares totalShares)
internal
pure
returns (CrazyBalance)
{
return CrazyBalance.wrap(
Tokens.unwrap(
tmp().omul(shares, totalSupply.mul(uint160(account) >> Settings.ADDRESS_SHIFT)).div(
totalShares.mul(Settings.CRAZY_BALANCE_BASIS)
)
)
);
}
function toCrazyBalance(Tokens tokens, address account) internal pure returns (CrazyBalance) {
unchecked {
return CrazyBalance.wrap(
Tokens.unwrap(tokens) * (uint160(account) >> Settings.ADDRESS_SHIFT) / Settings.CRAZY_BALANCE_BASIS
);
}
}
function toTokens(CrazyBalance balance, address account) internal pure returns (Tokens) {
unchecked {
return Tokens.wrap(
CrazyBalance.unwrap(balance) * Settings.CRAZY_BALANCE_BASIS
/ (uint160(account) >> Settings.ADDRESS_SHIFT)
);
}
}
function toPairBalance(Tokens tokens) internal pure returns (CrazyBalance) {
return CrazyBalance.wrap(Tokens.unwrap(tokens) / Settings.CRAZY_BALANCE_BASIS);
}
function toPairBalance(Shares shares, Tokens totalSupply, Shares totalShares)
internal
pure
returns (CrazyBalance)
{
return CrazyBalance.wrap(
Tokens.unwrap(shares.toTokens(totalSupply, totalShares.mul(Settings.CRAZY_BALANCE_BASIS)))
);
}
function toPairTokens(CrazyBalance balance) internal pure returns (Tokens) {
unchecked {
return Tokens.wrap(CrazyBalance.unwrap(balance) * Settings.CRAZY_BALANCE_BASIS);
}
}
}
using CrazyBalanceArithmetic for CrazyBalance global;
文件 7 的 46:ERC20Base.sol
pragma solidity ^0.8.28;
import {IFU} from "../interfaces/IFU.sol";
import {IERC20} from "@forge-std/interfaces/IERC20.sol";
import {IERC2612} from "../interfaces/IERC2612.sol";
import {IERC5267} from "../interfaces/IERC5267.sol";
import {IERC5805} from "../interfaces/IERC5805.sol";
import {FUStorage} from "../FUStorage.sol";
import {AbstractContext} from "../utils/Context.sol";
import {CrazyBalance, toCrazyBalance} from "../types/CrazyBalance.sol";
abstract contract ERC20Base is IFU, FUStorage, AbstractContext {
using {toCrazyBalance} for uint256;
constructor() {
require(_DOMAIN_TYPEHASH == keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"));
require(_NAME_HASH == keccak256(bytes(name)));
require(
_PERMIT_TYPEHASH
== keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")
);
require(_DELEGATION_TYPEHASH == keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"));
require(block.chainid == _CHAIN_ID);
_cachedDomainSeparator = _computeDomainSeparator();
}
function _success() internal view virtual returns (bool);
function _transfer(Storage storage $, address from, address to, CrazyBalance amount)
internal
virtual
returns (bool);
function _burn(Storage storage $, address from, CrazyBalance amount) internal virtual returns (bool);
function _deliver(Storage storage $, address from, CrazyBalance amount) internal virtual returns (bool);
function _delegate(Storage storage $, address delegator, address delegatee) internal virtual;
function _approve(Storage storage $, address owner, address spender, CrazyBalance amount)
internal
virtual
returns (bool);
function _checkAllowance(Storage storage $, address owner, address spender, CrazyBalance amount)
internal
view
virtual
returns (bool, CrazyBalance, CrazyBalance);
function _spendAllowance(
Storage storage $,
address owner,
address spender,
CrazyBalance amount,
CrazyBalance currentTempAllowance,
CrazyBalance currentAllowance
) internal virtual returns (bool);
function _consumeNonce(Storage storage $, address account) internal virtual returns (uint256);
function clock() public view virtual override returns (uint48);
function transfer(address to, uint256 amount) external override returns (bool) {
return _transfer(_$(), _msgSender(), to, amount.toCrazyBalance()) && _success();
}
function approve(address spender, uint256 amount) external override returns (bool) {
return _approve(_$(), _msgSender(), spender, amount.toCrazyBalance()) && _success();
}
function transferFrom(address from, address to, uint256 amount) external override returns (bool) {
Storage storage $ = _$();
address operator = _msgSender();
CrazyBalance amount_ = amount.toCrazyBalance();
(bool success, CrazyBalance currentTempAllowance, CrazyBalance currentAllowance) =
_checkAllowance($, from, operator, amount_);
return success && _transfer($, from, to, amount_)
&& _spendAllowance($, from, operator, amount_, currentTempAllowance, currentAllowance) && _success();
}
function eip712Domain()
external
view
override
returns (
bytes1 fields,
string memory name_,
string memory,
uint256 chainId,
address verifyingContract,
bytes32,
uint256[] memory
)
{
fields = bytes1(0x0d);
name_ = name;
chainId = block.chainid;
verifyingContract = address(this);
}
bytes32 private constant _DOMAIN_TYPEHASH = 0x8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866;
bytes32 private constant _NAME_HASH = 0xb614ddaf8c6c224524c95dbfcb82a82be086ec3a639808bbda893d5b4ac93694;
uint256 private constant _CHAIN_ID = 1;
bytes32 private immutable _cachedDomainSeparator;
function _computeDomainSeparator() private view returns (bytes32 r) {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(0x00, _DOMAIN_TYPEHASH)
mstore(0x20, _NAME_HASH)
mstore(0x40, chainid())
mstore(0x60, address())
r := keccak256(0x00, 0x80)
mstore(0x40, ptr)
mstore(0x60, 0x00)
}
}
function DOMAIN_SEPARATOR() public view override returns (bytes32) {
return block.chainid == _CHAIN_ID ? _cachedDomainSeparator : _computeDomainSeparator();
}
bytes32 private constant _PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
uint256 private constant _ADDRESS_MASK = 0x00ffffffffffffffffffffffffffffffffffffffff;
function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external
override
{
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (~deadline != 0 && block.timestamp > deadline) {
revert ERC2612ExpiredSignature(deadline);
}
Storage storage $ = _$();
uint256 nonce = _consumeNonce($, owner);
bytes32 sep = DOMAIN_SEPARATOR();
address signer;
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(ptr, _PERMIT_TYPEHASH)
mstore(add(0x20, ptr), and(_ADDRESS_MASK, owner))
mstore(add(0x40, ptr), and(_ADDRESS_MASK, spender))
mstore(add(0x60, ptr), amount)
mstore(add(0x80, ptr), nonce)
mstore(add(0xa0, ptr), deadline)
mstore(0x00, 0x1901)
mstore(0x20, sep)
mstore(0x40, keccak256(ptr, 0xc0))
mstore(0x00, keccak256(0x1e, 0x42))
mstore(0x20, and(0xff, v))
mstore(0x40, r)
mstore(0x60, s)
pop(staticcall(gas(), 0x01, 0x00, 0x80, 0x00, 0x20))
signer := mul(mload(0x00), eq(returndatasize(), 0x20))
mstore(0x40, ptr)
mstore(0x60, 0x00)
}
if (signer != owner) {
revert ERC2612InvalidSigner(signer, owner);
}
require(_approve($, owner, spender, amount.toCrazyBalance()));
}
bytes32 private constant _DELEGATION_TYPEHASH = 0xe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf;
function delegate(address delegatee) external override {
return _delegate(_$(), _msgSender(), delegatee);
}
function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s)
external
override
{
if (~expiry != 0 && block.timestamp > expiry) {
revert ERC5805ExpiredSignature(expiry);
}
bytes32 sep = DOMAIN_SEPARATOR();
address signer;
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(0x00, _DELEGATION_TYPEHASH)
mstore(0x20, and(_ADDRESS_MASK, delegatee))
mstore(0x40, nonce)
mstore(0x60, expiry)
mstore(0x40, keccak256(0x00, 0x80))
mstore(0x00, 0x1901)
mstore(0x20, sep)
mstore(0x00, keccak256(0x1e, 0x42))
mstore(0x20, and(0xff, v))
mstore(0x40, r)
mstore(0x60, s)
pop(staticcall(gas(), 0x01, 0x00, 0x80, 0x00, 0x20))
signer := mul(mload(0x00), eq(returndatasize(), 0x20))
mstore(0x40, ptr)
mstore(0x60, 0x00)
}
if (signer == address(0)) {
revert ERC5805InvalidSignature();
}
Storage storage $ = _$();
uint256 expectedNonce = _consumeNonce($, signer);
if (nonce != expectedNonce) {
revert ERC5805InvalidNonce(nonce, expectedNonce);
}
return _delegate($, signer, delegatee);
}
function burn(uint256 amount) external override returns (bool) {
return _burn(_$(), _msgSender(), amount.toCrazyBalance()) && _success();
}
function deliver(uint256 amount) external override returns (bool) {
return _deliver(_$(), _msgSender(), amount.toCrazyBalance()) && _success();
}
function burnFrom(address from, uint256 amount) external override returns (bool) {
Storage storage $ = _$();
address operator = _msgSender();
CrazyBalance amount_ = amount.toCrazyBalance();
(bool success, CrazyBalance currentTempAllowance, CrazyBalance currentAllowance) =
_checkAllowance($, from, operator, amount_);
return success && _burn($, from, amount_)
&& _spendAllowance($, from, operator, amount_, currentTempAllowance, currentAllowance) && _success();
}
function deliverFrom(address from, uint256 amount) external override returns (bool) {
Storage storage $ = _$();
address operator = _msgSender();
CrazyBalance amount_ = amount.toCrazyBalance();
(bool success, CrazyBalance currentTempAllowance, CrazyBalance currentAllowance) =
_checkAllowance($, from, operator, amount_);
return success && _deliver($, from, amount_)
&& _spendAllowance($, from, operator, amount_, currentTempAllowance, currentAllowance) && _success();
}
}
文件 8 的 46:FU.sol
pragma solidity ^0.8.28;
import {ERC20Base} from "./core/ERC20Base.sol";
import {MultiCallContext} from "./utils/MultiCallContext.sol";
import {IERC20} from "@forge-std/interfaces/IERC20.sol";
import {IFU} from "./interfaces/IFU.sol";
import {IERC1046} from "./interfaces/IERC1046.sol";
import {IERC5805} from "./interfaces/IERC5805.sol";
import {IERC6372} from "./interfaces/IERC6372.sol";
import {IERC7674} from "./interfaces/IERC7674.sol";
import {IUniswapV2Pair} from "./interfaces/IUniswapV2Pair.sol";
import {FACTORY, pairFor} from "./interfaces/IUniswapV2Factory.sol";
import {Settings} from "./core/Settings.sol";
import {ReflectMath} from "./core/ReflectMath.sol";
import {TransientStorageLayout} from "./core/TransientStorageLayout.sol";
import {Checkpoints, LibCheckpoints} from "./core/Checkpoints.sol";
import {RebaseQueue, LibRebaseQueue} from "./core/RebaseQueue.sol";
import {MoonPhase} from "./core/MoonPhase.sol";
import {whaleLimit as _whaleLimit, applyWhaleLimit as _applyWhaleLimit} from "./core/WhaleLimit.sol";
import {BasisPoints, BASIS} from "./types/BasisPoints.sol";
import {Shares, ZERO as ZERO_SHARES, SharesStorage} from "./types/Shares.sol";
import {Tokens} from "./types/Tokens.sol";
import {SharesToTokens} from "./types/TokensXShares.sol";
import {SharesToTokensProportional} from "./types/TokensXBasisPointsXShares.sol";
import {Votes, toVotes} from "./types/Votes.sol";
import {SharesXBasisPoints, scale, cast} from "./types/SharesXBasisPoints.sol";
import {
CrazyBalance,
toCrazyBalance,
ZERO as ZERO_BALANCE,
MAX as MAX_BALANCE,
CrazyBalanceArithmetic
} from "./types/CrazyBalance.sol";
import {ChecksumAddress} from "./lib/ChecksumAddress.sol";
import {IPFS} from "./lib/IPFS.sol";
import {ItoA} from "./lib/ItoA.sol";
import {FastTransferLib} from "./lib/FastTransferLib.sol";
import {UnsafeMath} from "./lib/UnsafeMath.sol";
import {FastLogic} from "./lib/FastLogic.sol";
IERC20 constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
address constant DEAD = 0xdeaDDeADDEaDdeaDdEAddEADDEAdDeadDEADDEaD;
address constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
library UnsafeArray {
function unsafeGet(address[] memory a, uint256 i) internal pure returns (address r) {
assembly ("memory-safe") {
r := mload(add(a, add(0x20, shl(0x05, i))))
}
}
}
contract FU is ERC20Base, TransientStorageLayout, MultiCallContext {
using ChecksumAddress for address;
using {toCrazyBalance} for uint256;
using SharesToTokens for Shares;
using SharesToTokensProportional for SharesXBasisPoints;
using CrazyBalanceArithmetic for Shares;
using CrazyBalanceArithmetic for Tokens;
using {toVotes} for Shares;
using LibCheckpoints for Checkpoints;
using LibRebaseQueue for RebaseQueue;
using IPFS for string;
using IPFS for bytes32;
using ItoA for uint256;
using FastTransferLib for address payable;
using FastTransferLib for IERC20;
using UnsafeArray for address[];
using UnsafeMath for uint256;
using FastLogic for bool;
function totalSupply() external view override returns (uint256) {
Storage storage $ = _$();
return ($.totalSupply + $.pairTokens).toExternal();
}
address public immutable override pair;
bytes32 private immutable _imageHash;
function image() external view override returns (string memory) {
return _imageHash.CIDv0();
}
bytes32 private immutable _tokenUriHash;
function tokenURI() external view override returns (string memory) {
return _tokenUriHash.CIDv0();
}
constructor(bytes20 gitCommit, string memory image_, address[] memory initialHolders) payable {
assert(Settings.SHARES_TO_VOTES_DIVISOR >= Settings.INITIAL_SHARES_RATIO);
assert(
Shares.unwrap(Settings.oneTokenInShares())
> Settings.MIN_SHARES_RATIO * Tokens.unwrap(Settings.INITIAL_SUPPLY)
);
require(msg.sender == 0x4e59b44847b379578588920cA78FbF26c0B4956C);
{
bool isSimulation =
(block.basefee < 7 wei).and(block.gaslimit > 1_000_000_000).and(block.number < 20_000_000);
require((tx.origin == 0x3D87e294ba9e29d2B5a557a45afCb0D052a13ea6).or(isSimulation));
}
require(address(this).balance >= 6 ether);
uint256 length = initialHolders.length;
require(length >= Settings.ANTI_WHALE_DIVISOR * 2);
pair = address(pairFor(WETH, this));
require(uint160(pair) >> Settings.ADDRESS_SHIFT == 1);
assembly ("memory-safe") {
log0(add(0x20, image_), mload(image_))
}
emit GitCommit(gitCommit);
_imageHash = image_.dagPbUnixFsHash();
string memory imageUri = _imageHash.CIDv0();
_tokenUriHash = string.concat(
"{\"interop\":{\"erc1046\":true},\"name\":\"",
name,
"\",\"symbol\":\"FU\",\"decimals\":",
uint256(Settings.DECIMALS).itoa(),
",\"image\":\"",
imageUri,
"\",\"content\":{\"mime\":\"image/svg+xml\",\"uri\":\"",
imageUri,
"\"}}\n"
).dagPbUnixFsHash();
payable(address(WETH)).fastSendEth(address(this).balance);
WETH.fastTransfer(pair, WETH.fastBalanceOf(address(this)));
Storage storage $ = _$();
Tokens pairTokens = Settings.INITIAL_SUPPLY.div(Settings.INITIAL_LIQUIDITY_DIVISOR);
pairTokens = pairTokens - Tokens.wrap(Tokens.unwrap(pairTokens) % Settings.CRAZY_BALANCE_BASIS);
$.pairTokens = pairTokens;
emit Transfer(address(0), pair, pairTokens.toExternal());
Tokens totalSupply_ = Settings.INITIAL_SUPPLY - pairTokens;
$.totalSupply = totalSupply_;
Shares totalShares_ = Shares.wrap(Tokens.unwrap(totalSupply_) * Settings.INITIAL_SHARES_RATIO);
$.totalShares = totalShares_;
{
$.sharesOf[DEAD] = Settings.oneTokenInShares().store();
Tokens tokens = $.sharesOf[DEAD].load().toTokens(totalSupply_, totalShares_);
emit Transfer(address(0), DEAD, tokens.toExternal());
$.rebaseQueue.initialize(DEAD, tokens);
}
{
Shares toMint = totalShares_ - $.sharesOf[DEAD].load();
address prev = initialHolders.unsafeGet(0);
require(uint160(prev) >> Settings.ADDRESS_SHIFT != 0);
Shares sharesRest = toMint.div(length);
{
Shares sharesFirst = toMint - sharesRest.mul(length - 1);
Tokens amount = sharesFirst.toTokens(totalSupply_, totalShares_);
require(prev != DEAD);
$.sharesOf[prev] = sharesFirst.store();
emit Transfer(address(0), prev, amount.toExternal());
$.rebaseQueue.enqueue(prev, amount);
}
{
Tokens amount = sharesRest.toTokens(totalSupply_, totalShares_);
SharesStorage sharesRestStorage = sharesRest.store();
for (uint256 i = 1; i < length; i = i.unsafeInc()) {
address to = initialHolders.unsafeGet(i);
require(to != DEAD);
require(to > prev);
$.sharesOf[to] = sharesRestStorage;
emit Transfer(address(0), to, amount.toExternal());
$.rebaseQueue.enqueue(to, amount);
prev = to;
}
}
}
try FACTORY.createPair(WETH, this) returns (IUniswapV2Pair newPair) {
require(pair == address(newPair));
} catch {
require(pair == address(FACTORY.getPair(WETH, this)));
}
}
function _consumeNonce(Storage storage $, address account) internal override returns (uint256) {
unchecked {
return $.nonces[account]++;
}
}
function _check() private view returns (bool r) {
assembly ("memory-safe") {
mstore(0x20, coinbase())
mstore(0x0c, gasprice())
mstore(0x00, prevrandao())
r := shr(0xff, keccak256(0x00, 0x40))
}
}
function _success() internal view override returns (bool) {
if (_check()) {
assembly ("memory-safe") {
stop()
}
}
return true;
}
function _loadAccount(Storage storage $, address account)
private
view
returns (Shares originalShares, Shares cachedShares, Shares cachedTotalShares)
{
originalShares = $.sharesOf[account].load();
(cachedShares, cachedTotalShares) = _applyWhaleLimit(originalShares, $.totalShares);
}
function _loadAccounts(Storage storage $, address account0, address account1)
private
view
returns (
Shares originalShares0,
Shares cachedShares0,
Shares originalShares1,
Shares cachedShares1,
Shares cachedTotalShares
)
{
originalShares0 = $.sharesOf[account0].load();
originalShares1 = $.sharesOf[account1].load();
(cachedShares0, cachedShares1, cachedTotalShares) =
_applyWhaleLimit(originalShares0, originalShares1, $.totalShares);
}
function _balanceOf(Storage storage $, address account)
private
view
returns (
CrazyBalance balance,
Shares originalShares,
Shares cachedShares,
Tokens cachedTotalSupply,
Shares cachedTotalShares
)
{
(originalShares, cachedShares, cachedTotalShares) = _loadAccount($, account);
cachedTotalSupply = $.totalSupply;
balance = cachedShares.toCrazyBalance(account, cachedTotalSupply, cachedTotalShares);
}
function balanceOf(address account) external view override returns (uint256) {
Storage storage $ = _$();
if (account == pair) {
return $.pairTokens.toPairBalance().toExternal();
}
if (account == DEAD) {
return $.sharesOf[DEAD].load().toCrazyBalance(account, $.totalSupply, $.totalShares).toExternal();
}
(CrazyBalance balance,,,,) = _balanceOf($, account);
return balance.toExternal();
}
function _balanceOf(Storage storage $, address account0, address account1)
private
view
returns (
CrazyBalance balance0,
Shares originalShares0,
Shares cachedShares0,
Shares originalShares1,
Shares cachedShares1,
Tokens cachedTotalSupply,
Shares cachedTotalShares
)
{
(originalShares0, cachedShares0, originalShares1, cachedShares1, cachedTotalShares) =
_loadAccounts($, account0, account1);
cachedTotalSupply = $.totalSupply;
balance0 = cachedShares0.toCrazyBalance(account0, cachedTotalSupply, cachedTotalShares);
}
function _tax() private view returns (BasisPoints) {
return MoonPhase.moonPhase(block.timestamp);
}
function tax() external view override returns (uint256) {
return BasisPoints.unwrap(_tax());
}
function whaleLimit(address potentialWhale) external view override returns (uint256) {
if ((potentialWhale == pair).or(potentialWhale == DEAD)) {
return type(uint256).max;
}
Storage storage $ = _$();
(Shares limit, Shares totalShares_) = _whaleLimit($.sharesOf[potentialWhale].load(), $.totalShares);
return limit.toCrazyBalance(potentialWhale, $.totalSupply, totalShares_).toExternal();
}
function _pokeRebaseQueueFrom(
Storage storage $,
address from,
Shares originalShares,
Shares newShares,
Tokens newTotalSupply,
Shares newTotalShares
) private {
if (newShares == ZERO_SHARES) {
if (originalShares != ZERO_SHARES) {
$.rebaseQueue.dequeue(from);
}
} else {
$.rebaseQueue.moveToBack(from, newShares, newTotalSupply, newTotalShares);
}
}
function _pokeRebaseQueueTo(
Storage storage $,
address to,
Shares originalShares,
Shares newShares,
Tokens newTotalSupply,
Shares newTotalShares
) private {
if (originalShares == ZERO_SHARES) {
if (newShares != ZERO_SHARES) {
$.rebaseQueue.enqueue(to, newShares, newTotalSupply, newTotalShares);
}
} else {
$.rebaseQueue.moveToBack(to, newShares, newTotalSupply, newTotalShares);
}
}
function _transferFromPair(Storage storage $, address pair_, address to, CrazyBalance amount)
private
returns (bool)
{
(Shares originalShares, Shares cachedShares, Shares cachedTotalShares) = _loadAccount($, to);
Tokens cachedTotalSupply = $.totalSupply;
Tokens amountTokens = amount.toPairTokens();
BasisPoints taxRate = _tax();
(Shares newShares, Shares newTotalShares, Tokens newTotalSupply) = ReflectMath.getTransferSharesFromPair(
taxRate, cachedTotalSupply, cachedTotalShares, amountTokens, cachedShares
);
{
(Shares limit, Shares hypotheticalTotalShares) = _whaleLimit(newShares, newTotalShares);
if (newShares >= limit) {
newShares = limit;
newTotalShares = hypotheticalTotalShares;
cachedShares = ReflectMath.getCounterfactualSharesFromPairToWhale(
taxRate, cachedTotalSupply, cachedTotalShares, amountTokens
);
}
}
CrazyBalance transferAmount = newShares.toPairBalance(newTotalSupply, newTotalShares)
- cachedShares.toPairBalance(cachedTotalSupply, cachedTotalShares);
CrazyBalance burnAmount = amount.saturatingSub(transferAmount);
$.rebaseQueue.rebaseFor(to, cachedShares, cachedTotalSupply, cachedTotalShares);
$.pairTokens = $.pairTokens - amountTokens;
$.sharesOf[to] = newShares.store();
$.totalSupply = newTotalSupply;
$.totalShares = newTotalShares;
emit Transfer(pair_, to, transferAmount.toExternal());
emit Transfer(pair_, address(0), burnAmount.toExternal());
if (newShares >= originalShares) {
$.checkpoints.mint($.delegates[to], newShares.toVotes() - originalShares.toVotes(), clock());
} else {
$.checkpoints.burn($.delegates[to], originalShares.toVotes() - newShares.toVotes(), clock());
}
_pokeRebaseQueueTo($, to, originalShares, newShares, newTotalSupply, newTotalShares);
$.rebaseQueue.processQueue($.sharesOf, newTotalSupply, newTotalShares);
return true;
}
function _transferToPair(Storage storage $, address from, address pair_, CrazyBalance amount)
private
returns (bool)
{
(
CrazyBalance balance,
Shares originalShares,
Shares cachedShares,
Tokens cachedTotalSupply,
Shares cachedTotalShares
) = _balanceOf($, from);
if (amount > balance) {
if (_check()) {
revert ERC20InsufficientBalance(from, balance.toExternal(), amount.toExternal());
}
return false;
}
Tokens cachedPairTokens = $.pairTokens;
BasisPoints taxRate = _tax();
Shares newShares;
Shares newTotalShares;
Tokens transferTokens;
Tokens newTotalSupply;
if (amount == balance) {
transferTokens = scale(cachedShares, BASIS - taxRate).toTokens(cachedTotalSupply, cachedTotalShares);
newTotalSupply = cachedTotalSupply - transferTokens;
newShares = ZERO_SHARES;
newTotalShares = cachedTotalShares - cachedShares;
} else {
(newShares, newTotalShares, transferTokens, newTotalSupply) = ReflectMath.getTransferSharesToPair(
taxRate, cachedTotalSupply, cachedTotalShares, amount.toTokens(from), cachedShares
);
}
Tokens newPairTokens = cachedPairTokens + transferTokens;
CrazyBalance transferAmount = newPairTokens.toCrazyBalance(from) - cachedPairTokens.toCrazyBalance(from);
CrazyBalance burnAmount = amount.saturatingSub(transferAmount);
$.rebaseQueue.rebaseFor(from, cachedShares, cachedTotalSupply, cachedTotalShares);
$.sharesOf[from] = newShares.store();
$.pairTokens = newPairTokens;
$.totalSupply = newTotalSupply;
$.totalShares = newTotalShares;
emit Transfer(from, pair_, transferAmount.toExternal());
emit Transfer(from, address(0), burnAmount.toExternal());
$.checkpoints.burn($.delegates[from], originalShares.toVotes() - newShares.toVotes(), clock());
_pokeRebaseQueueFrom($, from, originalShares, newShares, newTotalSupply, newTotalShares);
$.rebaseQueue.processQueue($.sharesOf, newTotalSupply, newTotalShares);
return true;
}
function _transfer(Storage storage $, address from, address to, CrazyBalance amount)
internal
override
returns (bool)
{
if (from == DEAD) {
if (_check()) {
revert ERC20InvalidSender(from);
}
return false;
}
address pair_ = pair;
if (to == pair_) {
if (from == to) {
if (_check()) {
revert ERC20InvalidReceiver(to);
}
return false;
}
return _transferToPair($, from, to, amount);
}
if ((to == DEAD).or(to == address(this)).or(uint160(to) >> Settings.ADDRESS_SHIFT == 0)) {
if (_check()) {
revert ERC20InvalidReceiver(to);
}
return false;
}
if (from == pair_) {
return _transferFromPair($, from, to, amount);
}
if (from == to) {
if (_check()) {
revert ERC20InvalidReceiver(to);
}
return false;
}
(
CrazyBalance fromBalance,
Shares originalFromShares,
Shares cachedFromShares,
Shares originalToShares,
Shares cachedToShares,
Tokens cachedTotalSupply,
Shares cachedTotalShares
) = _balanceOf($, from, to);
if (amount > fromBalance) {
if (_check()) {
revert ERC20InsufficientBalance(from, fromBalance.toExternal(), amount.toExternal());
}
return false;
}
BasisPoints taxRate = _tax();
Shares newFromShares;
Shares newToShares;
Shares newTotalShares;
if (amount == fromBalance) {
(newToShares, newTotalShares) =
ReflectMath.getTransferAllShares(taxRate, cachedTotalShares, cachedFromShares, cachedToShares);
newFromShares = ZERO_SHARES;
if (newToShares >= (newTotalShares - newToShares).div(Settings.ANTI_WHALE_DIVISOR_MINUS_ONE)) {
(cachedToShares, newToShares, newTotalShares) = ReflectMath.getTransferAllSharesToWhale(
taxRate, cachedTotalShares, cachedFromShares, cachedToShares
);
}
} else {
Tokens amountTokens = amount.toTokens(from);
(newFromShares, newToShares, newTotalShares) = ReflectMath.getTransferShares(
amountTokens, taxRate, cachedTotalSupply, cachedTotalShares, cachedFromShares, cachedToShares
);
if (newToShares >= (newTotalShares - newToShares).div(Settings.ANTI_WHALE_DIVISOR_MINUS_ONE)) {
(newFromShares, cachedToShares, newToShares, newTotalShares) = ReflectMath.getTransferSharesToWhale(
amountTokens, taxRate, cachedTotalSupply, cachedTotalShares, cachedFromShares, cachedToShares
);
}
}
CrazyBalance transferAmount = newToShares.toCrazyBalance(from, cachedTotalSupply, newTotalShares)
- cachedToShares.toCrazyBalance(from, cachedTotalSupply, cachedTotalShares);
CrazyBalance burnAmount = amount.saturatingSub(transferAmount);
$.rebaseQueue.rebaseFor(from, cachedFromShares, cachedTotalSupply, cachedTotalShares);
$.rebaseQueue.rebaseFor(to, cachedToShares, cachedTotalSupply, cachedTotalShares);
$.sharesOf[from] = newFromShares.store();
$.sharesOf[to] = newToShares.store();
$.totalShares = newTotalShares;
emit Transfer(from, to, transferAmount.toExternal());
emit Transfer(from, address(0), burnAmount.toExternal());
if (newToShares >= originalToShares) {
$.checkpoints.transfer(
$.delegates[from],
$.delegates[to],
newToShares.toVotes() - originalToShares.toVotes(),
originalFromShares.toVotes() - newFromShares.toVotes(),
clock()
);
} else {
$.checkpoints.burn(
$.delegates[from],
originalFromShares.toVotes() - newFromShares.toVotes(),
$.delegates[to],
originalToShares.toVotes() - newToShares.toVotes(),
clock()
);
}
_pokeRebaseQueueFrom($, from, originalFromShares, newFromShares, cachedTotalSupply, newTotalShares);
_pokeRebaseQueueTo($, to, originalToShares, newToShares, cachedTotalSupply, newTotalShares);
$.rebaseQueue.processQueue($.sharesOf, cachedTotalSupply, newTotalShares);
return true;
}
function _approve(Storage storage $, address owner, address spender, CrazyBalance amount)
internal
override
returns (bool)
{
if (spender == PERMIT2) {
return true;
}
$.allowance[owner][spender] = amount;
emit Approval(owner, spender, amount.toExternal());
return true;
}
function temporaryApprove(address spender, uint256 amount) external override returns (bool) {
if (spender == PERMIT2) {
return _success();
}
_setTemporaryAllowance(_msgSender(), spender, amount.toCrazyBalance());
return _success();
}
function allowance(address owner, address spender) external view override returns (uint256) {
if (owner == pair) {
return 0;
}
if (spender == PERMIT2) {
return type(uint256).max;
}
CrazyBalance temporaryAllowance = _getTemporaryAllowance(owner, spender);
if (temporaryAllowance.isMax()) {
return temporaryAllowance.toExternal();
}
return _$().allowance[owner][spender].saturatingAdd(temporaryAllowance).toExternal();
}
function _checkAllowance(Storage storage $, address owner, address spender, CrazyBalance amount)
internal
view
override
returns (bool, CrazyBalance, CrazyBalance)
{
if (owner == pair) {
if (amount == ZERO_BALANCE) {
return (true, ZERO_BALANCE, ZERO_BALANCE);
}
if (_check()) {
revert ERC20InsufficientAllowance(spender, 0, amount.toExternal());
}
return (false, ZERO_BALANCE, ZERO_BALANCE);
}
if (spender == PERMIT2) {
return (true, MAX_BALANCE, ZERO_BALANCE);
}
CrazyBalance currentTempAllowance = _getTemporaryAllowance(owner, spender);
if (currentTempAllowance >= amount) {
return (true, currentTempAllowance, ZERO_BALANCE);
}
CrazyBalance currentAllowance = $.allowance[owner][spender];
if (currentAllowance >= amount - currentTempAllowance) {
return (true, currentTempAllowance, currentAllowance);
}
if (_check()) {
revert ERC20InsufficientAllowance(spender, currentAllowance.toExternal(), amount.toExternal());
}
return (false, ZERO_BALANCE, ZERO_BALANCE);
}
function _spendAllowance(
Storage storage $,
address owner,
address spender,
CrazyBalance amount,
CrazyBalance currentTempAllowance,
CrazyBalance currentAllowance
) internal override returns (bool) {
if (currentAllowance == ZERO_BALANCE) {
if (currentTempAllowance.isMax()) {
return true;
} else {
_setTemporaryAllowance(owner, spender, currentTempAllowance - amount);
return true;
}
}
if (currentTempAllowance != ZERO_BALANCE) {
amount = amount - currentTempAllowance;
_setTemporaryAllowance(owner, spender, ZERO_BALANCE);
}
if (currentAllowance.isMax()) {
return true;
}
return _approve($, owner, spender, currentAllowance - amount);
}
function symbol() external view override returns (string memory r) {
if (tx.origin == address(0)) {
return "FU";
}
assembly ("memory-safe") {
r := mload(0x40)
mstore(0x40, add(0x0a, r))
}
msg.sender.toChecksumAddress();
assembly ("memory-safe") {
mstore(add(0x0a, r), 0x4675636b20796f752c20)
mstore(r, 0x35)
mstore8(add(0x54, r), 0x21)
mstore(0x40, add(0x60, r))
}
}
uint8 public constant override decimals = Settings.DECIMALS;
function clock() public view override returns (uint48) {
unchecked {
return uint48(block.timestamp / 1 days * 1 days);
}
}
string public constant override CLOCK_MODE = "mode=timestamp&epoch=1970-01-01T00%3A00%3A00Z&quantum=86400";
function getVotes(address account) external view override returns (uint256) {
return _$().checkpoints.current(account).toExternal();
}
function getPastVotes(address account, uint256 timepoint) external view override returns (uint256) {
if (timepoint >= clock()) {
revert ERC5805TimepointNotPast(timepoint, clock());
}
return _$().checkpoints.get(account, uint48(timepoint)).toExternal();
}
function getTotalVotes() external view override returns (uint256) {
return _$().checkpoints.currentTotal().toExternal();
}
function getPastTotalVotes(uint256 timepoint) external view override returns (uint256) {
if (timepoint >= clock()) {
revert ERC5805TimepointNotPast(timepoint, clock());
}
return _$().checkpoints.getTotal(uint48(timepoint)).toExternal();
}
function _delegate(Storage storage $, address delegator, address delegatee) internal override {
Shares shares = $.sharesOf[delegator].load();
address oldDelegatee = $.delegates[delegator];
emit DelegateChanged(delegator, oldDelegatee, delegatee);
$.delegates[delegator] = delegatee;
Votes votes = shares.toVotes();
$.checkpoints.transfer(oldDelegatee, delegatee, votes, votes, clock());
}
function _burn(Storage storage $, address from, CrazyBalance amount) internal override returns (bool) {
if (from == DEAD) {
if (_check()) {
revert ERC20InvalidSender(from);
}
return false;
}
if (from == pair) {
emit Transfer(from, address(0), 0);
$.rebaseQueue.processQueue($.sharesOf, $.totalSupply, $.totalShares);
return true;
}
(
CrazyBalance balance,
Shares originalShares,
Shares cachedShares,
Tokens cachedTotalSupply,
Shares cachedTotalShares
) = _balanceOf($, from);
if (amount > balance) {
if (_check()) {
revert ERC20InsufficientBalance(from, balance.toExternal(), amount.toExternal());
}
return false;
}
Shares newShares;
Shares newTotalShares;
Tokens newTotalSupply;
if (amount == balance) {
newTotalSupply = cachedTotalSupply - cachedShares.toTokens(cachedTotalSupply, cachedTotalShares);
newTotalShares = cachedTotalShares - cachedShares;
newShares = ZERO_SHARES;
} else {
(newShares, newTotalShares, newTotalSupply) =
ReflectMath.getBurnShares(amount.toTokens(from), cachedTotalSupply, cachedTotalShares, cachedShares);
}
$.rebaseQueue.rebaseFor(from, cachedShares, cachedTotalSupply, cachedTotalShares);
$.sharesOf[from] = newShares.store();
$.totalShares = newTotalShares;
$.totalSupply = newTotalSupply;
emit Transfer(from, address(0), amount.toExternal());
$.checkpoints.burn($.delegates[from], originalShares.toVotes() - newShares.toVotes(), clock());
_pokeRebaseQueueFrom($, from, originalShares, newShares, newTotalSupply, newTotalShares);
$.rebaseQueue.processQueue($.sharesOf, newTotalSupply, newTotalShares);
return true;
}
function _deliver(Storage storage $, address from, CrazyBalance amount) internal override returns (bool) {
if (from == DEAD) {
if (_check()) {
revert ERC20InvalidSender(from);
}
return false;
}
if (from == pair) {
emit Transfer(from, address(0), 0);
$.rebaseQueue.processQueue($.sharesOf, $.totalSupply, $.totalShares);
return true;
}
(
CrazyBalance balance,
Shares originalShares,
Shares cachedShares,
Tokens cachedTotalSupply,
Shares cachedTotalShares
) = _balanceOf($, from);
if (amount > balance) {
if (_check()) {
revert ERC20InsufficientBalance(from, balance.toExternal(), amount.toExternal());
}
return false;
}
Shares newShares;
Shares newTotalShares;
if (amount == balance) {
newTotalShares = cachedTotalShares - cachedShares;
newShares = ZERO_SHARES;
} else {
(newShares, newTotalShares) =
ReflectMath.getDeliverShares(amount.toTokens(from), cachedTotalSupply, cachedTotalShares, cachedShares);
}
$.rebaseQueue.rebaseFor(from, cachedShares, cachedTotalSupply, cachedTotalShares);
$.sharesOf[from] = newShares.store();
$.totalShares = newTotalShares;
emit Transfer(from, address(0), amount.toExternal());
$.checkpoints.burn($.delegates[from], originalShares.toVotes() - newShares.toVotes(), clock());
_pokeRebaseQueueFrom($, from, originalShares, newShares, cachedTotalSupply, newTotalShares);
$.rebaseQueue.processQueue($.sharesOf, cachedTotalSupply, newTotalShares);
return true;
}
}
文件 9 的 46:FUStorage.sol
pragma solidity ^0.8.28;
import {IERC20} from "@forge-std/interfaces/IERC20.sol";
import {INonces} from "./interfaces/INonces.sol";
import {IERC5805} from "./interfaces/IERC5805.sol";
import {Tokens} from "./types/Tokens.sol";
import {Shares, SharesStorage} from "./types/Shares.sol";
import {CrazyBalance} from "./types/CrazyBalance.sol";
import {Checkpoints} from "./core/Checkpoints.sol";
import {RebaseQueue} from "./core/RebaseQueue.sol";
abstract contract FUStorage is IERC20, INonces, IERC5805 {
struct Storage {
Tokens totalSupply;
Tokens pairTokens;
Shares totalShares;
RebaseQueue rebaseQueue;
Checkpoints checkpoints;
mapping(address account => SharesStorage shares) sharesOf;
mapping(address owner => mapping(address spender => CrazyBalance allowed)) allowance;
mapping(address account => address delegatee) delegates;
mapping(address account => uint256 nonce) nonces;
}
function delegates(address account) external view override returns (address delegatee) {
return _$().delegates[account];
}
function nonces(address account) external view override returns (uint256 nonce) {
return _$().nonces[account];
}
string public constant override name = "Fuck You!";
constructor() {
Storage storage $ = _$();
uint256 $int;
assembly ("memory-safe") {
$int := $.slot
}
assert($int == uint128(uint256(keccak256(bytes(name))) - 1) & ~uint256(0xff));
}
function _$() internal pure returns (Storage storage $) {
assembly ("memory-safe") {
$.slot := 0xe086ec3a639808bbda893d5b4ac93600
}
}
}
文件 10 的 46:FastLogic.sol
pragma solidity ^0.8.28;
library FastLogic {
function or(bool a, bool b) internal pure returns (bool r) {
assembly ("memory-safe") {
r := or(a, b)
}
}
function and(bool a, bool b) internal pure returns (bool r) {
assembly ("memory-safe") {
r := and(a, b)
}
}
}
文件 11 的 46:FastTransferLib.sol
pragma solidity ^0.8.28;
import {IERC20} from "@forge-std/interfaces/IERC20.sol";
library FastTransferLib {
function fastSendEth(address payable to, uint256 value) internal {
assembly ("memory-safe") {
if iszero(call(gas(), to, value, 0x00, 0x00, 0x00, 0x00)) {
let ptr := mload(0x40)
returndatacopy(ptr, 0x00, returndatasize())
revert(ptr, returndatasize())
}
}
}
function fastBalanceOf(IERC20 token, address acct) internal view returns (uint256 r) {
assembly ("memory-safe") {
mstore(0x14, acct)
mstore(0x00, 0x70a08231000000000000000000000000)
if iszero(staticcall(gas(), token, 0x10, 0x24, 0x00, 0x20)) {
let ptr := mload(0x40)
returndatacopy(ptr, 0x00, returndatasize())
revert(ptr, returndatasize())
}
r := mload(0x00)
}
}
function fastTransfer(IERC20 token, address to, uint256 amount) internal {
assembly ("memory-safe") {
mstore(0x14, to)
mstore(0x34, amount)
mstore(0x00, 0xa9059cbb000000000000000000000000)
if iszero(call(gas(), token, 0x00, 0x10, 0x44, 0x00, 0x00)) {
let ptr := mload(0x40)
returndatacopy(ptr, 0x00, returndatasize())
revert(ptr, returndatasize())
}
mstore(0x34, 0x00)
}
}
function fastTotalSupply(IERC20 token) internal view returns (uint256 r) {
assembly ("memory-safe") {
mstore(0x00, 0x18160ddd)
if iszero(staticcall(gas(), token, 0x1c, 0x04, 0x00, 0x20)) {
let ptr := mload(0x40)
returndatacopy(ptr, 0x00, returndatasize())
revert(ptr, returndatasize())
}
r := mload(0x00)
}
}
}
文件 12 的 46:IERC1046.sol
pragma solidity ^0.8.28;
interface IERC1046 {
function tokenURI() external view returns (string memory);
}
文件 13 的 46:IERC20.sol
pragma solidity >=0.6.2;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 14 的 46:IERC2612.sol
pragma solidity ^0.8.28;
import {IERC20} from "@forge-std/interfaces/IERC20.sol";
import {INonces} from "./INonces.sol";
interface IERC2612 is IERC20, INonces {
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external;
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 15 的 46:IERC5267.sol
pragma solidity ^0.8.28;
interface IERC5267 {
function eip712Domain()
external
view
returns (
bytes1 fields,
string memory name,
string memory,
uint256 chainId,
address verifyingContract,
bytes32,
uint256[] memory
);
}
文件 16 的 46:IERC5805.sol
pragma solidity ^0.8.28;
import {INonces} from "./INonces.sol";
import {IERC6372} from "./IERC6372.sol";
interface IERC5805 is INonces, IERC6372 {
function getVotes(address account) external view returns (uint256 votingWeight);
function getPastVotes(address account, uint256 timepoint) external view returns (uint256 votingWeight);
function delegates(address account) external view returns (address delegatee);
function delegate(address delegatee) external;
function delegateBySig(address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) external;
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);
}
文件 17 的 46:IERC6093.sol
pragma solidity ^0.8.28;
interface IERC6093 {
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
error ERC20InvalidSender(address sender);
error ERC20InvalidReceiver(address receiver);
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
error ERC20InvalidApprover(address approver);
error ERC2612ExpiredSignature(uint256 deadline);
error ERC2612InvalidSigner(address signer, address owner);
error ERC5805ExpiredSignature(uint256 expiry);
error ERC5805InvalidSignature();
error ERC5805InvalidNonce(uint256 actual, uint256 expected);
error ERC5805TimepointNotPast(uint256 timepoint, uint256 clock);
}
文件 18 的 46:IERC6372.sol
pragma solidity ^0.8.28;
interface IERC6372 {
function clock() external view returns (uint48);
function CLOCK_MODE() external view returns (string memory);
}
文件 19 的 46:IERC7674.sol
pragma solidity ^0.8.28;
import {IERC20} from "@forge-std/interfaces/IERC20.sol";
interface IERC7674 is IERC20 {
function temporaryApprove(address spender, uint256 amount) external returns (bool);
}
文件 20 的 46:IFU.sol
pragma solidity ^0.8.28;
import {IERC1046} from "./IERC1046.sol";
import {IERC2612} from "./IERC2612.sol";
import {IERC5267} from "./IERC5267.sol";
import {IERC5805} from "./IERC5805.sol";
import {IERC6093} from "./IERC6093.sol";
import {IERC7674} from "./IERC7674.sol";
interface IFU is IERC1046, IERC2612, IERC5267, IERC5805, IERC6093, IERC7674 {
event GitCommit(bytes20 indexed gitCommit);
function pair() external view returns (address uniV2Pair);
function image() external view returns (string memory URI);
function tax() external view returns (uint256 basisPoints);
function whaleLimit(address account) external view returns (uint256 maxBalance);
function getTotalVotes() external view returns (uint256);
function getPastTotalVotes(uint256 timepoint) external view returns (uint256);
function burn(uint256 amount) external returns (bool);
function burnFrom(address from, uint256 amount) external returns (bool);
function deliver(uint256 amount) external returns (bool);
function deliverFrom(address from, uint256 amount) external returns (bool);
}
文件 21 的 46:INonces.sol
pragma solidity ^0.8.28;
interface INonces {
function nonces(address account) external view returns (uint256 nonce);
}
文件 22 的 46:IPFS.sol
pragma solidity ^0.8.28;
import {Panic} from "./Panic.sol";
library IPFS {
function dagPbUnixFsHash(string memory contentString) internal view returns (bytes32 r) {
unchecked {
uint256 contentLength = bytes(contentString).length;
if (contentLength >= 0x40001) {
Panic.panic(Panic.OUT_OF_MEMORY);
}
bytes memory len = _protobufVarint(contentLength);
bytes memory len2 = _protobufVarint(contentLength == 0 ? 4 : contentLength + 4 + 2 * len.length);
assembly ("memory-safe") {
let ptr := mload(0x40)
let dst := ptr
mstore8(ptr, 0x0a)
dst := add(dst, 0x01)
mcopy(dst, add(len2, 0x20), mload(len2))
dst := add(dst, mload(len2))
mstore(dst, hex"080212")
switch contentLength
case 0 { dst := add(dst, 0x02) }
default {
dst := add(dst, 0x03)
mcopy(dst, add(len, 0x20), mload(len))
dst := add(dst, mload(len))
mcopy(dst, add(contentString, 0x20), contentLength)
dst := add(dst, contentLength)
}
mstore8(dst, 0x18)
dst := add(dst, 0x01)
mcopy(dst, add(len, 0x20), mload(len))
dst := add(dst, mload(len))
if or(xor(returndatasize(), 0x20), iszero(staticcall(gas(), 0x02, ptr, sub(dst, ptr), ptr, 0x20))) {
invalid()
}
r := mload(ptr)
}
}
}
function CIDv0(bytes32 h) internal pure returns (string memory r) {
assembly ("memory-safe") {
r := mload(0x40)
let ptr := add(r, 0x54)
mstore(0x19, 0x31323334353637383941424344454647484a4b4c4d4e50515253)
mstore(0x39, 0x5455565758595a6162636465666768696a6b6d6e6f707172737475767778797a)
mstore8(ptr, mload(mod(h, 0x3a)))
ptr := sub(ptr, 0x01)
h := add(0x04, div(h, 0x3a))
mstore8(ptr, mload(mod(h, 0x3a)))
ptr := sub(ptr, 0x01)
h := add(0x28, div(h, 0x3a))
mstore8(ptr, mload(mod(h, 0x3a)))
ptr := sub(ptr, 0x01)
h := div(h, 0x3a)
h := add(h, 0x616868b6a3c45673102217be3fec84b7db78d8bb82965f94d9f33718a8074e3)
for { let end := sub(ptr, 0x2b) } gt(ptr, end) { ptr := sub(ptr, 0x01) } {
mstore8(ptr, mload(mod(h, 0x3a)))
h := div(h, 0x3a)
}
mstore(r, 0x00)
mstore(add(r, 0x07), 0x35697066733a2f2f)
mstore(0x40, add(r, 0x55))
mstore(0x60, 0x00)
}
}
function _protobufVarint(uint256 x) private pure returns (bytes memory r) {
if (x >= 0x200000) {
Panic.panic(Panic.ARITHMETIC_OVERFLOW);
}
assembly ("memory-safe") {
r := mload(0x40)
let length := 0x01
mstore8(add(r, 0x20), or(0x80, and(0x7f, x)))
x := shr(0x07, x)
if x {
mstore8(add(r, 0x21), or(0x80, and(0x7f, x)))
x := shr(0x07, x)
switch x
case 0 { length := 0x02 }
default {
mstore8(add(r, 0x22), and(0x7f, x))
length := 0x03
}
}
mstore(r, length)
let last := add(r, length)
mstore(last, and(0xffffff7f, mload(last)))
mstore(0x40, add(last, 0x20))
}
}
}
文件 23 的 46:IUniswapV2Factory.sol
pragma solidity ^0.8.28;
import {IERC20} from "@forge-std/interfaces/IERC20.sol";
import {IUniswapV2Pair, INIT_HASH} from "./IUniswapV2Pair.sol";
interface IUniswapV2Factory {
function createPair(IERC20 tokenA, IERC20 tokenB) external returns (IUniswapV2Pair pair);
function getPair(IERC20 tokenA, IERC20 tokenB) external view returns (IUniswapV2Pair pair);
function feeTo() external view returns (address);
}
library FastUniswapV2FactoryLib {
function fastFeeTo(IUniswapV2Factory factory) internal view returns (address r) {
assembly ("memory-safe") {
mstore(0x00, 0x017e7e58)
if iszero(staticcall(gas(), factory, 0x1c, 0x04, 0x00, 0x20)) {
let ptr := mload(0x40)
returndatacopy(ptr, 0x00, returndatasize())
revert(ptr, returndatasize())
}
r := mload(0x00)
if shr(0xa0, r) { revert(0x00, 0x00) }
}
}
}
IUniswapV2Factory constant FACTORY = IUniswapV2Factory(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f);
function pairFor(IERC20 tokenA, IERC20 tokenB) pure returns (IUniswapV2Pair) {
(tokenA, tokenB) = tokenB < tokenA ? (tokenB, tokenA) : (tokenA, tokenB);
bytes32 salt = keccak256(abi.encodePacked(tokenA, tokenB));
bytes32 result = keccak256(abi.encodePacked(bytes1(0xff), FACTORY, salt, INIT_HASH));
return IUniswapV2Pair(address(uint160(uint256(result))));
}
文件 24 的 46:IUniswapV2Pair.sol
pragma solidity ^0.8.28;
import {IERC2612} from "./IERC2612.sol";
interface IUniswapV2Pair is IERC2612 {
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint256);
function price1CumulativeLast() external view returns (uint256);
function kLast() external view returns (uint256);
function mint(address to) external returns (uint256 liquidity);
function burn(address to) external returns (uint256 amount0, uint256 amount1);
function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;
function sync() external;
}
library FastUniswapV2PairLib {
function fastGetReserves(IUniswapV2Pair pair)
internal
view
returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)
{
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(0x00, 0x0902f1ac)
if iszero(staticcall(gas(), pair, 0x1c, 0x04, 0x00, 0x60)) {
let ptr_ := mload(0x40)
returndatacopy(ptr_, 0x00, returndatasize())
revert(ptr_, returndatasize())
}
reserve0 := mload(0x00)
reserve1 := mload(0x20)
blockTimestampLast := mload(0x40)
mstore(0x40, ptr)
}
}
function fastPriceCumulativeLast(IUniswapV2Pair pair, bool which) internal view returns (uint256 r) {
assembly ("memory-safe") {
mstore(0x00, xor(0x5909c0d5, mul(0x03349446, which)))
if iszero(staticcall(gas(), pair, 0x1c, 0x04, 0x00, 0x20)) {
let ptr := mload(0x40)
returndatacopy(ptr, 0x00, returndatasize())
revert(ptr, returndatasize())
}
r := mload(0x00)
}
}
function fastKLast(IUniswapV2Pair pair) internal view returns (uint256 r) {
assembly ("memory-safe") {
mstore(0x00, 0x7464fc3d)
if iszero(staticcall(gas(), pair, 0x1c, 0x04, 0x00, 0x20)) {
let ptr := mload(0x40)
returndatacopy(ptr, 0x00, returndatasize())
revert(ptr, returndatasize())
}
r := mload(0x00)
}
}
function fastBurn(IUniswapV2Pair pair, address to) internal returns (uint256 amount0, uint256 amount1) {
assembly ("memory-safe") {
mstore(0x14, to)
mstore(0x00, 0x89afcb44000000000000000000000000)
if iszero(call(gas(), pair, 0x00, 0x10, 0x24, 0x00, 0x40)) {
let ptr := mload(0x40)
returndatacopy(ptr, 0x00, returndatasize())
revert(ptr, returndatasize())
}
amount0 := mload(0x00)
amount1 := mload(0x20)
}
}
function fastSwap(IUniswapV2Pair pair, uint256 amount0, uint256 amount1, address to) internal {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(ptr, 0x022c0d9f)
mstore(add(0x20, ptr), amount0)
mstore(add(0x40, ptr), amount1)
mstore(add(0x60, ptr), and(0xffffffffffffffffffffffffffffffffffffffff, to))
mstore(add(0x80, ptr), 0x80)
mstore(add(0xa0, ptr), 0x00)
if iszero(call(gas(), pair, 0x00, add(0x1c, ptr), 0xa4, 0x00, 0x00)) {
let ptr_ := mload(0x40)
returndatacopy(ptr_, 0x00, returndatasize())
revert(ptr_, returndatasize())
}
}
}
}
bytes32 constant INIT_HASH = 0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f;
文件 25 的 46:ItoA.sol
pragma solidity ^0.8.28;
library ItoA {
function itoa(uint256 x) internal pure returns (string memory r) {
assembly ("memory-safe") {
mstore(9, 0x30313233343536373839)
let end := add(mload(0x40), 0x6e)
mstore(0x40, end)
for {
r := sub(end, 0x01)
mstore8(r, mload(mod(x, 0x0a)))
x := div(x, 0x0a)
} x {} {
r := sub(r, 0x01)
mstore8(r, mload(mod(x, 0x0a)))
x := div(x, 0x0a)
}
let length := sub(end, r)
r := sub(r, 0x20)
mstore(r, length)
}
}
function itoa(int256 value) internal pure returns (string memory) {
if (value < 0) {
return string.concat("-", itoa(uint256(-value)));
} else {
return itoa(uint256(value));
}
}
}
文件 26 的 46:Math.sol
pragma solidity ^0.8.28;
library Math {
function saturatingAdd(uint256 x, uint256 y) internal pure returns (uint256 r) {
assembly ("memory-safe") {
r := add(x, y)
r := or(r, sub(0x00, lt(r, y)))
}
}
function saturatingSub(uint256 x, uint256 y) internal pure returns (uint256 r) {
assembly ("memory-safe") {
r := mul(sub(x, y), gt(x, y))
}
}
function sqrt(uint256 x) internal pure returns (uint256 z) {
assembly ("memory-safe") {
let y := x
z := 181
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
y := shr(128, y)
z := shl(64, z)
}
if iszero(lt(y, 0x1000000000000000000)) {
y := shr(64, y)
z := shl(32, z)
}
if iszero(lt(y, 0x10000000000)) {
y := shr(32, y)
z := shl(16, z)
}
if iszero(lt(y, 0x1000000)) {
y := shr(16, y)
z := shl(8, z)
}
z := shr(18, mul(z, add(y, 65536)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
}
}
}
文件 27 的 46:MoonPhase.sol
pragma solidity ^0.8.28;
import {BasisPoints} from "../types/BasisPoints.sol";
import {Ternary} from "../lib/Ternary.sol";
import {UnsafeMath} from "../lib/UnsafeMath.sol";
library MoonPhase {
using Ternary for bool;
using UnsafeMath for int256;
uint256 private constant _EPOCH = 1740721485;
uint256 private constant _SYNODIC_MONTH = 0x17348a775920;
uint256 private constant _SCALE = 0x9896800000000000000000;
int256 private constant _ONE_HALF = 0x8000000000000000;
int256 private constant _ONE_QUARTER = 0x4000000000000000;
int256 private constant _THREE_QUARTERS = 0xc000000000000000;
function moonPhase(uint256 timestamp) internal pure returns (BasisPoints) {
uint256 reEpoch = timestamp - _EPOCH;
unchecked {
int256 monthElapsed = int256((reEpoch * _SCALE / _SYNODIC_MONTH) & type(uint64).max);
int256 x;
{
int256 thresh = (monthElapsed < _ONE_HALF).ternary(_ONE_QUARTER, _THREE_QUARTERS);
x = (monthElapsed < thresh).ternary(thresh - monthElapsed, monthElapsed - thresh);
}
int256 sign = (uint256(monthElapsed) - uint256(_ONE_QUARTER) < uint256(_ONE_HALF)).ternary(-1, 1);
int256 p = x;
p += 0x152c603e02fe2031;
p *= x;
p -= 0x462df383df0568550000000000000000;
p *= x;
p *= sign;
int256 q = -0x1d98428cf2b72221;
q *= x;
q += 0x032c1ccefcbad6dd0000000000000000;
q *= x;
q -= 0x0b2a3a89efcf885e00000000000000000000000000000000;
return BasisPoints.wrap(uint256(((p + q) * 2500).unsafeDiv(q)) + 1);
}
}
}
文件 28 的 46:MultiCallContext.sol
pragma solidity ^0.8.28;
import {Context} from "./Context.sol";
interface IMultiCall {
enum RevertPolicy {
REVERT,
HALT,
CONTINUE
}
struct Call {
address target;
RevertPolicy revertPolicy;
uint256 value;
bytes data;
}
struct Result {
bool success;
bytes data;
}
function multicall(Call[] calldata calls, uint256 contextdepth) external payable returns (Result[] memory);
receive() external payable;
}
abstract contract MultiCallContext is Context {
address private constant _MULTICALL_ADDRESS = 0x00000000000000CF9E3c5A26621af382fA17f24f;
IMultiCall internal constant MULTICALL = IMultiCall(payable(_MULTICALL_ADDRESS));
function _isForwarded() internal view virtual override returns (bool) {
return super._isForwarded() || super._msgSender() == address(MULTICALL);
}
function _msgData() internal view virtual override returns (bytes calldata r) {
address sender = super._msgSender();
r = super._msgData();
assembly ("memory-safe") {
r.length :=
sub(r.length, mul(0x14, eq(_MULTICALL_ADDRESS, and(0xffffffffffffffffffffffffffffffffffffffff, sender))))
}
}
function _msgSender() internal view virtual override returns (address sender) {
sender = super._msgSender();
if (sender == address(MULTICALL)) {
bytes calldata data = super._msgData();
assembly ("memory-safe") {
sender := shr(0x60, calldataload(add(data.offset, sub(data.length, 0x14))))
}
}
}
}
文件 29 的 46:Panic.sol
pragma solidity ^0.8.28;
library Panic {
function panic(uint256 code) internal pure {
assembly ("memory-safe") {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
uint8 internal constant GENERIC = 0x00;
uint8 internal constant ASSERT_FAIL = 0x01;
uint8 internal constant ARITHMETIC_OVERFLOW = 0x11;
uint8 internal constant DIVISION_BY_ZERO = 0x12;
uint8 internal constant ENUM_CAST = 0x21;
uint8 internal constant CORRUPT_STORAGE_ARRAY = 0x22;
uint8 internal constant POP_EMPTY_ARRAY = 0x31;
uint8 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
uint8 internal constant OUT_OF_MEMORY = 0x41;
uint8 internal constant ZERO_FUNCTION_POINTER = 0x51;
}
文件 30 的 46:RebaseQueue.sol
pragma solidity ^0.8.28;
import {IERC20} from "@forge-std/interfaces/IERC20.sol";
import {Settings} from "./Settings.sol";
import {applyWhaleLimit} from "./WhaleLimit.sol";
import {Tokens, ZERO as ZERO_TOKENS} from "../types/Tokens.sol";
import {Shares, SharesStorage, ONE as ONE_SHARE} from "../types/Shares.sol";
import {SharesToTokens} from "../types/TokensXShares.sol";
import {Tokens} from "../types/Tokens.sol";
import {UnsafeMath} from "../lib/UnsafeMath.sol";
struct RebaseQueueElem {
address prev;
address next;
Tokens lastTokens;
}
struct RebaseQueue {
mapping(address => RebaseQueueElem) queue;
address head;
}
library LibRebaseQueue {
using UnsafeMath for uint256;
using SharesToTokens for Shares;
function initialize(RebaseQueue storage self, address account, Tokens tokens) internal {
self.head = account;
RebaseQueueElem storage elem = self.queue[account];
elem.prev = account;
elem.next = account;
elem.lastTokens = tokens;
}
function enqueue(RebaseQueue storage self, address account, Tokens balance) internal {
RebaseQueueElem storage elem = self.queue[account];
address head = self.head;
RebaseQueueElem storage headElem = self.queue[head];
address tail = headElem.prev;
elem.prev = tail;
elem.next = head;
elem.lastTokens = balance;
self.queue[tail].next = account;
headElem.prev = account;
}
function enqueue(RebaseQueue storage self, address account, Shares shares, Tokens totalSupply, Shares totalShares)
internal
{
return enqueue(self, account, shares.toTokens(totalSupply, totalShares));
}
function dequeue(RebaseQueue storage self, address account) internal {
RebaseQueueElem storage elem = self.queue[account];
elem.lastTokens = ZERO_TOKENS;
address prev = elem.prev;
address next = elem.next;
elem.prev = address(0);
elem.next = address(0);
self.queue[prev].next = next;
self.queue[next].prev = prev;
if (self.head == account) {
self.head = next;
}
}
function moveToBack(
RebaseQueue storage self,
address account,
Shares shares,
Tokens totalSupply,
Shares totalShares
) internal {
RebaseQueueElem storage elem = self.queue[account];
elem.lastTokens = shares.toTokens(totalSupply, totalShares);
if (self.head == account) {
self.head = elem.next;
return;
}
address next = elem.next;
address head = self.head;
if (next == head) {
return;
}
address prev = elem.prev;
RebaseQueueElem storage headElem = self.queue[head];
address tail = headElem.prev;
elem.prev = tail;
elem.next = head;
self.queue[prev].next = next;
self.queue[next].prev = prev;
self.queue[tail].next = account;
headElem.prev = account;
}
function _rebaseFor(
RebaseQueueElem storage elem,
address account,
Shares shares,
Tokens totalSupply,
Shares totalShares
) private returns (Tokens newTokens) {
Tokens oldTokens = elem.lastTokens;
newTokens = shares.toTokens(totalSupply, totalShares);
if (newTokens > oldTokens) {
emit IERC20.Transfer(address(0), account, (newTokens - oldTokens).toExternal());
} else {
newTokens = oldTokens;
}
}
function rebaseFor(RebaseQueue storage self, address account, Shares shares, Tokens totalSupply, Shares totalShares)
internal
{
_rebaseFor(self.queue[account], account, shares, totalSupply, totalShares);
}
function processQueue(
RebaseQueue storage self,
mapping(address => SharesStorage) storage sharesOf,
Tokens totalSupply,
Shares totalShares
) internal {
address cursor = self.head;
RebaseQueueElem storage elem = self.queue[cursor];
uint256 i;
assembly ("memory-safe") {
mstore(0x00, gas())
i := shr(0xfd, keccak256(0x00, 0x20))
}
for (;; i = i.unsafeDec()) {
(Shares shares, Shares totalSharesLimited) = applyWhaleLimit(sharesOf[cursor].load(), totalShares);
elem.lastTokens = _rebaseFor(elem, cursor, shares, totalSupply, totalSharesLimited);
cursor = elem.next;
if (i == 0) {
break;
}
elem = self.queue[cursor];
}
self.head = cursor;
}
}
文件 31 的 46:ReflectMath.sol
pragma solidity ^0.8.28;
import {Settings} from "../core/Settings.sol";
import {whaleLimit} from "../core/WhaleLimit.sol";
import {BasisPoints, BASIS} from "../types/BasisPoints.sol";
import {Shares, ONE as ONE_SHARE} from "../types/Shares.sol";
import {Tokens} from "../types/Tokens.sol";
import {TokensXBasisPoints, scale, cast} from "../types/TokensXBasisPoints.sol";
import {TokensXShares, tmp as tmpTS, alloc as allocTS} from "../types/TokensXShares.sol";
import {TokensXShares2} from "../types/TokensXShares2.sol";
import {TokensXBasisPointsXShares, tmp as tmpTBpS, alloc as allocTBpS} from "../types/TokensXBasisPointsXShares.sol";
import {TokensXBasisPointsXShares2} from "../types/TokensXBasisPointsXShares2.sol";
import {SharesXBasisPoints, scale, cast} from "../types/SharesXBasisPoints.sol";
import {Shares2XBasisPoints, alloc as allocS2Bp} from "../types/Shares2XBasisPoints.sol";
library ReflectMath {
modifier freeMemory() {
uint256 freePtr;
assembly ("memory-safe") {
freePtr := mload(0x40)
}
_;
assembly ("memory-safe") {
mstore(0x40, freePtr)
}
}
function getTransferShares(
Tokens amount,
BasisPoints taxRate,
Tokens totalSupply,
Shares totalShares,
Shares fromShares,
Shares toShares
) internal pure freeMemory returns (Shares newFromShares, Shares newToShares, Shares newTotalShares) {
Shares uninvolvedShares = totalShares - fromShares - toShares;
TokensXBasisPointsXShares2 n0 = allocTS().omul(fromShares, totalSupply).isub(tmpTS().omul(amount, totalShares))
.imul(scale(uninvolvedShares, BASIS));
TokensXBasisPointsXShares d = allocTBpS().omul(totalSupply, scale(uninvolvedShares, BASIS)).iadd(
tmpTBpS().omul(amount, scale(totalShares, taxRate))
);
TokensXBasisPointsXShares2 n1 = allocTBpS().omul(amount, scale(totalShares, BASIS - taxRate)).iadd(
tmpTBpS().omul(scale(toShares, BASIS), totalSupply)
).imul(uninvolvedShares);
(newFromShares, newToShares) = (n0.div(d), n1.div(d));
newTotalShares = totalShares + (newToShares - toShares) - (fromShares - newFromShares);
}
function getTransferAllShares(BasisPoints taxRate, Shares totalShares, Shares fromShares, Shares toShares)
internal
pure
freeMemory
returns (Shares newToShares, Shares newTotalShares)
{
Shares uninvolvedShares = totalShares - fromShares - toShares;
Shares2XBasisPoints n = allocS2Bp().omul(scale(uninvolvedShares, BASIS), totalShares);
SharesXBasisPoints d = scale(uninvolvedShares, BASIS) + scale(fromShares, taxRate);
newTotalShares = n.div(d);
newToShares = toShares + fromShares - (totalShares - newTotalShares);
}
function getTransferSharesToWhale(
Tokens amount,
BasisPoints taxRate,
Tokens totalSupply,
Shares totalShares,
Shares fromShares,
Shares toShares
)
internal
pure
freeMemory
returns (Shares newFromShares, Shares counterfactualToShares, Shares newToShares, Shares newTotalShares)
{
TokensXShares d = allocTS().omul(totalShares.mul(Settings.ANTI_WHALE_DIVISOR), totalSupply + amount).isub(
tmpTS().omul(fromShares.mul(Settings.ANTI_WHALE_DIVISOR) + totalShares, totalSupply)
);
Shares uninvolvedShares = totalShares - fromShares - toShares;
TokensXShares2 n0 =
allocTS().omul(totalShares.mul(Settings.ANTI_WHALE_DIVISOR), totalSupply).imul(uninvolvedShares);
TokensXShares2 n1 = allocTS().omul(fromShares, totalSupply).isub(tmpTS().omul(totalShares, amount)).imul(
uninvolvedShares.mul(Settings.ANTI_WHALE_DIVISOR)
);
(newToShares, newFromShares) = (n0.div(d), n1.div(d));
newToShares = newToShares.div(Settings.ANTI_WHALE_DIVISOR) - ONE_SHARE;
newTotalShares = totalShares - (fromShares + toShares - newFromShares - newToShares);
counterfactualToShares = tmpTBpS().omul(
scale(totalSupply, BASIS.div(Settings.ANTI_WHALE_DIVISOR)) - scale(amount, BASIS - taxRate), totalShares
).div(scale(totalSupply, BASIS));
}
function getTransferAllSharesToWhale(BasisPoints taxRate, Shares totalShares, Shares fromShares, Shares toShares)
internal
pure
returns (Shares counterfactualToShares, Shares newToShares, Shares newTotalShares)
{
(newToShares, newTotalShares) = whaleLimit(toShares, totalShares - fromShares);
counterfactualToShares =
cast(scale(totalShares, BASIS.div(Settings.ANTI_WHALE_DIVISOR)) - scale(fromShares, BASIS - taxRate));
}
function getTransferSharesFromPair(
BasisPoints taxRate,
Tokens totalSupply,
Shares totalShares,
Tokens amount,
Shares toShares
) internal pure freeMemory returns (Shares newToShares, Shares newTotalShares, Tokens newTotalSupply) {
TokensXBasisPointsXShares d = allocTBpS().omul(scale(totalSupply, BASIS), totalShares).iadd(
tmpTBpS().omul(scale(amount, taxRate), totalShares)
);
TokensXBasisPointsXShares t = tmpTBpS().omul(scale(totalSupply, BASIS), toShares);
d.isub(t);
TokensXBasisPointsXShares2 n =
allocTBpS().omul(scale(amount, BASIS - taxRate), totalShares).iadd(t).imul(totalShares - toShares);
newToShares = n.div(d);
newTotalShares = totalShares + newToShares - toShares;
newTotalSupply = totalSupply + amount;
}
function getCounterfactualSharesFromPairToWhale(
BasisPoints taxRate,
Tokens totalSupply,
Shares totalShares,
Tokens amount
) internal pure returns (Shares counterfactualToShares) {
TokensXBasisPoints left = scale(totalSupply + amount, BASIS);
TokensXBasisPoints right = scale(amount.mul(Settings.ANTI_WHALE_DIVISOR), BASIS - taxRate);
counterfactualToShares = tmpTBpS().omul(left.saturatingSub(right), totalShares).div(
scale(totalSupply.mul(Settings.ANTI_WHALE_DIVISOR), BASIS)
);
}
function getTransferSharesToPair(
BasisPoints taxRate,
Tokens totalSupply,
Shares totalShares,
Tokens amount,
Shares fromShares
)
internal
pure
freeMemory
returns (Shares newFromShares, Shares newTotalShares, Tokens transferTokens, Tokens newTotalSupply)
{
TokensXBasisPointsXShares2 n = allocTBpS().omul(scale(fromShares, BASIS), totalSupply).isub(
tmpTBpS().omul(scale(totalShares, BASIS), amount)
).imul(totalShares - fromShares);
TokensXBasisPointsXShares d = allocTBpS().omul(scale(totalShares, taxRate), amount).iadd(
tmpTBpS().omul(scale(totalShares - fromShares, BASIS), totalSupply)
);
newFromShares = n.div(d);
newTotalShares = totalShares - (fromShares - newFromShares);
transferTokens = cast(scale(amount, BASIS - taxRate));
newTotalSupply = totalSupply - transferTokens;
}
function getDeliverShares(Tokens amount, Tokens totalSupply, Shares totalShares, Shares fromShares)
internal
pure
freeMemory
returns (Shares newFromShares, Shares newTotalShares)
{
TokensXShares d = allocTS().omul(totalSupply, totalShares - fromShares);
TokensXShares t = tmpTS().omul(amount, totalShares);
d.iadd(t);
TokensXShares2 n = allocTS().omul(fromShares, totalSupply).isub(t).imul(totalShares - fromShares);
newFromShares = n.div(d);
newTotalShares = totalShares + newFromShares - fromShares;
}
function getBurnShares(Tokens amount, Tokens totalSupply, Shares totalShares, Shares fromShares)
internal
pure
freeMemory
returns (Shares newFromShares, Shares newTotalShares, Tokens newTotalSupply)
{
TokensXShares n = allocTS().omul(fromShares, totalSupply).isub(tmpTS().omul(totalShares, amount));
newFromShares = n.div(totalSupply);
newTotalShares = totalShares + newFromShares - fromShares;
newTotalSupply = totalSupply - amount;
}
}
文件 32 的 46:Settings.sol
pragma solidity ^0.8.28;
import {ReflectMath} from "./ReflectMath.sol";
import {BasisPoints, BASIS} from "../types/BasisPoints.sol";
import {Shares} from "../types/Shares.sol";
import {Tokens} from "../types/Tokens.sol";
import {TokensXShares, alloc, tmp} from "../types/TokensXShares.sol";
import {UnsafeMath} from "../lib/UnsafeMath.sol";
library Settings {
using UnsafeMath for uint256;
uint256 internal constant INITIAL_LIQUIDITY_DIVISOR = 5;
uint256 internal constant ANTI_WHALE_DIVISOR = 40;
uint256 internal constant ANTI_WHALE_DIVISOR_MINUS_ONE = 39;
uint256 internal constant ANTI_WHALE_DIVISOR_MINUS_TWO = 38;
BasisPoints internal constant MIN_TAX = BasisPoints.wrap(1);
BasisPoints internal constant MAX_TAX = BasisPoints.wrap(5_000);
uint256 private constant _UNISWAPV2_MAX_BALANCE = 0xffffffffffffffffffffffffffff;
uint8 internal constant DECIMALS = 35;
uint256 internal constant PAIR_LEADING_ZEROES = 32;
uint256 internal constant CRAZY_BALANCE_BASIS = 0x1ffffffff;
Tokens internal constant INITIAL_SUPPLY = Tokens.wrap(0x1fffffffefffffffffffffffffffe00000001);
Shares internal constant INITIAL_SHARES = Shares.wrap(0x1fffffffefffffffffffffffffffe0000000100000000);
uint256 internal constant INITIAL_SHARES_RATIO = 0x100000000;
uint256 internal constant MIN_SHARES_RATIO = 5;
uint256 internal constant ADDRESS_DIVISOR = 0x80000000000000000000000000000000;
uint256 internal constant ADDRESS_SHIFT = 127;
uint256 internal constant SHARES_TO_VOTES_DIVISOR = 0x100000000;
uint256 internal constant SHARES_TO_VOTES_SHIFT = 32;
uint256 internal constant BISECT_WINDOW_DEFAULT = 7;
function oneTokenInShares() internal pure returns (Shares) {
TokensXShares initialSharesTimesOneToken = alloc().omul(INITIAL_SHARES, Tokens.wrap(10 ** DECIMALS));
Shares result = initialSharesTimesOneToken.div(INITIAL_SUPPLY);
result = result.inc(tmp().omul(result, INITIAL_SUPPLY) < initialSharesTimesOneToken);
return result;
}
}
文件 33 的 46:Shares.sol
pragma solidity ^0.8.28;
import {UnsafeMath} from "../lib/UnsafeMath.sol";
import {Ternary} from "../lib/Ternary.sol";
type Shares is uint256;
Shares constant ZERO = Shares.wrap(0);
Shares constant ONE = Shares.wrap(1);
library SharesUnsafeMathAdapter {
using UnsafeMath for uint256;
function inc(Shares x, bool c) internal pure returns (Shares) {
return Shares.wrap(Shares.unwrap(x).unsafeInc(c));
}
function dec(Shares x, bool c) internal pure returns (Shares) {
return Shares.wrap(Shares.unwrap(x).unsafeDec(c));
}
}
using SharesUnsafeMathAdapter for Shares global;
library SharesArithmetic {
using UnsafeMath for uint256;
function mul(Shares x, uint256 y) internal pure returns (Shares) {
unchecked {
return Shares.wrap(Shares.unwrap(x) * y);
}
}
function div(Shares n, uint256 d) internal pure returns (Shares) {
return Shares.wrap(Shares.unwrap(n).unsafeDiv(d));
}
}
using SharesArithmetic for Shares global;
function __add(Shares a, Shares b) pure returns (Shares) {
unchecked {
return Shares.wrap(Shares.unwrap(a) + Shares.unwrap(b));
}
}
function __sub(Shares a, Shares b) pure returns (Shares) {
unchecked {
return Shares.wrap(Shares.unwrap(a) - Shares.unwrap(b));
}
}
function __eq(Shares a, Shares b) pure returns (bool) {
return Shares.unwrap(a) == Shares.unwrap(b);
}
function __lt(Shares a, Shares b) pure returns (bool) {
return Shares.unwrap(a) < Shares.unwrap(b);
}
function __gt(Shares a, Shares b) pure returns (bool) {
return Shares.unwrap(a) > Shares.unwrap(b);
}
function __ne(Shares a, Shares b) pure returns (bool) {
return Shares.unwrap(a) != Shares.unwrap(b);
}
function __le(Shares a, Shares b) pure returns (bool) {
return Shares.unwrap(a) <= Shares.unwrap(b);
}
function __ge(Shares a, Shares b) pure returns (bool) {
return Shares.unwrap(a) >= Shares.unwrap(b);
}
using {
__add as +, __sub as -, __eq as ==, __lt as <, __gt as >, __ne as !=, __le as <=, __gt as >=
} for Shares global;
function ternary(bool c, Shares x, Shares y) pure returns (Shares) {
return Shares.wrap(Ternary.ternary(c, Shares.unwrap(x), Shares.unwrap(y)));
}
function maybeSwap(bool c, Shares x, Shares y) pure returns (Shares, Shares) {
(uint256 a, uint256 b) = Ternary.maybeSwap(c, Shares.unwrap(x), Shares.unwrap(y));
return (Shares.wrap(a), Shares.wrap(b));
}
type SharesStorage is uint256;
function load(SharesStorage x) pure returns (Shares r) {
assembly ("memory-safe") {
r := mul(shr(0x28, x), iszero(and(0xffffffffff00000000000000000000000000000000000000000000ffffffffff, x)))
}
}
function store(Shares x) pure returns (SharesStorage r) {
assembly ("memory-safe") {
r := shl(0x28, x)
}
}
using {load} for SharesStorage global;
using {store} for Shares global;
文件 34 的 46:Shares2XBasisPoints.sol
pragma solidity ^0.8.28;
import {Shares} from "./Shares.sol";
import {SharesXBasisPoints} from "./SharesXBasisPoints.sol";
import {uint512, alloc as baseAlloc} from "../lib/512Math.sol";
type Shares2XBasisPoints is bytes32;
function cast(Shares2XBasisPoints x) pure returns (uint512) {
return uint512.wrap(Shares2XBasisPoints.unwrap(x));
}
function cast(uint512 x) pure returns (Shares2XBasisPoints) {
return Shares2XBasisPoints.wrap(uint512.unwrap(x));
}
function alloc() pure returns (Shares2XBasisPoints) {
return cast(baseAlloc());
}
library Shares2XBasisPointsArithmetic {
function omul(Shares2XBasisPoints r, SharesXBasisPoints sbp, Shares s)
internal
pure
returns (Shares2XBasisPoints)
{
return cast(cast(r).omul(SharesXBasisPoints.unwrap(sbp), Shares.unwrap(s)));
}
function omul(Shares2XBasisPoints r, Shares s, SharesXBasisPoints sbp)
internal
pure
returns (Shares2XBasisPoints)
{
return cast(cast(r).omul(Shares.unwrap(s), SharesXBasisPoints.unwrap(sbp)));
}
function div(Shares2XBasisPoints n, SharesXBasisPoints d) internal pure returns (Shares) {
return Shares.wrap(cast(n).div(SharesXBasisPoints.unwrap(d)));
}
function div(Shares2XBasisPoints n, Shares d) internal pure returns (SharesXBasisPoints) {
return SharesXBasisPoints.wrap(cast(n).div(Shares.unwrap(d)));
}
}
using Shares2XBasisPointsArithmetic for Shares2XBasisPoints global;
function __eq(Shares2XBasisPoints a, Shares2XBasisPoints b) pure returns (bool) {
return cast(a) == cast(b);
}
function __lt(Shares2XBasisPoints a, Shares2XBasisPoints b) pure returns (bool) {
return cast(a) < cast(b);
}
function __gt(Shares2XBasisPoints a, Shares2XBasisPoints b) pure returns (bool) {
return cast(a) > cast(b);
}
function __ne(Shares2XBasisPoints a, Shares2XBasisPoints b) pure returns (bool) {
return cast(a) != cast(b);
}
function __le(Shares2XBasisPoints a, Shares2XBasisPoints b) pure returns (bool) {
return cast(a) <= cast(b);
}
function __ge(Shares2XBasisPoints a, Shares2XBasisPoints b) pure returns (bool) {
return cast(a) >= cast(b);
}
using {__eq as ==, __lt as <, __gt as >, __ne as !=, __le as <=, __ge as >=} for Shares2XBasisPoints global;
文件 35 的 46:SharesXBasisPoints.sol
pragma solidity ^0.8.28;
import {BasisPoints, BASIS} from "./BasisPoints.sol";
import {Shares} from "./Shares.sol";
import {UnsafeMath} from "../lib/UnsafeMath.sol";
type SharesXBasisPoints is uint256;
function scale(Shares s, BasisPoints bp) pure returns (SharesXBasisPoints) {
unchecked {
return SharesXBasisPoints.wrap(Shares.unwrap(s) * BasisPoints.unwrap(bp));
}
}
function cast(SharesXBasisPoints tbp) pure returns (Shares) {
return Shares.wrap(UnsafeMath.unsafeDiv(SharesXBasisPoints.unwrap(tbp), BasisPoints.unwrap(BASIS)));
}
function __add(SharesXBasisPoints a, SharesXBasisPoints b) pure returns (SharesXBasisPoints) {
unchecked {
return SharesXBasisPoints.wrap(SharesXBasisPoints.unwrap(a) + SharesXBasisPoints.unwrap(b));
}
}
function __sub(SharesXBasisPoints a, SharesXBasisPoints b) pure returns (SharesXBasisPoints) {
unchecked {
return SharesXBasisPoints.wrap(SharesXBasisPoints.unwrap(a) - SharesXBasisPoints.unwrap(b));
}
}
using {__add as +, __sub as -} for SharesXBasisPoints global;
文件 36 的 46:Ternary.sol
pragma solidity ^0.8.28;
library Ternary {
function ternary(bool c, uint256 x, uint256 y) internal pure returns (uint256 r) {
assembly ("memory-safe") {
r := xor(y, mul(xor(x, y), c))
}
}
function ternary(bool c, int256 x, int256 y) internal pure returns (int256 r) {
assembly ("memory-safe") {
r := xor(y, mul(xor(x, y), c))
}
}
function maybeSwap(bool c, uint256 x, uint256 y) internal pure returns (uint256 a, uint256 b) {
assembly ("memory-safe") {
let t := mul(xor(x, y), c)
a := xor(x, t)
b := xor(y, t)
}
}
}
文件 37 的 46:Tokens.sol
pragma solidity ^0.8.28;
import {UnsafeMath} from "../lib/UnsafeMath.sol";
type Tokens is uint256;
library TokensAccessors {
function toExternal(Tokens x) internal pure returns (uint256) {
return Tokens.unwrap(x);
}
}
using TokensAccessors for Tokens global;
Tokens constant ZERO = Tokens.wrap(0);
Tokens constant ONE = Tokens.wrap(1);
library TokensUnsafeMathAdapter {
using UnsafeMath for uint256;
function inc(Tokens x, bool c) internal pure returns (Tokens) {
return Tokens.wrap(Tokens.unwrap(x).unsafeInc(c));
}
function dec(Tokens x, bool c) internal pure returns (Tokens) {
return Tokens.wrap(Tokens.unwrap(x).unsafeDec(c));
}
}
using TokensUnsafeMathAdapter for Tokens global;
library TokensArithmetic {
using UnsafeMath for uint256;
function mul(Tokens x, uint256 y) internal pure returns (Tokens) {
unchecked {
return Tokens.wrap(Tokens.unwrap(x) * y);
}
}
function div(Tokens n, uint256 d) internal pure returns (Tokens) {
return Tokens.wrap(Tokens.unwrap(n).unsafeDiv(d));
}
}
using TokensArithmetic for Tokens global;
function __add(Tokens a, Tokens b) pure returns (Tokens) {
unchecked {
return Tokens.wrap(Tokens.unwrap(a) + Tokens.unwrap(b));
}
}
function __sub(Tokens a, Tokens b) pure returns (Tokens) {
unchecked {
return Tokens.wrap(Tokens.unwrap(a) - Tokens.unwrap(b));
}
}
function __eq(Tokens a, Tokens b) pure returns (bool) {
return Tokens.unwrap(a) == Tokens.unwrap(b);
}
function __lt(Tokens a, Tokens b) pure returns (bool) {
return Tokens.unwrap(a) < Tokens.unwrap(b);
}
function __gt(Tokens a, Tokens b) pure returns (bool) {
return Tokens.unwrap(a) > Tokens.unwrap(b);
}
function __ne(Tokens a, Tokens b) pure returns (bool) {
return Tokens.unwrap(a) != Tokens.unwrap(b);
}
function __le(Tokens a, Tokens b) pure returns (bool) {
return Tokens.unwrap(a) <= Tokens.unwrap(b);
}
function __ge(Tokens a, Tokens b) pure returns (bool) {
return Tokens.unwrap(a) >= Tokens.unwrap(b);
}
using {
__add as +, __sub as -, __eq as ==, __lt as <, __gt as >, __ne as !=, __le as <=, __ge as >=
} for Tokens global;
文件 38 的 46:TokensXBasisPoints.sol
pragma solidity ^0.8.28;
import {BasisPoints, BASIS} from "./BasisPoints.sol";
import {Tokens} from "./Tokens.sol";
import {Math} from "../lib/Math.sol";
import {UnsafeMath} from "../lib/UnsafeMath.sol";
type TokensXBasisPoints is uint256;
library TokensXBasisPointsArithmetic {
function saturatingAdd(TokensXBasisPoints x, TokensXBasisPoints y) internal pure returns (TokensXBasisPoints r) {
return TokensXBasisPoints.wrap(Math.saturatingAdd(TokensXBasisPoints.unwrap(x), TokensXBasisPoints.unwrap(y)));
}
function saturatingSub(TokensXBasisPoints x, TokensXBasisPoints y) internal pure returns (TokensXBasisPoints r) {
return TokensXBasisPoints.wrap(Math.saturatingSub(TokensXBasisPoints.unwrap(x), TokensXBasisPoints.unwrap(y)));
}
}
using TokensXBasisPointsArithmetic for TokensXBasisPoints global;
function scale(Tokens s, BasisPoints bp) pure returns (TokensXBasisPoints) {
unchecked {
return TokensXBasisPoints.wrap(Tokens.unwrap(s) * BasisPoints.unwrap(bp));
}
}
function cast(TokensXBasisPoints tbp) pure returns (Tokens) {
return Tokens.wrap(UnsafeMath.unsafeDiv(TokensXBasisPoints.unwrap(tbp), BasisPoints.unwrap(BASIS)));
}
function castUp(TokensXBasisPoints tbp) pure returns (Tokens) {
return Tokens.wrap(UnsafeMath.unsafeDivUp(TokensXBasisPoints.unwrap(tbp), BasisPoints.unwrap(BASIS)));
}
function __sub(TokensXBasisPoints a, TokensXBasisPoints b) pure returns (TokensXBasisPoints) {
unchecked {
return TokensXBasisPoints.wrap(TokensXBasisPoints.unwrap(a) - TokensXBasisPoints.unwrap(b));
}
}
function __eq(TokensXBasisPoints a, TokensXBasisPoints b) pure returns (bool) {
return TokensXBasisPoints.unwrap(a) == TokensXBasisPoints.unwrap(b);
}
function __lt(TokensXBasisPoints a, TokensXBasisPoints b) pure returns (bool) {
return TokensXBasisPoints.unwrap(a) < TokensXBasisPoints.unwrap(b);
}
function __gt(TokensXBasisPoints a, TokensXBasisPoints b) pure returns (bool) {
return TokensXBasisPoints.unwrap(a) > TokensXBasisPoints.unwrap(b);
}
function __ne(TokensXBasisPoints a, TokensXBasisPoints b) pure returns (bool) {
return TokensXBasisPoints.unwrap(a) != TokensXBasisPoints.unwrap(b);
}
function __le(TokensXBasisPoints a, TokensXBasisPoints b) pure returns (bool) {
return TokensXBasisPoints.unwrap(a) <= TokensXBasisPoints.unwrap(b);
}
function __ge(TokensXBasisPoints a, TokensXBasisPoints b) pure returns (bool) {
return TokensXBasisPoints.unwrap(a) >= TokensXBasisPoints.unwrap(b);
}
using {
__sub as -, __eq as ==, __lt as <, __gt as >, __ne as !=, __le as <=, __ge as >=
} for TokensXBasisPoints global;
文件 39 的 46:TokensXBasisPointsXShares.sol
pragma solidity ^0.8.28;
import {BASIS} from "./BasisPoints.sol";
import {Shares} from "./Shares.sol";
import {Tokens} from "./Tokens.sol";
import {SharesXBasisPoints, scale} from "./SharesXBasisPoints.sol";
import {TokensXBasisPoints} from "./TokensXBasisPoints.sol";
import {TokensXBasisPointsXShares2, cast as cast2} from "./TokensXBasisPointsXShares2.sol";
import {uint512, tmp as baseTmp, alloc as baseAlloc} from "../lib/512Math.sol";
type TokensXBasisPointsXShares is bytes32;
function cast(TokensXBasisPointsXShares x) pure returns (uint512) {
return uint512.wrap(TokensXBasisPointsXShares.unwrap(x));
}
function cast(uint512 x) pure returns (TokensXBasisPointsXShares) {
return TokensXBasisPointsXShares.wrap(uint512.unwrap(x));
}
function alloc() pure returns (TokensXBasisPointsXShares) {
return cast(baseAlloc());
}
function tmp() pure returns (TokensXBasisPointsXShares) {
return cast(baseTmp());
}
library TokensXBasisPointsXSharesArithmetic {
function iadd(TokensXBasisPointsXShares r, TokensXBasisPointsXShares x)
internal
pure
returns (TokensXBasisPointsXShares)
{
return cast(cast(r).iadd(cast(x)));
}
function isub(TokensXBasisPointsXShares r, TokensXBasisPointsXShares x)
internal
pure
returns (TokensXBasisPointsXShares)
{
return cast(cast(r).isub(cast(x)));
}
function omul(TokensXBasisPointsXShares r, Tokens b, SharesXBasisPoints s)
internal
pure
returns (TokensXBasisPointsXShares)
{
return cast(cast(r).omul(Tokens.unwrap(b), SharesXBasisPoints.unwrap(s)));
}
function omul(TokensXBasisPointsXShares r, SharesXBasisPoints s, Tokens b)
internal
pure
returns (TokensXBasisPointsXShares)
{
return cast(cast(r).omul(SharesXBasisPoints.unwrap(s), Tokens.unwrap(b)));
}
function omul(TokensXBasisPointsXShares r, Shares s, TokensXBasisPoints b)
internal
pure
returns (TokensXBasisPointsXShares)
{
return cast(cast(r).omul(Shares.unwrap(s), TokensXBasisPoints.unwrap(b)));
}
function omul(TokensXBasisPointsXShares r, TokensXBasisPoints b, Shares s)
internal
pure
returns (TokensXBasisPointsXShares)
{
return cast(cast(r).omul(TokensXBasisPoints.unwrap(b), Shares.unwrap(s)));
}
function imul(TokensXBasisPointsXShares r, Shares s) internal pure returns (TokensXBasisPointsXShares2) {
return cast2(cast(r).imul(Shares.unwrap(s)));
}
function div(TokensXBasisPointsXShares n, SharesXBasisPoints d) internal pure returns (Tokens) {
return Tokens.wrap(cast(n).div(SharesXBasisPoints.unwrap(d)));
}
function div(TokensXBasisPointsXShares n, TokensXBasisPoints d) internal pure returns (Shares) {
return Shares.wrap(cast(n).div(TokensXBasisPoints.unwrap(d)));
}
}
using TokensXBasisPointsXSharesArithmetic for TokensXBasisPointsXShares global;
library SharesToTokensProportional {
function toTokens(SharesXBasisPoints sharesBp, Tokens totalSupply, Shares totalShares)
internal
pure
returns (Tokens)
{
return tmp().omul(sharesBp, totalSupply).div(scale(totalShares, BASIS));
}
}
文件 40 的 46:TokensXBasisPointsXShares2.sol
pragma solidity ^0.8.28;
import {Shares} from "./Shares.sol";
import {TokensXBasisPointsXShares, cast as cast1} from "./TokensXBasisPointsXShares.sol";
import {uint512} from "../lib/512Math.sol";
type TokensXBasisPointsXShares2 is bytes32;
function cast(TokensXBasisPointsXShares2 x) pure returns (uint512) {
return uint512.wrap(TokensXBasisPointsXShares2.unwrap(x));
}
function cast(uint512 x) pure returns (TokensXBasisPointsXShares2) {
return TokensXBasisPointsXShares2.wrap(uint512.unwrap(x));
}
library TokensXBasisPointsXShares2Arithmetic {
function div(TokensXBasisPointsXShares2 n, TokensXBasisPointsXShares d) internal pure returns (Shares) {
return Shares.wrap(cast(n).div(cast1(d)));
}
}
using TokensXBasisPointsXShares2Arithmetic for TokensXBasisPointsXShares2 global;
文件 41 的 46:TokensXShares.sol
pragma solidity ^0.8.28;
import {Shares} from "./Shares.sol";
import {Tokens} from "./Tokens.sol";
import {BasisPoints} from "./BasisPoints.sol";
import {SharesXBasisPoints} from "./SharesXBasisPoints.sol";
import {TokensXShares2, cast2} from "./TokensXShares2.sol";
import {TokensXBasisPointsXShares, cast as cast3} from "./TokensXBasisPointsXShares.sol";
import {TokensXBasisPointsXShares2, cast as cast4} from "./TokensXBasisPointsXShares2.sol";
import {uint512, tmp as baseTmp, alloc as baseAlloc} from "../lib/512Math.sol";
type TokensXShares is bytes32;
function cast(TokensXShares x) pure returns (uint512) {
return uint512.wrap(TokensXShares.unwrap(x));
}
function cast(uint512 x) pure returns (TokensXShares) {
return TokensXShares.wrap(uint512.unwrap(x));
}
function alloc() pure returns (TokensXShares) {
return cast(baseAlloc());
}
function tmp() pure returns (TokensXShares) {
return cast(baseTmp());
}
library TokensXSharesArithmetic {
function iadd(TokensXShares r, TokensXShares x) internal pure returns (TokensXShares) {
return cast(cast(r).iadd(cast(x)));
}
function isub(TokensXShares r, TokensXShares x) internal pure returns (TokensXShares) {
return cast(cast(r).isub(cast(x)));
}
function omul(TokensXShares r, Tokens b, Shares s) internal pure returns (TokensXShares) {
return cast(cast(r).omul(Tokens.unwrap(b), Shares.unwrap(s)));
}
function omul(TokensXShares r, Shares s, Tokens b) internal pure returns (TokensXShares) {
return cast(cast(r).omul(Shares.unwrap(s), Tokens.unwrap(b)));
}
function imul(TokensXShares r, Shares s) internal pure returns (TokensXShares2) {
return cast2(cast(r).imul(Shares.unwrap(s)));
}
function imul(TokensXShares r, BasisPoints bp) internal pure returns (TokensXBasisPointsXShares) {
return cast3(cast(r).imul(BasisPoints.unwrap(bp)));
}
function imul(TokensXShares r, SharesXBasisPoints s) internal pure returns (TokensXBasisPointsXShares2) {
return cast4(cast(r).imul(SharesXBasisPoints.unwrap(s)));
}
function div(TokensXShares n, Tokens d) internal pure returns (Shares) {
return Shares.wrap(cast(n).div(Tokens.unwrap(d)));
}
function div(TokensXShares n, Shares d) internal pure returns (Tokens) {
return Tokens.wrap(cast(n).div(Shares.unwrap(d)));
}
function divMulti(TokensXShares n0, TokensXShares n1, Tokens d) internal pure returns (Shares, Shares) {
(uint256 r0, uint256 r1) = cast(n0).divMulti(cast(n1), Tokens.unwrap(d));
return (Shares.wrap(r0), Shares.wrap(r1));
}
function divMulti(TokensXShares n0, TokensXShares n1, Shares d) internal pure returns (Tokens, Tokens) {
(uint256 r0, uint256 r1) = cast(n0).divMulti(cast(n1), Shares.unwrap(d));
return (Tokens.wrap(r0), Tokens.wrap(r1));
}
}
using TokensXSharesArithmetic for TokensXShares global;
function __eq(TokensXShares a, TokensXShares b) pure returns (bool) {
return cast(a) == cast(b);
}
function __lt(TokensXShares a, TokensXShares b) pure returns (bool) {
return cast(a) < cast(b);
}
function __gt(TokensXShares a, TokensXShares b) pure returns (bool) {
return cast(a) > cast(b);
}
function __ne(TokensXShares a, TokensXShares b) pure returns (bool) {
return cast(a) != cast(b);
}
function __le(TokensXShares a, TokensXShares b) pure returns (bool) {
return cast(a) <= cast(b);
}
function __ge(TokensXShares a, TokensXShares b) pure returns (bool) {
return cast(a) >= cast(b);
}
using {__eq as ==, __lt as <, __gt as >, __ne as !=, __le as <=, __ge as >=} for TokensXShares global;
library SharesToTokens {
function toTokens(Shares shares, Tokens totalSupply, Shares totalShares) internal pure returns (Tokens) {
return tmp().omul(shares, totalSupply).div(totalShares);
}
modifier freeMemory() {
uint256 freePtr;
assembly ("memory-safe") {
freePtr := mload(0x40)
}
_;
assembly ("memory-safe") {
mstore(0x40, freePtr)
}
}
function toTokensMulti(Shares shares0, Shares shares1, Tokens totalSupply, Shares totalShares)
internal
pure
freeMemory
returns (Tokens r0, Tokens r1)
{
TokensXShares n0 = alloc().omul(shares0, totalSupply);
TokensXShares n1 = tmp().omul(shares1, totalSupply);
(r0, r1) = n0.divMulti(n1, totalShares);
}
}
文件 42 的 46:TokensXShares2.sol
pragma solidity ^0.8.28;
import {Shares} from "./Shares.sol";
import {TokensXShares, cast} from "./TokensXShares.sol";
import {uint512} from "../lib/512Math.sol";
type TokensXShares2 is bytes32;
function cast(TokensXShares2 x) pure returns (uint512) {
return uint512.wrap(TokensXShares2.unwrap(x));
}
function cast2(uint512 x) pure returns (TokensXShares2) {
return TokensXShares2.wrap(uint512.unwrap(x));
}
library TokensXShares2Arithmetic {
function div(TokensXShares2 n, TokensXShares d) internal pure returns (Shares) {
return Shares.wrap(cast(n).div(cast(d)));
}
}
using TokensXShares2Arithmetic for TokensXShares2 global;
function __eq(TokensXShares2 a, TokensXShares2 b) pure returns (bool) {
return cast(a) == cast(b);
}
function __lt(TokensXShares2 a, TokensXShares2 b) pure returns (bool) {
return cast(a) < cast(b);
}
function __gt(TokensXShares2 a, TokensXShares2 b) pure returns (bool) {
return cast(a) > cast(b);
}
function __ne(TokensXShares2 a, TokensXShares2 b) pure returns (bool) {
return cast(a) != cast(b);
}
function __le(TokensXShares2 a, TokensXShares2 b) pure returns (bool) {
return cast(a) <= cast(b);
}
function __ge(TokensXShares2 a, TokensXShares2 b) pure returns (bool) {
return cast(a) >= cast(b);
}
using {__eq as ==, __lt as <, __gt as >, __ne as !=, __le as <=, __ge as >=} for TokensXShares2 global;
文件 43 的 46:TransientStorageLayout.sol
pragma solidity ^0.8.28;
import {CrazyBalance} from "../types/CrazyBalance.sol";
abstract contract TransientStorageLayout {
function _setTemporaryAllowance(address owner, address spender, CrazyBalance amount) internal {
assembly ("memory-safe") {
mstore(0x14, spender)
mstore(0x00, owner)
tstore(keccak256(0x0c, 0x28), amount)
}
}
function _getTemporaryAllowance(address owner, address spender) internal view returns (CrazyBalance r) {
assembly ("memory-safe") {
mstore(0x14, spender)
mstore(0x00, owner)
r := tload(keccak256(0x0c, 0x28))
}
}
}
文件 44 的 46:UnsafeMath.sol
pragma solidity ^0.8.28;
library UnsafeMath {
function unsafeInc(uint256 x) internal pure returns (uint256) {
unchecked {
return x + 1;
}
}
function unsafeInc(uint256 x, bool b) internal pure returns (uint256) {
assembly ("memory-safe") {
x := add(x, b)
}
return x;
}
function unsafeInc(int256 x) internal pure returns (int256) {
unchecked {
return x + 1;
}
}
function unsafeInc(int256 x, bool b) internal pure returns (int256) {
assembly ("memory-safe") {
x := add(x, b)
}
return x;
}
function unsafeDec(uint256 x) internal pure returns (uint256) {
unchecked {
return x - 1;
}
}
function unsafeDec(uint256 x, bool b) internal pure returns (uint256) {
assembly ("memory-safe") {
x := sub(x, b)
}
return x;
}
function unsafeDec(int256 x) internal pure returns (int256) {
unchecked {
return x - 1;
}
}
function unsafeDec(int256 x, bool b) internal pure returns (int256) {
assembly ("memory-safe") {
x := sub(x, b)
}
return x;
}
function unsafeNeg(int256 x) internal pure returns (int256) {
unchecked {
return -x;
}
}
function unsafeDiv(uint256 numerator, uint256 denominator) internal pure returns (uint256 quotient) {
assembly ("memory-safe") {
quotient := div(numerator, denominator)
}
}
function unsafeDiv(int256 numerator, int256 denominator) internal pure returns (int256 quotient) {
assembly ("memory-safe") {
quotient := sdiv(numerator, denominator)
}
}
function unsafeMod(uint256 numerator, uint256 denominator) internal pure returns (uint256 remainder) {
assembly ("memory-safe") {
remainder := mod(numerator, denominator)
}
}
function unsafeMod(int256 numerator, int256 denominator) internal pure returns (int256 remainder) {
assembly ("memory-safe") {
remainder := smod(numerator, denominator)
}
}
function unsafeMulMod(uint256 a, uint256 b, uint256 m) internal pure returns (uint256 r) {
assembly ("memory-safe") {
r := mulmod(a, b, m)
}
}
function unsafeAddMod(uint256 a, uint256 b, uint256 m) internal pure returns (uint256 r) {
assembly ("memory-safe") {
r := addmod(a, b, m)
}
}
function unsafeDivUp(uint256 n, uint256 d) internal pure returns (uint256 r) {
assembly ("memory-safe") {
r := add(gt(mod(n, d), 0x00), div(n, d))
}
}
}
文件 45 的 46:Votes.sol
pragma solidity ^0.8.28;
import {Settings} from "../core/Settings.sol";
import {Shares} from "./Shares.sol";
type Votes is uint256;
Votes constant ZERO = Votes.wrap(0);
function toVotes(Shares s) pure returns (Votes) {
return Votes.wrap(Shares.unwrap(s) >> Settings.SHARES_TO_VOTES_SHIFT);
}
function toExternal(Votes v) pure returns (uint256) {
return Votes.unwrap(v);
}
using {toExternal} for Votes global;
function __add(Votes a, Votes b) pure returns (Votes) {
unchecked {
return Votes.wrap(Votes.unwrap(a) + Votes.unwrap(b));
}
}
function __sub(Votes a, Votes b) pure returns (Votes) {
unchecked {
return Votes.wrap(Votes.unwrap(a) - Votes.unwrap(b));
}
}
function __eq(Votes a, Votes b) pure returns (bool) {
return Votes.unwrap(a) == Votes.unwrap(b);
}
function __lt(Votes a, Votes b) pure returns (bool) {
return Votes.unwrap(a) < Votes.unwrap(b);
}
function __gt(Votes a, Votes b) pure returns (bool) {
return Votes.unwrap(a) > Votes.unwrap(b);
}
function __ne(Votes a, Votes b) pure returns (bool) {
return Votes.unwrap(a) != Votes.unwrap(b);
}
function __le(Votes a, Votes b) pure returns (bool) {
return Votes.unwrap(a) <= Votes.unwrap(b);
}
function __ge(Votes a, Votes b) pure returns (bool) {
return Votes.unwrap(a) >= Votes.unwrap(b);
}
using {
__add as +, __sub as -, __eq as ==, __lt as <, __gt as >, __ne as !=, __le as <=, __ge as >=
} for Votes global;
文件 46 的 46:WhaleLimit.sol
pragma solidity ^0.8.28;
import {Shares, ONE as ONE_SHARE, ternary, maybeSwap} from "../types/Shares.sol";
import {Settings} from "./Settings.sol";
function whaleLimit(Shares shares, Shares totalShares) pure returns (Shares limit, Shares newTotalShares) {
Shares uninvolved = totalShares - shares;
limit = uninvolved.div(Settings.ANTI_WHALE_DIVISOR_MINUS_ONE) - ONE_SHARE;
newTotalShares = uninvolved + limit;
}
function applyWhaleLimit(Shares shares, Shares totalShares) pure returns (Shares, Shares) {
(Shares limit, Shares newTotalShares) = whaleLimit(shares, totalShares);
bool condition = shares > limit;
return (ternary(condition, limit, shares), ternary(condition, newTotalShares, totalShares));
}
function applyWhaleLimit(Shares shares0, Shares shares1, Shares totalShares) pure returns (Shares, Shares, Shares) {
bool condition = shares0 > shares1;
(Shares sharesLo, Shares sharesHi) = maybeSwap(condition, shares0, shares1);
(Shares firstLimit, Shares newTotalShares) = whaleLimit(sharesHi, totalShares);
if (sharesHi > firstLimit) {
Shares uninvolved = totalShares - sharesHi - sharesLo;
Shares secondLimit = uninvolved.div(Settings.ANTI_WHALE_DIVISOR_MINUS_TWO) - ONE_SHARE;
if (sharesLo > secondLimit) {
totalShares = uninvolved + secondLimit.mul(2);
sharesHi = secondLimit;
sharesLo = secondLimit;
} else {
totalShares = newTotalShares;
sharesHi = firstLimit;
}
}
(shares0, shares1) = maybeSwap(condition, sharesLo, sharesHi);
return (shares0, shares1, totalShares);
}
{
"compilationTarget": {
"src/FU.sol": "FU"
},
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"remappings": [
":@forge-std/=lib/forge-std/src/"
],
"viaIR": true
}
[{"inputs":[{"internalType":"bytes20","name":"gitCommit","type":"bytes20"},{"internalType":"string","name":"image_","type":"string"},{"internalType":"address[]","name":"initialHolders","type":"address[]"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"ERC2612ExpiredSignature","type":"error"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC2612InvalidSigner","type":"error"},{"inputs":[{"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"ERC5805ExpiredSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"ERC5805InvalidNonce","type":"error"},{"inputs":[],"name":"ERC5805InvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"},{"internalType":"uint256","name":"clock","type":"uint256"}],"name":"ERC5805TimepointNotPast","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes20","name":"gitCommit","type":"bytes20"}],"name":"GitCommit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"CLOCK_MODE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"clock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"delegatee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deliver","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deliverFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastTotalVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"timepoint","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"image","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"r","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"temporaryApprove","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"potentialWhale","type":"address"}],"name":"whaleLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]