Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Latest 25 from a total of 2,042 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Buy | 21795930 | 385 days ago | IN | 0 ETH | 0.00021649 | ||||
| Buy | 21629739 | 408 days ago | IN | 0 ETH | 0.00051597 | ||||
| Buy | 21621720 | 409 days ago | IN | 0 ETH | 0.00059747 | ||||
| Buy | 21615797 | 410 days ago | IN | 0 ETH | 0.00157137 | ||||
| Buy | 21615529 | 410 days ago | IN | 0 ETH | 0.00390228 | ||||
| Buy | 21586052 | 414 days ago | IN | 0 ETH | 0.00070993 | ||||
| Buy | 21580387 | 415 days ago | IN | 0 ETH | 0.0012924 | ||||
| Buy | 21575980 | 415 days ago | IN | 0 ETH | 0.00070194 | ||||
| Buy | 21575698 | 415 days ago | IN | 0 ETH | 0.00119382 | ||||
| Buy | 21575691 | 415 days ago | IN | 0 ETH | 0.00129872 | ||||
| Buy | 21575169 | 415 days ago | IN | 0 ETH | 0.00211223 | ||||
| Buy | 21575088 | 415 days ago | IN | 0 ETH | 0.0015684 | ||||
| Buy | 21575056 | 415 days ago | IN | 0 ETH | 0.00175249 | ||||
| Buy | 21572332 | 416 days ago | IN | 0 ETH | 0.00078536 | ||||
| Buy | 21570881 | 416 days ago | IN | 0 ETH | 0.00056213 | ||||
| Buy | 21570873 | 416 days ago | IN | 0 ETH | 0.00054671 | ||||
| Buy | 21559524 | 418 days ago | IN | 0 ETH | 0.00181913 | ||||
| Buy | 21553282 | 418 days ago | IN | 0 ETH | 0.00084617 | ||||
| Buy | 21552075 | 419 days ago | IN | 0 ETH | 0.00245252 | ||||
| Buy | 21550681 | 419 days ago | IN | 0 ETH | 0.00059484 | ||||
| Buy | 21548268 | 419 days ago | IN | 0 ETH | 0.00065727 | ||||
| Buy | 21541982 | 420 days ago | IN | 0 ETH | 0.00054509 | ||||
| Buy | 21541971 | 420 days ago | IN | 0 ETH | 0.00059767 | ||||
| Buy | 21538674 | 420 days ago | IN | 0 ETH | 0.00188447 | ||||
| Buy | 21538150 | 420 days ago | IN | 0 ETH | 0.0015882 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
EarlyLiquidity
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IEarlyLiquidity} from "@/interfaces/IEarlyLiquidity.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {ABDKMath64x64} from "@/libraries/ABDKMath64x64.sol";
import {IMinerPool} from "@/interfaces/IMinerPool.sol";
interface IDecimals {
error IncorrectDecimals();
function decimals() external view returns (uint8);
}
/**
* @title EarlyLiquidity
* @author @DavidVorick
* @author twitter: @0xSimon github: @0xSimbo
* @notice This contract allows users to buy Glow tokens with USDC
* @dev the cost of glow rises exponentially with the amount of glow sold
* - The price at increment x = 0.003 * 2^((x)/ 100_000_000)
* - if the function above to get price of increment x if f(x)
* - Then, the price to buy y tokens is Σ f(x) from x = the total increments sold, to x = the total increments sold + y
* - For example, to buy the first ten increments, (aka the first .1 tokens), the price is
* - f(0) + f(1) .... + f(9)
* - To buy the next ten increments, or token .1 -> .2, the price is
* - f(10) + f(11) ... + f(19)
* @dev to calculate the price for y tokens in real time, we use the sum of a geometric series which allows us
* - to efficiently calculate the price of y tokens in real time rather than looping through all the increments
*/
contract EarlyLiquidity is IEarlyLiquidity {
using ABDKMath64x64 for int128;
/* -------------------------------------------------------------------------- */
/* constants */
/* -------------------------------------------------------------------------- */
/// @dev Represents 1.0000000069314718 in 64x64 format, or `r` in the geometric series
int128 private constant _RATIO = 18446744201572638720;
/// @dev Represents 0.003 USDC in 64x64 format
int128 private constant _POINT_ZERO_ZERO_THREE = 55340232221128654848000;
/// @dev Represents 1 in 64x64 format
int128 private constant _ONE = 18446744073709551616;
/// @dev Represents ln(r) in 64x64 format
int128 private constant _LN_RATIO = 127863086660;
/// @dev Represents 1e8 in 64x64 format
int128 private constant _ONE_HUNDRED_MILLION = 100_000_000 << 64;
/// @dev Represents ln(2) in 64x64 format
int128 private constant _LN_2 = 12786308645202655659;
/// @dev represents (1-r) in 64x64 format
/// @dev r = 1 - 1.0000000069314718 = 0000000069314718
int128 private constant _DENOMINATOR = -127863086349;
/// @dev The number of decimals for USDC
uint256 public constant USDC_DECIMALS = 6;
/**
* @notice the total amount of .01 increments to sell
* - equals to 12,000,000 GLW total
* @dev The total number of glow tokens to sell
* @dev 12 million GLOW tokens
* @dev .01 * 1_200_000_000 = 12_000_000
*/
uint256 public constant TOTAL_INCREMENTS_TO_SELL = 1_200_000_000;
/**
* @notice the minimum increment that tokens can be bought in .01 GLW
* @dev The minimum increment that tokens can be bought in
* @dev this is essential so our floating point math doesn't break
*/
uint256 public constant MIN_TOKEN_INCREMENT = 1e16;
/* -------------------------------------------------------------------------- */
/* immutables */
/* -------------------------------------------------------------------------- */
/**
* @notice USDC token
* @dev The USDC token
*/
IERC20 public immutable USDC_TOKEN;
/**
* @notice The address of the holding contract
* @dev the holding contract holds all USDC tokens
*/
address public immutable HOLDING_CONTRACT;
/* -------------------------------------------------------------------------- */
/* state vars */
/* -------------------------------------------------------------------------- */
/// @dev tokens are demagnified by 1e18 to make floating point math easier
/// @dev the {totalSold} function returns the total sold in 1e18 (GLW DECIMALS)
uint256 private _totalIncrementsSold;
/// @notice The Glow token
IERC20 public immutable GLOW_TOKEN;
/// @notice The miner pool contract
/// @dev all USDC is donated to the miner pool
IMinerPool public immutable MINER_POOL;
/* -------------------------------------------------------------------------- */
/* constructor */
/* -------------------------------------------------------------------------- */
/**
* @notice Constructs the EarlyLiquidity contract
* @param _usdcAddress The address of the USDC token
* @param _holdingContract The address of the holding contract
* @param _glowToken The address of the glow token
* @param _minerPoolAddress The address of the miner pool
*/
constructor(address _usdcAddress, address _holdingContract, address _glowToken, address _minerPoolAddress)
payable
{
USDC_TOKEN = IERC20(_usdcAddress);
uint256 decimals = uint256(IDecimals(_usdcAddress).decimals());
if (decimals != USDC_DECIMALS) {
_revert(IDecimals.IncorrectDecimals.selector);
}
HOLDING_CONTRACT = _holdingContract;
GLOW_TOKEN = IERC20(_glowToken);
MINER_POOL = IMinerPool(_minerPoolAddress);
}
/* -------------------------------------------------------------------------- */
/* buy glow */
/* -------------------------------------------------------------------------- */
/**
* @inheritdoc IEarlyLiquidity
*/
function buy(uint256 increments, uint256 maxCost) external {
// Cache the minerPool in memory for gas optimization.
IMinerPool pool = MINER_POOL;
address _holdingContract = HOLDING_CONTRACT;
// Calculate the total cost of the desired amount of tokens.
uint256 totalCost = getPrice(increments);
// If the computed total cost is greater than the user's specified max cost, revert the transaction.
if (totalCost > maxCost) {
_revert(IEarlyLiquidity.PriceTooHigh.selector);
}
// Calculate the exact amount of tokens to send to the user. Convert the normalized increments back to its original scale.
// Impossible to overflow since this is equal to {increments} in the function inputs
// 1 increment = .01 (or 1e16) glw
uint256 glowToSend = increments * 1e16;
// Check the balance of USDC in the miner pool before making a transfer.
uint256 balBefore = USDC_TOKEN.balanceOf(_holdingContract);
// Transfer USDC from the user to the miner pool to pay for the tokens.
SafeERC20.safeTransferFrom(USDC_TOKEN, msg.sender, _holdingContract, totalCost);
// Check the balance of USDC in the miner pool after the transfer to find the actual transferred amount.
uint256 balAfter = USDC_TOKEN.balanceOf(_holdingContract);
//Underflow should be impossible, unless the USDC contract is hacked and malicious
//in which case, this transaction will revert
//For almost all cases possible, this should not underflow/revert
uint256 diff = balAfter - balBefore;
// Transfer the desired amount of tokens to the user.
SafeERC20.safeTransfer(GLOW_TOKEN, msg.sender, glowToSend);
// Donate the received USDC to the miner rewards pool, possibly accounting for a tax or fee.
pool.donateToUSDCMinerRewardsPoolEarlyLiquidity(diff);
// Update the total amount of tokens sold by adding the normalized amount to the total.
_totalIncrementsSold += increments;
// Emit an event to log the purchase details.
emit IEarlyLiquidity.Purchase(msg.sender, glowToSend, totalCost);
// End of function; the explicit 'return' here is unnecessary but it indicates the function's conclusion.
return;
}
/* -------------------------------------------------------------------------- */
/* view functions */
/* -------------------------------------------------------------------------- */
/**
* @inheritdoc IEarlyLiquidity
*/
function getPrice(uint256 incrementsToPurchase) public view returns (uint256) {
if (incrementsToPurchase == 0) return 0;
return _getPrice(_totalIncrementsSold, incrementsToPurchase);
}
/**
* @inheritdoc IEarlyLiquidity
*/
function totalSold() public view returns (uint256) {
return _totalIncrementsSold * MIN_TOKEN_INCREMENT;
}
/**
* @inheritdoc IEarlyLiquidity
*/
function getCurrentPrice() external view returns (uint256) {
return _getPrice(_totalIncrementsSold, 1);
}
/* -------------------------------------------------------------------------- */
/* internal view */
/* -------------------------------------------------------------------------- */
/**
* @notice Calculates the price of a given amount of tokens
* @param totalIncrementsSold The total amount of .01 increments sold
* @param incrementsToBuy The amount of .01 increments to buy
* @return price price of the increments to purchase in USDC
* @dev since our increments are in .01, the function evaluates to Σ .003 * 2^((incrementId)/ 100_000_000)
* - for increment id = totalIncrementsSold id: to incrementId = incrementsToBuy
* - rounding errors do occur due to floating point math, but divergence is sub 1e-7
*/
function _getPrice(uint256 totalIncrementsSold, uint256 incrementsToBuy) private pure returns (uint256) {
// Check if the combined total of tokens sold and tokens to buy exceed the allowed amount.
// If it does, revert the transaction.
if (totalIncrementsSold + incrementsToBuy > TOTAL_INCREMENTS_TO_SELL) {
_revert(IEarlyLiquidity.AllSold.selector);
}
// Convert the number of increments to buy into a fixed-point representation.
int128 n = ABDKMath64x64.fromUInt(incrementsToBuy);
// Compute r^n, where 'r' is the common ratio of the geometric series.
// Using logarithmic properties, we compute the exponent as: n * ln(r).
// This step computes the value of r raised to the power of n.
int128 rToTheN = ABDKMath64x64.exp(ABDKMath64x64.mul(n, _LN_RATIO));
// Calculate the numerator for the sum formula of an infinite geometric series:
// numerator = 1 - r^n
int128 numerator = _ONE.sub(rToTheN);
// Divide the numerator by the denominator, where the denominator is typically
// (1 - r) for the sum of an infinite geometric series. Here, the denominator
// the fixed-point representation of (1 - r).
int128 divisionResult = numerator.div(_DENOMINATOR);
// Calculate the first term in the geometric series. The first term is based on
// the total amount of increments already sold.
int128 firstTermInSeries = _getFirstTermInSeries(totalIncrementsSold);
//divisionResult > than geometricSeries, so we convert divisionResult to uint256
uint256 firstTimeInSerieWithFixed = uint256(int256(firstTermInSeries));
//divisionResult is always positive so we can cast it to uint256
uint256 divUint = uint256(int256(divisionResult));
//We do the fixed point math in uint256 domain since we know that the result will be positive
//Below is a fixed point multiplication
uint256 mulResFixed = firstTimeInSerieWithFixed * divUint >> 64;
//convert {mulResFixed} back to uint256
return mulResFixed >> 64;
// The following comments are for the purpose of explaining why the code cannot overflow.
//The maximum value of totalIncrementsSold is 1,200,000,000
//The maximum value of incrementsToBuy is 1,200,000,000
//The max value of n is 1,200,000
// _LN_RATIO = ln(1.0000000069314718)
//The maximum value of rToTheN is e^(1,200,000,000 * ln(r)) = e^8.317766180304424 = 4096.000055644491
//The maximum value of numerator is 1 - 4096 = -4095
//The maximum value of divisionResult is -4095 / -0.0000000069314718 = 590,783,619,721.2834
//The maximum value of firstTermInSeries is 3000 * 2^12 = 12288000
//The maximum value of geometricSeries is 12288000 * 590,783,619,721.2834 = 7.259549119135131e+18
//This cant overflow since it's < 2^63-1
}
/**
* @notice Calculates the first term in the geometric series for the current price of the current token
* @param totalIncrementsSold - the total number of increments that have already been sold
* @return firstTerm - first term to be used in the geometric series
*/
function _getFirstTermInSeries(uint256 totalIncrementsSold) private pure returns (int128) {
// Convert 'totalSold' to a fixed-point representation using ABDKMath64x64.
// This is done to perform mathematical operations with precision.
int128 floatingPointTotalSold = ABDKMath64x64.fromUInt(totalIncrementsSold);
// The goal is to compute the exponent for: 2^(totalIncrements / 100,000,000)
// Using logarithmic properties, this can be re-written using the identity:
// b^c = a^(ln(b)*c) => 2^(totalIncrements / 100,000,000) = e^(ln(2) * totalIncrements / 100,000,000)
// Here, '_LN_2' is the natural logarithm of 2, and '_ONE_HUNDRED_MILLION' represents 100,000,000.
int128 exponent = _LN_2.mul(floatingPointTotalSold).div(_ONE_HUNDRED_MILLION);
// Compute e^(exponent), which effectively calculates 2^(totalIncrements / 100,000,000)
// because of the earlier logarithmic transformation.
int128 baseResult = ABDKMath64x64.exp(exponent);
// Multiply the result by 0.003, where '_POINT_ZERO_ZERO_THREE' is the fixed-point representation of 0.003.
int128 result = _POINT_ZERO_ZERO_THREE.mul(baseResult);
// The following comments are for the purpose of explaining why the code cannot overflow.
//ln(2) = 0.693147......
//floatingPointTotalSold will never be more than 1,200,000,000
//so the maximum value of the exponent will be .693147 * 1,200,000,000 / 100,000,000 = 8.316
//None of those numbers are greater than 2^63-1 (the maximum value of a 64x6x int)
//Max value of baseResult possible is e^8.316 = 4,089 (rounded up)
//The max input that baseResult can take in is 43 since (e^44 > type(64x64).max > e^43)
//We will never cause an overflow in the exponent calculation
//Max value of result is 1,000 * 4,088 = 4088000
//This is well within the range of 2^63-1 = 9,223,372,036,854,775,807 approx 9.223372e+18
// Return the final result.
return result;
}
/* -------------------------------------------------------------------------- */
/* private utils */
/* -------------------------------------------------------------------------- */
/**
* @notice More efficiently reverts with a bytes4 selector
* @param selector The selector to revert with
*/
function _revert(bytes4 selector) private pure {
// solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
mstore(0x0, selector)
revert(0x0, 0x04)
}
}
/**
* @dev for more efficient zero address checks
*/
function _isZeroAddress(address a) private pure returns (bool isZero) {
// solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
isZero := iszero(a)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
if (nonceAfter != nonceBefore + 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IEarlyLiquidity {
/* -------------------------------------------------------------------------- */
/* errors */
/* -------------------------------------------------------------------------- */
error PriceTooHigh();
error ModNotZero();
error AllSold();
error MinerPoolAlreadySet();
error ZeroAddress();
error TooManyIncrements();
/* -------------------------------------------------------------------------- */
/* events */
/* -------------------------------------------------------------------------- */
/**
* @notice emitted when a purchase is made
* @param buyer The address of the buyer
* @param glwReceived The amount of glow the buyer received
* @param totalUSDCSpent The total amount of USDC the buyer spent to buy the tokens
* @dev emitted when {buy} is successfully called
*/
event Purchase(address indexed buyer, uint256 glwReceived, uint256 totalUSDCSpent);
/**
* @notice Buys tokens with USDC
* @param increments The amount of increments to buy
* - an {increment} is .01 GLW
* @param maxCost The maximum cost to pay for all the increments
*/
function buy(uint256 increments, uint256 maxCost) external;
/**
* @notice Calculates the price of a given amount of tokens
* @param increments The amount of increments to buy
* @return price - the total price in USDC for the given amount of increments
*/
function getPrice(uint256 increments) external view returns (uint256);
/**
* @notice Returns the total amount of GLW tokens sold so far
* @return totalSold - total amount of GLW tokens sold so far (18 decimal value)
*/
function totalSold() external view returns (uint256);
/**
* @notice Returns the current price of the next token.
* @return currentPrice current price of the next token in microdollars
*/
function getCurrentPrice() external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: BSD-4-Clause
/*
* ABDK Math 64.64 Smart Contract Library. Copyright © 2019 by ABDK Consulting.
* Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>
*/
pragma solidity ^0.8.0;
/**
* Smart contract library of mathematical functions operating with signed
* 64.64-bit fixed point numbers. Signed 64.64-bit fixed point number is
* basically a simple fraction whose numerator is signed 128-bit integer and
* denominator is 2^64. As long as denominator is always the same, there is no
* need to store it, thus in Solidity signed 64.64-bit fixed point numbers are
* represented by int128 type holding only the numerator.
*/
library ABDKMath64x64 {
/*
* Minimum value signed 64.64-bit fixed point number may have.
*/
int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;
/*
* Maximum value signed 64.64-bit fixed point number may have.
*/
int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
/**
* Convert signed 256-bit integer number into signed 64.64-bit fixed point
* number. Revert on overflow.
*
* @param x signed 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function fromInt(int256 x) internal pure returns (int128) {
unchecked {
require(x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF);
return int128(x << 64);
}
}
/**
* Convert signed 64.64 fixed point number into signed 64-bit integer number
* rounding down.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64-bit integer number
*/
function toInt(int128 x) internal pure returns (int64) {
unchecked {
return int64(x >> 64);
}
}
/**
* Convert unsigned 256-bit integer number into signed 64.64-bit fixed point
* number. Revert on overflow.
*
* @param x unsigned 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function fromUInt(uint256 x) internal pure returns (int128) {
unchecked {
require(x <= 0x7FFFFFFFFFFFFFFF);
return int128(int256(x << 64));
}
}
/**
* Convert signed 64.64 fixed point number into unsigned 64-bit integer
* number rounding down. Revert on underflow.
*
* @param x signed 64.64-bit fixed point number
* @return unsigned 64-bit integer number
*/
function toUInt(int128 x) internal pure returns (uint64) {
unchecked {
require(x >= 0);
return uint64(uint128(x >> 64));
}
}
/**
* Convert signed 128.128 fixed point number into signed 64.64-bit fixed point
* number rounding down. Revert on overflow.
*
* @param x signed 128.128-bin fixed point number
* @return signed 64.64-bit fixed point number
*/
function from128x128(int256 x) internal pure returns (int128) {
unchecked {
int256 result = x >> 64;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
}
/**
* Convert signed 64.64 fixed point number into signed 128.128 fixed point
* number.
*
* @param x signed 64.64-bit fixed point number
* @return signed 128.128 fixed point number
*/
function to128x128(int128 x) internal pure returns (int256) {
unchecked {
return int256(x) << 64;
}
}
/**
* Calculate x + y. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function add(int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 result = int256(x) + y;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
}
/**
* Calculate x - y. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function sub(int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 result = int256(x) - y;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
}
/**
* Calculate x * y rounding down. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function mul(int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 result = int256(x) * y >> 64;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
}
/**
* Calculate x * y rounding towards zero, where x is signed 64.64 fixed point
* number and y is signed 256-bit integer number. Revert on overflow.
*
* @param x signed 64.64 fixed point number
* @param y signed 256-bit integer number
* @return signed 256-bit integer number
*/
function muli(int128 x, int256 y) internal pure returns (int256) {
unchecked {
if (x == MIN_64x64) {
require(
y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
&& y <= 0x1000000000000000000000000000000000000000000000000
);
return -y << 63;
} else {
bool negativeResult = false;
if (x < 0) {
x = -x;
negativeResult = true;
}
if (y < 0) {
y = -y; // We rely on overflow behavior here
negativeResult = !negativeResult;
}
uint256 absoluteResult = mulu(x, uint256(y));
if (negativeResult) {
require(absoluteResult <= 0x8000000000000000000000000000000000000000000000000000000000000000);
return -int256(absoluteResult); // We rely on overflow behavior here
} else {
require(absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int256(absoluteResult);
}
}
}
}
/**
* Calculate x * y rounding down, where x is signed 64.64 fixed point number
* and y is unsigned 256-bit integer number. Revert on overflow.
*
* @param x signed 64.64 fixed point number
* @param y unsigned 256-bit integer number
* @return unsigned 256-bit integer number
*/
function mulu(int128 x, uint256 y) internal pure returns (uint256) {
unchecked {
if (y == 0) return 0;
require(x >= 0);
uint256 lo = (uint256(int256(x)) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;
uint256 hi = uint256(int256(x)) * (y >> 128);
require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
hi <<= 64;
require(hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo);
return hi + lo;
}
}
/**
* Calculate x / y rounding towards zero. Revert on overflow or when y is
* zero.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function div(int128 x, int128 y) internal pure returns (int128) {
unchecked {
require(y != 0);
int256 result = (int256(x) << 64) / y;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
}
/**
* Calculate x / y rounding towards zero, where x and y are signed 256-bit
* integer numbers. Revert on overflow or when y is zero.
*
* @param x signed 256-bit integer number
* @param y signed 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function divi(int256 x, int256 y) internal pure returns (int128) {
unchecked {
require(y != 0);
bool negativeResult = false;
if (x < 0) {
x = -x; // We rely on overflow behavior here
negativeResult = true;
}
if (y < 0) {
y = -y; // We rely on overflow behavior here
negativeResult = !negativeResult;
}
uint128 absoluteResult = divuu(uint256(x), uint256(y));
if (negativeResult) {
require(absoluteResult <= 0x80000000000000000000000000000000);
return -int128(absoluteResult); // We rely on overflow behavior here
} else {
require(absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int128(absoluteResult); // We rely on overflow behavior here
}
}
}
/**
* Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
* integer numbers. Revert on overflow or when y is zero.
*
* @param x unsigned 256-bit integer number
* @param y unsigned 256-bit integer number
* @return signed 64.64-bit fixed point number
*/
function divu(uint256 x, uint256 y) internal pure returns (int128) {
unchecked {
require(y != 0);
uint128 result = divuu(x, y);
require(result <= uint128(MAX_64x64));
return int128(result);
}
}
/**
* Calculate -x. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function neg(int128 x) internal pure returns (int128) {
unchecked {
require(x != MIN_64x64);
return -x;
}
}
/**
* Calculate |x|. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function abs(int128 x) internal pure returns (int128) {
unchecked {
require(x != MIN_64x64);
return x < 0 ? -x : x;
}
}
/**
* Calculate 1 / x rounding towards zero. Revert on overflow or when x is
* zero.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function inv(int128 x) internal pure returns (int128) {
unchecked {
require(x != 0);
int256 result = int256(0x100000000000000000000000000000000) / x;
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
}
/**
* Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function avg(int128 x, int128 y) internal pure returns (int128) {
unchecked {
return int128((int256(x) + int256(y)) >> 1);
}
}
/**
* Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down.
* Revert on overflow or in case x * y is negative.
*
* @param x signed 64.64-bit fixed point number
* @param y signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function gavg(int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 m = int256(x) * int256(y);
require(m >= 0);
require(m < 0x4000000000000000000000000000000000000000000000000000000000000000);
return int128(sqrtu(uint256(m)));
}
}
/**
* Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number
* and y is unsigned 256-bit integer number. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @param y uint256 value
* @return signed 64.64-bit fixed point number
*/
function pow(int128 x, uint256 y) internal pure returns (int128) {
unchecked {
bool negative = x < 0 && y & 1 == 1;
uint256 absX = uint128(x < 0 ? -x : x);
uint256 absResult;
absResult = 0x100000000000000000000000000000000;
if (absX <= 0x10000000000000000) {
absX <<= 63;
while (y != 0) {
if (y & 0x1 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
if (y & 0x2 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
if (y & 0x4 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
if (y & 0x8 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
y >>= 4;
}
absResult >>= 64;
} else {
uint256 absXShift = 63;
if (absX < 0x1000000000000000000000000) {
absX <<= 32;
absXShift -= 32;
}
if (absX < 0x10000000000000000000000000000) {
absX <<= 16;
absXShift -= 16;
}
if (absX < 0x1000000000000000000000000000000) {
absX <<= 8;
absXShift -= 8;
}
if (absX < 0x10000000000000000000000000000000) {
absX <<= 4;
absXShift -= 4;
}
if (absX < 0x40000000000000000000000000000000) {
absX <<= 2;
absXShift -= 2;
}
if (absX < 0x80000000000000000000000000000000) {
absX <<= 1;
absXShift -= 1;
}
uint256 resultShift = 0;
while (y != 0) {
require(absXShift < 64);
if (y & 0x1 != 0) {
absResult = absResult * absX >> 127;
resultShift += absXShift;
if (absResult > 0x100000000000000000000000000000000) {
absResult >>= 1;
resultShift += 1;
}
}
absX = absX * absX >> 127;
absXShift <<= 1;
if (absX >= 0x100000000000000000000000000000000) {
absX >>= 1;
absXShift += 1;
}
y >>= 1;
}
require(resultShift < 64);
absResult >>= 64 - resultShift;
}
int256 result = negative ? -int256(absResult) : int256(absResult);
require(result >= MIN_64x64 && result <= MAX_64x64);
return int128(result);
}
}
/**
* Calculate sqrt (x) rounding down. Revert if x < 0.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function sqrt(int128 x) internal pure returns (int128) {
unchecked {
require(x >= 0);
return int128(sqrtu(uint256(int256(x)) << 64));
}
}
/**
* Calculate binary logarithm of x. Revert if x <= 0.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function log_2(int128 x) internal pure returns (int128) {
unchecked {
require(x > 0);
int256 msb = 0;
int256 xc = x;
if (xc >= 0x10000000000000000) {
xc >>= 64;
msb += 64;
}
if (xc >= 0x100000000) {
xc >>= 32;
msb += 32;
}
if (xc >= 0x10000) {
xc >>= 16;
msb += 16;
}
if (xc >= 0x100) {
xc >>= 8;
msb += 8;
}
if (xc >= 0x10) {
xc >>= 4;
msb += 4;
}
if (xc >= 0x4) {
xc >>= 2;
msb += 2;
}
if (xc >= 0x2) msb += 1; // No need to shift xc anymore
int256 result = msb - 64 << 64;
uint256 ux = uint256(int256(x)) << uint256(127 - msb);
for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {
ux *= ux;
uint256 b = ux >> 255;
ux >>= 127 + b;
result += bit * int256(b);
}
return int128(result);
}
}
/**
* Calculate natural logarithm of x. Revert if x <= 0.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function ln(int128 x) internal pure returns (int128) {
unchecked {
require(x > 0);
return int128(int256(uint256(int256(log_2(x))) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128));
}
}
/**
* Calculate binary exponent of x. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function exp_2(int128 x) internal pure returns (int128) {
unchecked {
require(x < 0x400000000000000000); // Overflow
if (x < -0x400000000000000000) return 0; // Underflow
uint256 result = 0x80000000000000000000000000000000;
if (x & 0x8000000000000000 > 0) {
result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
}
if (x & 0x4000000000000000 > 0) {
result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
}
if (x & 0x2000000000000000 > 0) {
result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
}
if (x & 0x1000000000000000 > 0) {
result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
}
if (x & 0x800000000000000 > 0) {
result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
}
if (x & 0x400000000000000 > 0) {
result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
}
if (x & 0x200000000000000 > 0) {
result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
}
if (x & 0x100000000000000 > 0) {
result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
}
if (x & 0x80000000000000 > 0) {
result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
}
if (x & 0x40000000000000 > 0) {
result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
}
if (x & 0x20000000000000 > 0) {
result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
}
if (x & 0x10000000000000 > 0) {
result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
}
if (x & 0x8000000000000 > 0) {
result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
}
if (x & 0x4000000000000 > 0) {
result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
}
if (x & 0x2000000000000 > 0) {
result = result * 0x1000162E525EE054754457D5995292026 >> 128;
}
if (x & 0x1000000000000 > 0) {
result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
}
if (x & 0x800000000000 > 0) {
result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
}
if (x & 0x400000000000 > 0) {
result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
}
if (x & 0x200000000000 > 0) {
result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128;
}
if (x & 0x100000000000 > 0) {
result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
}
if (x & 0x80000000000 > 0) {
result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
}
if (x & 0x40000000000 > 0) {
result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
}
if (x & 0x20000000000 > 0) {
result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
}
if (x & 0x10000000000 > 0) {
result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
}
if (x & 0x8000000000 > 0) {
result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
}
if (x & 0x4000000000 > 0) {
result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
}
if (x & 0x2000000000 > 0) {
result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
}
if (x & 0x1000000000 > 0) {
result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
}
if (x & 0x800000000 > 0) {
result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
}
if (x & 0x400000000 > 0) {
result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
}
if (x & 0x200000000 > 0) {
result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
}
if (x & 0x100000000 > 0) {
result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
}
if (x & 0x80000000 > 0) {
result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
}
if (x & 0x40000000 > 0) {
result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
}
if (x & 0x20000000 > 0) {
result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128;
}
if (x & 0x10000000 > 0) {
result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
}
if (x & 0x8000000 > 0) {
result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
}
if (x & 0x4000000 > 0) {
result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
}
if (x & 0x2000000 > 0) {
result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
}
if (x & 0x1000000 > 0) {
result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128;
}
if (x & 0x800000 > 0) {
result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
}
if (x & 0x400000 > 0) {
result = result * 0x100000000002C5C85FDF477B662B26945 >> 128;
}
if (x & 0x200000 > 0) {
result = result * 0x10000000000162E42FEFA3AE53369388C >> 128;
}
if (x & 0x100000 > 0) {
result = result * 0x100000000000B17217F7D1D351A389D40 >> 128;
}
if (x & 0x80000 > 0) {
result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
}
if (x & 0x40000 > 0) {
result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
}
if (x & 0x20000 > 0) {
result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128;
}
if (x & 0x10000 > 0) {
result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
}
if (x & 0x8000 > 0) {
result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
}
if (x & 0x4000 > 0) {
result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128;
}
if (x & 0x2000 > 0) {
result = result * 0x1000000000000162E42FEFA39F02B772C >> 128;
}
if (x & 0x1000 > 0) {
result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
}
if (x & 0x800 > 0) {
result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
}
if (x & 0x400 > 0) {
result = result * 0x100000000000002C5C85FDF473DEA871F >> 128;
}
if (x & 0x200 > 0) {
result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128;
}
if (x & 0x100 > 0) {
result = result * 0x100000000000000B17217F7D1CF79E949 >> 128;
}
if (x & 0x80 > 0) {
result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
}
if (x & 0x40 > 0) {
result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
}
if (x & 0x20 > 0) {
result = result * 0x100000000000000162E42FEFA39EF366F >> 128;
}
if (x & 0x10 > 0) {
result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128;
}
if (x & 0x8 > 0) {
result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
}
if (x & 0x4 > 0) {
result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
}
if (x & 0x2 > 0) {
result = result * 0x1000000000000000162E42FEFA39EF358 >> 128;
}
if (x & 0x1 > 0) {
result = result * 0x10000000000000000B17217F7D1CF79AB >> 128;
}
result >>= uint256(int256(63 - (x >> 64)));
require(result <= uint256(int256(MAX_64x64)));
return int128(int256(result));
}
}
/**
* Calculate natural exponent of x. Revert on overflow.
*
* @param x signed 64.64-bit fixed point number
* @return signed 64.64-bit fixed point number
*/
function exp(int128 x) internal pure returns (int128) {
unchecked {
require(x < 0x400000000000000000); // Overflow
if (x < -0x400000000000000000) return 0; // Underflow
return exp_2(int128(int256(x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128));
}
}
/**
* Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
* integer numbers. Revert on overflow or when y is zero.
*
* @param x unsigned 256-bit integer number
* @param y unsigned 256-bit integer number
* @return unsigned 64.64-bit fixed point number
*/
function divuu(uint256 x, uint256 y) private pure returns (uint128) {
unchecked {
require(y != 0);
uint256 result;
if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {
result = (x << 64) / y;
} else {
uint256 msb = 192;
uint256 xc = x >> 192;
if (xc >= 0x100000000) {
xc >>= 32;
msb += 32;
}
if (xc >= 0x10000) {
xc >>= 16;
msb += 16;
}
if (xc >= 0x100) {
xc >>= 8;
msb += 8;
}
if (xc >= 0x10) {
xc >>= 4;
msb += 4;
}
if (xc >= 0x4) {
xc >>= 2;
msb += 2;
}
if (xc >= 0x2) msb += 1; // No need to shift xc anymore
result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1);
require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
uint256 hi = result * (y >> 128);
uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
uint256 xh = x >> 192;
uint256 xl = x << 64;
if (xl < lo) xh -= 1;
xl -= lo; // We rely on overflow behavior here
lo = hi << 128;
if (xl < lo) xh -= 1;
xl -= lo; // We rely on overflow behavior here
result += xh == hi >> 128 ? xl / y : 1;
}
require(result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return uint128(result);
}
}
/**
* Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer
* number.
*
* @param x unsigned 256-bit integer number
* @return unsigned 128-bit integer number
*/
function sqrtu(uint256 x) private pure returns (uint128) {
unchecked {
if (x == 0) {
return 0;
} else {
uint256 xx = x;
uint256 r = 1;
if (xx >= 0x100000000000000000000000000000000) {
xx >>= 128;
r <<= 64;
}
if (xx >= 0x10000000000000000) {
xx >>= 64;
r <<= 32;
}
if (xx >= 0x100000000) {
xx >>= 32;
r <<= 16;
}
if (xx >= 0x10000) {
xx >>= 16;
r <<= 8;
}
if (xx >= 0x100) {
xx >>= 8;
r <<= 4;
}
if (xx >= 0x10) {
xx >>= 4;
r <<= 2;
}
if (xx >= 0x4) r <<= 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1; // Seven iterations should be enough
uint256 r1 = x / r;
return uint128(r < r1 ? r : r1);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IMinerPool {
/* -------------------------------------------------------------------------- */
/* errors */
/* -------------------------------------------------------------------------- */
error ElectricityFuturesSignatureExpired();
error ElectricityFuturesAuctionEnded();
error ElectricityFuturesAuctionBidTooLow();
error ElectricityFuturesAuctionAuthorizationTooLong();
error ElectricityFuturesAuctionInvalidSignature();
error ElectricityFutureAuctionBidMustBeGreaterThanMinimumBid();
error CallerNotEarlyLiquidity();
error NotUSDCToken();
error InvalidProof();
error UserAlreadyClaimed();
error AlreadyMintedToCarbonCreditAuction();
error BucketNotFinalized();
error CallerNotVetoCouncilMember();
error CannotDelayEmptyBucket();
error CannotDelayBucketThatNeedsToUpdateSlashNonce();
error BucketAlreadyDelayed();
error SignerNotGCA();
error SignatureDoesNotMatchUser();
error GlowWeightOverflow();
error USDCWeightOverflow();
error GlowWeightGreaterThanTotalWeight();
error USDCWeightGreaterThanTotalWeight();
/* -------------------------------------------------------------------------- */
/* state-changing */
/* -------------------------------------------------------------------------- */
/**
* @notice Allows anyone to donate USDC into the miner USDC rewards pool
* @notice the amount is split across 192 weeks starting at the current week + 16
* @param amount - amount to deposit
*/
function donateToUSDCMinerRewardsPool(uint256 amount) external;
/**
* @notice Allows the early liquidity to donate USDC into the miner USDC rewards pool
* @notice the amount is split across 192 weeks starting at the current week + 16
* @dev the USDC token must be a valid USDC token
* @dev early liquidity will safeTransfer from the user to the miner pool
* - and then call this function directly.
* - we do this to prevent extra transfers.
* @param amount - amount to deposit
*/
function donateToUSDCMinerRewardsPoolEarlyLiquidity(uint256 amount) external;
/**
* @notice allows a user to claim their rewards for a bucket
* @dev It's highly recommended to use a CLI or UI to call this function.
* - the proof can only be generated off-chain with access to the entire tree
* - furthermore, USDC tokens must be correctly input in order to receive rewards
* - the USDC tokens should be kept on record off-chain.
* - failure to input all correct USDC Tokens will result in lost rewards
* @param bucketId - the id of the bucket
* @param glwWeight - the weight of the user's glw rewards
* @param USDCWeight - the weight of the user's USDC rewards
* @param proof - the merkle proof of the user's rewards
* - the leaves are {payoutWallet, glwWeight, USDCWeight}
* @param index - the index of the report in the bucket
* - that contains the merkle root where the user's rewards are stored
* @param user - the address of the user
* @param claimFromInflation - whether or not to claim glow from inflation
* @param signature - the eip712 signature that allows a relayer to execute the action
* - to claim for a user.
* - the relayer is not able to access rewards under any means
* - rewards are always sent to the {user}
*/
function claimRewardFromBucket(
uint256 bucketId,
uint256 glwWeight,
uint256 USDCWeight,
bytes32[] calldata proof,
uint256 index,
address user,
bool claimFromInflation,
bytes memory signature
) external;
/**
* @notice allows a veto council member to delay the finalization of a bucket
* @dev the bucket must already be initialized in order to be delayed
* @dev the bucket cannot be finalized in order to be delayed
* @dev the bucket can be delayed multiple times
* @param bucketId - the id of the bucket to delay
*/
function delayBucketFinalization(uint256 bucketId) external;
/* -------------------------------------------------------------------------- */
/* view */
/* -------------------------------------------------------------------------- */
/**
* @notice returns true if a bucket has been delayed
* @param bucketId - the id of the bucket
* @return true if the bucket has been delayed
*/
function hasBucketBeenDelayed(uint256 bucketId) external view returns (bool);
/**
* @notice returns the bytes32 digest of the claim reward from bucket message
* @param bucketId - the id of the bucket
* @param glwWeight - the weight of the user's glw rewards in the leaf of the report root
* @param USDCWeight - the weight of the user's USDC rewards in the leaf of the report root
* @param index - the index of the report in the bucket
* - that contains the merkle root where the user's rewards are stored
* @param claimFromInflation - whether or not to claim glow from inflation
* @return the bytes32 digest of the claim reward from bucket message
*/
function createClaimRewardFromBucketDigest(
uint256 bucketId,
uint256 glwWeight,
uint256 USDCWeight,
uint256 index,
bool claimFromInflation
) external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}{
"remappings": [
"forge-std/=lib/forge-std/src/",
"solmate/=lib/solmate/src/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@/=src/",
"@solady/=lib/solady/src/",
"@unifapv2/=src/UnifapV2/",
"clones/=lib/clones-with-immutable-args/src/",
"@openzeppelin/=lib/openzeppelin-contracts/contracts/",
"@clones/=lib/unifap-v2/lib/clones-with-immutable-args/src/",
"@ds/=lib/unifap-v2/lib/ds-test/src/",
"@solmate/=lib/unifap-v2/lib/solmate/src/",
"@std/=lib/unifap-v2/lib/forge-std/src/",
"abdk-libraries-solidity/=lib/abdk-libraries-solidity/",
"clones-with-immutable-args/=lib/clones-with-immutable-args/src/",
"clones/=lib/unifap-v2/lib/clones-with-immutable-args/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"solady/=lib/solady/",
"unifap-v2/=lib/unifap-v2/src/"
],
"optimizer": {
"enabled": true,
"runs": 1000000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"libraries": {
"src/libraries/HalfLife.sol": {
"HalfLife": "0xcf4d7552ca9f07c474d69e89a88943fabb60b199"
},
"src/libraries/HalfLifeCarbonCreditAuction.sol": {
"HalfLifeCarbonCreditAuction": "0xd178525026bafc51d045a2e98b0c79a526d446de"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_usdcAddress","type":"address"},{"internalType":"address","name":"_holdingContract","type":"address"},{"internalType":"address","name":"_glowToken","type":"address"},{"internalType":"address","name":"_minerPoolAddress","type":"address"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AllSold","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"MinerPoolAlreadySet","type":"error"},{"inputs":[],"name":"ModNotZero","type":"error"},{"inputs":[],"name":"PriceTooHigh","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TooManyIncrements","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"glwReceived","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalUSDCSpent","type":"uint256"}],"name":"Purchase","type":"event"},{"inputs":[],"name":"GLOW_TOKEN","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HOLDING_CONTRACT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINER_POOL","outputs":[{"internalType":"contract IMinerPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_TOKEN_INCREMENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOTAL_INCREMENTS_TO_SELL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC_TOKEN","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"increments","type":"uint256"},{"internalType":"uint256","name":"maxCost","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCurrentPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"incrementsToPurchase","type":"uint256"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
610100604052604051620019fd380380620019fd83398101604081905262000027916200010f565b836001600160a01b03166080816001600160a01b0316815250506000846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000082573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000a891906200016c565b60ff16905060068114620000c857620000c863436093a560e01b620000e8565b506001600160a01b0392831660a05290821660c0521660e0525062000198565b8060005260046000fd5b80516001600160a01b03811681146200010a57600080fd5b919050565b600080600080608085870312156200012657600080fd5b6200013185620000f2565b93506200014160208601620000f2565b92506200015160408601620000f2565b91506200016160608601620000f2565b905092959194509250565b6000602082840312156200017f57600080fd5b815160ff811681146200019157600080fd5b9392505050565b60805160a05160c05160e051611802620001fb60003960008181610182015261021901526000818160d30152610458015260008181610124015261023a0152600081816101d9015281816102f50152818161036701526103d601526118026000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063c1419def11610081578063e75722301161005b578063e7572230146101b9578063eb91d37e146101cc578063fa569274146101d457600080fd5b8063c1419def14610175578063d203d5a01461017d578063d6febde8146101a457600080fd5b80637c34b052116100b25780637c34b052146101465780639106d7ba1461015f5780639ec5b8051461016757600080fd5b806339b6eaf5146100ce57806379193d291461011f575b600080fd5b6100f57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f57f000000000000000000000000000000000000000000000000000000000000000081565b6101516347868c0081565b604051908152602001610116565b6101516101fb565b610151662386f26fc1000081565b610151600681565b6100f57f000000000000000000000000000000000000000000000000000000000000000081565b6101b76101b236600461168c565b610217565b005b6101516101c73660046116ae565b61055a565b61015161057e565b6100f57f000000000000000000000000000000000000000000000000000000000000000081565b6000662386f26fc1000060005461021291906116f6565b905090565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060006102648561055a565b905083811115610297576102977f24fe11920000000000000000000000000000000000000000000000000000000061058d565b60006102aa86662386f26fc100006116f6565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301529192506000917f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561033c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610360919061170d565b905061038e7f0000000000000000000000000000000000000000000000000000000000000000338686610597565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526000917f0000000000000000000000000000000000000000000000000000000000000000909116906370a0823190602401602060405180830381865afa15801561041f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610443919061170d565b905060006104518383611726565b905061047e7f00000000000000000000000000000000000000000000000000000000000000003386610626565b6040517feaea67a50000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff88169063eaea67a590602401600060405180830381600087803b1580156104e657600080fd5b505af11580156104fa573d6000803e3d6000fd5b505050508860008082825461050f9190611739565b9091555050604080518581526020810187905233917f12cb4648cf3058b17ceeb33e579f8b0bc269fe0843f3900b8e24b6c54871703c910160405180910390a2505050505050505050565b60008160000361056c57506000919050565b61057860005483610669565b92915050565b60006102126000546001610669565b8060005260046000fd5b60405173ffffffffffffffffffffffffffffffffffffffff84811660248301528381166044830152606482018390526106209186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610752565b50505050565b60405173ffffffffffffffffffffffffffffffffffffffff83811660248301526044820183905261066491859182169063a9059cbb906064016105d9565b505050565b60006347868c0061067a8385611739565b11156106a9576106a97fb3723c6b0000000000000000000000000000000000000000000000000000000061058d565b60006106b4836107ed565b905060006106cf6106ca83641dc53bde4461080b565b61086a565b905060006106e668010000000000000000836108da565b90506000610718600f83900b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffe23ac422f361092e565b90506000610725886109a6565b9050600f81810b9083900b6000604061073e83856116f6565b901c60401c9b9a5050505050505050505050565b600061077473ffffffffffffffffffffffffffffffffffffffff841683610a10565b90508051600014158015610799575080806020019051810190610797919061174c565b155b15610664576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024015b60405180910390fd5b6000677fffffffffffffff82111561080457600080fd5b5060401b90565b6000600f83810b9083900b0260401d7fffffffffffffffffffffffffffffffff80000000000000000000000000000000811280159061085a57506f7fffffffffffffffffffffffffffffff8113155b61086357600080fd5b9392505050565b60006840000000000000000082600f0b1261088457600080fd5b7fffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000082600f0b12156108b757506000919050565b610578608083600f0b700171547652b82fe1777d0ffda0d23a7d1202901d610a1e565b6000600f82810b9084900b037fffffffffffffffffffffffffffffffff80000000000000000000000000000000811280159061085a57506f7fffffffffffffffffffffffffffffff81131561086357600080fd5b600081600f0b60000361094057600080fd5b600082600f0b604085600f0b901b8161095b5761095b61176e565b0590507fffffffffffffffffffffffffffffffff80000000000000000000000000000000811280159061085a57506f7fffffffffffffffffffffffffffffff81131561086357600080fd5b6000806109b2836107ed565b905060006109e16b05f5e10000000000000000006109d867b17217f7d1cf79ab8561080b565b600f0b9061092e565b905060006109ee8261086a565b90506000610a06690bb800000000000000008361080b565b9695505050505050565b606061086383836000611507565b60006840000000000000000082600f0b12610a3857600080fd5b7fffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000082600f0b1215610a6b57506000919050565b6f8000000000000000000000000000000060006780000000000000008416600f0b1315610aa95770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b60008367400000000000000016600f0b1315610ad6577001306fe0a31b7152de8d5a46305c85edec0260801c5b60008367200000000000000016600f0b1315610b03577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b60008367100000000000000016600f0b1315610b305770010b5586cf9890f6298b92b71842a983630260801c5b60008367080000000000000016600f0b1315610b5d577001059b0d31585743ae7c548eb68ca417fd0260801c5b60008367040000000000000016600f0b1315610b8a57700102c9a3e778060ee6f7caca4f7a29bde80260801c5b60008367020000000000000016600f0b1315610bb75770010163da9fb33356d84a66ae336dcdfa3f0260801c5b60008367010000000000000016600f0b1315610be457700100b1afa5abcbed6129ab13ec11dc95430260801c5b600083668000000000000016600f0b1315610c105770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600083664000000000000016600f0b1315610c3c577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600083662000000000000016600f0b1315610c6857700100162f3904051fa128bca9c55c31e5df0260801c5b600083661000000000000016600f0b1315610c94577001000b175effdc76ba38e31671ca9397250260801c5b600083660800000000000016600f0b1315610cc057700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600083660400000000000016600f0b1315610cec5770010002c5cc37da9491d0985c348c68e7b30260801c5b600083660200000000000016600f0b1315610d18577001000162e525ee054754457d59952920260260801c5b600083660100000000000016600f0b1315610d445770010000b17255775c040618bf4a4ade83fc0260801c5b6000836580000000000016600f0b1315610d6f577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6000836540000000000016600f0b1315610d9a57700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6000836520000000000016600f0b1315610dc55770010000162e43f4f831060e02d839a9d16d0260801c5b6000836510000000000016600f0b1315610df057700100000b1721bcfc99d9f890ea069117630260801c5b6000836508000000000016600f0b1315610e1b5770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6000836504000000000016600f0b1315610e46577001000002c5c863b73f016468f6bac5ca2b0260801c5b6000836502000000000016600f0b1315610e7157700100000162e430e5a18f6119e3c02282a50260801c5b6000836501000000000016600f0b1315610e9c577001000000b1721835514b86e6d96efd1bfe0260801c5b60008364800000000016600f0b1315610ec657700100000058b90c0b48c6be5df846c5b2ef0260801c5b60008364400000000016600f0b1315610ef05770010000002c5c8601cc6b9e94213c72737a0260801c5b60008364200000000016600f0b1315610f1a577001000000162e42fff037df38aa2b219f060260801c5b60008364100000000016600f0b1315610f445770010000000b17217fba9c739aa5819f44f90260801c5b60008364080000000016600f0b1315610f6e577001000000058b90bfcdee5acd3c1cedc8230260801c5b60008364040000000016600f0b1315610f9857700100000002c5c85fe31f35a6a30da1be500260801c5b60008364020000000016600f0b1315610fc25770010000000162e42ff0999ce3541b9fffcf0260801c5b60008364010000000016600f0b1315610fec57700100000000b17217f80f4ef5aadda455540260801c5b600083638000000016600f0b13156110155770010000000058b90bfbf8479bd5a81b51ad0260801c5b600083634000000016600f0b131561103e577001000000002c5c85fdf84bd62ae30a74cc0260801c5b600083632000000016600f0b131561106757700100000000162e42fefb2fed257559bdaa0260801c5b600083631000000016600f0b1315611090577001000000000b17217f7d5a7716bba4a9ae0260801c5b600083630800000016600f0b13156110b957700100000000058b90bfbe9ddbac5e109cce0260801c5b600083630400000016600f0b13156110e25770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600083630200000016600f0b131561110b577001000000000162e42fefa494f1478fde050260801c5b600083630100000016600f0b13156111345770010000000000b17217f7d20cf927c8e94c0260801c5b6000836280000016600f0b131561115c577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6000836240000016600f0b131561118457700100000000002c5c85fdf477b662b269450260801c5b6000836220000016600f0b13156111ac5770010000000000162e42fefa3ae53369388c0260801c5b6000836210000016600f0b13156111d457700100000000000b17217f7d1d351a389d400260801c5b6000836208000016600f0b13156111fc5770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6000836204000016600f0b1315611224577001000000000002c5c85fdf4741bea6e77e0260801c5b6000836202000016600f0b131561124c57700100000000000162e42fefa39fe95583c20260801c5b6000836201000016600f0b1315611274577001000000000000b17217f7d1cfb72b45e10260801c5b60008361800016600f0b131561129b57700100000000000058b90bfbe8e7cc35c3f00260801c5b60008361400016600f0b13156112c25770010000000000002c5c85fdf473e242ea380260801c5b60008361200016600f0b13156112e9577001000000000000162e42fefa39f02b772c0260801c5b60008361100016600f0b13156113105770010000000000000b17217f7d1cf7d83c1a0260801c5b60008361080016600f0b1315611337577001000000000000058b90bfbe8e7bdcbe2e0260801c5b60008361040016600f0b131561135e57700100000000000002c5c85fdf473dea871f0260801c5b60008361020016600f0b13156113855770010000000000000162e42fefa39ef44d910260801c5b60008361010016600f0b13156113ac57700100000000000000b17217f7d1cf79e9490260801c5b600083608016600f0b13156113d25770010000000000000058b90bfbe8e7bce5440260801c5b600083604016600f0b13156113f8577001000000000000002c5c85fdf473de6eca0260801c5b600083602016600f0b131561141e57700100000000000000162e42fefa39ef366f0260801c5b600083601016600f0b1315611444577001000000000000000b17217f7d1cf79afa0260801c5b600083600816600f0b131561146a57700100000000000000058b90bfbe8e7bcd6d0260801c5b600083600416600f0b13156114905770010000000000000002c5c85fdf473de6b20260801c5b600083600216600f0b13156114b6577001000000000000000162e42fefa39ef3580260801c5b600083600116600f0b13156114dc5770010000000000000000b17217f7d1cf79ab0260801c5b600f83810b60401d603f03900b1c6f7fffffffffffffffffffffffffffffff81111561057857600080fd5b606081471015611545576040517fcd7860590000000000000000000000000000000000000000000000000000000081523060048201526024016107e4565b6000808573ffffffffffffffffffffffffffffffffffffffff16848660405161156e919061179d565b60006040518083038185875af1925050503d80600081146115ab576040519150601f19603f3d011682016040523d82523d6000602084013e6115b0565b606091505b5091509150610a068683836060826115d0576115cb8261164a565b610863565b81511580156115f4575073ffffffffffffffffffffffffffffffffffffffff84163b155b15611643576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016107e4565b5080610863565b80511561165a5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806040838503121561169f57600080fd5b50508035926020909101359150565b6000602082840312156116c057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610578576105786116c7565b60006020828403121561171f57600080fd5b5051919050565b81810381811115610578576105786116c7565b80820180821115610578576105786116c7565b60006020828403121561175e57600080fd5b8151801515811461086357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000825160005b818110156117be57602081860181015185830152016117a4565b50600092019182525091905056fea26469706673582212208878d08444744ce78397e3e37bdcc9f59b74dff5f3044318441edc83ed285d4264736f6c63430008150033000000000000000000000000e010ec500720be9ef3f82129e7ed2ee1fb7955f2000000000000000000000000d5970622b740a2ea5a5574616c193968b10e1297000000000000000000000000f4fbc617a5733eaaf9af08e1ab816b103388d8b60000000000000000000000006fa8c7a89b22bf3212392b778905b12f3dbaf5c4
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100c95760003560e01c8063c1419def11610081578063e75722301161005b578063e7572230146101b9578063eb91d37e146101cc578063fa569274146101d457600080fd5b8063c1419def14610175578063d203d5a01461017d578063d6febde8146101a457600080fd5b80637c34b052116100b25780637c34b052146101465780639106d7ba1461015f5780639ec5b8051461016757600080fd5b806339b6eaf5146100ce57806379193d291461011f575b600080fd5b6100f57f000000000000000000000000f4fbc617a5733eaaf9af08e1ab816b103388d8b681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100f57f000000000000000000000000d5970622b740a2ea5a5574616c193968b10e129781565b6101516347868c0081565b604051908152602001610116565b6101516101fb565b610151662386f26fc1000081565b610151600681565b6100f57f0000000000000000000000006fa8c7a89b22bf3212392b778905b12f3dbaf5c481565b6101b76101b236600461168c565b610217565b005b6101516101c73660046116ae565b61055a565b61015161057e565b6100f57f000000000000000000000000e010ec500720be9ef3f82129e7ed2ee1fb7955f281565b6000662386f26fc1000060005461021291906116f6565b905090565b7f0000000000000000000000006fa8c7a89b22bf3212392b778905b12f3dbaf5c47f000000000000000000000000d5970622b740a2ea5a5574616c193968b10e129760006102648561055a565b905083811115610297576102977f24fe11920000000000000000000000000000000000000000000000000000000061058d565b60006102aa86662386f26fc100006116f6565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301529192506000917f000000000000000000000000e010ec500720be9ef3f82129e7ed2ee1fb7955f216906370a0823190602401602060405180830381865afa15801561033c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610360919061170d565b905061038e7f000000000000000000000000e010ec500720be9ef3f82129e7ed2ee1fb7955f2338686610597565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526000917f000000000000000000000000e010ec500720be9ef3f82129e7ed2ee1fb7955f2909116906370a0823190602401602060405180830381865afa15801561041f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610443919061170d565b905060006104518383611726565b905061047e7f000000000000000000000000f4fbc617a5733eaaf9af08e1ab816b103388d8b63386610626565b6040517feaea67a50000000000000000000000000000000000000000000000000000000081526004810182905273ffffffffffffffffffffffffffffffffffffffff88169063eaea67a590602401600060405180830381600087803b1580156104e657600080fd5b505af11580156104fa573d6000803e3d6000fd5b505050508860008082825461050f9190611739565b9091555050604080518581526020810187905233917f12cb4648cf3058b17ceeb33e579f8b0bc269fe0843f3900b8e24b6c54871703c910160405180910390a2505050505050505050565b60008160000361056c57506000919050565b61057860005483610669565b92915050565b60006102126000546001610669565b8060005260046000fd5b60405173ffffffffffffffffffffffffffffffffffffffff84811660248301528381166044830152606482018390526106209186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610752565b50505050565b60405173ffffffffffffffffffffffffffffffffffffffff83811660248301526044820183905261066491859182169063a9059cbb906064016105d9565b505050565b60006347868c0061067a8385611739565b11156106a9576106a97fb3723c6b0000000000000000000000000000000000000000000000000000000061058d565b60006106b4836107ed565b905060006106cf6106ca83641dc53bde4461080b565b61086a565b905060006106e668010000000000000000836108da565b90506000610718600f83900b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffe23ac422f361092e565b90506000610725886109a6565b9050600f81810b9083900b6000604061073e83856116f6565b901c60401c9b9a5050505050505050505050565b600061077473ffffffffffffffffffffffffffffffffffffffff841683610a10565b90508051600014158015610799575080806020019051810190610797919061174c565b155b15610664576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024015b60405180910390fd5b6000677fffffffffffffff82111561080457600080fd5b5060401b90565b6000600f83810b9083900b0260401d7fffffffffffffffffffffffffffffffff80000000000000000000000000000000811280159061085a57506f7fffffffffffffffffffffffffffffff8113155b61086357600080fd5b9392505050565b60006840000000000000000082600f0b1261088457600080fd5b7fffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000082600f0b12156108b757506000919050565b610578608083600f0b700171547652b82fe1777d0ffda0d23a7d1202901d610a1e565b6000600f82810b9084900b037fffffffffffffffffffffffffffffffff80000000000000000000000000000000811280159061085a57506f7fffffffffffffffffffffffffffffff81131561086357600080fd5b600081600f0b60000361094057600080fd5b600082600f0b604085600f0b901b8161095b5761095b61176e565b0590507fffffffffffffffffffffffffffffffff80000000000000000000000000000000811280159061085a57506f7fffffffffffffffffffffffffffffff81131561086357600080fd5b6000806109b2836107ed565b905060006109e16b05f5e10000000000000000006109d867b17217f7d1cf79ab8561080b565b600f0b9061092e565b905060006109ee8261086a565b90506000610a06690bb800000000000000008361080b565b9695505050505050565b606061086383836000611507565b60006840000000000000000082600f0b12610a3857600080fd5b7fffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000082600f0b1215610a6b57506000919050565b6f8000000000000000000000000000000060006780000000000000008416600f0b1315610aa95770016a09e667f3bcc908b2fb1366ea957d3e0260801c5b60008367400000000000000016600f0b1315610ad6577001306fe0a31b7152de8d5a46305c85edec0260801c5b60008367200000000000000016600f0b1315610b03577001172b83c7d517adcdf7c8c50eb14a791f0260801c5b60008367100000000000000016600f0b1315610b305770010b5586cf9890f6298b92b71842a983630260801c5b60008367080000000000000016600f0b1315610b5d577001059b0d31585743ae7c548eb68ca417fd0260801c5b60008367040000000000000016600f0b1315610b8a57700102c9a3e778060ee6f7caca4f7a29bde80260801c5b60008367020000000000000016600f0b1315610bb75770010163da9fb33356d84a66ae336dcdfa3f0260801c5b60008367010000000000000016600f0b1315610be457700100b1afa5abcbed6129ab13ec11dc95430260801c5b600083668000000000000016600f0b1315610c105770010058c86da1c09ea1ff19d294cf2f679b0260801c5b600083664000000000000016600f0b1315610c3c577001002c605e2e8cec506d21bfc89a23a00f0260801c5b600083662000000000000016600f0b1315610c6857700100162f3904051fa128bca9c55c31e5df0260801c5b600083661000000000000016600f0b1315610c94577001000b175effdc76ba38e31671ca9397250260801c5b600083660800000000000016600f0b1315610cc057700100058ba01fb9f96d6cacd4b180917c3d0260801c5b600083660400000000000016600f0b1315610cec5770010002c5cc37da9491d0985c348c68e7b30260801c5b600083660200000000000016600f0b1315610d18577001000162e525ee054754457d59952920260260801c5b600083660100000000000016600f0b1315610d445770010000b17255775c040618bf4a4ade83fc0260801c5b6000836580000000000016600f0b1315610d6f577001000058b91b5bc9ae2eed81e9b7d4cfab0260801c5b6000836540000000000016600f0b1315610d9a57700100002c5c89d5ec6ca4d7c8acc017b7c90260801c5b6000836520000000000016600f0b1315610dc55770010000162e43f4f831060e02d839a9d16d0260801c5b6000836510000000000016600f0b1315610df057700100000b1721bcfc99d9f890ea069117630260801c5b6000836508000000000016600f0b1315610e1b5770010000058b90cf1e6d97f9ca14dbcc16280260801c5b6000836504000000000016600f0b1315610e46577001000002c5c863b73f016468f6bac5ca2b0260801c5b6000836502000000000016600f0b1315610e7157700100000162e430e5a18f6119e3c02282a50260801c5b6000836501000000000016600f0b1315610e9c577001000000b1721835514b86e6d96efd1bfe0260801c5b60008364800000000016600f0b1315610ec657700100000058b90c0b48c6be5df846c5b2ef0260801c5b60008364400000000016600f0b1315610ef05770010000002c5c8601cc6b9e94213c72737a0260801c5b60008364200000000016600f0b1315610f1a577001000000162e42fff037df38aa2b219f060260801c5b60008364100000000016600f0b1315610f445770010000000b17217fba9c739aa5819f44f90260801c5b60008364080000000016600f0b1315610f6e577001000000058b90bfcdee5acd3c1cedc8230260801c5b60008364040000000016600f0b1315610f9857700100000002c5c85fe31f35a6a30da1be500260801c5b60008364020000000016600f0b1315610fc25770010000000162e42ff0999ce3541b9fffcf0260801c5b60008364010000000016600f0b1315610fec57700100000000b17217f80f4ef5aadda455540260801c5b600083638000000016600f0b13156110155770010000000058b90bfbf8479bd5a81b51ad0260801c5b600083634000000016600f0b131561103e577001000000002c5c85fdf84bd62ae30a74cc0260801c5b600083632000000016600f0b131561106757700100000000162e42fefb2fed257559bdaa0260801c5b600083631000000016600f0b1315611090577001000000000b17217f7d5a7716bba4a9ae0260801c5b600083630800000016600f0b13156110b957700100000000058b90bfbe9ddbac5e109cce0260801c5b600083630400000016600f0b13156110e25770010000000002c5c85fdf4b15de6f17eb0d0260801c5b600083630200000016600f0b131561110b577001000000000162e42fefa494f1478fde050260801c5b600083630100000016600f0b13156111345770010000000000b17217f7d20cf927c8e94c0260801c5b6000836280000016600f0b131561115c577001000000000058b90bfbe8f71cb4e4b33d0260801c5b6000836240000016600f0b131561118457700100000000002c5c85fdf477b662b269450260801c5b6000836220000016600f0b13156111ac5770010000000000162e42fefa3ae53369388c0260801c5b6000836210000016600f0b13156111d457700100000000000b17217f7d1d351a389d400260801c5b6000836208000016600f0b13156111fc5770010000000000058b90bfbe8e8b2d3d4ede0260801c5b6000836204000016600f0b1315611224577001000000000002c5c85fdf4741bea6e77e0260801c5b6000836202000016600f0b131561124c57700100000000000162e42fefa39fe95583c20260801c5b6000836201000016600f0b1315611274577001000000000000b17217f7d1cfb72b45e10260801c5b60008361800016600f0b131561129b57700100000000000058b90bfbe8e7cc35c3f00260801c5b60008361400016600f0b13156112c25770010000000000002c5c85fdf473e242ea380260801c5b60008361200016600f0b13156112e9577001000000000000162e42fefa39f02b772c0260801c5b60008361100016600f0b13156113105770010000000000000b17217f7d1cf7d83c1a0260801c5b60008361080016600f0b1315611337577001000000000000058b90bfbe8e7bdcbe2e0260801c5b60008361040016600f0b131561135e57700100000000000002c5c85fdf473dea871f0260801c5b60008361020016600f0b13156113855770010000000000000162e42fefa39ef44d910260801c5b60008361010016600f0b13156113ac57700100000000000000b17217f7d1cf79e9490260801c5b600083608016600f0b13156113d25770010000000000000058b90bfbe8e7bce5440260801c5b600083604016600f0b13156113f8577001000000000000002c5c85fdf473de6eca0260801c5b600083602016600f0b131561141e57700100000000000000162e42fefa39ef366f0260801c5b600083601016600f0b1315611444577001000000000000000b17217f7d1cf79afa0260801c5b600083600816600f0b131561146a57700100000000000000058b90bfbe8e7bcd6d0260801c5b600083600416600f0b13156114905770010000000000000002c5c85fdf473de6b20260801c5b600083600216600f0b13156114b6577001000000000000000162e42fefa39ef3580260801c5b600083600116600f0b13156114dc5770010000000000000000b17217f7d1cf79ab0260801c5b600f83810b60401d603f03900b1c6f7fffffffffffffffffffffffffffffff81111561057857600080fd5b606081471015611545576040517fcd7860590000000000000000000000000000000000000000000000000000000081523060048201526024016107e4565b6000808573ffffffffffffffffffffffffffffffffffffffff16848660405161156e919061179d565b60006040518083038185875af1925050503d80600081146115ab576040519150601f19603f3d011682016040523d82523d6000602084013e6115b0565b606091505b5091509150610a068683836060826115d0576115cb8261164a565b610863565b81511580156115f4575073ffffffffffffffffffffffffffffffffffffffff84163b155b15611643576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016107e4565b5080610863565b80511561165a5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806040838503121561169f57600080fd5b50508035926020909101359150565b6000602082840312156116c057600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610578576105786116c7565b60006020828403121561171f57600080fd5b5051919050565b81810381811115610578576105786116c7565b80820180821115610578576105786116c7565b60006020828403121561175e57600080fd5b8151801515811461086357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000825160005b818110156117be57602081860181015185830152016117a4565b50600092019182525091905056fea26469706673582212208878d08444744ce78397e3e37bdcc9f59b74dff5f3044318441edc83ed285d4264736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e010ec500720be9ef3f82129e7ed2ee1fb7955f2000000000000000000000000d5970622b740a2ea5a5574616c193968b10e1297000000000000000000000000f4fbc617a5733eaaf9af08e1ab816b103388d8b60000000000000000000000006fa8c7a89b22bf3212392b778905b12f3dbaf5c4
-----Decoded View---------------
Arg [0] : _usdcAddress (address): 0xe010ec500720bE9EF3F82129E7eD2Ee1FB7955F2
Arg [1] : _holdingContract (address): 0xd5970622b740a2eA5A5574616c193968b10e1297
Arg [2] : _glowToken (address): 0xf4fbC617A5733EAAF9af08E1Ab816B103388d8B6
Arg [3] : _minerPoolAddress (address): 0x6Fa8C7a89b22bf3212392b778905B12f3dBAF5C4
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000e010ec500720be9ef3f82129e7ed2ee1fb7955f2
Arg [1] : 000000000000000000000000d5970622b740a2ea5a5574616c193968b10e1297
Arg [2] : 000000000000000000000000f4fbc617a5733eaaf9af08e1ab816b103388d8b6
Arg [3] : 0000000000000000000000006fa8c7a89b22bf3212392b778905b12f3dbaf5c4
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 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.