Latest 25 from a total of 978 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Claim | 3175933 | 626 days ago | IN | 0 ETH | 0.000008 | ||||
| Claim | 2401576 | 644 days ago | IN | 0 ETH | 0.00000997 | ||||
| Claim | 2021453 | 653 days ago | IN | 0 ETH | 0.00003814 | ||||
| Claim | 2021419 | 653 days ago | IN | 0 ETH | 0.00003702 | ||||
| Claim | 1323128 | 669 days ago | IN | 0 ETH | 0.00003765 | ||||
| Claim | 1323105 | 669 days ago | IN | 0 ETH | 0.00003552 | ||||
| Claim | 1323046 | 669 days ago | IN | 0 ETH | 0.00003585 | ||||
| Claim | 1323024 | 669 days ago | IN | 0 ETH | 0.00003578 | ||||
| Claim | 1322926 | 669 days ago | IN | 0 ETH | 0.0000321 | ||||
| Claim | 1322467 | 669 days ago | IN | 0 ETH | 0.00003583 | ||||
| Claim | 1294265 | 670 days ago | IN | 0 ETH | 0.00004984 | ||||
| Claim | 1263584 | 671 days ago | IN | 0 ETH | 0.00002595 | ||||
| Claim | 1213734 | 672 days ago | IN | 0 ETH | 0.00002276 | ||||
| Claim | 1213670 | 672 days ago | IN | 0 ETH | 0.00002192 | ||||
| Claim | 1197373 | 672 days ago | IN | 0 ETH | 0.00003209 | ||||
| Claim | 1197301 | 672 days ago | IN | 0 ETH | 0.00003328 | ||||
| Claim | 968521 | 677 days ago | IN | 0 ETH | 0.00002811 | ||||
| Claim | 958152 | 678 days ago | IN | 0 ETH | 0.00003661 | ||||
| Claim | 657964 | 685 days ago | IN | 0 ETH | 0.0000567 | ||||
| Claim | 657934 | 685 days ago | IN | 0 ETH | 0.00005203 | ||||
| Claim | 657911 | 685 days ago | IN | 0 ETH | 0.00005344 | ||||
| Claim | 553499 | 687 days ago | IN | 0 ETH | 0.00010093 | ||||
| Claim | 467375 | 689 days ago | IN | 0 ETH | 0.00027954 | ||||
| Claim | 453538 | 689 days ago | IN | 0 ETH | 0.00018468 | ||||
| Claim | 452081 | 689 days ago | IN | 0 ETH | 0.00020552 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
PreAsset
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 0 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity =0.8.23;
import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol";
import {MerkleProofLib} from "solady/utils/MerkleProofLib.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";
import {Owned} from "solmate/auth/Owned.sol";
import {IERC20Rebasing, YieldMode} from "../interfaces/IBlast.sol";
import {BAsset} from "./bAsset.sol";
import {BlastClaimer} from "./BlastClaimer.sol";
contract PreAsset is Owned {
ERC20 public immutable reserve;
bytes32 public immutable merkleRoot;
address public immutable baselineFactory;
uint256 public immutable deployTime;
// allow anyone to abort presale after `timeLimit` from `deployTime`
uint256 public constant timeLimit = 2 weeks;
BAsset public bAsset;
bool public active;
uint256 public totalDeposits;
mapping(address => uint256) public whitelist;
mapping(address => uint256) public deposits;
event Deposit(address indexed user, uint256 amount);
event Claim(address indexed user, uint256 amount);
event Withdraw(address indexed user, uint256 amount);
event Seeded(uint256 amount);
event Aborted();
error InvalidCaller();
error InvalidInput();
error InvalidWithdraw();
error MaxDepositExceeded();
error MintInactive();
error MintActive();
error ClaimNotAvailable();
constructor(
ERC20 reserve_,
address baselineFactory_,
address owner_,
bytes32 merkleRoot_
) Owned(owner_) {
// set immutable variables
reserve = reserve_;
baselineFactory = baselineFactory_;
merkleRoot = merkleRoot_;
deployTime = block.timestamp;
// turn on minting
active = true;
BlastClaimer.configure(owner_);
IERC20Rebasing(address(reserve)).configure(YieldMode.CLAIMABLE);
}
// Verify user deposit against merkle tree and deposit
function deposit(
uint256 amount_,
uint256 limit_,
bytes32[] calldata proofs_
) external {
// Verify user
bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(msg.sender, limit_))));
if (!MerkleProofLib.verifyCalldata(proofs_, merkleRoot, leaf)) revert InvalidCaller();
_deposit(amount_, limit_);
}
// Verify user deposit against whitelist and deposit
function whitelistDeposit(uint256 amount_) external {
_deposit(amount_, whitelist[msg.sender]);
}
function _deposit(uint256 amount_, uint256 limit_) internal {
if (amount_ == 0) revert InvalidInput();
// If mint has ended revert
if (!active) revert MintInactive();
// If user has already deposited the max amount, revert
if ((deposits[msg.sender] += amount_) > limit_) revert MaxDepositExceeded();
// Take reserves
totalDeposits += amount_;
reserve.transferFrom(msg.sender, address(this), amount_);
emit Deposit(msg.sender, amount_);
}
// Claim bAssets
function claim() external returns (uint256){
// Cannot claim while mint is active
if (active) revert MintActive();
// Cannot claim if there are no bAssets in the contract or if user has no deposits
uint256 totalBAssets = bAsset.balanceOf(address(this));
uint256 depositAmount = deposits[msg.sender];
if (totalBAssets == 0 || depositAmount == 0) revert ClaimNotAvailable();
// Calculate amount claimable
uint256 percent = depositAmount * 1e18 / totalDeposits;
uint256 claimable = percent * totalBAssets / 1e18;
// Update state
totalDeposits -= depositAmount;
deposits[msg.sender] = 0;
bAsset.transfer(msg.sender, claimable);
emit Claim(msg.sender, claimable);
return claimable;
}
// Allow users to withdraw their bAssets if the presale is cancelled
function withdraw() external returns (uint256) {
if (active) revert MintActive();
// Ensure user has a deposit
uint256 amount = deposits[msg.sender];
if (amount == 0) revert InvalidWithdraw();
// zero out users deposit
deposits[msg.sender] = 0;
totalDeposits -= amount;
// send user back their deposit
reserve.transfer(msg.sender, amount);
emit Withdraw(msg.sender, amount);
return amount;
}
// Transfer reserves to baseline to seed the pool
function seed() external returns (uint256) {
if (!active) revert MintInactive();
// ensure caller is baseline
address baseline = bAsset.baseline();
if (msg.sender != baseline) revert InvalidCaller();
active = false;
uint256 totalReserves = reserve.balanceOf(address(this));
reserve.transfer(baseline, totalReserves);
emit Seeded(totalReserves);
return totalReserves;
}
// Set the precalculated BAsset address, must be called before baseline deployment
function setBAsset(BAsset bAsset_) external {
if (msg.sender != baselineFactory) revert InvalidCaller();
if (address(bAsset) != address(0)) revert InvalidInput();
bAsset = bAsset_;
}
// Manually add users to whitelist to deposit through manual deposit
function modifyWhitelist(
address[] calldata users_,
uint256[] calldata limits_
) external onlyOwner {
if (users_.length != limits_.length) revert InvalidInput();
uint256 totalUsers = users_.length;
for (uint256 i; i < totalUsers; i++) {
whitelist[users_[i]] = limits_[i];
}
}
// Abort the presale and allow users to withdraw their reserves
function abort() external {
if (
msg.sender == owner ||
block.timestamp > deployTime + timeLimit
) {
active = false;
emit Aborted();
} else {
revert InvalidCaller();
}
}
function claimYield() external onlyOwner {
IERC20Rebasing(address(reserve)).claim(
owner,
IERC20Rebasing(address(reserve)).getClaimableAmount(address(this))
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
library FixedPointMathLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The operation failed, as the output exceeds the maximum value of uint256.
error ExpOverflow();
/// @dev The operation failed, as the output exceeds the maximum value of uint256.
error FactorialOverflow();
/// @dev The operation failed, due to an overflow.
error RPowOverflow();
/// @dev The mantissa is too big to fit.
error MantissaOverflow();
/// @dev The operation failed, due to an multiplication overflow.
error MulWadFailed();
/// @dev The operation failed, either due to a
/// multiplication overflow, or a division by a zero.
error DivWadFailed();
/// @dev The multiply-divide operation failed, either due to a
/// multiplication overflow, or a division by a zero.
error MulDivFailed();
/// @dev The division failed, as the denominator is zero.
error DivFailed();
/// @dev The full precision multiply-divide operation failed, either due
/// to the result being larger than 256 bits, or a division by a zero.
error FullMulDivFailed();
/// @dev The output is undefined, as the input is less-than-or-equal to zero.
error LnWadUndefined();
/// @dev The input outside the acceptable domain.
error OutOfDomain();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The scalar of ETH and most ERC20s.
uint256 internal constant WAD = 1e18;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* SIMPLIFIED FIXED POINT OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Equivalent to `(x * y) / WAD` rounded down.
function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.
if mul(y, gt(x, div(not(0), y))) {
mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.
revert(0x1c, 0x04)
}
z := div(mul(x, y), WAD)
}
}
/// @dev Equivalent to `(x * y) / WAD` rounded up.
function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.
if mul(y, gt(x, div(not(0), y))) {
mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.
revert(0x1c, 0x04)
}
z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))
}
}
/// @dev Equivalent to `(x * WAD) / y` rounded down.
function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.
if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {
mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.
revert(0x1c, 0x04)
}
z := div(mul(x, WAD), y)
}
}
/// @dev Equivalent to `(x * WAD) / y` rounded up.
function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.
if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {
mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.
revert(0x1c, 0x04)
}
z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))
}
}
/// @dev Equivalent to `x` to the power of `y`.
/// because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`.
function powWad(int256 x, int256 y) internal pure returns (int256) {
// Using `ln(x)` means `x` must be greater than 0.
return expWad((lnWad(x) * y) / int256(WAD));
}
/// @dev Returns `exp(x)`, denominated in `WAD`.
function expWad(int256 x) internal pure returns (int256 r) {
unchecked {
// When the result is less than 0.5 we return zero.
// This happens when `x <= floor(log(0.5e18) * 1e18) ≈ -42e18`.
if (x <= -42139678854452767551) return r;
/// @solidity memory-safe-assembly
assembly {
// When the result is greater than `(2**255 - 1) / 1e18` we can not represent it as
// an int. This happens when `x >= floor(log((2**255 - 1) / 1e18) * 1e18) ≈ 135`.
if iszero(slt(x, 135305999368893231589)) {
mstore(0x00, 0xa37bfec9) // `ExpOverflow()`.
revert(0x1c, 0x04)
}
}
// `x` is now in the range `(-42, 136) * 1e18`. Convert to `(-42, 136) * 2**96`
// for more intermediate precision and a binary basis. This base conversion
// is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.
x = (x << 78) / 5 ** 18;
// Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers
// of two such that exp(x) = exp(x') * 2**k, where k is an integer.
// Solving this gives k = round(x / log(2)) and x' = x - k * log(2).
int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96;
x = x - k * 54916777467707473351141471128;
// `k` is in the range `[-61, 195]`.
// Evaluate using a (6, 7)-term rational approximation.
// `p` is made monic, we'll multiply by a scale factor later.
int256 y = x + 1346386616545796478920950773328;
y = ((y * x) >> 96) + 57155421227552351082224309758442;
int256 p = y + x - 94201549194550492254356042504812;
p = ((p * y) >> 96) + 28719021644029726153956944680412240;
p = p * x + (4385272521454847904659076985693276 << 96);
// We leave `p` in `2**192` basis so we don't need to scale it back up for the division.
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;
/// @solidity memory-safe-assembly
assembly {
// Div in assembly because solidity adds a zero check despite the unchecked.
// The q polynomial won't have zeros in the domain as all its roots are complex.
// No scaling is necessary because p is already `2**96` too large.
r := sdiv(p, q)
}
// r should be in the range `(0.09, 0.25) * 2**96`.
// We now need to multiply r by:
// - The scale factor `s ≈ 6.031367120`.
// - The `2**k` factor from the range reduction.
// - The `1e18 / 2**96` factor for base conversion.
// We do this all at once, with an intermediate result in `2**213`
// basis, so the final right shift is always by a positive amount.
r = int256(
(uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)
);
}
}
/// @dev Returns `ln(x)`, denominated in `WAD`.
function lnWad(int256 x) internal pure returns (int256 r) {
/// @solidity memory-safe-assembly
assembly {
if iszero(sgt(x, 0)) {
mstore(0x00, 0x1615e638) // `LnWadUndefined()`.
revert(0x1c, 0x04)
}
// We want to convert `x` from `10**18` fixed point to `2**96` fixed point.
// We do this by multiplying by `2**96 / 10**18`. But since
// `ln(x * C) = ln(x) + ln(C)`, we can simply do nothing here
// and add `ln(2**96 / 10**18)` at the end.
// Compute `k = log2(x) - 96`, `t = 159 - k = 255 - log2(x) = 255 ^ log2(x)`.
let t := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
t := or(t, shl(6, lt(0xffffffffffffffff, shr(t, x))))
t := or(t, shl(5, lt(0xffffffff, shr(t, x))))
t := or(t, shl(4, lt(0xffff, shr(t, x))))
t := or(t, shl(3, lt(0xff, shr(t, x))))
// forgefmt: disable-next-item
t := xor(t, byte(and(0x1f, shr(shr(t, x), 0x8421084210842108cc6318c6db6d54be)),
0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff))
// Reduce range of x to (1, 2) * 2**96
// ln(2^k * x) = k * ln(2) + ln(x)
x := shr(159, shl(t, x))
// Evaluate using a (8, 8)-term rational approximation.
// `p` is made monic, we will multiply by a scale factor later.
// forgefmt: disable-next-item
let p := sub( // This heavily nested expression is to avoid stack-too-deep for via-ir.
sar(96, mul(add(43456485725739037958740375743393,
sar(96, mul(add(24828157081833163892658089445524,
sar(96, mul(add(3273285459638523848632254066296,
x), x))), x))), x)), 11111509109440967052023855526967)
p := sub(sar(96, mul(p, x)), 45023709667254063763336534515857)
p := sub(sar(96, mul(p, x)), 14706773417378608786704636184526)
p := sub(mul(p, x), shl(96, 795164235651350426258249787498))
// We leave `p` in `2**192` basis so we don't need to scale it back up for the division.
// `q` is monic by convention.
let q := add(5573035233440673466300451813936, x)
q := add(71694874799317883764090561454958, sar(96, mul(x, q)))
q := add(283447036172924575727196451306956, sar(96, mul(x, q)))
q := add(401686690394027663651624208769553, sar(96, mul(x, q)))
q := add(204048457590392012362485061816622, sar(96, mul(x, q)))
q := add(31853899698501571402653359427138, sar(96, mul(x, q)))
q := add(909429971244387300277376558375, sar(96, mul(x, q)))
// `r` is in the range `(0, 0.125) * 2**96`.
// Finalization, we need to:
// - Multiply by the scale factor `s = 5.549…`.
// - Add `ln(2**96 / 10**18)`.
// - Add `k * ln(2)`.
// - Multiply by `10**18 / 2**96 = 5**18 >> 78`.
// The q polynomial is known not to have zeros in the domain.
// No scaling required because p is already `2**96` too large.
r := sdiv(p, q)
// Multiply by the scaling factor: `s * 5e18 * 2**96`, base is now `5**18 * 2**192`.
r := mul(1677202110996718588342820967067443963516166, r)
// Add `ln(2) * k * 5e18 * 2**192`.
// forgefmt: disable-next-item
r := add(mul(16597577552685614221487285958193947469193820559219878177908093499208371, sub(159, t)), r)
// Add `ln(2**96 / 10**18) * 5e18 * 2**192`.
r := add(600920179829731861736702779321621459595472258049074101567377883020018308, r)
// Base conversion: mul `2**18 / 2**192`.
r := sar(174, r)
}
}
/// @dev Returns `W_0(x)`, denominated in `WAD`.
/// See: https://en.wikipedia.org/wiki/Lambert_W_function
/// a.k.a. Product log function. This is an approximation of the principal branch.
function lambertW0Wad(int256 x) internal pure returns (int256 w) {
if ((w = x) <= -367879441171442322) revert OutOfDomain(); // `x` less than `-1/e`.
uint256 c; // Whether we need to avoid catastrophic cancellation.
uint256 i = 4; // Number of iterations.
if (w <= 0x1ffffffffffff) {
if (-0x4000000000000 <= w) {
i = 1; // Inputs near zero only take one step to converge.
} else if (w <= -0x3ffffffffffffff) {
i = 32; // Inputs near `-1/e` take very long to converge.
}
} else if (w >> 63 == 0) {
/// @solidity memory-safe-assembly
assembly {
// Inline log2 for more performance, since the range is small.
let v := shr(49, w)
let l := shl(3, lt(0xff, v))
// forgefmt: disable-next-item
l := add(or(l, byte(and(0x1f, shr(shr(l, v), 0x8421084210842108cc6318c6db6d54be)),
0x0706060506020504060203020504030106050205030304010505030400000000)), 49)
w := sdiv(shl(l, 7), byte(sub(l, 31), 0x0303030303030303040506080c13))
c := gt(l, 60)
i := add(2, add(gt(l, 53), c))
}
} else {
// `ln(x) - ln(ln(x)) + b * ln(ln(x)) / ln(x)`.
int256 ll = lnWad(w = lnWad(w));
/// @solidity memory-safe-assembly
assembly {
w := add(sdiv(mul(ll, 1023715080943847266), w), sub(w, ll))
i := add(3, iszero(shr(68, x)))
c := iszero(shr(143, x))
}
if (c == 0) {
int256 wad = int256(WAD);
int256 p = x;
// If `x` is big, use Newton's so that intermediate values won't overflow.
do {
int256 e = expWad(w);
/// @solidity memory-safe-assembly
assembly {
let t := mul(w, div(e, wad))
w := sub(w, sdiv(sub(t, x), div(add(e, t), wad)))
i := sub(i, 1)
}
if (p <= w) break;
p = w;
} while (i != 0);
/// @solidity memory-safe-assembly
assembly {
w := sub(w, sgt(w, 2))
}
return w;
}
}
// forgefmt: disable-next-item
unchecked {
int256 wad = int256(WAD);
int256 p = x;
do { // Otherwise, use Halley's for faster convergence.
int256 e = expWad(w);
/// @solidity memory-safe-assembly
assembly {
let t := add(w, wad)
let s := sub(mul(w, e), mul(x, wad))
w := sub(w, sdiv(mul(s, wad), sub(mul(e, t), sdiv(mul(add(t, wad), s), add(t, t)))))
}
if (p <= w) break;
p = w;
} while (--i != c);
/// @solidity memory-safe-assembly
assembly {
w := sub(w, sgt(w, 2))
}
// For certain ranges of `x`, we'll use the quadratic-rate recursive formula of
// R. Iacono and J.P. Boyd for the last iteration, to avoid catastrophic cancellation.
if (c != 0) {
/// @solidity memory-safe-assembly
assembly {
x := sdiv(mul(x, wad), w)
}
x = (w * (wad + lnWad(x)));
/// @solidity memory-safe-assembly
assembly {
w := sdiv(x, add(wad, w))
}
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* GENERAL NUMBER UTILITIES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Calculates `floor(a * b / d)` with full precision.
/// Throws if result overflows a uint256 or when `d` is zero.
/// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv
function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
for {} 1 {} {
// 512-bit multiply `[p1 p0] = x * y`.
// Compute the product mod `2**256` and mod `2**256 - 1`
// then use the Chinese Remainder Theorem to reconstruct
// the 512 bit result. The result is stored in two 256
// variables such that `product = p1 * 2**256 + p0`.
// Least significant 256 bits of the product.
let p0 := mul(x, y)
let mm := mulmod(x, y, not(0))
// Most significant 256 bits of the product.
let p1 := sub(mm, add(p0, lt(mm, p0)))
// Handle non-overflow cases, 256 by 256 division.
if iszero(p1) {
if iszero(d) {
mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
revert(0x1c, 0x04)
}
result := div(p0, d)
break
}
// Make sure the result is less than `2**256`. Also prevents `d == 0`.
if iszero(gt(d, p1)) {
mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
revert(0x1c, 0x04)
}
/*------------------- 512 by 256 division --------------------*/
// Make division exact by subtracting the remainder from `[p1 p0]`.
// Compute remainder using mulmod.
let r := mulmod(x, y, d)
// `t` is the least significant bit of `d`.
// Always greater or equal to 1.
let t := and(d, sub(0, d))
// Divide `d` by `t`, which is a power of two.
d := div(d, t)
// Invert `d mod 2**256`
// Now that `d` is an odd number, it has an inverse
// modulo `2**256` such that `d * inv = 1 mod 2**256`.
// Compute the inverse by starting with a seed that is correct
// correct for four bits. That is, `d * inv = 1 mod 2**4`.
let inv := xor(mul(3, d), 2)
// Now use Newton-Raphson iteration to improve the precision.
// Thanks to Hensel's lifting lemma, this also works in modular
// arithmetic, doubling the correct bits in each step.
inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8
inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16
inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32
inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64
inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128
result :=
mul(
// Divide [p1 p0] by the factors of two.
// Shift in bits from `p1` into `p0`. For this we need
// to flip `t` such that it is `2**256 / t`.
or(mul(sub(p1, gt(r, p0)), add(div(sub(0, t), t), 1)), div(sub(p0, r), t)),
// inverse mod 2**256
mul(inv, sub(2, mul(d, inv)))
)
break
}
}
}
/// @dev Calculates `floor(x * y / d)` with full precision, rounded up.
/// Throws if result overflows a uint256 or when `d` is zero.
/// Credit to Uniswap-v3-core under MIT license:
/// https://github.com/Uniswap/v3-core/blob/contracts/libraries/FullMath.sol
function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {
result = fullMulDiv(x, y, d);
/// @solidity memory-safe-assembly
assembly {
if mulmod(x, y, d) {
result := add(result, 1)
if iszero(result) {
mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Returns `floor(x * y / d)`.
/// Reverts if `x * y` overflows, or `d` is zero.
function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {
mstore(0x00, 0xad251c27) // `MulDivFailed()`.
revert(0x1c, 0x04)
}
z := div(mul(x, y), d)
}
}
/// @dev Returns `ceil(x * y / d)`.
/// Reverts if `x * y` overflows, or `d` is zero.
function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {
mstore(0x00, 0xad251c27) // `MulDivFailed()`.
revert(0x1c, 0x04)
}
z := add(iszero(iszero(mod(mul(x, y), d))), div(mul(x, y), d))
}
}
/// @dev Returns `ceil(x / d)`.
/// Reverts if `d` is zero.
function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
if iszero(d) {
mstore(0x00, 0x65244e4e) // `DivFailed()`.
revert(0x1c, 0x04)
}
z := add(iszero(iszero(mod(x, d))), div(x, d))
}
}
/// @dev Returns `max(0, x - y)`.
function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := mul(gt(x, y), sub(x, y))
}
}
/// @dev Exponentiate `x` to `y` by squaring, denominated in base `b`.
/// Reverts if the computation overflows.
function rpow(uint256 x, uint256 y, uint256 b) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := mul(b, iszero(y)) // `0 ** 0 = 1`. Otherwise, `0 ** n = 0`.
if x {
z := xor(b, mul(xor(b, x), and(y, 1))) // `z = isEven(y) ? scale : x`
let half := shr(1, b) // Divide `b` by 2.
// Divide `y` by 2 every iteration.
for { y := shr(1, y) } y { y := shr(1, y) } {
let xx := mul(x, x) // Store x squared.
let xxRound := add(xx, half) // Round to the nearest number.
// Revert if `xx + half` overflowed, or if `x ** 2` overflows.
if or(lt(xxRound, xx), shr(128, x)) {
mstore(0x00, 0x49f7642b) // `RPowOverflow()`.
revert(0x1c, 0x04)
}
x := div(xxRound, b) // Set `x` to scaled `xxRound`.
// If `y` is odd:
if and(y, 1) {
let zx := mul(z, x) // Compute `z * x`.
let zxRound := add(zx, half) // Round to the nearest number.
// If `z * x` overflowed or `zx + half` overflowed:
if or(xor(div(zx, x), z), lt(zxRound, zx)) {
// Revert if `x` is non-zero.
if iszero(iszero(x)) {
mstore(0x00, 0x49f7642b) // `RPowOverflow()`.
revert(0x1c, 0x04)
}
}
z := div(zxRound, b) // Return properly scaled `zxRound`.
}
}
}
}
}
/// @dev Returns the square root of `x`.
function sqrt(uint256 x) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`.
z := 181 // The "correct" value is 1, but this saves a multiplication later.
// This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
// start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.
// Let `y = x / 2**r`. We check `y >= 2**(k + 8)`
// but shift right by `k` bits to ensure that if `x >= 256`, then `y >= 256`.
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)
// Goal was to get `z*z*y` within a small factor of `x`. More iterations could
// get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`.
// We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small.
// That's not possible if `x < 256` but we can just verify those cases exhaustively.
// Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`.
// Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`.
// Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps.
// For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)`
// is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`,
// with largest error when `s = 1` and when `s = 256` or `1/256`.
// Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`.
// Then we can estimate `sqrt(y)` using
// `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`.
// There is no overflow risk here since `y < 2**136` after the first branch above.
z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181.
// Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
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)))
// If `x+1` is a perfect square, the Babylonian method cycles between
// `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor.
// See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
z := sub(z, lt(div(x, z), z))
}
}
/// @dev Returns the cube root of `x`.
/// Credit to bout3fiddy and pcaversaccio under AGPLv3 license:
/// https://github.com/pcaversaccio/snekmate/blob/main/src/utils/Math.vy
function cbrt(uint256 x) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
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 := div(shl(div(r, 3), shl(lt(0xf, shr(r, x)), 0xf)), xor(7, mod(r, 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 := div(add(add(div(x, mul(z, z)), z), z), 3)
z := sub(z, lt(div(x, mul(z, z)), z))
}
}
/// @dev Returns the square root of `x`, denominated in `WAD`.
function sqrtWad(uint256 x) internal pure returns (uint256 z) {
unchecked {
z = 10 ** 9;
if (x <= type(uint256).max / 10 ** 36 - 1) {
x *= 10 ** 18;
z = 1;
}
z *= sqrt(x);
}
}
/// @dev Returns the cube root of `x`, denominated in `WAD`.
function cbrtWad(uint256 x) internal pure returns (uint256 z) {
unchecked {
z = 10 ** 12;
if (x <= (type(uint256).max / 10 ** 36) * 10 ** 18 - 1) {
if (x >= type(uint256).max / 10 ** 36) {
x *= 10 ** 18;
z = 10 ** 6;
} else {
x *= 10 ** 36;
z = 1;
}
}
z *= cbrt(x);
}
}
/// @dev Returns the factorial of `x`.
function factorial(uint256 x) internal pure returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
if iszero(lt(x, 58)) {
mstore(0x00, 0xaba0f2a2) // `FactorialOverflow()`.
revert(0x1c, 0x04)
}
for { result := 1 } x { x := sub(x, 1) } { result := mul(result, x) }
}
}
/// @dev Returns the log2 of `x`.
/// Equivalent to computing the index of the most significant bit (MSB) of `x`.
/// Returns 0 if `x` is zero.
function log2(uint256 x) internal pure returns (uint256 r) {
/// @solidity memory-safe-assembly
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))))
// forgefmt: disable-next-item
r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
0x0706060506020504060203020504030106050205030304010505030400000000))
}
}
/// @dev Returns the log2 of `x`, rounded up.
/// Returns 0 if `x` is zero.
function log2Up(uint256 x) internal pure returns (uint256 r) {
r = log2(x);
/// @solidity memory-safe-assembly
assembly {
r := add(r, lt(shl(r, 1), x))
}
}
/// @dev Returns the log10 of `x`.
/// Returns 0 if `x` is zero.
function log10(uint256 x) internal pure returns (uint256 r) {
/// @solidity memory-safe-assembly
assembly {
if iszero(lt(x, 100000000000000000000000000000000000000)) {
x := div(x, 100000000000000000000000000000000000000)
r := 38
}
if iszero(lt(x, 100000000000000000000)) {
x := div(x, 100000000000000000000)
r := add(r, 20)
}
if iszero(lt(x, 10000000000)) {
x := div(x, 10000000000)
r := add(r, 10)
}
if iszero(lt(x, 100000)) {
x := div(x, 100000)
r := add(r, 5)
}
r := add(r, add(gt(x, 9), add(gt(x, 99), add(gt(x, 999), gt(x, 9999)))))
}
}
/// @dev Returns the log10 of `x`, rounded up.
/// Returns 0 if `x` is zero.
function log10Up(uint256 x) internal pure returns (uint256 r) {
r = log10(x);
/// @solidity memory-safe-assembly
assembly {
r := add(r, lt(exp(10, r), x))
}
}
/// @dev Returns the log256 of `x`.
/// Returns 0 if `x` is zero.
function log256(uint256 x) internal pure returns (uint256 r) {
/// @solidity memory-safe-assembly
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(shr(3, r), lt(0xff, shr(r, x)))
}
}
/// @dev Returns the log256 of `x`, rounded up.
/// Returns 0 if `x` is zero.
function log256Up(uint256 x) internal pure returns (uint256 r) {
r = log256(x);
/// @solidity memory-safe-assembly
assembly {
r := add(r, lt(shl(shl(3, r), 1), x))
}
}
/// @dev Returns the scientific notation format `mantissa * 10 ** exponent` of `x`.
/// Useful for compressing prices (e.g. using 25 bit mantissa and 7 bit exponent).
function sci(uint256 x) internal pure returns (uint256 mantissa, uint256 exponent) {
/// @solidity memory-safe-assembly
assembly {
mantissa := x
if mantissa {
if iszero(mod(mantissa, 1000000000000000000000000000000000)) {
mantissa := div(mantissa, 1000000000000000000000000000000000)
exponent := 33
}
if iszero(mod(mantissa, 10000000000000000000)) {
mantissa := div(mantissa, 10000000000000000000)
exponent := add(exponent, 19)
}
if iszero(mod(mantissa, 1000000000000)) {
mantissa := div(mantissa, 1000000000000)
exponent := add(exponent, 12)
}
if iszero(mod(mantissa, 1000000)) {
mantissa := div(mantissa, 1000000)
exponent := add(exponent, 6)
}
if iszero(mod(mantissa, 10000)) {
mantissa := div(mantissa, 10000)
exponent := add(exponent, 4)
}
if iszero(mod(mantissa, 100)) {
mantissa := div(mantissa, 100)
exponent := add(exponent, 2)
}
if iszero(mod(mantissa, 10)) {
mantissa := div(mantissa, 10)
exponent := add(exponent, 1)
}
}
}
}
/// @dev Convenience function for packing `x` into a smaller number using `sci`.
/// The `mantissa` will be in bits [7..255] (the upper 249 bits).
/// The `exponent` will be in bits [0..6] (the lower 7 bits).
/// Use `SafeCastLib` to safely ensure that the `packed` number is small
/// enough to fit in the desired unsigned integer type:
/// ```
/// uint32 packed = SafeCastLib.toUint32(FixedPointMathLib.packSci(777 ether));
/// ```
function packSci(uint256 x) internal pure returns (uint256 packed) {
(x, packed) = sci(x); // Reuse for `mantissa` and `exponent`.
/// @solidity memory-safe-assembly
assembly {
if shr(249, x) {
mstore(0x00, 0xce30380c) // `MantissaOverflow()`.
revert(0x1c, 0x04)
}
packed := or(shl(7, x), packed)
}
}
/// @dev Convenience function for unpacking a packed number from `packSci`.
function unpackSci(uint256 packed) internal pure returns (uint256 unpacked) {
unchecked {
unpacked = (packed >> 7) * 10 ** (packed & 0x7f);
}
}
/// @dev Returns the average of `x` and `y`.
function avg(uint256 x, uint256 y) internal pure returns (uint256 z) {
unchecked {
z = (x & y) + ((x ^ y) >> 1);
}
}
/// @dev Returns the average of `x` and `y`.
function avg(int256 x, int256 y) internal pure returns (int256 z) {
unchecked {
z = (x >> 1) + (y >> 1) + (((x & 1) + (y & 1)) >> 1);
}
}
/// @dev Returns the absolute value of `x`.
function abs(int256 x) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := xor(sub(0, shr(255, x)), add(sub(0, shr(255, x)), x))
}
}
/// @dev Returns the absolute distance between `x` and `y`.
function dist(int256 x, int256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := xor(mul(xor(sub(y, x), sub(x, y)), sgt(x, y)), sub(y, x))
}
}
/// @dev Returns the minimum of `x` and `y`.
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := xor(x, mul(xor(x, y), lt(y, x)))
}
}
/// @dev Returns the minimum of `x` and `y`.
function min(int256 x, int256 y) internal pure returns (int256 z) {
/// @solidity memory-safe-assembly
assembly {
z := xor(x, mul(xor(x, y), slt(y, x)))
}
}
/// @dev Returns the maximum of `x` and `y`.
function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := xor(x, mul(xor(x, y), gt(y, x)))
}
}
/// @dev Returns the maximum of `x` and `y`.
function max(int256 x, int256 y) internal pure returns (int256 z) {
/// @solidity memory-safe-assembly
assembly {
z := xor(x, mul(xor(x, y), sgt(y, x)))
}
}
/// @dev Returns `x`, bounded to `minValue` and `maxValue`.
function clamp(uint256 x, uint256 minValue, uint256 maxValue)
internal
pure
returns (uint256 z)
{
/// @solidity memory-safe-assembly
assembly {
z := xor(x, mul(xor(x, minValue), gt(minValue, x)))
z := xor(z, mul(xor(z, maxValue), lt(maxValue, z)))
}
}
/// @dev Returns `x`, bounded to `minValue` and `maxValue`.
function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) {
/// @solidity memory-safe-assembly
assembly {
z := xor(x, mul(xor(x, minValue), sgt(minValue, x)))
z := xor(z, mul(xor(z, maxValue), slt(maxValue, z)))
}
}
/// @dev Returns greatest common divisor of `x` and `y`.
function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
for { z := x } y {} {
let t := y
y := mod(z, y)
z := t
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* RAW NUMBER OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns `x + y`, without checking for overflow.
function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) {
unchecked {
z = x + y;
}
}
/// @dev Returns `x + y`, without checking for overflow.
function rawAdd(int256 x, int256 y) internal pure returns (int256 z) {
unchecked {
z = x + y;
}
}
/// @dev Returns `x - y`, without checking for underflow.
function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
unchecked {
z = x - y;
}
}
/// @dev Returns `x - y`, without checking for underflow.
function rawSub(int256 x, int256 y) internal pure returns (int256 z) {
unchecked {
z = x - y;
}
}
/// @dev Returns `x * y`, without checking for overflow.
function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) {
unchecked {
z = x * y;
}
}
/// @dev Returns `x * y`, without checking for overflow.
function rawMul(int256 x, int256 y) internal pure returns (int256 z) {
unchecked {
z = x * y;
}
}
/// @dev Returns `x / y`, returning 0 if `y` is zero.
function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := div(x, y)
}
}
/// @dev Returns `x / y`, returning 0 if `y` is zero.
function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) {
/// @solidity memory-safe-assembly
assembly {
z := sdiv(x, y)
}
}
/// @dev Returns `x % y`, returning 0 if `y` is zero.
function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := mod(x, y)
}
}
/// @dev Returns `x % y`, returning 0 if `y` is zero.
function rawSMod(int256 x, int256 y) internal pure returns (int256 z) {
/// @solidity memory-safe-assembly
assembly {
z := smod(x, y)
}
}
/// @dev Returns `(x + y) % d`, return 0 if `d` if zero.
function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := addmod(x, y, d)
}
}
/// @dev Returns `(x * y) % d`, return 0 if `d` if zero.
function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := mulmod(x, y, d)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol)
library MerkleProofLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MERKLE PROOF VERIFICATION OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf)
internal
pure
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
if mload(proof) {
// Initialize `offset` to the offset of `proof` elements in memory.
let offset := add(proof, 0x20)
// Left shift by 5 is equivalent to multiplying by 0x20.
let end := add(offset, shl(5, mload(proof)))
// Iterate over proof elements to compute root hash.
for {} 1 {} {
// Slot of `leaf` in scratch space.
// If the condition is true: 0x20, otherwise: 0x00.
let scratch := shl(5, gt(leaf, mload(offset)))
// Store elements to hash contiguously in scratch space.
// Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
mstore(scratch, leaf)
mstore(xor(scratch, 0x20), mload(offset))
// Reuse `leaf` to store the hash to reduce stack operations.
leaf := keccak256(0x00, 0x40)
offset := add(offset, 0x20)
if iszero(lt(offset, end)) { break }
}
}
isValid := eq(leaf, root)
}
}
/// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf)
internal
pure
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
if proof.length {
// Left shift by 5 is equivalent to multiplying by 0x20.
let end := add(proof.offset, shl(5, proof.length))
// Initialize `offset` to the offset of `proof` in the calldata.
let offset := proof.offset
// Iterate over proof elements to compute root hash.
for {} 1 {} {
// Slot of `leaf` in scratch space.
// If the condition is true: 0x20, otherwise: 0x00.
let scratch := shl(5, gt(leaf, calldataload(offset)))
// Store elements to hash contiguously in scratch space.
// Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
mstore(scratch, leaf)
mstore(xor(scratch, 0x20), calldataload(offset))
// Reuse `leaf` to store the hash to reduce stack operations.
leaf := keccak256(0x00, 0x40)
offset := add(offset, 0x20)
if iszero(lt(offset, end)) { break }
}
}
isValid := eq(leaf, root)
}
}
/// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
/// given `proof` and `flags`.
///
/// Note:
/// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
/// will always return false.
/// - The sum of the lengths of `proof` and `leaves` must never overflow.
/// - Any non-zero word in the `flags` array is treated as true.
/// - The memory offset of `proof` must be non-zero
/// (i.e. `proof` is not pointing to the scratch space).
function verifyMultiProof(
bytes32[] memory proof,
bytes32 root,
bytes32[] memory leaves,
bool[] memory flags
) internal pure returns (bool isValid) {
// Rebuilds the root by consuming and producing values on a queue.
// The queue starts with the `leaves` array, and goes into a `hashes` array.
// After the process, the last element on the queue is verified
// to be equal to the `root`.
//
// The `flags` array denotes whether the sibling
// should be popped from the queue (`flag == true`), or
// should be popped from the `proof` (`flag == false`).
/// @solidity memory-safe-assembly
assembly {
// Cache the lengths of the arrays.
let leavesLength := mload(leaves)
let proofLength := mload(proof)
let flagsLength := mload(flags)
// Advance the pointers of the arrays to point to the data.
leaves := add(0x20, leaves)
proof := add(0x20, proof)
flags := add(0x20, flags)
// If the number of flags is correct.
for {} eq(add(leavesLength, proofLength), add(flagsLength, 1)) {} {
// For the case where `proof.length + leaves.length == 1`.
if iszero(flagsLength) {
// `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
isValid := eq(mload(xor(leaves, mul(xor(proof, leaves), proofLength))), root)
break
}
// The required final proof offset if `flagsLength` is not zero, otherwise zero.
let proofEnd := add(proof, shl(5, proofLength))
// We can use the free memory space for the queue.
// We don't need to allocate, since the queue is temporary.
let hashesFront := mload(0x40)
// Copy the leaves into the hashes.
// Sometimes, a little memory expansion costs less than branching.
// Should cost less, even with a high free memory offset of 0x7d00.
leavesLength := shl(5, leavesLength)
for { let i := 0 } iszero(eq(i, leavesLength)) { i := add(i, 0x20) } {
mstore(add(hashesFront, i), mload(add(leaves, i)))
}
// Compute the back of the hashes.
let hashesBack := add(hashesFront, leavesLength)
// This is the end of the memory for the queue.
// We recycle `flagsLength` to save on stack variables (sometimes save gas).
flagsLength := add(hashesBack, shl(5, flagsLength))
for {} 1 {} {
// Pop from `hashes`.
let a := mload(hashesFront)
// Pop from `hashes`.
let b := mload(add(hashesFront, 0x20))
hashesFront := add(hashesFront, 0x40)
// If the flag is false, load the next proof,
// else, pops from the queue.
if iszero(mload(flags)) {
// Loads the next proof.
b := mload(proof)
proof := add(proof, 0x20)
// Unpop from `hashes`.
hashesFront := sub(hashesFront, 0x20)
}
// Advance to the next flag.
flags := add(flags, 0x20)
// Slot of `a` in scratch space.
// If the condition is true: 0x20, otherwise: 0x00.
let scratch := shl(5, gt(a, b))
// Hash the scratch space and push the result onto the queue.
mstore(scratch, a)
mstore(xor(scratch, 0x20), b)
mstore(hashesBack, keccak256(0x00, 0x40))
hashesBack := add(hashesBack, 0x20)
if iszero(lt(hashesBack, flagsLength)) { break }
}
isValid :=
and(
// Checks if the last value in the queue is same as the root.
eq(mload(sub(hashesBack, 0x20)), root),
// And whether all the proofs are used, if required.
eq(proofEnd, proof)
)
break
}
}
}
/// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
/// given `proof` and `flags`.
///
/// Note:
/// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
/// will always return false.
/// - Any non-zero word in the `flags` array is treated as true.
/// - The calldata offset of `proof` must be non-zero
/// (i.e. `proof` is from a regular Solidity function with a 4-byte selector).
function verifyMultiProofCalldata(
bytes32[] calldata proof,
bytes32 root,
bytes32[] calldata leaves,
bool[] calldata flags
) internal pure returns (bool isValid) {
// Rebuilds the root by consuming and producing values on a queue.
// The queue starts with the `leaves` array, and goes into a `hashes` array.
// After the process, the last element on the queue is verified
// to be equal to the `root`.
//
// The `flags` array denotes whether the sibling
// should be popped from the queue (`flag == true`), or
// should be popped from the `proof` (`flag == false`).
/// @solidity memory-safe-assembly
assembly {
// If the number of flags is correct.
for {} eq(add(leaves.length, proof.length), add(flags.length, 1)) {} {
// For the case where `proof.length + leaves.length == 1`.
if iszero(flags.length) {
// `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
// forgefmt: disable-next-item
isValid := eq(
calldataload(
xor(leaves.offset, mul(xor(proof.offset, leaves.offset), proof.length))
),
root
)
break
}
// The required final proof offset if `flagsLength` is not zero, otherwise zero.
let proofEnd := add(proof.offset, shl(5, proof.length))
// We can use the free memory space for the queue.
// We don't need to allocate, since the queue is temporary.
let hashesFront := mload(0x40)
// Copy the leaves into the hashes.
// Sometimes, a little memory expansion costs less than branching.
// Should cost less, even with a high free memory offset of 0x7d00.
calldatacopy(hashesFront, leaves.offset, shl(5, leaves.length))
// Compute the back of the hashes.
let hashesBack := add(hashesFront, shl(5, leaves.length))
// This is the end of the memory for the queue.
// We recycle `flagsLength` to save on stack variables (sometimes save gas).
flags.length := add(hashesBack, shl(5, flags.length))
// We don't need to make a copy of `proof.offset` or `flags.offset`,
// as they are pass-by-value (this trick may not always save gas).
for {} 1 {} {
// Pop from `hashes`.
let a := mload(hashesFront)
// Pop from `hashes`.
let b := mload(add(hashesFront, 0x20))
hashesFront := add(hashesFront, 0x40)
// If the flag is false, load the next proof,
// else, pops from the queue.
if iszero(calldataload(flags.offset)) {
// Loads the next proof.
b := calldataload(proof.offset)
proof.offset := add(proof.offset, 0x20)
// Unpop from `hashes`.
hashesFront := sub(hashesFront, 0x20)
}
// Advance to the next flag offset.
flags.offset := add(flags.offset, 0x20)
// Slot of `a` in scratch space.
// If the condition is true: 0x20, otherwise: 0x00.
let scratch := shl(5, gt(a, b))
// Hash the scratch space and push the result onto the queue.
mstore(scratch, a)
mstore(xor(scratch, 0x20), b)
mstore(hashesBack, keccak256(0x00, 0x40))
hashesBack := add(hashesBack, 0x20)
if iszero(lt(hashesBack, flags.length)) { break }
}
isValid :=
and(
// Checks if the last value in the queue is same as the root.
eq(mload(sub(hashesBack, 0x20)), root),
// And whether all the proofs are used, if required.
eq(proofEnd, proof.offset)
)
break
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EMPTY CALLDATA HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an empty calldata bytes32 array.
function emptyProof() internal pure returns (bytes32[] calldata proof) {
/// @solidity memory-safe-assembly
assembly {
proof.length := 0
}
}
/// @dev Returns an empty calldata bytes32 array.
function emptyLeaves() internal pure returns (bytes32[] calldata leaves) {
/// @solidity memory-safe-assembly
assembly {
leaves.length := 0
}
}
/// @dev Returns an empty calldata bool array.
function emptyFlags() internal pure returns (bool[] calldata flags) {
/// @solidity memory-safe-assembly
assembly {
flags.length := 0
}
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
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;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
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]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
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 because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
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)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event OwnershipTransferred(address indexed user, address indexed newOwner);
/*//////////////////////////////////////////////////////////////
OWNERSHIP STORAGE
//////////////////////////////////////////////////////////////*/
address public owner;
modifier onlyOwner() virtual {
require(msg.sender == owner, "UNAUTHORIZED");
_;
}
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(address _owner) {
owner = _owner;
emit OwnershipTransferred(address(0), _owner);
}
/*//////////////////////////////////////////////////////////////
OWNERSHIP LOGIC
//////////////////////////////////////////////////////////////*/
function transferOwnership(address newOwner) public virtual onlyOwner {
owner = newOwner;
emit OwnershipTransferred(msg.sender, newOwner);
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
enum YieldMode {
AUTOMATIC,
VOID,
CLAIMABLE
}
enum GasMode {
VOID,
CLAIMABLE
}
interface IBlast{
// configure
function configureContract(address contractAddress, YieldMode _yield, GasMode gasMode, address governor) external;
function configure(YieldMode _yield, GasMode gasMode, address governor) external;
// base configuration options
function configureClaimableYield() external;
function configureClaimableYieldOnBehalf(address contractAddress) external;
function configureAutomaticYield() external;
function configureAutomaticYieldOnBehalf(address contractAddress) external;
function configureVoidYield() external;
function configureVoidYieldOnBehalf(address contractAddress) external;
function configureClaimableGas() external;
function configureClaimableGasOnBehalf(address contractAddress) external;
function configureVoidGas() external;
function configureVoidGasOnBehalf(address contractAddress) external;
function configureGovernor(address _governor) external;
function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external;
// claim yield
function claimYield(address contractAddress, address recipientOfYield, uint256 amount) external returns (uint256);
function claimAllYield(address contractAddress, address recipientOfYield) external returns (uint256);
// claim gas
function claimAllGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGasAtMinClaimRate(address contractAddress, address recipientOfGas, uint256 minClaimRateBips) external returns (uint256);
function claimMaxGas(address contractAddress, address recipientOfGas) external returns (uint256);
function claimGas(address contractAddress, address recipientOfGas, uint256 gasToClaim, uint256 gasSecondsToConsume) external returns (uint256);
// read functions
function readClaimableYield(address contractAddress) external view returns (uint256);
function readYieldConfiguration(address contractAddress) external view returns (uint8);
function readGasParams(address contractAddress) external view returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode);
}
interface IERC20Rebasing {
// changes the yield mode of the caller and update the balance
// to reflect the configuration
function configure(YieldMode) external returns (uint256);
// "claimable" yield mode accounts can call this this claim their yield
// to another address
function claim(address recipient, uint256 amount) external returns (uint256);
// read the claimable amount for an account
function getClaimableAmount(address account) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity =0.8.23;
import {ERC20} from "solmate/tokens/ERC20.sol";
import {BlastClaimer} from "./BlastClaimer.sol";
// Baseline token implementation
contract BAsset is ERC20 {
address public immutable baseline;
error InvalidCaller();
constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_, 18) {
// start with 0 initial supply and mint it when we deploy Initial Liquidity in the callback
baseline = msg.sender;
BlastClaimer.configureGovernor(msg.sender);
}
function mint(address to, uint256 amount_) external {
if (msg.sender != baseline) revert InvalidCaller();
_mint(to, amount_);
}
// Burns all token supply greater than totalSupply
function burn(uint256 amount_) external {
if (msg.sender != baseline) revert InvalidCaller();
_burn(baseline, amount_);
}
}//SPDX-License-Identifier: UNLICENSED
pragma solidity =0.8.23;
import {IBlast, YieldMode, GasMode} from "../interfaces/IBlast.sol";
library BlastClaimer {
IBlast constant BLAST = IBlast(0x4300000000000000000000000000000000000002);
function configure(address governor_) internal {
BLAST.configure(
YieldMode.CLAIMABLE,
GasMode.CLAIMABLE,
governor_
);
}
function configureGovernor(address governor_) external {
BLAST.configureGovernor(governor_);
}
function configureContract(address contract_, address governor_) external {
BLAST.configureContract(
contract_,
YieldMode.CLAIMABLE,
GasMode.CLAIMABLE,
governor_
);
}
}{
"remappings": [
"forge-std/=lib/forge-std/src/",
"@uniswap/v3-core/=lib/v3-core/",
"@uniswap/v3-core-0_8/=lib/v3-core-0_8/",
"@uniswap/v3-periphery/=lib/v3-periphery/",
"@uniswap/v3-periphery-0_8/=lib/v3-periphery-0_8/",
"solmate/=lib/solmate/src/",
"solady/=lib/solady/src/",
"murky/=lib/murky/src/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"openzeppelin-contracts/=lib/murky/lib/openzeppelin-contracts/",
"@openzeppelin/=lib/murky/lib/openzeppelin-contracts/",
"v3-core-0_8/=lib/v3-core-0_8/contracts/",
"v3-core/=lib/v3-core/contracts/",
"v3-periphery-0_8/=lib/v3-periphery-0_8/contracts/",
"v3-periphery/=lib/v3-periphery/contracts/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"joe-v2/=lib/joe-v2/",
"openzeppelin/=lib/openzeppelin-contracts/contracts/",
"prb-test/=lib/prb-test/src/",
"v2-core/=lib/v2-core/contracts/",
"vulcan/=lib/vulcan/src/"
],
"optimizer": {
"enabled": true,
"runs": 0
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": true,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract ERC20","name":"reserve_","type":"address"},{"internalType":"address","name":"baselineFactory_","type":"address"},{"internalType":"address","name":"owner_","type":"address"},{"internalType":"bytes32","name":"merkleRoot_","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ClaimNotAvailable","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidWithdraw","type":"error"},{"inputs":[],"name":"MaxDepositExceeded","type":"error"},{"inputs":[],"name":"MintActive","type":"error"},{"inputs":[],"name":"MintInactive","type":"error"},{"anonymous":false,"inputs":[],"name":"Aborted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Seeded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"abort","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"active","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bAsset","outputs":[{"internalType":"contract BAsset","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baselineFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimYield","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"uint256","name":"limit_","type":"uint256"},{"internalType":"bytes32[]","name":"proofs_","type":"bytes32[]"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"users_","type":"address[]"},{"internalType":"uint256[]","name":"limits_","type":"uint256[]"}],"name":"modifyWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"seed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract BAsset","name":"bAsset_","type":"address"}],"name":"setBAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timeLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"whitelistDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101006040818152346200022f57600091608081620011fe803803809162000028828562000234565b833981010312620002275780516001600160a01b0391849083831683036200022b5762000058602082016200026e565b90846060620000698884016200026e565b9201519116918260018060a01b031985541617845586519483857f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a360805260c05260a0524260e0526001805460ff60a01b1916600160a01b17905573430000000000000000000000000000000000000290813b1562000227578383819360649363c8992e6160e01b8452600260048501526001602485015260448401525af180156200021a57620001ed575b50916020819293608051166024855180948193631a33757d60e01b8352600260048401525af18015620001e357620001af575b8251610f7a90816200028482396080518181816101d2015281816104830152818161090a01528181610b360152610e7f015260a05181818161037d0152610c97015260c0518181816102340152610685015260e0518181816106340152610c390152f35b602090813d8311620001db575b620001c8818362000234565b81010312620001d857806200014b565b80fd5b503d620001bc565b83513d84823e3d90fd5b6001600160401b03811162000206578252602062000118565b634e487b7160e01b84526041600452602484fd5b50505051903d90823e3d90fd5b8280fd5b5080fd5b600080fd5b601f909101601f19168101906001600160401b038211908210176200025857604052565b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036200022f5756fe6080604081815260048036101561001557600080fd5b600092833560e01c90816302fb0c5e14610cba575080632eb4a7ab14610c7f57806335a063b414610bd65780633ccfd60b14610ac35780633e10020d14610a0257838163406cf229146108dc575080634e71d92d1461070a57806361325e18146106e25780637a385da7146106575780637a40624b1461061c5780637d882097146105fd5780637d94792a1461040a57806384eb7731146102ed5780638da5cb5b146102c55780639b19251a1461028c578063b8ab24bd14610263578063bf3a9c721461021f578063c08d1fe514610201578063cd3293de146101bd578063f2fde38b1461014c5763fc7e286d1461010c57600080fd5b346101485760203660031901126101485780356001600160a01b03811690819003610144579282916020948252845220549051908152f35b8380fd5b8280fd5b8382346101b95760203660031901126101b957356001600160a01b038181169182900361014857819061018484549182163314610daf565b6001600160a01b031916178255337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b5080fd5b5050346101b957816003193601126101b957517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5050346101b957816003193601126101b95760209051621275008152f35b5050346101b957816003193601126101b957517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5050346101b957816003193601126101b95760015490516001600160a01b039091168152602090f35b503461014857602036600319011261014857356001600160a01b0381169081900361014857828291602094526003845220549051908152f35b5050346101b957816003193601126101b957905490516001600160a01b039091168152602090f35b509190346101b95760603660031901126101b957602435906001600160401b03604435818111610406576103249036908701610cde565b91835190602091602081019061034d8161033f8a3386610d94565b03601f198101835282610d43565b5190208551602080820192835281529091818701908111828210176103f357865251902092806103bf575b5050507f0000000000000000000000000000000000000000000000000000000000000000036103b057506103ad919235610e10565b80f35b516348f5c3ed60e01b81528390fd5b60059060051b830192935b82853591828111841b9081521852818588209401938385106103ca579350505050388080610378565b634e487b7160e01b895260418a52602489fd5b8480fd5b5090346101485782600319360112610148576001549260ff8460a01c16156105ef57815163ab2637af60e01b81526020946001600160a01b0390868387818486165afa92831561059d5784936105b7575b5081831633036105a75760ff60a01b191660015583516370a0823160e01b81523086820152947f00000000000000000000000000000000000000000000000000000000000000009190911691908686602481865afa95861561059d5790879392918597610560575b50918691856104e896959488519788958694859363a9059cbb60e01b85528401610d94565b03925af19081156105555750610528575b507ffe8b095e1a768e83a862933c32f2bd9b62b7b87f8fc8843d83ccce205208b656838251848152a151908152f35b61054790843d861161054e575b61053f8183610d43565b810190610d7c565b50386104f9565b503d610535565b8351903d90823e3d90fd5b8481939495929698503d8311610596575b61057b8183610d43565b8101031261059257519492869291906104e86104c3565b8580fd5b503d610571565b85513d86823e3d90fd5b84516348f5c3ed60e01b81528690fd5b9092508681813d83116105e8575b6105cf8183610d43565b810103126101445751818116810361014457913861045b565b503d6105c5565b5051630d0ca57160e21b8152fd5b5050346101b957816003193601126101b9576020906002549051908152f35b5050346101b957816003193601126101b957602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b509034610148576020366003190112610148576001600160a01b0382358181169391929084900361040657827f00000000000000000000000000000000000000000000000000000000000000001633036106d5576001549283166106c85750506001600160a01b0319161760015580f35b5163b4fa3fb360e01b8152fd5b516348f5c3ed60e01b8152fd5b5034610148576020366003190112610148576103ad9133845260036020528320549035610e10565b5090346101485782600319360112610148576001549260ff8460a01c166108ce5781516370a0823160e01b815230818501526020946001600160a01b03949086908390602490829089165afa9182156108c4578392610895575b5033835280865283832054948215801561088d575b61087e57670de0b6b3a7640000808702938785048214881517156108585760025494851561086b5785900481810291818304149015171561085857916107ca8994926107f997969404988994610d36565b6002553385528184528487812055600154169084875180978195829463a9059cbb60e01b845233908401610d94565b03925af1908115610555575061083b575b5080518281527f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4843392a251908152f35b61085190843d861161054e5761053f8183610d43565b503861080a565b634e487b7160e01b865260118452602486fd5b634e487b7160e01b875260128552602487fd5b508351633c21f90f60e01b8152fd5b508515610779565b9091508581813d83116108bd575b6108ad8183610d43565b8101031261014857519038610764565b503d6108a3565b84513d85823e3d90fd5b5051634a324f2160e11b8152fd5b828185346101b957816003193601126101b95781546001600160a01b0390811690610908338314610daf565b7f00000000000000000000000000000000000000000000000000000000000000001682519163e12f3a6160e01b835230868401526020958684602481865afa9384156109f85790879493929187946109c3575b509561097b96865197889586948593635569f64b60e11b85528401610d94565b03925af19081156109ba575061098f578280f35b813d83116109b3575b6109a28183610d43565b810103126109b05781808280f35b80fd5b503d610998565b513d85823e3d90fd5b8581969295503d83116109f1575b6109db8183610d43565b810103126105925792518693909261097b61095b565b503d6109d1565b85513d88823e3d90fd5b5090346101485780600319360112610148576001600160401b0390823582811161040657610a339036908501610cde565b93909260243590811161059257610a4d9036908301610cde565b9060018060a01b0392610a64848954163314610daf565b828703610ab55750865b868110610a79578780f35b610a84818484610dea565b3590610a91818989610dea565b3591858316809303610ab1576001928a526003602052868a205501610a6e565b8980fd5b845163b4fa3fb360e01b8152fd5b50903461014857826003193601126101485760ff60015460a01c16610bc95733835260209282845281812054928315610bbb57908484610b31933384528083528386812055610b1482600254610d36565b600255855163a9059cbb60e01b8152948592839233908401610d94565b0381847f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af19081156105555750610b9e575b5080518281527f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364843392a251908152f35b610bb490843d861161054e5761053f8183610d43565b5038610b6d565b82516335411d8b60e01b8152fd5b51634a324f2160e11b8152fd5b50903461014857826003193601126101485782546001600160a01b031633148015610c36575b156106d5576001805460ff60a01b19169055827f72c874aeff0b183a56e2b79c71b46e1aed4dee5e09862134b8821ba2fddbf8bf8180a180f35b507f0000000000000000000000000000000000000000000000000000000000000000621275008101809111610c6c574211610bfc565b634e487b7160e01b845260118352602484fd5b5050346101b957816003193601126101b957602090517f00000000000000000000000000000000000000000000000000000000000000008152f35b8490346101b957816003193601126101b95760209060ff60015460a01c1615158152f35b9181601f84011215610d0e578235916001600160401b038311610d0e576020808501948460051b010111610d0e57565b600080fd5b91908201809211610d2057565b634e487b7160e01b600052601160045260246000fd5b91908203918211610d2057565b601f909101601f19168101906001600160401b03821190821017610d6657604052565b634e487b7160e01b600052604160045260246000fd5b90816020910312610d0e57518015158103610d0e5790565b6001600160a01b039091168152602081019190915260400190565b15610db657565b60405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606490fd5b9190811015610dfa5760051b0190565b634e487b7160e01b600052603260045260246000fd5b908115610f325760ff60015460a01c1615610f20573360005260046020526040600020610e3e838254610d13565b80915511610f0e57610e5281600254610d13565b6002556040516323b872dd60e01b81523360048201523060248201526044810182905260208160648160007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165af18015610f0257610ee3575b506040519081527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c60203392a2565b610efb9060203d60201161054e5761053f8183610d43565b5038610eb4565b6040513d6000823e3d90fd5b604051636f7b6d7960e11b8152600490fd5b604051630d0ca57160e21b8152600490fd5b60405163b4fa3fb360e01b8152600490fdfea26469706673582212202237e1fb214e9649199babb884f15e6b77b28b5e9d91b4f2477e763271d1a18c64736f6c6343000817003300000000000000000000000043000000000000000000000000000000000000040000000000000000000000000c056b34f2afa70ee1351e3659dfbd20977652750000000000000000000000008044f710c58b6ea6a178cc540f9f1cd758f7d1b2135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd
Deployed Bytecode
0x6080604081815260048036101561001557600080fd5b600092833560e01c90816302fb0c5e14610cba575080632eb4a7ab14610c7f57806335a063b414610bd65780633ccfd60b14610ac35780633e10020d14610a0257838163406cf229146108dc575080634e71d92d1461070a57806361325e18146106e25780637a385da7146106575780637a40624b1461061c5780637d882097146105fd5780637d94792a1461040a57806384eb7731146102ed5780638da5cb5b146102c55780639b19251a1461028c578063b8ab24bd14610263578063bf3a9c721461021f578063c08d1fe514610201578063cd3293de146101bd578063f2fde38b1461014c5763fc7e286d1461010c57600080fd5b346101485760203660031901126101485780356001600160a01b03811690819003610144579282916020948252845220549051908152f35b8380fd5b8280fd5b8382346101b95760203660031901126101b957356001600160a01b038181169182900361014857819061018484549182163314610daf565b6001600160a01b031916178255337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b5080fd5b5050346101b957816003193601126101b957517f00000000000000000000000043000000000000000000000000000000000000046001600160a01b03168152602090f35b5050346101b957816003193601126101b95760209051621275008152f35b5050346101b957816003193601126101b957517f0000000000000000000000000c056b34f2afa70ee1351e3659dfbd20977652756001600160a01b03168152602090f35b5050346101b957816003193601126101b95760015490516001600160a01b039091168152602090f35b503461014857602036600319011261014857356001600160a01b0381169081900361014857828291602094526003845220549051908152f35b5050346101b957816003193601126101b957905490516001600160a01b039091168152602090f35b509190346101b95760603660031901126101b957602435906001600160401b03604435818111610406576103249036908701610cde565b91835190602091602081019061034d8161033f8a3386610d94565b03601f198101835282610d43565b5190208551602080820192835281529091818701908111828210176103f357865251902092806103bf575b5050507f135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd036103b057506103ad919235610e10565b80f35b516348f5c3ed60e01b81528390fd5b60059060051b830192935b82853591828111841b9081521852818588209401938385106103ca579350505050388080610378565b634e487b7160e01b895260418a52602489fd5b8480fd5b5090346101485782600319360112610148576001549260ff8460a01c16156105ef57815163ab2637af60e01b81526020946001600160a01b0390868387818486165afa92831561059d5784936105b7575b5081831633036105a75760ff60a01b191660015583516370a0823160e01b81523086820152947f00000000000000000000000043000000000000000000000000000000000000049190911691908686602481865afa95861561059d5790879392918597610560575b50918691856104e896959488519788958694859363a9059cbb60e01b85528401610d94565b03925af19081156105555750610528575b507ffe8b095e1a768e83a862933c32f2bd9b62b7b87f8fc8843d83ccce205208b656838251848152a151908152f35b61054790843d861161054e575b61053f8183610d43565b810190610d7c565b50386104f9565b503d610535565b8351903d90823e3d90fd5b8481939495929698503d8311610596575b61057b8183610d43565b8101031261059257519492869291906104e86104c3565b8580fd5b503d610571565b85513d86823e3d90fd5b84516348f5c3ed60e01b81528690fd5b9092508681813d83116105e8575b6105cf8183610d43565b810103126101445751818116810361014457913861045b565b503d6105c5565b5051630d0ca57160e21b8152fd5b5050346101b957816003193601126101b9576020906002549051908152f35b5050346101b957816003193601126101b957602090517f0000000000000000000000000000000000000000000000000000000065e0cd198152f35b509034610148576020366003190112610148576001600160a01b0382358181169391929084900361040657827f0000000000000000000000000c056b34f2afa70ee1351e3659dfbd20977652751633036106d5576001549283166106c85750506001600160a01b0319161760015580f35b5163b4fa3fb360e01b8152fd5b516348f5c3ed60e01b8152fd5b5034610148576020366003190112610148576103ad9133845260036020528320549035610e10565b5090346101485782600319360112610148576001549260ff8460a01c166108ce5781516370a0823160e01b815230818501526020946001600160a01b03949086908390602490829089165afa9182156108c4578392610895575b5033835280865283832054948215801561088d575b61087e57670de0b6b3a7640000808702938785048214881517156108585760025494851561086b5785900481810291818304149015171561085857916107ca8994926107f997969404988994610d36565b6002553385528184528487812055600154169084875180978195829463a9059cbb60e01b845233908401610d94565b03925af1908115610555575061083b575b5080518281527f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4843392a251908152f35b61085190843d861161054e5761053f8183610d43565b503861080a565b634e487b7160e01b865260118452602486fd5b634e487b7160e01b875260128552602487fd5b508351633c21f90f60e01b8152fd5b508515610779565b9091508581813d83116108bd575b6108ad8183610d43565b8101031261014857519038610764565b503d6108a3565b84513d85823e3d90fd5b5051634a324f2160e11b8152fd5b828185346101b957816003193601126101b95781546001600160a01b0390811690610908338314610daf565b7f00000000000000000000000043000000000000000000000000000000000000041682519163e12f3a6160e01b835230868401526020958684602481865afa9384156109f85790879493929187946109c3575b509561097b96865197889586948593635569f64b60e11b85528401610d94565b03925af19081156109ba575061098f578280f35b813d83116109b3575b6109a28183610d43565b810103126109b05781808280f35b80fd5b503d610998565b513d85823e3d90fd5b8581969295503d83116109f1575b6109db8183610d43565b810103126105925792518693909261097b61095b565b503d6109d1565b85513d88823e3d90fd5b5090346101485780600319360112610148576001600160401b0390823582811161040657610a339036908501610cde565b93909260243590811161059257610a4d9036908301610cde565b9060018060a01b0392610a64848954163314610daf565b828703610ab55750865b868110610a79578780f35b610a84818484610dea565b3590610a91818989610dea565b3591858316809303610ab1576001928a526003602052868a205501610a6e565b8980fd5b845163b4fa3fb360e01b8152fd5b50903461014857826003193601126101485760ff60015460a01c16610bc95733835260209282845281812054928315610bbb57908484610b31933384528083528386812055610b1482600254610d36565b600255855163a9059cbb60e01b8152948592839233908401610d94565b0381847f00000000000000000000000043000000000000000000000000000000000000046001600160a01b03165af19081156105555750610b9e575b5080518281527f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a9424364843392a251908152f35b610bb490843d861161054e5761053f8183610d43565b5038610b6d565b82516335411d8b60e01b8152fd5b51634a324f2160e11b8152fd5b50903461014857826003193601126101485782546001600160a01b031633148015610c36575b156106d5576001805460ff60a01b19169055827f72c874aeff0b183a56e2b79c71b46e1aed4dee5e09862134b8821ba2fddbf8bf8180a180f35b507f0000000000000000000000000000000000000000000000000000000065e0cd19621275008101809111610c6c574211610bfc565b634e487b7160e01b845260118352602484fd5b5050346101b957816003193601126101b957602090517f135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd8152f35b8490346101b957816003193601126101b95760209060ff60015460a01c1615158152f35b9181601f84011215610d0e578235916001600160401b038311610d0e576020808501948460051b010111610d0e57565b600080fd5b91908201809211610d2057565b634e487b7160e01b600052601160045260246000fd5b91908203918211610d2057565b601f909101601f19168101906001600160401b03821190821017610d6657604052565b634e487b7160e01b600052604160045260246000fd5b90816020910312610d0e57518015158103610d0e5790565b6001600160a01b039091168152602081019190915260400190565b15610db657565b60405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606490fd5b9190811015610dfa5760051b0190565b634e487b7160e01b600052603260045260246000fd5b908115610f325760ff60015460a01c1615610f20573360005260046020526040600020610e3e838254610d13565b80915511610f0e57610e5281600254610d13565b6002556040516323b872dd60e01b81523360048201523060248201526044810182905260208160648160007f00000000000000000000000043000000000000000000000000000000000000046001600160a01b03165af18015610f0257610ee3575b506040519081527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c60203392a2565b610efb9060203d60201161054e5761053f8183610d43565b5038610eb4565b6040513d6000823e3d90fd5b604051636f7b6d7960e11b8152600490fd5b604051630d0ca57160e21b8152600490fd5b60405163b4fa3fb360e01b8152600490fdfea26469706673582212202237e1fb214e9649199babb884f15e6b77b28b5e9d91b4f2477e763271d1a18c64736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000043000000000000000000000000000000000000040000000000000000000000000c056b34f2afa70ee1351e3659dfbd20977652750000000000000000000000008044f710c58b6ea6a178cc540f9f1cd758f7d1b2135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd
-----Decoded View---------------
Arg [0] : reserve_ (address): 0x4300000000000000000000000000000000000004
Arg [1] : baselineFactory_ (address): 0x0C056B34F2AFa70Ee1351e3659DFBD2097765275
Arg [2] : owner_ (address): 0x8044f710c58B6eA6a178CC540f9F1Cd758F7d1B2
Arg [3] : merkleRoot_ (bytes32): 0x135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000004300000000000000000000000000000000000004
Arg [1] : 0000000000000000000000000c056b34f2afa70ee1351e3659dfbd2097765275
Arg [2] : 0000000000000000000000008044f710c58b6ea6a178cc540f9f1cd758f7d1b2
Arg [3] : 135c608a07e6154918e33166e99da599bdc4a61d43f18acab4527ad6c9cbfcbd
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.