编译器
0.8.17+commit.8df45f5f
文件 1 的 39:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 39:ArrayLib.sol
pragma solidity >=0.8.0;
library ArrayLib {
function sum(uint256[] memory input) internal pure returns (uint256) {
uint256 value = 0;
for (uint256 i = 0; i < input.length; ) {
value += input[i];
unchecked {
i++;
}
}
return value;
}
function contains(address[] memory array, address element) internal pure returns (bool) {
uint256 length = array.length;
for (uint256 i = 0; i < length; ) {
if (array[i] == element) return true;
unchecked {
i++;
}
}
return false;
}
function append(address[] memory inp, address element)
internal
pure
returns (address[] memory out)
{
uint256 length = inp.length;
out = new address[](length + 1);
for (uint256 i = 0; i < length; ) {
out[i] = inp[i];
unchecked {
i++;
}
}
out[length] = element;
}
}
文件 3 的 39:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 4 的 39:Counters.sol
pragma solidity ^0.8.0;
library Counters {
struct Counter {
uint256 _value;
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
unchecked {
counter._value += 1;
}
}
function decrement(Counter storage counter) internal {
uint256 value = counter._value;
require(value > 0, "Counter: decrement overflow");
unchecked {
counter._value = value - 1;
}
}
function reset(Counter storage counter) internal {
counter._value = 0;
}
}
文件 5 的 39:ECDSA.sol
pragma solidity ^0.8.0;
import "../Strings.sol";
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return;
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
文件 6 的 39:ERC20.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
文件 7 的 39:Errors.sol
pragma solidity 0.8.17;
library Errors {
error BulkInsufficientSyForTrade(uint256 currentAmount, uint256 requiredAmount);
error BulkInsufficientTokenForTrade(uint256 currentAmount, uint256 requiredAmount);
error BulkInSufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut);
error BulkInSufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut);
error BulkInsufficientSyReceived(uint256 actualBalance, uint256 requiredBalance);
error BulkNotMaintainer();
error BulkNotAdmin();
error BulkSellerAlreadyExisted(address token, address SY, address bulk);
error BulkSellerInvalidToken(address token, address SY);
error BulkBadRateTokenToSy(uint256 actualRate, uint256 currentRate, uint256 eps);
error BulkBadRateSyToToken(uint256 actualRate, uint256 currentRate, uint256 eps);
error ApproxFail();
error ApproxParamsInvalid(uint256 guessMin, uint256 guessMax, uint256 eps);
error ApproxBinarySearchInputInvalid(
uint256 approxGuessMin,
uint256 approxGuessMax,
uint256 minGuessMin,
uint256 maxGuessMax
);
error MarketExpired();
error MarketZeroAmountsInput();
error MarketZeroAmountsOutput();
error MarketZeroLnImpliedRate();
error MarketInsufficientPtForTrade(int256 currentAmount, int256 requiredAmount);
error MarketInsufficientPtReceived(uint256 actualBalance, uint256 requiredBalance);
error MarketInsufficientSyReceived(uint256 actualBalance, uint256 requiredBalance);
error MarketZeroTotalPtOrTotalAsset(int256 totalPt, int256 totalAsset);
error MarketExchangeRateBelowOne(int256 exchangeRate);
error MarketProportionMustNotEqualOne();
error MarketRateScalarBelowZero(int256 rateScalar);
error MarketScalarRootBelowZero(int256 scalarRoot);
error MarketProportionTooHigh(int256 proportion, int256 maxProportion);
error OracleUninitialized();
error OracleTargetTooOld(uint32 target, uint32 oldest);
error OracleZeroCardinality();
error MarketFactoryExpiredPt();
error MarketFactoryInvalidPt();
error MarketFactoryMarketExists();
error MarketFactoryLnFeeRateRootTooHigh(uint80 lnFeeRateRoot, uint256 maxLnFeeRateRoot);
error MarketFactoryReserveFeePercentTooHigh(
uint8 reserveFeePercent,
uint8 maxReserveFeePercent
);
error MarketFactoryZeroTreasury();
error MarketFactoryInitialAnchorTooLow(int256 initialAnchor, int256 minInitialAnchor);
error RouterInsufficientLpOut(uint256 actualLpOut, uint256 requiredLpOut);
error RouterInsufficientSyOut(uint256 actualSyOut, uint256 requiredSyOut);
error RouterInsufficientPtOut(uint256 actualPtOut, uint256 requiredPtOut);
error RouterInsufficientYtOut(uint256 actualYtOut, uint256 requiredYtOut);
error RouterInsufficientPYOut(uint256 actualPYOut, uint256 requiredPYOut);
error RouterInsufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut);
error RouterExceededLimitSyIn(uint256 actualSyIn, uint256 limitSyIn);
error RouterExceededLimitPtIn(uint256 actualPtIn, uint256 limitPtIn);
error RouterExceededLimitYtIn(uint256 actualYtIn, uint256 limitYtIn);
error RouterInsufficientSyRepay(uint256 actualSyRepay, uint256 requiredSyRepay);
error RouterInsufficientPtRepay(uint256 actualPtRepay, uint256 requiredPtRepay);
error RouterNotAllSyUsed(uint256 netSyDesired, uint256 netSyUsed);
error RouterTimeRangeZero();
error RouterCallbackNotPendleMarket(address caller);
error RouterInvalidAction(bytes4 selector);
error RouterKyberSwapDataZero();
error YCExpired();
error YCNotExpired();
error YieldContractInsufficientSy(uint256 actualSy, uint256 requiredSy);
error YCNothingToRedeem();
error YCPostExpiryDataNotSet();
error YCNoFloatingSy();
error YCFactoryInvalidExpiry();
error YCFactoryYieldContractExisted();
error YCFactoryZeroExpiryDivisor();
error YCFactoryZeroTreasury();
error YCFactoryInterestFeeRateTooHigh(uint256 interestFeeRate, uint256 maxInterestFeeRate);
error YCFactoryRewardFeeRateTooHigh(uint256 newRewardFeeRate, uint256 maxRewardFeeRate);
error SYInvalidTokenIn(address token);
error SYInvalidTokenOut(address token);
error SYZeroDeposit();
error SYZeroRedeem();
error SYInsufficientSharesOut(uint256 actualSharesOut, uint256 requiredSharesOut);
error SYInsufficientTokenOut(uint256 actualTokenOut, uint256 requiredTokenOut);
error SYQiTokenMintFailed(uint256 errCode);
error SYQiTokenRedeemFailed(uint256 errCode);
error SYQiTokenRedeemRewardsFailed(uint256 rewardAccruedType0, uint256 rewardAccruedType1);
error SYQiTokenBorrowRateTooHigh(uint256 borrowRate, uint256 borrowRateMax);
error SYCurveInvalidPid();
error SYCurve3crvPoolNotFound();
error VCInactivePool(address pool);
error VCPoolAlreadyActive(address pool);
error VCZeroVePendle(address user);
error VCExceededMaxWeight(uint256 totalWeight, uint256 maxWeight);
error VCEpochNotFinalized(uint256 wTime);
error VCPoolAlreadyAddAndRemoved(address pool);
error VEInvalidNewExpiry(uint256 newExpiry);
error VEExceededMaxLockTime();
error VEInsufficientLockTime();
error VENotAllowedReduceExpiry();
error VEZeroAmountLocked();
error VEPositionNotExpired();
error VEZeroPosition();
error VEZeroSlope(uint128 bias, uint128 slope);
error VEReceiveOldSupply(uint256 msgTime);
error GCNotPendleMarket(address caller);
error GCNotVotingController(address caller);
error InvalidWTime(uint256 wTime);
error ExpiryInThePast(uint256 expiry);
error ChainNotSupported(uint256 chainId);
error FDCantFundFutureEpoch();
error FDFactoryDistributorAlreadyExisted(address pool, address distributor);
error MsgNotFromSendEndpoint(uint16 srcChainId, bytes path);
error MsgNotFromReceiveEndpoint(address sender);
error InsufficientFeeToSendMsg(uint256 currentFee, uint256 requiredFee);
error ApproxDstExecutionGasNotSet();
error InvalidRetryData();
error ArrayLengthMismatch();
error ArrayEmpty();
error ArrayOutOfBounds();
error ZeroAddress();
error OnlyLayerZeroEndpoint();
error OnlyYT();
error OnlyYCFactory();
error OnlyWhitelisted();
}
文件 8 的 39:IERC20.sol
pragma solidity ^0.8.0;
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);
}
文件 9 的 39:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 10 的 39:IPGauge.sol
pragma solidity 0.8.17;
interface IPGauge {
function totalActiveSupply() external view returns (uint256);
function activeBalance(address user) external view returns (uint256);
}
文件 11 的 39:IPGaugeController.sol
pragma solidity 0.8.17;
interface IPGaugeController {
event MarketClaimReward(address indexed market, uint256 amount);
event ReceiveVotingResults(uint128 indexed wTime, address[] markets, uint256[] pendleAmounts);
event UpdateMarketReward(
address indexed market,
uint256 pendlePerSec,
uint256 incentiveEndsAt
);
function fundPendle(uint256 amount) external;
function withdrawPendle(uint256 amount) external;
function pendle() external returns (address);
function redeemMarketReward() external;
function rewardData(address pool)
external
view
returns (
uint128 pendlePerSec,
uint128,
uint128,
uint128
);
}
文件 12 的 39:IPInterestManagerYT.sol
pragma solidity 0.8.17;
interface IPInterestManagerYT {
function userInterest(address user)
external
view
returns (uint128 lastPYIndex, uint128 accruedInterest);
}
文件 13 的 39:IPMarket.sol
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "./IPPrincipalToken.sol";
import "./IPYieldToken.sol";
import "./IStandardizedYield.sol";
import "./IPGauge.sol";
import "../core/Market/MarketMathCore.sol";
interface IPMarket is IERC20Metadata, IPGauge {
event Mint(
address indexed receiver,
uint256 netLpMinted,
uint256 netSyUsed,
uint256 netPtUsed
);
event Burn(
address indexed receiverSy,
address indexed receiverPt,
uint256 netLpBurned,
uint256 netSyOut,
uint256 netPtOut
);
event Swap(
address indexed caller,
address indexed receiver,
int256 netPtOut,
int256 netSyOut,
uint256 netSyFee,
uint256 netSyToReserve
);
event UpdateImpliedRate(uint256 indexed timestamp, uint256 lnLastImpliedRate);
event IncreaseObservationCardinalityNext(
uint16 observationCardinalityNextOld,
uint16 observationCardinalityNextNew
);
function mint(
address receiver,
uint256 netSyDesired,
uint256 netPtDesired
)
external
returns (
uint256 netLpOut,
uint256 netSyUsed,
uint256 netPtUsed
);
function burn(
address receiverSy,
address receiverPt,
uint256 netLpToBurn
) external returns (uint256 netSyOut, uint256 netPtOut);
function swapExactPtForSy(
address receiver,
uint256 exactPtIn,
bytes calldata data
) external returns (uint256 netSyOut, uint256 netSyFee);
function swapSyForExactPt(
address receiver,
uint256 exactPtOut,
bytes calldata data
) external returns (uint256 netSyIn, uint256 netSyFee);
function redeemRewards(address user) external returns (uint256[] memory);
function readState(address router) external view returns (MarketState memory market);
function observe(uint32[] memory secondsAgos)
external
view
returns (uint216[] memory lnImpliedRateCumulative);
function increaseObservationsCardinalityNext(uint16 cardinalityNext) external;
function readTokens()
external
view
returns (
IStandardizedYield _SY,
IPPrincipalToken _PT,
IPYieldToken _YT
);
function getRewardTokens() external view returns (address[] memory);
function isExpired() external view returns (bool);
function expiry() external view returns (uint256);
}
文件 14 的 39:IPMarketFactory.sol
pragma solidity 0.8.17;
interface IPMarketFactory {
struct FeeConfig {
uint80 lnFeeRateRoot;
uint8 reserveFeePercent;
bool active;
}
event NewMarketConfig(
address indexed treasury,
uint80 defaultLnFeeRateRoot,
uint8 reserveFeePercent
);
event SetOverriddenFee(address indexed router, uint80 lnFeeRateRoot, uint8 reserveFeePercent);
event UnsetOverriddenFee(address indexed router);
event CreateNewMarket(
address indexed market,
address indexed PT,
int256 scalarRoot,
int256 initialAnchor
);
function isValidMarket(address market) external view returns (bool);
function getMarketConfig(address router)
external
view
returns (
address treasury,
uint80 lnFeeRateRoot,
uint8 reserveFeePercent
);
}
文件 15 的 39:IPMarketSwapCallback.sol
pragma solidity 0.8.17;
interface IPMarketSwapCallback {
function swapCallback(
int256 ptToAccount,
int256 syToAccount,
bytes calldata data
) external;
}
文件 16 的 39:IPPrincipalToken.sol
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
interface IPPrincipalToken is IERC20Metadata {
function burnByYT(address user, uint256 amount) external;
function mintByYT(address user, uint256 amount) external;
function initialize(address _YT) external;
function SY() external view returns (address);
function YT() external view returns (address);
function factory() external view returns (address);
function expiry() external view returns (uint256);
function isExpired() external view returns (bool);
}
文件 17 的 39:IPVeToken.sol
pragma solidity 0.8.17;
interface IPVeToken {
function balanceOf(address user) external view returns (uint128);
function positionData(address user) external view returns (uint128 amount, uint128 expiry);
function totalSupplyStored() external view returns (uint128);
function totalSupplyCurrent() external returns (uint128);
function totalSupplyAndBalanceCurrent(address user) external returns (uint128, uint128);
}
文件 18 的 39:IPYieldToken.sol
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "./IRewardManager.sol";
import "./IPInterestManagerYT.sol";
interface IPYieldToken is IERC20Metadata, IRewardManager, IPInterestManagerYT {
event NewInterestIndex(uint256 indexed newIndex);
event Mint(
address indexed caller,
address indexed receiverPT,
address indexed receiverYT,
uint256 amountSyToMint,
uint256 amountPYOut
);
event Burn(
address indexed caller,
address indexed receiver,
uint256 amountPYToRedeem,
uint256 amountSyOut
);
event RedeemRewards(address indexed user, uint256[] amountRewardsOut);
event RedeemInterest(address indexed user, uint256 interestOut);
event WithdrawFeeToTreasury(uint256[] amountRewardsOut, uint256 syOut);
function mintPY(address receiverPT, address receiverYT) external returns (uint256 amountPYOut);
function redeemPY(address receiver) external returns (uint256 amountSyOut);
function redeemPYMulti(address[] calldata receivers, uint256[] calldata amountPYToRedeems)
external
returns (uint256[] memory amountSyOuts);
function redeemDueInterestAndRewards(
address user,
bool redeemInterest,
bool redeemRewards
) external returns (uint256 interestOut, uint256[] memory rewardsOut);
function rewardIndexesCurrent() external returns (uint256[] memory);
function pyIndexCurrent() external returns (uint256);
function pyIndexStored() external view returns (uint256);
function getRewardTokens() external view returns (address[] memory);
function SY() external view returns (address);
function PT() external view returns (address);
function factory() external view returns (address);
function expiry() external view returns (uint256);
function isExpired() external view returns (bool);
function doCacheIndexSameBlock() external view returns (bool);
}
文件 19 的 39:IRewardManager.sol
pragma solidity 0.8.17;
interface IRewardManager {
function userReward(address token, address user)
external
view
returns (uint128 index, uint128 accrued);
}
文件 20 的 39:IStandardizedYield.sol
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
interface IStandardizedYield is IERC20Metadata {
event Deposit(
address indexed caller,
address indexed receiver,
address indexed tokenIn,
uint256 amountDeposited,
uint256 amountSyOut
);
event Redeem(
address indexed caller,
address indexed receiver,
address indexed tokenOut,
uint256 amountSyToRedeem,
uint256 amountTokenOut
);
enum AssetType {
TOKEN,
LIQUIDITY
}
event ClaimRewards(address indexed user, address[] rewardTokens, uint256[] rewardAmounts);
function deposit(
address receiver,
address tokenIn,
uint256 amountTokenToDeposit,
uint256 minSharesOut
) external payable returns (uint256 amountSharesOut);
function redeem(
address receiver,
uint256 amountSharesToRedeem,
address tokenOut,
uint256 minTokenOut,
bool burnFromInternalBalance
) external returns (uint256 amountTokenOut);
function exchangeRate() external view returns (uint256 res);
function claimRewards(address user) external returns (uint256[] memory rewardAmounts);
function accruedRewards(address user) external view returns (uint256[] memory rewardAmounts);
function rewardIndexesCurrent() external returns (uint256[] memory indexes);
function rewardIndexesStored() external view returns (uint256[] memory indexes);
function getRewardTokens() external view returns (address[] memory);
function yieldToken() external view returns (address);
function getTokensIn() external view returns (address[] memory res);
function getTokensOut() external view returns (address[] memory res);
function isValidTokenIn(address token) external view returns (bool);
function isValidTokenOut(address token) external view returns (bool);
function previewDeposit(address tokenIn, uint256 amountTokenToDeposit)
external
view
returns (uint256 amountSharesOut);
function previewRedeem(address tokenOut, uint256 amountSharesToRedeem)
external
view
returns (uint256 amountTokenOut);
function assetInfo()
external
view
returns (
AssetType assetType,
address assetAddress,
uint8 assetDecimals
);
}
文件 21 的 39:LogExpMath.sol
pragma solidity 0.8.17;
library LogExpMath {
int256 constant ONE_18 = 1e18;
int256 constant ONE_20 = 1e20;
int256 constant ONE_36 = 1e36;
int256 constant MAX_NATURAL_EXPONENT = 130e18;
int256 constant MIN_NATURAL_EXPONENT = -41e18;
int256 constant LN_36_LOWER_BOUND = ONE_18 - 1e17;
int256 constant LN_36_UPPER_BOUND = ONE_18 + 1e17;
uint256 constant MILD_EXPONENT_BOUND = 2**254 / uint256(ONE_20);
int256 constant x0 = 128000000000000000000;
int256 constant a0 = 38877084059945950922200000000000000000000000000000000000;
int256 constant x1 = 64000000000000000000;
int256 constant a1 = 6235149080811616882910000000;
int256 constant x2 = 3200000000000000000000;
int256 constant a2 = 7896296018268069516100000000000000;
int256 constant x3 = 1600000000000000000000;
int256 constant a3 = 888611052050787263676000000;
int256 constant x4 = 800000000000000000000;
int256 constant a4 = 298095798704172827474000;
int256 constant x5 = 400000000000000000000;
int256 constant a5 = 5459815003314423907810;
int256 constant x6 = 200000000000000000000;
int256 constant a6 = 738905609893065022723;
int256 constant x7 = 100000000000000000000;
int256 constant a7 = 271828182845904523536;
int256 constant x8 = 50000000000000000000;
int256 constant a8 = 164872127070012814685;
int256 constant x9 = 25000000000000000000;
int256 constant a9 = 128402541668774148407;
int256 constant x10 = 12500000000000000000;
int256 constant a10 = 113314845306682631683;
int256 constant x11 = 6250000000000000000;
int256 constant a11 = 106449445891785942956;
function exp(int256 x) internal pure returns (int256) {
unchecked {
require(x >= MIN_NATURAL_EXPONENT && x <= MAX_NATURAL_EXPONENT, "Invalid exponent");
if (x < 0) {
return ((ONE_18 * ONE_18) / exp(-x));
}
int256 firstAN;
if (x >= x0) {
x -= x0;
firstAN = a0;
} else if (x >= x1) {
x -= x1;
firstAN = a1;
} else {
firstAN = 1;
}
x *= 100;
int256 product = ONE_20;
if (x >= x2) {
x -= x2;
product = (product * a2) / ONE_20;
}
if (x >= x3) {
x -= x3;
product = (product * a3) / ONE_20;
}
if (x >= x4) {
x -= x4;
product = (product * a4) / ONE_20;
}
if (x >= x5) {
x -= x5;
product = (product * a5) / ONE_20;
}
if (x >= x6) {
x -= x6;
product = (product * a6) / ONE_20;
}
if (x >= x7) {
x -= x7;
product = (product * a7) / ONE_20;
}
if (x >= x8) {
x -= x8;
product = (product * a8) / ONE_20;
}
if (x >= x9) {
x -= x9;
product = (product * a9) / ONE_20;
}
int256 seriesSum = ONE_20;
int256 term;
term = x;
seriesSum += term;
term = ((term * x) / ONE_20) / 2;
seriesSum += term;
term = ((term * x) / ONE_20) / 3;
seriesSum += term;
term = ((term * x) / ONE_20) / 4;
seriesSum += term;
term = ((term * x) / ONE_20) / 5;
seriesSum += term;
term = ((term * x) / ONE_20) / 6;
seriesSum += term;
term = ((term * x) / ONE_20) / 7;
seriesSum += term;
term = ((term * x) / ONE_20) / 8;
seriesSum += term;
term = ((term * x) / ONE_20) / 9;
seriesSum += term;
term = ((term * x) / ONE_20) / 10;
seriesSum += term;
term = ((term * x) / ONE_20) / 11;
seriesSum += term;
term = ((term * x) / ONE_20) / 12;
seriesSum += term;
return (((product * seriesSum) / ONE_20) * firstAN) / 100;
}
}
function ln(int256 a) internal pure returns (int256) {
unchecked {
require(a > 0, "out of bounds");
if (LN_36_LOWER_BOUND < a && a < LN_36_UPPER_BOUND) {
return _ln_36(a) / ONE_18;
} else {
return _ln(a);
}
}
}
function pow(uint256 x, uint256 y) internal pure returns (uint256) {
unchecked {
if (y == 0) {
return uint256(ONE_18);
}
if (x == 0) {
return 0;
}
require(x < 2**255, "x out of bounds");
int256 x_int256 = int256(x);
require(y < MILD_EXPONENT_BOUND, "y out of bounds");
int256 y_int256 = int256(y);
int256 logx_times_y;
if (LN_36_LOWER_BOUND < x_int256 && x_int256 < LN_36_UPPER_BOUND) {
int256 ln_36_x = _ln_36(x_int256);
logx_times_y = ((ln_36_x / ONE_18) *
y_int256 +
((ln_36_x % ONE_18) * y_int256) /
ONE_18);
} else {
logx_times_y = _ln(x_int256) * y_int256;
}
logx_times_y /= ONE_18;
require(
MIN_NATURAL_EXPONENT <= logx_times_y && logx_times_y <= MAX_NATURAL_EXPONENT,
"product out of bounds"
);
return uint256(exp(logx_times_y));
}
}
function _ln(int256 a) private pure returns (int256) {
unchecked {
if (a < ONE_18) {
return (-_ln((ONE_18 * ONE_18) / a));
}
int256 sum = 0;
if (a >= a0 * ONE_18) {
a /= a0;
sum += x0;
}
if (a >= a1 * ONE_18) {
a /= a1;
sum += x1;
}
sum *= 100;
a *= 100;
if (a >= a2) {
a = (a * ONE_20) / a2;
sum += x2;
}
if (a >= a3) {
a = (a * ONE_20) / a3;
sum += x3;
}
if (a >= a4) {
a = (a * ONE_20) / a4;
sum += x4;
}
if (a >= a5) {
a = (a * ONE_20) / a5;
sum += x5;
}
if (a >= a6) {
a = (a * ONE_20) / a6;
sum += x6;
}
if (a >= a7) {
a = (a * ONE_20) / a7;
sum += x7;
}
if (a >= a8) {
a = (a * ONE_20) / a8;
sum += x8;
}
if (a >= a9) {
a = (a * ONE_20) / a9;
sum += x9;
}
if (a >= a10) {
a = (a * ONE_20) / a10;
sum += x10;
}
if (a >= a11) {
a = (a * ONE_20) / a11;
sum += x11;
}
int256 z = ((a - ONE_20) * ONE_20) / (a + ONE_20);
int256 z_squared = (z * z) / ONE_20;
int256 num = z;
int256 seriesSum = num;
num = (num * z_squared) / ONE_20;
seriesSum += num / 3;
num = (num * z_squared) / ONE_20;
seriesSum += num / 5;
num = (num * z_squared) / ONE_20;
seriesSum += num / 7;
num = (num * z_squared) / ONE_20;
seriesSum += num / 9;
num = (num * z_squared) / ONE_20;
seriesSum += num / 11;
seriesSum *= 2;
return (sum + seriesSum) / 100;
}
}
function _ln_36(int256 x) private pure returns (int256) {
unchecked {
x *= ONE_18;
int256 z = ((x - ONE_36) * ONE_36) / (x + ONE_36);
int256 z_squared = (z * z) / ONE_36;
int256 num = z;
int256 seriesSum = num;
num = (num * z_squared) / ONE_36;
seriesSum += num / 3;
num = (num * z_squared) / ONE_36;
seriesSum += num / 5;
num = (num * z_squared) / ONE_36;
seriesSum += num / 7;
num = (num * z_squared) / ONE_36;
seriesSum += num / 9;
num = (num * z_squared) / ONE_36;
seriesSum += num / 11;
num = (num * z_squared) / ONE_36;
seriesSum += num / 13;
num = (num * z_squared) / ONE_36;
seriesSum += num / 15;
return seriesSum * 2;
}
}
}
文件 22 的 39:MarketMathCore.sol
pragma solidity 0.8.17;
import "../libraries/math/Math.sol";
import "../libraries/math/LogExpMath.sol";
import "../StandardizedYield/PYIndex.sol";
import "../libraries/MiniHelpers.sol";
import "../libraries/Errors.sol";
struct MarketState {
int256 totalPt;
int256 totalSy;
int256 totalLp;
address treasury;
int256 scalarRoot;
uint256 expiry;
uint256 lnFeeRateRoot;
uint256 reserveFeePercent;
uint256 lastLnImpliedRate;
}
struct MarketPreCompute {
int256 rateScalar;
int256 totalAsset;
int256 rateAnchor;
int256 feeRate;
}
library MarketMathCore {
using Math for uint256;
using Math for int256;
using LogExpMath for int256;
using PYIndexLib for PYIndex;
int256 internal constant MINIMUM_LIQUIDITY = 10**3;
int256 internal constant PERCENTAGE_DECIMALS = 100;
uint256 internal constant DAY = 86400;
uint256 internal constant IMPLIED_RATE_TIME = 365 * DAY;
int256 internal constant MAX_MARKET_PROPORTION = (1e18 * 96) / 100;
using Math for uint256;
using Math for int256;
function addLiquidity(
MarketState memory market,
uint256 syDesired,
uint256 ptDesired,
uint256 blockTime
)
internal
pure
returns (
uint256 lpToReserve,
uint256 lpToAccount,
uint256 syUsed,
uint256 ptUsed
)
{
(
int256 _lpToReserve,
int256 _lpToAccount,
int256 _syUsed,
int256 _ptUsed
) = addLiquidityCore(market, syDesired.Int(), ptDesired.Int(), blockTime);
lpToReserve = _lpToReserve.Uint();
lpToAccount = _lpToAccount.Uint();
syUsed = _syUsed.Uint();
ptUsed = _ptUsed.Uint();
}
function removeLiquidity(MarketState memory market, uint256 lpToRemove)
internal
pure
returns (uint256 netSyToAccount, uint256 netPtToAccount)
{
(int256 _syToAccount, int256 _ptToAccount) = removeLiquidityCore(market, lpToRemove.Int());
netSyToAccount = _syToAccount.Uint();
netPtToAccount = _ptToAccount.Uint();
}
function swapExactPtForSy(
MarketState memory market,
PYIndex index,
uint256 exactPtToMarket,
uint256 blockTime
)
internal
pure
returns (
uint256 netSyToAccount,
uint256 netSyFee,
uint256 netSyToReserve
)
{
(int256 _netSyToAccount, int256 _netSyFee, int256 _netSyToReserve) = executeTradeCore(
market,
index,
exactPtToMarket.neg(),
blockTime
);
netSyToAccount = _netSyToAccount.Uint();
netSyFee = _netSyFee.Uint();
netSyToReserve = _netSyToReserve.Uint();
}
function swapSyForExactPt(
MarketState memory market,
PYIndex index,
uint256 exactPtToAccount,
uint256 blockTime
)
internal
pure
returns (
uint256 netSyToMarket,
uint256 netSyFee,
uint256 netSyToReserve
)
{
(int256 _netSyToAccount, int256 _netSyFee, int256 _netSyToReserve) = executeTradeCore(
market,
index,
exactPtToAccount.Int(),
blockTime
);
netSyToMarket = _netSyToAccount.neg().Uint();
netSyFee = _netSyFee.Uint();
netSyToReserve = _netSyToReserve.Uint();
}
function addLiquidityCore(
MarketState memory market,
int256 syDesired,
int256 ptDesired,
uint256 blockTime
)
internal
pure
returns (
int256 lpToReserve,
int256 lpToAccount,
int256 syUsed,
int256 ptUsed
)
{
if (syDesired == 0 || ptDesired == 0) revert Errors.MarketZeroAmountsInput();
if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();
if (market.totalLp == 0) {
lpToAccount = Math.sqrt((syDesired * ptDesired).Uint()).Int() - MINIMUM_LIQUIDITY;
lpToReserve = MINIMUM_LIQUIDITY;
syUsed = syDesired;
ptUsed = ptDesired;
} else {
int256 netLpByPt = (ptDesired * market.totalLp) / market.totalPt;
int256 netLpBySy = (syDesired * market.totalLp) / market.totalSy;
if (netLpByPt < netLpBySy) {
lpToAccount = netLpByPt;
ptUsed = ptDesired;
syUsed = (market.totalSy * lpToAccount) / market.totalLp;
} else {
lpToAccount = netLpBySy;
syUsed = syDesired;
ptUsed = (market.totalPt * lpToAccount) / market.totalLp;
}
}
if (lpToAccount <= 0) revert Errors.MarketZeroAmountsOutput();
market.totalSy += syUsed;
market.totalPt += ptUsed;
market.totalLp += lpToAccount + lpToReserve;
}
function removeLiquidityCore(MarketState memory market, int256 lpToRemove)
internal
pure
returns (int256 netSyToAccount, int256 netPtToAccount)
{
if (lpToRemove == 0) revert Errors.MarketZeroAmountsInput();
netSyToAccount = (lpToRemove * market.totalSy) / market.totalLp;
netPtToAccount = (lpToRemove * market.totalPt) / market.totalLp;
if (netSyToAccount == 0 && netPtToAccount == 0) revert Errors.MarketZeroAmountsOutput();
market.totalLp = market.totalLp.subNoNeg(lpToRemove);
market.totalPt = market.totalPt.subNoNeg(netPtToAccount);
market.totalSy = market.totalSy.subNoNeg(netSyToAccount);
}
function executeTradeCore(
MarketState memory market,
PYIndex index,
int256 netPtToAccount,
uint256 blockTime
)
internal
pure
returns (
int256 netSyToAccount,
int256 netSyFee,
int256 netSyToReserve
)
{
if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();
if (market.totalPt <= netPtToAccount)
revert Errors.MarketInsufficientPtForTrade(market.totalPt, netPtToAccount);
MarketPreCompute memory comp = getMarketPreCompute(market, index, blockTime);
(netSyToAccount, netSyFee, netSyToReserve) = calcTrade(
market,
comp,
index,
netPtToAccount
);
_setNewMarketStateTrade(
market,
comp,
index,
netPtToAccount,
netSyToAccount,
netSyToReserve,
blockTime
);
}
function getMarketPreCompute(
MarketState memory market,
PYIndex index,
uint256 blockTime
) internal pure returns (MarketPreCompute memory res) {
if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();
uint256 timeToExpiry = market.expiry - blockTime;
res.rateScalar = _getRateScalar(market, timeToExpiry);
res.totalAsset = index.syToAsset(market.totalSy);
if (market.totalPt == 0 || res.totalAsset == 0)
revert Errors.MarketZeroTotalPtOrTotalAsset(market.totalPt, res.totalAsset);
res.rateAnchor = _getRateAnchor(
market.totalPt,
market.lastLnImpliedRate,
res.totalAsset,
res.rateScalar,
timeToExpiry
);
res.feeRate = _getExchangeRateFromImpliedRate(market.lnFeeRateRoot, timeToExpiry);
}
function calcTrade(
MarketState memory market,
MarketPreCompute memory comp,
PYIndex index,
int256 netPtToAccount
)
internal
pure
returns (
int256 netSyToAccount,
int256 netSyFee,
int256 netSyToReserve
)
{
int256 preFeeExchangeRate = _getExchangeRate(
market.totalPt,
comp.totalAsset,
comp.rateScalar,
comp.rateAnchor,
netPtToAccount
);
int256 preFeeAssetToAccount = netPtToAccount.divDown(preFeeExchangeRate).neg();
int256 fee = comp.feeRate;
if (netPtToAccount > 0) {
int256 postFeeExchangeRate = preFeeExchangeRate.divDown(fee);
if (postFeeExchangeRate < Math.IONE)
revert Errors.MarketExchangeRateBelowOne(postFeeExchangeRate);
fee = preFeeAssetToAccount.mulDown(Math.IONE - fee);
} else {
fee = ((preFeeAssetToAccount * (Math.IONE - fee)) / fee).neg();
}
int256 netAssetToReserve = (fee * market.reserveFeePercent.Int()) / PERCENTAGE_DECIMALS;
int256 netAssetToAccount = preFeeAssetToAccount - fee;
netSyToAccount = netAssetToAccount < 0
? index.assetToSyUp(netAssetToAccount)
: index.assetToSy(netAssetToAccount);
netSyFee = index.assetToSy(fee);
netSyToReserve = index.assetToSy(netAssetToReserve);
}
function _setNewMarketStateTrade(
MarketState memory market,
MarketPreCompute memory comp,
PYIndex index,
int256 netPtToAccount,
int256 netSyToAccount,
int256 netSyToReserve,
uint256 blockTime
) internal pure {
uint256 timeToExpiry = market.expiry - blockTime;
market.totalPt = market.totalPt.subNoNeg(netPtToAccount);
market.totalSy = market.totalSy.subNoNeg(netSyToAccount + netSyToReserve);
market.lastLnImpliedRate = _getLnImpliedRate(
market.totalPt,
index.syToAsset(market.totalSy),
comp.rateScalar,
comp.rateAnchor,
timeToExpiry
);
if (market.lastLnImpliedRate == 0) revert Errors.MarketZeroLnImpliedRate();
}
function _getRateAnchor(
int256 totalPt,
uint256 lastLnImpliedRate,
int256 totalAsset,
int256 rateScalar,
uint256 timeToExpiry
) internal pure returns (int256 rateAnchor) {
int256 newExchangeRate = _getExchangeRateFromImpliedRate(lastLnImpliedRate, timeToExpiry);
if (newExchangeRate < Math.IONE) revert Errors.MarketExchangeRateBelowOne(newExchangeRate);
{
int256 proportion = totalPt.divDown(totalPt + totalAsset);
int256 lnProportion = _logProportion(proportion);
rateAnchor = newExchangeRate - lnProportion.divDown(rateScalar);
}
}
function _getLnImpliedRate(
int256 totalPt,
int256 totalAsset,
int256 rateScalar,
int256 rateAnchor,
uint256 timeToExpiry
) internal pure returns (uint256 lnImpliedRate) {
int256 exchangeRate = _getExchangeRate(totalPt, totalAsset, rateScalar, rateAnchor, 0);
uint256 lnRate = exchangeRate.ln().Uint();
lnImpliedRate = (lnRate * IMPLIED_RATE_TIME) / timeToExpiry;
}
function _getExchangeRateFromImpliedRate(uint256 lnImpliedRate, uint256 timeToExpiry)
internal
pure
returns (int256 exchangeRate)
{
uint256 rt = (lnImpliedRate * timeToExpiry) / IMPLIED_RATE_TIME;
exchangeRate = LogExpMath.exp(rt.Int());
}
function _getExchangeRate(
int256 totalPt,
int256 totalAsset,
int256 rateScalar,
int256 rateAnchor,
int256 netPtToAccount
) internal pure returns (int256 exchangeRate) {
int256 numerator = totalPt.subNoNeg(netPtToAccount);
int256 proportion = (numerator.divDown(totalPt + totalAsset));
if (proportion > MAX_MARKET_PROPORTION)
revert Errors.MarketProportionTooHigh(proportion, MAX_MARKET_PROPORTION);
int256 lnProportion = _logProportion(proportion);
exchangeRate = lnProportion.divDown(rateScalar) + rateAnchor;
if (exchangeRate < Math.IONE) revert Errors.MarketExchangeRateBelowOne(exchangeRate);
}
function _logProportion(int256 proportion) internal pure returns (int256 res) {
if (proportion == Math.IONE) revert Errors.MarketProportionMustNotEqualOne();
int256 logitP = proportion.divDown(Math.IONE - proportion);
res = logitP.ln();
}
function _getRateScalar(MarketState memory market, uint256 timeToExpiry)
internal
pure
returns (int256 rateScalar)
{
rateScalar = (market.scalarRoot * IMPLIED_RATE_TIME.Int()) / timeToExpiry.Int();
if (rateScalar <= 0) revert Errors.MarketRateScalarBelowZero(rateScalar);
}
function setInitialLnImpliedRate(
MarketState memory market,
PYIndex index,
int256 initialAnchor,
uint256 blockTime
) internal pure {
if (MiniHelpers.isExpired(market.expiry, blockTime)) revert Errors.MarketExpired();
int256 totalAsset = index.syToAsset(market.totalSy);
uint256 timeToExpiry = market.expiry - blockTime;
int256 rateScalar = _getRateScalar(market, timeToExpiry);
market.lastLnImpliedRate = _getLnImpliedRate(
market.totalPt,
totalAsset,
rateScalar,
initialAnchor,
timeToExpiry
);
}
}
文件 23 的 39:Math.sol
pragma solidity 0.8.17;
library Math {
uint256 internal constant ONE = 1e18;
int256 internal constant IONE = 1e18;
function subMax0(uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
return (a >= b ? a - b : 0);
}
}
function subNoNeg(int256 a, int256 b) internal pure returns (int256) {
require(a >= b, "negative");
return a - b;
}
function mulDown(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 product = a * b;
unchecked {
return product / ONE;
}
}
function mulDown(int256 a, int256 b) internal pure returns (int256) {
int256 product = a * b;
unchecked {
return product / IONE;
}
}
function divDown(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 aInflated = a * ONE;
unchecked {
return aInflated / b;
}
}
function divDown(int256 a, int256 b) internal pure returns (int256) {
int256 aInflated = a * IONE;
unchecked {
return aInflated / b;
}
}
function rawDivUp(uint256 a, uint256 b) internal pure returns (uint256) {
return (a + b - 1) / b;
}
function sqrt(uint256 y) internal pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
function abs(int256 x) internal pure returns (uint256) {
return uint256(x > 0 ? x : -x);
}
function neg(int256 x) internal pure returns (int256) {
return x * (-1);
}
function neg(uint256 x) internal pure returns (int256) {
return Int(x) * (-1);
}
function max(uint256 x, uint256 y) internal pure returns (uint256) {
return (x > y ? x : y);
}
function max(int256 x, int256 y) internal pure returns (int256) {
return (x > y ? x : y);
}
function min(uint256 x, uint256 y) internal pure returns (uint256) {
return (x < y ? x : y);
}
function min(int256 x, int256 y) internal pure returns (int256) {
return (x < y ? x : y);
}
function Int(uint256 x) internal pure returns (int256) {
require(x <= uint256(type(int256).max));
return int256(x);
}
function Int128(int256 x) internal pure returns (int128) {
require(type(int128).min <= x && x <= type(int128).max);
return int128(x);
}
function Int128(uint256 x) internal pure returns (int128) {
return Int128(Int(x));
}
function Uint(int256 x) internal pure returns (uint256) {
require(x >= 0);
return uint256(x);
}
function Uint32(uint256 x) internal pure returns (uint32) {
require(x <= type(uint32).max);
return uint32(x);
}
function Uint112(uint256 x) internal pure returns (uint112) {
require(x <= type(uint112).max);
return uint112(x);
}
function Uint96(uint256 x) internal pure returns (uint96) {
require(x <= type(uint96).max);
return uint96(x);
}
function Uint128(uint256 x) internal pure returns (uint128) {
require(x <= type(uint128).max);
return uint128(x);
}
function isAApproxB(
uint256 a,
uint256 b,
uint256 eps
) internal pure returns (bool) {
return mulDown(b, ONE - eps) <= a && a <= mulDown(b, ONE + eps);
}
function isAGreaterApproxB(
uint256 a,
uint256 b,
uint256 eps
) internal pure returns (bool) {
return a >= b && a <= mulDown(b, ONE + eps);
}
function isASmallerApproxB(
uint256 a,
uint256 b,
uint256 eps
) internal pure returns (bool) {
return a <= b && a >= mulDown(b, ONE - eps);
}
}
文件 24 的 39:MiniHelpers.sol
pragma solidity 0.8.17;
library MiniHelpers {
function isCurrentlyExpired(uint256 expiry) internal view returns (bool) {
return (expiry <= block.timestamp);
}
function isExpired(uint256 expiry, uint256 blockTime) internal pure returns (bool) {
return (expiry <= blockTime);
}
function isTimeInThePast(uint256 timestamp) internal view returns (bool) {
return (timestamp <= block.timestamp);
}
}
文件 25 的 39:OracleLib.sol
pragma solidity 0.8.17;
import "../libraries/Errors.sol";
library OracleLib {
struct Observation {
uint32 blockTimestamp;
uint216 lnImpliedRateCumulative;
bool initialized;
}
function transform(
Observation memory last,
uint32 blockTimestamp,
uint96 lnImpliedRate
) public pure returns (Observation memory) {
return
Observation({
blockTimestamp: blockTimestamp,
lnImpliedRateCumulative: last.lnImpliedRateCumulative +
uint216(lnImpliedRate) *
(blockTimestamp - last.blockTimestamp),
initialized: true
});
}
function initialize(Observation[65535] storage self, uint32 time)
public
returns (uint16 cardinality, uint16 cardinalityNext)
{
self[0] = Observation({
blockTimestamp: time,
lnImpliedRateCumulative: 0,
initialized: true
});
return (1, 1);
}
function write(
Observation[65535] storage self,
uint16 index,
uint32 blockTimestamp,
uint96 lnImpliedRate,
uint16 cardinality,
uint16 cardinalityNext
) public returns (uint16 indexUpdated, uint16 cardinalityUpdated) {
Observation memory last = self[index];
if (last.blockTimestamp == blockTimestamp) return (index, cardinality);
if (cardinalityNext > cardinality && index == (cardinality - 1)) {
cardinalityUpdated = cardinalityNext;
} else {
cardinalityUpdated = cardinality;
}
indexUpdated = (index + 1) % cardinalityUpdated;
self[indexUpdated] = transform(last, blockTimestamp, lnImpliedRate);
}
function grow(
Observation[65535] storage self,
uint16 current,
uint16 next
) public returns (uint16) {
if (current == 0) revert Errors.OracleUninitialized();
if (next <= current) return current;
for (uint16 i = current; i != next; ) {
self[i].blockTimestamp = 1;
unchecked {
++i;
}
}
return next;
}
function binarySearch(
Observation[65535] storage self,
uint32 target,
uint16 index,
uint16 cardinality
) public view returns (Observation memory beforeOrAt, Observation memory atOrAfter) {
uint256 l = (index + 1) % cardinality;
uint256 r = l + cardinality - 1;
uint256 i;
while (true) {
i = (l + r) / 2;
beforeOrAt = self[i % cardinality];
if (!beforeOrAt.initialized) {
l = i + 1;
continue;
}
atOrAfter = self[(i + 1) % cardinality];
bool targetAtOrAfter = beforeOrAt.blockTimestamp <= target;
if (targetAtOrAfter && target <= atOrAfter.blockTimestamp) break;
if (!targetAtOrAfter) r = i - 1;
else l = i + 1;
}
}
function getSurroundingObservations(
Observation[65535] storage self,
uint32 target,
uint96 lnImpliedRate,
uint16 index,
uint16 cardinality
) public view returns (Observation memory beforeOrAt, Observation memory atOrAfter) {
beforeOrAt = self[index];
if (beforeOrAt.blockTimestamp <= target) {
if (beforeOrAt.blockTimestamp == target) {
return (beforeOrAt, atOrAfter);
} else {
return (beforeOrAt, transform(beforeOrAt, target, lnImpliedRate));
}
}
beforeOrAt = self[(index + 1) % cardinality];
if (!beforeOrAt.initialized) beforeOrAt = self[0];
if (target < beforeOrAt.blockTimestamp)
revert Errors.OracleTargetTooOld(target, beforeOrAt.blockTimestamp);
return binarySearch(self, target, index, cardinality);
}
function observeSingle(
Observation[65535] storage self,
uint32 time,
uint32 secondsAgo,
uint96 lnImpliedRate,
uint16 index,
uint16 cardinality
) public view returns (uint216 lnImpliedRateCumulative) {
if (secondsAgo == 0) {
Observation memory last = self[index];
if (last.blockTimestamp != time) {
return transform(last, time, lnImpliedRate).lnImpliedRateCumulative;
}
return last.lnImpliedRateCumulative;
}
uint32 target = time - secondsAgo;
(Observation memory beforeOrAt, Observation memory atOrAfter) = getSurroundingObservations(
self,
target,
lnImpliedRate,
index,
cardinality
);
if (target == beforeOrAt.blockTimestamp) {
return beforeOrAt.lnImpliedRateCumulative;
} else if (target == atOrAfter.blockTimestamp) {
return atOrAfter.lnImpliedRateCumulative;
} else {
return (beforeOrAt.lnImpliedRateCumulative +
uint216(
(uint256(
atOrAfter.lnImpliedRateCumulative - beforeOrAt.lnImpliedRateCumulative
) * (target - beforeOrAt.blockTimestamp)) /
(atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp)
));
}
}
function observe(
Observation[65535] storage self,
uint32 time,
uint32[] memory secondsAgos,
uint96 lnImpliedRate,
uint16 index,
uint16 cardinality
) public view returns (uint216[] memory lnImpliedRateCumulative) {
if (cardinality == 0) revert Errors.OracleZeroCardinality();
lnImpliedRateCumulative = new uint216[](secondsAgos.length);
for (uint256 i = 0; i < lnImpliedRateCumulative.length; ++i) {
lnImpliedRateCumulative[i] = observeSingle(
self,
time,
secondsAgos[i],
lnImpliedRate,
index,
cardinality
);
}
}
}
文件 26 的 39:PYIndex.sol
pragma solidity 0.8.17;
import "../../interfaces/IPYieldToken.sol";
import "../../interfaces/IPPrincipalToken.sol";
import "./SYUtils.sol";
import "../libraries/math/Math.sol";
type PYIndex is uint256;
library PYIndexLib {
using Math for uint256;
using Math for int256;
function newIndex(IPYieldToken YT) internal returns (PYIndex) {
return PYIndex.wrap(YT.pyIndexCurrent());
}
function syToAsset(PYIndex index, uint256 syAmount)
internal
pure
returns (uint256)
{
return SYUtils.syToAsset(PYIndex.unwrap(index), syAmount);
}
function assetToSy(PYIndex index, uint256 assetAmount)
internal
pure
returns (uint256)
{
return SYUtils.assetToSy(PYIndex.unwrap(index), assetAmount);
}
function assetToSyUp(PYIndex index, uint256 assetAmount)
internal
pure
returns (uint256)
{
return SYUtils.assetToSyUp(PYIndex.unwrap(index), assetAmount);
}
function syToAssetUp(PYIndex index, uint256 syAmount)
internal
pure
returns (uint256)
{
uint256 _index = PYIndex.unwrap(index);
return SYUtils.syToAssetUp(_index, syAmount);
}
function syToAsset(PYIndex index, int256 syAmount)
internal
pure
returns (int256)
{
int256 sign = syAmount < 0 ? int256(-1) : int256(1);
return sign * (SYUtils.syToAsset(PYIndex.unwrap(index), syAmount.abs())).Int();
}
function assetToSy(PYIndex index, int256 assetAmount)
internal
pure
returns (int256)
{
int256 sign = assetAmount < 0 ? int256(-1) : int256(1);
return sign * (SYUtils.assetToSy(PYIndex.unwrap(index), assetAmount.abs())).Int();
}
function assetToSyUp(PYIndex index, int256 assetAmount)
internal
pure
returns (int256)
{
int256 sign = assetAmount < 0 ? int256(-1) : int256(1);
return sign * (SYUtils.assetToSyUp(PYIndex.unwrap(index), assetAmount.abs())).Int();
}
}
文件 27 的 39:PendleERC20.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/utils/Context.sol";
contract PendleERC20 is Context, IERC20, IERC20Metadata {
uint8 private constant _NOT_ENTERED = 1;
uint8 private constant _ENTERED = 2;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint248 private _totalSupply;
uint8 private _status;
string private _name;
string private _symbol;
uint8 public immutable decimals;
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_
) {
_name = name_;
_symbol = symbol_;
decimals = decimals_;
_status = _NOT_ENTERED;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount)
external
virtual
override
nonReentrant
returns (bool)
{
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender)
public
view
virtual
override
returns (uint256)
{
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) external virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) external virtual override nonReentrant returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
require(from != to, "ERC20: transfer to self");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += toUint248(amount);
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= toUint248(amount);
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function toUint248(uint256 x) internal virtual returns (uint248) {
require(x <= type(uint248).max);
return uint248(x);
}
}
文件 28 的 39:PendleERC20Permit.sol
pragma solidity ^0.8.0;
import "./PendleERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract PendleERC20Permit is PendleERC20, IERC20Permit, EIP712 {
using Counters for Counters.Counter;
mapping(address => Counters.Counter) private _nonces;
bytes32 private constant _PERMIT_TYPEHASH =
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
);
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_
) PendleERC20(name_, symbol_, decimals_) EIP712(name_, "1") {}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override {
require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
bytes32 structHash = keccak256(
abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)
);
bytes32 hash = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(hash, v, r, s);
require(signer == owner, "ERC20Permit: invalid signature");
_approve(owner, spender, value);
}
function nonces(address owner) public view virtual override returns (uint256) {
return _nonces[owner].current();
}
function DOMAIN_SEPARATOR() external view override returns (bytes32) {
return _domainSeparatorV4();
}
function _useNonce(address owner) internal virtual returns (uint256 current) {
Counters.Counter storage nonce = _nonces[owner];
current = nonce.current();
nonce.increment();
}
}
文件 29 的 39:PendleGauge.sol
pragma solidity 0.8.17;
import "../../interfaces/IPGauge.sol";
import "../../interfaces/IPVeToken.sol";
import "../../interfaces/IPGaugeController.sol";
import "../../interfaces/IStandardizedYield.sol";
import "../RewardManager/RewardManager.sol";
abstract contract PendleGauge is RewardManager, IPGauge {
using Math for uint256;
using SafeERC20 for IERC20;
using ArrayLib for address[];
address private immutable SY;
uint256 internal constant TOKENLESS_PRODUCTION = 40;
address internal immutable PENDLE;
IPVeToken internal immutable vePENDLE;
address internal immutable gaugeController;
uint256 public totalActiveSupply;
mapping(address => uint256) public activeBalance;
constructor(
address _SY,
address _vePendle,
address _gaugeController
) {
SY = _SY;
vePENDLE = IPVeToken(_vePendle);
gaugeController = _gaugeController;
PENDLE = IPGaugeController(gaugeController).pendle();
}
function _redeemRewards(address user) internal virtual returns (uint256[] memory) {
_updateAndDistributeRewards(user);
_updateUserActiveBalance(user);
return _doTransferOutRewards(user, user);
}
function _updateUserActiveBalance(address user) internal virtual {
_updateUserActiveBalanceForTwo(user, address(0));
}
function _updateUserActiveBalanceForTwo(address user1, address user2) internal virtual {
if (user1 != address(0) && user1 != address(this)) _updateUserActiveBalancePrivate(user1);
if (user2 != address(0) && user2 != address(this)) _updateUserActiveBalancePrivate(user2);
}
function _updateUserActiveBalancePrivate(address user) private {
assert(user != address(0) && user != address(this));
uint256 lpBalance = _stakedBalance(user);
uint256 veBoostedLpBalance = _calcVeBoostedLpBalance(user, lpBalance);
uint256 newActiveBalance = Math.min(veBoostedLpBalance, lpBalance);
totalActiveSupply = totalActiveSupply - activeBalance[user] + newActiveBalance;
activeBalance[user] = newActiveBalance;
}
function _calcVeBoostedLpBalance(address user, uint256 lpBalance)
internal
virtual
returns (uint256)
{
(uint256 vePendleSupply, uint256 vePendleBalance) = vePENDLE.totalSupplyAndBalanceCurrent(
user
);
uint256 veBoostedLpBalance = (lpBalance * TOKENLESS_PRODUCTION) / 100;
if (vePendleSupply > 0) {
veBoostedLpBalance +=
(((_totalStaked() * vePendleBalance) / vePendleSupply) *
(100 - TOKENLESS_PRODUCTION)) /
100;
}
return veBoostedLpBalance;
}
function _redeemExternalReward() internal virtual override {
IStandardizedYield(SY).claimRewards(address(this));
IPGaugeController(gaugeController).redeemMarketReward();
}
function _stakedBalance(address user) internal view virtual returns (uint256);
function _totalStaked() internal view virtual returns (uint256);
function _rewardSharesTotal() internal view virtual override returns (uint256) {
return totalActiveSupply;
}
function _rewardSharesUser(address user) internal view virtual override returns (uint256) {
return activeBalance[user];
}
function _getRewardTokens() internal view virtual override returns (address[] memory) {
address[] memory SYRewards = IStandardizedYield(SY).getRewardTokens();
if (SYRewards.contains(PENDLE)) return SYRewards;
return SYRewards.append(PENDLE);
}
function _beforeTokenTransfer(
address from,
address to,
uint256
) internal virtual {
_updateAndDistributeRewardsForTwo(from, to);
}
function _afterTokenTransfer(
address from,
address to,
uint256
) internal virtual {
_updateUserActiveBalanceForTwo(from, to);
}
}
文件 30 的 39:PendleMarket.sol
pragma solidity 0.8.17;
import "../../interfaces/IPMarket.sol";
import "../../interfaces/IPMarketFactory.sol";
import "../../interfaces/IPMarketSwapCallback.sol";
import "../erc20/PendleERC20Permit.sol";
import "./PendleGauge.sol";
import "./OracleLib.sol";
contract PendleMarket is PendleERC20Permit, PendleGauge, IPMarket {
using Math for uint256;
using Math for int256;
using MarketMathCore for MarketState;
using SafeERC20 for IERC20;
using PYIndexLib for IPYieldToken;
using OracleLib for OracleLib.Observation[65535];
struct MarketStorage {
int128 totalPt;
int128 totalSy;
uint96 lastLnImpliedRate;
uint16 observationIndex;
uint16 observationCardinality;
uint16 observationCardinalityNext;
}
string private constant NAME = "Pendle Market";
string private constant SYMBOL = "PENDLE-LPT";
IPPrincipalToken internal immutable PT;
IStandardizedYield internal immutable SY;
IPYieldToken internal immutable YT;
address public immutable factory;
uint256 public immutable expiry;
int256 public immutable scalarRoot;
int256 public immutable initialAnchor;
MarketStorage public _storage;
OracleLib.Observation[65535] public observations;
modifier notExpired() {
if (isExpired()) revert Errors.MarketExpired();
_;
}
constructor(
address _PT,
int256 _scalarRoot,
int256 _initialAnchor,
address _vePendle,
address _gaugeController
)
PendleERC20Permit(NAME, SYMBOL, 18)
PendleGauge(IPPrincipalToken(_PT).SY(), _vePendle, _gaugeController)
{
PT = IPPrincipalToken(_PT);
SY = IStandardizedYield(PT.SY());
YT = IPYieldToken(PT.YT());
(_storage.observationCardinality, _storage.observationCardinalityNext) = observations
.initialize(uint32(block.timestamp));
if (_scalarRoot <= 0) revert Errors.MarketScalarRootBelowZero(_scalarRoot);
scalarRoot = _scalarRoot;
initialAnchor = _initialAnchor;
expiry = IPPrincipalToken(_PT).expiry();
factory = msg.sender;
}
function mint(
address receiver,
uint256 netSyDesired,
uint256 netPtDesired
)
external
nonReentrant
notExpired
returns (
uint256 netLpOut,
uint256 netSyUsed,
uint256 netPtUsed
)
{
MarketState memory market = readState(msg.sender);
PYIndex index = YT.newIndex();
uint256 lpToReserve;
(lpToReserve, netLpOut, netSyUsed, netPtUsed) = market.addLiquidity(
netSyDesired,
netPtDesired,
block.timestamp
);
if (lpToReserve != 0) {
market.setInitialLnImpliedRate(index, initialAnchor, block.timestamp);
_mint(address(1), lpToReserve);
}
_mint(receiver, netLpOut);
_writeState(market);
if (_selfBalance(SY) < market.totalSy.Uint())
revert Errors.MarketInsufficientSyReceived(_selfBalance(SY), market.totalSy.Uint());
if (_selfBalance(PT) < market.totalPt.Uint())
revert Errors.MarketInsufficientPtReceived(_selfBalance(PT), market.totalPt.Uint());
emit Mint(receiver, netLpOut, netSyUsed, netPtUsed);
}
function burn(
address receiverSy,
address receiverPt,
uint256 netLpToBurn
) external nonReentrant returns (uint256 netSyOut, uint256 netPtOut) {
MarketState memory market = readState(msg.sender);
_burn(address(this), netLpToBurn);
(netSyOut, netPtOut) = market.removeLiquidity(netLpToBurn);
if (receiverSy != address(this)) IERC20(SY).safeTransfer(receiverSy, netSyOut);
if (receiverPt != address(this)) IERC20(PT).safeTransfer(receiverPt, netPtOut);
_writeState(market);
emit Burn(receiverSy, receiverPt, netLpToBurn, netSyOut, netPtOut);
}
function swapExactPtForSy(
address receiver,
uint256 exactPtIn,
bytes calldata data
) external nonReentrant notExpired returns (uint256 netSyOut, uint256 netSyFee) {
MarketState memory market = readState(msg.sender);
uint256 netSyToReserve;
(netSyOut, netSyFee, netSyToReserve) = market.swapExactPtForSy(
YT.newIndex(),
exactPtIn,
block.timestamp
);
if (receiver != address(this)) IERC20(SY).safeTransfer(receiver, netSyOut);
IERC20(SY).safeTransfer(market.treasury, netSyToReserve);
_writeState(market);
if (data.length > 0) {
IPMarketSwapCallback(msg.sender).swapCallback(exactPtIn.neg(), netSyOut.Int(), data);
}
if (_selfBalance(PT) < market.totalPt.Uint())
revert Errors.MarketInsufficientPtReceived(_selfBalance(PT), market.totalPt.Uint());
emit Swap(msg.sender, receiver, exactPtIn.neg(), netSyOut.Int(), netSyFee, netSyToReserve);
}
function swapSyForExactPt(
address receiver,
uint256 exactPtOut,
bytes calldata data
) external nonReentrant notExpired returns (uint256 netSyIn, uint256 netSyFee) {
MarketState memory market = readState(msg.sender);
uint256 netSyToReserve;
(netSyIn, netSyFee, netSyToReserve) = market.swapSyForExactPt(
YT.newIndex(),
exactPtOut,
block.timestamp
);
if (receiver != address(this)) IERC20(PT).safeTransfer(receiver, exactPtOut);
IERC20(SY).safeTransfer(market.treasury, netSyToReserve);
_writeState(market);
if (data.length > 0) {
IPMarketSwapCallback(msg.sender).swapCallback(exactPtOut.Int(), netSyIn.neg(), data);
}
if (_selfBalance(SY) < market.totalSy.Uint())
revert Errors.MarketInsufficientSyReceived(_selfBalance(SY), market.totalSy.Uint());
emit Swap(msg.sender, receiver, exactPtOut.Int(), netSyIn.neg(), netSyFee, netSyToReserve);
}
function skim() external nonReentrant {
MarketState memory market = readState(msg.sender);
uint256 excessPt = _selfBalance(PT) - market.totalPt.Uint();
uint256 excessSy = _selfBalance(SY) - market.totalSy.Uint();
if (excessPt != 0) IERC20(PT).safeTransfer(market.treasury, excessPt);
if (excessSy != 0) IERC20(SY).safeTransfer(market.treasury, excessSy);
}
function redeemRewards(address user) external nonReentrant returns (uint256[] memory) {
return _redeemRewards(user);
}
function getRewardTokens() external view returns (address[] memory) {
return _getRewardTokens();
}
function observe(uint32[] memory secondsAgos)
external
view
returns (uint216[] memory lnImpliedRateCumulative)
{
return
observations.observe(
uint32(block.timestamp),
secondsAgos,
_storage.lastLnImpliedRate,
_storage.observationIndex,
_storage.observationCardinality
);
}
function increaseObservationsCardinalityNext(uint16 cardinalityNext) external nonReentrant {
uint16 cardinalityNextOld = _storage.observationCardinalityNext;
uint16 cardinalityNextNew = observations.grow(cardinalityNextOld, cardinalityNext);
if (cardinalityNextOld != cardinalityNextNew) {
_storage.observationCardinalityNext = cardinalityNextNew;
emit IncreaseObservationCardinalityNext(cardinalityNextOld, cardinalityNextNew);
}
}
function readState(address router) public view returns (MarketState memory market) {
market.totalPt = _storage.totalPt;
market.totalSy = _storage.totalSy;
market.totalLp = totalSupply().Int();
(market.treasury, market.lnFeeRateRoot, market.reserveFeePercent) = IPMarketFactory(
factory
).getMarketConfig(router);
market.scalarRoot = scalarRoot;
market.expiry = expiry;
market.lastLnImpliedRate = _storage.lastLnImpliedRate;
}
function _writeState(MarketState memory market) internal {
uint96 lastLnImpliedRate96 = market.lastLnImpliedRate.Uint96();
int128 totalPt128 = market.totalPt.Int128();
int128 totalSy128 = market.totalSy.Int128();
(uint16 observationIndex, uint16 observationCardinality) = observations.write(
_storage.observationIndex,
uint32(block.timestamp),
_storage.lastLnImpliedRate,
_storage.observationCardinality,
_storage.observationCardinalityNext
);
_storage.totalPt = totalPt128;
_storage.totalSy = totalSy128;
_storage.lastLnImpliedRate = lastLnImpliedRate96;
_storage.observationIndex = observationIndex;
_storage.observationCardinality = observationCardinality;
emit UpdateImpliedRate(block.timestamp, market.lastLnImpliedRate);
}
function readTokens()
external
view
returns (
IStandardizedYield _SY,
IPPrincipalToken _PT,
IPYieldToken _YT
)
{
_SY = SY;
_PT = PT;
_YT = YT;
}
function isExpired() public view returns (bool) {
return MiniHelpers.isCurrentlyExpired(expiry);
}
function _stakedBalance(address user) internal view override returns (uint256) {
return balanceOf(user);
}
function _totalStaked() internal view override returns (uint256) {
return totalSupply();
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal override(PendleERC20, PendleGauge) {
PendleGauge._beforeTokenTransfer(from, to, amount);
}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal override(PendleERC20, PendleGauge) {
PendleGauge._afterTokenTransfer(from, to, amount);
}
}
文件 31 的 39:RewardManager.sol
pragma solidity 0.8.17;
import "./RewardManagerAbstract.sol";
abstract contract RewardManager is RewardManagerAbstract {
using Math for uint256;
using ArrayLib for uint256[];
uint256 public lastRewardBlock;
mapping(address => RewardState) public rewardState;
uint256 internal constant INITIAL_REWARD_INDEX = 1;
function _updateRewardIndex()
internal
virtual
override
returns (address[] memory tokens, uint256[] memory indexes)
{
tokens = _getRewardTokens();
indexes = new uint256[](tokens.length);
if (tokens.length == 0) return (tokens, indexes);
if (lastRewardBlock != block.number) {
lastRewardBlock = block.number;
uint256 totalShares = _rewardSharesTotal();
_redeemExternalReward();
for (uint256 i = 0; i < tokens.length; ++i) {
address token = tokens[i];
uint256 accrued = _selfBalance(tokens[i]) - rewardState[token].lastBalance;
uint256 index = rewardState[token].index;
if (index == 0) index = INITIAL_REWARD_INDEX;
if (totalShares != 0) index += accrued.divDown(totalShares);
rewardState[token].index = index.Uint128();
rewardState[token].lastBalance += accrued.Uint128();
}
}
for (uint256 i = 0; i < tokens.length; i++) indexes[i] = rewardState[tokens[i]].index;
}
function _doTransferOutRewards(address user, address receiver)
internal
virtual
override
returns (uint256[] memory rewardAmounts)
{
address[] memory tokens = _getRewardTokens();
rewardAmounts = new uint256[](tokens.length);
for (uint256 i = 0; i < tokens.length; i++) {
rewardAmounts[i] = userReward[tokens[i]][user].accrued;
if (rewardAmounts[i] != 0) {
userReward[tokens[i]][user].accrued = 0;
rewardState[tokens[i]].lastBalance -= rewardAmounts[i].Uint128();
_transferOut(tokens[i], receiver, rewardAmounts[i]);
}
}
}
function _getRewardTokens() internal view virtual returns (address[] memory);
function _rewardSharesTotal() internal view virtual returns (uint256);
}
文件 32 的 39:RewardManagerAbstract.sol
pragma solidity 0.8.17;
import "../../interfaces/IRewardManager.sol";
import "../libraries/ArrayLib.sol";
import "../libraries/TokenHelper.sol";
import "../libraries/math/Math.sol";
import "./RewardManagerAbstract.sol";
abstract contract RewardManagerAbstract is IRewardManager, TokenHelper {
using Math for uint256;
struct RewardState {
uint128 index;
uint128 lastBalance;
}
struct UserReward {
uint128 index;
uint128 accrued;
}
mapping(address => mapping(address => UserReward)) public userReward;
function _updateAndDistributeRewards(address user) internal virtual {
_updateAndDistributeRewardsForTwo(user, address(0));
}
function _updateAndDistributeRewardsForTwo(address user1, address user2) internal virtual {
(address[] memory tokens, uint256[] memory indexes) = _updateRewardIndex();
if (tokens.length == 0) return;
if (user1 != address(0) && user1 != address(this))
_distributeRewardsPrivate(user1, tokens, indexes);
if (user2 != address(0) && user2 != address(this))
_distributeRewardsPrivate(user2, tokens, indexes);
}
function _distributeRewardsPrivate(
address user,
address[] memory tokens,
uint256[] memory indexes
) private {
assert(user != address(0) && user != address(this));
uint256 userShares = _rewardSharesUser(user);
for (uint256 i = 0; i < tokens.length; ++i) {
address token = tokens[i];
uint256 index = indexes[i];
uint256 userIndex = userReward[token][user].index;
if (userIndex == 0) {
userReward[token][user].index = index.Uint128();
continue;
}
if (userIndex == index) continue;
uint256 deltaIndex = index - userIndex;
uint256 rewardDelta = userShares.mulDown(deltaIndex);
uint256 rewardAccrued = userReward[token][user].accrued + rewardDelta;
userReward[token][user] = UserReward({
index: index.Uint128(),
accrued: rewardAccrued.Uint128()
});
}
}
function _updateRewardIndex()
internal
virtual
returns (address[] memory tokens, uint256[] memory indexes);
function _redeemExternalReward() internal virtual;
function _doTransferOutRewards(address user, address receiver)
internal
virtual
returns (uint256[] memory rewardAmounts);
function _rewardSharesUser(address user) internal view virtual returns (uint256);
}
文件 33 的 39:SYUtils.sol
pragma solidity 0.8.17;
library SYUtils {
uint256 internal constant ONE = 1e18;
function syToAsset(uint256 exchangeRate, uint256 syAmount) internal pure returns (uint256) {
return (syAmount * exchangeRate) / ONE;
}
function syToAssetUp(uint256 exchangeRate, uint256 syAmount) internal pure returns (uint256) {
return (syAmount * exchangeRate + ONE - 1) / ONE;
}
function assetToSy(uint256 exchangeRate, uint256 assetAmount) internal pure returns (uint256) {
return (assetAmount * ONE) / exchangeRate;
}
function assetToSyUp(uint256 exchangeRate, uint256 assetAmount)
internal
pure
returns (uint256)
{
return (assetAmount * ONE + exchangeRate - 1) / exchangeRate;
}
}
文件 34 的 39:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 35 的 39:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
文件 36 的 39:TokenHelper.sol
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
abstract contract TokenHelper {
using SafeERC20 for IERC20;
address internal constant NATIVE = address(0);
uint256 internal constant LOWER_BOUND_APPROVAL = type(uint96).max / 2;
function _transferIn(
address token,
address from,
uint256 amount
) internal {
if (token == NATIVE) require(msg.value == amount, "eth mismatch");
else if (amount != 0) IERC20(token).safeTransferFrom(from, address(this), amount);
}
function _transferFrom(
IERC20 token,
address from,
address to,
uint256 amount
) internal {
if (amount != 0) token.safeTransferFrom(from, to, amount);
}
function _transferOut(
address token,
address to,
uint256 amount
) internal {
if (amount == 0) return;
if (token == NATIVE) {
(bool success, ) = to.call{ value: amount }("");
require(success, "eth send failed");
} else {
IERC20(token).safeTransfer(to, amount);
}
}
function _transferOut(
address[] memory tokens,
address to,
uint256[] memory amounts
) internal {
uint256 numTokens = tokens.length;
require(numTokens == amounts.length, "length mismatch");
for (uint256 i = 0; i < numTokens; ) {
_transferOut(tokens[i], to, amounts[i]);
unchecked {
i++;
}
}
}
function _selfBalance(address token) internal view returns (uint256) {
return (token == NATIVE) ? address(this).balance : IERC20(token).balanceOf(address(this));
}
function _selfBalance(IERC20 token) internal view returns (uint256) {
return token.balanceOf(address(this));
}
function _safeApprove(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(IERC20.approve.selector, to, value)
);
require(success && (data.length == 0 || abi.decode(data, (bool))), "Safe Approve");
}
function _safeApproveInf(address token, address to) internal {
if (token == NATIVE) return;
if (IERC20(token).allowance(address(this), to) < LOWER_BOUND_APPROVAL) {
_safeApprove(token, to, 0);
_safeApprove(token, to, type(uint256).max);
}
}
}
文件 37 的 39:draft-EIP712.sol
pragma solidity ^0.8.0;
import "./ECDSA.sol";
abstract contract EIP712 {
bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;
uint256 private immutable _CACHED_CHAIN_ID;
address private immutable _CACHED_THIS;
bytes32 private immutable _HASHED_NAME;
bytes32 private immutable _HASHED_VERSION;
bytes32 private immutable _TYPE_HASH;
constructor(string memory name, string memory version) {
bytes32 hashedName = keccak256(bytes(name));
bytes32 hashedVersion = keccak256(bytes(version));
bytes32 typeHash = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
_HASHED_NAME = hashedName;
_HASHED_VERSION = hashedVersion;
_CACHED_CHAIN_ID = block.chainid;
_CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);
_CACHED_THIS = address(this);
_TYPE_HASH = typeHash;
}
function _domainSeparatorV4() internal view returns (bytes32) {
if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {
return _CACHED_DOMAIN_SEPARATOR;
} else {
return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);
}
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));
}
function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {
return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);
}
}
文件 38 的 39:draft-ERC20Permit.sol
pragma solidity ^0.8.0;
import "./draft-IERC20Permit.sol";
import "../ERC20.sol";
import "../../../utils/cryptography/draft-EIP712.sol";
import "../../../utils/cryptography/ECDSA.sol";
import "../../../utils/Counters.sol";
abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {
using Counters for Counters.Counter;
mapping(address => Counters.Counter) private _nonces;
bytes32 private constant _PERMIT_TYPEHASH =
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;
constructor(string memory name) EIP712(name, "1") {}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override {
require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));
bytes32 hash = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(hash, v, r, s);
require(signer == owner, "ERC20Permit: invalid signature");
_approve(owner, spender, value);
}
function nonces(address owner) public view virtual override returns (uint256) {
return _nonces[owner].current();
}
function DOMAIN_SEPARATOR() external view override returns (bytes32) {
return _domainSeparatorV4();
}
function _useNonce(address owner) internal virtual returns (uint256 current) {
Counters.Counter storage nonce = _nonces[owner];
current = nonce.current();
nonce.increment();
}
}
文件 39 的 39:draft-IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
{
"compilationTarget": {
"contracts/pendle/contracts/core/Market/PendleMarket.sol": "PendleMarket"
},
"evmVersion": "london",
"libraries": {
"contracts/pendle/contracts/core/Market/OracleLib.sol:OracleLib": "0x02176d640657740539f70eea98501ebbf1c10ecc"
},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 800
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_PT","type":"address"},{"internalType":"int256","name":"_scalarRoot","type":"int256"},{"internalType":"int256","name":"_initialAnchor","type":"int256"},{"internalType":"address","name":"_vePendle","type":"address"},{"internalType":"address","name":"_gaugeController","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"int256","name":"exchangeRate","type":"int256"}],"name":"MarketExchangeRateBelowOne","type":"error"},{"inputs":[],"name":"MarketExpired","type":"error"},{"inputs":[{"internalType":"int256","name":"currentAmount","type":"int256"},{"internalType":"int256","name":"requiredAmount","type":"int256"}],"name":"MarketInsufficientPtForTrade","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualBalance","type":"uint256"},{"internalType":"uint256","name":"requiredBalance","type":"uint256"}],"name":"MarketInsufficientPtReceived","type":"error"},{"inputs":[{"internalType":"uint256","name":"actualBalance","type":"uint256"},{"internalType":"uint256","name":"requiredBalance","type":"uint256"}],"name":"MarketInsufficientSyReceived","type":"error"},{"inputs":[],"name":"MarketProportionMustNotEqualOne","type":"error"},{"inputs":[{"internalType":"int256","name":"proportion","type":"int256"},{"internalType":"int256","name":"maxProportion","type":"int256"}],"name":"MarketProportionTooHigh","type":"error"},{"inputs":[{"internalType":"int256","name":"rateScalar","type":"int256"}],"name":"MarketRateScalarBelowZero","type":"error"},{"inputs":[{"internalType":"int256","name":"scalarRoot","type":"int256"}],"name":"MarketScalarRootBelowZero","type":"error"},{"inputs":[],"name":"MarketZeroAmountsInput","type":"error"},{"inputs":[],"name":"MarketZeroAmountsOutput","type":"error"},{"inputs":[],"name":"MarketZeroLnImpliedRate","type":"error"},{"inputs":[{"internalType":"int256","name":"totalPt","type":"int256"},{"internalType":"int256","name":"totalAsset","type":"int256"}],"name":"MarketZeroTotalPtOrTotalAsset","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":"receiverSy","type":"address"},{"indexed":true,"internalType":"address","name":"receiverPt","type":"address"},{"indexed":false,"internalType":"uint256","name":"netLpBurned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netSyOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netPtOut","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"observationCardinalityNextOld","type":"uint16"},{"indexed":false,"internalType":"uint16","name":"observationCardinalityNextNew","type":"uint16"}],"name":"IncreaseObservationCardinalityNext","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"netLpMinted","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netSyUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netPtUsed","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"int256","name":"netPtOut","type":"int256"},{"indexed":false,"internalType":"int256","name":"netSyOut","type":"int256"},{"indexed":false,"internalType":"uint256","name":"netSyFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"netSyToReserve","type":"uint256"}],"name":"Swap","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lnLastImpliedRate","type":"uint256"}],"name":"UpdateImpliedRate","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_storage","outputs":[{"internalType":"int128","name":"totalPt","type":"int128"},{"internalType":"int128","name":"totalSy","type":"int128"},{"internalType":"uint96","name":"lastLnImpliedRate","type":"uint96"},{"internalType":"uint16","name":"observationIndex","type":"uint16"},{"internalType":"uint16","name":"observationCardinality","type":"uint16"},{"internalType":"uint16","name":"observationCardinalityNext","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"activeBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"address","name":"receiverSy","type":"address"},{"internalType":"address","name":"receiverPt","type":"address"},{"internalType":"uint256","name":"netLpToBurn","type":"uint256"}],"name":"burn","outputs":[{"internalType":"uint256","name":"netSyOut","type":"uint256"},{"internalType":"uint256","name":"netPtOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"expiry","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"cardinalityNext","type":"uint16"}],"name":"increaseObservationsCardinalityNext","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialAnchor","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isExpired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRewardBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"netSyDesired","type":"uint256"},{"internalType":"uint256","name":"netPtDesired","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"netLpOut","type":"uint256"},{"internalType":"uint256","name":"netSyUsed","type":"uint256"},{"internalType":"uint256","name":"netPtUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"observations","outputs":[{"internalType":"uint32","name":"blockTimestamp","type":"uint32"},{"internalType":"uint216","name":"lnImpliedRateCumulative","type":"uint216"},{"internalType":"bool","name":"initialized","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"secondsAgos","type":"uint32[]"}],"name":"observe","outputs":[{"internalType":"uint216[]","name":"lnImpliedRateCumulative","type":"uint216[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","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":[{"internalType":"address","name":"router","type":"address"}],"name":"readState","outputs":[{"components":[{"internalType":"int256","name":"totalPt","type":"int256"},{"internalType":"int256","name":"totalSy","type":"int256"},{"internalType":"int256","name":"totalLp","type":"int256"},{"internalType":"address","name":"treasury","type":"address"},{"internalType":"int256","name":"scalarRoot","type":"int256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint256","name":"lnFeeRateRoot","type":"uint256"},{"internalType":"uint256","name":"reserveFeePercent","type":"uint256"},{"internalType":"uint256","name":"lastLnImpliedRate","type":"uint256"}],"internalType":"struct MarketState","name":"market","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"readTokens","outputs":[{"internalType":"contract IStandardizedYield","name":"_SY","type":"address"},{"internalType":"contract IPPrincipalToken","name":"_PT","type":"address"},{"internalType":"contract IPYieldToken","name":"_YT","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"redeemRewards","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardState","outputs":[{"internalType":"uint128","name":"index","type":"uint128"},{"internalType":"uint128","name":"lastBalance","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"scalarRoot","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"skim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"exactPtIn","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swapExactPtForSy","outputs":[{"internalType":"uint256","name":"netSyOut","type":"uint256"},{"internalType":"uint256","name":"netSyFee","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"exactPtOut","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swapSyForExactPt","outputs":[{"internalType":"uint256","name":"netSyIn","type":"uint256"},{"internalType":"uint256","name":"netSyFee","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalActiveSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userReward","outputs":[{"internalType":"uint128","name":"index","type":"uint128"},{"internalType":"uint128","name":"accrued","type":"uint128"}],"stateMutability":"view","type":"function"}]