编译器
0.8.19+commit.7dd6d404
文件 1 的 11:BloomPool.sol
pragma solidity 0.8.19;
import {ERC20} from "solmate/tokens/ERC20.sol";
import {IBloomPool, State} from "./interfaces/IBloomPool.sol";
import {ISwapRecipient} from "./interfaces/ISwapRecipient.sol";
import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol";
import {SafeCastLib} from "solady/utils/SafeCastLib.sol";
import {FixedPointMathLib as Math} from "solady/utils/FixedPointMathLib.sol";
import {CommitmentsLib, Commitments, AssetCommitment} from "./lib/CommitmentsLib.sol";
import {IWhitelist} from "./interfaces/IWhitelist.sol";
import {ISwapFacility} from "./interfaces/ISwapFacility.sol";
import {IBPSFeed} from "./interfaces/IBPSFeed.sol";
contract BloomPool is IBloomPool, ISwapRecipient, ERC20 {
using CommitmentsLib for Commitments;
using CommitmentsLib for AssetCommitment;
using SafeTransferLib for address;
using SafeCastLib for uint256;
uint256 internal constant BPS = 1e4;
address public immutable UNDERLYING_TOKEN;
address public immutable BILL_TOKEN;
IWhitelist public immutable WHITELIST;
address public immutable SWAP_FACILITY;
address public immutable TREASURY;
address public immutable EMERGENCY_HANDLER;
address public immutable LENDER_RETURN_BPS_FEED;
uint256 public immutable LEVERAGE_BPS;
uint256 public immutable MIN_BORROW_DEPOSIT;
uint256 public immutable COMMIT_PHASE_END;
uint256 public immutable PRE_HOLD_SWAP_TIMEOUT_END;
uint256 public immutable POOL_PHASE_END;
uint256 public immutable POOL_PHASE_DURATION;
uint256 public immutable LENDER_RETURN_FEE;
uint256 public immutable BORROWER_RETURN_FEE;
Commitments internal borrowers;
Commitments internal lenders;
State internal setState = State.Commit;
uint128 internal borrowerDistribution;
uint128 internal totalBorrowerShares;
uint128 internal lenderDistribution;
uint128 internal totalLenderShares;
modifier onlyState(State expectedState) {
State currentState = state();
if (currentState != expectedState) revert InvalidState(currentState);
_;
}
modifier onlyAfterState(State lastInvalidState) {
State currentState = state();
if (currentState <= lastInvalidState) revert InvalidState(currentState);
_;
}
constructor(
address underlyingToken,
address billToken,
IWhitelist whitelist,
address swapFacility,
address treasury,
address lenderReturnBpsFeed,
address emergencyHandler,
uint256 leverageBps,
uint256 minBorrowDeposit,
uint256 commitPhaseDuration,
uint256 preHoldSwapTimeout,
uint256 poolPhaseDuration,
uint256 lenderReturnFee,
uint256 borrowerReturnFee,
string memory name,
string memory symbol
) ERC20(name, symbol, ERC20(underlyingToken).decimals()) {
UNDERLYING_TOKEN = underlyingToken;
BILL_TOKEN = billToken;
WHITELIST = whitelist;
SWAP_FACILITY = swapFacility;
TREASURY = treasury;
LENDER_RETURN_BPS_FEED = lenderReturnBpsFeed;
EMERGENCY_HANDLER = emergencyHandler;
LEVERAGE_BPS = leverageBps;
MIN_BORROW_DEPOSIT = minBorrowDeposit;
COMMIT_PHASE_END = block.timestamp + commitPhaseDuration;
PRE_HOLD_SWAP_TIMEOUT_END = block.timestamp + commitPhaseDuration + preHoldSwapTimeout;
POOL_PHASE_END = block.timestamp + commitPhaseDuration + poolPhaseDuration;
POOL_PHASE_DURATION = poolPhaseDuration;
LENDER_RETURN_FEE = lenderReturnFee;
BORROWER_RETURN_FEE = borrowerReturnFee;
}
function depositBorrower(uint256 amount, bytes32[] calldata proof)
external
onlyState(State.Commit)
returns (uint256 newId)
{
if (amount < MIN_BORROW_DEPOSIT) revert CommitTooSmall();
if (!IWhitelist(WHITELIST).isWhitelisted(msg.sender, proof)) revert NotWhitelisted();
UNDERLYING_TOKEN.safeTransferFrom(msg.sender, address(this), amount);
uint256 cumulativeAmountEnd;
(newId, cumulativeAmountEnd) = borrowers.add(msg.sender, amount);
emit BorrowerCommit(msg.sender, newId, amount, cumulativeAmountEnd);
}
function depositLender(uint256 amount) external onlyState(State.Commit) returns (uint256 newId) {
if (amount == 0) revert CommitTooSmall();
UNDERLYING_TOKEN.safeTransferFrom(msg.sender, address(this), amount);
uint256 cumulativeAmountEnd;
(newId, cumulativeAmountEnd) = lenders.add(msg.sender, amount);
emit LenderCommit(msg.sender, newId, amount, cumulativeAmountEnd);
}
function processBorrowerCommit(uint256 id) external onlyAfterState(State.Commit) {
AssetCommitment storage commitment = borrowers.commitments[id];
if (commitment.cumulativeAmountEnd == 0) revert NoCommitToProcess();
uint256 committedBorrowValue = lenders.totalAssetsCommitted * BPS / LEVERAGE_BPS;
(uint256 includedAmount, uint256 excludedAmount) = commitment.getAmountSplit(committedBorrowValue);
commitment.committedAmount = includedAmount.toUint128();
commitment.cumulativeAmountEnd = 0;
address owner = commitment.owner;
emit BorrowerCommitmentProcessed(owner, id, includedAmount, excludedAmount);
if (excludedAmount > 0) UNDERLYING_TOKEN.safeTransfer(owner, excludedAmount);
}
function processLenderCommit(uint256 id) external onlyAfterState(State.Commit) {
AssetCommitment storage commitment = lenders.commitments[id];
if (commitment.cumulativeAmountEnd == 0) revert NoCommitToProcess();
uint256 committedBorrowValue = borrowers.totalAssetsCommitted * LEVERAGE_BPS / BPS;
(uint256 includedAmount, uint256 excludedAmount) = commitment.getAmountSplit(committedBorrowValue);
address owner = commitment.owner;
delete lenders.commitments[id];
_mint(owner, includedAmount);
emit LenderCommitmentProcessed(owner, id, includedAmount, excludedAmount);
if (excludedAmount > 0) UNDERLYING_TOKEN.safeTransfer(owner, excludedAmount);
}
function initiatePreHoldSwap(bytes32[] calldata proof) external onlyState(State.ReadyPreHoldSwap) {
uint256 amountToSwap = totalMatchAmount() * (LEVERAGE_BPS + BPS) / LEVERAGE_BPS;
UNDERLYING_TOKEN.safeApprove(SWAP_FACILITY, 0);
UNDERLYING_TOKEN.safeApprove(SWAP_FACILITY, amountToSwap);
emit ExplictStateTransition(State.ReadyPreHoldSwap, setState = State.PendingPreHoldSwap);
ISwapFacility(SWAP_FACILITY).swap(UNDERLYING_TOKEN, BILL_TOKEN, amountToSwap, proof);
}
function initiatePostHoldSwap(bytes32[] calldata proof) external onlyState(State.ReadyPostHoldSwap) {
uint256 amountToSwap = ERC20(BILL_TOKEN).balanceOf(address(this));
BILL_TOKEN.safeApprove(SWAP_FACILITY, 0);
BILL_TOKEN.safeApprove(SWAP_FACILITY, amountToSwap);
emit ExplictStateTransition(State.ReadyPostHoldSwap, setState = State.PendingPostHoldSwap);
ISwapFacility(SWAP_FACILITY).swap(BILL_TOKEN, UNDERLYING_TOKEN, amountToSwap, proof);
}
function completeSwap(address outToken, uint256 outAmount) external {
if (msg.sender != SWAP_FACILITY) revert NotSwapFacility();
State currentState = state();
if (currentState == State.PendingPreHoldSwap) {
if (outToken != BILL_TOKEN) revert InvalidOutToken(outToken);
emit ExplictStateTransition(State.PendingPreHoldSwap, setState = State.Holding);
return;
}
if (currentState == State.PendingPostHoldSwap) {
if (outToken != UNDERLYING_TOKEN) revert InvalidOutToken(outToken);
uint256 totalMatched = totalMatchAmount();
uint256 lenderReturn = Math.min(
totalMatched * IBPSFeed(LENDER_RETURN_BPS_FEED).getWeightedRate() * POOL_PHASE_DURATION / 360 days / BPS,
outAmount
);
uint256 borrowerReturn = outAmount - lenderReturn;
uint256 lenderReturnFee = (lenderReturn - totalMatched) * LENDER_RETURN_FEE / BPS;
uint256 borrowerReturnFee = borrowerReturn * BORROWER_RETURN_FEE / BPS;
borrowerDistribution = (borrowerReturn - borrowerReturnFee).toUint128();
totalBorrowerShares = uint256(totalMatched * BPS / LEVERAGE_BPS).toUint128();
lenderDistribution = (lenderReturn - lenderReturnFee).toUint128();
totalLenderShares = uint256(totalMatched).toUint128();
UNDERLYING_TOKEN.safeTransfer(TREASURY, lenderReturnFee + borrowerReturnFee);
emit ExplictStateTransition(State.PendingPostHoldSwap, setState = State.FinalWithdraw);
return;
}
revert InvalidState(currentState);
}
function withdrawBorrower(uint256 id) external onlyState(State.FinalWithdraw) {
AssetCommitment storage commitment = borrowers.commitments[id];
if (commitment.cumulativeAmountEnd != 0) revert CanOnlyWithdrawProcessedCommit(id);
address owner = commitment.owner;
if (owner == address(0)) revert NoCommitToWithdraw();
uint256 shares = commitment.committedAmount;
uint256 currentBorrowerDist = borrowerDistribution;
uint256 sharesLeft = totalBorrowerShares;
uint256 claimAmount = shares * currentBorrowerDist / sharesLeft;
borrowerDistribution = (currentBorrowerDist - claimAmount).toUint128();
totalBorrowerShares = (sharesLeft - shares).toUint128();
delete borrowers.commitments[id];
emit BorrowerWithdraw(owner, id, claimAmount);
UNDERLYING_TOKEN.safeTransfer(owner, claimAmount);
}
function withdrawLender(uint256 shares) external onlyState(State.FinalWithdraw) {
_burn(msg.sender, shares);
uint256 currentLenderDist = lenderDistribution;
uint256 sharesLeft = totalLenderShares;
uint256 claimAmount = shares * currentLenderDist / sharesLeft;
lenderDistribution = (currentLenderDist - claimAmount).toUint128();
totalLenderShares = (sharesLeft - shares).toUint128();
emit LenderWithdraw(msg.sender, shares, claimAmount);
UNDERLYING_TOKEN.safeTransfer(msg.sender, claimAmount);
}
function emergencyWithdrawTo(address to) external onlyState(State.EmergencyExit) {
if (msg.sender != EMERGENCY_HANDLER) revert NotEmergencyHandler();
emit EmergencyWithdraw(to);
UNDERLYING_TOKEN.safeTransferAll(to);
BILL_TOKEN.safeTransferAll(to);
}
function totalMatchAmount() public view returns (uint256) {
uint256 borrowDemand = borrowers.totalAssetsCommitted * LEVERAGE_BPS / BPS;
uint256 lendDemand = lenders.totalAssetsCommitted;
return Math.min(borrowDemand, lendDemand);
}
function state() public view returns (State) {
if (block.timestamp < COMMIT_PHASE_END) {
return State.Commit;
}
State lastState = setState;
if (lastState == State.Commit && block.timestamp >= COMMIT_PHASE_END) {
return State.ReadyPreHoldSwap;
}
if (lastState == State.PendingPreHoldSwap && block.timestamp >= PRE_HOLD_SWAP_TIMEOUT_END) {
return State.EmergencyExit;
}
if (lastState == State.Holding && block.timestamp >= POOL_PHASE_END) {
return State.ReadyPostHoldSwap;
}
return lastState;
}
function getBorrowCommitment(uint256 id) external view returns (AssetCommitment memory) {
return borrowers.get(id);
}
function getLenderCommitment(uint256 id) external view returns (AssetCommitment memory) {
return lenders.get(id);
}
function getTotalBorrowCommitment()
external
view
returns (uint256 totalAssetsCommitted, uint256 totalCommitmentCount)
{
totalAssetsCommitted = borrowers.totalAssetsCommitted;
totalCommitmentCount = borrowers.commitmentCount;
}
function getTotalLendCommitment()
external
view
returns (uint256 totalAssetsCommitted, uint256 totalCommitmentCount)
{
totalAssetsCommitted = lenders.totalAssetsCommitted;
totalCommitmentCount = lenders.commitmentCount;
}
function getDistributionInfo() external view returns (uint128, uint128, uint128, uint128) {
return (borrowerDistribution, totalBorrowerShares, lenderDistribution, totalLenderShares);
}
}
文件 2 的 11:CommitmentsLib.sol
pragma solidity 0.8.19;
import {SafeCastLib} from "solady/utils/SafeCastLib.sol";
struct AssetCommitment {
address owner;
uint128 committedAmount;
uint128 cumulativeAmountEnd;
}
struct Commitments {
mapping(uint256 => AssetCommitment) commitments;
uint64 commitmentCount;
uint192 totalAssetsCommitted;
}
library CommitmentsLib {
using SafeCastLib for uint256;
error NonexistentCommit();
function add(Commitments storage commitments, address owner, uint256 amount)
internal
returns (uint256 newCommitmendId, uint256 cumulativeAmountEnd)
{
uint256 commitmentCount = commitments.commitmentCount;
unchecked {
newCommitmendId = commitmentCount++;
}
cumulativeAmountEnd = commitments.totalAssetsCommitted + amount;
commitments.commitments[newCommitmendId] = AssetCommitment({
owner: owner,
committedAmount: uint128(amount),
cumulativeAmountEnd: cumulativeAmountEnd.toUint128()
});
commitments.commitmentCount = commitmentCount.toUint64();
commitments.totalAssetsCommitted = uint192(cumulativeAmountEnd);
}
function getAmountSplit(AssetCommitment storage commitment, uint256 totalIncludedAmount)
internal
view
returns (uint256 includedAmount, uint256 excludedAmount)
{
uint256 committedAmount = commitment.committedAmount;
uint256 cumulativeAmountEnd = commitment.cumulativeAmountEnd;
if (totalIncludedAmount >= cumulativeAmountEnd) {
includedAmount = committedAmount;
excludedAmount = 0;
} else {
uint256 cumulativeAmountStart = cumulativeAmountEnd - committedAmount;
if (cumulativeAmountStart > totalIncludedAmount) {
includedAmount = 0;
excludedAmount = committedAmount;
} else {
unchecked {
includedAmount = totalIncludedAmount - cumulativeAmountStart;
excludedAmount = committedAmount - includedAmount;
}
}
}
}
function get(Commitments storage commitments, uint256 id) internal view returns (AssetCommitment storage) {
if (id >= commitments.commitmentCount) {
revert NonexistentCommit();
}
return commitments.commitments[id];
}
}
文件 3 的 11:ERC20.sol
pragma solidity >=0.8.0;
abstract contract ERC20 {
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}
文件 4 的 11:FixedPointMathLib.sol
pragma solidity ^0.8.4;
library FixedPointMathLib {
error ExpOverflow();
error FactorialOverflow();
error MulWadFailed();
error DivWadFailed();
error MulDivFailed();
error DivFailed();
error FullMulDivFailed();
error LnWadUndefined();
error Log2Undefined();
uint256 internal constant WAD = 1e18;
function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
if mul(y, gt(x, div(not(0), y))) {
mstore(0x00, 0xbac65e5b)
revert(0x1c, 0x04)
}
z := div(mul(x, y), WAD)
}
}
function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
if mul(y, gt(x, div(not(0), y))) {
mstore(0x00, 0xbac65e5b)
revert(0x1c, 0x04)
}
z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))
}
}
function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {
mstore(0x00, 0x7c5f487d)
revert(0x1c, 0x04)
}
z := div(mul(x, WAD), y)
}
}
function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {
mstore(0x00, 0x7c5f487d)
revert(0x1c, 0x04)
}
z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))
}
}
function powWad(int256 x, int256 y) internal pure returns (int256) {
return expWad((lnWad(x) * y) / int256(WAD));
}
function expWad(int256 x) internal pure returns (int256 r) {
unchecked {
if (x <= -42139678854452767551) return r;
assembly {
if iszero(slt(x, 135305999368893231589)) {
mstore(0x00, 0xa37bfec9)
revert(0x1c, 0x04)
}
}
x = (x << 78) / 5 ** 18;
int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96;
x = x - k * 54916777467707473351141471128;
int256 y = x + 1346386616545796478920950773328;
y = ((y * x) >> 96) + 57155421227552351082224309758442;
int256 p = y + x - 94201549194550492254356042504812;
p = ((p * y) >> 96) + 28719021644029726153956944680412240;
p = p * x + (4385272521454847904659076985693276 << 96);
int256 q = x - 2855989394907223263936484059900;
q = ((q * x) >> 96) + 50020603652535783019961831881945;
q = ((q * x) >> 96) - 533845033583426703283633433725380;
q = ((q * x) >> 96) + 3604857256930695427073651918091429;
q = ((q * x) >> 96) - 14423608567350463180887372962807573;
q = ((q * x) >> 96) + 26449188498355588339934803723976023;
assembly {
r := sdiv(p, q)
}
r = int256(
(uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)
);
}
}
function lnWad(int256 x) internal pure returns (int256 r) {
unchecked {
assembly {
if iszero(sgt(x, 0)) {
mstore(0x00, 0x1615e638)
revert(0x1c, 0x04)
}
}
int256 k;
assembly {
let v := x
k := shl(7, lt(0xffffffffffffffffffffffffffffffff, v))
k := or(k, shl(6, lt(0xffffffffffffffff, shr(k, v))))
k := or(k, shl(5, lt(0xffffffff, shr(k, v))))
v := shr(k, v)
v := or(v, shr(1, v))
v := or(v, shr(2, v))
v := or(v, shr(4, v))
v := or(v, shr(8, v))
v := or(v, shr(16, v))
k := sub(or(k, byte(shr(251, mul(v, shl(224, 0x07c4acdd))),
0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f)), 96)
}
x <<= uint256(159 - k);
x = int256(uint256(x) >> 159);
int256 p = x + 3273285459638523848632254066296;
p = ((p * x) >> 96) + 24828157081833163892658089445524;
p = ((p * x) >> 96) + 43456485725739037958740375743393;
p = ((p * x) >> 96) - 11111509109440967052023855526967;
p = ((p * x) >> 96) - 45023709667254063763336534515857;
p = ((p * x) >> 96) - 14706773417378608786704636184526;
p = p * x - (795164235651350426258249787498 << 96);
int256 q = x + 5573035233440673466300451813936;
q = ((q * x) >> 96) + 71694874799317883764090561454958;
q = ((q * x) >> 96) + 283447036172924575727196451306956;
q = ((q * x) >> 96) + 401686690394027663651624208769553;
q = ((q * x) >> 96) + 204048457590392012362485061816622;
q = ((q * x) >> 96) + 31853899698501571402653359427138;
q = ((q * x) >> 96) + 909429971244387300277376558375;
assembly {
r := sdiv(p, q)
}
r *= 1677202110996718588342820967067443963516166;
r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;
r += 600920179829731861736702779321621459595472258049074101567377883020018308;
r >>= 174;
}
}
function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {
assembly {
for {} 1 {} {
let prod0 := mul(x, y)
let mm := mulmod(x, y, not(0))
let prod1 := sub(mm, add(prod0, lt(mm, prod0)))
if iszero(prod1) {
if iszero(d) {
mstore(0x00, 0xae47f702)
revert(0x1c, 0x04)
}
result := div(prod0, d)
break
}
if iszero(gt(d, prod1)) {
mstore(0x00, 0xae47f702)
revert(0x1c, 0x04)
}
let remainder := mulmod(x, y, d)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
let twos := and(d, sub(0, d))
d := div(d, twos)
prod0 := div(prod0, twos)
prod0 := or(prod0, mul(prod1, add(div(sub(0, twos), twos), 1)))
let inv := xor(mul(3, d), 2)
inv := mul(inv, sub(2, mul(d, inv)))
inv := mul(inv, sub(2, mul(d, inv)))
inv := mul(inv, sub(2, mul(d, inv)))
inv := mul(inv, sub(2, mul(d, inv)))
inv := mul(inv, sub(2, mul(d, inv)))
result := mul(prod0, mul(inv, sub(2, mul(d, inv))))
break
}
}
}
function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {
result = fullMulDiv(x, y, d);
assembly {
if mulmod(x, y, d) {
if iszero(add(result, 1)) {
mstore(0x00, 0xae47f702)
revert(0x1c, 0x04)
}
result := add(result, 1)
}
}
}
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))
}
}
function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) {
assembly {
if iszero(d) {
mstore(0x00, 0x65244e4e)
revert(0x1c, 0x04)
}
z := add(iszero(iszero(mod(x, d))), div(x, d))
}
}
function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := mul(gt(x, y), sub(x, y))
}
}
function sqrt(uint256 x) internal pure returns (uint256 z) {
assembly {
z := 181
let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x))
r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x))))
r := or(r, shl(5, lt(0xffffffffff, shr(r, x))))
r := or(r, shl(4, lt(0xffffff, shr(r, x))))
z := shl(shr(1, r), z)
z := shr(18, mul(z, add(shr(r, x), 65536)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := sub(z, lt(div(x, z), z))
}
}
function cbrt(uint256 x) internal pure returns (uint256 z) {
assembly {
let 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))))
z := shl(add(div(r, 3), lt(0xf, shr(r, x))), 0xff)
z := div(z, byte(mod(r, 3), shl(232, 0x7f624b)))
z := div(add(add(div(x, mul(z, z)), z), z), 3)
z := div(add(add(div(x, mul(z, z)), z), z), 3)
z := div(add(add(div(x, mul(z, z)), z), z), 3)
z := div(add(add(div(x, mul(z, z)), z), z), 3)
z := div(add(add(div(x, mul(z, z)), z), z), 3)
z := div(add(add(div(x, mul(z, z)), z), z), 3)
z := div(add(add(div(x, mul(z, z)), z), z), 3)
z := sub(z, lt(div(x, mul(z, z)), z))
}
}
function factorial(uint256 x) internal pure returns (uint256 result) {
assembly {
for {} 1 {} {
if iszero(lt(10, x)) {
result := and(
shr(mul(22, x), 0x375f0016260009d80004ec0002d00001e0000180000180000200000400001),
0x3fffff
)
break
}
if iszero(lt(57, x)) {
let end := 31
result := 8222838654177922817725562880000000
if iszero(lt(end, x)) {
end := 10
result := 3628800
}
for { let w := not(0) } 1 {} {
result := mul(result, x)
x := add(x, w)
if eq(x, end) { break }
}
break
}
mstore(0x00, 0xaba0f2a2)
revert(0x1c, 0x04)
}
}
}
function log2(uint256 x) internal pure returns (uint256 r) {
assembly {
if iszero(x) {
mstore(0x00, 0x5be3aa5c)
revert(0x1c, 0x04)
}
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))))
x := shr(r, x)
x := or(x, shr(1, x))
x := or(x, shr(2, x))
x := or(x, shr(4, x))
x := or(x, shr(8, x))
x := or(x, shr(16, x))
r := or(r, byte(shr(251, mul(x, shl(224, 0x07c4acdd))),
0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f))
}
}
function log2Up(uint256 x) internal pure returns (uint256 r) {
unchecked {
uint256 isNotPo2;
assembly {
isNotPo2 := iszero(iszero(and(x, sub(x, 1))))
}
return log2(x) + isNotPo2;
}
}
function avg(uint256 x, uint256 y) internal pure returns (uint256 z) {
unchecked {
z = (x & y) + ((x ^ y) >> 1);
}
}
function avg(int256 x, int256 y) internal pure returns (int256 z) {
unchecked {
z = (x >> 1) + (y >> 1) + (((x & 1) + (y & 1)) >> 1);
}
}
function abs(int256 x) internal pure returns (uint256 z) {
assembly {
let mask := sub(0, shr(255, x))
z := xor(mask, add(mask, x))
}
}
function dist(int256 x, int256 y) internal pure returns (uint256 z) {
assembly {
let a := sub(y, x)
z := xor(a, mul(xor(a, sub(x, y)), sgt(x, y)))
}
}
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := xor(x, mul(xor(x, y), lt(y, x)))
}
}
function min(int256 x, int256 y) internal pure returns (int256 z) {
assembly {
z := xor(x, mul(xor(x, y), slt(y, x)))
}
}
function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := xor(x, mul(xor(x, y), gt(y, x)))
}
}
function max(int256 x, int256 y) internal pure returns (int256 z) {
assembly {
z := xor(x, mul(xor(x, y), sgt(y, x)))
}
}
function clamp(uint256 x, uint256 minValue, uint256 maxValue)
internal
pure
returns (uint256 z)
{
z = min(max(x, minValue), maxValue);
}
function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) {
z = min(max(x, minValue), maxValue);
}
function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
for { z := x } y {} {
let t := y
y := mod(z, y)
z := t
}
}
}
function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) {
unchecked {
z = x + y;
}
}
function rawAdd(int256 x, int256 y) internal pure returns (int256 z) {
unchecked {
z = x + y;
}
}
function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
unchecked {
z = x - y;
}
}
function rawSub(int256 x, int256 y) internal pure returns (int256 z) {
unchecked {
z = x - y;
}
}
function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) {
unchecked {
z = x * y;
}
}
function rawMul(int256 x, int256 y) internal pure returns (int256 z) {
unchecked {
z = x * y;
}
}
function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := div(x, y)
}
}
function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) {
assembly {
z := sdiv(x, y)
}
}
function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := mod(x, y)
}
}
function rawSMod(int256 x, int256 y) internal pure returns (int256 z) {
assembly {
z := smod(x, y)
}
}
function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
assembly {
z := addmod(x, y, d)
}
}
function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
assembly {
z := mulmod(x, y, d)
}
}
}
文件 5 的 11:IBPSFeed.sol
pragma solidity 0.8.19;
interface IBPSFeed {
error InvalidRate();
event UpdateRate(uint256 currentRate);
function getWeightedRate() external view returns (uint256);
function currentRate() external view returns (uint256);
function lastTimestamp() external view returns (uint256);
function updateRate(uint256 rate) external;
}
文件 6 的 11:IBloomPool.sol
pragma solidity 0.8.19;
import {AssetCommitment} from "../lib/CommitmentsLib.sol";
import {IWhitelist} from "../interfaces/IWhitelist.sol";
enum State {
Other,
Commit,
ReadyPreHoldSwap,
PendingPreHoldSwap,
Holding,
ReadyPostHoldSwap,
PendingPostHoldSwap,
EmergencyExit,
FinalWithdraw
}
interface IBloomPool {
error ZeroAddress();
error NotSwapFacility();
error InvalidOutToken(address outToken);
error NotWhitelisted();
error NoCommitToProcess();
error CommitTooSmall();
error CanOnlyWithdrawProcessedCommit(uint256 id);
error NoCommitToWithdraw();
error InvalidState(State current);
error NotEmergencyHandler();
event BorrowerCommit(address indexed owner, uint256 indexed id, uint256 amount, uint256 cumulativeAmountEnd);
event LenderCommit(address indexed owner, uint256 indexed id, uint256 amount, uint256 cumulativeAmountEnd);
event BorrowerCommitmentProcessed(
address indexed owner, uint256 indexed id, uint256 includedAmount, uint256 excludedAmount
);
event LenderCommitmentProcessed(
address indexed owner, uint256 indexed id, uint256 includedAmount, uint256 excludedAmount
);
event ExplictStateTransition(State prevState, State newState);
event BorrowerWithdraw(address indexed owner, uint256 indexed id, uint256 amount);
event LenderWithdraw(address indexed owner, uint256 sharesRedeemed, uint256 amount);
event EmergencyWithdraw(address indexed to);
function initiatePreHoldSwap(bytes32[] calldata proof) external;
function initiatePostHoldSwap(bytes32[] calldata proof) external;
function depositBorrower(uint256 amount, bytes32[] calldata proof) external returns (uint256 newCommitmentId);
function depositLender(uint256 amount) external returns (uint256 newCommitmentId);
function processBorrowerCommit(uint256 commitId) external;
function processLenderCommit(uint256 commitId) external;
function withdrawBorrower(uint256 id) external;
function withdrawLender(uint256 shares) external;
function UNDERLYING_TOKEN() external view returns (address);
function BILL_TOKEN() external view returns (address);
function WHITELIST() external view returns (IWhitelist);
function SWAP_FACILITY() external view returns (address);
function TREASURY() external view returns (address);
function LENDER_RETURN_BPS_FEED() external view returns (address);
function LEVERAGE_BPS() external view returns (uint256);
function MIN_BORROW_DEPOSIT() external view returns (uint256);
function COMMIT_PHASE_END() external view returns (uint256);
function PRE_HOLD_SWAP_TIMEOUT_END() external view returns (uint256);
function POOL_PHASE_END() external view returns (uint256);
function POOL_PHASE_DURATION() external view returns (uint256);
function LENDER_RETURN_FEE() external view returns (uint256);
function BORROWER_RETURN_FEE() external view returns (uint256);
function state() external view returns (State currentState);
function totalMatchAmount() external view returns (uint256);
function getBorrowCommitment(uint256 id) external view returns (AssetCommitment memory);
function getLenderCommitment(uint256 id) external view returns (AssetCommitment memory);
function getTotalBorrowCommitment()
external
view
returns (uint256 totalAssetsCommited, uint256 totalCommitmentCount);
function getTotalLendCommitment()
external
view
returns (uint256 totalAssetsCommited, uint256 totalCommitmentCount);
function getDistributionInfo()
external
view
returns (
uint128 borrowerDistribution,
uint128 totalBorrowerShares,
uint128 lenderDistribution,
uint128 totalLenderShares
);
}
文件 7 的 11:ISwapFacility.sol
pragma solidity 0.8.19;
import {IWhitelist} from "../interfaces/IWhitelist.sol";
interface ISwapFacility {
function underlyingToken() external view returns (address);
function billyToken() external view returns (address);
function underlyingTokenOracle() external view returns (address);
function billyTokenOracle() external view returns (address);
function whitelist() external view returns (IWhitelist);
function spread() external view returns (uint256);
function pool() external view returns (address);
function swap(address inToken, address outToken, uint256 inAmount, bytes32[] calldata proof) external;
}
文件 8 的 11:ISwapRecipient.sol
pragma solidity ^0.8.0;
interface ISwapRecipient {
function completeSwap(address outToken, uint256 outAmount) external;
}
文件 9 的 11:IWhitelist.sol
pragma solidity 0.8.19;
interface IWhitelist {
event NewWhitelistRoot(bytes32 newRoot);
function setRoot(bytes32 newRoot) external;
function isWhitelisted(address member, bytes32[] calldata proof) external returns (bool);
}
文件 10 的 11:SafeCastLib.sol
pragma solidity ^0.8.4;
library SafeCastLib {
error Overflow();
function toUint8(uint256 x) internal pure returns (uint8) {
if (x >= 1 << 8) _revertOverflow();
return uint8(x);
}
function toUint16(uint256 x) internal pure returns (uint16) {
if (x >= 1 << 16) _revertOverflow();
return uint16(x);
}
function toUint24(uint256 x) internal pure returns (uint24) {
if (x >= 1 << 24) _revertOverflow();
return uint24(x);
}
function toUint32(uint256 x) internal pure returns (uint32) {
if (x >= 1 << 32) _revertOverflow();
return uint32(x);
}
function toUint40(uint256 x) internal pure returns (uint40) {
if (x >= 1 << 40) _revertOverflow();
return uint40(x);
}
function toUint48(uint256 x) internal pure returns (uint48) {
if (x >= 1 << 48) _revertOverflow();
return uint48(x);
}
function toUint56(uint256 x) internal pure returns (uint56) {
if (x >= 1 << 56) _revertOverflow();
return uint56(x);
}
function toUint64(uint256 x) internal pure returns (uint64) {
if (x >= 1 << 64) _revertOverflow();
return uint64(x);
}
function toUint72(uint256 x) internal pure returns (uint72) {
if (x >= 1 << 72) _revertOverflow();
return uint72(x);
}
function toUint80(uint256 x) internal pure returns (uint80) {
if (x >= 1 << 80) _revertOverflow();
return uint80(x);
}
function toUint88(uint256 x) internal pure returns (uint88) {
if (x >= 1 << 88) _revertOverflow();
return uint88(x);
}
function toUint96(uint256 x) internal pure returns (uint96) {
if (x >= 1 << 96) _revertOverflow();
return uint96(x);
}
function toUint104(uint256 x) internal pure returns (uint104) {
if (x >= 1 << 104) _revertOverflow();
return uint104(x);
}
function toUint112(uint256 x) internal pure returns (uint112) {
if (x >= 1 << 112) _revertOverflow();
return uint112(x);
}
function toUint120(uint256 x) internal pure returns (uint120) {
if (x >= 1 << 120) _revertOverflow();
return uint120(x);
}
function toUint128(uint256 x) internal pure returns (uint128) {
if (x >= 1 << 128) _revertOverflow();
return uint128(x);
}
function toUint136(uint256 x) internal pure returns (uint136) {
if (x >= 1 << 136) _revertOverflow();
return uint136(x);
}
function toUint144(uint256 x) internal pure returns (uint144) {
if (x >= 1 << 144) _revertOverflow();
return uint144(x);
}
function toUint152(uint256 x) internal pure returns (uint152) {
if (x >= 1 << 152) _revertOverflow();
return uint152(x);
}
function toUint160(uint256 x) internal pure returns (uint160) {
if (x >= 1 << 160) _revertOverflow();
return uint160(x);
}
function toUint168(uint256 x) internal pure returns (uint168) {
if (x >= 1 << 168) _revertOverflow();
return uint168(x);
}
function toUint176(uint256 x) internal pure returns (uint176) {
if (x >= 1 << 176) _revertOverflow();
return uint176(x);
}
function toUint184(uint256 x) internal pure returns (uint184) {
if (x >= 1 << 184) _revertOverflow();
return uint184(x);
}
function toUint192(uint256 x) internal pure returns (uint192) {
if (x >= 1 << 192) _revertOverflow();
return uint192(x);
}
function toUint200(uint256 x) internal pure returns (uint200) {
if (x >= 1 << 200) _revertOverflow();
return uint200(x);
}
function toUint208(uint256 x) internal pure returns (uint208) {
if (x >= 1 << 208) _revertOverflow();
return uint208(x);
}
function toUint216(uint256 x) internal pure returns (uint216) {
if (x >= 1 << 216) _revertOverflow();
return uint216(x);
}
function toUint224(uint256 x) internal pure returns (uint224) {
if (x >= 1 << 224) _revertOverflow();
return uint224(x);
}
function toUint232(uint256 x) internal pure returns (uint232) {
if (x >= 1 << 232) _revertOverflow();
return uint232(x);
}
function toUint240(uint256 x) internal pure returns (uint240) {
if (x >= 1 << 240) _revertOverflow();
return uint240(x);
}
function toUint248(uint256 x) internal pure returns (uint248) {
if (x >= 1 << 248) _revertOverflow();
return uint248(x);
}
function toInt8(int256 x) internal pure returns (int8) {
int8 y = int8(x);
if (x != y) _revertOverflow();
return y;
}
function toInt16(int256 x) internal pure returns (int16) {
int16 y = int16(x);
if (x != y) _revertOverflow();
return y;
}
function toInt24(int256 x) internal pure returns (int24) {
int24 y = int24(x);
if (x != y) _revertOverflow();
return y;
}
function toInt32(int256 x) internal pure returns (int32) {
int32 y = int32(x);
if (x != y) _revertOverflow();
return y;
}
function toInt40(int256 x) internal pure returns (int40) {
int40 y = int40(x);
if (x != y) _revertOverflow();
return y;
}
function toInt48(int256 x) internal pure returns (int48) {
int48 y = int48(x);
if (x != y) _revertOverflow();
return y;
}
function toInt56(int256 x) internal pure returns (int56) {
int56 y = int56(x);
if (x != y) _revertOverflow();
return y;
}
function toInt64(int256 x) internal pure returns (int64) {
int64 y = int64(x);
if (x != y) _revertOverflow();
return y;
}
function toInt72(int256 x) internal pure returns (int72) {
int72 y = int72(x);
if (x != y) _revertOverflow();
return y;
}
function toInt80(int256 x) internal pure returns (int80) {
int80 y = int80(x);
if (x != y) _revertOverflow();
return y;
}
function toInt88(int256 x) internal pure returns (int88) {
int88 y = int88(x);
if (x != y) _revertOverflow();
return y;
}
function toInt96(int256 x) internal pure returns (int96) {
int96 y = int96(x);
if (x != y) _revertOverflow();
return y;
}
function toInt104(int256 x) internal pure returns (int104) {
int104 y = int104(x);
if (x != y) _revertOverflow();
return y;
}
function toInt112(int256 x) internal pure returns (int112) {
int112 y = int112(x);
if (x != y) _revertOverflow();
return y;
}
function toInt120(int256 x) internal pure returns (int120) {
int120 y = int120(x);
if (x != y) _revertOverflow();
return y;
}
function toInt128(int256 x) internal pure returns (int128) {
int128 y = int128(x);
if (x != y) _revertOverflow();
return y;
}
function toInt136(int256 x) internal pure returns (int136) {
int136 y = int136(x);
if (x != y) _revertOverflow();
return y;
}
function toInt144(int256 x) internal pure returns (int144) {
int144 y = int144(x);
if (x != y) _revertOverflow();
return y;
}
function toInt152(int256 x) internal pure returns (int152) {
int152 y = int152(x);
if (x != y) _revertOverflow();
return y;
}
function toInt160(int256 x) internal pure returns (int160) {
int160 y = int160(x);
if (x != y) _revertOverflow();
return y;
}
function toInt168(int256 x) internal pure returns (int168) {
int168 y = int168(x);
if (x != y) _revertOverflow();
return y;
}
function toInt176(int256 x) internal pure returns (int176) {
int176 y = int176(x);
if (x != y) _revertOverflow();
return y;
}
function toInt184(int256 x) internal pure returns (int184) {
int184 y = int184(x);
if (x != y) _revertOverflow();
return y;
}
function toInt192(int256 x) internal pure returns (int192) {
int192 y = int192(x);
if (x != y) _revertOverflow();
return y;
}
function toInt200(int256 x) internal pure returns (int200) {
int200 y = int200(x);
if (x != y) _revertOverflow();
return y;
}
function toInt208(int256 x) internal pure returns (int208) {
int208 y = int208(x);
if (x != y) _revertOverflow();
return y;
}
function toInt216(int256 x) internal pure returns (int216) {
int216 y = int216(x);
if (x != y) _revertOverflow();
return y;
}
function toInt224(int256 x) internal pure returns (int224) {
int224 y = int224(x);
if (x != y) _revertOverflow();
return y;
}
function toInt232(int256 x) internal pure returns (int232) {
int232 y = int232(x);
if (x != y) _revertOverflow();
return y;
}
function toInt240(int256 x) internal pure returns (int240) {
int240 y = int240(x);
if (x != y) _revertOverflow();
return y;
}
function toInt248(int256 x) internal pure returns (int248) {
int248 y = int248(x);
if (x != y) _revertOverflow();
return y;
}
function _revertOverflow() private pure {
assembly {
mstore(0x00, 0x35278d12)
revert(0x1c, 0x04)
}
}
}
文件 11 的 11:SafeTransferLib.sol
pragma solidity ^0.8.4;
library SafeTransferLib {
error ETHTransferFailed();
error TransferFromFailed();
error TransferFailed();
error ApproveFailed();
uint256 internal constant _GAS_STIPEND_NO_STORAGE_WRITES = 2300;
uint256 internal constant _GAS_STIPEND_NO_GRIEF = 100000;
function safeTransferETH(address to, uint256 amount) internal {
assembly {
if iszero(call(gas(), to, amount, 0, 0, 0, 0)) {
mstore(0x00, 0xb12d13eb)
revert(0x1c, 0x04)
}
}
}
function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
assembly {
if lt(selfbalance(), amount) {
mstore(0x00, 0xb12d13eb)
revert(0x1c, 0x04)
}
if iszero(call(gasStipend, to, amount, 0, 0, 0, 0)) {
mstore(0x00, to)
mstore8(0x0b, 0x73)
mstore8(0x20, 0xff)
if iszero(create(amount, 0x0b, 0x16)) {
if iszero(gt(gas(), 1000000)) { revert(0, 0) }
}
}
}
}
function forceSafeTransferETH(address to, uint256 amount) internal {
assembly {
if lt(selfbalance(), amount) {
mstore(0x00, 0xb12d13eb)
revert(0x1c, 0x04)
}
if iszero(call(_GAS_STIPEND_NO_GRIEF, to, amount, 0, 0, 0, 0)) {
mstore(0x00, to)
mstore8(0x0b, 0x73)
mstore8(0x20, 0xff)
if iszero(create(amount, 0x0b, 0x16)) {
if iszero(gt(gas(), 1000000)) { revert(0, 0) }
}
}
}
}
function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
internal
returns (bool success)
{
assembly {
success := call(gasStipend, to, amount, 0, 0, 0, 0)
}
}
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 safeTransferAllFrom(address token, address from, address to)
internal
returns (uint256 amount)
{
assembly {
let m := mload(0x40)
mstore(0x40, to)
mstore(0x2c, shl(96, from))
mstore(0x0c, 0x70a08231000000000000000000000000)
if iszero(
and(
gt(returndatasize(), 0x1f),
staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
)
) {
mstore(0x00, 0x7939f424)
revert(0x1c, 0x04)
}
mstore(0x00, 0x23b872dd)
amount := mload(0x60)
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 safeApprove(address token, address to, uint256 amount) internal {
assembly {
mstore(0x14, to)
mstore(0x34, amount)
mstore(0x00, 0x095ea7b3000000000000000000000000)
if iszero(
and(
or(eq(mload(0x00), 1), iszero(returndatasize())),
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x3e3f8f73)
revert(0x1c, 0x04)
}
mstore(0x34, 0)
}
}
function balanceOf(address token, address account) internal view returns (uint256 amount) {
assembly {
mstore(0x14, account)
mstore(0x00, 0x70a08231000000000000000000000000)
amount :=
mul(
mload(0x20),
and(
gt(returndatasize(), 0x1f),
staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
)
)
}
}
}
{
"compilationTarget": {
"src/BloomPool.sol": "BloomPool"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 10000
},
"remappings": [
":ds-test/=lib/forge-safe/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-safe/=lib/forge-safe/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin-contracts/contracts/",
":solady/=lib/solady/src/",
":solidity-stringutils/=lib/forge-safe/lib/surl/lib/solidity-stringutils/",
":solmate/=lib/solmate/src/",
":surl/=lib/forge-safe/lib/surl/"
],
"viaIR": true
}
[{"inputs":[{"internalType":"address","name":"underlyingToken","type":"address"},{"internalType":"address","name":"billToken","type":"address"},{"internalType":"contract IWhitelist","name":"whitelist","type":"address"},{"internalType":"address","name":"swapFacility","type":"address"},{"internalType":"address","name":"treasury","type":"address"},{"internalType":"address","name":"lenderReturnBpsFeed","type":"address"},{"internalType":"address","name":"emergencyHandler","type":"address"},{"internalType":"uint256","name":"leverageBps","type":"uint256"},{"internalType":"uint256","name":"minBorrowDeposit","type":"uint256"},{"internalType":"uint256","name":"commitPhaseDuration","type":"uint256"},{"internalType":"uint256","name":"preHoldSwapTimeout","type":"uint256"},{"internalType":"uint256","name":"poolPhaseDuration","type":"uint256"},{"internalType":"uint256","name":"lenderReturnFee","type":"uint256"},{"internalType":"uint256","name":"borrowerReturnFee","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"CanOnlyWithdrawProcessedCommit","type":"error"},{"inputs":[],"name":"CommitTooSmall","type":"error"},{"inputs":[{"internalType":"address","name":"outToken","type":"address"}],"name":"InvalidOutToken","type":"error"},{"inputs":[{"internalType":"enum State","name":"current","type":"uint8"}],"name":"InvalidState","type":"error"},{"inputs":[],"name":"NoCommitToProcess","type":"error"},{"inputs":[],"name":"NoCommitToWithdraw","type":"error"},{"inputs":[],"name":"NonexistentCommit","type":"error"},{"inputs":[],"name":"NotEmergencyHandler","type":"error"},{"inputs":[],"name":"NotSwapFacility","type":"error"},{"inputs":[],"name":"NotWhitelisted","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cumulativeAmountEnd","type":"uint256"}],"name":"BorrowerCommit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"includedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"excludedAmount","type":"uint256"}],"name":"BorrowerCommitmentProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BorrowerWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum State","name":"prevState","type":"uint8"},{"indexed":false,"internalType":"enum State","name":"newState","type":"uint8"}],"name":"ExplictStateTransition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cumulativeAmountEnd","type":"uint256"}],"name":"LenderCommit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"includedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"excludedAmount","type":"uint256"}],"name":"LenderCommitmentProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"sharesRedeemed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LenderWithdraw","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":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BILL_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BORROWER_RETURN_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COMMIT_PHASE_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMERGENCY_HANDLER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LENDER_RETURN_BPS_FEED","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LENDER_RETURN_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEVERAGE_BPS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BORROW_DEPOSIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_PHASE_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POOL_PHASE_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRE_HOLD_SWAP_TIMEOUT_END","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SWAP_FACILITY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TREASURY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNDERLYING_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WHITELIST","outputs":[{"internalType":"contract IWhitelist","name":"","type":"address"}],"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":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"outToken","type":"address"},{"internalType":"uint256","name":"outAmount","type":"uint256"}],"name":"completeSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"depositBorrower","outputs":[{"internalType":"uint256","name":"newId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"depositLender","outputs":[{"internalType":"uint256","name":"newId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"emergencyWithdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBorrowCommitment","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint128","name":"committedAmount","type":"uint128"},{"internalType":"uint128","name":"cumulativeAmountEnd","type":"uint128"}],"internalType":"struct AssetCommitment","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDistributionInfo","outputs":[{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getLenderCommitment","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint128","name":"committedAmount","type":"uint128"},{"internalType":"uint128","name":"cumulativeAmountEnd","type":"uint128"}],"internalType":"struct AssetCommitment","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalBorrowCommitment","outputs":[{"internalType":"uint256","name":"totalAssetsCommitted","type":"uint256"},{"internalType":"uint256","name":"totalCommitmentCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalLendCommitment","outputs":[{"internalType":"uint256","name":"totalAssetsCommitted","type":"uint256"},{"internalType":"uint256","name":"totalCommitmentCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"initiatePostHoldSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"initiatePreHoldSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"processBorrowerCommit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"processLenderCommit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"state","outputs":[{"internalType":"enum State","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMatchAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"withdrawBorrower","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"withdrawLender","outputs":[],"stateMutability":"nonpayable","type":"function"}]