Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 1,197 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim Tokens Fro... | 2877718 | 20 secs ago | IN | 0 ETH | 0.00000635 | ||||
Approve | 2877563 | 3 mins ago | IN | 0 ETH | 0.00000434 | ||||
Claim Tokens Fro... | 2877505 | 4 mins ago | IN | 0 ETH | 0.00000542 | ||||
Claim Tokens Fro... | 2877052 | 11 mins ago | IN | 0 ETH | 0.00000625 | ||||
Claim Tokens Fro... | 2876710 | 17 mins ago | IN | 0 ETH | 0.00000702 | ||||
Approve | 2876074 | 28 mins ago | IN | 0 ETH | 0.00000478 | ||||
Claim Tokens Fro... | 2875434 | 39 mins ago | IN | 0 ETH | 0.00000556 | ||||
Claim Tokens Fro... | 2875353 | 40 mins ago | IN | 0 ETH | 0.00000703 | ||||
Approve | 2875106 | 44 mins ago | IN | 0 ETH | 0.00000506 | ||||
Approve | 2874427 | 56 mins ago | IN | 0 ETH | 0.00000476 | ||||
Approve | 2874134 | 1 hr ago | IN | 0 ETH | 0.00000478 | ||||
Approve | 2874089 | 1 hr ago | IN | 0 ETH | 0.00000475 | ||||
Approve | 2873589 | 1 hr ago | IN | 0 ETH | 0.00000475 | ||||
Approve | 2872582 | 1 hr ago | IN | 0 ETH | 0.00000435 | ||||
Approve | 2872556 | 1 hr ago | IN | 0 ETH | 0.00000435 | ||||
Transfer | 2872143 | 1 hr ago | IN | 0 ETH | 0.00000573 | ||||
Claim Tokens Fro... | 2871410 | 1 hr ago | IN | 0 ETH | 0.00000703 | ||||
Approve | 2870801 | 1 hr ago | IN | 0 ETH | 0.00000424 | ||||
Approve | 2870729 | 1 hr ago | IN | 0 ETH | 0.00000435 | ||||
Claim Tokens Fro... | 2870645 | 2 hrs ago | IN | 0 ETH | 0.0000039 | ||||
Claim Tokens Fro... | 2870641 | 2 hrs ago | IN | 0 ETH | 0.00000559 | ||||
Approve | 2870466 | 2 hrs ago | IN | 0 ETH | 0.00000494 | ||||
Approve | 2870443 | 2 hrs ago | IN | 0 ETH | 0.00000494 | ||||
Claim Tokens Fro... | 2870341 | 2 hrs ago | IN | 0 ETH | 0.00000579 | ||||
Claim Tokens Fro... | 2870291 | 2 hrs ago | IN | 0 ETH | 0.00000559 |
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
2861636 | 4 hrs ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
GameToken
Compiler Version
v0.8.28+commit.7893614a
ZkSolc Version
v1.5.11
Optimization Enabled:
Yes with Mode 3
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {FixedPointMathLib} from "../lib/solady/src/utils/FixedPointMathLib.sol"; import {ERC20} from "../lib/solady/src/tokens/ERC20.sol"; import {Game} from "./Game.sol"; contract GameToken is ERC20 { Game public immutable game; string private _name; string private _symbol; mapping(address => bool) public hasMinted; constructor(address _game, string memory name_, string memory symbol_) { game = Game(_game); _name = name_; _symbol = symbol_; // Mint initial supply (25%) to game contract for liquidity _mint(address(game), 250_000_000 ether); // Burn 50% of supply _mint( address(0x000000000000000000000000000000000000dEaD), 500_000_000 ether ); } function name() public view override returns (string memory) { return _name; } function symbol() public view override returns (string memory) { return _symbol; } function claimTokensFromGameParticipant(address participant) external { require(!hasMinted[participant], "Tokens already claimed"); // Mark as minted before the mint to prevent reentrancy hasMinted[participant] = true; // Get this participants share of the prize pool uint256 amountToMint = game.determineTokenDistribution(participant); // Mint new tokens to the participant _mint(participant, amountToMint); } function crackAnswer() external pure returns (string memory) { return "SIKE"; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) library FixedPointMathLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The operation failed, as the output exceeds the maximum value of uint256. error ExpOverflow(); /// @dev The operation failed, as the output exceeds the maximum value of uint256. error FactorialOverflow(); /// @dev The operation failed, due to an overflow. error RPowOverflow(); /// @dev The mantissa is too big to fit. error MantissaOverflow(); /// @dev The operation failed, due to an multiplication overflow. error MulWadFailed(); /// @dev The operation failed, due to an multiplication overflow. error SMulWadFailed(); /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero. error DivWadFailed(); /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero. error SDivWadFailed(); /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero. error MulDivFailed(); /// @dev The division failed, as the denominator is zero. error DivFailed(); /// @dev The full precision multiply-divide operation failed, either due /// to the result being larger than 256 bits, or a division by a zero. error FullMulDivFailed(); /// @dev The output is undefined, as the input is less-than-or-equal to zero. error LnWadUndefined(); /// @dev The input outside the acceptable domain. error OutOfDomain(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The scalar of ETH and most ERC20s. uint256 internal constant WAD = 1e18; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* SIMPLIFIED FIXED POINT OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to `(x * y) / WAD` rounded down. function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`. if gt(x, div(not(0), y)) { if y { mstore(0x00, 0xbac65e5b) // `MulWadFailed()`. revert(0x1c, 0x04) } } z := div(mul(x, y), WAD) } } /// @dev Equivalent to `(x * y) / WAD` rounded down. function sMulWad(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, y) // Equivalent to `require((x == 0 || z / x == y) && !(x == -1 && y == type(int256).min))`. if iszero(gt(or(iszero(x), eq(sdiv(z, x), y)), lt(not(x), eq(y, shl(255, 1))))) { mstore(0x00, 0xedcd4dd4) // `SMulWadFailed()`. revert(0x1c, 0x04) } z := sdiv(z, WAD) } } /// @dev Equivalent to `(x * y) / WAD` rounded down, but without overflow checks. function rawMulWad(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := div(mul(x, y), WAD) } } /// @dev Equivalent to `(x * y) / WAD` rounded down, but without overflow checks. function rawSMulWad(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := sdiv(mul(x, y), WAD) } } /// @dev Equivalent to `(x * y) / WAD` rounded up. function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, y) // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`. if iszero(eq(div(z, y), x)) { if y { mstore(0x00, 0xbac65e5b) // `MulWadFailed()`. revert(0x1c, 0x04) } } z := add(iszero(iszero(mod(z, WAD))), div(z, WAD)) } } /// @dev Equivalent to `(x * y) / WAD` rounded up, but without overflow checks. function rawMulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD)) } } /// @dev Equivalent to `(x * WAD) / y` rounded down. function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to `require(y != 0 && x <= type(uint256).max / WAD)`. if iszero(mul(y, lt(x, add(1, div(not(0), WAD))))) { mstore(0x00, 0x7c5f487d) // `DivWadFailed()`. revert(0x1c, 0x04) } z := div(mul(x, WAD), y) } } /// @dev Equivalent to `(x * WAD) / y` rounded down. function sDivWad(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, WAD) // Equivalent to `require(y != 0 && ((x * WAD) / WAD == x))`. if iszero(mul(y, eq(sdiv(z, WAD), x))) { mstore(0x00, 0x5c43740d) // `SDivWadFailed()`. revert(0x1c, 0x04) } z := sdiv(z, y) } } /// @dev Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks. function rawDivWad(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := div(mul(x, WAD), y) } } /// @dev Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks. function rawSDivWad(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := sdiv(mul(x, WAD), y) } } /// @dev Equivalent to `(x * WAD) / y` rounded up. function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to `require(y != 0 && x <= type(uint256).max / WAD)`. if iszero(mul(y, lt(x, add(1, div(not(0), WAD))))) { mstore(0x00, 0x7c5f487d) // `DivWadFailed()`. revert(0x1c, 0x04) } z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y)) } } /// @dev Equivalent to `(x * WAD) / y` rounded up, but without overflow and divide by zero checks. function rawDivWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y)) } } /// @dev Equivalent to `x` to the power of `y`. /// because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`. /// Note: This function is an approximation. function powWad(int256 x, int256 y) internal pure returns (int256) { // Using `ln(x)` means `x` must be greater than 0. return expWad((lnWad(x) * y) / int256(WAD)); } /// @dev Returns `exp(x)`, denominated in `WAD`. /// Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-ln /// Note: This function is an approximation. Monotonically increasing. function expWad(int256 x) internal pure returns (int256 r) { unchecked { // When the result is less than 0.5 we return zero. // This happens when `x <= (log(1e-18) * 1e18) ~ -4.15e19`. if (x <= -41446531673892822313) return r; /// @solidity memory-safe-assembly assembly { // When the result is greater than `(2**255 - 1) / 1e18` we can not represent it as // an int. This happens when `x >= floor(log((2**255 - 1) / 1e18) * 1e18) ≈ 135`. if iszero(slt(x, 135305999368893231589)) { mstore(0x00, 0xa37bfec9) // `ExpOverflow()`. revert(0x1c, 0x04) } } // `x` is now in the range `(-42, 136) * 1e18`. Convert to `(-42, 136) * 2**96` // for more intermediate precision and a binary basis. This base conversion // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78. x = (x << 78) / 5 ** 18; // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers // of two such that exp(x) = exp(x') * 2**k, where k is an integer. // Solving this gives k = round(x / log(2)) and x' = x - k * log(2). int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96; x = x - k * 54916777467707473351141471128; // `k` is in the range `[-61, 195]`. // Evaluate using a (6, 7)-term rational approximation. // `p` is made monic, we'll multiply by a scale factor later. int256 y = x + 1346386616545796478920950773328; y = ((y * x) >> 96) + 57155421227552351082224309758442; int256 p = y + x - 94201549194550492254356042504812; p = ((p * y) >> 96) + 28719021644029726153956944680412240; p = p * x + (4385272521454847904659076985693276 << 96); // We leave `p` in `2**192` basis so we don't need to scale it back up for the division. int256 q = x - 2855989394907223263936484059900; q = ((q * x) >> 96) + 50020603652535783019961831881945; q = ((q * x) >> 96) - 533845033583426703283633433725380; q = ((q * x) >> 96) + 3604857256930695427073651918091429; q = ((q * x) >> 96) - 14423608567350463180887372962807573; q = ((q * x) >> 96) + 26449188498355588339934803723976023; /// @solidity memory-safe-assembly assembly { // Div in assembly because solidity adds a zero check despite the unchecked. // The q polynomial won't have zeros in the domain as all its roots are complex. // No scaling is necessary because p is already `2**96` too large. r := sdiv(p, q) } // r should be in the range `(0.09, 0.25) * 2**96`. // We now need to multiply r by: // - The scale factor `s ≈ 6.031367120`. // - The `2**k` factor from the range reduction. // - The `1e18 / 2**96` factor for base conversion. // We do this all at once, with an intermediate result in `2**213` // basis, so the final right shift is always by a positive amount. r = int256( (uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k) ); } } /// @dev Returns `ln(x)`, denominated in `WAD`. /// Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-ln /// Note: This function is an approximation. Monotonically increasing. function lnWad(int256 x) internal pure returns (int256 r) { /// @solidity memory-safe-assembly assembly { // We want to convert `x` from `10**18` fixed point to `2**96` fixed point. // We do this by multiplying by `2**96 / 10**18`. But since // `ln(x * C) = ln(x) + ln(C)`, we can simply do nothing here // and add `ln(2**96 / 10**18)` at the end. // Compute `k = log2(x) - 96`, `r = 159 - k = 255 - log2(x) = 255 ^ log2(x)`. r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // We place the check here for more optimal stack operations. if iszero(sgt(x, 0)) { mstore(0x00, 0x1615e638) // `LnWadUndefined()`. revert(0x1c, 0x04) } // forgefmt: disable-next-item r := xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), 0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff)) // Reduce range of x to (1, 2) * 2**96 // ln(2^k * x) = k * ln(2) + ln(x) x := shr(159, shl(r, x)) // Evaluate using a (8, 8)-term rational approximation. // `p` is made monic, we will multiply by a scale factor later. // forgefmt: disable-next-item let p := sub( // This heavily nested expression is to avoid stack-too-deep for via-ir. sar(96, mul(add(43456485725739037958740375743393, sar(96, mul(add(24828157081833163892658089445524, sar(96, mul(add(3273285459638523848632254066296, x), x))), x))), x)), 11111509109440967052023855526967) p := sub(sar(96, mul(p, x)), 45023709667254063763336534515857) p := sub(sar(96, mul(p, x)), 14706773417378608786704636184526) p := sub(mul(p, x), shl(96, 795164235651350426258249787498)) // We leave `p` in `2**192` basis so we don't need to scale it back up for the division. // `q` is monic by convention. let q := add(5573035233440673466300451813936, x) q := add(71694874799317883764090561454958, sar(96, mul(x, q))) q := add(283447036172924575727196451306956, sar(96, mul(x, q))) q := add(401686690394027663651624208769553, sar(96, mul(x, q))) q := add(204048457590392012362485061816622, sar(96, mul(x, q))) q := add(31853899698501571402653359427138, sar(96, mul(x, q))) q := add(909429971244387300277376558375, sar(96, mul(x, q))) // `p / q` is in the range `(0, 0.125) * 2**96`. // Finalization, we need to: // - Multiply by the scale factor `s = 5.549…`. // - Add `ln(2**96 / 10**18)`. // - Add `k * ln(2)`. // - Multiply by `10**18 / 2**96 = 5**18 >> 78`. // The q polynomial is known not to have zeros in the domain. // No scaling required because p is already `2**96` too large. p := sdiv(p, q) // Multiply by the scaling factor: `s * 5**18 * 2**96`, base is now `5**18 * 2**192`. p := mul(1677202110996718588342820967067443963516166, p) // Add `ln(2) * k * 5**18 * 2**192`. // forgefmt: disable-next-item p := add(mul(16597577552685614221487285958193947469193820559219878177908093499208371, sub(159, r)), p) // Add `ln(2**96 / 10**18) * 5**18 * 2**192`. p := add(600920179829731861736702779321621459595472258049074101567377883020018308, p) // Base conversion: mul `2**18 / 2**192`. r := sar(174, p) } } /// @dev Returns `W_0(x)`, denominated in `WAD`. /// See: https://en.wikipedia.org/wiki/Lambert_W_function /// a.k.a. Product log function. This is an approximation of the principal branch. /// Note: This function is an approximation. Monotonically increasing. function lambertW0Wad(int256 x) internal pure returns (int256 w) { // forgefmt: disable-next-item unchecked { if ((w = x) <= -367879441171442322) revert OutOfDomain(); // `x` less than `-1/e`. (int256 wad, int256 p) = (int256(WAD), x); uint256 c; // Whether we need to avoid catastrophic cancellation. uint256 i = 4; // Number of iterations. if (w <= 0x1ffffffffffff) { if (-0x4000000000000 <= w) { i = 1; // Inputs near zero only take one step to converge. } else if (w <= -0x3ffffffffffffff) { i = 32; // Inputs near `-1/e` take very long to converge. } } else if (uint256(w >> 63) == uint256(0)) { /// @solidity memory-safe-assembly assembly { // Inline log2 for more performance, since the range is small. let v := shr(49, w) let l := shl(3, lt(0xff, v)) l := add(or(l, byte(and(0x1f, shr(shr(l, v), 0x8421084210842108cc6318c6db6d54be)), 0x0706060506020504060203020504030106050205030304010505030400000000)), 49) w := sdiv(shl(l, 7), byte(sub(l, 31), 0x0303030303030303040506080c13)) c := gt(l, 60) i := add(2, add(gt(l, 53), c)) } } else { int256 ll = lnWad(w = lnWad(w)); /// @solidity memory-safe-assembly assembly { // `w = ln(x) - ln(ln(x)) + b * ln(ln(x)) / ln(x)`. w := add(sdiv(mul(ll, 1023715080943847266), w), sub(w, ll)) i := add(3, iszero(shr(68, x))) c := iszero(shr(143, x)) } if (c == uint256(0)) { do { // If `x` is big, use Newton's so that intermediate values won't overflow. int256 e = expWad(w); /// @solidity memory-safe-assembly assembly { let t := mul(w, div(e, wad)) w := sub(w, sdiv(sub(t, x), div(add(e, t), wad))) } if (p <= w) break; p = w; } while (--i != uint256(0)); /// @solidity memory-safe-assembly assembly { w := sub(w, sgt(w, 2)) } return w; } } do { // Otherwise, use Halley's for faster convergence. int256 e = expWad(w); /// @solidity memory-safe-assembly assembly { let t := add(w, wad) let s := sub(mul(w, e), mul(x, wad)) w := sub(w, sdiv(mul(s, wad), sub(mul(e, t), sdiv(mul(add(t, wad), s), add(t, t))))) } if (p <= w) break; p = w; } while (--i != c); /// @solidity memory-safe-assembly assembly { w := sub(w, sgt(w, 2)) } // For certain ranges of `x`, we'll use the quadratic-rate recursive formula of // R. Iacono and J.P. Boyd for the last iteration, to avoid catastrophic cancellation. if (c == uint256(0)) return w; int256 t = w | 1; /// @solidity memory-safe-assembly assembly { x := sdiv(mul(x, wad), t) } x = (t * (wad + lnWad(x))); /// @solidity memory-safe-assembly assembly { w := sdiv(x, add(wad, t)) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* GENERAL NUMBER UTILITIES */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns `a * b == x * y`, with full precision. function fullMulEq(uint256 a, uint256 b, uint256 x, uint256 y) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := and(eq(mul(a, b), mul(x, y)), eq(mulmod(x, y, not(0)), mulmod(a, b, not(0)))) } } /// @dev Calculates `floor(x * y / d)` with full precision. /// Throws if result overflows a uint256 or when `d` is zero. /// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // 512-bit multiply `[p1 p0] = x * y`. // Compute the product mod `2**256` and mod `2**256 - 1` // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that `product = p1 * 2**256 + p0`. // Temporarily use `z` as `p0` to save gas. z := mul(x, y) // Lower 256 bits of `x * y`. for {} 1 {} { // If overflows. if iszero(mul(or(iszero(x), eq(div(z, x), y)), d)) { let mm := mulmod(x, y, not(0)) let p1 := sub(mm, add(z, lt(mm, z))) // Upper 256 bits of `x * y`. /*------------------- 512 by 256 division --------------------*/ // Make division exact by subtracting the remainder from `[p1 p0]`. let r := mulmod(x, y, d) // Compute remainder using mulmod. let t := and(d, sub(0, d)) // The least significant bit of `d`. `t >= 1`. // Make sure `z` is less than `2**256`. Also prevents `d == 0`. // Placing the check here seems to give more optimal stack operations. if iszero(gt(d, p1)) { mstore(0x00, 0xae47f702) // `FullMulDivFailed()`. revert(0x1c, 0x04) } d := div(d, t) // Divide `d` by `t`, which is a power of two. // Invert `d mod 2**256` // Now that `d` is an odd number, it has an inverse // modulo `2**256` such that `d * inv = 1 mod 2**256`. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, `d * inv = 1 mod 2**4`. let inv := xor(2, mul(3, d)) // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128 z := mul( // Divide [p1 p0] by the factors of two. // Shift in bits from `p1` into `p0`. For this we need // to flip `t` such that it is `2**256 / t`. or(mul(sub(p1, gt(r, z)), add(div(sub(0, t), t), 1)), div(sub(z, r), t)), mul(sub(2, mul(d, inv)), inv) // inverse mod 2**256 ) break } z := div(z, d) break } } } /// @dev Calculates `floor(x * y / d)` with full precision. /// Behavior is undefined if `d` is zero or the final result cannot fit in 256 bits. /// Performs the full 512 bit calculation regardless. function fullMulDivUnchecked(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, y) let mm := mulmod(x, y, not(0)) let p1 := sub(mm, add(z, lt(mm, z))) let t := and(d, sub(0, d)) let r := mulmod(x, y, d) d := div(d, t) let inv := xor(2, mul(3, d)) inv := mul(inv, sub(2, mul(d, inv))) inv := mul(inv, sub(2, mul(d, inv))) inv := mul(inv, sub(2, mul(d, inv))) inv := mul(inv, sub(2, mul(d, inv))) inv := mul(inv, sub(2, mul(d, inv))) z := mul( or(mul(sub(p1, gt(r, z)), add(div(sub(0, t), t), 1)), div(sub(z, r), t)), mul(sub(2, mul(d, inv)), inv) ) } } /// @dev Calculates `floor(x * y / d)` with full precision, rounded up. /// Throws if result overflows a uint256 or when `d` is zero. /// Credit to Uniswap-v3-core under MIT license: /// https://github.com/Uniswap/v3-core/blob/main/contracts/libraries/FullMath.sol function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { z = fullMulDiv(x, y, d); /// @solidity memory-safe-assembly assembly { if mulmod(x, y, d) { z := add(z, 1) if iszero(z) { mstore(0x00, 0xae47f702) // `FullMulDivFailed()`. revert(0x1c, 0x04) } } } } /// @dev Calculates `floor(x * y / 2 ** n)` with full precision. /// Throws if result overflows a uint256. /// Credit to Philogy under MIT license: /// https://github.com/SorellaLabs/angstrom/blob/main/contracts/src/libraries/X128MathLib.sol function fullMulDivN(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Temporarily use `z` as `p0` to save gas. z := mul(x, y) // Lower 256 bits of `x * y`. We'll call this `z`. for {} 1 {} { if iszero(or(iszero(x), eq(div(z, x), y))) { let k := and(n, 0xff) // `n`, cleaned. let mm := mulmod(x, y, not(0)) let p1 := sub(mm, add(z, lt(mm, z))) // Upper 256 bits of `x * y`. // | p1 | z | // Before: | p1_0 ¦ p1_1 | z_0 ¦ z_1 | // Final: | 0 ¦ p1_0 | p1_1 ¦ z_0 | // Check that final `z` doesn't overflow by checking that p1_0 = 0. if iszero(shr(k, p1)) { z := add(shl(sub(256, k), p1), shr(k, z)) break } mstore(0x00, 0xae47f702) // `FullMulDivFailed()`. revert(0x1c, 0x04) } z := shr(and(n, 0xff), z) break } } } /// @dev Returns `floor(x * y / d)`. /// Reverts if `x * y` overflows, or `d` is zero. function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, y) // Equivalent to `require(d != 0 && (y == 0 || x <= type(uint256).max / y))`. if iszero(mul(or(iszero(x), eq(div(z, x), y)), d)) { mstore(0x00, 0xad251c27) // `MulDivFailed()`. revert(0x1c, 0x04) } z := div(z, d) } } /// @dev Returns `ceil(x * y / d)`. /// Reverts if `x * y` overflows, or `d` is zero. function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, y) // Equivalent to `require(d != 0 && (y == 0 || x <= type(uint256).max / y))`. if iszero(mul(or(iszero(x), eq(div(z, x), y)), d)) { mstore(0x00, 0xad251c27) // `MulDivFailed()`. revert(0x1c, 0x04) } z := add(iszero(iszero(mod(z, d))), div(z, d)) } } /// @dev Returns `x`, the modular multiplicative inverse of `a`, such that `(a * x) % n == 1`. function invMod(uint256 a, uint256 n) internal pure returns (uint256 x) { /// @solidity memory-safe-assembly assembly { let g := n let r := mod(a, n) for { let y := 1 } 1 {} { let q := div(g, r) let t := g g := r r := sub(t, mul(r, q)) let u := x x := y y := sub(u, mul(y, q)) if iszero(r) { break } } x := mul(eq(g, 1), add(x, mul(slt(x, 0), n))) } } /// @dev Returns `ceil(x / d)`. /// Reverts if `d` is zero. function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { if iszero(d) { mstore(0x00, 0x65244e4e) // `DivFailed()`. revert(0x1c, 0x04) } z := add(iszero(iszero(mod(x, d))), div(x, d)) } } /// @dev Returns `max(0, x - y)`. Alias for `saturatingSub`. function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(gt(x, y), sub(x, y)) } } /// @dev Returns `max(0, x - y)`. function saturatingSub(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(gt(x, y), sub(x, y)) } } /// @dev Returns `min(2 ** 256 - 1, x + y)`. function saturatingAdd(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := or(sub(0, lt(add(x, y), x)), add(x, y)) } } /// @dev Returns `min(2 ** 256 - 1, x * y)`. function saturatingMul(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := or(sub(or(iszero(x), eq(div(mul(x, y), x), y)), 1), mul(x, y)) } } /// @dev Returns `condition ? x : y`, without branching. function ternary(bool condition, uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), iszero(condition))) } } /// @dev Returns `condition ? x : y`, without branching. function ternary(bool condition, bytes32 x, bytes32 y) internal pure returns (bytes32 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), iszero(condition))) } } /// @dev Returns `condition ? x : y`, without branching. function ternary(bool condition, address x, address y) internal pure returns (address z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), iszero(condition))) } } /// @dev Exponentiate `x` to `y` by squaring, denominated in base `b`. /// Reverts if the computation overflows. function rpow(uint256 x, uint256 y, uint256 b) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(b, iszero(y)) // `0 ** 0 = 1`. Otherwise, `0 ** n = 0`. if x { z := xor(b, mul(xor(b, x), and(y, 1))) // `z = isEven(y) ? scale : x` let half := shr(1, b) // Divide `b` by 2. // Divide `y` by 2 every iteration. for { y := shr(1, y) } y { y := shr(1, y) } { let xx := mul(x, x) // Store x squared. let xxRound := add(xx, half) // Round to the nearest number. // Revert if `xx + half` overflowed, or if `x ** 2` overflows. if or(lt(xxRound, xx), shr(128, x)) { mstore(0x00, 0x49f7642b) // `RPowOverflow()`. revert(0x1c, 0x04) } x := div(xxRound, b) // Set `x` to scaled `xxRound`. // If `y` is odd: if and(y, 1) { let zx := mul(z, x) // Compute `z * x`. let zxRound := add(zx, half) // Round to the nearest number. // If `z * x` overflowed or `zx + half` overflowed: if or(xor(div(zx, x), z), lt(zxRound, zx)) { // Revert if `x` is non-zero. if x { mstore(0x00, 0x49f7642b) // `RPowOverflow()`. revert(0x1c, 0x04) } } z := div(zxRound, b) // Return properly scaled `zxRound`. } } } } } /// @dev Returns the square root of `x`, rounded down. function sqrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // Let `y = x / 2**r`. We check `y >= 2**(k + 8)` // but shift right by `k` bits to ensure that if `x >= 256`, then `y >= 256`. let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffffff, shr(r, x)))) z := shl(shr(1, r), z) // Goal was to get `z*z*y` within a small factor of `x`. More iterations could // get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`. // We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small. // That's not possible if `x < 256` but we can just verify those cases exhaustively. // Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`. // Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`. // Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps. // For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)` // is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`, // with largest error when `s = 1` and when `s = 256` or `1/256`. // Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`. // Then we can estimate `sqrt(y)` using // `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`. // There is no overflow risk here since `y < 2**136` after the first branch above. z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If `x+1` is a perfect square, the Babylonian method cycles between // `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division z := sub(z, lt(div(x, z), z)) } } /// @dev Returns the cube root of `x`, rounded down. /// Credit to bout3fiddy and pcaversaccio under AGPLv3 license: /// https://github.com/pcaversaccio/snekmate/blob/main/src/utils/Math.vy /// Formally verified by xuwinnie: /// https://github.com/vectorized/solady/blob/main/audits/xuwinnie-solady-cbrt-proof.pdf function cbrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { let r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // Makeshift lookup table to nudge the approximate log2 result. z := div(shl(div(r, 3), shl(lt(0xf, shr(r, x)), 0xf)), xor(7, mod(r, 3))) // Newton-Raphson's. z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) // Round down. z := sub(z, lt(div(x, mul(z, z)), z)) } } /// @dev Returns the square root of `x`, denominated in `WAD`, rounded down. function sqrtWad(uint256 x) internal pure returns (uint256 z) { unchecked { if (x <= type(uint256).max / 10 ** 18) return sqrt(x * 10 ** 18); z = (1 + sqrt(x)) * 10 ** 9; z = (fullMulDivUnchecked(x, 10 ** 18, z) + z) >> 1; } /// @solidity memory-safe-assembly assembly { z := sub(z, gt(999999999999999999, sub(mulmod(z, z, x), 1))) // Round down. } } /// @dev Returns the cube root of `x`, denominated in `WAD`, rounded down. /// Formally verified by xuwinnie: /// https://github.com/vectorized/solady/blob/main/audits/xuwinnie-solady-cbrt-proof.pdf function cbrtWad(uint256 x) internal pure returns (uint256 z) { unchecked { if (x <= type(uint256).max / 10 ** 36) return cbrt(x * 10 ** 36); z = (1 + cbrt(x)) * 10 ** 12; z = (fullMulDivUnchecked(x, 10 ** 36, z * z) + z + z) / 3; } /// @solidity memory-safe-assembly assembly { let p := x for {} 1 {} { if iszero(shr(229, p)) { if iszero(shr(199, p)) { p := mul(p, 100000000000000000) // 10 ** 17. break } p := mul(p, 100000000) // 10 ** 8. break } if iszero(shr(249, p)) { p := mul(p, 100) } break } let t := mulmod(mul(z, z), z, p) z := sub(z, gt(lt(t, shr(1, p)), iszero(t))) // Round down. } } /// @dev Returns the factorial of `x`. function factorial(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := 1 if iszero(lt(x, 58)) { mstore(0x00, 0xaba0f2a2) // `FactorialOverflow()`. revert(0x1c, 0x04) } for {} x { x := sub(x, 1) } { z := mul(z, x) } } } /// @dev Returns the log2 of `x`. /// Equivalent to computing the index of the most significant bit (MSB) of `x`. /// Returns 0 if `x` is zero. function log2(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), 0x0706060506020504060203020504030106050205030304010505030400000000)) } } /// @dev Returns the log2 of `x`, rounded up. /// Returns 0 if `x` is zero. function log2Up(uint256 x) internal pure returns (uint256 r) { r = log2(x); /// @solidity memory-safe-assembly assembly { r := add(r, lt(shl(r, 1), x)) } } /// @dev Returns the log10 of `x`. /// Returns 0 if `x` is zero. function log10(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { if iszero(lt(x, 100000000000000000000000000000000000000)) { x := div(x, 100000000000000000000000000000000000000) r := 38 } if iszero(lt(x, 100000000000000000000)) { x := div(x, 100000000000000000000) r := add(r, 20) } if iszero(lt(x, 10000000000)) { x := div(x, 10000000000) r := add(r, 10) } if iszero(lt(x, 100000)) { x := div(x, 100000) r := add(r, 5) } r := add(r, add(gt(x, 9), add(gt(x, 99), add(gt(x, 999), gt(x, 9999))))) } } /// @dev Returns the log10 of `x`, rounded up. /// Returns 0 if `x` is zero. function log10Up(uint256 x) internal pure returns (uint256 r) { r = log10(x); /// @solidity memory-safe-assembly assembly { r := add(r, lt(exp(10, r), x)) } } /// @dev Returns the log256 of `x`. /// Returns 0 if `x` is zero. function log256(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(shr(3, r), lt(0xff, shr(r, x))) } } /// @dev Returns the log256 of `x`, rounded up. /// Returns 0 if `x` is zero. function log256Up(uint256 x) internal pure returns (uint256 r) { r = log256(x); /// @solidity memory-safe-assembly assembly { r := add(r, lt(shl(shl(3, r), 1), x)) } } /// @dev Returns the scientific notation format `mantissa * 10 ** exponent` of `x`. /// Useful for compressing prices (e.g. using 25 bit mantissa and 7 bit exponent). function sci(uint256 x) internal pure returns (uint256 mantissa, uint256 exponent) { /// @solidity memory-safe-assembly assembly { mantissa := x if mantissa { if iszero(mod(mantissa, 1000000000000000000000000000000000)) { mantissa := div(mantissa, 1000000000000000000000000000000000) exponent := 33 } if iszero(mod(mantissa, 10000000000000000000)) { mantissa := div(mantissa, 10000000000000000000) exponent := add(exponent, 19) } if iszero(mod(mantissa, 1000000000000)) { mantissa := div(mantissa, 1000000000000) exponent := add(exponent, 12) } if iszero(mod(mantissa, 1000000)) { mantissa := div(mantissa, 1000000) exponent := add(exponent, 6) } if iszero(mod(mantissa, 10000)) { mantissa := div(mantissa, 10000) exponent := add(exponent, 4) } if iszero(mod(mantissa, 100)) { mantissa := div(mantissa, 100) exponent := add(exponent, 2) } if iszero(mod(mantissa, 10)) { mantissa := div(mantissa, 10) exponent := add(exponent, 1) } } } } /// @dev Convenience function for packing `x` into a smaller number using `sci`. /// The `mantissa` will be in bits [7..255] (the upper 249 bits). /// The `exponent` will be in bits [0..6] (the lower 7 bits). /// Use `SafeCastLib` to safely ensure that the `packed` number is small /// enough to fit in the desired unsigned integer type: /// ``` /// uint32 packed = SafeCastLib.toUint32(FixedPointMathLib.packSci(777 ether)); /// ``` function packSci(uint256 x) internal pure returns (uint256 packed) { (x, packed) = sci(x); // Reuse for `mantissa` and `exponent`. /// @solidity memory-safe-assembly assembly { if shr(249, x) { mstore(0x00, 0xce30380c) // `MantissaOverflow()`. revert(0x1c, 0x04) } packed := or(shl(7, x), packed) } } /// @dev Convenience function for unpacking a packed number from `packSci`. function unpackSci(uint256 packed) internal pure returns (uint256 unpacked) { unchecked { unpacked = (packed >> 7) * 10 ** (packed & 0x7f); } } /// @dev Returns the average of `x` and `y`. Rounds towards zero. function avg(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = (x & y) + ((x ^ y) >> 1); } } /// @dev Returns the average of `x` and `y`. Rounds towards negative infinity. function avg(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = (x >> 1) + (y >> 1) + (x & y & 1); } } /// @dev Returns the absolute value of `x`. function abs(int256 x) internal pure returns (uint256 z) { unchecked { z = (uint256(x) + uint256(x >> 255)) ^ uint256(x >> 255); } } /// @dev Returns the absolute distance between `x` and `y`. function dist(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := add(xor(sub(0, gt(x, y)), sub(y, x)), gt(x, y)) } } /// @dev Returns the absolute distance between `x` and `y`. function dist(int256 x, int256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := add(xor(sub(0, sgt(x, y)), sub(y, x)), sgt(x, y)) } } /// @dev Returns the minimum of `x` and `y`. function min(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), lt(y, x))) } } /// @dev Returns the minimum of `x` and `y`. function min(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), slt(y, x))) } } /// @dev Returns the maximum of `x` and `y`. function max(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), gt(y, x))) } } /// @dev Returns the maximum of `x` and `y`. function max(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), sgt(y, x))) } } /// @dev Returns `x`, bounded to `minValue` and `maxValue`. function clamp(uint256 x, uint256 minValue, uint256 maxValue) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, minValue), gt(minValue, x))) z := xor(z, mul(xor(z, maxValue), lt(maxValue, z))) } } /// @dev Returns `x`, bounded to `minValue` and `maxValue`. function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, minValue), sgt(minValue, x))) z := xor(z, mul(xor(z, maxValue), slt(maxValue, z))) } } /// @dev Returns greatest common divisor of `x` and `y`. function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { for { z := x } y {} { let t := y y := mod(z, y) z := t } } } /// @dev Returns `a + (b - a) * (t - begin) / (end - begin)`, /// with `t` clamped between `begin` and `end` (inclusive). /// Agnostic to the order of (`a`, `b`) and (`end`, `begin`). /// If `begins == end`, returns `t <= begin ? a : b`. function lerp(uint256 a, uint256 b, uint256 t, uint256 begin, uint256 end) internal pure returns (uint256) { if (begin > end) (t, begin, end) = (~t, ~begin, ~end); if (t <= begin) return a; if (t >= end) return b; unchecked { if (b >= a) return a + fullMulDiv(b - a, t - begin, end - begin); return a - fullMulDiv(a - b, t - begin, end - begin); } } /// @dev Returns `a + (b - a) * (t - begin) / (end - begin)`. /// with `t` clamped between `begin` and `end` (inclusive). /// Agnostic to the order of (`a`, `b`) and (`end`, `begin`). /// If `begins == end`, returns `t <= begin ? a : b`. function lerp(int256 a, int256 b, int256 t, int256 begin, int256 end) internal pure returns (int256) { if (begin > end) (t, begin, end) = (~t, ~begin, ~end); if (t <= begin) return a; if (t >= end) return b; // forgefmt: disable-next-item unchecked { if (b >= a) return int256(uint256(a) + fullMulDiv(uint256(b - a), uint256(t - begin), uint256(end - begin))); return int256(uint256(a) - fullMulDiv(uint256(a - b), uint256(t - begin), uint256(end - begin))); } } /// @dev Returns if `x` is an even number. Some people may need this. function isEven(uint256 x) internal pure returns (bool) { return x & uint256(1) == uint256(0); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RAW NUMBER OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns `x + y`, without checking for overflow. function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = x + y; } } /// @dev Returns `x + y`, without checking for overflow. function rawAdd(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = x + y; } } /// @dev Returns `x - y`, without checking for underflow. function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = x - y; } } /// @dev Returns `x - y`, without checking for underflow. function rawSub(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = x - y; } } /// @dev Returns `x * y`, without checking for overflow. function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = x * y; } } /// @dev Returns `x * y`, without checking for overflow. function rawMul(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = x * y; } } /// @dev Returns `x / y`, returning 0 if `y` is zero. function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := div(x, y) } } /// @dev Returns `x / y`, returning 0 if `y` is zero. function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := sdiv(x, y) } } /// @dev Returns `x % y`, returning 0 if `y` is zero. function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mod(x, y) } } /// @dev Returns `x % y`, returning 0 if `y` is zero. function rawSMod(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := smod(x, y) } } /// @dev Returns `(x + y) % d`, return 0 if `d` if zero. function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := addmod(x, y, d) } } /// @dev Returns `(x * y) % d`, return 0 if `d` if zero. function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mulmod(x, y, d) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple ERC20 + EIP-2612 implementation. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol) /// /// @dev Note: /// - The ERC20 standard allows minting and transferring to and from the zero address, /// minting and transferring zero tokens, as well as self-approvals. /// For performance, this implementation WILL NOT revert for such actions. /// Please add any checks with overrides if desired. /// - The `permit` function uses the ecrecover precompile (0x1). /// /// If you are overriding: /// - NEVER violate the ERC20 invariant: /// the total sum of all balances must be equal to `totalSupply()`. /// - Check that the overridden function is actually used in the function you want to /// change the behavior of. Much of the code has been manually inlined for performance. abstract contract ERC20 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The total supply has overflowed. error TotalSupplyOverflow(); /// @dev The allowance has overflowed. error AllowanceOverflow(); /// @dev The allowance has underflowed. error AllowanceUnderflow(); /// @dev Insufficient balance. error InsufficientBalance(); /// @dev Insufficient allowance. error InsufficientAllowance(); /// @dev The permit is invalid. error InvalidPermit(); /// @dev The permit has expired. error PermitExpired(); /// @dev The allowance of Permit2 is fixed at infinity. error Permit2AllowanceIsFixedAtInfinity(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Emitted when `amount` tokens is transferred from `from` to `to`. event Transfer(address indexed from, address indexed to, uint256 amount); /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`. event Approval(address indexed owner, address indexed spender, uint256 amount); /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`. uint256 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`. uint256 private constant _APPROVAL_EVENT_SIGNATURE = 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The storage slot for the total supply. uint256 private constant _TOTAL_SUPPLY_SLOT = 0x05345cdf77eb68f44c; /// @dev The balance slot of `owner` is given by: /// ``` /// mstore(0x0c, _BALANCE_SLOT_SEED) /// mstore(0x00, owner) /// let balanceSlot := keccak256(0x0c, 0x20) /// ``` uint256 private constant _BALANCE_SLOT_SEED = 0x87a211a2; /// @dev The allowance slot of (`owner`, `spender`) is given by: /// ``` /// mstore(0x20, spender) /// mstore(0x0c, _ALLOWANCE_SLOT_SEED) /// mstore(0x00, owner) /// let allowanceSlot := keccak256(0x0c, 0x34) /// ``` uint256 private constant _ALLOWANCE_SLOT_SEED = 0x7f5e9f20; /// @dev The nonce slot of `owner` is given by: /// ``` /// mstore(0x0c, _NONCES_SLOT_SEED) /// mstore(0x00, owner) /// let nonceSlot := keccak256(0x0c, 0x20) /// ``` uint256 private constant _NONCES_SLOT_SEED = 0x38377508; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev `(_NONCES_SLOT_SEED << 16) | 0x1901`. uint256 private constant _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX = 0x383775081901; /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`. bytes32 private constant _DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; /// @dev `keccak256("1")`. /// If you need to use a different version, override `_versionHash`. bytes32 private constant _DEFAULT_VERSION_HASH = 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6; /// @dev `keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")`. bytes32 private constant _PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; /// @dev The canonical Permit2 address. /// For signature-based allowance granting for single transaction ERC20 `transferFrom`. /// To enable, override `_givePermit2InfiniteAllowance()`. /// [Github](https://github.com/Uniswap/permit2) /// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) address internal constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 METADATA */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the name of the token. function name() public view virtual returns (string memory); /// @dev Returns the symbol of the token. function symbol() public view virtual returns (string memory); /// @dev Returns the decimals places of the token. function decimals() public view virtual returns (uint8) { return 18; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the amount of tokens in existence. function totalSupply() public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { result := sload(_TOTAL_SUPPLY_SLOT) } } /// @dev Returns the amount of tokens owned by `owner`. function balanceOf(address owner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, owner) result := sload(keccak256(0x0c, 0x20)) } } /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`. function allowance(address owner, address spender) public view virtual returns (uint256 result) { if (_givePermit2InfiniteAllowance()) { if (spender == _PERMIT2) return type(uint256).max; } /// @solidity memory-safe-assembly assembly { mstore(0x20, spender) mstore(0x0c, _ALLOWANCE_SLOT_SEED) mstore(0x00, owner) result := sload(keccak256(0x0c, 0x34)) } } /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens. /// /// Emits a {Approval} event. function approve(address spender, uint256 amount) public virtual returns (bool) { if (_givePermit2InfiniteAllowance()) { /// @solidity memory-safe-assembly assembly { // If `spender == _PERMIT2 && amount != type(uint256).max`. if iszero(or(xor(shr(96, shl(96, spender)), _PERMIT2), iszero(not(amount)))) { mstore(0x00, 0x3f68539a) // `Permit2AllowanceIsFixedAtInfinity()`. revert(0x1c, 0x04) } } } /// @solidity memory-safe-assembly assembly { // Compute the allowance slot and store the amount. mstore(0x20, spender) mstore(0x0c, _ALLOWANCE_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x34), amount) // Emit the {Approval} event. mstore(0x00, amount) log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c))) } return true; } /// @dev Transfer `amount` tokens from the caller to `to`. /// /// Requirements: /// - `from` must at least have `amount`. /// /// Emits a {Transfer} event. function transfer(address to, uint256 amount) public virtual returns (bool) { _beforeTokenTransfer(msg.sender, to, amount); /// @solidity memory-safe-assembly assembly { // Compute the balance slot and load its value. mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, caller()) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Compute the balance slot of `to`. mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance of `to`. // Will not overflow because the sum of all user balances // cannot exceed the maximum uint256 value. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, caller(), shr(96, mload(0x0c))) } _afterTokenTransfer(msg.sender, to, amount); return true; } /// @dev Transfers `amount` tokens from `from` to `to`. /// /// Note: Does not update the allowance if it is the maximum uint256 value. /// /// Requirements: /// - `from` must at least have `amount`. /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`. /// /// Emits a {Transfer} event. function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) { _beforeTokenTransfer(from, to, amount); // Code duplication is for zero-cost abstraction if possible. if (_givePermit2InfiniteAllowance()) { /// @solidity memory-safe-assembly assembly { let from_ := shl(96, from) if iszero(eq(caller(), _PERMIT2)) { // Compute the allowance slot and load its value. mstore(0x20, caller()) mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED)) let allowanceSlot := keccak256(0x0c, 0x34) let allowance_ := sload(allowanceSlot) // If the allowance is not the maximum uint256 value. if not(allowance_) { // Revert if the amount to be transferred exceeds the allowance. if gt(amount, allowance_) { mstore(0x00, 0x13be252b) // `InsufficientAllowance()`. revert(0x1c, 0x04) } // Subtract and store the updated allowance. sstore(allowanceSlot, sub(allowance_, amount)) } } // Compute the balance slot and load its value. mstore(0x0c, or(from_, _BALANCE_SLOT_SEED)) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Compute the balance slot of `to`. mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance of `to`. // Will not overflow because the sum of all user balances // cannot exceed the maximum uint256 value. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c))) } } else { /// @solidity memory-safe-assembly assembly { let from_ := shl(96, from) // Compute the allowance slot and load its value. mstore(0x20, caller()) mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED)) let allowanceSlot := keccak256(0x0c, 0x34) let allowance_ := sload(allowanceSlot) // If the allowance is not the maximum uint256 value. if not(allowance_) { // Revert if the amount to be transferred exceeds the allowance. if gt(amount, allowance_) { mstore(0x00, 0x13be252b) // `InsufficientAllowance()`. revert(0x1c, 0x04) } // Subtract and store the updated allowance. sstore(allowanceSlot, sub(allowance_, amount)) } // Compute the balance slot and load its value. mstore(0x0c, or(from_, _BALANCE_SLOT_SEED)) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Compute the balance slot of `to`. mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance of `to`. // Will not overflow because the sum of all user balances // cannot exceed the maximum uint256 value. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c))) } } _afterTokenTransfer(from, to, amount); return true; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EIP-2612 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev For more performance, override to return the constant value /// of `keccak256(bytes(name()))` if `name()` will never change. function _constantNameHash() internal view virtual returns (bytes32 result) {} /// @dev If you need a different value, override this function. function _versionHash() internal view virtual returns (bytes32 result) { result = _DEFAULT_VERSION_HASH; } /// @dev For inheriting contracts to increment the nonce. function _incrementNonce(address owner) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _NONCES_SLOT_SEED) mstore(0x00, owner) let nonceSlot := keccak256(0x0c, 0x20) sstore(nonceSlot, add(1, sload(nonceSlot))) } } /// @dev Returns the current nonce for `owner`. /// This value is used to compute the signature for EIP-2612 permit. function nonces(address owner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the nonce slot and load its value. mstore(0x0c, _NONCES_SLOT_SEED) mstore(0x00, owner) result := sload(keccak256(0x0c, 0x20)) } } /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`, /// authorized by a signed approval by `owner`. /// /// Emits a {Approval} event. function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { if (_givePermit2InfiniteAllowance()) { /// @solidity memory-safe-assembly assembly { // If `spender == _PERMIT2 && value != type(uint256).max`. if iszero(or(xor(shr(96, shl(96, spender)), _PERMIT2), iszero(not(value)))) { mstore(0x00, 0x3f68539a) // `Permit2AllowanceIsFixedAtInfinity()`. revert(0x1c, 0x04) } } } bytes32 nameHash = _constantNameHash(); // We simply calculate it on-the-fly to allow for cases where the `name` may change. if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name())); bytes32 versionHash = _versionHash(); /// @solidity memory-safe-assembly assembly { // Revert if the block timestamp is greater than `deadline`. if gt(timestamp(), deadline) { mstore(0x00, 0x1a15a3cc) // `PermitExpired()`. revert(0x1c, 0x04) } let m := mload(0x40) // Grab the free memory pointer. // Clean the upper 96 bits. owner := shr(96, shl(96, owner)) spender := shr(96, shl(96, spender)) // Compute the nonce slot and load its value. mstore(0x0e, _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX) mstore(0x00, owner) let nonceSlot := keccak256(0x0c, 0x20) let nonceValue := sload(nonceSlot) // Prepare the domain separator. mstore(m, _DOMAIN_TYPEHASH) mstore(add(m, 0x20), nameHash) mstore(add(m, 0x40), versionHash) mstore(add(m, 0x60), chainid()) mstore(add(m, 0x80), address()) mstore(0x2e, keccak256(m, 0xa0)) // Prepare the struct hash. mstore(m, _PERMIT_TYPEHASH) mstore(add(m, 0x20), owner) mstore(add(m, 0x40), spender) mstore(add(m, 0x60), value) mstore(add(m, 0x80), nonceValue) mstore(add(m, 0xa0), deadline) mstore(0x4e, keccak256(m, 0xc0)) // Prepare the ecrecover calldata. mstore(0x00, keccak256(0x2c, 0x42)) mstore(0x20, and(0xff, v)) mstore(0x40, r) mstore(0x60, s) let t := staticcall(gas(), 1, 0x00, 0x80, 0x20, 0x20) // If the ecrecover fails, the returndatasize will be 0x00, // `owner` will be checked if it equals the hash at 0x00, // which evaluates to false (i.e. 0), and we will revert. // If the ecrecover succeeds, the returndatasize will be 0x20, // `owner` will be compared against the returned address at 0x20. if iszero(eq(mload(returndatasize()), owner)) { mstore(0x00, 0xddafbaef) // `InvalidPermit()`. revert(0x1c, 0x04) } // Increment and store the updated nonce. sstore(nonceSlot, add(nonceValue, t)) // `t` is 1 if ecrecover succeeds. // Compute the allowance slot and store the value. // The `owner` is already at slot 0x20. mstore(0x40, or(shl(160, _ALLOWANCE_SLOT_SEED), spender)) sstore(keccak256(0x2c, 0x34), value) // Emit the {Approval} event. log3(add(m, 0x60), 0x20, _APPROVAL_EVENT_SIGNATURE, owner, spender) mstore(0x40, m) // Restore the free memory pointer. mstore(0x60, 0) // Restore the zero pointer. } } /// @dev Returns the EIP-712 domain separator for the EIP-2612 permit. function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) { bytes32 nameHash = _constantNameHash(); // We simply calculate it on-the-fly to allow for cases where the `name` may change. if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name())); bytes32 versionHash = _versionHash(); /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Grab the free memory pointer. mstore(m, _DOMAIN_TYPEHASH) mstore(add(m, 0x20), nameHash) mstore(add(m, 0x40), versionHash) mstore(add(m, 0x60), chainid()) mstore(add(m, 0x80), address()) result := keccak256(m, 0xa0) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL MINT FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Mints `amount` tokens to `to`, increasing the total supply. /// /// Emits a {Transfer} event. function _mint(address to, uint256 amount) internal virtual { _beforeTokenTransfer(address(0), to, amount); /// @solidity memory-safe-assembly assembly { let totalSupplyBefore := sload(_TOTAL_SUPPLY_SLOT) let totalSupplyAfter := add(totalSupplyBefore, amount) // Revert if the total supply overflows. if lt(totalSupplyAfter, totalSupplyBefore) { mstore(0x00, 0xe5cfe957) // `TotalSupplyOverflow()`. revert(0x1c, 0x04) } // Store the updated total supply. sstore(_TOTAL_SUPPLY_SLOT, totalSupplyAfter) // Compute the balance slot and load its value. mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, 0, shr(96, mload(0x0c))) } _afterTokenTransfer(address(0), to, amount); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL BURN FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Burns `amount` tokens from `from`, reducing the total supply. /// /// Emits a {Transfer} event. function _burn(address from, uint256 amount) internal virtual { _beforeTokenTransfer(from, address(0), amount); /// @solidity memory-safe-assembly assembly { // Compute the balance slot and load its value. mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, from) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Subtract and store the updated total supply. sstore(_TOTAL_SUPPLY_SLOT, sub(sload(_TOTAL_SUPPLY_SLOT), amount)) // Emit the {Transfer} event. mstore(0x00, amount) log3(0x00, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, shl(96, from)), 0) } _afterTokenTransfer(from, address(0), amount); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL TRANSFER FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Moves `amount` of tokens from `from` to `to`. function _transfer(address from, address to, uint256 amount) internal virtual { _beforeTokenTransfer(from, to, amount); /// @solidity memory-safe-assembly assembly { let from_ := shl(96, from) // Compute the balance slot and load its value. mstore(0x0c, or(from_, _BALANCE_SLOT_SEED)) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Compute the balance slot of `to`. mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance of `to`. // Will not overflow because the sum of all user balances // cannot exceed the maximum uint256 value. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c))) } _afterTokenTransfer(from, to, amount); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL ALLOWANCE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Updates the allowance of `owner` for `spender` based on spent `amount`. function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { if (_givePermit2InfiniteAllowance()) { if (spender == _PERMIT2) return; // Do nothing, as allowance is infinite. } /// @solidity memory-safe-assembly assembly { // Compute the allowance slot and load its value. mstore(0x20, spender) mstore(0x0c, _ALLOWANCE_SLOT_SEED) mstore(0x00, owner) let allowanceSlot := keccak256(0x0c, 0x34) let allowance_ := sload(allowanceSlot) // If the allowance is not the maximum uint256 value. if not(allowance_) { // Revert if the amount to be transferred exceeds the allowance. if gt(amount, allowance_) { mstore(0x00, 0x13be252b) // `InsufficientAllowance()`. revert(0x1c, 0x04) } // Subtract and store the updated allowance. sstore(allowanceSlot, sub(allowance_, amount)) } } } /// @dev Sets `amount` as the allowance of `spender` over the tokens of `owner`. /// /// Emits a {Approval} event. function _approve(address owner, address spender, uint256 amount) internal virtual { if (_givePermit2InfiniteAllowance()) { /// @solidity memory-safe-assembly assembly { // If `spender == _PERMIT2 && amount != type(uint256).max`. if iszero(or(xor(shr(96, shl(96, spender)), _PERMIT2), iszero(not(amount)))) { mstore(0x00, 0x3f68539a) // `Permit2AllowanceIsFixedAtInfinity()`. revert(0x1c, 0x04) } } } /// @solidity memory-safe-assembly assembly { let owner_ := shl(96, owner) // Compute the allowance slot and store the amount. mstore(0x20, spender) mstore(0x0c, or(owner_, _ALLOWANCE_SLOT_SEED)) sstore(keccak256(0x0c, 0x34), amount) // Emit the {Approval} event. mstore(0x00, amount) log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, shr(96, owner_), shr(96, mload(0x2c))) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HOOKS TO OVERRIDE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Hook that is called before any transfer of tokens. /// This includes minting and burning. function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /// @dev Hook that is called after any transfer of tokens. /// This includes minting and burning. function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PERMIT2 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether to fix the Permit2 contract's allowance at infinity. /// /// This value should be kept constant after contract initialization, /// or else the actual allowance values may not match with the {Approval} events. /// For best performance, return a compile-time constant for zero-cost abstraction. function _givePermit2InfiniteAllowance() internal view virtual returns (bool) { return true; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {FixedPointMathLib} from "../lib/solady/src/utils/FixedPointMathLib.sol"; import {GameToken} from "./Token.sol"; import {IUniswapV2Router02} from "../lib/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import {IUniswapV2Factory} from "../lib/v2-core/contracts/interfaces/IUniswapV2Factory.sol"; contract Game { address public owner; uint256 public messagePrice; uint256 public prizePool; bool public isGameActive; address public winner; GameToken public token; uint256 public immutable gameStartTimestamp; uint256 public constant EMERGENCY_WITHDRAWAL_DELAY = 30 days; IUniswapV2Router02 private immutable UNISWAP_ROUTER; IUniswapV2Factory private immutable UNISWAP_FACTORY; address public pair; struct Message { uint256 id; address sender; string content; uint256 timestamp; } struct AgentResponse { uint256 id; uint256 respondingToMessageId; string content; uint256 timestamp; } Message[] public messages; AgentResponse[] public agentResponses; mapping(uint256 => bool) public messageHasResponse; mapping(address => uint256) public addressToMessagesSubmitted; event MessageSubmitted( uint256 indexed messageId, address indexed sender, string message ); event AgentResponseSubmitted( uint256 indexed responseId, uint256 indexed respondingToMessageId, string message ); constructor() { owner = msg.sender; messagePrice = 0.0035 ether; isGameActive = true; UNISWAP_ROUTER = IUniswapV2Router02( 0xad1eCa41E6F772bE3cb5A48A6141f9bcc1AF9F7c ); UNISWAP_FACTORY = IUniswapV2Factory( 0x566d7510dEE58360a64C9827257cF6D0Dc43985E ); gameStartTimestamp = block.timestamp; } modifier onlyOwner() { require(msg.sender == owner, "Only owner"); _; } modifier onlyGameActive() { require(isGameActive, "Game is over"); _; } function submitMessage( string memory message ) external payable onlyGameActive { require(msg.value == messagePrice, "Incorrect fee"); prizePool += msg.value; addressToMessagesSubmitted[msg.sender]++; uint256 messageId = messages.length; messages.push(Message(messageId, msg.sender, message, block.timestamp)); messagePrice = FixedPointMathLib.mulDivUp(messagePrice, 1001, 1000); emit MessageSubmitted(messageId, msg.sender, message); } function submitAgentResponse( uint256 _respondingToMessageId, string memory _content ) external onlyOwner onlyGameActive { require( _respondingToMessageId < messages.length, "Message ID to respond to does not exist" ); require( !messageHasResponse[_respondingToMessageId], "Message already responded to" ); messageHasResponse[_respondingToMessageId] = true; uint256 responseId = agentResponses.length; agentResponses.push( AgentResponse( responseId, _respondingToMessageId, _content, block.timestamp ) ); if (agentResponses.length >= 2500) { winner = address(0x000000000000000000000000000000000000dEaD); isGameActive = false; _deployTokenAndAddLiquidity("Poopcoin", "POOP"); } emit AgentResponseSubmitted( responseId, _respondingToMessageId, _content ); } function declareWinner(address _winner) external onlyOwner onlyGameActive { winner = _winner; isGameActive = false; _deployTokenAndAddLiquidity("Poopcoin", "POOP"); } function _deployTokenAndAddLiquidity( string memory _name, string memory _symbol ) internal onlyOwner { // Deploy token token = new GameToken(address(this), _name, _symbol); // Only proceed with Uniswap if we have ETH to add if (prizePool > 0) { // Get 25% of supply for liquidity uint256 tokenAmount = 250_000_000 ether; // Create pair (or get existing) pair = UNISWAP_FACTORY.createPair( address(token), UNISWAP_ROUTER.WETH() ); // Approve router to spend tokens token.approve(address(UNISWAP_ROUTER), tokenAmount); // Add liquidity with ETH UNISWAP_ROUTER.addLiquidityETH{value: prizePool}( address(token), tokenAmount, 0, 0, address(0x000000000000000000000000000000000000dEaD), // dead address block.timestamp ); } } function determineTokenDistribution( address _participant ) external view returns (uint256) { uint256 baseAllocation = 0; // Winner gets 2.5% of the tokens as base allocation if (_participant == winner) { baseAllocation = 25_000_000 ether; } // If the participant has not submitted any messages, return only base allocation if (addressToMessagesSubmitted[_participant] == 0) { return baseAllocation; } // Calculate message-based allocation (22.5% distributed amongst participants) uint256 tokensPerMessage = FixedPointMathLib.divWad( 225_000_000 ether, messages.length ); uint256 messageBasedAllocation = FixedPointMathLib.mulWad( tokensPerMessage, addressToMessagesSubmitted[_participant] ); // Add base allocation to message-based allocation return baseAllocation + messageBasedAllocation; } /** * @notice Emergency withdrawal function if something goes wrong and funds are locked. * Requires 30 days to elapse since the contract was deployed. * This allows all deposited funds to be withdrawn to the agent wallet. * The agent will be then able to manually create the token and add liquidity. */ function emergencyWithdraw() external onlyOwner { require( block.timestamp >= gameStartTimestamp + EMERGENCY_WITHDRAWAL_DELAY, "Withdrawal delay not met" ); (bool success, ) = owner.call{value: address(this).balance}(""); require(success, "Transfer failed"); } function transferOwner(address _newOwner) external onlyOwner { owner = _newOwner; } function getMessages() external view returns (Message[] memory) { return messages; } function getAgentResponses() external view returns (AgentResponse[] memory) { return agentResponses; } function getAgentResponseById( uint256 _id ) external view returns (AgentResponse memory) { return agentResponses[_id]; } function getMessageById( uint256 _id ) external view returns (Message memory) { return messages[_id]; } function numMessages() external view returns (uint256) { return messages.length; } function getCurrentMessagePrice() external view returns (uint256) { return messagePrice; } function getPrizePool() external view returns (uint256) { return prizePool; } function crackAnswer() external pure returns (string memory) { return "SIKE"; } }
pragma solidity >=0.6.2; import './IUniswapV2Router01.sol'; interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
pragma solidity >=0.5.0; interface IUniswapV2Factory { event PairCreated(address indexed token0, address indexed token1, address pair, uint); function feeTo() external view returns (address); function feeToSetter() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint) external view returns (address pair); function allPairsLength() external view returns (uint); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeToSetter(address) external; }
pragma solidity >=0.6.2; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); }
{ "viaIR": false, "codegen": "yul", "remappings": [ "solady/=lib/solady/src/", "uniswap/v2-periphery/=lib/v2-periphery/", "forge-std/=lib/forge-std/src/", "v2-core/=lib/v2-core/contracts/", "v2-periphery/=lib/v2-periphery/contracts/" ], "evmVersion": "cancun", "outputSelection": { "*": { "*": [ "abi" ] } }, "optimizer": { "enabled": true, "mode": "3", "fallback_to_optimizing_for_size": false, "disable_system_request_memoization": true }, "metadata": {}, "libraries": {}, "enableEraVMExtensions": false, "forceEVMLA": false }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_game","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AllowanceOverflow","type":"error"},{"inputs":[],"name":"AllowanceUnderflow","type":"error"},{"inputs":[],"name":"InsufficientAllowance","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidPermit","type":"error"},{"inputs":[],"name":"Permit2AllowanceIsFixedAtInfinity","type":"error"},{"inputs":[],"name":"PermitExpired","type":"error"},{"inputs":[],"name":"TotalSupplyOverflow","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"result","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"participant","type":"address"}],"name":"claimTokensFromGameParticipant","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"crackAnswer","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"game","outputs":[{"internalType":"contract Game","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
000000000000000000000000a51594022dc770eeefdb479f3320e5316a51d507000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000008506f6f70636f696e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004504f4f5000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x0001000000000002001000000000000200000000000103550000006003100270000001b10330019700000001002001900000002c0000c13d0000008004000039000000400040043f000000040030008c000000500000413d000000000201043b000000e002200270000001c80020009c000000520000213d000001d40020009c000000650000213d000001da0020009c000000c10000213d000001dd0020009c000001820000613d000001de0020009c000000500000c13d000000440030008c000000500000413d0000000002000416000000000002004b000000500000c13d0000000402100370000000000202043b000001b40020009c000000500000213d0000002401100370000000000401043b000002070040009c00000000010000390000000101006039000001df0320016700000000001301a00000030f0000c13d0000020601000041000000000010043f000001f101000041000006c300010430000000a004000039000000400040043f0000000002000416000000000002004b000000500000c13d0000001f02300039000001b202200197000000a002200039000000400020043f0000001f0530018f000001b306300198000000a0026000390000003e0000613d000000000701034f000000007807043c0000000004840436000000000024004b0000003a0000c13d000000000005004b0000004b0000613d000000000161034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000600030008c000000500000413d000000a00200043d000001b40020009c000000910000a13d0000000001000019000006c300010430000001c90020009c000000aa0000213d000001cf0020009c000001090000213d000001d20020009c0000018a0000613d000001d30020009c000000500000c13d000000240030008c000000500000413d0000000002000416000000000002004b000000500000c13d0000000401100370000000000101043b000001b40010009c000000500000213d0000020102000041000001940000013d000001d50020009c0000012f0000213d000001d80020009c0000019a0000613d000001d90020009c000000500000c13d0000000001000416000000000001004b000000500000c13d06c1064a0000040f000000001201043406c106840000040f000000400300043d000d00000003001d00000020023000390000000000120435000001e80100004100000040023000390000000000120435000001e90100004100000000001304350000800b0100003900000004030000390000000004000415000000100440008a0000000504400210000001ea0200004106c106990000040f00000000020004100000000d040000290000008003400039000000000023043500000060024000390000000000120435000000a002000039000000000104001906c106840000040f000000400200043d0000000000120435000001b10020009c000001b1020080410000004001200210000001e2011001c7000006c20001042e000000c00600043d000001b50060009c000000500000213d0000001f01600039000000000031004b0000000004000019000001b604008041000001b601100197000000000001004b0000000005000019000001b605004041000001b60010009c000000000504c019000000000005004b000000500000c13d000000a0016000390000000005010433000001b50050009c000001590000a13d0000020001000041000000000010043f0000004101000039000000040010043f000001fe01000041000006c300010430000001ca0020009c000001440000213d000001cd0020009c000001a10000613d000001ce0020009c000000500000c13d0000000001000416000000000001004b000000500000c13d0000000001000412000f00000001001d000e00000000003d0000800501000039000000440300003900000000040004150000000f0440008a0000000504400210000001f60200004106c106990000040f000001b401100197000000800010043f000001f701000041000006c20001042e000001db0020009c000002470000613d000001dc0020009c000000500000c13d000000640030008c000000500000413d0000000002000416000000000002004b000000500000c13d0000000402100370000000000202043b000d00000002001d000001b40020009c000000500000213d0000002402100370000000000202043b000c00000002001d000001b40020009c000000500000213d0000000d0200002900000060042002100000004401100370000000000101043b000b00000001001d0000000001000411000001df0010009c000003320000c13d000001bf014001c70000000c0010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001c0011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000000000201041a0000000b0220006c0000012b0000413d000000000021041b0000000c01000029000000000010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001c0011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000000000201041a0000000b030000290000000002320019000000000021041b000000200030043f0000000c0100043d00000000020004140000006006100270000001b10020009c000001b102008041000000c001200210000001c2011001c70000800d020000390000000303000039000001c3040000410000000d05000029000003670000013d000001d00020009c0000024f0000613d000001d10020009c000000500000c13d000000440030008c000000500000413d0000000002000416000000000002004b000000500000c13d0000000402100370000000000202043b000d00000002001d000001b40020009c000000500000213d0000002401100370000000000101043b000c00000001001d000001bf010000410000000c0010043f0000000001000411000000000010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001c0011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000000000201041a0000000c0220006c0000034a0000813d0000020501000041000000000010043f000001f101000041000006c300010430000001d60020009c000002640000613d000001d70020009c000000500000c13d0000000001000416000000000001004b000000500000c13d000000c001000039000000400010043f0000000402000039000000800020043f0000020202000041000000a00020043f000000800200003906c106030000040f000000c00110008a000001b10010009c000001b101008041000000600110021000000203011001c7000006c20001042e000001cb0020009c0000027a0000613d000001cc0020009c000000500000c13d000000440030008c000000500000413d0000000002000416000000000002004b000000500000c13d0000000402100370000000000202043b000001b40020009c000000500000213d0000002401100370000000000101043b000001b40010009c000000500000213d000001df0010009c000003720000c13d000000010100008a000003820000013d0000001f0150003900000208011001970000003f011000390000020801100197000000400700043d0000000001170019000000000071004b00000000040000390000000104004039000001b50010009c000000a40000213d0000000100400190000000a40000c13d000000a004300039000000400010043f000d00000007001d0000000001570436000000c0066000390000000007650019000000000047004b000000500000213d00000208085001970000001f0750018f000000000016004b000002b80000813d000000000008004b0000017e0000613d000000000a7600190000000009710019000000200990008a000000200aa0008a000000000b890019000000000c8a0019000000000c0c04330000000000cb0435000000200880008c000001780000c13d000000000007004b000002ce0000613d0000000009010019000002c40000013d0000000001000416000000000001004b000000500000c13d06c1064a0000040f0000000002010019000000400100043d000d00000001001d000003aa0000013d000000240030008c000000500000413d0000000002000416000000000002004b000000500000c13d0000000401100370000000000101043b000001b40010009c000000500000213d000001bf020000410000000c0020043f000000000010043f0000000c01000039000000200200003906c106840000040f0000024b0000013d0000000001000416000000000001004b000000500000c13d0000001201000039000000800010043f000001f701000041000006c20001042e000000240030008c000000500000413d0000000002000416000000000002004b000000500000c13d0000000401100370000000000101043b000d00000001001d000001b40010009c000000500000213d0000000d01000029000000000010043f0000000201000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001f8011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000000000101041a000000ff00100190000003880000c13d0000000d01000029000000000010043f0000000201000039000000200010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001f8011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000000000201041a000002090220019700000001022001bf000000000021041b000001fc01000041000000400200043d0000000000120435000c00000002001d00000004012000390000000d020000290000000000210435000001f60100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000001b10010009c000001b101008041000000c001100210000001fd011001c7000080050200003906c106bc0000040f0000000100200190000005270000613d000000000201043b0000000c01000029000001b10010009c000001b10100804100000040011002100000000003000414000001b10030009c000001b103008041000000c003300210000000000113019f000001fe011001c7000001b40220019706c106bc0000040f0000006003100270000001b103300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000c0b00002900000000057b0019000002000000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000001fc0000c13d000000000006004b0000020d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000004010000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000001b50010009c000000a40000213d0000000100200190000000a40000c13d000000400010043f000000200030008c000000500000413d00000000030b0433000001bc01000041000000000201041a000c00000003001d000000000032001a000005a90000413d0000000c02200029000000000021041b000001bf010000410000000c0010043f0000000d01000029000000000010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001c0011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000000000201041a0000000c030000290000000002320019000000000021041b000000200030043f0000000c0100043d00000000020004140000006006100270000001b10020009c000001b102008041000000c001200210000001c2011001c70000800d020000390000000303000039000001c304000041000000000500001906c106b70000040f0000000100200190000000500000613d0000000001000019000006c20001042e0000000001000416000000000001004b000000500000c13d000001bc01000041000000000101041a000000800010043f000001f701000041000006c20001042e0000000001000416000000000001004b000000500000c13d0000000103000039000000000203041a000000010520019000000001012002700000007f0410018f00000000010460190000001f0010008c00000000060000390000000106002039000000000662013f0000000100600190000002af0000613d0000020001000041000000000010043f0000002201000039000000040010043f000001fe01000041000006c300010430000000240030008c000000500000413d0000000002000416000000000002004b000000500000c13d0000000401100370000000000101043b000001b40010009c000000500000213d000000000010043f0000000201000039000000200010043f0000004002000039000000000100001906c106840000040f000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f000001f701000041000006c20001042e000000e40030008c000000500000413d0000000002000416000000000002004b000000500000c13d0000000402100370000000000202043b000d00000002001d000001b40020009c000000500000213d0000002402100370000000000202043b000c00000002001d000001b40020009c000000500000213d0000006402100370000000000202043b000a00000002001d0000004402100370000000000202043b000b00000002001d0000008401100370000000000101043b000900000001001d000000ff0010008c000000500000213d000000010100008a0000000b0010006b000000000100003900000001010060390000000c02000029000001df0220016700000000001201a0000000280000613d000000000200041a000000010320019000000001012002700000007f0110618f0000001f0010008c00000000040000390000000104002039000000000442013f00000001004001900000025e0000c13d000000800010043f000000000003004b0000041f0000613d000000000000043f000000000001004b000004270000c13d000000a0020000390000000001000019000004360000013d000000800010043f000000000005004b0000032d0000c13d0000020901200197000000a00010043f000000000004004b000000c001000039000000a001006039000003a40000013d0000000009810019000000000008004b000002c10000613d000000000a060019000000000b01001900000000ac0a0434000000000bcb043600000000009b004b000002bd0000c13d000000000007004b000002ce0000613d00000000068600190000000307700210000000000809043300000000087801cf000000000878022f00000000060604330000010007700089000000000676022f00000000067601cf000000000686019f000000000069043500000000055100190000000000050435000000e00500043d000001b50050009c000000500000213d0000001f06500039000000000036004b0000000003000019000001b603008041000001b606600197000000000006004b0000000007000019000001b607004041000001b60060009c000000000703c019000000000007004b000000500000c13d000000a0035000390000000003030433000001b50030009c000000a40000213d0000001f0630003900000208066001970000003f066000390000020806600197000000400800043d0000000006680019000000000086004b00000000070000390000000107004039000001b50060009c000000a40000213d0000000100700190000000a40000c13d000000400060043f000b00000008001d0000000006380436000c00000006001d000000c0055000390000000006530019000000000046004b000000500000213d000001b40220019700000208063001970000001f0430018f0000000c0b0000290000000000b5004b000003b50000813d000000000006004b0000030a0000613d000000000845001900000000074b0019000000200770008a000000200880008a0000000009670019000000000a680019000000000a0a04330000000000a90435000000200660008c000003040000c13d000000000004004b0000000d08000029000003cc0000613d00000000070b0019000003c20000013d000d00000004001d000000200020043f000001e0010000410000000c0010043f0000000001000411000000000010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001e1011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b0000000d02000029000000000021041b000000000020043f0000002c0100043d00000000020004140000006006100270000001b10020009c000001b102008041000000c001200210000001b9011001c70000800d020000390000000303000039000001f404000041000003660000013d000000000030043f000000020020008c000003990000813d000000a001000039000003a40000013d000000200010043f000a00000004001d000001e0014001c70000000c0010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001e1011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000000000201041a000002070020009c0000000a04000029000000dc0000613d0000000b0220006c000004250000813d0000020401000041000000000010043f000001f101000041000006c300010430000000000021041b0000000d01000029000000000010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001c0011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000000000201041a0000000c030000290000000002320019000000000021041b000000200030043f0000000c0100043d00000000020004140000006006100270000001b10020009c000001b102008041000000c001200210000001c2011001c70000800d020000390000000303000039000001c304000041000000000500041106c106b70000040f0000000100200190000000500000613d000000400100043d00000001020000390000000000210435000001b10010009c000001b1010080410000004001100210000001e2011001c7000006c20001042e000000200010043f000001e0010000410000000c0010043f000000000020043f0000000001000414000001b10010009c000001b101008041000000c001100210000001e1011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000400400043d000000000101043b000000000101041a0000000000140435000001b10040009c000001b1040080410000004001400210000001e2011001c7000006c20001042e000000400100043d0000004402100039000001f9030000410000000000320435000000240210003900000016030000390000000000320435000001fa020000410000000000210435000000040210003900000020030000390000000000320435000001b10010009c000001b1010080410000004001100210000001fb011001c7000006c300010430000001bb0200004100000000040000190000000003040019000000000402041a000000a005300039000000000045043500000001022000390000002004300039000000000014004b0000039b0000413d000000c001300039000000800210008a000000800100003906c106380000040f000000400100043d000d00000001001d000000800200003906c106030000040f0000000d020000290000000001210049000001b10010009c000001b1010080410000006001100210000001b10020009c000001b1020080410000004002200210000000000121019f000006c20001042e00000000076b0019000000000006004b000003be0000613d000000000805001900000000090b0019000000008a0804340000000009a90436000000000079004b000003ba0000c13d000000000004004b0000000d08000029000003cc0000613d00000000056500190000000304400210000000000607043300000000064601cf000000000646022f00000000050504330000010004400089000000000545022f00000000044501cf000000000464019f000000000047043500000000033b00190000000000030435000000800020043f0000000002080433000a00000002001d000001b50020009c000000a40000213d000000000200041a000000010420019000000001032002700000007f0330618f0000001f0030008c00000000020000390000000102002039000000000024004b0000025e0000c13d000000200030008c000003ee0000413d0000000a040000290000001f024000390000000502200270000001b70220009a000000200040008c000001b802004041000000000000043f0000001f033000390000000503300270000001b70330009a000000000032004b000003ee0000813d000000000002041b0000000102200039000000000032004b000003ea0000413d0000000a020000290000001f0020008c000004580000a13d000000000000043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000200200008a0000000a02200180000000000101043b000005280000c13d0000002003000039000005350000013d0000001f0530018f000001b306300198000000400200043d00000000046200190000040c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000004080000c13d000000000005004b000004190000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000001b10020009c000001b1020080410000004002200210000000000112019f000006c3000104300000020902200197000000a00020043f000000000001004b00000020020000390000000002006039000004300000013d000000000021041b000000dc0000013d000001b8030000410000000002000019000000000403041a000000a005200039000000000045043500000001033000390000002002200039000000000012004b000004290000413d0000003f012000390000020802100197000001e30020009c000000a40000213d000000800100043d0000008002200039000000400020043f000001b10010009c000001b10100804100000060011002100000000002000414000001b10020009c000001b102008041000000c002200210000000000121019f000001e4011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000800000001001d000001e50100004100000000001004430000000001000414000001b10010009c000001b101008041000000c001100210000001e6011001c70000800b0200003906c106bc0000040f0000000100200190000005270000613d000000000101043b0000000a0010006c000004640000a13d000001f501000041000000000010043f000001f101000041000006c3000104300000000a0000006b00000000020000190000045c0000613d00000000020104330000000a040000290000000301400210000002070110027f0000020701100167000000000112016f0000000102400210000000000121019f000005430000013d000000400100043d000700000001001d000001e7010000410000000e0010043f0000000d01000029000001b401100197000d00000001001d000000000010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001c0011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000300000001001d000000000101041a000600000001001d00000007020000290000004003200039000001e801000041000500000003001d00000000001304350000002001200039000400000001001d00000008030000290000000000310435000001e9010000410000000000120435000001ea0100004100000000001004430000000001000414000001b10010009c000001b101008041000000c001100210000001e6011001c70000800b0200003906c106bc0000040f0000000100200190000005270000613d00000007030000290000006002300039000000000101043b000800000002001d000000000012043500000080023000390000000001000410000100000002001d0000000000120435000001b10030009c000001b101000041000000000103401900020040001002180000000001000414000001b10010009c000001b101008041000000c00110021000000002011001af000001eb011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b0000002e0010043f000001ec01000041000000070300002900000000001304350000000d01000029000000040200002900000000001204350000000c01000029000000050200002900000000001204350000000b0100002900000008020000290000000000120435000000060100002900000001020000290000000000120435000000a0013000390000000a0200002900000000002104350000000001000414000001b10010009c000001b101008041000000c00110021000000002011001af000001ed011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b0000004e0010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001ee011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000000000010043f0000000901000029000000ff0110018f000000200010043f0000000001000367000000a402100370000000000202043b000000400020043f000000c401100370000000000101043b000000600010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001ef011001c7000000010200003906c106bc0000040f0000006003100270000001b103300197000000200030008c000000200400003900000000040340190000001f0540018f00000020064001900000002004600039000004f10000613d0000002007000039000000000801034f000000008908043c0000000007970436000000000047004b000004ed0000c13d000000000005004b000004fe0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000000010304330000000d0010006c000005ff0000c13d000000010120018f00000006011000290000000302000029000000000012041b0000000c01000029000001f2011001c7000000400010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001f3011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b0000000b02000029000000000021041b0000000801000029000001b10010009c000001b10100804100000040011002100000000002000414000001b10020009c000001b102008041000000c002200210000000000112019f000001b9011001c70000800d020000390000000303000039000001f4040000410000000d050000290000000c0600002906c106b70000040f0000000100200190000000500000613d000002450000013d000000000001042f000000010320008a00000005033002700000000004310019000000200300003900000001044000390000000d0600002900000000056300190000000005050433000000000051041b00000020033000390000000101100039000000000041004b0000052e0000c13d0000000a0020006c000005400000813d0000000a020000290000000302200210000000f80220018f000002070220027f00000207022001670000000d033000290000000003030433000000000223016f000000000021041b0000000a01000029000000010110021000000001011001bf000000000010041b0000000b010000290000000001010433000d00000001001d000001b50010009c000000a40000213d0000000101000039000000000201041a000000010020019000000001012002700000007f0110618f0000001f0010008c00000000030000390000000103002039000000000232013f00000001002001900000025e0000c13d000000200010008c000005670000413d0000000102000039000000000020043f0000000d030000290000001f023000390000000502200270000001ba0220009a000000200030008c000001bb020040410000001f011000390000000501100270000001ba0110009a000000000012004b000005670000813d000000000002041b0000000102200039000000000012004b000005630000413d0000000d010000290000001f0010008c0000057b0000a13d0000000101000039000000000010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001b9011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000200200008a0000000d02200180000000000101043b000005880000c13d0000002003000039000005950000013d0000000d0000006b0000000001000019000005800000613d0000000c0100002900000000010104330000000d040000290000000302400210000002070220027f0000020702200167000000000121016f0000000102400210000000000121019f000005a30000013d000000010320008a00000005033002700000000004310019000000200300003900000001044000390000000b0600002900000000056300190000000005050433000000000051041b00000020033000390000000101100039000000000041004b0000058e0000c13d0000000d0020006c000005a00000813d0000000d020000290000000302200210000000f80220018f000002070220027f00000207022001670000000b033000290000000003030433000000000223016f000000000021041b0000000d01000029000000010110021000000001011001bf0000000102000039000000000012041b000001bc01000041000000000201041a000001be0220009c000005ad0000413d000001ff01000041000000000010043f000001f101000041000006c300010430000000800300043d000000000021041b000001bf010000410000000c0010043f000001b401300197000000000010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001c0011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000000000201041a000001be0220009a000000000021041b000001c101000041000000200010043f0000000c0100043d00000000020004140000006006100270000001b10020009c000001b102008041000000c001200210000001c2011001c70000800d020000390000000303000039000001c304000041000000000500001906c106b70000040f0000000100200190000000500000613d000001bc01000041000000000201041a000001c50220009c000005a90000813d000000000021041b000001bf010000410000000c0010043f0000dead01000039000000000010043f0000000001000414000001b10010009c000001b101008041000000c001100210000001c0011001c7000080100200003906c106bc0000040f0000000100200190000000500000613d000000000101043b000000000201041a000001c50220009a000000000021041b000001c601000041000000200010043f0000000c0100043d00000000020004140000006006100270000001b10020009c000001b102008041000000c001200210000001c2011001c70000800d020000390000000303000039000001c304000041000000000500001906c106b70000040f0000000100200190000000500000613d000000800100043d000001400000044300000160001004430000002001000039000001000010044300000001010000390000012000100443000001c701000041000006c20001042e000001f001000041000000000010043f000001f101000041000006c300010430000000200300003900000000033104360000000042020434000000000023043500000208062001970000001f0520018f0000004001100039000000000014004b0000061c0000813d000000000006004b000006180000613d00000000085400190000000007510019000000200770008a000000200880008a0000000009670019000000000a680019000000000a0a04330000000000a90435000000200660008c000006120000c13d000000000005004b000006320000613d0000000007010019000006280000013d0000000007610019000000000006004b000006250000613d00000000080400190000000009010019000000008a0804340000000009a90436000000000079004b000006210000c13d000000000005004b000006320000613d00000000046400190000000305500210000000000607043300000000065601cf000000000656022f00000000040404330000010005500089000000000454022f00000000045401cf000000000464019f0000000000470435000000000421001900000000000404350000001f0220003900000208022001970000000001210019000000000001042d0000001f0220003900000208022001970000000001120019000000000021004b00000000020000390000000102004039000001b50010009c000006440000213d0000000100200190000006440000c13d000000400010043f000000000001042d0000020001000041000000000010043f0000004101000039000000040010043f000001fe01000041000006c300010430000000000400041a000000010540019000000001024002700000007f0220618f0000001f0020008c00000000010000390000000101002039000000000015004b000006770000c13d000000400100043d0000000003210436000000000005004b000006640000613d000000000000043f000000000002004b0000066a0000613d000001b80500004100000000040000190000000006430019000000000705041a000000000076043500000001055000390000002004400039000000000024004b0000065c0000413d0000066b0000013d00000209044001970000000000430435000000000002004b000000200400003900000000040060390000066b0000013d00000000040000190000003f0240003900000208032001970000000002130019000000000032004b00000000030000390000000103004039000001b50020009c0000067d0000213d00000001003001900000067d0000c13d000000400020043f000000000001042d0000020001000041000000000010043f0000002201000039000000040010043f000001fe01000041000006c3000104300000020001000041000000000010043f0000004101000039000000040010043f000001fe01000041000006c300010430000000000001042f000001b10010009c000001b1010080410000004001100210000001b10020009c000001b1020080410000006002200210000000000112019f0000000002000414000001b10020009c000001b102008041000000c002200210000000000112019f0000020a011001c7000080100200003906c106bc0000040f0000000100200190000006970000613d000000000101043b000000000001042d0000000001000019000006c30001043000000000050100190000000000200443000000050030008c000006a70000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b0000069f0000413d000001b10030009c000001b10300804100000060013002100000000002000414000001b10020009c000001b102008041000000c002200210000000000112019f0000020b011001c7000000000205001906c106bc0000040f0000000100200190000006b60000613d000000000101043b000000000001042d000000000001042f000006ba002104210000000102000039000000000001042d0000000002000019000000000001042d000006bf002104230000000102000039000000000001042d0000000002000019000000000001042d000006c100000432000006c20001042e000006c30001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000d6f21326ab749d5729fcba5677c79037b459436ab7bff709c9d06ce9f10c1a9d290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56302000000000000000000000000000000000000200000000000000000000000004ef1d2ad89edf8c4d91132028e8195cdf30bb4b5053d4f8cd260341d4805f30ab10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6000000000000000000000000000000000000000000000005345cdf77eb68f44cffffffffffffffffffffffffffffffffffffffffff313470d80bdff0c5ffffffffffffffffffffffffffffffffffffffffffffffff313470d80bdff0c60000000000000000000000000000000000000000000000000000000000000087a211a202000000000000000000000000000000000000200000000c0000000000000000000000000000000000000000000000000000000000cecb8f27f4200f3a0000000200000000000000000000000000000000000020000000200000000000000000ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3effffffffffffffffffffffffffffffffffffffffffe6268e1b017bfe18bfffffffffffffffffffffffffffffffffffffffffffffffe6268e1b017bfe18c0000000000000000000000000000000000000000000000019d971e4fe8401e7400000000000002000000000000000000000000000000800000010000000000000000000000000000000000000000000000000000000000000000000000000070a0823000000000000000000000000000000000000000000000000000000000c20bfe6800000000000000000000000000000000000000000000000000000000d505acce00000000000000000000000000000000000000000000000000000000d505accf00000000000000000000000000000000000000000000000000000000dd62ed3e00000000000000000000000000000000000000000000000000000000c20bfe6900000000000000000000000000000000000000000000000000000000c3fe3e280000000000000000000000000000000000000000000000000000000095d89b400000000000000000000000000000000000000000000000000000000095d89b4100000000000000000000000000000000000000000000000000000000a9059cbb0000000000000000000000000000000000000000000000000000000070a08231000000000000000000000000000000000000000000000000000000007ecebe0000000000000000000000000000000000000000000000000000000000313ce5660000000000000000000000000000000000000000000000000000000038e21ccd0000000000000000000000000000000000000000000000000000000038e21cce0000000000000000000000000000000000000000000000000000000044b0554700000000000000000000000000000000000000000000000000000000313ce567000000000000000000000000000000000000000000000000000000003644e5150000000000000000000000000000000000000000000000000000000018160ddc0000000000000000000000000000000000000000000000000000000018160ddd0000000000000000000000000000000000000000000000000000000023b872dd0000000000000000000000000000000000000000000000000000000006fdde0300000000000000000000000000000000000000000000000000000000095ea7b3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3000000000000000000000000000000000000000000000000000000007f5e9f2002000000000000000000000000000000000000340000000c00000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f0200000000000000000000000000000000000000000000a00000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d9553913202000002000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000383775081901c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc68b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f9a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b02000000000000000000000000000000000000a00000000000000000000000006e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c902000000000000000000000000000000000000c000000000000000000000000002000000000000000000000000000000000000420000002c0000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000ddafbaef00000000000000000000000000000000000000040000001c000000000000000000000000000000007f5e9f20000000000000000000000000000000000000000002000000000000000000000000000000000000340000002c00000000000000008c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925000000000000000000000000000000000000000000000000000000001a15a3cc310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e00000000000000000000000000000000000000200000008000000000000000000200000000000000000000000000000000000040000000000000000000000000546f6b656e7320616c726561647920636c61696d65640000000000000000000008c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000843433e3000000000000000000000000000000000000000000000000000000000200000200000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000e5cfe9574e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003837750853494b45000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000013be252b00000000000000000000000000000000000000000000000000000000f4d678b8000000000000000000000000000000000000000000000000000000003f68539affffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00020000000000000000000000000000000000000000000000000000000000000002000002000000000000000000000000000000000000000000000000000000003cddf4f609d1c352d382fb28d825500407365755ad63fda11cbd62a284e0611e
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e2811cfc7c2f2f71a02ad15913dbacfb6fc16d47000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000008506f6f70636f696e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000520504f4f50000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _game (address): 0xE2811cFC7C2f2F71a02Ad15913Dbacfb6FC16d47
Arg [1] : name_ (string): Poopcoin
Arg [2] : symbol_ (string): POOP
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000e2811cfc7c2f2f71a02ad15913dbacfb6fc16d47
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [4] : 506f6f70636f696e000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [6] : 20504f4f50000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
[ 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.