编译器
0.8.11+commit.d7f03943
文件 1 的 30:BalancerOracle.sol
pragma solidity 0.8.11;
interface BalancerOracle {
function getTimeWeightedAverage(OracleAverageQuery[] memory queries)
external
view
returns (uint256[] memory results);
enum Variable {
PAIR_PRICE,
BPT_PRICE,
INVARIANT
}
struct OracleAverageQuery {
Variable variable;
uint256 secs;
uint256 ago;
}
function getSample(uint256 index)
external
view
returns (
int256 logPairPrice,
int256 accLogPairPrice,
int256 logBptPrice,
int256 accLogBptPrice,
int256 logInvariant,
int256 accLogInvariant,
uint256 timestamp
);
function getPoolId() external view returns (bytes32);
function getVault() external view returns (address);
function getIndices() external view returns (uint256 _pti, uint256 _targeti);
function totalSupply() external view returns (uint256);
function getTotalSamples() external pure returns (uint256);
}
文件 2 的 30:BaseAdapter.sol
pragma solidity 0.8.11;
import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol";
import { SafeTransferLib } from "@rari-capital/solmate/src/utils/SafeTransferLib.sol";
import { IERC3156FlashLender } from "../external/flashloan/IERC3156FlashLender.sol";
import { IERC3156FlashBorrower } from "../external/flashloan/IERC3156FlashBorrower.sol";
import { Divider } from "../Divider.sol";
import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol";
abstract contract BaseAdapter is IERC3156FlashLender {
using SafeTransferLib for ERC20;
bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
address public immutable divider;
address public immutable target;
address public immutable underlying;
uint128 public immutable ifee;
AdapterParams public adapterParams;
struct AdapterParams {
address oracle;
address stake;
uint256 stakeSize;
uint256 minm;
uint256 maxm;
uint64 tilt;
uint48 level;
uint16 mode;
}
string public name;
string public symbol;
constructor(
address _divider,
address _target,
address _underlying,
uint128 _ifee,
AdapterParams memory _adapterParams
) {
divider = _divider;
target = _target;
underlying = _underlying;
ifee = _ifee;
adapterParams = _adapterParams;
name = string(abi.encodePacked(ERC20(_target).name(), " Adapter"));
symbol = string(abi.encodePacked(ERC20(_target).symbol(), "-adapter"));
ERC20(_target).approve(divider, type(uint256).max);
ERC20(_adapterParams.stake).approve(divider, type(uint256).max);
}
function flashLoan(
IERC3156FlashBorrower receiver,
address,
uint256 amount,
bytes calldata data
) external returns (bool) {
if (Divider(divider).periphery() != msg.sender) revert Errors.OnlyPeriphery();
ERC20(target).safeTransfer(address(receiver), amount);
bytes32 keccak = IERC3156FlashBorrower(receiver).onFlashLoan(msg.sender, target, amount, 0, data);
if (keccak != CALLBACK_SUCCESS) revert Errors.FlashCallbackFailed();
ERC20(target).safeTransferFrom(address(receiver), address(this), amount);
return true;
}
function scale() external virtual returns (uint256);
function scaleStored() external view virtual returns (uint256);
function getUnderlyingPrice() external view virtual returns (uint256);
function wrapUnderlying(uint256 amount) external virtual returns (uint256);
function unwrapTarget(uint256 amount) external virtual returns (uint256);
function flashFee(address token, uint256) external view returns (uint256) {
if (token != target) revert Errors.TokenNotSupported();
return 0;
}
function maxFlashLoan(address token) external view override returns (uint256) {
return ERC20(token).balanceOf(address(this));
}
function notify(
address,
uint256,
bool
) public virtual {
return;
}
function onRedeem(
uint256,
uint256,
uint256,
uint256
) public virtual {
return;
}
function getMaturityBounds() external view returns (uint256, uint256) {
return (adapterParams.minm, adapterParams.maxm);
}
function getStakeAndTarget()
external
view
returns (
address,
address,
uint256
)
{
return (target, adapterParams.stake, adapterParams.stakeSize);
}
function mode() external view returns (uint256) {
return adapterParams.mode;
}
function tilt() external view returns (uint256) {
return adapterParams.tilt;
}
function level() external view returns (uint256) {
return adapterParams.level;
}
}
文件 3 的 30:BaseFactory.sol
pragma solidity 0.8.11;
import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol";
import { BaseAdapter } from "./BaseAdapter.sol";
import { Divider } from "../Divider.sol";
abstract contract BaseFactory {
uint48 public constant DEFAULT_LEVEL = 31;
address public immutable divider;
mapping(address => address) public adapters;
FactoryParams public factoryParams;
struct FactoryParams {
address oracle;
address stake;
uint256 stakeSize;
uint256 minm;
uint256 maxm;
uint128 ifee;
uint16 mode;
uint64 tilt;
}
constructor(address _divider, FactoryParams memory _factoryParams) {
divider = _divider;
factoryParams = _factoryParams;
}
function deployAdapter(address _target, bytes memory _data) external virtual returns (address adapter) {}
event AdapterAdded(address addr, address indexed target);
}
文件 4 的 30:Bytes32AddressLib.sol
pragma solidity >=0.8.0;
library Bytes32AddressLib {
function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) {
return address(uint160(uint256(bytesValue)));
}
function fillLast12Bytes(address addressValue) internal pure returns (bytes32) {
return bytes32(bytes20(addressValue));
}
}
文件 5 的 30:CToken.sol
pragma solidity 0.8.11;
interface CToken {
function underlying() external view returns (address);
function mint(uint256 mintAmount) external returns (uint256);
function redeem(uint256 redeemTokens) external returns (uint256);
function borrow(uint256 borrowAmount) external returns (uint256);
function repayBorrow(uint256 repayAmount) external returns (uint256);
function exchangeRateCurrent() external returns (uint256);
function decimals() external view returns (uint8);
}
文件 6 的 30:Clones.sol
pragma solidity ^0.8.0;
library Clones {
function clone(address implementation) internal returns (address instance) {
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create(0, ptr, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create2(0, ptr, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
mstore(add(ptr, 0x38), shl(0x60, deployer))
mstore(add(ptr, 0x4c), salt)
mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
predicted := keccak256(add(ptr, 0x37), 0x55)
}
}
function predictDeterministicAddress(address implementation, bytes32 salt)
internal
view
returns (address predicted)
{
return predictDeterministicAddress(implementation, salt, address(this));
}
}
文件 7 的 30: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;
}
}
文件 8 的 30:DateTime.sol
pragma solidity 0.8.11;
library DateTime {
uint256 constant SECONDS_PER_DAY = 24 * 60 * 60;
uint256 constant SECONDS_PER_HOUR = 60 * 60;
uint256 constant SECONDS_PER_MINUTE = 60;
int256 constant OFFSET19700101 = 2440588;
function timestampToDate(uint256 timestamp)
internal
pure
returns (
uint256 year,
uint256 month,
uint256 day
)
{
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function timestampToDateTime(uint256 timestamp)
internal
pure
returns (
uint256 year,
uint256 month,
uint256 day,
uint256 hour,
uint256 minute,
uint256 second
)
{
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
uint256 secs = timestamp % SECONDS_PER_DAY;
hour = secs / SECONDS_PER_HOUR;
secs = secs % SECONDS_PER_HOUR;
minute = secs / SECONDS_PER_MINUTE;
second = secs % SECONDS_PER_MINUTE;
}
function toDateString(uint256 _timestamp)
internal
pure
returns (
string memory d,
string memory m,
string memory y
)
{
(uint256 year, uint256 month, uint256 day) = timestampToDate(_timestamp);
d = uintToString(day);
m = uintToString(month);
y = uintToString(year);
if (day < 10) d = string(abi.encodePacked("0", d));
if (month < 10) m = string(abi.encodePacked("0", m));
}
function format(uint256 _timestamp) internal pure returns (string memory datestring) {
string[12] memory months = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"June",
"July",
"Aug",
"Sept",
"Oct",
"Nov",
"Dec"
];
(uint256 year, uint256 month, uint256 day) = timestampToDate(_timestamp);
uint256 last = day % 10;
string memory suffix = "th";
if (day < 11 || day > 20) {
if (last == 1) suffix = "st";
if (last == 2) suffix = "nd";
if (last == 3) suffix = "rd";
}
return string(abi.encodePacked(uintToString(day), suffix, " ", months[month - 1], " ", uintToString(year)));
}
function getDayOfWeek(uint256 timestamp) internal pure returns (uint256 dayOfWeek) {
uint256 _days = timestamp / SECONDS_PER_DAY;
dayOfWeek = ((_days + 3) % 7) + 1;
}
function uintToString(uint256 _i) internal pure returns (string memory _uintAsString) {
if (_i == 0) return "0";
uint256 j = _i;
uint256 len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint256 k = len;
while (_i != 0) {
k = k - 1;
uint8 temp = (48 + uint8(_i - (_i / 10) * 10));
bytes1 b1 = bytes1(temp);
bstr[k] = b1;
_i /= 10;
}
return string(bstr);
}
function _daysFromDate(
uint256 year,
uint256 month,
uint256 day
) internal pure returns (uint256 _days) {
require(year >= 1970);
int256 _year = int256(year);
int256 _month = int256(month);
int256 _day = int256(day);
int256 __days = _day -
32075 +
(1461 * (_year + 4800 + (_month - 14) / 12)) /
4 +
(367 * (_month - 2 - ((_month - 14) / 12) * 12)) /
12 -
(3 * ((_year + 4900 + (_month - 14) / 12) / 100)) /
4 -
OFFSET19700101;
_days = uint256(__days);
}
function _daysToDate(uint256 _days)
internal
pure
returns (
uint256 year,
uint256 month,
uint256 day
)
{
int256 __days = int256(_days);
int256 L = __days + 68569 + OFFSET19700101;
int256 N = (4 * L) / 146097;
L = L - (146097 * N + 3) / 4;
int256 _year = (4000 * (L + 1)) / 1461001;
L = L - (1461 * _year) / 4 + 31;
int256 _month = (80 * L) / 2447;
int256 _day = L - (2447 * _month) / 80;
L = _month / 11;
_month = _month + 2 - 12 * L;
_year = 100 * (N - 49) + _year + L;
year = uint256(_year);
month = uint256(_month);
day = uint256(_day);
}
}
文件 9 的 30:Divider.sol
pragma solidity 0.8.11;
import { Pausable } from "@openzeppelin/contracts/security/Pausable.sol";
import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol";
import { SafeTransferLib } from "@rari-capital/solmate/src/utils/SafeTransferLib.sol";
import { ReentrancyGuard } from "@rari-capital/solmate/src/utils/ReentrancyGuard.sol";
import { DateTime } from "./external/DateTime.sol";
import { FixedMath } from "./external/FixedMath.sol";
import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol";
import { Levels } from "@sense-finance/v1-utils/src/libs/Levels.sol";
import { Trust } from "@sense-finance/v1-utils/src/Trust.sol";
import { YT } from "./tokens/YT.sol";
import { Token } from "./tokens/Token.sol";
import { BaseAdapter as Adapter } from "./adapters/BaseAdapter.sol";
contract Divider is Trust, ReentrancyGuard, Pausable {
using SafeTransferLib for ERC20;
using FixedMath for uint256;
using Levels for uint256;
uint256 public constant SPONSOR_WINDOW = 3 hours;
uint256 public constant SETTLEMENT_WINDOW = 3 hours;
uint256 public constant ISSUANCE_FEE_CAP = 0.05e18;
address public periphery;
address public immutable cup;
address public immutable tokenHandler;
bool public permissionless;
bool public guarded = true;
uint248 public adapterCounter;
mapping(uint256 => address) public adapterAddresses;
mapping(address => AdapterMeta) public adapterMeta;
mapping(address => mapping(uint256 => Series)) public series;
mapping(address => mapping(uint256 => mapping(address => uint256))) public lscales;
struct Series {
address pt;
uint48 issuance;
address yt;
uint96 tilt;
address sponsor;
uint256 reward;
uint256 iscale;
uint256 mscale;
uint256 maxscale;
}
struct AdapterMeta {
uint248 id;
bool enabled;
uint256 guard;
uint248 level;
}
constructor(address _cup, address _tokenHandler) Trust(msg.sender) {
cup = _cup;
tokenHandler = _tokenHandler;
}
function addAdapter(address adapter) external whenNotPaused {
if (!permissionless && msg.sender != periphery) revert Errors.OnlyPermissionless();
if (adapterMeta[adapter].id > 0 && !adapterMeta[adapter].enabled) revert Errors.InvalidAdapter();
_setAdapter(adapter, true);
}
function initSeries(
address adapter,
uint256 maturity,
address sponsor
) external nonReentrant whenNotPaused returns (address pt, address yt) {
if (periphery != msg.sender) revert Errors.OnlyPeriphery();
if (!adapterMeta[adapter].enabled) revert Errors.InvalidAdapter();
if (_exists(adapter, maturity)) revert Errors.DuplicateSeries();
if (!_isValid(adapter, maturity)) revert Errors.InvalidMaturity();
(address target, address stake, uint256 stakeSize) = Adapter(adapter).getStakeAndTarget();
(pt, yt) = TokenHandler(tokenHandler).deploy(adapter, adapterMeta[adapter].id, maturity);
uint256 scale = Adapter(adapter).scale();
series[adapter][maturity].pt = pt;
series[adapter][maturity].issuance = uint48(block.timestamp);
series[adapter][maturity].yt = yt;
series[adapter][maturity].tilt = uint96(Adapter(adapter).tilt());
series[adapter][maturity].sponsor = sponsor;
series[adapter][maturity].iscale = scale;
series[adapter][maturity].maxscale = scale;
ERC20(stake).safeTransferFrom(msg.sender, adapter, stakeSize);
emit SeriesInitialized(adapter, maturity, pt, yt, sponsor, target);
}
function settleSeries(address adapter, uint256 maturity) external nonReentrant whenNotPaused {
if (!adapterMeta[adapter].enabled) revert Errors.InvalidAdapter();
if (!_exists(adapter, maturity)) revert Errors.SeriesDoesNotExist();
if (_settled(adapter, maturity)) revert Errors.AlreadySettled();
if (!_canBeSettled(adapter, maturity)) revert Errors.OutOfWindowBoundaries();
uint256 mscale = Adapter(adapter).scale();
series[adapter][maturity].mscale = mscale;
if (mscale > series[adapter][maturity].maxscale) {
series[adapter][maturity].maxscale = mscale;
}
(address target, address stake, uint256 stakeSize) = Adapter(adapter).getStakeAndTarget();
ERC20(target).safeTransferFrom(adapter, msg.sender, series[adapter][maturity].reward);
ERC20(stake).safeTransferFrom(adapter, msg.sender, stakeSize);
emit SeriesSettled(adapter, maturity, msg.sender);
}
function issue(
address adapter,
uint256 maturity,
uint256 tBal
) external nonReentrant whenNotPaused returns (uint256 uBal) {
if (!adapterMeta[adapter].enabled) revert Errors.InvalidAdapter();
if (!_exists(adapter, maturity)) revert Errors.SeriesDoesNotExist();
if (_settled(adapter, maturity)) revert Errors.IssueOnSettle();
uint256 level = adapterMeta[adapter].level;
if (level.issueRestricted() && msg.sender != adapter) revert Errors.IssuanceRestricted();
ERC20 target = ERC20(Adapter(adapter).target());
uint256 issuanceFee = Adapter(adapter).ifee();
if (issuanceFee > ISSUANCE_FEE_CAP) revert Errors.IssuanceFeeCapExceeded();
uint256 fee = tBal.fmul(issuanceFee);
unchecked {
series[adapter][maturity].reward += fee;
}
uint256 tBalSubFee = tBal - fee;
unchecked {
if (guarded && target.balanceOf(adapter) + tBal > adapterMeta[address(adapter)].guard)
revert Errors.GuardCapReached();
}
Adapter(adapter).notify(msg.sender, tBalSubFee, true);
uint256 scale = level.collectDisabled() ? series[adapter][maturity].iscale : Adapter(adapter).scale();
uBal = tBalSubFee.fmul(scale);
lscales[adapter][maturity][msg.sender] = lscales[adapter][maturity][msg.sender] == 0
? scale
: _reweightLScale(
adapter,
maturity,
YT(series[adapter][maturity].yt).balanceOf(msg.sender),
uBal,
msg.sender,
scale
);
Token(series[adapter][maturity].pt).mint(msg.sender, uBal);
YT(series[adapter][maturity].yt).mint(msg.sender, uBal);
target.safeTransferFrom(msg.sender, adapter, tBal);
emit Issued(adapter, maturity, uBal, msg.sender);
}
function combine(
address adapter,
uint256 maturity,
uint256 uBal
) external nonReentrant whenNotPaused returns (uint256 tBal) {
if (!adapterMeta[adapter].enabled) revert Errors.InvalidAdapter();
if (!_exists(adapter, maturity)) revert Errors.SeriesDoesNotExist();
uint256 level = adapterMeta[adapter].level;
if (level.combineRestricted() && msg.sender != adapter) revert Errors.CombineRestricted();
Token(series[adapter][maturity].pt).burn(msg.sender, uBal);
uint256 collected = _collect(msg.sender, adapter, maturity, uBal, uBal, address(0));
uint256 cscale = series[adapter][maturity].mscale;
bool settled = _settled(adapter, maturity);
if (!settled) {
YT(series[adapter][maturity].yt).burn(msg.sender, uBal);
cscale = level.collectDisabled()
? series[adapter][maturity].iscale
: lscales[adapter][maturity][msg.sender];
}
tBal = uBal.fdiv(cscale);
ERC20(Adapter(adapter).target()).safeTransferFrom(adapter, msg.sender, tBal);
if (!settled) Adapter(adapter).notify(msg.sender, tBal, false);
unchecked {
tBal += collected;
}
emit Combined(adapter, maturity, tBal, msg.sender);
}
function redeem(
address adapter,
uint256 maturity,
uint256 uBal
) external nonReentrant whenNotPaused returns (uint256 tBal) {
if (!_settled(adapter, maturity)) revert Errors.NotSettled();
uint256 level = adapterMeta[adapter].level;
if (level.redeemRestricted() && msg.sender == adapter) revert Errors.RedeemRestricted();
Token(series[adapter][maturity].pt).burn(msg.sender, uBal);
uint256 zShare = FixedMath.WAD - series[adapter][maturity].tilt;
if (series[adapter][maturity].mscale.fdiv(series[adapter][maturity].maxscale) >= zShare) {
tBal = (uBal * zShare) / series[adapter][maturity].mscale;
} else {
tBal = uBal.fdiv(series[adapter][maturity].maxscale);
}
if (!level.redeemHookDisabled()) {
Adapter(adapter).onRedeem(uBal, series[adapter][maturity].mscale, series[adapter][maturity].maxscale, tBal);
}
ERC20(Adapter(adapter).target()).safeTransferFrom(adapter, msg.sender, tBal);
emit PTRedeemed(adapter, maturity, tBal);
}
function collect(
address usr,
address adapter,
uint256 maturity,
uint256 uBalTransfer,
address to
) external nonReentrant onlyYT(adapter, maturity) whenNotPaused returns (uint256 collected) {
uint256 uBal = YT(msg.sender).balanceOf(usr);
return _collect(usr, adapter, maturity, uBal, uBalTransfer > 0 ? uBalTransfer : uBal, to);
}
function _collect(
address usr,
address adapter,
uint256 maturity,
uint256 uBal,
uint256 uBalTransfer,
address to
) internal returns (uint256 collected) {
if (!_exists(adapter, maturity)) revert Errors.SeriesDoesNotExist();
if (!adapterMeta[adapter].enabled && !_settled(adapter, maturity)) revert Errors.InvalidAdapter();
Series memory _series = series[adapter][maturity];
uint256 lscale = lscales[adapter][maturity][usr];
uint256 level = adapterMeta[adapter].level;
if (level.collectDisabled()) {
if (_settled(adapter, maturity)) {
lscale = series[adapter][maturity].iscale;
} else {
return 0;
}
}
if (_settled(adapter, maturity)) {
_redeemYT(usr, adapter, maturity, uBal);
} else {
if (block.timestamp > maturity + SPONSOR_WINDOW) {
revert Errors.CollectNotSettled();
} else {
uint256 cscale = Adapter(adapter).scale();
if (cscale > _series.maxscale) {
_series.maxscale = cscale;
lscales[adapter][maturity][usr] = cscale;
} else {
lscales[adapter][maturity][usr] = _series.maxscale;
}
}
}
uint256 tBalNow = uBal.fdivUp(_series.maxscale);
uint256 tBalPrev = uBal.fdiv(lscale);
unchecked {
collected = tBalPrev > tBalNow ? tBalPrev - tBalNow : 0;
}
ERC20(Adapter(adapter).target()).safeTransferFrom(adapter, usr, collected);
Adapter(adapter).notify(usr, collected, false);
if (to != address(0)) {
uint256 ytBal = YT(_series.yt).balanceOf(to);
lscales[adapter][maturity][to] = ytBal > 0
? _reweightLScale(adapter, maturity, ytBal, uBalTransfer, to, _series.maxscale)
: _series.maxscale;
uint256 tBalTransfer = uBalTransfer.fdiv(_series.maxscale);
Adapter(adapter).notify(usr, tBalTransfer, false);
Adapter(adapter).notify(to, tBalTransfer, true);
}
series[adapter][maturity] = _series;
emit Collected(adapter, maturity, collected);
}
function _reweightLScale(
address adapter,
uint256 maturity,
uint256 ytBal,
uint256 uBal,
address receiver,
uint256 scale
) internal view returns (uint256) {
return (ytBal + uBal).fdiv((ytBal.fdiv(lscales[adapter][maturity][receiver]) + uBal.fdiv(scale)));
}
function _redeemYT(
address usr,
address adapter,
uint256 maturity,
uint256 uBal
) internal {
YT(series[adapter][maturity].yt).burn(usr, uBal);
uint256 tBal = 0;
uint256 zShare = FixedMath.WAD - series[adapter][maturity].tilt;
if (series[adapter][maturity].mscale.fdiv(series[adapter][maturity].maxscale) >= zShare) {
tBal = uBal.fdiv(series[adapter][maturity].maxscale) - (uBal * zShare) / series[adapter][maturity].mscale;
ERC20(Adapter(adapter).target()).safeTransferFrom(adapter, usr, tBal);
}
Adapter(adapter).notify(usr, uBal.fdivUp(series[adapter][maturity].maxscale), false);
emit YTRedeemed(adapter, maturity, tBal);
}
function setAdapter(address adapter, bool isOn) public requiresTrust {
_setAdapter(adapter, isOn);
}
function setGuard(address adapter, uint256 cap) external requiresTrust {
adapterMeta[adapter].guard = cap;
emit GuardChanged(adapter, cap);
}
function setGuarded(bool _guarded) external requiresTrust {
guarded = _guarded;
emit GuardedChanged(_guarded);
}
function setPeriphery(address _periphery) external requiresTrust {
periphery = _periphery;
emit PeripheryChanged(_periphery);
}
function setPaused(bool _paused) external requiresTrust {
_paused ? _pause() : _unpause();
}
function setPermissionless(bool _permissionless) external requiresTrust {
permissionless = _permissionless;
emit PermissionlessChanged(_permissionless);
}
function backfillScale(
address adapter,
uint256 maturity,
uint256 mscale,
address[] calldata _usrs,
uint256[] calldata _lscales
) external requiresTrust {
if (!_exists(adapter, maturity)) revert Errors.SeriesDoesNotExist();
uint256 cutoff = maturity + SPONSOR_WINDOW + SETTLEMENT_WINDOW;
if (block.timestamp <= cutoff) revert Errors.OutOfWindowBoundaries();
for (uint256 i = 0; i < _usrs.length; i++) {
lscales[adapter][maturity][_usrs[i]] = _lscales[i];
}
if (mscale > 0) {
Series memory _series = series[adapter][maturity];
series[adapter][maturity].mscale = mscale;
if (mscale > _series.maxscale) {
series[adapter][maturity].maxscale = mscale;
}
(address target, address stake, uint256 stakeSize) = Adapter(adapter).getStakeAndTarget();
address stakeDst = adapterMeta[adapter].enabled ? cup : _series.sponsor;
ERC20(target).safeTransferFrom(adapter, cup, _series.reward);
series[adapter][maturity].reward = 0;
ERC20(stake).safeTransferFrom(adapter, stakeDst, stakeSize);
}
emit Backfilled(adapter, maturity, mscale, _usrs, _lscales);
}
function _exists(address adapter, uint256 maturity) internal view returns (bool) {
return series[adapter][maturity].pt != address(0);
}
function _settled(address adapter, uint256 maturity) internal view returns (bool) {
return series[adapter][maturity].mscale > 0;
}
function _canBeSettled(address adapter, uint256 maturity) internal view returns (bool) {
uint256 cutoff = maturity + SPONSOR_WINDOW + SETTLEMENT_WINDOW;
if (msg.sender == series[adapter][maturity].sponsor) {
return maturity - SPONSOR_WINDOW <= block.timestamp && cutoff >= block.timestamp;
} else {
return maturity + SPONSOR_WINDOW < block.timestamp && cutoff >= block.timestamp;
}
}
function _isValid(address adapter, uint256 maturity) internal view returns (bool) {
(uint256 minm, uint256 maxm) = Adapter(adapter).getMaturityBounds();
if (maturity < block.timestamp + minm || maturity > block.timestamp + maxm) return false;
(, , uint256 day, uint256 hour, uint256 minute, uint256 second) = DateTime.timestampToDateTime(maturity);
if (hour != 0 || minute != 0 || second != 0) return false;
uint256 mode = Adapter(adapter).mode();
if (mode == 0) {
return day == 1;
}
if (mode == 1) {
return DateTime.getDayOfWeek(maturity) == 1;
}
return false;
}
function _setAdapter(address adapter, bool isOn) internal {
AdapterMeta memory am = adapterMeta[adapter];
if (am.enabled == isOn) revert Errors.ExistingValue();
am.enabled = isOn;
if (isOn && am.id == 0) {
am.id = ++adapterCounter;
adapterAddresses[am.id] = adapter;
}
am.level = uint248(Adapter(adapter).level());
adapterMeta[adapter] = am;
emit AdapterChanged(adapter, am.id, isOn);
}
function pt(address adapter, uint256 maturity) public view returns (address) {
return series[adapter][maturity].pt;
}
function yt(address adapter, uint256 maturity) public view returns (address) {
return series[adapter][maturity].yt;
}
function mscale(address adapter, uint256 maturity) public view returns (uint256) {
return series[adapter][maturity].mscale;
}
modifier onlyYT(address adapter, uint256 maturity) {
if (series[adapter][maturity].yt != msg.sender) revert Errors.OnlyYT();
_;
}
event Backfilled(
address indexed adapter,
uint256 indexed maturity,
uint256 mscale,
address[] _usrs,
uint256[] _lscales
);
event GuardChanged(address indexed adapter, uint256 cap);
event AdapterChanged(address indexed adapter, uint256 indexed id, bool indexed isOn);
event PeripheryChanged(address indexed periphery);
event SeriesInitialized(
address adapter,
uint256 indexed maturity,
address pt,
address yt,
address indexed sponsor,
address indexed target
);
event Issued(address indexed adapter, uint256 indexed maturity, uint256 balance, address indexed sender);
event Combined(address indexed adapter, uint256 indexed maturity, uint256 balance, address indexed sender);
event Collected(address indexed adapter, uint256 indexed maturity, uint256 collected);
event SeriesSettled(address indexed adapter, uint256 indexed maturity, address indexed settler);
event PTRedeemed(address indexed adapter, uint256 indexed maturity, uint256 redeemed);
event YTRedeemed(address indexed adapter, uint256 indexed maturity, uint256 redeemed);
event GuardedChanged(bool indexed guarded);
event PermissionlessChanged(bool indexed permissionless);
}
contract TokenHandler is Trust {
address public divider;
constructor() Trust(msg.sender) {}
function init(address _divider) external requiresTrust {
if (divider != address(0)) revert Errors.AlreadyInitialized();
divider = _divider;
}
function deploy(
address adapter,
uint248 id,
uint256 maturity
) external returns (address pt, address yt) {
if (msg.sender != divider) revert Errors.OnlyDivider();
ERC20 target = ERC20(Adapter(adapter).target());
uint8 decimals = target.decimals();
string memory symbol = target.symbol();
(string memory d, string memory m, string memory y) = DateTime.toDateString(maturity);
string memory date = DateTime.format(maturity);
string memory datestring = string(abi.encodePacked(d, "-", m, "-", y));
string memory adapterId = DateTime.uintToString(id);
pt = address(
new Token(
string(abi.encodePacked(date, " ", symbol, " Sense Principal Token, A", adapterId)),
string(abi.encodePacked("sP-", symbol, ":", datestring, ":", adapterId)),
decimals,
divider
)
);
yt = address(
new YT(
adapter,
maturity,
string(abi.encodePacked(date, " ", symbol, " Sense Yield Token, A", adapterId)),
string(abi.encodePacked("sY-", symbol, ":", datestring, ":", adapterId)),
decimals,
divider
)
);
}
}
文件 10 的 30:ERC20.sol
pragma solidity >=0.8.0;
abstract contract ERC20 {
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}
文件 11 的 30:Errors.sol
pragma solidity >=0.8.4;
library Errors {
error CombineRestricted();
error IssuanceRestricted();
error NotAuthorized();
error OnlyYT();
error OnlyDivider();
error OnlyPeriphery();
error OnlyPermissionless();
error RedeemRestricted();
error Untrusted();
error TokenNotSupported();
error FlashCallbackFailed();
error SenderNotEligible();
error TargetMismatch();
error TargetNotSupported();
error AlreadySettled();
error CollectNotSettled();
error GuardCapReached();
error IssuanceFeeCapExceeded();
error IssueOnSettle();
error NotSettled();
error AlreadyInitialized();
error DuplicateSeries();
error ExistingValue();
error InvalidAdapter();
error InvalidMaturity();
error InvalidParam();
error NotImplemented();
error OutOfWindowBoundaries();
error SeriesDoesNotExist();
error SwapTooSmall();
error TargetParamsNotSet();
error PoolParamsNotSet();
error PTParamsNotSet();
error FactoryNotSupported();
error FlashBorrowFailed();
error FlashUntrustedBorrower();
error FlashUntrustedLoanInitiator();
error UnexpectedSwapAmount();
error TooMuchLeftoverTarget();
error AdapterNotSet();
error FailedBecomeAdmin();
error FailedAddTargetMarket();
error FailedToAddPTMarket();
error FailedAddLpMarket();
error OracleNotReady();
error PoolAlreadyDeployed();
error PoolNotDeployed();
error PoolNotSet();
error SeriesNotQueued();
error TargetExists();
error TargetNotInFuse();
error MintFailed();
error RedeemFailed();
error TransferFailed();
}
文件 12 的 30:FixedMath.sol
pragma solidity 0.8.11;
library FixedMath {
uint256 internal constant WAD = 1e18;
uint256 internal constant RAY = 1e27;
function fmul(
uint256 x,
uint256 y,
uint256 baseUnit
) internal pure returns (uint256) {
return mulDivDown(x, y, baseUnit);
}
function fmul(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, y, WAD);
}
function fmulUp(
uint256 x,
uint256 y,
uint256 baseUnit
) internal pure returns (uint256) {
return mulDivUp(x, y, baseUnit);
}
function fmulUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, y, WAD);
}
function fdiv(
uint256 x,
uint256 y,
uint256 baseUnit
) internal pure returns (uint256) {
return mulDivDown(x, baseUnit, y);
}
function fdiv(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, WAD, y);
}
function fdivUp(
uint256 x,
uint256 y,
uint256 baseUnit
) internal pure returns (uint256) {
return mulDivUp(x, baseUnit, y);
}
function fdivUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, WAD, y);
}
function mulDivDown(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
assembly {
z := mul(x, y)
if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
revert(0, 0)
}
z := div(z, denominator)
}
}
function mulDivUp(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
assembly {
z := mul(x, y)
if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
revert(0, 0)
}
z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))
}
}
}
文件 13 的 30:IERC3156FlashBorrower.sol
pragma solidity ^0.8.0;
interface IERC3156FlashBorrower {
function onFlashLoan(
address initiator,
address token,
uint256 amount,
uint256 fee,
bytes calldata data
) external returns (bytes32);
}
文件 14 的 30:IERC3156FlashLender.sol
pragma solidity ^0.8.0;
import "./IERC3156FlashBorrower.sol";
interface IERC3156FlashLender {
function maxFlashLoan(address token) external view returns (uint256);
function flashFee(address token, uint256 amount) external view returns (uint256);
function flashLoan(
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
) external returns (bool);
}
文件 15 的 30:LP.sol
pragma solidity 0.8.11;
import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol";
import { PriceOracle } from "../external/PriceOracle.sol";
import { CToken } from "../external/CToken.sol";
import { BalancerVault } from "@sense-finance/v1-core/src/external/balancer/Vault.sol";
import { BalancerPool } from "@sense-finance/v1-core/src/external/balancer/Pool.sol";
import { Trust } from "@sense-finance/v1-utils/src/Trust.sol";
import { FixedMath } from "@sense-finance/v1-core/src/external/FixedMath.sol";
import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol";
import { BaseAdapter as Adapter } from "@sense-finance/v1-core/src/adapters/BaseAdapter.sol";
interface SpaceLike {
function getFairBPTPrice(uint256 ptTwapDuration) external view returns (uint256);
function adapter() external view returns (address);
}
contract LPOracle is PriceOracle, Trust {
using FixedMath for uint256;
mapping(address => address) public pools;
uint256 public twapPeriod;
constructor() Trust(msg.sender) {
twapPeriod = 5.5 hours;
}
function setTwapPeriod(uint256 _twapPeriod) external requiresTrust {
twapPeriod = _twapPeriod;
}
function getUnderlyingPrice(CToken cToken) external view override returns (uint256) {
return _price(cToken.underlying());
}
function price(address pt) external view override returns (uint256) {
return _price(pt);
}
function _price(address _pool) internal view returns (uint256) {
SpaceLike pool = SpaceLike(_pool);
address target = Adapter(pool.adapter()).target();
return pool.getFairBPTPrice(twapPeriod).fmul(PriceOracle(msg.sender).price(target));
}
}
文件 16 的 30:Levels.sol
pragma solidity >=0.7.0;
library Levels {
uint256 private constant _INIT_BIT = 0x1;
uint256 private constant _ISSUE_BIT = 0x2;
uint256 private constant _COMBINE_BIT = 0x4;
uint256 private constant _COLLECT_BIT = 0x8;
uint256 private constant _REDEEM_BIT = 0x10;
uint256 private constant _REDEEM_HOOK_BIT = 0x20;
function initRestricted(uint256 level) internal pure returns (bool) {
return level & _INIT_BIT != _INIT_BIT;
}
function issueRestricted(uint256 level) internal pure returns (bool) {
return level & _ISSUE_BIT != _ISSUE_BIT;
}
function combineRestricted(uint256 level) internal pure returns (bool) {
return level & _COMBINE_BIT != _COMBINE_BIT;
}
function collectDisabled(uint256 level) internal pure returns (bool) {
return level & _COLLECT_BIT != _COLLECT_BIT;
}
function redeemRestricted(uint256 level) internal pure returns (bool) {
return level & _REDEEM_BIT != _REDEEM_BIT;
}
function redeemHookDisabled(uint256 level) internal pure returns (bool) {
return level & _REDEEM_HOOK_BIT != _REDEEM_HOOK_BIT;
}
}
文件 17 的 30:PT.sol
pragma solidity 0.8.11;
import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol";
import { PriceOracle } from "../external/PriceOracle.sol";
import { CToken } from "../external/CToken.sol";
import { BalancerOracle } from "../external/BalancerOracle.sol";
import { BalancerVault } from "@sense-finance/v1-core/src/external/balancer/Vault.sol";
import { Trust } from "@sense-finance/v1-utils/src/Trust.sol";
import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol";
import { Token } from "@sense-finance/v1-core/src/tokens/Token.sol";
import { FixedMath } from "@sense-finance/v1-core/src/external/FixedMath.sol";
import { BaseAdapter as Adapter } from "@sense-finance/v1-core/src/adapters/BaseAdapter.sol";
interface SpaceLike {
function getImpliedRateFromPrice(uint256 pTPriceInTarget) external view returns (uint256);
function getPriceFromImpliedRate(uint256 impliedRate) external view returns (uint256);
function getTotalSamples() external pure returns (uint256);
function adapter() external view returns (address);
}
contract PTOracle is PriceOracle, Trust {
using FixedMath for uint256;
mapping(address => address) public pools;
uint256 public floorRate;
uint256 public twapPeriod;
constructor() Trust(msg.sender) {
floorRate = 3e18;
twapPeriod = 5.5 hours;
}
function setFloorRate(uint256 _floorRate) external requiresTrust {
floorRate = _floorRate;
}
function setTwapPeriod(uint256 _twapPeriod) external requiresTrust {
twapPeriod = _twapPeriod;
}
function setPrincipal(address pt, address pool) external requiresTrust {
pools[pt] = pool;
}
function getUnderlyingPrice(CToken cToken) external view override returns (uint256) {
return _price(cToken.underlying());
}
function price(address pt) external view override returns (uint256) {
return _price(pt);
}
function _price(address pt) internal view returns (uint256) {
BalancerOracle pool = BalancerOracle(pools[address(pt)]);
if (pool == BalancerOracle(address(0))) revert Errors.PoolNotSet();
(, , , , , , uint256 sampleTs) = pool.getSample(SpaceLike(address(pool)).getTotalSamples() - 1);
if (sampleTs == 0) revert Errors.OracleNotReady();
BalancerOracle.OracleAverageQuery[] memory queries = new BalancerOracle.OracleAverageQuery[](1);
queries[0] = BalancerOracle.OracleAverageQuery({
variable: BalancerOracle.Variable.BPT_PRICE,
secs: twapPeriod,
ago: 1 hours
});
uint256[] memory results = pool.getTimeWeightedAverage(queries);
uint256 impliedRate = results[0];
if (impliedRate > floorRate) {
impliedRate = floorRate;
}
address target = Adapter(SpaceLike(address(pool)).adapter()).target();
return
SpaceLike(address(pool)).getPriceFromImpliedRate(impliedRate).fmul(PriceOracle(msg.sender).price(target));
}
}
文件 18 的 30:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
function paused() public view virtual returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 19 的 30:Periphery.sol
pragma solidity 0.8.11;
import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol";
import { SafeTransferLib } from "@rari-capital/solmate/src/utils/SafeTransferLib.sol";
import { FixedMath } from "./external/FixedMath.sol";
import { BalancerVault, IAsset } from "./external/balancer/Vault.sol";
import { BalancerPool } from "./external/balancer/Pool.sol";
import { IERC3156FlashBorrower } from "./external/flashloan/IERC3156FlashBorrower.sol";
import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol";
import { Levels } from "@sense-finance/v1-utils/src/libs/Levels.sol";
import { Trust } from "@sense-finance/v1-utils/src/Trust.sol";
import { BaseAdapter as Adapter } from "./adapters/BaseAdapter.sol";
import { BaseFactory as AdapterFactory } from "./adapters/BaseFactory.sol";
import { Divider } from "./Divider.sol";
import { PoolManager } from "@sense-finance/v1-fuse/src/PoolManager.sol";
interface SpaceFactoryLike {
function create(address, uint256) external returns (address);
function pools(address adapter, uint256 maturity) external view returns (address);
}
contract Periphery is Trust, IERC3156FlashBorrower {
using FixedMath for uint256;
using SafeTransferLib for ERC20;
using Levels for uint256;
uint256 public constant MIN_YT_SWAP_IN = 0.000001e18;
uint256 public constant PRICE_ESTIMATE_ACCEPTABLE_ERROR = 0.00000001e18;
Divider public immutable divider;
BalancerVault public immutable balancerVault;
PoolManager public poolManager;
SpaceFactoryLike public spaceFactory;
mapping(address => bool) public factories;
mapping(address => bool) public verified;
struct PoolLiquidity {
ERC20[] tokens;
uint256[] amounts;
uint256 minBptOut;
}
constructor(
address _divider,
address _poolManager,
address _spaceFactory,
address _balancerVault
) Trust(msg.sender) {
divider = Divider(_divider);
poolManager = PoolManager(_poolManager);
spaceFactory = SpaceFactoryLike(_spaceFactory);
balancerVault = BalancerVault(_balancerVault);
}
function sponsorSeries(
address adapter,
uint256 maturity,
bool withPool
) external returns (address pt, address yt) {
(, address stake, uint256 stakeSize) = Adapter(adapter).getStakeAndTarget();
ERC20(stake).safeTransferFrom(msg.sender, address(this), stakeSize);
ERC20(stake).approve(address(divider), stakeSize);
(pt, yt) = divider.initSeries(adapter, maturity, msg.sender);
if (verified[adapter]) {
poolManager.queueSeries(adapter, maturity, spaceFactory.create(adapter, maturity));
} else {
if (withPool) {
spaceFactory.create(adapter, maturity);
}
}
emit SeriesSponsored(adapter, maturity, msg.sender);
}
function deployAdapter(
address f,
address target,
bytes memory data
) external returns (address adapter) {
if (!factories[f]) revert Errors.FactoryNotSupported();
adapter = AdapterFactory(f).deployAdapter(target, data);
emit AdapterDeployed(adapter);
_verifyAdapter(adapter, true);
_onboardAdapter(adapter, true);
}
function swapTargetForPTs(
address adapter,
uint256 maturity,
uint256 tBal,
uint256 minAccepted
) external returns (uint256 ptBal) {
ERC20(Adapter(adapter).target()).safeTransferFrom(msg.sender, address(this), tBal);
return _swapTargetForPTs(adapter, maturity, tBal, minAccepted);
}
function swapUnderlyingForPTs(
address adapter,
uint256 maturity,
uint256 uBal,
uint256 minAccepted
) external returns (uint256 ptBal) {
ERC20 underlying = ERC20(Adapter(adapter).underlying());
underlying.safeTransferFrom(msg.sender, address(this), uBal);
uint256 tBal = Adapter(adapter).wrapUnderlying(uBal);
ptBal = _swapTargetForPTs(adapter, maturity, tBal, minAccepted);
}
function swapTargetForYTs(
address adapter,
uint256 maturity,
uint256 targetIn,
uint256 targetToBorrow,
uint256 minOut
) external returns (uint256 targetBal, uint256 ytBal) {
ERC20(Adapter(adapter).target()).safeTransferFrom(msg.sender, address(this), targetIn);
(targetBal, ytBal) = _flashBorrowAndSwapToYTs(adapter, maturity, targetIn, targetToBorrow, minOut);
ERC20(Adapter(adapter).target()).safeTransfer(msg.sender, targetBal);
ERC20(divider.yt(adapter, maturity)).safeTransfer(msg.sender, ytBal);
}
function swapUnderlyingForYTs(
address adapter,
uint256 maturity,
uint256 underlyingIn,
uint256 targetToBorrow,
uint256 minOut
) external returns (uint256 targetBal, uint256 ytBal) {
ERC20 underlying = ERC20(Adapter(adapter).underlying());
underlying.safeTransferFrom(msg.sender, address(this), underlyingIn);
uint256 targetIn = Adapter(adapter).wrapUnderlying(underlyingIn);
(targetBal, ytBal) = _flashBorrowAndSwapToYTs(adapter, maturity, targetIn, targetToBorrow, minOut);
ERC20(Adapter(adapter).target()).safeTransfer(msg.sender, targetBal);
ERC20(divider.yt(adapter, maturity)).safeTransfer(msg.sender, ytBal);
}
function swapPTsForTarget(
address adapter,
uint256 maturity,
uint256 ptBal,
uint256 minAccepted
) external returns (uint256 tBal) {
tBal = _swapPTsForTarget(adapter, maturity, ptBal, minAccepted);
ERC20(Adapter(adapter).target()).safeTransfer(msg.sender, tBal);
}
function swapPTsForUnderlying(
address adapter,
uint256 maturity,
uint256 ptBal,
uint256 minAccepted
) external returns (uint256 uBal) {
uint256 tBal = _swapPTsForTarget(adapter, maturity, ptBal, minAccepted);
uBal = Adapter(adapter).unwrapTarget(tBal);
ERC20(Adapter(adapter).underlying()).safeTransfer(msg.sender, uBal);
}
function swapYTsForTarget(
address adapter,
uint256 maturity,
uint256 ytBal
) external returns (uint256 tBal) {
tBal = _swapYTsForTarget(msg.sender, adapter, maturity, ytBal);
ERC20(Adapter(adapter).target()).safeTransfer(msg.sender, tBal);
}
function swapYTsForUnderlying(
address adapter,
uint256 maturity,
uint256 ytBal
) external returns (uint256 uBal) {
uint256 tBal = _swapYTsForTarget(msg.sender, adapter, maturity, ytBal);
uBal = Adapter(adapter).unwrapTarget(tBal);
ERC20(Adapter(adapter).underlying()).safeTransfer(msg.sender, uBal);
}
function addLiquidityFromTarget(
address adapter,
uint256 maturity,
uint256 tBal,
uint8 mode,
uint256 minBptOut
)
external
returns (
uint256 tAmount,
uint256 issued,
uint256 lpShares
)
{
ERC20(Adapter(adapter).target()).safeTransferFrom(msg.sender, address(this), tBal);
(tAmount, issued, lpShares) = _addLiquidity(adapter, maturity, tBal, mode, minBptOut);
}
function addLiquidityFromUnderlying(
address adapter,
uint256 maturity,
uint256 uBal,
uint8 mode,
uint256 minBptOut
)
external
returns (
uint256 tAmount,
uint256 issued,
uint256 lpShares
)
{
ERC20 underlying = ERC20(Adapter(adapter).underlying());
underlying.safeTransferFrom(msg.sender, address(this), uBal);
uint256 tBal = Adapter(adapter).wrapUnderlying(uBal);
(tAmount, issued, lpShares) = _addLiquidity(adapter, maturity, tBal, mode, minBptOut);
}
function removeLiquidity(
address adapter,
uint256 maturity,
uint256 lpBal,
uint256[] memory minAmountsOut,
uint256 minAccepted,
bool intoTarget
) external returns (uint256 tBal, uint256 ptBal) {
(tBal, ptBal) = _removeLiquidity(adapter, maturity, lpBal, minAmountsOut, minAccepted, intoTarget);
ERC20(Adapter(adapter).target()).safeTransfer(msg.sender, tBal);
}
function removeLiquidityAndUnwrapTarget(
address adapter,
uint256 maturity,
uint256 lpBal,
uint256[] memory minAmountsOut,
uint256 minAccepted,
bool intoTarget
) external returns (uint256 uBal, uint256 ptBal) {
uint256 tBal;
(tBal, ptBal) = _removeLiquidity(adapter, maturity, lpBal, minAmountsOut, minAccepted, intoTarget);
ERC20(Adapter(adapter).underlying()).safeTransfer(msg.sender, uBal = Adapter(adapter).unwrapTarget(tBal));
}
function migrateLiquidity(
address srcAdapter,
address dstAdapter,
uint256 srcMaturity,
uint256 dstMaturity,
uint256 lpBal,
uint256[] memory minAmountsOut,
uint256 minAccepted,
uint8 mode,
bool intoTarget,
uint256 minBptOut
)
external
returns (
uint256 tAmount,
uint256 issued,
uint256 lpShares,
uint256 ptBal
)
{
if (Adapter(srcAdapter).target() != Adapter(dstAdapter).target()) revert Errors.TargetMismatch();
uint256 tBal;
(tBal, ptBal) = _removeLiquidity(srcAdapter, srcMaturity, lpBal, minAmountsOut, minAccepted, intoTarget);
(tAmount, issued, lpShares) = _addLiquidity(dstAdapter, dstMaturity, tBal, mode, minBptOut);
}
function setFactory(address f, bool isOn) external requiresTrust {
if (factories[f] == isOn) revert Errors.ExistingValue();
factories[f] = isOn;
emit FactoryChanged(f, isOn);
}
function setSpaceFactory(address newSpaceFactory) external requiresTrust {
spaceFactory = SpaceFactoryLike(newSpaceFactory);
emit SpaceFactoryChanged(newSpaceFactory);
}
function setPoolManager(address newPoolManager) external requiresTrust {
poolManager = PoolManager(newPoolManager);
emit PoolManagerChanged(newPoolManager);
}
function verifyAdapter(address adapter, bool addToPool) public requiresTrust {
_verifyAdapter(adapter, addToPool);
}
function _verifyAdapter(address adapter, bool addToPool) private {
verified[adapter] = true;
if (addToPool) poolManager.addTarget(Adapter(adapter).target(), adapter);
emit AdapterVerified(adapter);
}
function onboardAdapter(address adapter, bool addAdapter) public {
if (!divider.permissionless() && !isTrusted[msg.sender]) revert Errors.OnlyPermissionless();
_onboardAdapter(adapter, addAdapter);
}
function _onboardAdapter(address adapter, bool addAdapter) private {
ERC20 target = ERC20(Adapter(adapter).target());
target.approve(address(divider), type(uint256).max);
target.approve(address(adapter), type(uint256).max);
ERC20(Adapter(adapter).underlying()).approve(address(adapter), type(uint256).max);
if (addAdapter) divider.addAdapter(adapter);
emit AdapterOnboarded(adapter);
}
function _swap(
address assetIn,
address assetOut,
uint256 amountIn,
bytes32 poolId,
uint256 minAccepted
) internal returns (uint256 amountOut) {
ERC20(assetIn).approve(address(balancerVault), amountIn);
BalancerVault.SingleSwap memory request = BalancerVault.SingleSwap({
poolId: poolId,
kind: BalancerVault.SwapKind.GIVEN_IN,
assetIn: IAsset(assetIn),
assetOut: IAsset(assetOut),
amount: amountIn,
userData: hex""
});
BalancerVault.FundManagement memory funds = BalancerVault.FundManagement({
sender: address(this),
fromInternalBalance: false,
recipient: payable(address(this)),
toInternalBalance: false
});
amountOut = balancerVault.swap(request, funds, minAccepted, type(uint256).max);
emit Swapped(msg.sender, poolId, assetIn, assetOut, amountIn, amountOut, msg.sig);
}
function _swapPTsForTarget(
address adapter,
uint256 maturity,
uint256 ptBal,
uint256 minAccepted
) internal returns (uint256 tBal) {
address principalToken = divider.pt(adapter, maturity);
ERC20(principalToken).safeTransferFrom(msg.sender, address(this), ptBal);
BalancerPool pool = BalancerPool(spaceFactory.pools(adapter, maturity));
tBal = _swap(principalToken, Adapter(adapter).target(), ptBal, pool.getPoolId(), minAccepted);
}
function _swapTargetForPTs(
address adapter,
uint256 maturity,
uint256 tBal,
uint256 minAccepted
) internal returns (uint256 ptBal) {
address principalToken = divider.pt(adapter, maturity);
BalancerPool pool = BalancerPool(spaceFactory.pools(adapter, maturity));
ptBal = _swap(Adapter(adapter).target(), principalToken, tBal, pool.getPoolId(), minAccepted);
ERC20(principalToken).safeTransfer(msg.sender, ptBal);
}
function _swapYTsForTarget(
address sender,
address adapter,
uint256 maturity,
uint256 ytBal
) internal returns (uint256 tBal) {
address yt = divider.yt(adapter, maturity);
if (ytBal * 10**(18 - ERC20(yt).decimals()) <= MIN_YT_SWAP_IN) revert Errors.SwapTooSmall();
BalancerPool pool = BalancerPool(spaceFactory.pools(adapter, maturity));
if (sender != address(this)) ERC20(yt).safeTransferFrom(msg.sender, address(this), ytBal);
bytes32 poolId = pool.getPoolId();
(uint256 pti, uint256 targeti) = pool.getIndices();
(ERC20[] memory tokens, uint256[] memory balances, ) = balancerVault.getPoolTokens(poolId);
uint256 targetToBorrow = BalancerPool(pool).onSwap(
BalancerPool.SwapRequest({
kind: BalancerVault.SwapKind.GIVEN_OUT,
tokenIn: tokens[targeti],
tokenOut: tokens[pti],
amount: ytBal,
poolId: poolId,
lastChangeBlock: 0,
from: address(0),
to: address(0),
userData: ""
}),
balances[targeti],
balances[pti]
);
tBal = _flashBorrowAndSwapFromYTs(adapter, maturity, ytBal, targetToBorrow);
}
function _addLiquidity(
address adapter,
uint256 maturity,
uint256 tBal,
uint8 mode,
uint256 minBptOut
)
internal
returns (
uint256 tAmount,
uint256 issued,
uint256 lpShares
)
{
(issued, lpShares) = _computeIssueAddLiq(adapter, maturity, tBal, minBptOut);
if (issued > 0) {
if (mode == 0) {
tAmount = _swapYTsForTarget(address(this), adapter, maturity, issued);
ERC20(Adapter(adapter).target()).safeTransfer(msg.sender, tAmount);
} else {
ERC20(divider.yt(adapter, maturity)).safeTransfer(msg.sender, issued);
}
}
}
function _computeIssueAddLiq(
address adapter,
uint256 maturity,
uint256 tBal,
uint256 minBptOut
) internal returns (uint256 issued, uint256 lpShares) {
BalancerPool pool = BalancerPool(spaceFactory.pools(adapter, maturity));
(ERC20[] memory tokens, uint256[] memory balances, ) = balancerVault.getPoolTokens(pool.getPoolId());
(uint256 pti, uint256 targeti) = pool.getIndices();
bool ptInitialized = balances[pti] != 0;
uint256 ptBalInTarget = ptInitialized ? _computeTarget(adapter, balances[pti], balances[targeti], tBal) : 0;
issued = ptBalInTarget > 0 ? divider.issue(adapter, maturity, ptBalInTarget) : 0;
uint256[] memory amounts = new uint256[](2);
amounts[targeti] = tBal - ptBalInTarget;
amounts[pti] = issued;
lpShares = _addLiquidityToSpace(pool, PoolLiquidity(tokens, amounts, minBptOut));
}
function _computeTarget(
address adapter,
uint256 ptiBal,
uint256 targetiBal,
uint256 tBal
) internal returns (uint256 tBalForIssuance) {
return
tBal.fmul(
ptiBal.fdiv(
Adapter(adapter).scale().fmul(FixedMath.WAD - Adapter(adapter).ifee()).fmul(targetiBal) + ptiBal
)
);
}
function _removeLiquidity(
address adapter,
uint256 maturity,
uint256 lpBal,
uint256[] memory minAmountsOut,
uint256 minAccepted,
bool intoTarget
) internal returns (uint256 tBal, uint256 ptBal) {
address target = Adapter(adapter).target();
address pt = divider.pt(adapter, maturity);
BalancerPool pool = BalancerPool(spaceFactory.pools(adapter, maturity));
bytes32 poolId = pool.getPoolId();
ERC20(address(pool)).safeTransferFrom(msg.sender, address(this), lpBal);
uint256 _ptBal;
(tBal, _ptBal) = _removeLiquidityFromSpace(poolId, pt, target, minAmountsOut, lpBal);
if (divider.mscale(adapter, maturity) > 0) {
if (uint256(Adapter(adapter).level()).redeemRestricted()) {
ptBal = _ptBal;
} else {
tBal += divider.redeem(adapter, maturity, _ptBal);
}
} else {
if (_ptBal > 0 && intoTarget) {
tBal += _swap(pt, target, _ptBal, poolId, minAccepted);
} else {
ptBal = _ptBal;
}
}
if (ptBal > 0) ERC20(pt).safeTransfer(msg.sender, ptBal);
}
function _flashBorrowAndSwapFromYTs(
address adapter,
uint256 maturity,
uint256 ytBalIn,
uint256 amountToBorrow
) internal returns (uint256 tBal) {
ERC20 target = ERC20(Adapter(adapter).target());
uint256 decimals = target.decimals();
uint256 acceptableError = decimals < 9 ? 1 : PRICE_ESTIMATE_ACCEPTABLE_ERROR / 10**(18 - decimals);
bytes memory data = abi.encode(adapter, uint256(maturity), ytBalIn, ytBalIn - acceptableError, true);
bool result = Adapter(adapter).flashLoan(this, address(target), amountToBorrow, data);
if (!result) revert Errors.FlashBorrowFailed();
tBal = target.balanceOf(address(this));
}
function _flashBorrowAndSwapToYTs(
address adapter,
uint256 maturity,
uint256 targetIn,
uint256 amountToBorrow,
uint256 minOut
) internal returns (uint256 targetBal, uint256 ytBal) {
bytes memory data = abi.encode(adapter, uint256(maturity), targetIn, minOut, false);
bool result = Adapter(adapter).flashLoan(this, Adapter(adapter).target(), amountToBorrow, data);
if (!result) revert Errors.FlashBorrowFailed();
targetBal = ERC20(Adapter(adapter).target()).balanceOf(address(this));
ytBal = ERC20(divider.yt(adapter, maturity)).balanceOf(address(this));
emit YTsPurchased(msg.sender, adapter, maturity, targetIn, targetBal, ytBal);
}
function onFlashLoan(
address initiator,
address,
uint256 amountBorrrowed,
uint256,
bytes calldata data
) external returns (bytes32) {
(address adapter, uint256 maturity, uint256 amountIn, uint256 minOut, bool ytToTarget) = abi.decode(
data,
(address, uint256, uint256, uint256, bool)
);
if (msg.sender != address(adapter)) revert Errors.FlashUntrustedBorrower();
if (initiator != address(this)) revert Errors.FlashUntrustedLoanInitiator();
BalancerPool pool = BalancerPool(spaceFactory.pools(adapter, maturity));
if (ytToTarget) {
ERC20 target = ERC20(Adapter(adapter).target());
uint256 ptBal = _swap(
address(target),
divider.pt(adapter, maturity),
target.balanceOf(address(this)),
pool.getPoolId(),
minOut
);
divider.combine(adapter, maturity, ptBal < amountIn ? ptBal : amountIn);
} else {
divider.issue(adapter, maturity, amountIn + amountBorrrowed);
ERC20 pt = ERC20(divider.pt(adapter, maturity));
_swap(
address(pt),
Adapter(adapter).target(),
pt.balanceOf(address(this)),
pool.getPoolId(),
minOut
);
}
return keccak256("ERC3156FlashBorrower.onFlashLoan");
}
function _addLiquidityToSpace(BalancerPool pool, PoolLiquidity memory liq) internal returns (uint256 lpBal) {
bytes32 poolId = pool.getPoolId();
IAsset[] memory assets = _convertERC20sToAssets(liq.tokens);
for (uint8 i; i < liq.tokens.length; i++) {
liq.tokens[i].approve(address(balancerVault), liq.amounts[i]);
}
BalancerVault.JoinPoolRequest memory request = BalancerVault.JoinPoolRequest({
assets: assets,
maxAmountsIn: liq.amounts,
userData: abi.encode(liq.amounts, liq.minBptOut),
fromInternalBalance: false
});
balancerVault.joinPool(poolId, address(this), msg.sender, request);
lpBal = ERC20(address(pool)).balanceOf(msg.sender);
}
function _removeLiquidityFromSpace(
bytes32 poolId,
address pt,
address target,
uint256[] memory minAmountsOut,
uint256 lpBal
) internal returns (uint256 tBal, uint256 ptBal) {
(ERC20[] memory tokens, , ) = balancerVault.getPoolTokens(poolId);
IAsset[] memory assets = _convertERC20sToAssets(tokens);
BalancerVault.ExitPoolRequest memory request = BalancerVault.ExitPoolRequest({
assets: assets,
minAmountsOut: minAmountsOut,
userData: abi.encode(lpBal),
toInternalBalance: false
});
balancerVault.exitPool(poolId, address(this), payable(address(this)), request);
tBal = ERC20(target).balanceOf(address(this));
ptBal = ERC20(pt).balanceOf(address(this));
}
function _convertERC20sToAssets(ERC20[] memory tokens) internal pure returns (IAsset[] memory assets) {
assembly {
assets := tokens
}
}
event FactoryChanged(address indexed factory, bool indexed isOn);
event SpaceFactoryChanged(address newSpaceFactory);
event PoolManagerChanged(address newPoolManager);
event SeriesSponsored(address indexed adapter, uint256 indexed maturity, address indexed sponsor);
event AdapterDeployed(address indexed adapter);
event AdapterOnboarded(address indexed adapter);
event AdapterVerified(address indexed adapter);
event YTsPurchased(
address indexed sender,
address adapter,
uint256 maturity,
uint256 targetIn,
uint256 targetReturned,
uint256 ytOut
);
event Swapped(
address indexed sender,
bytes32 indexed poolId,
address assetIn,
address assetOut,
uint256 amountIn,
uint256 amountOut,
bytes4 indexed sig
);
}
文件 20 的 30:Pool.sol
pragma solidity 0.8.11;
import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol";
import { BalancerVault } from "./Vault.sol";
interface BalancerPool {
function getTimeWeightedAverage(OracleAverageQuery[] memory queries)
external
view
returns (uint256[] memory results);
enum Variable {
PAIR_PRICE,
BPT_PRICE,
INVARIANT
}
struct OracleAverageQuery {
Variable variable;
uint256 secs;
uint256 ago;
}
function getSample(uint256 index)
external
view
returns (
int256 logPairPrice,
int256 accLogPairPrice,
int256 logBptPrice,
int256 accLogBptPrice,
int256 logInvariant,
int256 accLogInvariant,
uint256 timestamp
);
function getPoolId() external view returns (bytes32);
function getVault() external view returns (address);
function totalSupply() external view returns (uint256);
struct SwapRequest {
BalancerVault.SwapKind kind;
ERC20 tokenIn;
ERC20 tokenOut;
uint256 amount;
bytes32 poolId;
uint256 lastChangeBlock;
address from;
address to;
bytes userData;
}
function onSwap(
SwapRequest memory swapRequest,
uint256 currentBalanceTokenIn,
uint256 currentBalanceTokenOut
) external returns (uint256 amount);
function getIndices() external view returns (uint256 pti, uint256 targeti);
}
文件 21 的 30:PoolManager.sol
pragma solidity 0.8.11;
import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol";
import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol";
import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol";
import { PriceOracle } from "./external/PriceOracle.sol";
import { BalancerOracle } from "./external/BalancerOracle.sol";
import { UnderlyingOracle } from "./oracles/Underlying.sol";
import { TargetOracle } from "./oracles/Target.sol";
import { PTOracle } from "./oracles/PT.sol";
import { LPOracle } from "./oracles/LP.sol";
import { Trust } from "@sense-finance/v1-utils/src/Trust.sol";
import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol";
import { Divider } from "@sense-finance/v1-core/src/Divider.sol";
import { BaseAdapter as Adapter } from "@sense-finance/v1-core/src/adapters/BaseAdapter.sol";
interface FuseDirectoryLike {
function deployPool(
string memory name,
address implementation,
bool enforceWhitelist,
uint256 closeFactor,
uint256 liquidationIncentive,
address priceOracle
) external returns (uint256, address);
}
interface ComptrollerLike {
function _deployMarket(
bool isCEther,
bytes calldata constructorData,
uint256 collateralFactorMantissa
) external returns (uint256);
function _acceptAdmin() external returns (uint256);
function cTokensByUnderlying(address underlying) external view returns (address);
function markets(address cToken) external view returns (bool, uint256);
function _setBorrowPaused(address cToken, bool state) external returns (bool);
}
interface MasterOracleLike {
function initialize(
address[] memory underlyings,
PriceOracle[] memory _oracles,
PriceOracle _defaultOracle,
address _admin,
bool _canAdminOverwrite
) external;
function add(address[] calldata underlyings, PriceOracle[] calldata _oracles) external;
function getUnderlyingPrice(address cToken) external view returns (uint256);
}
contract PoolManager is Trust {
address public immutable comptrollerImpl;
address public immutable cERC20Impl;
address public immutable fuseDirectory;
address public immutable divider;
address public immutable oracleImpl;
address public immutable targetOracle;
address public immutable ptOracle;
address public immutable lpOracle;
address public immutable underlyingOracle;
address public comptroller;
address public masterOracle;
AssetParams public targetParams;
AssetParams public ptParams;
AssetParams public lpTokenParams;
mapping(address => mapping(uint256 => Series)) public sSeries;
enum SeriesStatus {
NONE,
QUEUED,
ADDED
}
struct AssetParams {
address irModel;
uint256 reserveFactor;
uint256 collateralFactor;
}
struct Series {
SeriesStatus status;
address pool;
}
constructor(
address _fuseDirectory,
address _comptrollerImpl,
address _cERC20Impl,
address _divider,
address _oracleImpl
) Trust(msg.sender) {
fuseDirectory = _fuseDirectory;
comptrollerImpl = _comptrollerImpl;
cERC20Impl = _cERC20Impl;
divider = _divider;
oracleImpl = _oracleImpl;
targetOracle = address(new TargetOracle());
ptOracle = address(new PTOracle());
lpOracle = address(new LPOracle());
underlyingOracle = address(new UnderlyingOracle());
}
function deployPool(
string calldata name,
uint256 closeFactor,
uint256 liqIncentive,
address fallbackOracle
) external requiresTrust returns (uint256 _poolIndex, address _comptroller) {
masterOracle = Clones.cloneDeterministic(oracleImpl, Bytes32AddressLib.fillLast12Bytes(address(this)));
MasterOracleLike(masterOracle).initialize(
new address[](0),
new PriceOracle[](0),
PriceOracle(fallbackOracle),
address(this),
true
);
(_poolIndex, _comptroller) = FuseDirectoryLike(fuseDirectory).deployPool(
name,
comptrollerImpl,
false,
closeFactor,
liqIncentive,
masterOracle
);
uint256 err = ComptrollerLike(_comptroller)._acceptAdmin();
if (err != 0) revert Errors.FailedBecomeAdmin();
comptroller = _comptroller;
emit PoolDeployed(name, _comptroller, _poolIndex, closeFactor, liqIncentive);
}
function addTarget(address target, address adapter) external requiresTrust returns (address cTarget) {
if (comptroller == address(0)) revert Errors.PoolNotDeployed();
if (targetParams.irModel == address(0)) revert Errors.TargetParamsNotSet();
address underlying = Adapter(adapter).underlying();
address[] memory underlyings = new address[](2);
underlyings[0] = target;
underlyings[1] = underlying;
PriceOracle[] memory oracles = new PriceOracle[](2);
oracles[0] = PriceOracle(targetOracle);
oracles[1] = PriceOracle(underlyingOracle);
UnderlyingOracle(underlyingOracle).setUnderlying(underlying, adapter);
TargetOracle(targetOracle).setTarget(target, adapter);
MasterOracleLike(masterOracle).add(underlyings, oracles);
bytes memory constructorData = abi.encode(
target,
comptroller,
targetParams.irModel,
ERC20(target).name(),
ERC20(target).symbol(),
cERC20Impl,
hex"",
targetParams.reserveFactor,
0
);
uint256 err = ComptrollerLike(comptroller)._deployMarket(false, constructorData, targetParams.collateralFactor);
if (err != 0) revert Errors.FailedAddTargetMarket();
cTarget = ComptrollerLike(comptroller).cTokensByUnderlying(target);
emit TargetAdded(target, cTarget);
}
function queueSeries(
address adapter,
uint256 maturity,
address pool
) external requiresTrust {
if (Divider(divider).pt(adapter, maturity) == address(0)) revert Errors.SeriesDoesNotExist();
if (sSeries[adapter][maturity].status != SeriesStatus.NONE) revert Errors.DuplicateSeries();
address cTarget = ComptrollerLike(comptroller).cTokensByUnderlying(Adapter(adapter).target());
if (cTarget == address(0)) revert Errors.TargetNotInFuse();
(bool isListed, ) = ComptrollerLike(comptroller).markets(cTarget);
if (!isListed) revert Errors.TargetNotInFuse();
sSeries[adapter][maturity] = Series({ status: SeriesStatus.QUEUED, pool: pool });
emit SeriesQueued(adapter, maturity, pool);
}
function addSeries(address adapter, uint256 maturity) external returns (address cPT, address cLPToken) {
if (sSeries[adapter][maturity].status != SeriesStatus.QUEUED) revert Errors.SeriesNotQueued();
if (ptParams.irModel == address(0)) revert Errors.PTParamsNotSet();
if (lpTokenParams.irModel == address(0)) revert Errors.PoolParamsNotSet();
address pt = Divider(divider).pt(adapter, maturity);
address pool = sSeries[adapter][maturity].pool;
(, , , , , , uint256 sampleTs) = BalancerOracle(pool).getSample(BalancerOracle(pool).getTotalSamples() - 1);
if (sampleTs == 0) revert Errors.OracleNotReady();
address[] memory underlyings = new address[](2);
underlyings[0] = pt;
underlyings[1] = pool;
PriceOracle[] memory oracles = new PriceOracle[](2);
oracles[0] = PriceOracle(ptOracle);
oracles[1] = PriceOracle(lpOracle);
PTOracle(ptOracle).setPrincipal(pt, pool);
MasterOracleLike(masterOracle).add(underlyings, oracles);
bytes memory constructorDataPrincipal = abi.encode(
pt,
comptroller,
ptParams.irModel,
ERC20(pt).name(),
ERC20(pt).symbol(),
cERC20Impl,
hex"",
ptParams.reserveFactor,
0
);
uint256 errPrincipal = ComptrollerLike(comptroller)._deployMarket(
false,
constructorDataPrincipal,
ptParams.collateralFactor
);
if (errPrincipal != 0) revert Errors.FailedToAddPTMarket();
bytes memory constructorDataLpToken = abi.encode(
pool,
comptroller,
lpTokenParams.irModel,
ERC20(pool).name(),
ERC20(pool).symbol(),
cERC20Impl,
hex"",
lpTokenParams.reserveFactor,
0
);
uint256 errLpToken = ComptrollerLike(comptroller)._deployMarket(
false,
constructorDataLpToken,
lpTokenParams.collateralFactor
);
if (errLpToken != 0) revert Errors.FailedAddLpMarket();
cPT = ComptrollerLike(comptroller).cTokensByUnderlying(pt);
cLPToken = ComptrollerLike(comptroller).cTokensByUnderlying(pool);
ComptrollerLike(comptroller)._setBorrowPaused(cLPToken, true);
sSeries[adapter][maturity].status = SeriesStatus.ADDED;
emit SeriesAdded(pt, pool);
}
function setParams(bytes32 what, AssetParams calldata data) external requiresTrust {
if (what == "PT_PARAMS") ptParams = data;
else if (what == "LP_TOKEN_PARAMS") lpTokenParams = data;
else if (what == "TARGET_PARAMS") targetParams = data;
else revert Errors.InvalidParam();
emit ParamsSet(what, data);
}
function execute(
address to,
uint256 value,
bytes memory data,
uint256 txGas
) external requiresTrust returns (bool success) {
assembly {
success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)
}
}
event ParamsSet(bytes32 indexed what, AssetParams data);
event PoolDeployed(string name, address comptroller, uint256 poolIndex, uint256 closeFactor, uint256 liqIncentive);
event TargetAdded(address indexed target, address indexed cTarget);
event SeriesQueued(address indexed adapter, uint256 indexed maturity, address indexed pool);
event SeriesAdded(address indexed pt, address indexed lpToken);
}
文件 22 的 30:PriceOracle.sol
pragma solidity 0.8.11;
import { CToken } from "./CToken.sol";
abstract contract PriceOracle {
bool public constant isPriceOracle = true;
function getUnderlyingPrice(CToken cToken) external view virtual returns (uint256);
function price(address underlying) external view virtual returns (uint256);
}
文件 23 的 30:ReentrancyGuard.sol
pragma solidity >=0.8.0;
abstract contract ReentrancyGuard {
uint256 private locked = 1;
modifier nonReentrant() {
require(locked == 1, "REENTRANCY");
locked = 2;
_;
locked = 1;
}
}
文件 24 的 30:SafeTransferLib.sol
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
library SafeTransferLib {
event Debug(bool one, bool two, uint256 retsize);
function safeTransferETH(address to, uint256 amount) internal {
bool success;
assembly {
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), from)
mstore(add(freeMemoryPointer, 36), to)
mstore(add(freeMemoryPointer, 68), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to)
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to)
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}
文件 25 的 30:Target.sol
pragma solidity 0.8.11;
import { PriceOracle } from "../external/PriceOracle.sol";
import { CToken } from "../external/CToken.sol";
import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol";
import { Trust } from "@sense-finance/v1-utils/src/Trust.sol";
import { Token } from "@sense-finance/v1-core/src/tokens/Token.sol";
import { FixedMath } from "@sense-finance/v1-core/src/external/FixedMath.sol";
import { BaseAdapter as Adapter } from "@sense-finance/v1-core/src/adapters/BaseAdapter.sol";
contract TargetOracle is PriceOracle, Trust {
using FixedMath for uint256;
mapping(address => address) public adapters;
constructor() Trust(msg.sender) {}
function setTarget(address target, address adapter) external requiresTrust {
adapters[target] = adapter;
}
function getUnderlyingPrice(CToken cToken) external view override returns (uint256) {
Token target = Token(cToken.underlying());
return _price(address(target));
}
function price(address target) external view override returns (uint256) {
return _price(target);
}
function _price(address target) internal view returns (uint256) {
address adapter = adapters[address(target)];
if (adapter == address(0)) revert Errors.AdapterNotSet();
uint256 scale = Adapter(adapter).scaleStored();
return scale.fmul(Adapter(adapter).getUnderlyingPrice());
}
}
文件 26 的 30:Token.sol
pragma solidity 0.8.11;
import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol";
import { Trust } from "@sense-finance/v1-utils/src/Trust.sol";
contract Token is ERC20, Trust {
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals,
address _trusted
) ERC20(_name, _symbol, _decimals) Trust(_trusted) {}
function mint(address usr, uint256 amount) public requiresTrust {
_mint(usr, amount);
}
function burn(address usr, uint256 amount) public requiresTrust {
_burn(usr, amount);
}
}
文件 27 的 30:Trust.sol
pragma solidity >=0.7.0;
abstract contract Trust {
event UserTrustUpdated(address indexed user, bool trusted);
mapping(address => bool) public isTrusted;
constructor(address initialUser) {
isTrusted[initialUser] = true;
emit UserTrustUpdated(initialUser, true);
}
function setIsTrusted(address user, bool trusted) public virtual requiresTrust {
isTrusted[user] = trusted;
emit UserTrustUpdated(user, trusted);
}
modifier requiresTrust() {
require(isTrusted[msg.sender], "UNTRUSTED");
_;
}
}
文件 28 的 30:Underlying.sol
pragma solidity 0.8.11;
import { PriceOracle } from "../external/PriceOracle.sol";
import { CToken } from "../external/CToken.sol";
import { Errors } from "@sense-finance/v1-utils/src/libs/Errors.sol";
import { Trust } from "@sense-finance/v1-utils/src/Trust.sol";
import { FixedMath } from "@sense-finance/v1-core/src/external/FixedMath.sol";
import { BaseAdapter as Adapter } from "@sense-finance/v1-core/src/adapters/BaseAdapter.sol";
contract UnderlyingOracle is PriceOracle, Trust {
using FixedMath for uint256;
mapping(address => address) public adapters;
constructor() Trust(msg.sender) {}
function setUnderlying(address underlying, address adapter) external requiresTrust {
adapters[underlying] = adapter;
}
function getUnderlyingPrice(CToken cToken) external view override returns (uint256) {
return _price(address(cToken.underlying()));
}
function price(address underlying) external view override returns (uint256) {
return _price(underlying);
}
function _price(address underlying) internal view returns (uint256) {
address adapter = adapters[address(underlying)];
if (adapter == address(0)) revert Errors.AdapterNotSet();
return Adapter(adapter).getUnderlyingPrice();
}
}
文件 29 的 30:Vault.sol
pragma solidity 0.8.11;
import { ERC20 } from "@rari-capital/solmate/src/tokens/ERC20.sol";
interface IAsset {}
interface BalancerVault {
struct JoinPoolRequest {
IAsset[] assets;
uint256[] maxAmountsIn;
bytes userData;
bool fromInternalBalance;
}
struct ExitPoolRequest {
IAsset[] assets;
uint256[] minAmountsOut;
bytes userData;
bool toInternalBalance;
}
enum PoolSpecialization {
GENERAL,
MINIMAL_SWAP_INFO,
TWO_TOKEN
}
enum SwapKind {
GIVEN_IN,
GIVEN_OUT
}
struct SingleSwap {
bytes32 poolId;
SwapKind kind;
IAsset assetIn;
IAsset assetOut;
uint256 amount;
bytes userData;
}
struct FundManagement {
address sender;
bool fromInternalBalance;
address payable recipient;
bool toInternalBalance;
}
function getPoolTokens(bytes32 poolId)
external
view
returns (
ERC20[] memory tokens,
uint256[] memory balances,
uint256 maxBlockNumber
);
function getPool(bytes32 poolId) external view returns (address, PoolSpecialization);
function swap(
SingleSwap memory singleSwap,
FundManagement memory funds,
uint256 limit,
uint256 deadline
) external payable returns (uint256);
function joinPool(
bytes32 poolId,
address sender,
address recipient,
JoinPoolRequest memory request
) external payable;
function exitPool(
bytes32 poolId,
address sender,
address payable recipient,
ExitPoolRequest memory request
) external;
}
文件 30 的 30:YT.sol
pragma solidity 0.8.11;
import { Divider } from "../Divider.sol";
import { Token } from "./Token.sol";
contract YT is Token {
address public immutable adapter;
address public immutable divider;
uint256 public immutable maturity;
constructor(
address _adapter,
uint256 _maturity,
string memory _name,
string memory _symbol,
uint8 _decimals,
address _divider
) Token(_name, _symbol, _decimals, _divider) {
adapter = _adapter;
maturity = _maturity;
divider = _divider;
}
function collect() external returns (uint256 _collected) {
return Divider(divider).collect(msg.sender, adapter, maturity, 0, address(0));
}
function transfer(address to, uint256 value) public override returns (bool) {
Divider(divider).collect(msg.sender, adapter, maturity, value, to);
return super.transfer(to, value);
}
function transferFrom(
address from,
address to,
uint256 value
) public override returns (bool) {
if (value > 0) Divider(divider).collect(from, adapter, maturity, value, to);
return super.transferFrom(from, to, value);
}
}
{
"compilationTarget": {
"@sense-finance/v1-core/src/Periphery.sol": "Periphery"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 15000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_divider","type":"address"},{"internalType":"address","name":"_poolManager","type":"address"},{"internalType":"address","name":"_spaceFactory","type":"address"},{"internalType":"address","name":"_balancerVault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ExistingValue","type":"error"},{"inputs":[],"name":"FactoryNotSupported","type":"error"},{"inputs":[],"name":"FlashBorrowFailed","type":"error"},{"inputs":[],"name":"FlashUntrustedBorrower","type":"error"},{"inputs":[],"name":"FlashUntrustedLoanInitiator","type":"error"},{"inputs":[],"name":"OnlyPermissionless","type":"error"},{"inputs":[],"name":"SwapTooSmall","type":"error"},{"inputs":[],"name":"TargetMismatch","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"adapter","type":"address"}],"name":"AdapterDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"adapter","type":"address"}],"name":"AdapterOnboarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"adapter","type":"address"}],"name":"AdapterVerified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"factory","type":"address"},{"indexed":true,"internalType":"bool","name":"isOn","type":"bool"}],"name":"FactoryChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newPoolManager","type":"address"}],"name":"PoolManagerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"adapter","type":"address"},{"indexed":true,"internalType":"uint256","name":"maturity","type":"uint256"},{"indexed":true,"internalType":"address","name":"sponsor","type":"address"}],"name":"SeriesSponsored","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newSpaceFactory","type":"address"}],"name":"SpaceFactoryChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"assetIn","type":"address"},{"indexed":false,"internalType":"address","name":"assetOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"}],"name":"Swapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"trusted","type":"bool"}],"name":"UserTrustUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"adapter","type":"address"},{"indexed":false,"internalType":"uint256","name":"maturity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetReturned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ytOut","type":"uint256"}],"name":"YTsPurchased","type":"event"},{"inputs":[],"name":"MIN_YT_SWAP_IN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_ESTIMATE_ACCEPTABLE_ERROR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"tBal","type":"uint256"},{"internalType":"uint8","name":"mode","type":"uint8"},{"internalType":"uint256","name":"minBptOut","type":"uint256"}],"name":"addLiquidityFromTarget","outputs":[{"internalType":"uint256","name":"tAmount","type":"uint256"},{"internalType":"uint256","name":"issued","type":"uint256"},{"internalType":"uint256","name":"lpShares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"uBal","type":"uint256"},{"internalType":"uint8","name":"mode","type":"uint8"},{"internalType":"uint256","name":"minBptOut","type":"uint256"}],"name":"addLiquidityFromUnderlying","outputs":[{"internalType":"uint256","name":"tAmount","type":"uint256"},{"internalType":"uint256","name":"issued","type":"uint256"},{"internalType":"uint256","name":"lpShares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"balancerVault","outputs":[{"internalType":"contract BalancerVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"f","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"deployAdapter","outputs":[{"internalType":"address","name":"adapter","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"divider","outputs":[{"internalType":"contract Divider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"factories","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isTrusted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"srcAdapter","type":"address"},{"internalType":"address","name":"dstAdapter","type":"address"},{"internalType":"uint256","name":"srcMaturity","type":"uint256"},{"internalType":"uint256","name":"dstMaturity","type":"uint256"},{"internalType":"uint256","name":"lpBal","type":"uint256"},{"internalType":"uint256[]","name":"minAmountsOut","type":"uint256[]"},{"internalType":"uint256","name":"minAccepted","type":"uint256"},{"internalType":"uint8","name":"mode","type":"uint8"},{"internalType":"bool","name":"intoTarget","type":"bool"},{"internalType":"uint256","name":"minBptOut","type":"uint256"}],"name":"migrateLiquidity","outputs":[{"internalType":"uint256","name":"tAmount","type":"uint256"},{"internalType":"uint256","name":"issued","type":"uint256"},{"internalType":"uint256","name":"lpShares","type":"uint256"},{"internalType":"uint256","name":"ptBal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"initiator","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"amountBorrrowed","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onFlashLoan","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"bool","name":"addAdapter","type":"bool"}],"name":"onboardAdapter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"poolManager","outputs":[{"internalType":"contract PoolManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"lpBal","type":"uint256"},{"internalType":"uint256[]","name":"minAmountsOut","type":"uint256[]"},{"internalType":"uint256","name":"minAccepted","type":"uint256"},{"internalType":"bool","name":"intoTarget","type":"bool"}],"name":"removeLiquidity","outputs":[{"internalType":"uint256","name":"tBal","type":"uint256"},{"internalType":"uint256","name":"ptBal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"lpBal","type":"uint256"},{"internalType":"uint256[]","name":"minAmountsOut","type":"uint256[]"},{"internalType":"uint256","name":"minAccepted","type":"uint256"},{"internalType":"bool","name":"intoTarget","type":"bool"}],"name":"removeLiquidityAndUnwrapTarget","outputs":[{"internalType":"uint256","name":"uBal","type":"uint256"},{"internalType":"uint256","name":"ptBal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"f","type":"address"},{"internalType":"bool","name":"isOn","type":"bool"}],"name":"setFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"trusted","type":"bool"}],"name":"setIsTrusted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPoolManager","type":"address"}],"name":"setPoolManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSpaceFactory","type":"address"}],"name":"setSpaceFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"spaceFactory","outputs":[{"internalType":"contract SpaceFactoryLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"bool","name":"withPool","type":"bool"}],"name":"sponsorSeries","outputs":[{"internalType":"address","name":"pt","type":"address"},{"internalType":"address","name":"yt","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"ptBal","type":"uint256"},{"internalType":"uint256","name":"minAccepted","type":"uint256"}],"name":"swapPTsForTarget","outputs":[{"internalType":"uint256","name":"tBal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"ptBal","type":"uint256"},{"internalType":"uint256","name":"minAccepted","type":"uint256"}],"name":"swapPTsForUnderlying","outputs":[{"internalType":"uint256","name":"uBal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"tBal","type":"uint256"},{"internalType":"uint256","name":"minAccepted","type":"uint256"}],"name":"swapTargetForPTs","outputs":[{"internalType":"uint256","name":"ptBal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"targetIn","type":"uint256"},{"internalType":"uint256","name":"targetToBorrow","type":"uint256"},{"internalType":"uint256","name":"minOut","type":"uint256"}],"name":"swapTargetForYTs","outputs":[{"internalType":"uint256","name":"targetBal","type":"uint256"},{"internalType":"uint256","name":"ytBal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"uBal","type":"uint256"},{"internalType":"uint256","name":"minAccepted","type":"uint256"}],"name":"swapUnderlyingForPTs","outputs":[{"internalType":"uint256","name":"ptBal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"underlyingIn","type":"uint256"},{"internalType":"uint256","name":"targetToBorrow","type":"uint256"},{"internalType":"uint256","name":"minOut","type":"uint256"}],"name":"swapUnderlyingForYTs","outputs":[{"internalType":"uint256","name":"targetBal","type":"uint256"},{"internalType":"uint256","name":"ytBal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"ytBal","type":"uint256"}],"name":"swapYTsForTarget","outputs":[{"internalType":"uint256","name":"tBal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint256","name":"ytBal","type":"uint256"}],"name":"swapYTsForUnderlying","outputs":[{"internalType":"uint256","name":"uBal","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"verified","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adapter","type":"address"},{"internalType":"bool","name":"addToPool","type":"bool"}],"name":"verifyAdapter","outputs":[],"stateMutability":"nonpayable","type":"function"}]