编译器
0.8.25+commit.b61c2a91
文件 1 的 35:BoolUtils.sol
pragma solidity >=0.8.20;
library BoolUtils {
function and(bool a, bool b) internal pure returns (bool c) {
assembly {
c := and(a, b)
}
}
function or(bool a, bool b) internal pure returns (bool c) {
assembly {
c := or(a, b)
}
}
function xor(bool a, bool b) internal pure returns (bool c) {
assembly {
c := xor(a, b)
}
}
}
文件 2 的 35:Errors.sol
pragma solidity >=0.8.20;
uint256 constant Panic_CompilerPanic = 0x00;
uint256 constant Panic_AssertFalse = 0x01;
uint256 constant Panic_Arithmetic = 0x11;
uint256 constant Panic_DivideByZero = 0x12;
uint256 constant Panic_InvalidEnumValue = 0x21;
uint256 constant Panic_InvalidStorageByteArray = 0x22;
uint256 constant Panic_EmptyArrayPop = 0x31;
uint256 constant Panic_ArrayOutOfBounds = 0x32;
uint256 constant Panic_MemoryTooLarge = 0x41;
uint256 constant Panic_UninitializedFunctionPointer = 0x51;
uint256 constant Panic_ErrorSelector = 0x4e487b71;
uint256 constant Panic_ErrorCodePointer = 0x20;
uint256 constant Panic_ErrorLength = 0x24;
uint256 constant Error_SelectorPointer = 0x1c;
function revertWithSelector(bytes4 errorSelector) pure {
assembly {
mstore(0, errorSelector)
revert(0, 4)
}
}
function revertWithSelector(uint256 errorSelector) pure {
assembly {
mstore(0, errorSelector)
revert(Error_SelectorPointer, 4)
}
}
function revertWithSelectorAndArgument(bytes4 errorSelector, uint256 argument) pure {
assembly {
mstore(0, errorSelector)
mstore(4, argument)
revert(0, 0x24)
}
}
function revertWithSelectorAndArgument(uint256 errorSelector, uint256 argument) pure {
assembly {
mstore(0, errorSelector)
mstore(0x20, argument)
revert(Error_SelectorPointer, 0x24)
}
}
文件 3 的 35:FIFOQueue.sol
pragma solidity >=0.8.20;
struct FIFOQueue {
uint128 startIndex;
uint128 nextIndex;
mapping(uint256 => uint32) data;
}
using FIFOQueueLib for FIFOQueue global;
library FIFOQueueLib {
error FIFOQueueOutOfBounds();
function empty(FIFOQueue storage arr) internal view returns (bool) {
return arr.nextIndex == arr.startIndex;
}
function first(FIFOQueue storage arr) internal view returns (uint32) {
if (arr.startIndex == arr.nextIndex) {
revert FIFOQueueOutOfBounds();
}
return arr.data[arr.startIndex];
}
function at(FIFOQueue storage arr, uint256 index) internal view returns (uint32) {
index += arr.startIndex;
if (index >= arr.nextIndex) {
revert FIFOQueueOutOfBounds();
}
return arr.data[index];
}
function length(FIFOQueue storage arr) internal view returns (uint128) {
return arr.nextIndex - arr.startIndex;
}
function values(FIFOQueue storage arr) internal view returns (uint32[] memory _values) {
uint256 startIndex = arr.startIndex;
uint256 nextIndex = arr.nextIndex;
uint256 len = nextIndex - startIndex;
_values = new uint32[](len);
for (uint256 i = 0; i < len; i++) {
_values[i] = arr.data[startIndex + i];
}
return _values;
}
function push(FIFOQueue storage arr, uint32 value) internal {
uint128 nextIndex = arr.nextIndex;
arr.data[nextIndex] = value;
arr.nextIndex = nextIndex + 1;
}
function shift(FIFOQueue storage arr) internal {
uint128 startIndex = arr.startIndex;
if (startIndex == arr.nextIndex) {
revert FIFOQueueOutOfBounds();
}
delete arr.data[startIndex];
arr.startIndex = startIndex + 1;
}
function shiftN(FIFOQueue storage arr, uint128 n) internal {
uint128 startIndex = arr.startIndex;
if (startIndex + n > arr.nextIndex) {
revert FIFOQueueOutOfBounds();
}
for (uint256 i = 0; i < n; i++) {
delete arr.data[startIndex + i];
}
arr.startIndex = startIndex + n;
}
}
文件 4 的 35:FeeMath.sol
pragma solidity >=0.8.20;
import './MathUtils.sol';
import './SafeCastLib.sol';
import './MarketState.sol';
using SafeCastLib for uint256;
using MathUtils for uint256;
library FeeMath {
function calculateLinearInterestFromBips(
uint256 rateBip,
uint256 timeDelta
) internal pure returns (uint256 result) {
uint256 rate = rateBip.bipToRay();
uint256 accumulatedInterestRay = rate * timeDelta;
unchecked {
return accumulatedInterestRay / SECONDS_IN_365_DAYS;
}
}
function calculateBaseInterest(
MarketState memory state,
uint256 timestamp
) internal pure returns (uint256 baseInterestRay) {
baseInterestRay = MathUtils.calculateLinearInterestFromBips(
state.annualInterestBips,
timestamp - state.lastInterestAccruedTimestamp
);
}
function applyProtocolFee(
MarketState memory state,
uint256 baseInterestRay
) internal pure returns (uint256 protocolFee) {
uint256 protocolFeeRay = uint(state.protocolFeeBips).bipMul(baseInterestRay);
protocolFee = uint256(state.scaledTotalSupply).rayMul(
uint256(state.scaleFactor).rayMul(protocolFeeRay)
);
state.accruedProtocolFees = (state.accruedProtocolFees + protocolFee).toUint128();
}
function updateDelinquency(
MarketState memory state,
uint256 timestamp,
uint256 delinquencyFeeBips,
uint256 delinquencyGracePeriod
) internal pure returns (uint256 delinquencyFeeRay) {
uint256 timeWithPenalty = updateTimeDelinquentAndGetPenaltyTime(
state,
delinquencyGracePeriod,
timestamp - state.lastInterestAccruedTimestamp
);
if (timeWithPenalty > 0) {
delinquencyFeeRay = calculateLinearInterestFromBips(delinquencyFeeBips, timeWithPenalty);
}
}
function updateTimeDelinquentAndGetPenaltyTime(
MarketState memory state,
uint256 delinquencyGracePeriod,
uint256 timeDelta
) internal pure returns (uint256 ) {
uint256 previousTimeDelinquent = state.timeDelinquent;
if (state.isDelinquent) {
state.timeDelinquent = (previousTimeDelinquent + timeDelta).toUint32();
uint256 secondsRemainingWithoutPenalty = delinquencyGracePeriod.satSub(
previousTimeDelinquent
);
return timeDelta.satSub(secondsRemainingWithoutPenalty);
}
state.timeDelinquent = previousTimeDelinquent.satSub(timeDelta).toUint32();
uint256 secondsRemainingWithPenalty = previousTimeDelinquent.satSub(delinquencyGracePeriod);
return MathUtils.min(secondsRemainingWithPenalty, timeDelta);
}
function updateScaleFactorAndFees(
MarketState memory state,
uint256 delinquencyFeeBips,
uint256 delinquencyGracePeriod,
uint256 timestamp
)
internal
pure
returns (uint256 baseInterestRay, uint256 delinquencyFeeRay, uint256 protocolFee)
{
baseInterestRay = state.calculateBaseInterest(timestamp);
if (state.protocolFeeBips > 0) {
protocolFee = state.applyProtocolFee(baseInterestRay);
}
if (delinquencyFeeBips > 0) {
delinquencyFeeRay = state.updateDelinquency(
timestamp,
delinquencyFeeBips,
delinquencyGracePeriod
);
}
uint256 prevScaleFactor = state.scaleFactor;
uint256 scaleFactorDelta = prevScaleFactor.rayMul(baseInterestRay + delinquencyFeeRay);
state.scaleFactor = (prevScaleFactor + scaleFactorDelta).toUint112();
state.lastInterestAccruedTimestamp = uint32(timestamp);
}
}
文件 5 的 35:FunctionTypeCasts.sol
pragma solidity >=0.8.20;
import { MarketParameters } from '../interfaces/WildcatStructsAndEnums.sol';
import { MarketState } from '../libraries/MarketState.sol';
import { WithdrawalBatch } from '../libraries/Withdrawal.sol';
library FunctionTypeCasts {
function asReturnsMarketState(
function() internal view returns (uint256) fnIn
) internal pure returns (function() internal view returns (MarketState memory) fnOut) {
assembly {
fnOut := fnIn
}
}
function asReturnsPointers(
function() internal view returns (MarketState memory, uint32, WithdrawalBatch memory) fnIn
) internal pure returns (function() internal view returns (uint256, uint32, uint256) fnOut) {
assembly {
fnOut := fnIn
}
}
function asReturnsMarketParameters(
function() internal view returns (uint256) fnIn
) internal pure returns (function() internal view returns (MarketParameters memory) fnOut) {
assembly {
fnOut := fnIn
}
}
}
文件 6 的 35:HooksConfig.sol
pragma solidity >=0.8.20;
import '../access/IHooks.sol';
import '../libraries/MarketState.sol';
type HooksConfig is uint256;
HooksConfig constant EmptyHooksConfig = HooksConfig.wrap(0);
using LibHooksConfig for HooksConfig global;
using LibHooksConfig for HooksDeploymentConfig global;
type HooksDeploymentConfig is uint256;
function encodeHooksDeploymentConfig(
HooksConfig optionalFlags,
HooksConfig requiredFlags
) pure returns (HooksDeploymentConfig flags) {
assembly {
let cleanedOptionalFlags := and(0xffff, shr(0x50, optionalFlags))
let cleanedRequiredFlags := and(0xffff0000, shr(0x40, requiredFlags))
flags := or(cleanedOptionalFlags, cleanedRequiredFlags)
}
}
uint256 constant Bit_Enabled_Deposit = 95;
uint256 constant Bit_Enabled_QueueWithdrawal = 94;
uint256 constant Bit_Enabled_ExecuteWithdrawal = 93;
uint256 constant Bit_Enabled_Transfer = 92;
uint256 constant Bit_Enabled_Borrow = 91;
uint256 constant Bit_Enabled_Repay = 90;
uint256 constant Bit_Enabled_CloseMarket = 89;
uint256 constant Bit_Enabled_NukeFromOrbit = 88;
uint256 constant Bit_Enabled_SetMaxTotalSupply = 87;
uint256 constant Bit_Enabled_SetAnnualInterestAndReserveRatioBips = 86;
uint256 constant Bit_Enabled_SetProtocolFeeBips = 85;
uint256 constant MarketStateSize = 0x01c0;
function encodeHooksConfig(
address hooksAddress,
bool useOnDeposit,
bool useOnQueueWithdrawal,
bool useOnExecuteWithdrawal,
bool useOnTransfer,
bool useOnBorrow,
bool useOnRepay,
bool useOnCloseMarket,
bool useOnNukeFromOrbit,
bool useOnSetMaxTotalSupply,
bool useOnSetAnnualInterestAndReserveRatioBips,
bool useOnSetProtocolFeeBips
) pure returns (HooksConfig hooks) {
assembly {
hooks := shl(96, hooksAddress)
hooks := or(hooks, shl(Bit_Enabled_Deposit, useOnDeposit))
hooks := or(hooks, shl(Bit_Enabled_QueueWithdrawal, useOnQueueWithdrawal))
hooks := or(hooks, shl(Bit_Enabled_ExecuteWithdrawal, useOnExecuteWithdrawal))
hooks := or(hooks, shl(Bit_Enabled_Transfer, useOnTransfer))
hooks := or(hooks, shl(Bit_Enabled_Borrow, useOnBorrow))
hooks := or(hooks, shl(Bit_Enabled_Repay, useOnRepay))
hooks := or(hooks, shl(Bit_Enabled_CloseMarket, useOnCloseMarket))
hooks := or(hooks, shl(Bit_Enabled_NukeFromOrbit, useOnNukeFromOrbit))
hooks := or(hooks, shl(Bit_Enabled_SetMaxTotalSupply, useOnSetMaxTotalSupply))
hooks := or(
hooks,
shl(
Bit_Enabled_SetAnnualInterestAndReserveRatioBips,
useOnSetAnnualInterestAndReserveRatioBips
)
)
hooks := or(hooks, shl(Bit_Enabled_SetProtocolFeeBips, useOnSetProtocolFeeBips))
}
}
library LibHooksConfig {
function setHooksAddress(
HooksConfig hooks,
address _hooksAddress
) internal pure returns (HooksConfig updatedHooks) {
assembly {
updatedHooks := shr(160, shl(160, hooks))
updatedHooks := or(updatedHooks, shl(96, _hooksAddress))
}
}
function mergeSharedFlags(
HooksConfig a,
HooksConfig b
) internal pure returns (HooksConfig merged) {
assembly {
let addressA := shl(0x60, shr(0x60, a))
let flagsA := shl(0xa0, a)
let flagsB := shl(0xa0, b)
let mergedFlags := shr(0xa0, and(flagsA, flagsB))
merged := or(addressA, mergedFlags)
}
}
function mergeAllFlags(HooksConfig a, HooksConfig b) internal pure returns (HooksConfig merged) {
assembly {
let addressA := shl(0x60, shr(0x60, a))
let flagsA := shl(0xa0, a)
let flagsB := shl(0xa0, b)
let mergedFlags := shr(0xa0, or(flagsA, flagsB))
merged := or(addressA, mergedFlags)
}
}
function mergeFlags(
HooksConfig config,
HooksDeploymentConfig flags
) internal pure returns (HooksConfig merged) {
assembly {
let _hooksAddress := shl(96, shr(96, config))
let configFlags := shr(0x50, config)
let _optionalFlags := flags
let _requiredFlags := shr(0x10, flags)
let mergedFlags := and(0xffff, or(and(configFlags, _optionalFlags), _requiredFlags))
merged := or(_hooksAddress, shl(0x50, mergedFlags))
}
}
function optionalFlags(HooksDeploymentConfig flags) internal pure returns (HooksConfig config) {
assembly {
config := shl(0x50, and(flags, 0xffff))
}
}
function requiredFlags(HooksDeploymentConfig flags) internal pure returns (HooksConfig config) {
assembly {
config := shl(0x40, and(flags, 0xffff0000))
}
}
function readFlag(HooksConfig hooks, uint256 bitsAfter) internal pure returns (bool flagged) {
assembly {
flagged := and(shr(bitsAfter, hooks), 1)
}
}
function setFlag(
HooksConfig hooks,
uint256 bitsAfter
) internal pure returns (HooksConfig updatedHooks) {
assembly {
updatedHooks := or(hooks, shl(bitsAfter, 1))
}
}
function clearFlag(
HooksConfig hooks,
uint256 bitsAfter
) internal pure returns (HooksConfig updatedHooks) {
assembly {
updatedHooks := and(hooks, not(shl(bitsAfter, 1)))
}
}
function hooksAddress(HooksConfig hooks) internal pure returns (address _hooks) {
assembly {
_hooks := shr(96, hooks)
}
}
function useOnDeposit(HooksConfig hooks) internal pure returns (bool) {
return hooks.readFlag(Bit_Enabled_Deposit);
}
function useOnQueueWithdrawal(HooksConfig hooks) internal pure returns (bool) {
return hooks.readFlag(Bit_Enabled_QueueWithdrawal);
}
function useOnExecuteWithdrawal(HooksConfig hooks) internal pure returns (bool) {
return hooks.readFlag(Bit_Enabled_ExecuteWithdrawal);
}
function useOnTransfer(HooksConfig hooks) internal pure returns (bool) {
return hooks.readFlag(Bit_Enabled_Transfer);
}
function useOnBorrow(HooksConfig hooks) internal pure returns (bool) {
return hooks.readFlag(Bit_Enabled_Borrow);
}
function useOnRepay(HooksConfig hooks) internal pure returns (bool) {
return hooks.readFlag(Bit_Enabled_Repay);
}
function useOnCloseMarket(HooksConfig hooks) internal pure returns (bool) {
return hooks.readFlag(Bit_Enabled_CloseMarket);
}
function useOnNukeFromOrbit(HooksConfig hooks) internal pure returns (bool) {
return hooks.readFlag(Bit_Enabled_NukeFromOrbit);
}
function useOnSetMaxTotalSupply(HooksConfig hooks) internal pure returns (bool) {
return hooks.readFlag(Bit_Enabled_SetMaxTotalSupply);
}
function useOnSetAnnualInterestAndReserveRatioBips(
HooksConfig hooks
) internal pure returns (bool) {
return hooks.readFlag(Bit_Enabled_SetAnnualInterestAndReserveRatioBips);
}
function useOnSetProtocolFeeBips(HooksConfig hooks) internal pure returns (bool) {
return hooks.readFlag(Bit_Enabled_SetProtocolFeeBips);
}
uint256 internal constant DepositCalldataSize = 0x24;
uint256 internal constant DepositHook_Base_Size = 0x0244;
uint256 internal constant DepositHook_ScaledAmount_Offset = 0x20;
uint256 internal constant DepositHook_State_Offset = 0x40;
uint256 internal constant DepositHook_ExtraData_Head_Offset = 0x200;
uint256 internal constant DepositHook_ExtraData_Length_Offset = 0x0220;
uint256 internal constant DepositHook_ExtraData_TailOffset = 0x0240;
function onDeposit(
HooksConfig self,
address lender,
uint256 scaledAmount,
MarketState memory state
) internal {
address target = self.hooksAddress();
uint32 onDepositSelector = uint32(IHooks.onDeposit.selector);
if (self.useOnDeposit()) {
assembly {
let extraCalldataBytes := sub(calldatasize(), DepositCalldataSize)
let cdPointer := mload(0x40)
let headPointer := add(cdPointer, 0x20)
mstore(cdPointer, onDepositSelector)
mstore(headPointer, lender)
mstore(add(headPointer, DepositHook_ScaledAmount_Offset), scaledAmount)
mcopy(add(headPointer, DepositHook_State_Offset), state, MarketStateSize)
mstore(
add(headPointer, DepositHook_ExtraData_Head_Offset),
DepositHook_ExtraData_Length_Offset
)
mstore(add(headPointer, DepositHook_ExtraData_Length_Offset), extraCalldataBytes)
calldatacopy(
add(headPointer, DepositHook_ExtraData_TailOffset),
DepositCalldataSize,
extraCalldataBytes
)
let size := add(DepositHook_Base_Size, extraCalldataBytes)
if iszero(call(gas(), target, 0, add(cdPointer, 0x1c), size, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
uint256 internal constant QueueWithdrawalHook_Base_Size = 0x0264;
uint256 internal constant QueueWithdrawalHook_Expiry_Offset = 0x20;
uint256 internal constant QueueWithdrawalHook_ScaledAmount_Offset = 0x40;
uint256 internal constant QueueWithdrawalHook_State_Offset = 0x60;
uint256 internal constant QueueWithdrawalHook_ExtraData_Head_Offset = 0x220;
uint256 internal constant QueueWithdrawalHook_ExtraData_Length_Offset = 0x0240;
uint256 internal constant QueueWithdrawalHook_ExtraData_TailOffset = 0x0260;
function onQueueWithdrawal(
HooksConfig self,
address lender,
uint32 expiry,
uint256 scaledAmount,
MarketState memory state,
uint256 baseCalldataSize
) internal {
address target = self.hooksAddress();
uint32 onQueueWithdrawalSelector = uint32(IHooks.onQueueWithdrawal.selector);
if (self.useOnQueueWithdrawal()) {
assembly {
let extraCalldataBytes := sub(calldatasize(), baseCalldataSize)
let cdPointer := mload(0x40)
let headPointer := add(cdPointer, 0x20)
mstore(cdPointer, onQueueWithdrawalSelector)
mstore(headPointer, lender)
mstore(add(headPointer, QueueWithdrawalHook_Expiry_Offset), expiry)
mstore(add(headPointer, QueueWithdrawalHook_ScaledAmount_Offset), scaledAmount)
mcopy(add(headPointer, QueueWithdrawalHook_State_Offset), state, MarketStateSize)
mstore(
add(headPointer, QueueWithdrawalHook_ExtraData_Head_Offset),
QueueWithdrawalHook_ExtraData_Length_Offset
)
mstore(add(headPointer, QueueWithdrawalHook_ExtraData_Length_Offset), extraCalldataBytes)
calldatacopy(
add(headPointer, QueueWithdrawalHook_ExtraData_TailOffset),
baseCalldataSize,
extraCalldataBytes
)
let size := add(QueueWithdrawalHook_Base_Size, extraCalldataBytes)
if iszero(call(gas(), target, 0, add(cdPointer, 0x1c), size, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
uint256 internal constant ExecuteWithdrawalHook_Base_Size = 0x0244;
uint256 internal constant ExecuteWithdrawalHook_ScaledAmount_Offset = 0x20;
uint256 internal constant ExecuteWithdrawalHook_State_Offset = 0x40;
uint256 internal constant ExecuteWithdrawalHook_ExtraData_Head_Offset = 0x0200;
uint256 internal constant ExecuteWithdrawalHook_ExtraData_Length_Offset = 0x0220;
uint256 internal constant ExecuteWithdrawalHook_ExtraData_TailOffset = 0x0240;
function onExecuteWithdrawal(
HooksConfig self,
address lender,
uint256 scaledAmount,
MarketState memory state,
uint256 baseCalldataSize
) internal {
address target = self.hooksAddress();
uint32 onExecuteWithdrawalSelector = uint32(IHooks.onExecuteWithdrawal.selector);
if (self.useOnExecuteWithdrawal()) {
assembly {
let extraCalldataBytes := sub(calldatasize(), baseCalldataSize)
let cdPointer := mload(0x40)
let headPointer := add(cdPointer, 0x20)
mstore(cdPointer, onExecuteWithdrawalSelector)
mstore(headPointer, lender)
mstore(add(headPointer, ExecuteWithdrawalHook_ScaledAmount_Offset), scaledAmount)
mcopy(add(headPointer, ExecuteWithdrawalHook_State_Offset), state, MarketStateSize)
mstore(
add(headPointer, ExecuteWithdrawalHook_ExtraData_Head_Offset),
ExecuteWithdrawalHook_ExtraData_Length_Offset
)
mstore(add(headPointer, ExecuteWithdrawalHook_ExtraData_Length_Offset), extraCalldataBytes)
calldatacopy(
add(headPointer, ExecuteWithdrawalHook_ExtraData_TailOffset),
baseCalldataSize,
extraCalldataBytes
)
let size := add(ExecuteWithdrawalHook_Base_Size, extraCalldataBytes)
if iszero(call(gas(), target, 0, add(cdPointer, 0x1c), size, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
uint256 internal constant TransferHook_Base_Size = 0x0284;
uint256 internal constant TransferHook_From_Offset = 0x20;
uint256 internal constant TransferHook_To_Offset = 0x40;
uint256 internal constant TransferHook_ScaledAmount_Offset = 0x60;
uint256 internal constant TransferHook_State_Offset = 0x80;
uint256 internal constant TransferHook_ExtraData_Head_Offset = 0x240;
uint256 internal constant TransferHook_ExtraData_Length_Offset = 0x0260;
uint256 internal constant TransferHook_ExtraData_TailOffset = 0x0280;
function onTransfer(
HooksConfig self,
address from,
address to,
uint256 scaledAmount,
MarketState memory state,
uint256 baseCalldataSize
) internal {
address target = self.hooksAddress();
uint32 onTransferSelector = uint32(IHooks.onTransfer.selector);
if (self.useOnTransfer()) {
assembly {
let extraCalldataBytes := sub(calldatasize(), baseCalldataSize)
let cdPointer := mload(0x40)
let headPointer := add(cdPointer, 0x20)
mstore(cdPointer, onTransferSelector)
mstore(headPointer, caller())
mstore(add(headPointer, TransferHook_From_Offset), from)
mstore(add(headPointer, TransferHook_To_Offset), to)
mstore(add(headPointer, TransferHook_ScaledAmount_Offset), scaledAmount)
mcopy(add(headPointer, TransferHook_State_Offset), state, MarketStateSize)
mstore(
add(headPointer, TransferHook_ExtraData_Head_Offset),
TransferHook_ExtraData_Length_Offset
)
mstore(add(headPointer, TransferHook_ExtraData_Length_Offset), extraCalldataBytes)
calldatacopy(
add(headPointer, TransferHook_ExtraData_TailOffset),
baseCalldataSize,
extraCalldataBytes
)
let size := add(TransferHook_Base_Size, extraCalldataBytes)
if iszero(call(gas(), target, 0, add(cdPointer, 0x1c), size, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
uint256 internal constant BorrowCalldataSize = 0x24;
uint256 internal constant BorrowHook_Base_Size = 0x0224;
uint256 internal constant BorrowHook_State_Offset = 0x20;
uint256 internal constant BorrowHook_ExtraData_Head_Offset = 0x01e0;
uint256 internal constant BorrowHook_ExtraData_Length_Offset = 0x0200;
uint256 internal constant BorrowHook_ExtraData_TailOffset = 0x0220;
function onBorrow(HooksConfig self, uint256 normalizedAmount, MarketState memory state) internal {
address target = self.hooksAddress();
uint32 onBorrowSelector = uint32(IHooks.onBorrow.selector);
if (self.useOnBorrow()) {
assembly {
let extraCalldataBytes := sub(calldatasize(), BorrowCalldataSize)
let ptr := mload(0x40)
let headPointer := add(ptr, 0x20)
mstore(ptr, onBorrowSelector)
mstore(headPointer, normalizedAmount)
mcopy(add(headPointer, BorrowHook_State_Offset), state, MarketStateSize)
mstore(
add(headPointer, BorrowHook_ExtraData_Head_Offset),
BorrowHook_ExtraData_Length_Offset
)
mstore(add(headPointer, BorrowHook_ExtraData_Length_Offset), extraCalldataBytes)
calldatacopy(
add(headPointer, BorrowHook_ExtraData_TailOffset),
BorrowCalldataSize,
extraCalldataBytes
)
let size := add(RepayHook_Base_Size, extraCalldataBytes)
if iszero(call(gas(), target, 0, add(ptr, 0x1c), size, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
uint256 internal constant RepayHook_Base_Size = 0x0224;
uint256 internal constant RepayHook_State_Offset = 0x20;
uint256 internal constant RepayHook_ExtraData_Head_Offset = 0x01e0;
uint256 internal constant RepayHook_ExtraData_Length_Offset = 0x0200;
uint256 internal constant RepayHook_ExtraData_TailOffset = 0x0220;
function onRepay(
HooksConfig self,
uint256 normalizedAmount,
MarketState memory state,
uint256 baseCalldataSize
) internal {
address target = self.hooksAddress();
uint32 onRepaySelector = uint32(IHooks.onRepay.selector);
if (self.useOnRepay()) {
assembly {
let extraCalldataBytes := sub(calldatasize(), baseCalldataSize)
let ptr := mload(0x40)
let headPointer := add(ptr, 0x20)
mstore(ptr, onRepaySelector)
mstore(headPointer, normalizedAmount)
mcopy(add(headPointer, RepayHook_State_Offset), state, MarketStateSize)
mstore(add(headPointer, RepayHook_ExtraData_Head_Offset), RepayHook_ExtraData_Length_Offset)
mstore(add(headPointer, RepayHook_ExtraData_Length_Offset), extraCalldataBytes)
calldatacopy(
add(headPointer, RepayHook_ExtraData_TailOffset),
baseCalldataSize,
extraCalldataBytes
)
let size := add(RepayHook_Base_Size, extraCalldataBytes)
if iszero(call(gas(), target, 0, add(ptr, 0x1c), size, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
uint256 internal constant CloseMarketCalldataSize = 0x04;
uint256 internal constant CloseMarketHook_Base_Size = 0x0204;
uint256 internal constant CloseMarketHook_ExtraData_Head_Offset = MarketStateSize;
uint256 internal constant CloseMarketHook_ExtraData_Length_Offset = 0x01e0;
uint256 internal constant CloseMarketHook_ExtraData_TailOffset = 0x0200;
function onCloseMarket(HooksConfig self, MarketState memory state) internal {
address target = self.hooksAddress();
uint32 onCloseMarketSelector = uint32(IHooks.onCloseMarket.selector);
if (self.useOnCloseMarket()) {
assembly {
let extraCalldataBytes := sub(calldatasize(), CloseMarketCalldataSize)
let cdPointer := mload(0x40)
let headPointer := add(cdPointer, 0x20)
mstore(cdPointer, onCloseMarketSelector)
mcopy(headPointer, state, MarketStateSize)
mstore(
add(headPointer, CloseMarketHook_ExtraData_Head_Offset),
CloseMarketHook_ExtraData_Length_Offset
)
mstore(add(headPointer, CloseMarketHook_ExtraData_Length_Offset), extraCalldataBytes)
calldatacopy(
add(headPointer, CloseMarketHook_ExtraData_TailOffset),
CloseMarketCalldataSize,
extraCalldataBytes
)
let size := add(CloseMarketHook_Base_Size, extraCalldataBytes)
if iszero(call(gas(), target, 0, add(cdPointer, 0x1c), size, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
uint256 internal constant SetMaxTotalSupplyCalldataSize = 0x24;
uint256 internal constant SetMaxTotalSupplyHook_Base_Size = 0x0224;
uint256 internal constant SetMaxTotalSupplyHook_State_Offset = 0x20;
uint256 internal constant SetMaxTotalSupplyHook_ExtraData_Head_Offset = 0x01e0;
uint256 internal constant SetMaxTotalSupplyHook_ExtraData_Length_Offset = 0x0200;
uint256 internal constant SetMaxTotalSupplyHook_ExtraData_TailOffset = 0x0220;
function onSetMaxTotalSupply(
HooksConfig self,
uint256 maxTotalSupply,
MarketState memory state
) internal {
address target = self.hooksAddress();
uint32 onSetMaxTotalSupplySelector = uint32(IHooks.onSetMaxTotalSupply.selector);
if (self.useOnSetMaxTotalSupply()) {
assembly {
let extraCalldataBytes := sub(calldatasize(), SetMaxTotalSupplyCalldataSize)
let cdPointer := mload(0x40)
let headPointer := add(cdPointer, 0x20)
mstore(cdPointer, onSetMaxTotalSupplySelector)
mstore(headPointer, maxTotalSupply)
mcopy(add(headPointer, SetMaxTotalSupplyHook_State_Offset), state, MarketStateSize)
mstore(
add(headPointer, SetMaxTotalSupplyHook_ExtraData_Head_Offset),
SetMaxTotalSupplyHook_ExtraData_Length_Offset
)
mstore(add(headPointer, SetMaxTotalSupplyHook_ExtraData_Length_Offset), extraCalldataBytes)
calldatacopy(
add(headPointer, SetMaxTotalSupplyHook_ExtraData_TailOffset),
SetMaxTotalSupplyCalldataSize,
extraCalldataBytes
)
let size := add(SetMaxTotalSupplyHook_Base_Size, extraCalldataBytes)
if iszero(call(gas(), target, 0, add(cdPointer, 0x1c), size, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
uint256 internal constant SetAnnualInterestAndReserveRatioBipsCalldataSize = 0x44;
uint256 internal constant SetAnnualInterestAndReserveRatioBipsHook_Base_Size = 0x0244;
uint256 internal constant SetAnnualInterestAndReserveRatioBipsHook_ReserveRatioBits_Offset = 0x20;
uint256 internal constant SetAnnualInterestAndReserveRatioBipsHook_State_Offset = 0x40;
uint256 internal constant SetAnnualInterestAndReserveRatioBipsHook_ExtraData_Head_Offset = 0x0200;
uint256 internal constant SetAnnualInterestAndReserveRatioBipsHook_ExtraData_Length_Offset =
0x0220;
uint256 internal constant SetAnnualInterestAndReserveRatioBipsHook_ExtraData_TailOffset = 0x0240;
function onSetAnnualInterestAndReserveRatioBips(
HooksConfig self,
uint16 annualInterestBips,
uint16 reserveRatioBips,
MarketState memory state
) internal returns (uint16 newAnnualInterestBips, uint16 newReserveRatioBips) {
address target = self.hooksAddress();
uint32 onSetAnnualInterestBipsSelector = uint32(
IHooks.onSetAnnualInterestAndReserveRatioBips.selector
);
if (self.useOnSetAnnualInterestAndReserveRatioBips()) {
assembly {
let extraCalldataBytes := sub(
calldatasize(),
SetAnnualInterestAndReserveRatioBipsCalldataSize
)
let cdPointer := mload(0x40)
let headPointer := add(cdPointer, 0x20)
mstore(cdPointer, onSetAnnualInterestBipsSelector)
mstore(headPointer, annualInterestBips)
mstore(
add(headPointer, SetAnnualInterestAndReserveRatioBipsHook_ReserveRatioBits_Offset),
reserveRatioBips
)
mcopy(
add(headPointer, SetAnnualInterestAndReserveRatioBipsHook_State_Offset),
state,
MarketStateSize
)
mstore(
add(headPointer, SetAnnualInterestAndReserveRatioBipsHook_ExtraData_Head_Offset),
SetAnnualInterestAndReserveRatioBipsHook_ExtraData_Length_Offset
)
mstore(
add(headPointer, SetAnnualInterestAndReserveRatioBipsHook_ExtraData_Length_Offset),
extraCalldataBytes
)
calldatacopy(
add(headPointer, SetAnnualInterestAndReserveRatioBipsHook_ExtraData_TailOffset),
SetAnnualInterestAndReserveRatioBipsCalldataSize,
extraCalldataBytes
)
let size := add(SetAnnualInterestAndReserveRatioBipsHook_Base_Size, extraCalldataBytes)
if or(
lt(returndatasize(), 0x40),
iszero(call(gas(), target, 0, add(cdPointer, 0x1c), size, 0, 0x40))
) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
newAnnualInterestBips := and(mload(0), 0xffff)
newReserveRatioBips := and(mload(0x20), 0xffff)
}
} else {
(newAnnualInterestBips, newReserveRatioBips) = (annualInterestBips, reserveRatioBips);
}
}
uint256 internal constant SetProtocolFeeBipsCalldataSize = 0x24;
uint256 internal constant SetProtocolFeeBips_Base_Size = 0x0224;
uint256 internal constant SetProtocolFeeBips_State_Offset = 0x20;
uint256 internal constant SetProtocolFeeBips_ExtraData_Head_Offset = 0x01e0;
uint256 internal constant SetProtocolFeeBips_ExtraData_Length_Offset = 0x0200;
uint256 internal constant SetProtocolFeeBips_ExtraData_TailOffset = 0x0220;
function onSetProtocolFeeBips(
HooksConfig self,
uint protocolFeeBips,
MarketState memory state
) internal {
address target = self.hooksAddress();
uint32 onSetProtocolFeeBipsSelector = uint32(IHooks.onSetProtocolFeeBips.selector);
if (self.useOnSetProtocolFeeBips()) {
assembly {
let extraCalldataBytes := sub(calldatasize(), SetProtocolFeeBipsCalldataSize)
let cdPointer := mload(0x40)
let headPointer := add(cdPointer, 0x20)
mstore(cdPointer, onSetProtocolFeeBipsSelector)
mstore(headPointer, protocolFeeBips)
mcopy(add(headPointer, SetProtocolFeeBips_State_Offset), state, MarketStateSize)
mstore(
add(headPointer, SetProtocolFeeBips_ExtraData_Head_Offset),
SetProtocolFeeBips_ExtraData_Length_Offset
)
mstore(add(headPointer, SetProtocolFeeBips_ExtraData_Length_Offset), extraCalldataBytes)
calldatacopy(
add(headPointer, SetProtocolFeeBips_ExtraData_TailOffset),
SetProtocolFeeBipsCalldataSize,
extraCalldataBytes
)
let size := add(SetProtocolFeeBips_Base_Size, extraCalldataBytes)
if iszero(call(gas(), target, 0, add(cdPointer, 0x1c), size, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
uint256 internal constant NukeFromOrbitCalldataSize = 0x24;
uint256 internal constant NukeFromOrbit_Base_Size = 0x0224;
uint256 internal constant NukeFromOrbit_State_Offset = 0x20;
uint256 internal constant NukeFromOrbit_ExtraData_Head_Offset = 0x01e0;
uint256 internal constant NukeFromOrbit_ExtraData_Length_Offset = 0x0200;
uint256 internal constant NukeFromOrbit_ExtraData_TailOffset = 0x0220;
function onNukeFromOrbit(HooksConfig self, address lender, MarketState memory state) internal {
address target = self.hooksAddress();
uint32 onNukeFromOrbitSelector = uint32(IHooks.onNukeFromOrbit.selector);
if (self.useOnNukeFromOrbit()) {
assembly {
let extraCalldataBytes := sub(calldatasize(), NukeFromOrbitCalldataSize)
let cdPointer := mload(0x40)
let headPointer := add(cdPointer, 0x20)
mstore(cdPointer, onNukeFromOrbitSelector)
mstore(headPointer, lender)
mcopy(add(headPointer, NukeFromOrbit_State_Offset), state, MarketStateSize)
mstore(
add(headPointer, NukeFromOrbit_ExtraData_Head_Offset),
NukeFromOrbit_ExtraData_Length_Offset
)
mstore(add(headPointer, NukeFromOrbit_ExtraData_Length_Offset), extraCalldataBytes)
calldatacopy(
add(headPointer, NukeFromOrbit_ExtraData_TailOffset),
NukeFromOrbitCalldataSize,
extraCalldataBytes
)
let size := add(NukeFromOrbit_Base_Size, extraCalldataBytes)
if iszero(call(gas(), target, 0, add(cdPointer, 0x1c), size, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
}
文件 7 的 35:IChainalysisSanctionsList.sol
pragma solidity >=0.8.20;
interface IChainalysisSanctionsList {
function isSanctioned(address addr) external view returns (bool);
}
文件 8 的 35:IERC20.sol
pragma solidity >=0.8.20;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 9 的 35:IHooks.sol
pragma solidity ^0.8.20;
import '../types/HooksConfig.sol';
import '../libraries/MarketState.sol';
import '../interfaces/WildcatStructsAndEnums.sol';
abstract contract IHooks {
error CallerNotFactory();
address public immutable factory;
constructor() {
factory = msg.sender;
}
function version() external view virtual returns (string memory);
function config() external view virtual returns (HooksDeploymentConfig);
function onCreateMarket(
address deployer,
address marketAddress,
DeployMarketInputs calldata parameters,
bytes calldata extraData
) external returns (HooksConfig) {
if (msg.sender != factory) revert CallerNotFactory();
return _onCreateMarket(deployer, marketAddress, parameters, extraData);
}
function _onCreateMarket(
address deployer,
address marketAddress,
DeployMarketInputs calldata parameters,
bytes calldata extraData
) internal virtual returns (HooksConfig);
function onDeposit(
address lender,
uint256 scaledAmount,
MarketState calldata intermediateState,
bytes calldata extraData
) external virtual;
function onQueueWithdrawal(
address lender,
uint32 expiry,
uint scaledAmount,
MarketState calldata intermediateState,
bytes calldata extraData
) external virtual;
function onExecuteWithdrawal(
address lender,
uint128 normalizedAmountWithdrawn,
MarketState calldata intermediateState,
bytes calldata extraData
) external virtual;
function onTransfer(
address caller,
address from,
address to,
uint scaledAmount,
MarketState calldata intermediateState,
bytes calldata extraData
) external virtual;
function onBorrow(
uint normalizedAmount,
MarketState calldata intermediateState,
bytes calldata extraData
) external virtual;
function onRepay(
uint normalizedAmount,
MarketState calldata intermediateState,
bytes calldata extraData
) external virtual;
function onCloseMarket(
MarketState calldata intermediateState,
bytes calldata extraData
) external virtual;
function onNukeFromOrbit(
address lender,
MarketState calldata intermediateState,
bytes calldata extraData
) external virtual;
function onSetMaxTotalSupply(
uint256 maxTotalSupply,
MarketState calldata intermediateState,
bytes calldata extraData
) external virtual;
function onSetAnnualInterestAndReserveRatioBips(
uint16 annualInterestBips,
uint16 reserveRatioBips,
MarketState calldata intermediateState,
bytes calldata extraData
) external virtual returns (uint16 updatedAnnualInterestBips, uint16 updatedReserveRatioBips);
function onSetProtocolFeeBips(
uint16 protocolFeeBips,
MarketState memory intermediateState,
bytes calldata extraData
) external virtual;
}
文件 10 的 35:IHooksFactory.sol
pragma solidity ^0.8.20;
import './access/IHooks.sol';
import './interfaces/WildcatStructsAndEnums.sol';
struct HooksTemplate {
address originationFeeAsset;
uint80 originationFeeAmount;
uint16 protocolFeeBips;
bool exists;
bool enabled;
uint24 index;
address feeRecipient;
string name;
}
interface IHooksFactoryEventsAndErrors {
error FeeMismatch();
error NotApprovedBorrower();
error HooksTemplateNotFound();
error HooksTemplateNotAvailable();
error HooksTemplateAlreadyExists();
error DeploymentFailed();
error HooksInstanceNotFound();
error CallerNotArchControllerOwner();
error InvalidFeeConfiguration();
error SaltDoesNotContainSender();
error MarketAlreadyExists();
error HooksInstanceAlreadyExists();
error NameOrSymbolTooLong();
error AssetBlacklisted();
error SetProtocolFeeBipsFailed();
event HooksInstanceDeployed(address hooksInstance, address hooksTemplate);
event HooksTemplateAdded(
address hooksTemplate,
string name,
address feeRecipient,
address originationFeeAsset,
uint80 originationFeeAmount,
uint16 protocolFeeBips
);
event HooksTemplateDisabled(address hooksTemplate);
event HooksTemplateFeesUpdated(
address hooksTemplate,
address feeRecipient,
address originationFeeAsset,
uint80 originationFeeAmount,
uint16 protocolFeeBips
);
event MarketDeployed(
address indexed hooksTemplate,
address indexed market,
string name,
string symbol,
address asset,
uint256 maxTotalSupply,
uint256 annualInterestBips,
uint256 delinquencyFeeBips,
uint256 withdrawalBatchDuration,
uint256 reserveRatioBips,
uint256 delinquencyGracePeriod,
HooksConfig hooks
);
}
interface IHooksFactory is IHooksFactoryEventsAndErrors {
function archController() external view returns (address);
function sanctionsSentinel() external view returns (address);
function marketInitCodeStorage() external view returns (address);
function marketInitCodeHash() external view returns (uint256);
function registerWithArchController() external;
function name() external view returns (string memory);
function addHooksTemplate(
address hooksTemplate,
string calldata name,
address feeRecipient,
address originationFeeAsset,
uint80 originationFeeAmount,
uint16 protocolFeeBips
) external;
function updateHooksTemplateFees(
address hooksTemplate,
address feeRecipient,
address originationFeeAsset,
uint80 originationFeeAmount,
uint16 protocolFeeBips
) external;
function disableHooksTemplate(address hooksTemplate) external;
function getHooksTemplateDetails(
address hooksTemplate
) external view returns (HooksTemplate memory);
function isHooksTemplate(address hooksTemplate) external view returns (bool);
function getHooksTemplates() external view returns (address[] memory);
function getHooksTemplates(
uint256 start,
uint256 end
) external view returns (address[] memory arr);
function getHooksTemplatesCount() external view returns (uint256);
function getMarketsForHooksTemplate(
address hooksTemplate
) external view returns (address[] memory);
function getMarketsForHooksTemplate(
address hooksTemplate,
uint256 start,
uint256 end
) external view returns (address[] memory arr);
function getMarketsForHooksTemplateCount(address hooksTemplate) external view returns (uint256);
function deployHooksInstance(
address hooksTemplate,
bytes calldata constructorArgs
) external returns (address hooksDeployment);
function getHooksInstancesForBorrower(address borrower) external view returns (address[] memory);
function getHooksInstancesCountForBorrower(address borrower) external view returns (uint256);
function isHooksInstance(address hooks) external view returns (bool);
function getHooksTemplateForInstance(address hooks) external view returns (address);
function getMarketsForHooksInstance(
address hooksInstance
) external view returns (address[] memory);
function getMarketsForHooksInstance(
address hooksInstance,
uint256 start,
uint256 len
) external view returns (address[] memory arr);
function getMarketsForHooksInstanceCount(address hooksInstance) external view returns (uint256);
function getMarketParameters() external view returns (MarketParameters memory parameters);
function deployMarket(
DeployMarketInputs calldata parameters,
bytes calldata hooksData,
bytes32 salt,
address originationFeeAsset,
uint256 originationFeeAmount
) external returns (address market);
function deployMarketAndHooks(
address hooksTemplate,
bytes calldata hooksConstructorArgs,
DeployMarketInputs calldata parameters,
bytes calldata hooksData,
bytes32 salt,
address originationFeeAsset,
uint256 originationFeeAmount
) external returns (address market, address hooks);
function computeMarketAddress(bytes32 salt) external view returns (address);
function pushProtocolFeeBipsUpdates(
address hooksTemplate,
uint marketStartIndex,
uint marketEndIndex
) external;
function pushProtocolFeeBipsUpdates(address hooksTemplate) external;
}
文件 11 的 35:IMarketEventsAndErrors.sol
pragma solidity >=0.8.20;
import { MarketState } from '../libraries/MarketState.sol';
interface IMarketEventsAndErrors {
error MaxSupplyExceeded();
error NotApprovedBorrower();
error NotApprovedLender();
error NotFactory();
error BadLaunchCode();
error AccountBlocked();
error BadRescueAsset();
error BorrowAmountTooHigh();
error InsufficientReservesForFeeWithdrawal();
error WithdrawalBatchNotExpired();
error NullMintAmount();
error NullBurnAmount();
error NullFeeAmount();
error NullTransferAmount();
error NullWithdrawalAmount();
error NullRepayAmount();
error NullBuyBackAmount();
error MarketAlreadyClosed();
error DepositToClosedMarket();
error RepayToClosedMarket();
error BuyBackOnDelinquentMarket();
error BorrowWhileSanctioned();
error BorrowFromClosedMarket();
error AprChangeOnClosedMarket();
error CapacityChangeOnClosedMarket();
error ProtocolFeeChangeOnClosedMarket();
error CloseMarketWithUnpaidWithdrawals();
error AnnualInterestBipsTooHigh();
error ReserveRatioBipsTooHigh();
error ProtocolFeeTooHigh();
error InsufficientReservesForNewLiquidityRatio();
error InsufficientReservesForOldLiquidityRatio();
error InvalidArrayLength();
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event MaxTotalSupplyUpdated(uint256 assets);
event ProtocolFeeBipsUpdated(uint256 protocolFeeBips);
event AnnualInterestBipsUpdated(uint256 annualInterestBipsUpdated);
event ReserveRatioBipsUpdated(uint256 reserveRatioBipsUpdated);
event SanctionedAccountAssetsSentToEscrow(
address indexed account,
address escrow,
uint256 amount
);
event SanctionedAccountAssetsQueuedForWithdrawal(
address indexed account,
uint256 expiry,
uint256 scaledAmount,
uint256 normalizedAmount
);
event Deposit(address indexed account, uint256 assetAmount, uint256 scaledAmount);
event Borrow(uint256 assetAmount);
event DebtRepaid(address indexed from, uint256 assetAmount);
event MarketClosed(uint256 timestamp);
event FeesCollected(uint256 assets);
event StateUpdated(uint256 scaleFactor, bool isDelinquent);
event InterestAndFeesAccrued(
uint256 fromTimestamp,
uint256 toTimestamp,
uint256 scaleFactor,
uint256 baseInterestRay,
uint256 delinquencyFeeRay,
uint256 protocolFees
);
event AccountSanctioned(address indexed account);
event WithdrawalBatchExpired(
uint256 indexed expiry,
uint256 scaledTotalAmount,
uint256 scaledAmountBurned,
uint256 normalizedAmountPaid
);
event WithdrawalBatchCreated(uint256 indexed expiry);
event WithdrawalBatchClosed(uint256 indexed expiry);
event WithdrawalBatchPayment(
uint256 indexed expiry,
uint256 scaledAmountBurned,
uint256 normalizedAmountPaid
);
event WithdrawalQueued(
uint256 indexed expiry,
address indexed account,
uint256 scaledAmount,
uint256 normalizedAmount
);
event WithdrawalExecuted(
uint256 indexed expiry,
address indexed account,
uint256 normalizedAmount
);
event SanctionedAccountWithdrawalSentToEscrow(
address indexed account,
address escrow,
uint32 expiry,
uint256 amount
);
}
文件 12 的 35:ISphereXEngine.sol
pragma solidity ^0.8.20;
struct ModifierLocals {
bytes32[] storageSlots;
bytes32[] valuesBefore;
uint256 gas;
address engine;
}
interface ISphereXEngine {
function sphereXValidatePre(
int256 num,
address sender,
bytes calldata data
) external returns (bytes32[] memory);
function sphereXValidatePost(
int256 num,
uint256 gas,
bytes32[] calldata valuesBefore,
bytes32[] calldata valuesAfter
) external;
function sphereXValidateInternalPre(int256 num) external returns (bytes32[] memory);
function sphereXValidateInternalPost(
int256 num,
uint256 gas,
bytes32[] calldata valuesBefore,
bytes32[] calldata valuesAfter
) external;
function addAllowedSenderOnChain(address sender) external;
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 13 的 35:IWildcatSanctionsEscrow.sol
pragma solidity >=0.8.20;
interface IWildcatSanctionsEscrow {
event EscrowReleased(address indexed account, address indexed asset, uint256 amount);
error CanNotReleaseEscrow();
function sentinel() external view returns (address);
function borrower() external view returns (address);
function account() external view returns (address);
function balance() external view returns (uint256);
function canReleaseEscrow() external view returns (bool);
function escrowedAsset() external view returns (address token, uint256 amount);
function releaseEscrow() external;
}
文件 14 的 35:IWildcatSanctionsSentinel.sol
pragma solidity >=0.8.20;
interface IWildcatSanctionsSentinel {
event NewSanctionsEscrow(
address indexed borrower,
address indexed account,
address indexed asset
);
event SanctionOverride(address indexed borrower, address indexed account);
event SanctionOverrideRemoved(address indexed borrower, address indexed account);
struct TmpEscrowParams {
address borrower;
address account;
address asset;
}
function WildcatSanctionsEscrowInitcodeHash() external pure returns (bytes32);
function chainalysisSanctionsList() external view returns (address);
function archController() external view returns (address);
function tmpEscrowParams()
external
view
returns (address borrower, address account, address asset);
function isFlaggedByChainalysis(address account) external view returns (bool);
function isSanctioned(address borrower, address account) external view returns (bool);
function sanctionOverrides(address borrower, address account) external view returns (bool);
function overrideSanction(address account) external;
function removeSanctionOverride(address account) external;
function getEscrowAddress(
address borrower,
address account,
address asset
) external view returns (address escrowContract);
function createEscrow(
address borrower,
address account,
address asset
) external returns (address escrowContract);
}
文件 15 的 35:LibBit.sol
pragma solidity ^0.8.4;
library LibBit {
function fls(uint256 x) internal pure returns (uint256 r) {
assembly {
r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, x)))
r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
r := or(r, shl(4, lt(0xffff, shr(r, x))))
r := or(r, shl(3, lt(0xff, shr(r, x))))
r := or(r, shl(2, lt(0xf, shr(r, x))))
r := or(r, byte(shr(r, x), hex"00000101020202020303030303030303"))
}
}
function clz(uint256 x) internal pure returns (uint256 r) {
assembly {
r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
r := or(r, shl(4, lt(0xffff, shr(r, x))))
r := or(r, shl(3, lt(0xff, shr(r, x))))
r := or(r, shl(2, lt(0xf, shr(r, x))))
r := add(iszero(x), xor(255,
or(r, byte(shr(r, x), hex"00000101020202020303030303030303"))))
}
}
function ffs(uint256 x) internal pure returns (uint256 r) {
assembly {
let b := and(x, add(not(x), 1))
r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, b)))
r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, b))))
r := or(r, shl(5, lt(0xffffffff, shr(r, b))))
r := or(r, byte(and(div(0xd76453e0, shr(r, b)), 0x1f),
0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
}
}
function popCount(uint256 x) internal pure returns (uint256 c) {
assembly {
let max := not(0)
let isMax := eq(x, max)
x := sub(x, and(shr(1, x), div(max, 3)))
x := add(and(x, div(max, 5)), and(shr(2, x), div(max, 5)))
x := and(add(x, shr(4, x)), div(max, 17))
c := or(shl(8, isMax), shr(248, mul(x, div(max, 255))))
}
}
function isPo2(uint256 x) internal pure returns (bool result) {
assembly {
result := iszero(add(and(x, sub(x, 1)), iszero(x)))
}
}
function reverseBits(uint256 x) internal pure returns (uint256 r) {
assembly {
let m := not(0)
r := x
for { let s := 128 } 1 {} {
m := xor(m, shl(s, m))
r := or(and(shr(s, r), m), and(shl(s, r), not(m)))
s := shr(1, s)
if iszero(s) { break }
}
}
}
function reverseBytes(uint256 x) internal pure returns (uint256 r) {
assembly {
let m := not(0)
r := x
for { let s := 128 } 1 {} {
m := xor(m, shl(s, m))
r := or(and(shr(s, r), m), and(shl(s, r), not(m)))
s := shr(1, s)
if eq(s, 4) { break }
}
}
}
function rawAnd(bool x, bool y) internal pure returns (bool z) {
assembly {
z := and(x, y)
}
}
function and(bool x, bool y) internal pure returns (bool z) {
assembly {
z := and(iszero(iszero(x)), iszero(iszero(y)))
}
}
function rawOr(bool x, bool y) internal pure returns (bool z) {
assembly {
z := or(x, y)
}
}
function or(bool x, bool y) internal pure returns (bool z) {
assembly {
z := or(iszero(iszero(x)), iszero(iszero(y)))
}
}
function rawToUint(bool b) internal pure returns (uint256 z) {
assembly {
z := b
}
}
function toUint(bool b) internal pure returns (uint256 z) {
assembly {
z := iszero(iszero(b))
}
}
}
文件 16 的 35:LibERC20.sol
pragma solidity ^0.8.4;
import './StringQuery.sol';
library LibERC20 {
error TransferFromFailed();
error TransferFailed();
error BalanceOfFailed();
error NameFailed();
error SymbolFailed();
error DecimalsFailed();
function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
assembly {
let m := mload(0x40)
mstore(0x60, amount)
mstore(0x40, to)
mstore(0x2c, shl(96, from))
mstore(0x0c, 0x23b872dd000000000000000000000000)
if iszero(
and(
or(eq(mload(0x00), 1), iszero(returndatasize())),
call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
)
) {
mstore(0x00, 0x7939f424)
revert(0x1c, 0x04)
}
mstore(0x60, 0)
mstore(0x40, m)
}
}
function safeTransfer(address token, address to, uint256 amount) internal {
assembly {
mstore(0x14, to)
mstore(0x34, amount)
mstore(0x00, 0xa9059cbb000000000000000000000000)
if iszero(
and(
or(eq(mload(0x00), 1), iszero(returndatasize())),
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x90b8ec18)
revert(0x1c, 0x04)
}
mstore(0x34, 0)
}
}
function safeTransferAll(address token, address to) internal returns (uint256 amount) {
assembly {
mstore(0x00, 0x70a08231)
mstore(0x20, address())
if iszero(
and(
gt(returndatasize(), 0x1f),
staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
)
) {
mstore(0x00, 0x90b8ec18)
revert(0x1c, 0x04)
}
mstore(0x14, to)
amount := mload(0x34)
mstore(0x00, 0xa9059cbb000000000000000000000000)
if iszero(
and(
or(eq(mload(0x00), 1), iszero(returndatasize())),
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x90b8ec18)
revert(0x1c, 0x04)
}
mstore(0x34, 0)
}
}
function balanceOf(address token, address account) internal view returns (uint256 amount) {
assembly {
mstore(0x00, 0x70a08231)
mstore(0x20, account)
if iszero(
and(
gt(returndatasize(), 0x1f),
staticcall(gas(), token, 0x1c, 0x24, 0x00, 0x20)
)
) {
mstore(0x00, 0x4963f6d5)
revert(0x1c, 0x04)
}
amount := mload(0x00)
}
}
function decimals(address token) internal view returns (uint8 _decimals) {
assembly {
mstore(0, 0x313ce567)
if iszero(
and(
and(eq(returndatasize(), 0x20), lt(mload(0), 0x100)),
staticcall(gas(), token, 0x1c, 0x04, 0, 0x20)
)
) {
mstore(0x00, 0x3394d170)
revert(0x1c, 0x04)
}
_decimals := mload(0)
}
}
function name(address token) internal view returns (string memory) {
return queryStringOrBytes32AsString(token, 0x06fdde03, 0x2ed09f54);
}
function symbol(address token) internal view returns (string memory) {
return queryStringOrBytes32AsString(token, 0x95d89b41, 0x3ddcc60a);
}
}
文件 17 的 35:MarketErrors.sol
pragma solidity ^0.8.20;
uint256 constant MaxSupplyExceeded_ErrorSelector = 0x8a164f63;
function revert_MaxSupplyExceeded() pure {
assembly {
mstore(0, 0x8a164f63)
revert(0x1c, 0x04)
}
}
uint256 constant CapacityChangeOnClosedMarket_ErrorSelector = 0x81b21078;
function revert_CapacityChangeOnClosedMarket() pure {
assembly {
mstore(0, 0x81b21078)
revert(0x1c, 0x04)
}
}
uint256 constant AprChangeOnClosedMarket_ErrorSelector = 0xb9de88a2;
function revert_AprChangeOnClosedMarket() pure {
assembly {
mstore(0, 0xb9de88a2)
revert(0x1c, 0x04)
}
}
uint256 constant MarketAlreadyClosed_ErrorSelector = 0x449e5f50;
function revert_MarketAlreadyClosed() pure {
assembly {
mstore(0, 0x449e5f50)
revert(0x1c, 0x04)
}
}
uint256 constant NotApprovedBorrower_ErrorSelector = 0x02171e6a;
function revert_NotApprovedBorrower() pure {
assembly {
mstore(0, 0x02171e6a)
revert(0x1c, 0x04)
}
}
uint256 constant NotApprovedLender_ErrorSelector = 0xe50a45ce;
function revert_NotApprovedLender() pure {
assembly {
mstore(0, 0xe50a45ce)
revert(0x1c, 0x04)
}
}
uint256 constant BadLaunchCode_ErrorSelector = 0xa97ab167;
function revert_BadLaunchCode() pure {
assembly {
mstore(0, 0xa97ab167)
revert(0x1c, 0x04)
}
}
uint256 constant ReserveRatioBipsTooHigh_ErrorSelector = 0x8ec83073;
function revert_ReserveRatioBipsTooHigh() pure {
assembly {
mstore(0, 0x8ec83073)
revert(0x1c, 0x04)
}
}
uint256 constant AnnualInterestBipsTooHigh_ErrorSelector = 0xcf1f916f;
function revert_AnnualInterestBipsTooHigh() pure {
assembly {
mstore(0, 0xcf1f916f)
revert(0x1c, 0x04)
}
}
uint256 constant AccountBlocked_ErrorSelector = 0x6bc671fd;
function revert_AccountBlocked() pure {
assembly {
mstore(0, 0x6bc671fd)
revert(0x1c, 0x04)
}
}
uint256 constant BorrowAmountTooHigh_ErrorSelector = 0x119fe6e3;
function revert_BorrowAmountTooHigh() pure {
assembly {
mstore(0, 0x119fe6e3)
revert(0x1c, 0x04)
}
}
uint256 constant BadRescueAsset_ErrorSelector = 0x11530cde;
function revert_BadRescueAsset() pure {
assembly {
mstore(0, 0x11530cde)
revert(0x1c, 0x04)
}
}
uint256 constant InsufficientReservesForFeeWithdrawal_ErrorSelector = 0xf784cfa4;
function revert_InsufficientReservesForFeeWithdrawal() pure {
assembly {
mstore(0, 0xf784cfa4)
revert(0x1c, 0x04)
}
}
uint256 constant WithdrawalBatchNotExpired_ErrorSelector = 0x2561b880;
function revert_WithdrawalBatchNotExpired() pure {
assembly {
mstore(0, 0x2561b880)
revert(0x1c, 0x04)
}
}
uint256 constant NullMintAmount_ErrorSelector = 0xe4aa5055;
function revert_NullMintAmount() pure {
assembly {
mstore(0, 0xe4aa5055)
revert(0x1c, 0x04)
}
}
uint256 constant NullBurnAmount_ErrorSelector = 0xd61c50f8;
function revert_NullBurnAmount() pure {
assembly {
mstore(0, 0xd61c50f8)
revert(0x1c, 0x04)
}
}
uint256 constant NullFeeAmount_ErrorSelector = 0x45c835cb;
function revert_NullFeeAmount() pure {
assembly {
mstore(0, 0x45c835cb)
revert(0x1c, 0x04)
}
}
uint256 constant NullTransferAmount_ErrorSelector = 0xddee9b30;
function revert_NullTransferAmount() pure {
assembly {
mstore(0, 0xddee9b30)
revert(0x1c, 0x04)
}
}
uint256 constant NullWithdrawalAmount_ErrorSelector = 0x186334fe;
function revert_NullWithdrawalAmount() pure {
assembly {
mstore(0, 0x186334fe)
revert(0x1c, 0x04)
}
}
uint256 constant NullRepayAmount_ErrorSelector = 0x7e082088;
function revert_NullRepayAmount() pure {
assembly {
mstore(0, 0x7e082088)
revert(0x1c, 0x04)
}
}
uint256 constant NullBuyBackAmount_ErrorSelector = 0x50394120;
function revert_NullBuyBackAmount() pure {
assembly {
mstore(0, 0x50394120)
revert(0x1c, 0x04)
}
}
uint256 constant DepositToClosedMarket_ErrorSelector = 0x22d7c043;
function revert_DepositToClosedMarket() pure {
assembly {
mstore(0, 0x22d7c043)
revert(0x1c, 0x04)
}
}
uint256 constant RepayToClosedMarket_ErrorSelector = 0x61d1bc8f;
function revert_RepayToClosedMarket() pure {
assembly {
mstore(0, 0x61d1bc8f)
revert(0x1c, 0x04)
}
}
uint256 constant BuyBackOnDelinquentMarket_Selector = 0x1707a7b7;
function revert_BuyBackOnDelinquentMarket() pure {
assembly {
mstore(0, 0x1707a7b7)
revert(0x1c, 0x04)
}
}
uint256 constant BorrowWhileSanctioned_ErrorSelector = 0x4a1c13a9;
function revert_BorrowWhileSanctioned() pure {
assembly {
mstore(0, 0x4a1c13a9)
revert(0x1c, 0x04)
}
}
uint256 constant BorrowFromClosedMarket_ErrorSelector = 0xd0242b28;
function revert_BorrowFromClosedMarket() pure {
assembly {
mstore(0, 0xd0242b28)
revert(0x1c, 0x04)
}
}
uint256 constant CloseMarketWithUnpaidWithdrawals_ErrorSelector = 0x4d790997;
function revert_CloseMarketWithUnpaidWithdrawals() pure {
assembly {
mstore(0, 0x4d790997)
revert(0x1c, 0x04)
}
}
uint256 constant InsufficientReservesForNewLiquidityRatio_ErrorSelector = 0x253ecbb9;
function revert_InsufficientReservesForNewLiquidityRatio() pure {
assembly {
mstore(0, 0x253ecbb9)
revert(0x1c, 0x04)
}
}
uint256 constant InsufficientReservesForOldLiquidityRatio_ErrorSelector = 0x0a68e5bf;
function revert_InsufficientReservesForOldLiquidityRatio() pure {
assembly {
mstore(0, 0x0a68e5bf)
revert(0x1c, 0x04)
}
}
uint256 constant InvalidArrayLength_ErrorSelector = 0x9d89020a;
function revert_InvalidArrayLength() pure {
assembly {
mstore(0, 0x9d89020a)
revert(0x1c, 0x04)
}
}
uint256 constant ProtocolFeeTooHigh_ErrorSelector = 0x499fddb1;
function revert_ProtocolFeeTooHigh() pure {
assembly {
mstore(0, 0x499fddb1)
revert(0x1c, 0x04)
}
}
uint256 constant ProtocolFeeChangeOnClosedMarket_ErrorSelector = 0x37f1a75f;
function revert_ProtocolFeeChangeOnClosedMarket() pure {
assembly {
mstore(0, 0x37f1a75f)
revert(0x1c, 0x04)
}
}
uint256 constant NotFactory_ErrorSelector = 0x32cc7236;
function revert_NotFactory() pure {
assembly {
mstore(0, 0x32cc7236)
revert(0x1c, 0x04)
}
}
文件 18 的 35:MarketEvents.sol
pragma solidity ^0.8.20;
uint256 constant InterestAndFeesAccrued_abi_head_size = 0xc0;
uint256 constant InterestAndFeesAccrued_toTimestamp_offset = 0x20;
uint256 constant InterestAndFeesAccrued_scaleFactor_offset = 0x40;
uint256 constant InterestAndFeesAccrued_baseInterestRay_offset = 0x60;
uint256 constant InterestAndFeesAccrued_delinquencyFeeRay_offset = 0x80;
uint256 constant InterestAndFeesAccrued_protocolFees_offset = 0xa0;
function emit_Transfer(address from, address to, uint256 value) {
assembly {
mstore(0, value)
log3(0, 0x20, 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, from, to)
}
}
function emit_Approval(address owner, address spender, uint256 value) {
assembly {
mstore(0, value)
log3(
0,
0x20,
0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925,
owner,
spender
)
}
}
function emit_MaxTotalSupplyUpdated(uint256 assets) {
assembly {
mstore(0, assets)
log1(0, 0x20, 0xf2672935fc79f5237559e2e2999dbe743bf65430894ac2b37666890e7c69e1af)
}
}
function emit_ProtocolFeeBipsUpdated(uint256 protocolFeeBips) {
assembly {
mstore(0, protocolFeeBips)
log1(0, 0x20, 0x4b34705283cdb9398d0e50b216b8fb424c6d4def5db9bfadc661ee3adc6076ee)
}
}
function emit_AnnualInterestBipsUpdated(uint256 annualInterestBipsUpdated) {
assembly {
mstore(0, annualInterestBipsUpdated)
log1(0, 0x20, 0xff7b6c8be373823323d3c5d99f5d027dd409dce5db54eae511bbdd5546b75037)
}
}
function emit_ReserveRatioBipsUpdated(uint256 reserveRatioBipsUpdated) {
assembly {
mstore(0, reserveRatioBipsUpdated)
log1(0, 0x20, 0x72877a153052500f5edbb2f9da96a0f45d671d4b4555fdf8628a709dc4eab43a)
}
}
function emit_SanctionedAccountAssetsSentToEscrow(address account, address escrow, uint256 amount) {
assembly {
mstore(0, escrow)
mstore(0x20, amount)
log2(0, 0x40, 0x571e706c2f09ae0632313e5f3ae89fffdedfc370a2ea59a07fb0d8091147645b, account)
}
}
function emit_SanctionedAccountAssetsQueuedForWithdrawal(
address account,
uint32 expiry,
uint256 scaledAmount,
uint256 normalizedAmount
) {
assembly {
let freePointer := mload(0x40)
mstore(0, expiry)
mstore(0x20, scaledAmount)
mstore(0x40, normalizedAmount)
log2(0, 0x60, 0xe12b220b92469ae28fb0d79de531f94161431be9f073b96b8aad3effb88be6fa, account)
mstore(0x40, freePointer)
}
}
function emit_Deposit(address account, uint256 assetAmount, uint256 scaledAmount) {
assembly {
mstore(0, assetAmount)
mstore(0x20, scaledAmount)
log2(0, 0x40, 0x90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15, account)
}
}
function emit_Borrow(uint256 assetAmount) {
assembly {
mstore(0, assetAmount)
log1(0, 0x20, 0xb848ae6b1253b6cb77e81464128ce8bd94d3d524fea54e801e0da869784dca33)
}
}
function emit_DebtRepaid(address from, uint256 assetAmount) {
assembly {
mstore(0, assetAmount)
log2(0, 0x20, 0xe8b606ac1e5df7657db58d297ca8f41c090fc94c5fd2d6958f043e41736e9fa6, from)
}
}
function emit_MarketClosed(uint256 _timestamp) {
assembly {
mstore(0, _timestamp)
log1(0, 0x20, 0x9dc30b8eda31a6a144e092e5de600955523a6a925cc15cc1d1b9b4872cfa6155)
}
}
function emit_FeesCollected(uint256 assets) {
assembly {
mstore(0, assets)
log1(0, 0x20, 0x860c0aa5520013080c2f65981705fcdea474d9f7c3daf954656ed5e65d692d1f)
}
}
function emit_StateUpdated(uint256 scaleFactor, bool isDelinquent) {
assembly {
mstore(0, scaleFactor)
mstore(0x20, isDelinquent)
log1(0, 0x40, 0x9385f9ff65bcd2fb81cece54b27d4ec7376795fc4dcff686e370e347b0ed86c0)
}
}
function emit_InterestAndFeesAccrued(
uint256 fromTimestamp,
uint256 toTimestamp,
uint256 scaleFactor,
uint256 baseInterestRay,
uint256 delinquencyFeeRay,
uint256 protocolFees
) {
assembly {
let dst := mload(0x40)
mstore(dst, fromTimestamp)
mstore(add(dst, InterestAndFeesAccrued_toTimestamp_offset), toTimestamp)
mstore(add(dst, InterestAndFeesAccrued_scaleFactor_offset), scaleFactor)
mstore(add(dst, InterestAndFeesAccrued_baseInterestRay_offset), baseInterestRay)
mstore(add(dst, InterestAndFeesAccrued_delinquencyFeeRay_offset), delinquencyFeeRay)
mstore(add(dst, InterestAndFeesAccrued_protocolFees_offset), protocolFees)
log1(
dst,
InterestAndFeesAccrued_abi_head_size,
0x18247a393d0531b65fbd94f5e78bc5639801a4efda62ae7b43533c4442116c3a
)
}
}
function emit_WithdrawalBatchExpired(
uint256 expiry,
uint256 scaledTotalAmount,
uint256 scaledAmountBurned,
uint256 normalizedAmountPaid
) {
assembly {
let freePointer := mload(0x40)
mstore(0, scaledTotalAmount)
mstore(0x20, scaledAmountBurned)
mstore(0x40, normalizedAmountPaid)
log2(0, 0x60, 0x9262dc39b47cad3a0512e4c08dda248cb345e7163058f300bc63f56bda288b6e, expiry)
mstore(0x40, freePointer)
}
}
function emit_WithdrawalBatchCreated(uint256 expiry) {
assembly {
log2(0, 0x00, 0x5c9a946d3041134198ebefcd814de7748def6576efd3d1b48f48193e183e89ef, expiry)
}
}
function emit_WithdrawalBatchClosed(uint256 expiry) {
assembly {
log2(0, 0x00, 0xcbdf25bf6e096dd9030d89bb2ba2e3e7adb82d25a233c3ca3d92e9f098b74e55, expiry)
}
}
function emit_WithdrawalBatchPayment(
uint256 expiry,
uint256 scaledAmountBurned,
uint256 normalizedAmountPaid
) {
assembly {
mstore(0, scaledAmountBurned)
mstore(0x20, normalizedAmountPaid)
log2(0, 0x40, 0x5272034725119f19d7236de4129fdb5093f0dcb80282ca5edbd587df91d2bd89, expiry)
}
}
function emit_WithdrawalQueued(
uint256 expiry,
address account,
uint256 scaledAmount,
uint256 normalizedAmount
) {
assembly {
mstore(0, scaledAmount)
mstore(0x20, normalizedAmount)
log3(
0,
0x40,
0xecc966b282a372469fa4d3e497c2ac17983c3eaed03f3f17c9acf4b15591663e,
expiry,
account
)
}
}
function emit_WithdrawalExecuted(uint256 expiry, address account, uint256 normalizedAmount) {
assembly {
mstore(0, normalizedAmount)
log3(
0,
0x20,
0xd6cddb3d69146e96ebc2c87b1b3dd0b20ee2d3b0eadf134e011afb434a3e56e6,
expiry,
account
)
}
}
function emit_SanctionedAccountWithdrawalSentToEscrow(
address account,
address escrow,
uint32 expiry,
uint256 amount
) {
assembly {
let freePointer := mload(0x40)
mstore(0, escrow)
mstore(0x20, expiry)
mstore(0x40, amount)
log2(0, 0x60, 0x0d0843a0fcb8b83f625aafb6e42f234ac48c6728b207d52d97cfa8fbd34d498f, account)
mstore(0x40, freePointer)
}
}
文件 19 的 35:MarketState.sol
pragma solidity >=0.8.20;
import './MathUtils.sol';
import './SafeCastLib.sol';
import './FeeMath.sol';
using MarketStateLib for MarketState global;
using MarketStateLib for Account global;
using FeeMath for MarketState global;
struct MarketState {
bool isClosed;
uint128 maxTotalSupply;
uint128 accruedProtocolFees;
uint128 normalizedUnclaimedWithdrawals;
uint104 scaledTotalSupply;
uint104 scaledPendingWithdrawals;
uint32 pendingWithdrawalExpiry;
bool isDelinquent;
uint32 timeDelinquent;
uint16 protocolFeeBips;
uint16 annualInterestBips;
uint16 reserveRatioBips;
uint112 scaleFactor;
uint32 lastInterestAccruedTimestamp;
}
struct Account {
uint104 scaledBalance;
}
library MarketStateLib {
using MathUtils for uint256;
using SafeCastLib for uint256;
function totalSupply(MarketState memory state) internal pure returns (uint256) {
return state.normalizeAmount(state.scaledTotalSupply);
}
function maximumDeposit(MarketState memory state) internal pure returns (uint256) {
return uint256(state.maxTotalSupply).satSub(state.totalSupply());
}
function normalizeAmount(
MarketState memory state,
uint256 amount
) internal pure returns (uint256) {
return amount.rayMul(state.scaleFactor);
}
function scaleAmount(MarketState memory state, uint256 amount) internal pure returns (uint256) {
return amount.rayDiv(state.scaleFactor);
}
function liquidityRequired(
MarketState memory state
) internal pure returns (uint256 _liquidityRequired) {
uint256 scaledWithdrawals = state.scaledPendingWithdrawals;
uint256 scaledRequiredReserves = (state.scaledTotalSupply - scaledWithdrawals).bipMul(
state.reserveRatioBips
) + scaledWithdrawals;
return
state.normalizeAmount(scaledRequiredReserves) +
state.accruedProtocolFees +
state.normalizedUnclaimedWithdrawals;
}
function withdrawableProtocolFees(
MarketState memory state,
uint256 totalAssets
) internal pure returns (uint128) {
uint256 totalAvailableAssets = totalAssets - state.normalizedUnclaimedWithdrawals;
return uint128(MathUtils.min(totalAvailableAssets, state.accruedProtocolFees));
}
function borrowableAssets(
MarketState memory state,
uint256 totalAssets
) internal pure returns (uint256) {
return totalAssets.satSub(state.liquidityRequired());
}
function hasPendingExpiredBatch(MarketState memory state) internal view returns (bool result) {
uint256 expiry = state.pendingWithdrawalExpiry;
assembly {
result := and(gt(expiry, 0), gt(timestamp(), expiry))
}
}
function totalDebts(MarketState memory state) internal pure returns (uint256) {
return
state.normalizeAmount(state.scaledTotalSupply) +
state.normalizedUnclaimedWithdrawals +
state.accruedProtocolFees;
}
}
文件 20 的 35:MathUtils.sol
pragma solidity >=0.8.20;
import './Errors.sol';
uint256 constant BIP = 1e4;
uint256 constant HALF_BIP = 0.5e4;
uint256 constant RAY = 1e27;
uint256 constant HALF_RAY = 0.5e27;
uint256 constant BIP_RAY_RATIO = 1e23;
uint256 constant SECONDS_IN_365_DAYS = 365 days;
library MathUtils {
error MulDivFailed();
using MathUtils for uint256;
function calculateLinearInterestFromBips(
uint256 rateBip,
uint256 timeDelta
) internal pure returns (uint256 result) {
uint256 rate = rateBip.bipToRay();
uint256 accumulatedInterestRay = rate * timeDelta;
unchecked {
return accumulatedInterestRay / SECONDS_IN_365_DAYS;
}
}
function min(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = ternary(a < b, a, b);
}
function max(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = ternary(a < b, b, a);
}
function satSub(uint256 a, uint256 b) internal pure returns (uint256 c) {
assembly {
c := mul(gt(a, b), sub(a, b))
}
}
function satAdd(uint256 a, uint256 b, uint256 maxValue) internal pure returns (uint256 c) {
unchecked {
c = a + b;
return ternary(c < maxValue, c, maxValue);
}
}
function ternary(
bool condition,
uint256 valueIfTrue,
uint256 valueIfFalse
) internal pure returns (uint256 c) {
assembly {
c := add(valueIfFalse, mul(condition, sub(valueIfTrue, valueIfFalse)))
}
}
function bipMul(uint256 a, uint256 b) internal pure returns (uint256 c) {
assembly {
if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_BIP), b))))) {
mstore(0, Panic_ErrorSelector)
mstore(Panic_ErrorCodePointer, Panic_Arithmetic)
revert(Error_SelectorPointer, Panic_ErrorLength)
}
c := div(add(mul(a, b), HALF_BIP), BIP)
}
}
function bipDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
assembly {
if or(iszero(b), gt(a, div(sub(not(0), div(b, 2)), BIP))) {
mstore(0, Panic_ErrorSelector)
mstore(Panic_ErrorCodePointer, Panic_Arithmetic)
revert(Error_SelectorPointer, Panic_ErrorLength)
}
c := div(add(mul(a, BIP), div(b, 2)), b)
}
}
function bipToRay(uint256 a) internal pure returns (uint256 b) {
assembly {
b := mul(a, BIP_RAY_RATIO)
if iszero(eq(div(b, BIP_RAY_RATIO), a)) {
mstore(0, Panic_ErrorSelector)
mstore(Panic_ErrorCodePointer, Panic_Arithmetic)
revert(Error_SelectorPointer, Panic_ErrorLength)
}
}
}
function rayMul(uint256 a, uint256 b) internal pure returns (uint256 c) {
assembly {
if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_RAY), b))))) {
mstore(0, Panic_ErrorSelector)
mstore(Panic_ErrorCodePointer, Panic_Arithmetic)
revert(Error_SelectorPointer, Panic_ErrorLength)
}
c := div(add(mul(a, b), HALF_RAY), RAY)
}
}
function rayDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {
assembly {
if or(iszero(b), gt(a, div(sub(not(0), div(b, 2)), RAY))) {
mstore(0, Panic_ErrorSelector)
mstore(Panic_ErrorCodePointer, Panic_Arithmetic)
revert(Error_SelectorPointer, Panic_ErrorLength)
}
c := div(add(mul(a, RAY), div(b, 2)), b)
}
}
function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
assembly {
if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {
mstore(0x00, 0xad251c27)
revert(0x1c, 0x04)
}
z := div(mul(x, y), d)
}
}
function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
assembly {
if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {
mstore(0x00, 0xad251c27)
revert(0x1c, 0x04)
}
z := add(iszero(iszero(mod(mul(x, y), d))), div(mul(x, y), d))
}
}
}
文件 21 的 35:ReentrancyGuard.sol
pragma solidity >=0.8.20;
uint256 constant NoReentrantCalls_ErrorSelector = 0x7fa8a987;
uint256 constant _REENTRANCY_GUARD_SLOT = 0x929eee14;
contract ReentrancyGuard {
error NoReentrantCalls();
uint256 private constant _NOT_ENTERED = 0;
uint256 private constant _ENTERED = 1;
modifier nonReentrant() {
_setReentrancyGuard();
_;
_clearReentrancyGuard();
}
modifier nonReentrantView() {
_assertNonReentrant();
_;
}
function _setReentrancyGuard() internal {
assembly {
let _reentrancyGuard := tload(_REENTRANCY_GUARD_SLOT)
if _reentrancyGuard {
mstore(0, NoReentrantCalls_ErrorSelector)
revert(0x1c, 0x04)
}
tstore(_REENTRANCY_GUARD_SLOT, _ENTERED)
}
}
function _clearReentrancyGuard() internal {
assembly {
tstore(_REENTRANCY_GUARD_SLOT, _NOT_ENTERED)
}
}
function _assertNonReentrant() internal view {
assembly {
if tload(_REENTRANCY_GUARD_SLOT) {
mstore(0, NoReentrantCalls_ErrorSelector)
revert(0x1c, 0x04)
}
}
}
}
文件 22 的 35:SafeCastLib.sol
pragma solidity >=0.8.20;
import './Errors.sol';
library SafeCastLib {
function _assertNonOverflow(bool didNotOverflow) private pure {
assembly {
if iszero(didNotOverflow) {
mstore(0, Panic_ErrorSelector)
mstore(Panic_ErrorCodePointer, Panic_Arithmetic)
revert(Error_SelectorPointer, Panic_ErrorLength)
}
}
}
function toUint8(uint256 x) internal pure returns (uint8 y) {
_assertNonOverflow(x == (y = uint8(x)));
}
function toUint16(uint256 x) internal pure returns (uint16 y) {
_assertNonOverflow(x == (y = uint16(x)));
}
function toUint24(uint256 x) internal pure returns (uint24 y) {
_assertNonOverflow(x == (y = uint24(x)));
}
function toUint32(uint256 x) internal pure returns (uint32 y) {
_assertNonOverflow(x == (y = uint32(x)));
}
function toUint40(uint256 x) internal pure returns (uint40 y) {
_assertNonOverflow(x == (y = uint40(x)));
}
function toUint48(uint256 x) internal pure returns (uint48 y) {
_assertNonOverflow(x == (y = uint48(x)));
}
function toUint56(uint256 x) internal pure returns (uint56 y) {
_assertNonOverflow(x == (y = uint56(x)));
}
function toUint64(uint256 x) internal pure returns (uint64 y) {
_assertNonOverflow(x == (y = uint64(x)));
}
function toUint72(uint256 x) internal pure returns (uint72 y) {
_assertNonOverflow(x == (y = uint72(x)));
}
function toUint80(uint256 x) internal pure returns (uint80 y) {
_assertNonOverflow(x == (y = uint80(x)));
}
function toUint88(uint256 x) internal pure returns (uint88 y) {
_assertNonOverflow(x == (y = uint88(x)));
}
function toUint96(uint256 x) internal pure returns (uint96 y) {
_assertNonOverflow(x == (y = uint96(x)));
}
function toUint104(uint256 x) internal pure returns (uint104 y) {
_assertNonOverflow(x == (y = uint104(x)));
}
function toUint112(uint256 x) internal pure returns (uint112 y) {
_assertNonOverflow(x == (y = uint112(x)));
}
function toUint120(uint256 x) internal pure returns (uint120 y) {
_assertNonOverflow(x == (y = uint120(x)));
}
function toUint128(uint256 x) internal pure returns (uint128 y) {
_assertNonOverflow(x == (y = uint128(x)));
}
function toUint136(uint256 x) internal pure returns (uint136 y) {
_assertNonOverflow(x == (y = uint136(x)));
}
function toUint144(uint256 x) internal pure returns (uint144 y) {
_assertNonOverflow(x == (y = uint144(x)));
}
function toUint152(uint256 x) internal pure returns (uint152 y) {
_assertNonOverflow(x == (y = uint152(x)));
}
function toUint160(uint256 x) internal pure returns (uint160 y) {
_assertNonOverflow(x == (y = uint160(x)));
}
function toUint168(uint256 x) internal pure returns (uint168 y) {
_assertNonOverflow(x == (y = uint168(x)));
}
function toUint176(uint256 x) internal pure returns (uint176 y) {
_assertNonOverflow(x == (y = uint176(x)));
}
function toUint184(uint256 x) internal pure returns (uint184 y) {
_assertNonOverflow(x == (y = uint184(x)));
}
function toUint192(uint256 x) internal pure returns (uint192 y) {
_assertNonOverflow(x == (y = uint192(x)));
}
function toUint200(uint256 x) internal pure returns (uint200 y) {
_assertNonOverflow(x == (y = uint200(x)));
}
function toUint208(uint256 x) internal pure returns (uint208 y) {
_assertNonOverflow(x == (y = uint208(x)));
}
function toUint216(uint256 x) internal pure returns (uint216 y) {
_assertNonOverflow(x == (y = uint216(x)));
}
function toUint224(uint256 x) internal pure returns (uint224 y) {
_assertNonOverflow(x == (y = uint224(x)));
}
function toUint232(uint256 x) internal pure returns (uint232 y) {
_assertNonOverflow(x == (y = uint232(x)));
}
function toUint240(uint256 x) internal pure returns (uint240 y) {
_assertNonOverflow(x == (y = uint240(x)));
}
function toUint248(uint256 x) internal pure returns (uint248 y) {
_assertNonOverflow(x == (y = uint248(x)));
}
}
文件 23 的 35:SphereXProtectedErrors.sol
pragma solidity ^0.8.20;
function revert_SphereXOperatorRequired() pure {
assembly {
mstore(0, 0x4ee0b8f8)
revert(0x1c, 0x04)
}
}
function revert_SphereXAdminRequired() pure {
assembly {
mstore(0, 0x6222a550)
revert(0x1c, 0x04)
}
}
function revert_SphereXOperatorOrAdminRequired() pure {
assembly {
mstore(0, 0xb2dbeb59)
revert(0x1c, 0x04)
}
}
function revert_SphereXNotPendingAdmin() pure {
assembly {
mstore(0, 0x4d28a58e)
revert(0x1c, 0x04)
}
}
function revert_SphereXNotEngine() pure {
assembly {
mstore(0, 0x7dcb7ada)
revert(0x1c, 0x04)
}
}
文件 24 的 35:SphereXProtectedEvents.sol
pragma solidity ^0.8.20;
function emit_ChangedSpherexOperator(address oldSphereXAdmin, address newSphereXAdmin) {
assembly {
mstore(0, oldSphereXAdmin)
mstore(0x20, newSphereXAdmin)
log1(0, 0x40, 0x2ac55ae7ba47db34b5334622acafeb34a65daf143b47019273185d64c73a35a5)
}
}
function emit_ChangedSpherexEngineAddress(address oldEngineAddress, address newEngineAddress) {
assembly {
mstore(0, oldEngineAddress)
mstore(0x20, newEngineAddress)
log1(0, 0x40, 0xf33499cccaa0611882086224cc48cd82ef54b66a4d2edf4ed67108dd516896d5)
}
}
function emit_SpherexAdminTransferStarted(address currentAdmin, address pendingAdmin) {
assembly {
mstore(0, currentAdmin)
mstore(0x20, pendingAdmin)
log1(0, 0x40, 0x5778f1547abbbb86090a43c32aec38334b31df4beeb6f8f3fa063f593b53a526)
}
}
function emit_SpherexAdminTransferCompleted(address oldAdmin, address newAdmin) {
assembly {
mstore(0, oldAdmin)
mstore(0x20, newAdmin)
log1(0, 0x40, 0x67ebaebcd2ca5a91a404e898110f221747e8d15567f2388a34794aab151cf3e6)
}
}
function emit_NewAllowedSenderOnchain(address sender) {
assembly {
mstore(0, sender)
log1(0, 0x20, 0x6de0a1fd3a59e5479e6480ba65ef28d4f3ab8143c2c631bbfd9969ab39074797)
}
}
文件 25 的 35:SphereXProtectedRegisteredBase.sol
pragma solidity ^0.8.20;
import { ISphereXEngine, ModifierLocals } from './ISphereXEngine.sol';
import './SphereXProtectedEvents.sol';
import './SphereXProtectedErrors.sol';
abstract contract SphereXProtectedRegisteredBase {
bytes32 private constant SPHEREX_ENGINE_STORAGE_SLOT =
bytes32(uint256(keccak256('eip1967.spherex.spherex_engine')) - 1);
address internal immutable _archController;
function __SphereXProtectedRegisteredBase_init(address engine) internal virtual {
emit_ChangedSpherexOperator(address(0), _archController);
_setAddress(SPHEREX_ENGINE_STORAGE_SLOT, engine);
emit_ChangedSpherexEngineAddress(address(0), engine);
}
error SphereXOperatorRequired();
event ChangedSpherexOperator(address oldSphereXAdmin, address newSphereXAdmin);
event ChangedSpherexEngineAddress(address oldEngineAddress, address newEngineAddress);
modifier spherexOnlyOperator() {
if (msg.sender != _archController) {
revert_SphereXOperatorRequired();
}
_;
}
modifier returnsIfNotActivatedPre(ModifierLocals memory locals) {
locals.engine = sphereXEngine();
if (locals.engine == address(0)) {
return;
}
_;
}
modifier returnsIfNotActivatedPost(ModifierLocals memory locals) {
if (locals.engine == address(0)) {
return;
}
_;
}
function sphereXOperator() public view returns (address) {
return _archController;
}
function sphereXEngine() public view returns (address) {
return _getAddress(SPHEREX_ENGINE_STORAGE_SLOT);
}
function changeSphereXEngine(address newSphereXEngine) external spherexOnlyOperator {
address oldEngine = _getAddress(SPHEREX_ENGINE_STORAGE_SLOT);
_setAddress(SPHEREX_ENGINE_STORAGE_SLOT, newSphereXEngine);
emit_ChangedSpherexEngineAddress(oldEngine, newSphereXEngine);
}
function _sphereXValidateExternalPre() internal returns (uint256 localsPointer) {
return _castFunctionToPointerOutput(_getStorageSlotsAndPreparePostCalldata)(_getSelector());
}
function _getStorageSlotsAndPreparePostCalldata(
int256 num
) internal returnsIfNotActivatedPre(locals) returns (ModifierLocals memory locals) {
assembly {
let engineAddress := mload(add(locals, 0x60))
let pointer := mload(0x40)
mstore(pointer, 0x8925ca5a)
mstore(add(pointer, 0x20), num)
mstore(add(pointer, 0x40), caller())
mstore(add(pointer, 0x60), 0x60)
mstore(add(pointer, 0x80), calldatasize())
calldatacopy(add(pointer, 0xa0), 0, calldatasize())
let size := add(0xc4, calldatasize())
if iszero(
and(eq(mload(0), 0x20), call(gas(), engineAddress, 0, add(pointer, 28), size, 0, 0x40))
) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
let length := mload(0x20)
let arrayDataSize := shl(5, length)
mstore(0x40, add(pointer, add(0xe0, mul(arrayDataSize, 3))))
returndatacopy(pointer, 0x20, add(arrayDataSize, 0x20))
mstore(locals, pointer)
let calldataPointer := add(pointer, add(arrayDataSize, 0x20))
mstore(calldataPointer, sub(0, num))
mstore(add(calldataPointer, 0x40), 0x80)
mstore(add(locals, 0x20), add(calldataPointer, 0x80))
mstore(add(calldataPointer, 0x60), add(0xa0, arrayDataSize))
mstore(add(locals, 0x40), gas())
}
_readStorageTo(locals.storageSlots, locals.valuesBefore);
}
function _sphereXValidateExternalPost(uint256 locals) internal {
_castFunctionToPointerInput(_callSphereXValidatePost)(locals);
}
function _callSphereXValidatePost(
ModifierLocals memory locals
) internal returnsIfNotActivatedPost(locals) {
uint256 length;
bytes32[] memory storageSlots;
bytes32[] memory valuesAfter;
assembly {
storageSlots := mload(locals)
length := mload(storageSlots)
valuesAfter := add(storageSlots, add(0xc0, shl(6, length)))
}
_readStorageTo(storageSlots, valuesAfter);
assembly {
let sphereXEngineAddress := mload(add(locals, 0x60))
let arrayDataSize := shl(5, length)
let calldataSize := add(0xc4, shl(1, arrayDataSize))
let calldataPointer := add(storageSlots, add(arrayDataSize, 0x20))
let gasDiff := sub(mload(add(locals, 0x40)), gas())
mstore(add(calldataPointer, 0x20), gasDiff)
let slotBefore := sub(calldataPointer, 32)
let slotBeforeCache := mload(slotBefore)
mstore(slotBefore, 0xf0bd9468)
if iszero(call(gas(), sphereXEngineAddress, 0, add(slotBefore, 28), calldataSize, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
mstore(slotBefore, slotBeforeCache)
}
}
function _getSelector() internal pure returns (int256 selector) {
assembly {
selector := shr(224, calldataload(0))
}
}
modifier sphereXGuardExternal() {
uint256 localsPointer = _sphereXValidateExternalPre();
_;
_sphereXValidateExternalPost(localsPointer);
}
function _setAddress(bytes32 slot, address newAddress) internal {
assembly {
sstore(slot, newAddress)
}
}
function _getAddress(bytes32 slot) internal view returns (address addr) {
assembly {
addr := sload(slot)
}
}
function _readStorageTo(bytes32[] memory storageSlots, bytes32[] memory values) internal view {
assembly {
let length := mload(storageSlots)
let arrayDataSize := shl(5, length)
mstore(values, length)
let nextSlotPointer := add(storageSlots, 0x20)
let nextElementPointer := add(values, 0x20)
let endPointer := add(nextElementPointer, shl(5, length))
for {
} lt(nextElementPointer, endPointer) {
} {
mstore(nextElementPointer, sload(mload(nextSlotPointer)))
nextElementPointer := add(nextElementPointer, 0x20)
nextSlotPointer := add(nextSlotPointer, 0x20)
}
}
}
function _castFunctionToPointerInput(
function(ModifierLocals memory) internal fnIn
) internal pure returns (function(uint256) internal fnOut) {
assembly {
fnOut := fnIn
}
}
function _castFunctionToPointerOutput(
function(int256) internal returns (ModifierLocals memory) fnIn
) internal pure returns (function(int256) internal returns (uint256) fnOut) {
assembly {
fnOut := fnIn
}
}
}
文件 26 的 35:StringQuery.sol
pragma solidity >=0.8.20;
import { LibBit } from 'solady/utils/LibBit.sol';
using LibBit for uint256;
uint256 constant OnlyFullWordMask = 0xffffffe0;
function bytes32ToString(bytes32 value) pure returns (string memory str) {
uint256 size;
unchecked {
uint256 sizeInBits = 255 - uint256(value).ffs();
size = (sizeInBits + 7) / 8;
}
assembly {
str := mload(0x40)
mstore(0x40, add(str, 0x40))
mstore(str, size)
mstore(add(str, 0x20), value)
}
}
function queryStringOrBytes32AsString(
address target,
uint256 leftPaddedFunctionSelector,
uint256 leftPaddedGenericErrorSelector
) view returns (string memory str) {
bool isBytes32;
assembly {
mstore(0, leftPaddedFunctionSelector)
let status := staticcall(gas(), target, 0x1c, 0x04, 0, 0)
isBytes32 := eq(returndatasize(), 0x20)
if or(iszero(status), iszero(or(isBytes32, gt(returndatasize(), 0x5f)))) {
if iszero(status) {
if returndatasize() {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
mstore(0, leftPaddedGenericErrorSelector)
revert(0x1c, 0x04)
}
mstore(0, 0x4cb9c000)
revert(0x1c, 0x04)
}
}
if (isBytes32) {
bytes32 value;
assembly {
returndatacopy(0x00, 0x00, 0x20)
value := mload(0)
}
str = bytes32ToString(value);
} else {
assembly {
str := mload(0x40)
let allocSize := and(sub(returndatasize(), 1), OnlyFullWordMask)
mstore(0x40, add(str, allocSize))
returndatacopy(str, 0x20, sub(returndatasize(), 0x20))
let length := mload(str)
let expectedReturndataSize := add(allocSize, 0x20)
if xor(returndatasize(), expectedReturndataSize) {
mstore(0, 0x4cb9c000)
revert(0x1c, 0x04)
}
}
}
}
文件 27 的 35:WildcatMarket.sol
pragma solidity >=0.8.20;
import './WildcatMarketBase.sol';
import './WildcatMarketConfig.sol';
import './WildcatMarketToken.sol';
import './WildcatMarketWithdrawals.sol';
import '../WildcatSanctionsSentinel.sol';
contract WildcatMarket is
WildcatMarketBase,
WildcatMarketConfig,
WildcatMarketToken,
WildcatMarketWithdrawals
{
using MathUtils for uint256;
using SafeCastLib for uint256;
using LibERC20 for address;
using BoolUtils for bool;
function updateState() external nonReentrant sphereXGuardExternal {
MarketState memory state = _getUpdatedState();
_writeState(state);
}
function rescueTokens(address token) external nonReentrant onlyBorrower {
if ((token == asset).or(token == address(this))) {
revert_BadRescueAsset();
}
token.safeTransferAll(msg.sender);
}
function _depositUpTo(
uint256 amount
) internal virtual nonReentrant returns (uint256 ) {
MarketState memory state = _getUpdatedState();
if (state.isClosed) revert_DepositToClosedMarket();
amount = MathUtils.min(amount, state.maximumDeposit());
uint104 scaledAmount = state.scaleAmount(amount).toUint104();
if (scaledAmount == 0) revert_NullMintAmount();
Account memory account = _getAccount(msg.sender);
hooks.onDeposit(msg.sender, scaledAmount, state);
asset.safeTransferFrom(msg.sender, address(this), amount);
account.scaledBalance += scaledAmount;
_accounts[msg.sender] = account;
emit_Transfer(_runtimeConstant(address(0)), msg.sender, amount);
emit_Deposit(msg.sender, amount, scaledAmount);
state.scaledTotalSupply += scaledAmount;
_writeState(state);
return amount;
}
function depositUpTo(
uint256 amount
) external virtual sphereXGuardExternal returns (uint256 ) {
return _depositUpTo(amount);
}
function deposit(uint256 amount) external virtual sphereXGuardExternal {
uint256 actualAmount = _depositUpTo(amount);
if (amount != actualAmount) revert_MaxSupplyExceeded();
}
function collectFees() external nonReentrant sphereXGuardExternal {
MarketState memory state = _getUpdatedState();
if (state.accruedProtocolFees == 0) revert_NullFeeAmount();
uint128 withdrawableFees = state.withdrawableProtocolFees(totalAssets());
if (withdrawableFees == 0) revert_InsufficientReservesForFeeWithdrawal();
state.accruedProtocolFees -= withdrawableFees;
asset.safeTransfer(feeRecipient, withdrawableFees);
_writeState(state);
emit_FeesCollected(withdrawableFees);
}
function borrow(uint256 amount) external onlyBorrower nonReentrant sphereXGuardExternal {
if (_isFlaggedByChainalysis(borrower)) {
revert_BorrowWhileSanctioned();
}
MarketState memory state = _getUpdatedState();
if (state.isClosed) revert_BorrowFromClosedMarket();
uint256 borrowable = state.borrowableAssets(totalAssets());
if (amount > borrowable) revert_BorrowAmountTooHigh();
hooks.onBorrow(amount, state);
asset.safeTransfer(msg.sender, amount);
_writeState(state);
emit_Borrow(amount);
}
function _repay(MarketState memory state, uint256 amount, uint256 baseCalldataSize) internal {
if (amount == 0) revert_NullRepayAmount();
if (state.isClosed) revert_RepayToClosedMarket();
asset.safeTransferFrom(msg.sender, address(this), amount);
emit_DebtRepaid(msg.sender, amount);
hooks.onRepay(amount, state, baseCalldataSize);
}
function repay(uint256 amount) external nonReentrant sphereXGuardExternal {
if (amount == 0) revert_NullRepayAmount();
asset.safeTransferFrom(msg.sender, address(this), amount);
emit_DebtRepaid(msg.sender, amount);
MarketState memory state = _getUpdatedState();
if (state.isClosed) revert_RepayToClosedMarket();
hooks.onRepay(amount, state, _runtimeConstant(0x24));
_writeState(state);
}
function closeMarket() external onlyBorrower nonReentrant sphereXGuardExternal {
MarketState memory state = _getUpdatedState();
if (state.isClosed) revert_MarketAlreadyClosed();
uint256 currentlyHeld = totalAssets();
uint256 totalDebts = state.totalDebts();
if (currentlyHeld < totalDebts) {
uint256 remainingDebt = totalDebts - currentlyHeld;
_repay(state, remainingDebt, 0x04);
currentlyHeld += remainingDebt;
} else if (currentlyHeld > totalDebts) {
uint256 excessDebt = currentlyHeld - totalDebts;
asset.safeTransfer(borrower, excessDebt);
currentlyHeld -= excessDebt;
}
hooks.onCloseMarket(state);
state.annualInterestBips = 0;
state.isClosed = true;
state.reserveRatioBips = 10000;
state.timeDelinquent = 0;
uint256 availableLiquidity = currentlyHeld -
(state.normalizedUnclaimedWithdrawals + state.accruedProtocolFees);
if (state.pendingWithdrawalExpiry != 0) {
uint32 expiry = state.pendingWithdrawalExpiry;
WithdrawalBatch memory batch = _withdrawalData.batches[expiry];
if (batch.scaledAmountBurned < batch.scaledTotalAmount) {
(, uint128 normalizedAmountPaid) = _applyWithdrawalBatchPayment(
batch,
state,
expiry,
availableLiquidity
);
availableLiquidity -= normalizedAmountPaid;
_withdrawalData.batches[expiry] = batch;
}
state.pendingWithdrawalExpiry = 0;
emit_WithdrawalBatchExpired(
expiry,
batch.scaledTotalAmount,
batch.scaledAmountBurned,
batch.normalizedAmountPaid
);
emit_WithdrawalBatchClosed(expiry);
if (expiry == block.timestamp) {
uint32 newExpiry = expiry + 1;
emit_WithdrawalBatchCreated(newExpiry);
state.pendingWithdrawalExpiry = newExpiry;
}
}
uint256 numBatches = _withdrawalData.unpaidBatches.length();
for (uint256 i; i < numBatches; i++) {
uint256 normalizedAmountPaid = _processUnpaidWithdrawalBatch(state, availableLiquidity);
availableLiquidity -= normalizedAmountPaid;
}
if (state.scaledPendingWithdrawals != 0) {
revert_CloseMarketWithUnpaidWithdrawals();
}
_writeState(state);
emit_MarketClosed(block.timestamp);
}
function _blockAccount(MarketState memory state, address accountAddress) internal override {
Account memory account = _accounts[accountAddress];
if (account.scaledBalance > 0) {
uint104 scaledAmount = account.scaledBalance;
uint256 normalizedAmount = state.normalizeAmount(scaledAmount);
uint32 expiry = _queueWithdrawal(
state,
account,
accountAddress,
scaledAmount,
normalizedAmount,
msg.data.length
);
emit_SanctionedAccountAssetsQueuedForWithdrawal(
accountAddress,
expiry,
scaledAmount,
normalizedAmount
);
}
}
}
文件 28 的 35:WildcatMarketBase.sol
pragma solidity >=0.8.20;
import '../ReentrancyGuard.sol';
import '../spherex/SphereXProtectedRegisteredBase.sol';
import '../interfaces/IMarketEventsAndErrors.sol';
import '../interfaces/IERC20.sol';
import '../IHooksFactory.sol';
import '../libraries/FeeMath.sol';
import '../libraries/MarketErrors.sol';
import '../libraries/MarketEvents.sol';
import '../libraries/Withdrawal.sol';
import '../libraries/FunctionTypeCasts.sol';
import '../libraries/LibERC20.sol';
import '../types/HooksConfig.sol';
contract WildcatMarketBase is
SphereXProtectedRegisteredBase,
ReentrancyGuard,
IMarketEventsAndErrors
{
using SafeCastLib for uint256;
using MathUtils for uint256;
using FunctionTypeCasts for *;
using LibERC20 for address;
function version() external pure returns (string memory) {
assembly {
mstore(0x40, 0)
mstore(0x41, 0x0132)
mstore(0x20, 0x20)
return(0x20, 0x60)
}
}
HooksConfig public immutable hooks;
address public immutable sentinel;
address public immutable borrower;
address public immutable factory;
address public immutable feeRecipient;
uint public immutable delinquencyFeeBips;
uint public immutable delinquencyGracePeriod;
uint public immutable withdrawalBatchDuration;
uint8 public immutable decimals;
address public immutable asset;
bytes32 internal immutable PACKED_NAME_WORD_0;
bytes32 internal immutable PACKED_NAME_WORD_1;
bytes32 internal immutable PACKED_SYMBOL_WORD_0;
bytes32 internal immutable PACKED_SYMBOL_WORD_1;
function symbol() external view returns (string memory) {
bytes32 symbolWord0 = PACKED_SYMBOL_WORD_0;
bytes32 symbolWord1 = PACKED_SYMBOL_WORD_1;
assembly {
mstore(0, 0x20)
mstore(0x20, 0)
mstore(0x3f, symbolWord0)
mstore(0x5f, symbolWord1)
return(0, 0x80)
}
}
function name() external view returns (string memory) {
bytes32 nameWord0 = PACKED_NAME_WORD_0;
bytes32 nameWord1 = PACKED_NAME_WORD_1;
assembly {
mstore(0, 0x20)
mstore(0x20, 0)
mstore(0x3f, nameWord0)
mstore(0x5f, nameWord1)
return(0, 0x80)
}
}
function archController() external view returns (address) {
return _archController;
}
MarketState internal _state;
mapping(address => Account) internal _accounts;
WithdrawalData internal _withdrawalData;
function _getMarketParameters() internal view returns (uint256 marketParametersPointer) {
assembly {
marketParametersPointer := mload(0x40)
mstore(0x40, add(marketParametersPointer, 0x260))
mstore(0x00, 0x04032dbb)
if iszero(
and(
eq(returndatasize(), 0x260),
staticcall(gas(), caller(), 0x1c, 0x04, marketParametersPointer, 0x260)
)
) {
revert(0, 0)
}
}
}
constructor() {
factory = msg.sender;
MarketParameters memory parameters = _getMarketParameters.asReturnsMarketParameters()();
asset = parameters.asset;
decimals = parameters.decimals;
PACKED_NAME_WORD_0 = parameters.packedNameWord0;
PACKED_NAME_WORD_1 = parameters.packedNameWord1;
PACKED_SYMBOL_WORD_0 = parameters.packedSymbolWord0;
PACKED_SYMBOL_WORD_1 = parameters.packedSymbolWord1;
{
uint maxTotalSupply = parameters.maxTotalSupply;
uint reserveRatioBips = parameters.reserveRatioBips;
uint annualInterestBips = parameters.annualInterestBips;
uint protocolFeeBips = parameters.protocolFeeBips;
assembly {
let slot0 := shl(8, maxTotalSupply)
sstore(_state.slot, slot0)
let slot3 := or(
or(or(shl(0xc0, timestamp()), shl(0x50, RAY)), shl(0x40, reserveRatioBips)),
or(shl(0x30, annualInterestBips), shl(0x20, protocolFeeBips))
)
sstore(add(_state.slot, 3), slot3)
}
}
hooks = parameters.hooks;
sentinel = parameters.sentinel;
borrower = parameters.borrower;
feeRecipient = parameters.feeRecipient;
delinquencyFeeBips = parameters.delinquencyFeeBips;
delinquencyGracePeriod = parameters.delinquencyGracePeriod;
withdrawalBatchDuration = parameters.withdrawalBatchDuration;
_archController = parameters.archController;
__SphereXProtectedRegisteredBase_init(parameters.sphereXEngine);
}
modifier onlyBorrower() {
address _borrower = borrower;
assembly {
if xor(caller(), _borrower) {
mstore(0, 0x02171e6a)
revert(0x1c, 0x04)
}
}
_;
}
function _getAccount(address accountAddress) internal view returns (Account memory account) {
account = _accounts[accountAddress];
if (_isSanctioned(accountAddress)) revert_AccountBlocked();
}
function _isSanctioned(address account) internal view returns (bool result) {
address _borrower = borrower;
address _sentinel = address(sentinel);
assembly {
let freeMemoryPointer := mload(0x40)
mstore(0, 0x06e74444)
mstore(0x20, _borrower)
mstore(0x40, account)
if iszero(
and(eq(returndatasize(), 0x20), staticcall(gas(), _sentinel, 0x1c, 0x44, 0, 0x20))
) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
result := mload(0)
mstore(0x40, freeMemoryPointer)
}
}
function coverageLiquidity() external view nonReentrantView returns (uint256) {
return _calculateCurrentStatePointers.asReturnsMarketState()().liquidityRequired();
}
function scaleFactor() external view nonReentrantView returns (uint256) {
return _calculateCurrentStatePointers.asReturnsMarketState()().scaleFactor;
}
function totalAssets() public view returns (uint256) {
return asset.balanceOf(address(this));
}
function borrowableAssets() external view nonReentrantView returns (uint256) {
return _calculateCurrentStatePointers.asReturnsMarketState()().borrowableAssets(totalAssets());
}
function accruedProtocolFees() external view nonReentrantView returns (uint256) {
return _calculateCurrentStatePointers.asReturnsMarketState()().accruedProtocolFees;
}
function totalDebts() external view nonReentrantView returns (uint256) {
return _calculateCurrentStatePointers.asReturnsMarketState()().totalDebts();
}
function previousState() external view returns (MarketState memory) {
MarketState memory state = _state;
assembly {
return(state, 0x1c0)
}
}
function currentState() external view nonReentrantView returns (MarketState memory state) {
state = _calculateCurrentStatePointers.asReturnsMarketState()();
assembly {
return(state, 0x1c0)
}
}
function _calculateCurrentStatePointers() internal view returns (uint256 state) {
(state, , ) = _calculateCurrentState.asReturnsPointers()();
}
function scaledTotalSupply() external view nonReentrantView returns (uint256) {
return _calculateCurrentStatePointers.asReturnsMarketState()().scaledTotalSupply;
}
function scaledBalanceOf(address account) external view nonReentrantView returns (uint256) {
return _accounts[account].scaledBalance;
}
function withdrawableProtocolFees() external view returns (uint128) {
return
_calculateCurrentStatePointers.asReturnsMarketState()().withdrawableProtocolFees(
totalAssets()
);
}
function _blockAccount(MarketState memory state, address accountAddress) internal virtual {}
function _getUpdatedState() internal returns (MarketState memory state) {
state = _state;
if (state.hasPendingExpiredBatch()) {
uint256 expiry = state.pendingWithdrawalExpiry;
uint32 lastInterestAccruedTimestamp = state.lastInterestAccruedTimestamp;
if (expiry != lastInterestAccruedTimestamp) {
(uint256 baseInterestRay, uint256 delinquencyFeeRay, uint256 protocolFee) = state
.updateScaleFactorAndFees(delinquencyFeeBips, delinquencyGracePeriod, expiry);
emit_InterestAndFeesAccrued(
lastInterestAccruedTimestamp,
expiry,
state.scaleFactor,
baseInterestRay,
delinquencyFeeRay,
protocolFee
);
}
_processExpiredWithdrawalBatch(state);
}
uint32 lastInterestAccruedTimestamp = state.lastInterestAccruedTimestamp;
if (block.timestamp != lastInterestAccruedTimestamp) {
(uint256 baseInterestRay, uint256 delinquencyFeeRay, uint256 protocolFee) = state
.updateScaleFactorAndFees(delinquencyFeeBips, delinquencyGracePeriod, block.timestamp);
emit_InterestAndFeesAccrued(
lastInterestAccruedTimestamp,
block.timestamp,
state.scaleFactor,
baseInterestRay,
delinquencyFeeRay,
protocolFee
);
}
if (state.pendingWithdrawalExpiry != 0) {
uint32 expiry = state.pendingWithdrawalExpiry;
WithdrawalBatch memory batch = _withdrawalData.batches[expiry];
if (batch.scaledAmountBurned < batch.scaledTotalAmount) {
uint256 availableLiquidity = batch.availableLiquidityForPendingBatch(state, totalAssets());
if (availableLiquidity > 0) {
_applyWithdrawalBatchPayment(batch, state, expiry, availableLiquidity);
_withdrawalData.batches[expiry] = batch;
}
}
}
}
function _calculateCurrentState()
internal
view
returns (
MarketState memory state,
uint32 pendingBatchExpiry,
WithdrawalBatch memory pendingBatch
)
{
state = _state;
if (state.hasPendingExpiredBatch()) {
pendingBatchExpiry = state.pendingWithdrawalExpiry;
if (pendingBatchExpiry != state.lastInterestAccruedTimestamp) {
state.updateScaleFactorAndFees(
delinquencyFeeBips,
delinquencyGracePeriod,
pendingBatchExpiry
);
}
pendingBatch = _withdrawalData.batches[pendingBatchExpiry];
uint256 availableLiquidity = pendingBatch.availableLiquidityForPendingBatch(
state,
totalAssets()
);
if (availableLiquidity > 0) {
_applyWithdrawalBatchPaymentView(pendingBatch, state, availableLiquidity);
}
state.pendingWithdrawalExpiry = 0;
}
if (state.lastInterestAccruedTimestamp != block.timestamp) {
state.updateScaleFactorAndFees(delinquencyFeeBips, delinquencyGracePeriod, block.timestamp);
}
if (state.pendingWithdrawalExpiry != 0) {
pendingBatchExpiry = state.pendingWithdrawalExpiry;
pendingBatch = _withdrawalData.batches[pendingBatchExpiry];
if (pendingBatch.scaledAmountBurned < pendingBatch.scaledTotalAmount) {
uint256 availableLiquidity = pendingBatch.availableLiquidityForPendingBatch(
state,
totalAssets()
);
if (availableLiquidity > 0) {
_applyWithdrawalBatchPaymentView(pendingBatch, state, availableLiquidity);
}
}
}
}
function _writeState(MarketState memory state) internal {
bool isDelinquent = state.liquidityRequired() > totalAssets();
state.isDelinquent = isDelinquent;
{
bool isClosed = state.isClosed;
uint maxTotalSupply = state.maxTotalSupply;
assembly {
let slot0 := or(isClosed, shl(0x08, maxTotalSupply))
sstore(_state.slot, slot0)
}
}
{
uint accruedProtocolFees = state.accruedProtocolFees;
uint normalizedUnclaimedWithdrawals = state.normalizedUnclaimedWithdrawals;
assembly {
let slot1 := or(accruedProtocolFees, shl(0x80, normalizedUnclaimedWithdrawals))
sstore(add(_state.slot, 1), slot1)
}
}
{
uint scaledTotalSupply = state.scaledTotalSupply;
uint scaledPendingWithdrawals = state.scaledPendingWithdrawals;
uint pendingWithdrawalExpiry = state.pendingWithdrawalExpiry;
assembly {
let slot2 := or(
or(
or(shl(0xf0, isDelinquent), shl(0xd0, pendingWithdrawalExpiry)),
shl(0x68, scaledPendingWithdrawals)
),
scaledTotalSupply
)
sstore(add(_state.slot, 2), slot2)
}
}
{
uint timeDelinquent = state.timeDelinquent;
uint protocolFeeBips = state.protocolFeeBips;
uint annualInterestBips = state.annualInterestBips;
uint reserveRatioBips = state.reserveRatioBips;
uint scaleFactor = state.scaleFactor;
uint lastInterestAccruedTimestamp = state.lastInterestAccruedTimestamp;
assembly {
let slot3 := or(
or(
or(
or(shl(0xc0, lastInterestAccruedTimestamp), shl(0x50, scaleFactor)),
shl(0x40, reserveRatioBips)
),
or(shl(0x30, annualInterestBips), shl(0x20, protocolFeeBips))
),
timeDelinquent
)
sstore(add(_state.slot, 3), slot3)
}
}
emit_StateUpdated(state.scaleFactor, isDelinquent);
}
function _processExpiredWithdrawalBatch(MarketState memory state) internal {
uint32 expiry = state.pendingWithdrawalExpiry;
WithdrawalBatch memory batch = _withdrawalData.batches[expiry];
if (batch.scaledAmountBurned < batch.scaledTotalAmount) {
uint256 availableLiquidity = batch.availableLiquidityForPendingBatch(state, totalAssets());
if (availableLiquidity > 0) {
_applyWithdrawalBatchPayment(batch, state, expiry, availableLiquidity);
}
}
emit_WithdrawalBatchExpired(
expiry,
batch.scaledTotalAmount,
batch.scaledAmountBurned,
batch.normalizedAmountPaid
);
if (batch.scaledAmountBurned < batch.scaledTotalAmount) {
_withdrawalData.unpaidBatches.push(expiry);
} else {
emit_WithdrawalBatchClosed(expiry);
}
state.pendingWithdrawalExpiry = 0;
_withdrawalData.batches[expiry] = batch;
}
function _applyWithdrawalBatchPayment(
WithdrawalBatch memory batch,
MarketState memory state,
uint32 expiry,
uint256 availableLiquidity
) internal returns (uint104 scaledAmountBurned, uint128 normalizedAmountPaid) {
uint104 scaledAmountOwed = batch.scaledTotalAmount - batch.scaledAmountBurned;
if (scaledAmountOwed == 0) return (0, 0);
uint256 scaledAvailableLiquidity = state.scaleAmount(availableLiquidity);
scaledAmountBurned = MathUtils.min(scaledAvailableLiquidity, scaledAmountOwed).toUint104();
normalizedAmountPaid = MathUtils.mulDiv(scaledAmountBurned, state.scaleFactor, RAY).toUint128();
batch.scaledAmountBurned += scaledAmountBurned;
batch.normalizedAmountPaid += normalizedAmountPaid;
state.scaledPendingWithdrawals -= scaledAmountBurned;
state.normalizedUnclaimedWithdrawals += normalizedAmountPaid;
state.scaledTotalSupply -= scaledAmountBurned;
emit_Transfer(address(this), _runtimeConstant(address(0)), normalizedAmountPaid);
emit_WithdrawalBatchPayment(expiry, scaledAmountBurned, normalizedAmountPaid);
}
function _applyWithdrawalBatchPaymentView(
WithdrawalBatch memory batch,
MarketState memory state,
uint256 availableLiquidity
) internal pure {
uint104 scaledAmountOwed = batch.scaledTotalAmount - batch.scaledAmountBurned;
if (scaledAmountOwed == 0) return;
uint256 scaledAvailableLiquidity = state.scaleAmount(availableLiquidity);
uint104 scaledAmountBurned = MathUtils
.min(scaledAvailableLiquidity, scaledAmountOwed)
.toUint104();
uint128 normalizedAmountPaid = MathUtils
.mulDiv(scaledAmountBurned, state.scaleFactor, RAY)
.toUint128();
batch.scaledAmountBurned += scaledAmountBurned;
batch.normalizedAmountPaid += normalizedAmountPaid;
state.scaledPendingWithdrawals -= scaledAmountBurned;
state.normalizedUnclaimedWithdrawals += normalizedAmountPaid;
state.scaledTotalSupply -= scaledAmountBurned;
}
function _runtimeConstant(
uint256 actualConstant
) internal pure returns (uint256 runtimeConstant) {
assembly {
mstore(0, actualConstant)
runtimeConstant := mload(iszero(calldatasize()))
}
}
function _runtimeConstant(
address actualConstant
) internal pure returns (address runtimeConstant) {
assembly {
mstore(0, actualConstant)
runtimeConstant := mload(iszero(calldatasize()))
}
}
function _isFlaggedByChainalysis(address account) internal view returns (bool isFlagged) {
address sentinelAddress = address(sentinel);
assembly {
mstore(0, 0x95c09839)
mstore(0x20, account)
if iszero(
and(eq(returndatasize(), 0x20), staticcall(gas(), sentinelAddress, 0x1c, 0x24, 0, 0x20))
) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
isFlagged := mload(0)
}
}
function _createEscrowForUnderlyingAsset(
address accountAddress
) internal returns (address escrow) {
address tokenAddress = address(asset);
address borrowerAddress = borrower;
address sentinelAddress = address(sentinel);
assembly {
let freeMemoryPointer := mload(0x40)
mstore(0, 0xa1054f6b)
mstore(0x20, borrowerAddress)
mstore(0x40, accountAddress)
mstore(0x60, tokenAddress)
if iszero(
and(eq(returndatasize(), 0x20), call(gas(), sentinelAddress, 0, 0x1c, 0x64, 0, 0x20))
) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
escrow := mload(0)
mstore(0x40, freeMemoryPointer)
mstore(0x60, 0)
}
}
}
文件 29 的 35:WildcatMarketConfig.sol
pragma solidity >=0.8.20;
import './WildcatMarketBase.sol';
import '../libraries/FeeMath.sol';
import '../libraries/SafeCastLib.sol';
contract WildcatMarketConfig is WildcatMarketBase {
using SafeCastLib for uint256;
using FunctionTypeCasts for *;
function isClosed() external view returns (bool) {
return _state.isClosed;
}
function maximumDeposit() external view returns (uint256) {
MarketState memory state = _calculateCurrentStatePointers.asReturnsMarketState()();
return state.maximumDeposit();
}
function maxTotalSupply() external view returns (uint256) {
return _state.maxTotalSupply;
}
function annualInterestBips() external view returns (uint256) {
return _state.annualInterestBips;
}
function reserveRatioBips() external view returns (uint256) {
return _state.reserveRatioBips;
}
function nukeFromOrbit(address accountAddress) external nonReentrant sphereXGuardExternal {
if (!_isSanctioned(accountAddress)) revert_BadLaunchCode();
MarketState memory state = _getUpdatedState();
hooks.onNukeFromOrbit(accountAddress, state);
_blockAccount(state, accountAddress);
_writeState(state);
}
function setMaxTotalSupply(
uint256 _maxTotalSupply
) external onlyBorrower nonReentrant sphereXGuardExternal {
MarketState memory state = _getUpdatedState();
if (state.isClosed) revert_CapacityChangeOnClosedMarket();
hooks.onSetMaxTotalSupply(_maxTotalSupply, state);
state.maxTotalSupply = _maxTotalSupply.toUint128();
_writeState(state);
emit_MaxTotalSupplyUpdated(_maxTotalSupply);
}
function setAnnualInterestAndReserveRatioBips(
uint16 _annualInterestBips,
uint16 _reserveRatioBips
) external onlyBorrower nonReentrant sphereXGuardExternal {
MarketState memory state = _getUpdatedState();
if (state.isClosed) revert_AprChangeOnClosedMarket();
uint256 initialReserveRatioBips = state.reserveRatioBips;
(_annualInterestBips, _reserveRatioBips) = hooks.onSetAnnualInterestAndReserveRatioBips(
_annualInterestBips,
_reserveRatioBips,
state
);
if (_annualInterestBips > BIP) {
revert_AnnualInterestBipsTooHigh();
}
if (_reserveRatioBips > BIP) {
revert_ReserveRatioBipsTooHigh();
}
if (_reserveRatioBips <= initialReserveRatioBips) {
if (state.liquidityRequired() > totalAssets()) {
revert_InsufficientReservesForOldLiquidityRatio();
}
}
state.reserveRatioBips = _reserveRatioBips;
state.annualInterestBips = _annualInterestBips;
if (_reserveRatioBips > initialReserveRatioBips) {
if (state.liquidityRequired() > totalAssets()) {
revert_InsufficientReservesForNewLiquidityRatio();
}
}
_writeState(state);
emit_AnnualInterestBipsUpdated(_annualInterestBips);
emit_ReserveRatioBipsUpdated(_reserveRatioBips);
}
function setProtocolFeeBips(uint16 _protocolFeeBips) external nonReentrant sphereXGuardExternal {
if (msg.sender != factory) revert_NotFactory();
if (_protocolFeeBips > 1_000) revert_ProtocolFeeTooHigh();
MarketState memory state = _getUpdatedState();
if (state.isClosed) revert_ProtocolFeeChangeOnClosedMarket();
if (_protocolFeeBips != state.protocolFeeBips) {
hooks.onSetProtocolFeeBips(_protocolFeeBips, state);
state.protocolFeeBips = _protocolFeeBips;
emit ProtocolFeeBipsUpdated(_protocolFeeBips);
}
_writeState(state);
}
}
文件 30 的 35:WildcatMarketToken.sol
pragma solidity >=0.8.20;
import './WildcatMarketBase.sol';
contract WildcatMarketToken is WildcatMarketBase {
using SafeCastLib for uint256;
using FunctionTypeCasts for *;
mapping(address => mapping(address => uint256)) public allowance;
function balanceOf(address account) public view virtual nonReentrantView returns (uint256) {
return
_calculateCurrentStatePointers.asReturnsMarketState()().normalizeAmount(
_accounts[account].scaledBalance
);
}
function totalSupply() external view virtual nonReentrantView returns (uint256) {
return _calculateCurrentStatePointers.asReturnsMarketState()().totalSupply();
}
function approve(
address spender,
uint256 amount
) external virtual nonReentrant sphereXGuardExternal returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}
function transfer(
address to,
uint256 amount
) external virtual nonReentrant sphereXGuardExternal returns (bool) {
_transfer(msg.sender, to, amount, 0x44);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) external virtual nonReentrant sphereXGuardExternal returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) {
uint256 newAllowance = allowed - amount;
_approve(from, msg.sender, newAllowance);
}
_transfer(from, to, amount, 0x64);
return true;
}
function _approve(address approver, address spender, uint256 amount) internal virtual {
allowance[approver][spender] = amount;
emit_Approval(approver, spender, amount);
}
function _transfer(
address from,
address to,
uint256 amount,
uint baseCalldataSize
) internal virtual {
MarketState memory state = _getUpdatedState();
uint104 scaledAmount = state.scaleAmount(amount).toUint104();
if (scaledAmount == 0) revert_NullTransferAmount();
hooks.onTransfer(from, to, scaledAmount, state, baseCalldataSize);
Account memory fromAccount = _getAccount(from);
fromAccount.scaledBalance -= scaledAmount;
_accounts[from] = fromAccount;
Account memory toAccount = _getAccount(to);
toAccount.scaledBalance += scaledAmount;
_accounts[to] = toAccount;
_writeState(state);
emit_Transfer(from, to, amount);
}
}
文件 31 的 35:WildcatMarketWithdrawals.sol
pragma solidity >=0.8.20;
import './WildcatMarketBase.sol';
import '../libraries/LibERC20.sol';
import '../libraries/BoolUtils.sol';
contract WildcatMarketWithdrawals is WildcatMarketBase {
using LibERC20 for address;
using MathUtils for uint256;
using MathUtils for bool;
using SafeCastLib for uint256;
using BoolUtils for bool;
function getUnpaidBatchExpiries() external view nonReentrantView returns (uint32[] memory) {
return _withdrawalData.unpaidBatches.values();
}
function getWithdrawalBatch(
uint32 expiry
) external view nonReentrantView returns (WithdrawalBatch memory batch) {
(, uint32 pendingBatchExpiry, WithdrawalBatch memory pendingBatch) = _calculateCurrentState();
if ((expiry == pendingBatchExpiry).and(expiry > 0)) {
return pendingBatch;
}
WithdrawalBatch storage _batch = _withdrawalData.batches[expiry];
batch.scaledTotalAmount = _batch.scaledTotalAmount;
batch.scaledAmountBurned = _batch.scaledAmountBurned;
batch.normalizedAmountPaid = _batch.normalizedAmountPaid;
}
function getAccountWithdrawalStatus(
address accountAddress,
uint32 expiry
) external view nonReentrantView returns (AccountWithdrawalStatus memory status) {
AccountWithdrawalStatus storage _status = _withdrawalData.accountStatuses[expiry][
accountAddress
];
status.scaledAmount = _status.scaledAmount;
status.normalizedAmountWithdrawn = _status.normalizedAmountWithdrawn;
}
function getAvailableWithdrawalAmount(
address accountAddress,
uint32 expiry
) external view nonReentrantView returns (uint256) {
if (expiry >= block.timestamp) {
revert_WithdrawalBatchNotExpired();
}
(, uint32 pendingBatchExpiry, WithdrawalBatch memory pendingBatch) = _calculateCurrentState();
WithdrawalBatch memory batch;
if (expiry == pendingBatchExpiry) {
batch = pendingBatch;
} else {
batch = _withdrawalData.batches[expiry];
}
AccountWithdrawalStatus memory status = _withdrawalData.accountStatuses[expiry][accountAddress];
uint256 previousTotalWithdrawn = status.normalizedAmountWithdrawn;
uint256 newTotalWithdrawn = uint256(batch.normalizedAmountPaid).mulDiv(
status.scaledAmount,
batch.scaledTotalAmount
);
return newTotalWithdrawn - previousTotalWithdrawn;
}
function _queueWithdrawal(
MarketState memory state,
Account memory account,
address accountAddress,
uint104 scaledAmount,
uint normalizedAmount,
uint baseCalldataSize
) internal returns (uint32 expiry) {
expiry = state.pendingWithdrawalExpiry;
if (state.pendingWithdrawalExpiry == 0) {
uint duration = state.isClosed.ternary(0, withdrawalBatchDuration);
expiry = uint32(block.timestamp + duration);
emit_WithdrawalBatchCreated(expiry);
state.pendingWithdrawalExpiry = expiry;
}
hooks.onQueueWithdrawal(accountAddress, expiry, scaledAmount, state, baseCalldataSize);
account.scaledBalance -= scaledAmount;
_accounts[accountAddress] = account;
emit_Transfer(accountAddress, address(this), normalizedAmount);
WithdrawalBatch memory batch = _withdrawalData.batches[expiry];
_withdrawalData.accountStatuses[expiry][accountAddress].scaledAmount += scaledAmount;
batch.scaledTotalAmount += scaledAmount;
state.scaledPendingWithdrawals += scaledAmount;
emit_WithdrawalQueued(expiry, accountAddress, scaledAmount, normalizedAmount);
uint256 availableLiquidity = batch.availableLiquidityForPendingBatch(state, totalAssets());
if (availableLiquidity > 0) {
_applyWithdrawalBatchPayment(batch, state, expiry, availableLiquidity);
}
_withdrawalData.batches[expiry] = batch;
_writeState(state);
}
function queueWithdrawal(
uint256 amount
) external nonReentrant sphereXGuardExternal returns (uint32 expiry) {
MarketState memory state = _getUpdatedState();
uint104 scaledAmount = state.scaleAmount(amount).toUint104();
if (scaledAmount == 0) revert_NullBurnAmount();
Account memory account = _getAccount(msg.sender);
return
_queueWithdrawal(state, account, msg.sender, scaledAmount, amount, _runtimeConstant(0x24));
}
function queueFullWithdrawal()
external
nonReentrant
sphereXGuardExternal
returns (uint32 expiry)
{
MarketState memory state = _getUpdatedState();
Account memory account = _getAccount(msg.sender);
uint104 scaledAmount = account.scaledBalance;
if (scaledAmount == 0) revert_NullBurnAmount();
uint256 normalizedAmount = state.normalizeAmount(scaledAmount);
return
_queueWithdrawal(
state,
account,
msg.sender,
scaledAmount,
normalizedAmount,
_runtimeConstant(0x04)
);
}
function executeWithdrawal(
address accountAddress,
uint32 expiry
) public nonReentrant sphereXGuardExternal returns (uint256) {
MarketState memory state = _getUpdatedState();
uint256 normalizedAmountWithdrawn = _executeWithdrawal(
state,
accountAddress,
expiry,
_runtimeConstant(0x44)
);
_writeState(state);
return normalizedAmountWithdrawn;
}
function executeWithdrawals(
address[] calldata accountAddresses,
uint32[] calldata expiries
) external nonReentrant sphereXGuardExternal returns (uint256[] memory amounts) {
if (accountAddresses.length != expiries.length) revert_InvalidArrayLength();
amounts = new uint256[](accountAddresses.length);
MarketState memory state = _getUpdatedState();
for (uint256 i = 0; i < accountAddresses.length; i++) {
amounts[i] = _executeWithdrawal(state, accountAddresses[i], expiries[i], msg.data.length);
}
_writeState(state);
return amounts;
}
function _executeWithdrawal(
MarketState memory state,
address accountAddress,
uint32 expiry,
uint baseCalldataSize
) internal returns (uint256) {
WithdrawalBatch memory batch = _withdrawalData.batches[expiry];
if (expiry == state.pendingWithdrawalExpiry) revert_WithdrawalBatchNotExpired();
AccountWithdrawalStatus storage status = _withdrawalData.accountStatuses[expiry][
accountAddress
];
uint128 newTotalWithdrawn = uint128(
MathUtils.mulDiv(batch.normalizedAmountPaid, status.scaledAmount, batch.scaledTotalAmount)
);
uint128 normalizedAmountWithdrawn = newTotalWithdrawn - status.normalizedAmountWithdrawn;
if (normalizedAmountWithdrawn == 0) revert_NullWithdrawalAmount();
hooks.onExecuteWithdrawal(accountAddress, normalizedAmountWithdrawn, state, baseCalldataSize);
status.normalizedAmountWithdrawn = newTotalWithdrawn;
state.normalizedUnclaimedWithdrawals -= normalizedAmountWithdrawn;
if (_isSanctioned(accountAddress)) {
address escrow = _createEscrowForUnderlyingAsset(accountAddress);
asset.safeTransfer(escrow, normalizedAmountWithdrawn);
emit_SanctionedAccountWithdrawalSentToEscrow(
accountAddress,
escrow,
expiry,
normalizedAmountWithdrawn
);
} else {
asset.safeTransfer(accountAddress, normalizedAmountWithdrawn);
}
emit_WithdrawalExecuted(expiry, accountAddress, normalizedAmountWithdrawn);
return normalizedAmountWithdrawn;
}
function repayAndProcessUnpaidWithdrawalBatches(
uint256 repayAmount,
uint256 maxBatches
) public nonReentrant sphereXGuardExternal {
if (repayAmount > 0) {
asset.safeTransferFrom(msg.sender, address(this), repayAmount);
emit_DebtRepaid(msg.sender, repayAmount);
}
MarketState memory state = _getUpdatedState();
if (state.isClosed) revert_RepayToClosedMarket();
if (repayAmount > 0) hooks.onRepay(repayAmount, state, _runtimeConstant(0x44));
uint256 availableLiquidity = totalAssets() -
(state.normalizedUnclaimedWithdrawals + state.accruedProtocolFees);
uint256 numBatches = MathUtils.min(maxBatches, _withdrawalData.unpaidBatches.length());
uint256 i;
while (i++ < numBatches && availableLiquidity > 0) {
uint256 normalizedAmountPaid = _processUnpaidWithdrawalBatch(state, availableLiquidity);
availableLiquidity = availableLiquidity.satSub(normalizedAmountPaid);
}
_writeState(state);
}
function _processUnpaidWithdrawalBatch(
MarketState memory state,
uint256 availableLiquidity
) internal returns (uint256 normalizedAmountPaid) {
uint32 expiry = _withdrawalData.unpaidBatches.first();
WithdrawalBatch memory batch = _withdrawalData.batches[expiry];
(, normalizedAmountPaid) = _applyWithdrawalBatchPayment(
batch,
state,
expiry,
availableLiquidity
);
_withdrawalData.batches[expiry] = batch;
if (batch.scaledTotalAmount == batch.scaledAmountBurned) {
_withdrawalData.unpaidBatches.shift();
emit_WithdrawalBatchClosed(expiry);
}
}
}
文件 32 的 35:WildcatSanctionsEscrow.sol
pragma solidity >=0.8.20;
import './interfaces/IERC20.sol';
import './interfaces/IWildcatSanctionsEscrow.sol';
import './interfaces/IWildcatSanctionsSentinel.sol';
import './libraries/LibERC20.sol';
contract WildcatSanctionsEscrow is IWildcatSanctionsEscrow {
using LibERC20 for address;
address public immutable override sentinel;
address public immutable override borrower;
address public immutable override account;
address internal immutable asset;
constructor() {
sentinel = msg.sender;
(borrower, account, asset) = IWildcatSanctionsSentinel(sentinel).tmpEscrowParams();
}
function balance() public view override returns (uint256) {
return IERC20(asset).balanceOf(address(this));
}
function canReleaseEscrow() public view override returns (bool) {
return !IWildcatSanctionsSentinel(sentinel).isSanctioned(borrower, account);
}
function escrowedAsset() public view override returns (address, uint256) {
return (asset, balance());
}
function releaseEscrow() public override {
if (!canReleaseEscrow()) revert CanNotReleaseEscrow();
uint256 amount = balance();
address _account = account;
address _asset = asset;
asset.safeTransfer(_account, amount);
emit EscrowReleased(_account, _asset, amount);
}
}
文件 33 的 35:WildcatSanctionsSentinel.sol
pragma solidity >=0.8.20;
import { IChainalysisSanctionsList } from './interfaces/IChainalysisSanctionsList.sol';
import { IWildcatSanctionsSentinel } from './interfaces/IWildcatSanctionsSentinel.sol';
import { WildcatSanctionsEscrow } from './WildcatSanctionsEscrow.sol';
contract WildcatSanctionsSentinel is IWildcatSanctionsSentinel {
bytes32 public constant override WildcatSanctionsEscrowInitcodeHash =
keccak256(type(WildcatSanctionsEscrow).creationCode);
address public immutable override chainalysisSanctionsList;
address public immutable override archController;
TmpEscrowParams public override tmpEscrowParams;
mapping(address borrower => mapping(address account => bool sanctionOverride))
public
override sanctionOverrides;
constructor(address _archController, address _chainalysisSanctionsList) {
archController = _archController;
chainalysisSanctionsList = _chainalysisSanctionsList;
_resetTmpEscrowParams();
}
function _resetTmpEscrowParams() internal {
tmpEscrowParams = TmpEscrowParams(address(1), address(1), address(1));
}
function _deriveSalt(
address borrower,
address account,
address asset
) internal pure returns (bytes32 salt) {
assembly {
let freeMemoryPointer := mload(0x40)
mstore(0x00, borrower)
mstore(0x20, account)
mstore(0x40, asset)
salt := keccak256(0, 0x60)
mstore(0x40, freeMemoryPointer)
}
}
function isFlaggedByChainalysis(address account) public view override returns (bool) {
return IChainalysisSanctionsList(chainalysisSanctionsList).isSanctioned(account);
}
function isSanctioned(address borrower, address account) public view override returns (bool) {
return !sanctionOverrides[borrower][account] && isFlaggedByChainalysis(account);
}
function overrideSanction(address account) public override {
sanctionOverrides[msg.sender][account] = true;
emit SanctionOverride(msg.sender, account);
}
function removeSanctionOverride(address account) public override {
sanctionOverrides[msg.sender][account] = false;
emit SanctionOverrideRemoved(msg.sender, account);
}
function createEscrow(
address borrower,
address account,
address asset
) public override returns (address escrowContract) {
escrowContract = getEscrowAddress(borrower, account, asset);
if (escrowContract.code.length != 0) return escrowContract;
tmpEscrowParams = TmpEscrowParams(borrower, account, asset);
new WildcatSanctionsEscrow{ salt: _deriveSalt(borrower, account, asset) }();
emit NewSanctionsEscrow(borrower, account, asset);
sanctionOverrides[borrower][escrowContract] = true;
emit SanctionOverride(borrower, escrowContract);
_resetTmpEscrowParams();
}
function getEscrowAddress(
address borrower,
address account,
address asset
) public view override returns (address escrowAddress) {
bytes32 salt = _deriveSalt(borrower, account, asset);
bytes32 initCodeHash = WildcatSanctionsEscrowInitcodeHash;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(0x00, or(0xff0000000000000000000000000000000000000000, address()))
mstore(0x20, salt)
mstore(0x40, initCodeHash)
escrowAddress := and(keccak256(0x0b, 0x55), 0xffffffffffffffffffffffffffffffffffffffff)
mstore(0x40, freeMemoryPointer)
}
}
}
文件 34 的 35:WildcatStructsAndEnums.sol
pragma solidity >=0.8.20;
import { MarketState } from '../libraries/MarketState.sol';
import { HooksConfig } from '../types/HooksConfig.sol';
struct MarketParameters {
address asset;
uint8 decimals;
bytes32 packedNameWord0;
bytes32 packedNameWord1;
bytes32 packedSymbolWord0;
bytes32 packedSymbolWord1;
address borrower;
address feeRecipient;
address sentinel;
uint128 maxTotalSupply;
uint16 protocolFeeBips;
uint16 annualInterestBips;
uint16 delinquencyFeeBips;
uint32 withdrawalBatchDuration;
uint16 reserveRatioBips;
uint32 delinquencyGracePeriod;
address archController;
address sphereXEngine;
HooksConfig hooks;
}
struct DeployMarketInputs {
address asset;
string namePrefix;
string symbolPrefix;
uint128 maxTotalSupply;
uint16 annualInterestBips;
uint16 delinquencyFeeBips;
uint32 withdrawalBatchDuration;
uint16 reserveRatioBips;
uint32 delinquencyGracePeriod;
HooksConfig hooks;
}
struct MarketControllerParameters {
address archController;
address borrower;
address sentinel;
address marketInitCodeStorage;
uint256 marketInitCodeHash;
uint32 minimumDelinquencyGracePeriod;
uint32 maximumDelinquencyGracePeriod;
uint16 minimumReserveRatioBips;
uint16 maximumReserveRatioBips;
uint16 minimumDelinquencyFeeBips;
uint16 maximumDelinquencyFeeBips;
uint32 minimumWithdrawalBatchDuration;
uint32 maximumWithdrawalBatchDuration;
uint16 minimumAnnualInterestBips;
uint16 maximumAnnualInterestBips;
address sphereXEngine;
}
struct ProtocolFeeConfiguration {
address feeRecipient;
address originationFeeAsset;
uint80 originationFeeAmount;
uint16 protocolFeeBips;
}
struct MarketParameterConstraints {
uint32 minimumDelinquencyGracePeriod;
uint32 maximumDelinquencyGracePeriod;
uint16 minimumReserveRatioBips;
uint16 maximumReserveRatioBips;
uint16 minimumDelinquencyFeeBips;
uint16 maximumDelinquencyFeeBips;
uint32 minimumWithdrawalBatchDuration;
uint32 maximumWithdrawalBatchDuration;
uint16 minimumAnnualInterestBips;
uint16 maximumAnnualInterestBips;
}
文件 35 的 35:Withdrawal.sol
pragma solidity >=0.8.20;
import './MarketState.sol';
import './FIFOQueue.sol';
using MathUtils for uint256;
using WithdrawalLib for WithdrawalBatch global;
struct WithdrawalBatch {
uint104 scaledTotalAmount;
uint104 scaledAmountBurned;
uint128 normalizedAmountPaid;
}
struct AccountWithdrawalStatus {
uint104 scaledAmount;
uint128 normalizedAmountWithdrawn;
}
struct WithdrawalData {
FIFOQueue unpaidBatches;
mapping(uint32 => WithdrawalBatch) batches;
mapping(uint256 => mapping(address => AccountWithdrawalStatus)) accountStatuses;
}
library WithdrawalLib {
function scaledOwedAmount(WithdrawalBatch memory batch) internal pure returns (uint104) {
return batch.scaledTotalAmount - batch.scaledAmountBurned;
}
function availableLiquidityForPendingBatch(
WithdrawalBatch memory batch,
MarketState memory state,
uint256 totalAssets
) internal pure returns (uint256) {
uint256 priorScaledAmountPending = (state.scaledPendingWithdrawals - batch.scaledOwedAmount());
uint256 unavailableAssets = state.normalizedUnclaimedWithdrawals +
state.normalizeAmount(priorScaledAmountPending) +
state.accruedProtocolFees;
return totalAssets.satSub(unavailableAssets);
}
}
{
"compilationTarget": {
"src/market/WildcatMarket.sol": "WildcatMarket"
},
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 50000
},
"remappings": [
":ds-test/=lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":ethereum-access-token/=lib/ethereum-access-token/contracts/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin-contracts/",
":sol-utils/=lib/sol-utils/src/",
":solady/=lib/solady/src/",
":solmate/=lib/solmate/src/",
":src/=src/",
":vulcan/=lib/vulcan/src/"
],
"viaIR": true
}
[{"inputs":[],"name":"AccountBlocked","type":"error"},{"inputs":[],"name":"AnnualInterestBipsTooHigh","type":"error"},{"inputs":[],"name":"AprChangeOnClosedMarket","type":"error"},{"inputs":[],"name":"BadLaunchCode","type":"error"},{"inputs":[],"name":"BadRescueAsset","type":"error"},{"inputs":[],"name":"BorrowAmountTooHigh","type":"error"},{"inputs":[],"name":"BorrowFromClosedMarket","type":"error"},{"inputs":[],"name":"BorrowWhileSanctioned","type":"error"},{"inputs":[],"name":"BuyBackOnDelinquentMarket","type":"error"},{"inputs":[],"name":"CapacityChangeOnClosedMarket","type":"error"},{"inputs":[],"name":"CloseMarketWithUnpaidWithdrawals","type":"error"},{"inputs":[],"name":"DepositToClosedMarket","type":"error"},{"inputs":[],"name":"FIFOQueueOutOfBounds","type":"error"},{"inputs":[],"name":"InsufficientReservesForFeeWithdrawal","type":"error"},{"inputs":[],"name":"InsufficientReservesForNewLiquidityRatio","type":"error"},{"inputs":[],"name":"InsufficientReservesForOldLiquidityRatio","type":"error"},{"inputs":[],"name":"InvalidArrayLength","type":"error"},{"inputs":[],"name":"MarketAlreadyClosed","type":"error"},{"inputs":[],"name":"MaxSupplyExceeded","type":"error"},{"inputs":[],"name":"NoReentrantCalls","type":"error"},{"inputs":[],"name":"NotApprovedBorrower","type":"error"},{"inputs":[],"name":"NotApprovedLender","type":"error"},{"inputs":[],"name":"NotFactory","type":"error"},{"inputs":[],"name":"NullBurnAmount","type":"error"},{"inputs":[],"name":"NullBuyBackAmount","type":"error"},{"inputs":[],"name":"NullFeeAmount","type":"error"},{"inputs":[],"name":"NullMintAmount","type":"error"},{"inputs":[],"name":"NullRepayAmount","type":"error"},{"inputs":[],"name":"NullTransferAmount","type":"error"},{"inputs":[],"name":"NullWithdrawalAmount","type":"error"},{"inputs":[],"name":"ProtocolFeeChangeOnClosedMarket","type":"error"},{"inputs":[],"name":"ProtocolFeeTooHigh","type":"error"},{"inputs":[],"name":"RepayToClosedMarket","type":"error"},{"inputs":[],"name":"ReserveRatioBipsTooHigh","type":"error"},{"inputs":[],"name":"SphereXOperatorRequired","type":"error"},{"inputs":[],"name":"WithdrawalBatchNotExpired","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AccountSanctioned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"annualInterestBipsUpdated","type":"uint256"}],"name":"AnnualInterestBipsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assetAmount","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldEngineAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newEngineAddress","type":"address"}],"name":"ChangedSpherexEngineAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldSphereXAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newSphereXAdmin","type":"address"}],"name":"ChangedSpherexOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"assetAmount","type":"uint256"}],"name":"DebtRepaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"assetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"scaledAmount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"FeesCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fromTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"scaleFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseInterestRay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"delinquencyFeeRay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"protocolFees","type":"uint256"}],"name":"InterestAndFeesAccrued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"MarketClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"}],"name":"MaxTotalSupplyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"protocolFeeBips","type":"uint256"}],"name":"ProtocolFeeBipsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reserveRatioBipsUpdated","type":"uint256"}],"name":"ReserveRatioBipsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"expiry","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"scaledAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"normalizedAmount","type":"uint256"}],"name":"SanctionedAccountAssetsQueuedForWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"escrow","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SanctionedAccountAssetsSentToEscrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"escrow","type":"address"},{"indexed":false,"internalType":"uint32","name":"expiry","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SanctionedAccountWithdrawalSentToEscrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"scaleFactor","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isDelinquent","type":"bool"}],"name":"StateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"WithdrawalBatchClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"WithdrawalBatchCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"expiry","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"scaledTotalAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"scaledAmountBurned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"normalizedAmountPaid","type":"uint256"}],"name":"WithdrawalBatchExpired","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"expiry","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"scaledAmountBurned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"normalizedAmountPaid","type":"uint256"}],"name":"WithdrawalBatchPayment","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"expiry","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"normalizedAmount","type":"uint256"}],"name":"WithdrawalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"expiry","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"scaledAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"normalizedAmount","type":"uint256"}],"name":"WithdrawalQueued","type":"event"},{"inputs":[],"name":"accruedProtocolFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"annualInterestBips","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"archController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"borrowableAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrower","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newSphereXEngine","type":"address"}],"name":"changeSphereXEngine","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"closeMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collectFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"coverageLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentState","outputs":[{"components":[{"internalType":"bool","name":"isClosed","type":"bool"},{"internalType":"uint128","name":"maxTotalSupply","type":"uint128"},{"internalType":"uint128","name":"accruedProtocolFees","type":"uint128"},{"internalType":"uint128","name":"normalizedUnclaimedWithdrawals","type":"uint128"},{"internalType":"uint104","name":"scaledTotalSupply","type":"uint104"},{"internalType":"uint104","name":"scaledPendingWithdrawals","type":"uint104"},{"internalType":"uint32","name":"pendingWithdrawalExpiry","type":"uint32"},{"internalType":"bool","name":"isDelinquent","type":"bool"},{"internalType":"uint32","name":"timeDelinquent","type":"uint32"},{"internalType":"uint16","name":"protocolFeeBips","type":"uint16"},{"internalType":"uint16","name":"annualInterestBips","type":"uint16"},{"internalType":"uint16","name":"reserveRatioBips","type":"uint16"},{"internalType":"uint112","name":"scaleFactor","type":"uint112"},{"internalType":"uint32","name":"lastInterestAccruedTimestamp","type":"uint32"}],"internalType":"struct MarketState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delinquencyFeeBips","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delinquencyGracePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositUpTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"accountAddress","type":"address"},{"internalType":"uint32","name":"expiry","type":"uint32"}],"name":"executeWithdrawal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accountAddresses","type":"address[]"},{"internalType":"uint32[]","name":"expiries","type":"uint32[]"}],"name":"executeWithdrawals","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"accountAddress","type":"address"},{"internalType":"uint32","name":"expiry","type":"uint32"}],"name":"getAccountWithdrawalStatus","outputs":[{"components":[{"internalType":"uint104","name":"scaledAmount","type":"uint104"},{"internalType":"uint128","name":"normalizedAmountWithdrawn","type":"uint128"}],"internalType":"struct AccountWithdrawalStatus","name":"status","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"accountAddress","type":"address"},{"internalType":"uint32","name":"expiry","type":"uint32"}],"name":"getAvailableWithdrawalAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUnpaidBatchExpiries","outputs":[{"internalType":"uint32[]","name":"","type":"uint32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"expiry","type":"uint32"}],"name":"getWithdrawalBatch","outputs":[{"components":[{"internalType":"uint104","name":"scaledTotalAmount","type":"uint104"},{"internalType":"uint104","name":"scaledAmountBurned","type":"uint104"},{"internalType":"uint128","name":"normalizedAmountPaid","type":"uint128"}],"internalType":"struct WithdrawalBatch","name":"batch","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hooks","outputs":[{"internalType":"HooksConfig","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isClosed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maximumDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"accountAddress","type":"address"}],"name":"nukeFromOrbit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"previousState","outputs":[{"components":[{"internalType":"bool","name":"isClosed","type":"bool"},{"internalType":"uint128","name":"maxTotalSupply","type":"uint128"},{"internalType":"uint128","name":"accruedProtocolFees","type":"uint128"},{"internalType":"uint128","name":"normalizedUnclaimedWithdrawals","type":"uint128"},{"internalType":"uint104","name":"scaledTotalSupply","type":"uint104"},{"internalType":"uint104","name":"scaledPendingWithdrawals","type":"uint104"},{"internalType":"uint32","name":"pendingWithdrawalExpiry","type":"uint32"},{"internalType":"bool","name":"isDelinquent","type":"bool"},{"internalType":"uint32","name":"timeDelinquent","type":"uint32"},{"internalType":"uint16","name":"protocolFeeBips","type":"uint16"},{"internalType":"uint16","name":"annualInterestBips","type":"uint16"},{"internalType":"uint16","name":"reserveRatioBips","type":"uint16"},{"internalType":"uint112","name":"scaleFactor","type":"uint112"},{"internalType":"uint32","name":"lastInterestAccruedTimestamp","type":"uint32"}],"internalType":"struct MarketState","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"queueFullWithdrawal","outputs":[{"internalType":"uint32","name":"expiry","type":"uint32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"queueWithdrawal","outputs":[{"internalType":"uint32","name":"expiry","type":"uint32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"repayAmount","type":"uint256"},{"internalType":"uint256","name":"maxBatches","type":"uint256"}],"name":"repayAndProcessUnpaidWithdrawalBatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"rescueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reserveRatioBips","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"scaleFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"scaledBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"scaledTotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sentinel","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_annualInterestBips","type":"uint16"},{"internalType":"uint16","name":"_reserveRatioBips","type":"uint16"}],"name":"setAnnualInterestAndReserveRatioBips","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxTotalSupply","type":"uint256"}],"name":"setMaxTotalSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_protocolFeeBips","type":"uint16"}],"name":"setProtocolFeeBips","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sphereXEngine","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sphereXOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDebts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"withdrawableProtocolFees","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalBatchDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]