Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 6 from a total of 6 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Submit Agent Res... | 1402295 | 16 days ago | IN | 0 ETH | 0.00000589 | ||||
Declare Winner | 1402289 | 16 days ago | IN | 0 ETH | 0.00002114 | ||||
Submit Message | 1402279 | 16 days ago | IN | 0.0051515 ETH | 0.00000937 | ||||
Submit Message | 1402017 | 16 days ago | IN | 0.0051005 ETH | 0.00000921 | ||||
Submit Message | 1401360 | 16 days ago | IN | 0.00505 ETH | 0.00000886 | ||||
Submit Message | 1400658 | 16 days ago | IN | 0.005 ETH | 0.00000957 |
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:
Game
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 {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; 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( uint256 _messagePrice, address _uniswapRouter, address _uniswapFactory ) { owner = msg.sender; messagePrice = _messagePrice; isGameActive = true; UNISWAP_ROUTER = IUniswapV2Router02(_uniswapRouter); UNISWAP_FACTORY = IUniswapV2Factory(_uniswapFactory); } 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, 101, 100); emit MessageSubmitted(messageId, msg.sender, message); } function submitAgentResponse( uint256 _respondingToMessageId, string memory _content ) external onlyOwner { 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 ) ); emit AgentResponseSubmitted( responseId, _respondingToMessageId, _content ); } function declareWinner( address _winner, string memory _name, string memory _symbol ) external onlyOwner onlyGameActive { winner = _winner; isGameActive = false; // Deploy token token = new GameToken(address(this), _name, _symbol); // Only proceed with Uniswap if we have ETH to add if (prizePool > 0) { // Get 70% of supply for liquidity uint256 tokenAmount = 700_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 & owner get 2.5% of the tokens as base allocation if (_participant == winner || _participant == owner) { 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 (25% distributed amongst winners) uint256 tokensPerMessage = FixedPointMathLib.divWad( 250_000_000 ether, messages.length ); uint256 messageBasedAllocation = FixedPointMathLib.mulWad( tokensPerMessage, addressToMessagesSubmitted[_participant] ); // Add base allocation to message-based allocation return baseAllocation + messageBasedAllocation; } 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; } }
// 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.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 (70%) to game contract for liquidity _mint(address(game), 700_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"); // Get this participants share of the prize pool uint256 amountToMint = game.determineTokenDistribution(participant); // Mark as minted before the mint to prevent reentrancy hasMinted[participant] = true; // Mint new tokens to the participant _mint(participant, amountToMint); } }
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; }
// 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; } }
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":"uint256","name":"_messagePrice","type":"uint256"},{"internalType":"address","name":"_uniswapRouter","type":"address"},{"internalType":"address","name":"_uniswapFactory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"responseId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"respondingToMessageId","type":"uint256"},{"indexed":false,"internalType":"string","name":"message","type":"string"}],"name":"AgentResponseSubmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"messageId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"string","name":"message","type":"string"}],"name":"MessageSubmitted","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"addressToMessagesSubmitted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"agentResponses","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"respondingToMessageId","type":"uint256"},{"internalType":"string","name":"content","type":"string"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_winner","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"}],"name":"declareWinner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_participant","type":"address"}],"name":"determineTokenDistribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getAgentResponseById","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"respondingToMessageId","type":"uint256"},{"internalType":"string","name":"content","type":"string"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct Game.AgentResponse","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAgentResponses","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"respondingToMessageId","type":"uint256"},{"internalType":"string","name":"content","type":"string"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct Game.AgentResponse[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentMessagePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getMessageById","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"content","type":"string"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct Game.Message","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMessages","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"content","type":"string"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"internalType":"struct Game.Message[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPrizePool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isGameActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"messageHasResponse","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"messagePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"messages","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"content","type":"string"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numMessages","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prizePool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_respondingToMessageId","type":"uint256"},{"internalType":"string","name":"_content","type":"string"}],"name":"submitAgentResponse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"message","type":"string"}],"name":"submitMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract GameToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"winner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
9c4d535b00000000000000000000000000000000000000000000000000000000000000000100034b8c0e2d599fcb0d0fcdf8754f638b0d097a2b120f14eb049484bdc5a3000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000ad1eca41e6f772be3cb5a48a6141f9bcc1af9f7c000000000000000000000000566d7510dee58360a64c9827257cf6d0dc43985e
Deployed Bytecode
0x0002000000000002000900000000000200010000000103550000006003100270000002e90030019d000002e90330019700000001002001900000002d0000c13d0000008002000039000000400020043f000000040030008c000009610000413d000000000201043b000000e002200270000002ef0020009c0000006c0000a13d000002f00020009c0000015a0000213d000002f80020009c0000018e0000213d000002fc0020009c000002220000613d000002fd0020009c000002420000613d000002fe0020009c000009610000c13d000000240030008c000009610000413d0000000002000416000000000002004b000009610000c13d0000000401100370000000000101043b000900000001001d000002ec0010009c000009610000213d0000000301000039000000000101041a0000000801100270000002ec011001970000000902000029000000000012004b0000039b0000c13d0000032201000041000003a00000013d0000000002000416000000000002004b000009610000c13d0000001f02300039000002ea02200197000000c002200039000000400020043f0000001f0430018f000002eb05300198000000c0025000390000003e0000613d000000c006000039000000000701034f000000007807043c0000000006860436000000000026004b0000003a0000c13d000000000004004b0000004b0000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000600030008c000009610000413d000000e00100043d000002ec0010009c000009610000213d000001000200043d000002ec0020009c000009610000213d000000c00300043d000000000400041a000002ed044001970000000005000411000000000454019f000000000040041b0000000104000039000000000034041b0000000303000039000000000403041a000003450440019700000001044001bf000000000043041b000000800010043f000000a00020043f0000014000000443000001600010044300000020010000390000018000100443000001a000200443000001000010044300000002010000390000012000100443000002ee0100004100000b9d0001042e000002ff0020009c0000016f0000a13d000003000020009c000001a40000213d000003040020009c000003770000613d000003050020009c000002270000613d000003060020009c000009610000c13d000000440030008c000009610000413d0000000002000416000000000002004b000009610000c13d0000000402100370000000000202043b000900000002001d0000002402100370000000000402043b0000030e0040009c000009610000213d0000002302400039000000000032004b000009610000813d0000000405400039000000000251034f000000000202043b0000033a0020009c000003950000813d0000001f0620003900000346066001970000003f0660003900000346066001970000030f0060009c000003950000213d0000008006600039000000400060043f000000800020043f00000000042400190000002404400039000000000034004b000009610000213d0000002003500039000000000331034f00000346042001980000001f0520018f000000a001400039000000a30000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000016004b0000009f0000c13d000000000005004b000000b00000613d000000000343034f0000000304500210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000310435000000a0012000390000000000010435000000000100041a000002ec011001970000000002000411000000000012004b000005610000c13d0000000601000039000000000101041a0000000902000029000000000012004b0000058e0000813d000000000020043f0000000801000039000000200010043f0000000001000414000002e90010009c000002e901008041000000c00110021000000323011001c700008010020000390b9c0b970000040f0000000100200190000009610000613d000000000101043b000000000101041a000000ff00100190000005a90000c13d0000000901000029000000000010043f0000000801000039000000200010043f0000000001000414000002e90010009c000002e901008041000000c00110021000000323011001c700008010020000390b9c0b970000040f0000000100200190000009610000613d000000000101043b000000000201041a000003450220019700000001022001bf000000000021041b000000400100043d000800000001001d0000030f0010009c000003950000213d0000000701000039000000000201041a00000008030000290000008001300039000000400010043f00000040043000390000008001000039000600000004001d0000000000140435000700000002001d00000000022304360000000901000029000500000002001d00000000001204350000031e0100004100000000001004430000000001000414000002e90010009c000002e901008041000000c0011002100000031f011001c70000800b020000390b9c0b970000040f0000000100200190000007da0000613d000000000101043b00000008020000290000006002200039000400000002001d000000000012043500000007010000290000030e0010009c000003950000213d000000070200002900000001012000390000000703000039000000000013041b000000000030043f000000080100002900000000010104330000000203200210000003400230009a000000000012041b00000005010000290000000001010433000800000003001d000003410230009a000000000012041b00000006010000290000000001010433000300000001001d0000000021010434000500000002001d000600000001001d0000030e0010009c000003950000213d0000000801000029000003420110009a000200000001001d000000000101041a000000010210019000000001011002700000007f0110618f000100000001001d0000001f0010008c00000000010000390000000101002039000000000012004b000006090000c13d0000000101000029000000200010008c000001460000413d0000000201000029000000000010043f0000000001000414000002e90010009c000002e901008041000000c0011002100000032c011001c700008010020000390b9c0b970000040f0000000100200190000009610000613d00000006030000290000001f023000390000000502200270000000200030008c0000000002004019000000000301043b00000001010000290000001f01100039000000050110027000000000011300190000000002230019000000000012004b000001460000813d000000000002041b0000000102200039000000000012004b000001420000413d00000006010000290000001f0010008c000008090000a13d0000000201000029000000000010043f0000000001000414000002e90010009c000002e901008041000000c0011002100000032c011001c700008010020000390b9c0b970000040f0000000100200190000009610000613d000000200200008a0000000602200180000000000101043b000008af0000c13d0000002003000039000008bc0000013d000002f10020009c000001990000213d000002f50020009c0000033b0000613d000002f60020009c000002670000613d000002f70020009c000009610000c13d000000240030008c000009610000413d0000000002000416000000000002004b000009610000c13d0000000401100370000000000101043b000000000010043f0000000801000039000000200010043f00000040010000390b9c0b810000040f000003340000013d000003070020009c000001eb0000a13d000003080020009c0000023d0000613d000003090020009c0000022c0000613d0000030a0020009c000009610000c13d000000240030008c000009610000413d0000000002000416000000000002004b000009610000c13d0000000401100370000000000101043b000900000001001d000002ec0010009c000009610000213d000000000100041a000002ec011001970000000002000411000000000012004b000000000100003900000001010060390b9c0b070000040f000000000100041a000002ed0110019700000009011001af000000000010041b000000000100001900000b9d0001042e000002f90020009c000002220000613d000002fa0020009c0000026d0000613d000002fb0020009c000009610000c13d0000000001000416000000000001004b000009610000c13d000000000100041a000003730000013d000002f20020009c0000036d0000613d000002f30020009c000003160000613d000002f40020009c000009610000c13d0000000001000416000000000001004b000009610000c13d00000004010000390000026b0000013d000003010020009c000003890000613d000003020020009c000002270000613d000003030020009c000009610000c13d000000240030008c000009610000413d0000000402100370000000000402043b0000030e0040009c000009610000213d0000002302400039000000000032004b000009610000813d0000000405400039000000000251034f000000000202043b0000030e0020009c000003950000213d0000001f0620003900000346066001970000003f0660003900000346066001970000030f0060009c000003950000213d0000008006600039000000400060043f000000800020043f00000000042400190000002404400039000000000034004b000009610000213d0000002003500039000000000331034f00000346042001980000001f0520018f000000a001400039000001d10000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000016004b000001cd0000c13d000000000005004b000001de0000613d000000000343034f0000000304500210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000310435000000a00120003900000000000104350000000301000039000000000101041a000000ff00100190000005680000c13d000000400100043d00000044021000390000033803000041000000000032043500000024021000390000000c03000039000005af0000013d0000030b0020009c000003300000613d0000030c0020009c000009610000c13d000000240030008c000009610000413d0000000002000416000000000002004b000009610000c13d0000000401100370000000000101043b0000000602000039000000000202041a000000000021004b000009610000813d0b9c096f0000040f0000000002010019000900000001001d0000000101100039000000000101041a000700000001001d000000000102041a000800000001001d00000002012000390b9c098b0000040f00000009020000290000000302200039000000000202041a000900000002001d000000400400043d000600000004001d0000004002400039000000800300003900000000003204350000000702000029000002ec02200197000000200340003900000000002304350000000802000029000000000024043500000080024000390b9c09d80000040f00000006040000290000006002400039000000090300002900000000003204350000000001410049000002e90010009c000002e901008041000002e90040009c000002e90400804100000060011002100000004002400210000000000121019f00000b9d0001042e0000000001000416000000000001004b000009610000c13d0000000201000039000003850000013d0000000001000416000000000001004b000009610000c13d0000000101000039000003850000013d000000240030008c000009610000413d0000000001000416000000000001004b000009610000c13d0b9c0a8d0000040f00000004010000390000000101100367000000000101043b0b9c096f0000040f0b9c0aa10000040f0000002002000039000000400300043d000900000003001d00000000022304360b9c0a0a0000040f000003260000013d0000000001000416000000000001004b000009610000c13d0000000601000039000003850000013d0000000001000416000000000001004b000009610000c13d0000000701000039000000000501041a0000030e0050009c000003950000213d00000005025002100000003f022000390000032a022001970000030f0020009c000003950000213d0000008007200039000000400070043f000000800050043f000000000010043f000000000005004b000003d20000c13d00000020010000390000000002170436000000800100043d0000000000120435000000400470003900000005031002100000000003430019000800000001001d000000000001004b000004a50000c13d0000000001730049000002e90010009c000002e9010080410000006001100210000002e90070009c000002e9070080410000004002700210000000000121019f00000b9d0001042e0000000001000416000000000001004b000009610000c13d0000000501000039000000000101041a000003730000013d000000640030008c000009610000413d0000000002000416000000000002004b000009610000c13d0000000402100370000000000602043b000002ec0060009c000009610000213d0000002402100370000000000502043b0000030e0050009c000009610000213d0000002302500039000000000032004b000009610000813d0000000407500039000000000271034f000000000402043b0000030e0040009c000003950000213d0000001f0840003900000346088001970000003f0880003900000346088001970000030f0080009c000003950000213d0000008008800039000000400080043f000000800040043f00000000054500190000002405500039000000000035004b000009610000213d0000002005700039000000000751034f00000346084001980000001f0940018f000000a0058000390000029b0000613d000000a00a000039000000000b07034f00000000bc0b043c000000000aca043600000000005a004b000002970000c13d000000000009004b000002a80000613d000000000787034f0000000308900210000000000905043300000000098901cf000000000989022f000000000707043b0000010008800089000000000787022f00000000078701cf000000000797019f0000000000750435000000a00440003900000000000404350000004404100370000000000804043b0000030e0080009c000009610000213d0000002304800039000000000034004b000009610000813d0000000409800039000000000491034f000000000704043b0000030e0070009c000003950000213d0000001f0470003900000346044001970000003f044000390000034604400197000000400500043d0000000004450019000000000054004b000000000a000039000000010a0040390000030e0040009c000003950000213d0000000100a00190000003950000c13d000000400040043f000000000475043600000000087800190000002408800039000000000038004b000009610000213d0000002003900039000000000331034f00000346087001980000001f0970018f0000000001840019000002d50000613d000000000a03034f000000000b04001900000000ac0a043c000000000bcb043600000000001b004b000002d10000c13d000000000009004b000002e20000613d000000000383034f0000000308900210000000000901043300000000098901cf000000000989022f000000000303043b0000010008800089000000000383022f00000000038301cf000000000393019f000000000031043500000000017400190000000000010435000000000100041a000002ec011001970000000003000411000000000013004b000005610000c13d0000000301000039000000000301041a000000ff00300190000001e40000613d000003100330019700000008066002100000031106600197000000000363019f000000000031041b000000400100043d000003120010009c000003950000213d000000a406100039000000600300003900000000003604350000002406100039000002e8070000410000000000760435000000840610003900000000070004100000000000760435000000e408100039000000800700043d0000000000780435000003460a7001970000001f0970018f0000010408100039000000a10080008c0000060f0000413d00000000000a004b000003110000613d000000000c980019000000800b9001bf000000200cc0008a000000000dac0019000000000eab0019000000000e0e04330000000000ed0435000000200aa0008c0000030b0000c13d000000000009004b000006250000613d000000a00a000039000000000b0800190000061b0000013d000000240030008c000009610000413d0000000001000416000000000001004b000009610000c13d0b9c0a8d0000040f00000004010000390000000101100367000000000101043b0b9c097d0000040f0b9c0b1b0000040f0000002002000039000000400300043d000900000003001d00000000022304360b9c0a4c0000040f00000009020000290000000001210049000002e90010009c000002e9010080410000006001100210000002e90020009c000002e9020080410000004002200210000000000121019f00000b9d0001042e0000000001000416000000000001004b000009610000c13d0000000301000039000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f0000030d0100004100000b9d0001042e000000240030008c000009610000413d0000000002000416000000000002004b000009610000c13d0000000401100370000000000101043b0000000702000039000000000202041a000000000021004b000009610000813d0b9c097d0000040f0000000002010019000900000001001d0000000101100039000000000101041a000800000001001d000000000102041a000700000001001d00000002012000390b9c098b0000040f00000009020000290000000302200039000000000202041a000900000002001d000000400400043d000600000004001d0000004002400039000000800300003900000000003204350000002002400039000000080300002900000000003204350000000702000029000000000024043500000080024000390b9c09d80000040f00000006030000290000006002300039000000090400002900000000004204350000000001310049000002e90010009c000002e901008041000002e90030009c000002e90300804100000060011002100000004002300210000000000121019f00000b9d0001042e0000000001000416000000000001004b000009610000c13d0000000301000039000000000101041a0000000801100270000002ec01100197000000800010043f0000030d0100004100000b9d0001042e000000240030008c000009610000413d0000000002000416000000000002004b000009610000c13d0000000401100370000000000101043b000002ec0010009c000009610000213d000000000010043f0000000901000039000000200010043f00000040010000390b9c0b810000040f000000000101041a000000800010043f0000030d0100004100000b9d0001042e0000000001000416000000000001004b000009610000c13d0000000601000039000000000501041a0000030e0050009c000003950000213d00000005025002100000003f022000390000032a022001970000030f0020009c000003b90000a13d0000033601000041000000000010043f0000004101000039000000040010043f000003370100004100000b9e00010430000000000100041a000002ec01100197000000000012004b00000000010000190000032201006041000800000001001d000000000020043f0000000901000039000000200010043f0000000001000414000002e90010009c000002e901008041000000c00110021000000323011001c700008010020000390b9c0b970000040f0000000100200190000009610000613d000000000101043b000000000101041a000000000001004b000004370000c13d0000000802000029000000400100043d0000000000210435000002e90010009c000002e901008041000000400110021000000329011001c700000b9d0001042e000000800e2000390000004000e0043f000000800050043f000000000010043f000000000005004b0000043f0000c13d000000200100003900000000021e0436000000800100043d00000000001204350000004002e0003900000005031002100000000003230019000900000001001d000000000001004b000004f50000c13d0000000001e30049000002e90010009c000002e9010080410000006001100210000002e900e0009c000002e90e0080410000004002e00210000000000121019f00000b9d0001042e000000a0060000390000032b08000041000000200900008a000000000a000019000200000005001d0000030f0070009c000003950000213d0000008001700039000000400010043f000000000108041a000000000117043600000001028001bf000000000202041a000000000021043500000002018001bf000000000201041a0000000103200190000000010c2002700000007f0cc0618f0000001f00c0008c00000000040000390000000104002039000000000442013f0000000100400190000006090000c13d000000400b00043d0000000004cb0436000000000003004b000004150000613d000300000004001d00040000000c001d00050000000b001d00060000000a001d000700000008001d000800000006001d000900000007001d000000000010043f0000000001000414000002e90010009c000002e901008041000000c0011002100000032c011001c700008010020000390b9c0b970000040f0000000100200190000009610000613d000000040c00002900000000000c004b00000002050000290000000806000029000000200900008a000000060a0000290000041b0000613d000000000201043b000000000100001900000009070000290000000708000029000000050b000029000000030d00002900000000031d0019000000000402041a0000000000430435000000010220003900000020011000390000000000c1004b0000040d0000413d0000041f0000013d0000034501200197000000000014043500000000000c004b000000200100003900000000010060390000041f0000013d000000000100001900000009070000290000000708000029000000050b0000290000003f01100039000000000291016f0000000001b20019000000000021004b000000000200003900000001020040390000030e0010009c000003950000213d0000000100200190000003950000c13d000000400010043f00000040017000390000000000b1043500000003018001bf000000000101041a0000006002700039000000000012043500000000067604360000000408800039000000400700043d000000010aa0003900000000005a004b000003d70000413d000002540000013d0000000601000039000000000101041a000000000001004b000005460000c13d0000032801000041000000000010043f000003260100004100000b9e00010430000000a0060000390000033907000041000000200800008a0000000009000019000200000005001d0000030f00e0009c000003950000213d0000008001e00039000000400010043f000000000107041a00000000011e04360000000102700039000000000202041a000002ec0220019700000000002104350000000201700039000000000201041a0000000103200190000000010b2002700000007f0bb0618f0000001f00b0008c00000000040000390000000104002039000000000442013f0000000100400190000006090000c13d000000400a00043d0000000004ba0436000000000003004b000004830000613d000300000004001d00040000000b001d00050000000a001d000600000009001d000700000007001d000800000006001d00090000000e001d000000000010043f0000000001000414000002e90010009c000002e901008041000000c0011002100000032c011001c700008010020000390b9c0b970000040f0000000100200190000009610000613d000000040b00002900000000000b004b00000002050000290000000806000029000000200800008a0000000609000029000004890000613d000000000201043b0000000001000019000000090e0000290000000707000029000000050a000029000000030c00002900000000031c0019000000000402041a0000000000430435000000010220003900000020011000390000000000b1004b0000047b0000413d0000048d0000013d0000034501200197000000000014043500000000000b004b000000200100003900000000010060390000048d0000013d0000000001000019000000090e0000290000000707000029000000050a0000290000003f01100039000000000281016f0000000001a20019000000000021004b000000000200003900000001020040390000030e0010009c000003950000213d0000000100200190000003950000c13d000000400010043f0000004001e000390000000000a104350000000301700039000000000101041a0000006002e0003900000000001204350000000006e604360000000407700039000000400e00043d0000000109900039000000000059004b000004440000413d000003bf0000013d000000a005000039000000200b00008a0000000006000019000900000007001d000004c20000013d0000000301b00210000000000b0d0433000000000b1b01cf000000000b1b022f000000000a0a04330000010001100089000000000a1a022f00000000011a01cf0000000001b1019f00000000001d04350000000001980019000000000001043500000060013000390000006003700039000000000303043300000000003104350000001f01800039000000000b020019000000000121016f00000000039100190000000106600039000000080060006c00000009070000290000025e0000813d0000000007730049000000400770008a00000000047404360000000057050434000000009807043400000000088304360000000009090433000000000098043500000040087000390000000008080433000000400930003900000080010000390000000000190435000000800930003900000000a8080434000000000089043500000000020b0019000000000cb8016f0000001f0b80018f000000a00930003900000000009a004b000004e80000813d00000000000c004b000004e40000613d000000000eba0019000000000db90019000000200dd0008a000000200ee0008a000000000fcd00190000000001ce0019000000000101043300000000001f0435000000200cc0008c000004de0000c13d00000000000b004b000004b40000613d000000000d090019000004aa0000013d000000000dc9001900000000000c004b000004f10000613d000000000e0a0019000000000f09001900000000e10e0434000000000f1f04360000000000df004b000004ed0000c13d00000000000b004b000004b40000613d000000000aca0019000004aa0000013d000000a004000039000000200b00008a0000000006000019000005110000013d000000000aca00190000000301b00210000000000b0d0433000000000b1b01cf000000000b1b022f000000000a0a04330000010001100089000000000a1a022f00000000011a01cf0000000001b1019f00000000001d04350000000001980019000000000001043500000060013000390000006003700039000000000303043300000000003104350000001f01800039000000200b00008a0000000001b1016f00000000039100190000000106600039000000090060006c000003c90000813d00000000050e00190000000007e30049000000400770008a00000000027204360000000047040434000000009807043400000000088304360000000009090433000002ec09900197000000000098043500000040087000390000000008080433000000400930003900000080010000390000000000190435000000800930003900000000a80804340000000000890435000000000cb8016f0000001f0b80018f000000a00930003900000000009a004b000005390000813d00000000000c004b000005340000613d000000000eba0019000000000db90019000000200dd0008a000000200ee0008a000000000fcd00190000000001ce0019000000000101043300000000001f0435000000200cc0008c0000052e0000c13d00000000000b004b000000000e050019000005040000613d000000000d090019000004fa0000013d000000000dc9001900000000000c004b000005420000613d000000000e0a0019000000000f09001900000000e10e0434000000000f1f04360000000000df004b0000053e0000c13d00000000000b004b000000000e050019000004f90000c13d000005040000013d000700000001001d0000000901000029000000000010043f0000000901000039000000200010043f0000000001000414000002e90010009c000002e901008041000000c00110021000000323011001c700008010020000390b9c0b970000040f0000000100200190000009610000613d00000007020000290000032402200129000000000101043b000000000101041a000000000001004b0000058a0000613d0000034703100129000000000032004b0000058a0000a13d0000032501000041000000000010043f000003260100004100000b9e00010430000000400100043d00000044021000390000033b03000041000000000032043500000024021000390000000a03000039000005af0000013d0000000101000039000000000201041a0000000001000416000000000021004b000005a20000c13d0000000202000039000000000302041a000000000013001a000005840000413d0000000001130019000000000012041b0000000001000411000000000010043f0000000901000039000000200010043f0000000001000414000002e90010009c000002e901008041000000c00110021000000323011001c700008010020000390b9c0b970000040f0000000100200190000009610000613d000000000101043b000000000201041a000000010220003a000005ba0000c13d0000033601000041000000000010043f0000001101000039000000040010043f000003370100004100000b9e0001043000000000012100a9000003270110012a0000000802100029000003b20000013d000000400100043d00000064021000390000033c03000041000000000032043500000044021000390000033d0300004100000000003204350000002402100039000000270300003900000000003204350000032e020000410000000000210435000000040210003900000020030000390000000000320435000002e90010009c000002e90100804100000040011002100000033e011001c700000b9e00010430000000400100043d00000044021000390000032d03000041000000000032043500000024021000390000000d03000039000005af0000013d000000400100043d00000044021000390000033f03000041000000000032043500000024021000390000001c0300003900000000003204350000032e020000410000000000210435000000040210003900000020030000390000000000320435000002e90010009c000002e90100804100000040011002100000032f011001c700000b9e00010430000000000021041b000000400100043d000900000001001d0000030f0010009c000003950000213d0000000601000039000000000201041a00000009040000290000008001400039000000400010043f00000040034000390000008001000039000700000003001d0000000000130435000800000002001d00000000022404360000000001000411000600000002001d00000000001204350000031e0100004100000000001004430000000001000414000002e90010009c000002e901008041000000c0011002100000031f011001c70000800b020000390b9c0b970000040f0000000100200190000007da0000613d000000000101043b00000009020000290000006002200039000500000002001d000000000012043500000008010000290000030e0010009c000003950000213d000000080200002900000001012000390000000603000039000000000013041b000000000030043f000000090100002900000000010104330000000203200210000003300230009a000000000012041b00000006010000290000000001010433000002ec01100197000900000003001d000003310230009a000000000302041a000002ed03300197000000000113019f000000000012041b00000007010000290000000001010433000400000001001d0000000021010434000600000002001d000700000001001d0000030e0010009c000003950000213d0000000901000029000003320110009a000300000001001d000000000101041a000000010010019000000001021002700000007f0220618f000200000002001d0000001f0020008c00000000020000390000000102002039000000000121013f0000000100100190000006430000613d0000033601000041000000000010043f0000002201000039000000040010043f000003370100004100000b9e00010430000000000ba8001900000000000a004b000006180000613d000000a00c000039000000000d08001900000000ce0c0434000000000ded04360000000000bd004b000006140000c13d000000000009004b000006250000613d000000a00aa000390000000309900210000000000c0b0433000000000c9c01cf000000000c9c022f000000000a0a04330000010009900089000000000a9a022f00000000099a01cf0000000009c9019f00000000009b0435000000000987001900000000000904350000001f07700039000003460770019700000000078700190000000006670049000000c40810003900000000006804350000000006050433000000000567043600000346086001970000001f0760018f000000000054004b000006760000813d000000000008004b0000063f0000613d000000000a7400190000000009750019000000200990008a000000200aa0008a000000000b890019000000000c8a0019000000000c0c04330000000000cb0435000000200880008c000006390000c13d000000000007004b0000068c0000613d0000000009050019000006820000013d0000000201000029000000200010008c000006620000413d0000000301000029000000000010043f0000000001000414000002e90010009c000002e901008041000000c0011002100000032c011001c700008010020000390b9c0b970000040f0000000100200190000009610000613d00000007030000290000001f023000390000000502200270000000200030008c0000000002004019000000000301043b00000002010000290000001f01100039000000050110027000000000011300190000000002230019000000000012004b000006620000813d000000000002041b0000000102200039000000000012004b0000065e0000413d00000007010000290000001f0010008c000007fc0000a13d0000000301000029000000000010043f0000000001000414000002e90010009c000002e901008041000000c0011002100000032c011001c700008010020000390b9c0b970000040f0000000100200190000009610000613d000000200200008a0000000702200180000000000101043b000008160000c13d0000002003000039000008230000013d0000000009850019000000000008004b0000067f0000613d000000000a040019000000000b05001900000000ac0a0434000000000bcb043600000000009b004b0000067b0000c13d000000000007004b0000068c0000613d00000000048400190000000307700210000000000809043300000000087801cf000000000878022f00000000040404330000010007700089000000000474022f00000000047401cf000000000484019f0000000000490435000000000456001900000000000404350000004404100039000000000700041400000000003404350000001f03600039000003460230019700000000031500490000000002320019000000840320008a000000640410003900000000003404350000031303000041000000000031043500000004031000390000000000030435000002e90020009c000002e9020080410000006002200210000002e90010009c000002e9010080410000004001100210000000000112019f000002e90070009c000002e907008041000000c002700210000000000112019f00000314011001c700008006020000390b9c0b920000040f0000000100200190000007db0000613d00000000020000310000000103200367000000000101043b000000000001004b0000000002000019000007de0000613d000902ec0010019b0000000402000039000000000102041a000002ed0110019700000009011001af000000000012041b0000000201000039000000000101041a000000000001004b0000091b0000613d000003150100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000002e90010009c000002e901008041000000c00110021000000316011001c700008005020000390b9c0b970000040f0000000100200190000007da0000613d000000000201043b000000400300043d000800000003001d00000317010000410000000000130435000002e90030009c000002e901000041000000000103401900000040011002100000000003000414000002e90030009c000002e903008041000000c003300210000000000113019f00000318011001c7000002ec02200197000700000002001d0b9c0b970000040f0000006003100270000002e903300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000080b0000290000000805700029000006ec0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000006e80000c13d000000000006004b000006f90000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000008910000613d0000001f01400039000000600110018f0000000002b10019000000000012004b00000000010000390000000101004039000600000002001d0000030e0020009c000003950000213d0000000100100190000003950000c13d0000000601000029000000400010043f000000200030008c000009610000413d00000000010b0433000002ec0010009c000009610000213d000000060300002900000024023000390000000000120435000003190100004100000000001304350000000401300039000000090200002900000000002104350000031501000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000002e90010009c000002e901008041000000c00110021000000316011001c700008005020000390b9c0b970000040f0000000100200190000007da0000613d000000000201043b0000000601000029000002e90010009c000002e90100804100000040011002100000000003000414000002e90030009c000002e903008041000000c003300210000000000113019f0000031a011001c7000002ec022001970b9c0b920000040f0000006003100270000002e903300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000605700029000007400000613d000000000801034f0000000609000029000000008a08043c0000000009a90436000000000059004b0000073c0000c13d000000000006004b0000074d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f000000000065043500000001002001900000091d0000613d0000001f01400039000000600110018f0000000601100029000900000001001d0000030e0010009c000003950000213d0000000901000029000000400010043f000000200030008c000009610000413d00000006010000290000000001010433000002ec0010009c000009610000213d0000000502000039000000000302041a000002ed03300197000000000113019f000000000012041b0000000401000039000000000201041a000000090400002900000024014000390000031b0300004100000000003104350000031c010000410000000000140435000000040140003900000007030000290000000000310435000002e90040009c000002e901000041000000000104401900000040011002100000000003000414000002e90030009c000002e903008041000000c003300210000000000113019f0000031a011001c7000002ec022001970b9c0b920000040f0000006003100270000002e903300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000905700029000007880000613d000000000801034f0000000909000029000000008a08043c0000000009a90436000000000059004b000007840000c13d000000000006004b000007950000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000009290000613d0000001f01400039000000600110018f0000000901100029000800000001001d0000030e0010009c000003950000213d0000000801000029000000400010043f000000200030008c000009610000413d00000009010000290000000001010433000000000001004b0000000002000039000000010200c039000000000021004b000009610000c13d0000000201000039000000000101041a000900000001001d0000000401000039000000000101041a000000080400002900000084024000390000dead03000039000000000032043500000024024000390000031b0300004100000000003204350000031d020000410000000000240435000002ec011001970000000402400039000000000012043500000064014000390000000000010435000000440140003900000000000104350000031e0100004100000000001004430000000001000414000002e90010009c000002e901008041000000c0011002100000031f011001c70000800b020000390b9c0b970000040f0000000100200190000007da0000613d000000000101043b0000000803000029000000a4023000390000000000120435000002e90030009c000002e901000041000000000103401900000040011002100000000002000414000002e90020009c000002e902008041000000c002200210000000000112019f000000090000006b000009350000c13d00000321011001c700000007020000290000093a0000013d000000000001042f0000006002100270000002e902200197000000000301034f0000001f0520018f000002eb06200198000000400100043d0000000004610019000007e90000613d000000000703034f0000000008010019000000007907043c0000000008980436000000000048004b000007e50000c13d000000000005004b000007f60000613d000000000363034f0000000305500210000000000604043300000000065601cf000000000656022f000000000303043b0000010005500089000000000353022f00000000035301cf000000000363019f00000000003404350000006002200210000002e90010009c000002e9010080410000004001100210000000000121019f00000b9e00010430000000070000006b0000000001000019000008010000613d0000000601000029000000000101043300000007040000290000000302400210000003470220027f0000034702200167000000000121016f0000000102400210000000000121019f000008310000013d000000060000006b00000000010000190000080e0000613d0000000501000029000000000101043300000006040000290000000302400210000003470220027f0000034702200167000000000121016f0000000102400210000000000121019f000008ca0000013d000000010320008a0000000503300270000000000431001900000020030000390000000104400039000000040600002900000000056300190000000005050433000000000051041b00000020033000390000000101100039000000000041004b0000081c0000c13d000000070020006c0000082e0000813d00000007020000290000000302200210000000f80220018f000003470220027f000003470220016700000004033000290000000003030433000000000223016f000000000021041b0000000701000029000000010110021000000001011001bf0000000302000029000000000012041b0000000901000029000003330110009a00000005020000290000000002020433000000000021041b0000000101000039000000000201041a00000065012000c9000000000002004b000008400000613d00000000022100d9000000650020008c0000088d0000c13d000000641210011a000000000001004b000000010220c0390000000101000039000000000021041b0000002002000039000000400100043d0000000003210436000000800200043d000000000023043500000346052001970000001f0420018f0000004003100039000000a10030008c0000085f0000413d000000000005004b0000085a0000613d000000000743001900000080064001bf000000200770008a0000000008570019000000000956001900000000090904330000000000980435000000200550008c000008540000c13d000000000004004b000008750000613d000000a00500003900000000060300190000086b0000013d0000000006530019000000000005004b000008680000613d000000a007000039000000000803001900000000790704340000000008980436000000000068004b000008640000c13d000000000004004b000008750000613d000000a0055000390000000304400210000000000706043300000000074701cf000000000747022f00000000050504330000010004400089000000000545022f00000000044501cf000000000474019f00000000004604350000001f042000390000034604400197000000000232001900000000000204350000004002400039000002e90020009c000002e9020080410000006002200210000002e90010009c000002e9010080410000004001100210000000000112019f0000000002000414000002e90020009c000002e902008041000000c002200210000000000121019f00000314011001c70000800d020000390000000303000039000003350400004100000008050000290000000006000411000009180000013d0000033401000041000000000010043f000003260100004100000b9e000104300000001f0530018f000002eb06300198000000400200043d00000000046200190000089c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008980000c13d000000000005004b000008a90000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000002e90020009c000002e9020080410000004002200210000000000112019f00000b9e00010430000000010320008a0000000503300270000000000431001900000020030000390000000104400039000000030600002900000000056300190000000005050433000000000051041b00000020033000390000000101100039000000000041004b000008b50000c13d000000060020006c000008c70000813d00000006020000290000000302200210000000f80220018f000003470220027f000003470220016700000003033000290000000003030433000000000223016f000000000021041b0000000601000029000000010110021000000001011001bf0000000202000029000000000012041b0000000801000029000003430110009a00000004020000290000000002020433000000000021041b0000002002000039000000400100043d0000000003210436000000800200043d000000000023043500000346052001970000001f0420018f0000004003100039000000a10030008c000008eb0000413d000000000005004b000008e60000613d000000000743001900000080064001bf000000200770008a0000000008570019000000000956001900000000090904330000000000980435000000200550008c000008e00000c13d000000000004004b000009010000613d000000a0050000390000000006030019000008f70000013d0000000006530019000000000005004b000008f40000613d000000a007000039000000000803001900000000790704340000000008980436000000000068004b000008f00000c13d000000000004004b000009010000613d000000a0055000390000000304400210000000000706043300000000074701cf000000000747022f00000000050504330000010004400089000000000545022f00000000044501cf000000000474019f00000000004604350000001f042000390000034604400197000000000232001900000000000204350000004002400039000002e90020009c000002e9020080410000006002200210000002e90010009c000002e9010080410000004001100210000000000112019f0000000002000414000002e90020009c000002e902008041000000c002200210000000000121019f00000314011001c70000800d0200003900000003030000390000034404000041000000070500002900000009060000290b9c0b920000040f0000000100200190000009610000613d000000000100001900000b9d0001042e0000001f0530018f000002eb06300198000000400200043d00000000046200190000089c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009240000c13d0000089c0000013d0000001f0530018f000002eb06300198000000400200043d00000000046200190000089c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009300000c13d0000089c0000013d00000320011001c700008009020000390000000903000029000000070400002900000000050000190b9c0b920000040f0000006003100270000002e903300197000000600030008c000000600400003900000000040340190000001f0640018f000000600740019000000008057000290000094a0000613d000000000801034f0000000809000029000000008a08043c0000000009a90436000000000059004b000009460000c13d000000000006004b000009570000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000009630000613d0000001f01400039000000e00110018f00000008011000290000030e0010009c000003950000213d000000400010043f000000600030008c0000091b0000813d000000000100001900000b9e000104300000001f0530018f000002eb06300198000000400200043d00000000046200190000089c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000096a0000c13d0000089c0000013d0000000602000039000000000302041a000000000013004b000009770000a13d000000000020043f0000000201100210000003300110009a000000000001042d0000033601000041000000000010043f0000003201000039000000040010043f000003370100004100000b9e000104300000000702000039000000000302041a000000000013004b000009850000a13d000000000020043f0000000201100210000003400110009a000000000001042d0000033601000041000000000010043f0000003201000039000000040010043f000003370100004100000b9e000104300003000000000002000000000201041a000000010320019000000001062002700000007f0660618f0000001f0060008c00000000040000390000000104002039000000000043004b000009ca0000c13d000000400500043d0000000004650436000000000003004b000009b50000613d000100000004001d000300000006001d000200000005001d000000000010043f0000000001000414000002e90010009c000002e901008041000000c0011002100000032c011001c700008010020000390b9c0b970000040f0000000100200190000009d60000613d0000000306000029000000000006004b000009bb0000613d000000000201043b0000000001000019000000020500002900000001070000290000000003170019000000000402041a000000000043043500000001022000390000002001100039000000000061004b000009ad0000413d000009bd0000013d00000345012001970000000000140435000000000006004b00000020010000390000000001006039000009bd0000013d000000000100001900000002050000290000003f0110003900000346021001970000000001520019000000000021004b000000000200003900000001020040390000030e0010009c000009d00000213d0000000100200190000009d00000c13d000000400010043f0000000001050019000000000001042d0000033601000041000000000010043f0000002201000039000000040010043f000003370100004100000b9e000104300000033601000041000000000010043f0000004101000039000000040010043f000003370100004100000b9e00010430000000000100001900000b9e000104300000000043010434000000000132043600000346063001970000001f0530018f000000000014004b000009ee0000813d000000000006004b000009ea0000613d00000000085400190000000007510019000000200770008a000000200880008a0000000009670019000000000a680019000000000a0a04330000000000a90435000000200660008c000009e40000c13d000000000005004b00000a040000613d0000000007010019000009fa0000013d0000000007610019000000000006004b000009f70000613d00000000080400190000000009010019000000008a0804340000000009a90436000000000079004b000009f30000c13d000000000005004b00000a040000613d00000000046400190000000305500210000000000607043300000000065601cf000000000656022f00000000040404330000010005500089000000000454022f00000000045401cf000000000464019f0000000000470435000000000431001900000000000404350000001f0330003900000346023001970000000001210019000000000001042d000000004301043400000000033204360000000004040433000002ec0440019700000000004304350000004003100039000000000303043300000040042000390000008005000039000000000054043500000080042000390000000063030434000000000034043500000346083001970000001f0730018f000000a005200039000000000056004b00000a2c0000813d000000000008004b00000a280000613d000000000a7600190000000009750019000000200990008a000000200aa0008a000000000b890019000000000c8a0019000000000c0c04330000000000cb0435000000200880008c00000a220000c13d000000000007004b00000a420000613d000000000905001900000a380000013d0000000009850019000000000008004b00000a350000613d000000000a060019000000000b05001900000000ac0a0434000000000bcb043600000000009b004b00000a310000c13d000000000007004b00000a420000613d00000000068600190000000307700210000000000809043300000000087801cf000000000878022f00000000060604330000010007700089000000000676022f00000000067601cf000000000686019f00000000006904350000000006530019000000000006043500000060022000390000006001100039000000000101043300000000001204350000001f0130003900000346011001970000000001510019000000000001042d00000000430104340000000003320436000000000404043300000000004304350000004003100039000000000303043300000040042000390000008005000039000000000054043500000080042000390000000063030434000000000034043500000346083001970000001f0730018f000000a005200039000000000056004b00000a6d0000813d000000000008004b00000a690000613d000000000a7600190000000009750019000000200990008a000000200aa0008a000000000b890019000000000c8a0019000000000c0c04330000000000cb0435000000200880008c00000a630000c13d000000000007004b00000a830000613d000000000905001900000a790000013d0000000009850019000000000008004b00000a760000613d000000000a060019000000000b05001900000000ac0a0434000000000bcb043600000000009b004b00000a720000c13d000000000007004b00000a830000613d00000000068600190000000307700210000000000809043300000000087801cf000000000878022f00000000060604330000010007700089000000000676022f00000000067601cf000000000686019f00000000006904350000000006530019000000000006043500000060022000390000006001100039000000000101043300000000001204350000001f0130003900000346011001970000000001510019000000000001042d000000400100043d000003480010009c00000a9b0000813d0000008002100039000000400020043f00000040021000390000006003000039000000000032043500000060021000390000000000020435000000200210003900000000000204350000000000010435000000000001042d0000033601000041000000000010043f0000004101000039000000040010043f000003370100004100000b9e000104300005000000000002000000400500043d000003480050009c00000af90000813d00000000060100190000008001500039000000400010043f000000000106041a00000000011504360000000102600039000000000202041a000002ec0220019700000000002104350000000201600039000000000201041a000000010320019000000001082002700000007f0880618f0000001f0080008c00000000040000390000000104002039000000000043004b00000aff0000c13d000000400700043d0000000004870436000000000003004b00000adc0000613d000100000004001d000500000008001d000200000007001d000300000006001d000400000005001d000000000010043f0000000001000414000002e90010009c000002e901008041000000c0011002100000032c011001c700008010020000390b9c0b970000040f000000010020019000000b050000613d0000000508000029000000000008004b00000ae20000613d000000000201043b000000000100001900000004050000290000000306000029000000020700002900000001090000290000000003190019000000000402041a000000000043043500000001022000390000002001100039000000000081004b00000ad40000413d00000ae60000013d00000345012001970000000000140435000000000008004b0000002001000039000000000100603900000ae60000013d00000000010000190000000405000029000000030600002900000002070000290000003f0110003900000346021001970000000001720019000000000021004b000000000200003900000001020040390000030e0010009c00000af90000213d000000010020019000000af90000c13d000000400010043f000000400150003900000000007104350000000301600039000000000101041a000000600250003900000000001204350000000001050019000000000001042d0000033601000041000000000010043f0000004101000039000000040010043f000003370100004100000b9e000104300000033601000041000000000010043f0000002201000039000000040010043f000003370100004100000b9e00010430000000000100001900000b9e00010430000000000001004b00000b0a0000613d000000000001042d000000400100043d00000044021000390000033b03000041000000000032043500000024021000390000000a0300003900000000003204350000032e020000410000000000210435000000040210003900000020030000390000000000320435000002e90010009c000002e90100804100000040011002100000032f011001c700000b9e000104300005000000000002000000400500043d000003480050009c00000b720000813d00000000060100190000008001500039000000400010043f000000000106041a00000000011504360000000102600039000000000202041a00000000002104350000000201600039000000000201041a000000010320019000000001082002700000007f0880618f0000001f0080008c00000000040000390000000104002039000000000043004b00000b780000c13d000000400700043d0000000004870436000000000003004b00000b550000613d000100000004001d000500000008001d000200000007001d000300000006001d000400000005001d000000000010043f0000000001000414000002e90010009c000002e901008041000000c0011002100000032c011001c700008010020000390b9c0b970000040f000000010020019000000b7e0000613d0000000508000029000000000008004b00000b5b0000613d000000000201043b000000000100001900000004050000290000000306000029000000020700002900000001090000290000000003190019000000000402041a000000000043043500000001022000390000002001100039000000000081004b00000b4d0000413d00000b5f0000013d00000345012001970000000000140435000000000008004b0000002001000039000000000100603900000b5f0000013d00000000010000190000000405000029000000030600002900000002070000290000003f0110003900000346021001970000000001720019000000000021004b000000000200003900000001020040390000030e0010009c00000b720000213d000000010020019000000b720000c13d000000400010043f000000400150003900000000007104350000000301600039000000000101041a000000600250003900000000001204350000000001050019000000000001042d0000033601000041000000000010043f0000004101000039000000040010043f000003370100004100000b9e000104300000033601000041000000000010043f0000002201000039000000040010043f000003370100004100000b9e00010430000000000100001900000b9e00010430000000000001042f000002e90010009c000002e90100804100000060011002100000000002000414000002e90020009c000002e902008041000000c002200210000000000112019f00000314011001c700008010020000390b9c0b970000040f000000010020019000000b900000613d000000000101043b000000000001042d000000000100001900000b9e0001043000000b95002104210000000102000039000000000001042d0000000002000019000000000001042d00000b9a002104230000000102000039000000000001042d0000000002000019000000000001042d00000b9c0000043200000b9d0001042e00000b9e000104300000000000000000010001f7a2b1f3743cff52325e3ce5a90fc379bccaa6cb0cddf7234dfb062dd600000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000002000000000000000000000000000000c000000100000000000000000000000000000000000000000000000000000000000000000000000000719ce73d0000000000000000000000000000000000000000000000000000000090e2758100000000000000000000000000000000000000000000000000000000dfbf53ad00000000000000000000000000000000000000000000000000000000dfbf53ae00000000000000000000000000000000000000000000000000000000e44d8e1c00000000000000000000000000000000000000000000000000000000fc0c546a0000000000000000000000000000000000000000000000000000000090e2758200000000000000000000000000000000000000000000000000000000a8aa1b3100000000000000000000000000000000000000000000000000000000ddd49c1300000000000000000000000000000000000000000000000000000000884bf67b00000000000000000000000000000000000000000000000000000000884bf67c000000000000000000000000000000000000000000000000000000008d2143dc000000000000000000000000000000000000000000000000000000008da5cb5b00000000000000000000000000000000000000000000000000000000719ce73e000000000000000000000000000000000000000000000000000000008193302900000000000000000000000000000000000000000000000000000000843433e30000000000000000000000000000000000000000000000000000000052e1e92c000000000000000000000000000000000000000000000000000000005ff6cbf2000000000000000000000000000000000000000000000000000000005ff6cbf3000000000000000000000000000000000000000000000000000000006d65331200000000000000000000000000000000000000000000000000000000708b34fe0000000000000000000000000000000000000000000000000000000052e1e92d0000000000000000000000000000000000000000000000000000000054cc76a70000000000000000000000000000000000000000000000000000000056d13a80000000000000000000000000000000000000000000000000000000000f4cf691000000000000000000000000000000000000000000000000000000000f4cf6920000000000000000000000000000000000000000000000000000000017902601000000000000000000000000000000000000000000000000000000004fb2e45d000000000000000000000000000000000000000000000000000000000c0ef2b0000000000000000000000000000000000000000000000000000000000d80fefd0000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffff7fffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000ffffffffffffff7b9c4d535bdea7cd8a978f128b93471df48c7dbab89d703809115bdc118c235bfd0200000000000000000000000000000000000000000000000000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0200000200000000000000000000000000000044000000000000000000000000ad5c4648000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000c9c653960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000000000000000000000000000000000000000000000000000024306c4097859c43c000000095ea7b300000000000000000000000000000000000000000000000000000000f305d71900000000000000000000000000000000000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132020000020000000000000000000000000000000400000000000000000000000002000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000c400000000000000000000000000000000000000000000000000000000000000000014adf4b7320334b90000000200000000000000000000000000000000000040000000000000000000000000000000000000000000000000000b35dbf821ae4f38bdda2802c8a8000000000000000000000000000000000000000000000000000000000000000000bac65e5b00000000000000000000000000000000000000040000001c00000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000000000000000000000000000000000007c5f487d00000000000000000000000000000000000000200000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0a66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880200000000000000000000000000000000000020000000000000000000000000496e636f7272656374206665650000000000000000000000000000000000000008c379a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006400000000000000000000000009addddcec1d7ba6ad726df49aeea3e93fb0c1037d551236841a60c0c883f2c109addddcec1d7ba6ad726df49aeea3e93fb0c1037d551236841a60c0c883f2c009addddcec1d7ba6ad726df49aeea3e93fb0c1037d551236841a60c0c883f2bf09addddcec1d7ba6ad726df49aeea3e93fb0c1037d551236841a60c0c883f2be00000000000000000000000000000000000000000000000000000000ad251c2720b26bd2450264026954a2a2c88bcad73c60c0e689fe0d12d646d86bfd1642004e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000047616d65206973206f7665720000000000000000000000000000000000000000f652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f00000000000000000000000000000000000000000000000100000000000000004f6e6c79206f776e65720000000000000000000000000000000000000000000074206578697374000000000000000000000000000000000000000000000000004d65737361676520494420746f20726573706f6e6420746f20646f6573206e6f00000000000000000000000000000000000000840000000000000000000000004d65737361676520616c726561647920726573706f6e64656420746f00000000599336d74a1247d50642b66dd6abeaa5484f6bd96b415b31bb99e26578c93978599336d74a1247d50642b66dd6abeaa5484f6bd96b415b31bb99e26578c93977599336d74a1247d50642b66dd6abeaa5484f6bd96b415b31bb99e26578c93976599336d74a1247d50642b66dd6abeaa5484f6bd96b415b31bb99e26578c93975b7cfa42f7f83eac8a1ada3f18c51fc04fa2fe60fc2ff50c9b0250df2bf4068c8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffff800000000000000000000000000000000000000000000000000000000000000000ee0334848e27c55782083aea62b9a21de32d1791fc558c6888f6d0f037aca706
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000ad1eca41e6f772be3cb5a48a6141f9bcc1af9f7c000000000000000000000000566d7510dee58360a64c9827257cf6d0dc43985e
-----Decoded View---------------
Arg [0] : _messagePrice (uint256): 5000000000000000
Arg [1] : _uniswapRouter (address): 0xad1eCa41E6F772bE3cb5A48A6141f9bcc1AF9F7c
Arg [2] : _uniswapFactory (address): 0x566d7510dEE58360a64C9827257cF6D0Dc43985E
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000011c37937e08000
Arg [1] : 000000000000000000000000ad1eca41e6f772be3cb5a48a6141f9bcc1af9f7c
Arg [2] : 000000000000000000000000566d7510dee58360a64c9827257cf6d0dc43985e
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.