Latest 25 from a total of 35,441 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Claim Points | 26134744 | 12 secs ago | IN | 0 ETH | 0.00000543 | ||||
| Stake | 26134652 | 53 secs ago | IN | 0 ETH | 0.00000671 | ||||
| Claim Points | 26133243 | 11 mins ago | IN | 0 ETH | 0.00000408 | ||||
| Claim Points | 26133197 | 11 mins ago | IN | 0 ETH | 0.00000518 | ||||
| Claim Points | 26133030 | 12 mins ago | IN | 0 ETH | 0.00000543 | ||||
| Stake | 26132950 | 13 mins ago | IN | 0 ETH | 0.00000619 | ||||
| Claim Points | 26132776 | 14 mins ago | IN | 0 ETH | 0.00000663 | ||||
| Claim Points | 26132643 | 15 mins ago | IN | 0 ETH | 0.00000518 | ||||
| Stake | 26132604 | 15 mins ago | IN | 0 ETH | 0.00000619 | ||||
| Claim Points | 26132519 | 16 mins ago | IN | 0 ETH | 0.00000518 | ||||
| Claim Points | 26132322 | 17 mins ago | IN | 0 ETH | 0.00000518 | ||||
| Claim Points | 26132260 | 18 mins ago | IN | 0 ETH | 0.00000714 | ||||
| Claim Points | 26132003 | 20 mins ago | IN | 0 ETH | 0.00000408 | ||||
| Claim Points | 26131945 | 20 mins ago | IN | 0 ETH | 0.00000408 | ||||
| Stake | 26131526 | 23 mins ago | IN | 0 ETH | 0.00000619 | ||||
| Claim Points | 26131498 | 23 mins ago | IN | 0 ETH | 0.00000442 | ||||
| Stake | 26131446 | 23 mins ago | IN | 0 ETH | 0.00000836 | ||||
| Claim Points | 26131063 | 26 mins ago | IN | 0 ETH | 0.00000408 | ||||
| Claim Points | 26130839 | 28 mins ago | IN | 0 ETH | 0.00000663 | ||||
| Claim Points | 26130443 | 31 mins ago | IN | 0 ETH | 0.00000433 | ||||
| Stake | 26130398 | 31 mins ago | IN | 0 ETH | 0.0000067 | ||||
| Claim Points | 26129626 | 37 mins ago | IN | 0 ETH | 0.00000594 | ||||
| Claim Points | 26127674 | 53 mins ago | IN | 0 ETH | 0.00000518 | ||||
| Claim Points | 26127620 | 53 mins ago | IN | 0 ETH | 0.00000714 | ||||
| Claim Points | 26124666 | 1 hr ago | IN | 0 ETH | 0.00000518 |
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 19880497 | 56 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
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:
KonaPointsFarm
Compiler Version
v0.8.28-1.0.1
ZkSolc Version
v1.5.15
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 {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {ReentrancyGuard} from "openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol";
import {Ownable} from "openzeppelin-contracts/contracts/access/Ownable.sol";
import {Math} from "openzeppelin-contracts/contracts/utils/math/Math.sol";
import {IKonaPointsFarm} from "./interfaces/IKonaPointsFarm.sol";
import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
contract KonaPointsFarm is IKonaPointsFarm, ReentrancyGuard, Ownable {
using SafeERC20 for IERC20;
/**
* CONSTANTS ***************************************
*/
uint256 public constant SCALAR_PRECISION = 1e36;
uint256 public constant POINTS_PER_BLOCK_PRECISION = 100;
FarmInfo[] public farms;
address public nftMinter;
/**
* MAPPINGS ***************************************
*/
mapping(address user => mapping(uint256 farmId => UserInfo info)) public userInfo;
mapping(address user => uint256 totalPoints) public totalPoints;
mapping(address user => uint256 spentPoints) public spentPoints;
constructor(address _owner) Ownable(_owner) { }
/**
*
* *
* ONLY OWNER FUNCTIONS *
* *
*
*/
function setNFTMinter(address _nftMinter) external onlyOwner {
require(_nftMinter != address(0), "Invalid nft minter");
nftMinter = _nftMinter;
emit NFTMinterSet(_nftMinter);
}
function addFarm(IERC20 _lpToken, uint256 _pointsPerBlock, uint256 _minStakeAmount) external onlyOwner returns (uint256) {
require(_pointsPerBlock >= 10, "Points must be gt 10");
require(address(_lpToken) != address(0), "Invalid lp token");
farms.push(
FarmInfo({
lpToken: _lpToken,
pointsPerBlock: _pointsPerBlock,
totalStaked: 0,
lastRewardBlock: block.number,
accPointsPerShare: 0,
active: true,
minStakeAmount: _minStakeAmount
})
);
uint256 farmId = farms.length - 1;
emit FarmAdded(farmId, address(_lpToken), _pointsPerBlock);
return farmId;
}
function updateFarmStatus(uint256 _farmId, bool _active, uint256 _pointsPerBlock, uint256 _minStakeAmount)
external
onlyOwner
{
require(_pointsPerBlock >= 10, "Points must be gt 10");
FarmInfo storage farm = farms[_farmId];
updateFarm(_farmId);
farm.active = _active;
farm.pointsPerBlock = _pointsPerBlock;
farm.minStakeAmount = _minStakeAmount;
emit FarmUpdated(_farmId);
}
function batchDistributePoints(address[] calldata _users, uint256[] calldata _points) external onlyOwner {
require(_users.length == _points.length, "Arrays length mismatch");
require(_users.length > 0, "No users provided");
uint256 totalDistributed = 0;
for (uint256 i = 0; i < _users.length; i++) {
require(_users[i] != address(0), "Invalid user address");
totalPoints[_users[i]] += _points[i];
totalDistributed += _points[i];
}
emit BatchPointsDistributed(msg.sender, _users.length, totalDistributed);
}
/**
* *
* PUBLIC/EXTERNAL FUNCTIONS *
* *
*/
function updateFarm(uint256 _farmId) public {
FarmInfo storage farm = farms[_farmId];
if (!farm.active || block.number <= farm.lastRewardBlock) return;
if (farm.totalStaked == 0) {
farm.lastRewardBlock = block.number;
return;
}
uint256 blocksElapsed = block.number - farm.lastRewardBlock;
uint256 pointsReward = blocksElapsed * farm.pointsPerBlock;
uint256 accPointsPerShareBeforePrecision =
Math.mulDiv(pointsReward, SCALAR_PRECISION, farm.totalStaked, Math.Rounding.Ceil);
farm.accPointsPerShare += Math.ceilDiv(accPointsPerShareBeforePrecision, POINTS_PER_BLOCK_PRECISION);
farm.lastRewardBlock = block.number;
}
function stake(uint256 _farmId, uint256 _amount) external nonReentrant {
FarmInfo storage farm = farms[_farmId];
require(_amount >= farm.minStakeAmount, "Amount lt minStakeAmount");
require(farm.active, "Farm is not active");
UserInfo storage user = userInfo[msg.sender][_farmId];
updateFarm(_farmId);
if (user.amount > 0) {
uint256 pendingPointsCount =
Math.mulDiv(user.amount, farm.accPointsPerShare, SCALAR_PRECISION) - user.pointsDebt;
totalPoints[msg.sender] += pendingPointsCount;
}
farm.totalStaked += _amount;
user.amount += _amount;
user.pointsDebt = Math.mulDiv(user.amount, farm.accPointsPerShare, SCALAR_PRECISION);
farm.lpToken.safeTransferFrom(msg.sender, address(this), _amount);
emit Stake(msg.sender, _farmId, _amount);
}
function unstake(uint256 _farmId, uint256 _amount) external nonReentrant {
FarmInfo storage farm = farms[_farmId];
UserInfo storage user = userInfo[msg.sender][_farmId];
require(user.amount >= _amount, "Insufficient staked amount");
uint256 remainingUserAmount = user.amount - _amount;
require(remainingUserAmount >= farm.minStakeAmount, "Remaining must be gt min");
updateFarm(_farmId);
uint256 pendingPointsCount =
Math.mulDiv(user.amount, farm.accPointsPerShare, SCALAR_PRECISION) - user.pointsDebt;
totalPoints[msg.sender] += pendingPointsCount;
farm.totalStaked -= _amount;
user.amount -= _amount;
user.pointsDebt = Math.mulDiv(user.amount, farm.accPointsPerShare, SCALAR_PRECISION);
farm.lpToken.safeTransfer(msg.sender, _amount);
emit Unstake(msg.sender, _farmId, _amount);
}
function claimPoints(uint256 _farmId) external nonReentrant {
FarmInfo storage farm = farms[_farmId];
UserInfo storage user = userInfo[msg.sender][_farmId];
updateFarm(_farmId);
uint256 pendingPointsCount =
Math.mulDiv(user.amount, farm.accPointsPerShare, SCALAR_PRECISION) - user.pointsDebt;
if (pendingPointsCount > 0) {
totalPoints[msg.sender] += pendingPointsCount;
user.pointsDebt = Math.mulDiv(user.amount, farm.accPointsPerShare, SCALAR_PRECISION);
emit ClaimPoints(msg.sender, _farmId, pendingPointsCount);
}
}
function spendPoints(address _user, uint256 _amount) external {
require(msg.sender == nftMinter, "Only NFTMinter can spend points");
require(totalPoints[_user] >= _amount, "Insufficient points");
totalPoints[_user] -= _amount;
spentPoints[_user] += _amount;
emit PointsSpent(_user, _amount);
}
/**
* *
* VIEW FUNCTIONS *
* *
*/
function getFarmsLength() external view returns (uint256) {
return farms.length;
}
/**
* Points******************************************
*/
function pendingPoints(uint256 _farmId, address _user) public view returns (uint256) {
FarmInfo storage farm = farms[_farmId];
UserInfo storage user = userInfo[_user][_farmId];
uint256 accPointsPerShare = farm.accPointsPerShare;
if (farm.active && block.number > farm.lastRewardBlock && farm.totalStaked != 0) {
uint256 blocksElapsed = block.number - farm.lastRewardBlock;
uint256 pointsReward = blocksElapsed * farm.pointsPerBlock;
uint256 accPointsPerShareBeforePrecision =
Math.mulDiv(pointsReward, SCALAR_PRECISION, farm.totalStaked, Math.Rounding.Ceil);
accPointsPerShare += Math.ceilDiv(accPointsPerShareBeforePrecision, POINTS_PER_BLOCK_PRECISION);
}
return Math.mulDiv(user.amount, accPointsPerShare, SCALAR_PRECISION) - user.pointsDebt;
}
function getRealTimePoints(address _user)
external
view
returns (uint256 claimedPoints, uint256 pendingTotalPoints)
{
claimedPoints = totalPoints[_user];
uint256 farmsCount = farms.length;
for (uint256 farmId = 0; farmId < farmsCount; farmId++) {
pendingTotalPoints += pendingPoints(farmId, _user);
}
return (claimedPoints, pendingTotalPoints);
}
function getTotalPoints(address _user) external view returns (uint256) {
return totalPoints[_user];
}
function getCountFarms() external view returns (uint256) {
return farms.length;
}
/**
* Only for emergency purposes
*
*/
function sweepTokens(address _token, address receiver) external onlyOwner {
require(receiver != address(0), "Invalid receiver address");
uint256 balance = IERC20(_token).balanceOf(address(this));
IERC20(_token).safeTransfer(receiver, balance);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
if (!_safeTransfer(token, to, value, true)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
if (!_safeTransferFrom(token, from, to, value, true)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _safeTransfer(token, to, value, false);
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _safeTransferFrom(token, from, to, value, false);
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
if (!_safeApprove(token, spender, value, false)) {
if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));
if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the
* return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param to The recipient of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {
bytes4 selector = IERC20.transfer.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(to, shr(96, not(0))))
mstore(0x24, value)
success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
}
}
/**
* @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, relaxing the requirement on the return
* value: the return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param from The sender of the tokens
* @param to The recipient of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value,
bool bubble
) private returns (bool success) {
bytes4 selector = IERC20.transferFrom.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(from, shr(96, not(0))))
mstore(0x24, and(to, shr(96, not(0))))
mstore(0x44, value)
success := call(gas(), token, 0, 0x00, 0x64, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
mstore(0x60, 0)
}
}
/**
* @dev Imitates a Solidity `token.approve(spender, value)` call, relaxing the requirement on the return value:
* the return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param spender The spender of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {
bytes4 selector = IERC20.approve.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(spender, shr(96, not(0))))
mstore(0x24, value)
success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)
pragma solidity ^0.8.20;
/**
* @dev Helper library for emitting standardized panic codes.
*
* ```solidity
* contract Example {
* using Panic for uint256;
*
* // Use any of the declared internal constants
* function foo() { Panic.GENERIC.panic(); }
*
* // Alternatively
* function foo() { Panic.panic(Panic.GENERIC); }
* }
* ```
*
* Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
*
* _Available since v5.1._
*/
// slither-disable-next-line unused-state
library Panic {
/// @dev generic / unspecified error
uint256 internal constant GENERIC = 0x00;
/// @dev used by the assert() builtin
uint256 internal constant ASSERT = 0x01;
/// @dev arithmetic underflow or overflow
uint256 internal constant UNDER_OVERFLOW = 0x11;
/// @dev division or modulo by zero
uint256 internal constant DIVISION_BY_ZERO = 0x12;
/// @dev enum conversion error
uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
/// @dev invalid encoding in storage
uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
/// @dev empty array pop
uint256 internal constant EMPTY_ARRAY_POP = 0x31;
/// @dev array out of bounds access
uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
/// @dev resource error (too large allocation or too large array)
uint256 internal constant RESOURCE_ERROR = 0x41;
/// @dev calling invalid internal function
uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
/// @dev Reverts with a panic code. Recommended to use with
/// the internal constants with predefined codes.
function panic(uint256 code) internal pure {
assembly ("memory-safe") {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
import {StorageSlot} from "./StorageSlot.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*
* IMPORTANT: Deprecated. This storage-based reentrancy guard will be removed and replaced
* by the {ReentrancyGuardTransient} variant in v6.0.
*/
abstract contract ReentrancyGuard {
using StorageSlot for bytes32;
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant REENTRANCY_GUARD_STORAGE =
0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
/**
* @dev A `view` only version of {nonReentrant}. Use to block view functions
* from being called, preventing reading from inconsistent contract state.
*
* CAUTION: This is a "view" modifier and does not change the reentrancy
* status. Use it only on view functions. For payable or non-payable functions,
* use the standard {nonReentrant} modifier instead.
*/
modifier nonReentrantView() {
_nonReentrantBeforeView();
_;
}
function _nonReentrantBeforeView() private view {
if (_reentrancyGuardEntered()) {
revert ReentrancyGuardReentrantCall();
}
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
_nonReentrantBeforeView();
// Any calls to nonReentrant after this point will fail
_reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;
}
function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {
return REENTRANCY_GUARD_STORAGE;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC-1967 implementation slot:
* ```solidity
* contract ERC1967 {
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct Int256Slot {
int256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Int256Slot` with member `value` located at `slot`.
*/
function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
/**
* @dev Returns a `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
import {Panic} from "../Panic.sol";
import {SafeCast} from "./SafeCast.sol";
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Return the 512-bit addition of two uint256.
*
* The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
*/
function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
assembly ("memory-safe") {
low := add(a, b)
high := lt(low, a)
}
}
/**
* @dev Return the 512-bit multiplication of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
*/
function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
// 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
// the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = high * 2²⁵⁶ + low.
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
low := mul(a, b)
high := sub(sub(mm, low), lt(mm, low))
}
}
/**
* @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
success = c >= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a - b;
success = c <= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a * b;
assembly ("memory-safe") {
// Only true when the multiplication doesn't overflow
// (c / a == b) || (a == 0)
success := or(eq(div(c, a), b), iszero(a))
}
// equivalent to: success ? c : 0
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `DIV` opcode returns zero when the denominator is 0.
result := div(a, b)
}
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `MOD` opcode returns zero when the denominator is 0.
result := mod(a, b)
}
}
}
/**
* @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryAdd(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
*/
function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
(, uint256 result) = trySub(a, b);
return result;
}
/**
* @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryMul(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * SafeCast.toUint(condition));
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
Panic.panic(Panic.DIVISION_BY_ZERO);
}
// The following calculation ensures accurate ceiling division without overflow.
// Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
// Handle non-overflow cases, 256 by 256 division.
if (high == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return low / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= high) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [high low].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
high := sub(high, gt(remainder, low))
low := sub(low, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly ("memory-safe") {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [high low] by twos.
low := div(low, twos)
// Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from high into low.
low |= high * twos;
// Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
// that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv ≡ 1 mod 2⁴.
uint256 inverse = (3 * denominator) ^ 2;
// Use the 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.
inverse *= 2 - denominator * inverse; // inverse mod 2⁸
inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
inverse *= 2 - denominator * inverse; // inverse mod 2³²
inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
// less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
// is no longer required.
result = low * inverse;
return result;
}
}
/**
* @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
*/
function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
if (high >= 1 << n) {
Panic.panic(Panic.UNDER_OVERFLOW);
}
return (high << (256 - n)) | (low >> n);
}
}
/**
* @dev Calculates x * y >> n with full precision, following the selected rounding direction.
*/
function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
// The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
// Used to compute integers x and y such that: ax + ny = gcd(a, n).
// When the gcd is 1, then the inverse of a modulo n exists and it's x.
// ax + ny = 1
// ax = 1 + (-y)n
// ax ≡ 1 (mod n) # x is the inverse of a modulo n
// If the remainder is 0 the gcd is n right away.
uint256 remainder = a % n;
uint256 gcd = n;
// Therefore the initial coefficients are:
// ax + ny = gcd(a, n) = n
// 0a + 1n = n
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
// The old remainder is the next gcd to try.
remainder,
// Compute the next remainder.
// Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
// where gcd is at most n (capped to type(uint256).max)
gcd - remainder * quotient
);
(x, y) = (
// Increment the coefficient of a.
y,
// Decrement the coefficient of n.
// Can overflow, but the result is casted to uint256 so that the
// next value of y is "wrapped around" to a value between 0 and n - 1.
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; // No inverse exists.
return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
}
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
* prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
* the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
* of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
// | Offset | Content | Content (Hex) |
// |-----------|------------|--------------------------------------------------------------------|
// | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x60:0x7f | value of b | 0x<.............................................................b> |
// | 0x80:0x9f | value of e | 0x<.............................................................e> |
// | 0xa0:0xbf | value of m | 0x<.............................................................m> |
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
// Given the result < m, it's guaranteed to fit in 32 bytes,
// so we can use the memory scratch space located at offset 0.
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
// Encode call args in result and move the free memory pointer
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
// Write result on top of args to avoid allocating extra memory.
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
// Overwrite the length.
// result.length > returndatasize() is guaranteed because returndatasize() == m.length
mstore(result, mLen)
// Set the memory pointer after the returned data.
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
for (uint256 i = 0; i < byteArray.length; ++i) {
if (byteArray[i] != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
// Take care of easy edge cases when a == 0 or a == 1
if (a <= 1) {
return a;
}
// In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
// sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
// the current value as `ε_n = | x_n - sqrt(a) |`.
//
// For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
// of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
// bigger than any uint256.
//
// By noticing that
// `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
// we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
// to the msb function.
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
// We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
//
// We can refine our estimation by noticing that the middle of that interval minimizes the error.
// If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
// This is going to be our x_0 (and ε_0)
xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
// From here, Newton's method give us:
// x_{n+1} = (x_n + a / x_n) / 2
//
// One should note that:
// x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
// = ((x_n² + a) / (2 * x_n))² - a
// = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
// = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
// = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
// = (x_n² - a)² / (2 * x_n)²
// = ((x_n² - a) / (2 * x_n))²
// ≥ 0
// Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
//
// This gives us the proof of quadratic convergence of the sequence:
// ε_{n+1} = | x_{n+1} - sqrt(a) |
// = | (x_n + a / x_n) / 2 - sqrt(a) |
// = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
// = | (x_n - sqrt(a))² / (2 * x_n) |
// = | ε_n² / (2 * x_n) |
// = ε_n² / | (2 * x_n) |
//
// For the first iteration, we have a special case where x_0 is known:
// ε_1 = ε_0² / | (2 * x_0) |
// ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
// ≤ 2**(2*e-4) / (3 * 2**(e-1))
// ≤ 2**(e-3) / 3
// ≤ 2**(e-3-log2(3))
// ≤ 2**(e-4.5)
//
// For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
// ε_{n+1} = ε_n² / | (2 * x_n) |
// ≤ (2**(e-k))² / (2 * 2**(e-1))
// ≤ 2**(2*e-2*k) / 2**e
// ≤ 2**(e-2*k)
xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above
xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5
xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9
xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18
xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36
xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72
// Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
// ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
// sqrt(a) or sqrt(a) + 1.
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// If upper 8 bits of 16-bit half set, add 8 to result
r |= SafeCast.toUint((x >> r) > 0xff) << 3;
// If upper 4 bits of 8-bit half set, add 4 to result
r |= SafeCast.toUint((x >> r) > 0xf) << 2;
// Shifts value right by the current result and use it as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
assembly ("memory-safe") {
r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
}
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
/**
* @dev Counts the number of leading zero bits in a uint256.
*/
function clz(uint256 x) internal pure returns (uint256) {
return ternary(x == 0, 256, 255 - log2(x));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
/**
* @title IKonaPointsFarm
* @notice Interface for the KonaPointsFarm contract that handles staking and points distribution
*/
interface IKonaPointsFarm {
/**
* @notice Structure to store user information for each farm
* @param amount Amount of LP tokens staked by the user
* @param pointsDebt Points debt for accounting purposes
*/
struct UserInfo {
uint256 amount;
uint256 pointsDebt;
}
/**
* @notice Structure to track user status in a farm
* @param active Whether the user is active in the farm
* @param index Index of the user in the farm's users array
*/
struct UserStatus {
bool active;
uint32 index;
}
/**
* @notice Structure to store farm information
* @param lpToken LP token contract address
* @param pointsPerBlock Points generated per block
* @param totalStaked Total amount of LP tokens staked in the farm
* @param lastRewardBlock Last block number when rewards were calculated
* @param accPointsPerShare Accumulated points per share
* @param active Whether the farm is active
* @param minStakeAmount Minimum amount that must be staked
*/
struct FarmInfo {
IERC20 lpToken;
uint256 pointsPerBlock;
uint256 totalStaked;
uint256 lastRewardBlock;
uint256 accPointsPerShare;
bool active;
uint256 minStakeAmount;
}
event Stake(address indexed user, uint256 farmId, uint256 amount);
event Unstake(address indexed user, uint256 farmId, uint256 amount);
event ClaimPoints(address indexed user, uint256 farmId, uint256 points);
event FarmAdded(uint256 farmId, address lpToken, uint256 pointsPerBlock);
event BatchPointsDistributed(address indexed owner, uint256 totalAddresses, uint256 totalPoints);
event PointsSpent(address indexed user, uint256 amount);
event FarmUpdated(uint256 farmId);
event NFTMinterSet(address indexed nftMinter);
event NFTMinterRemoved(address indexed nftMinter);
/**
* @notice Sets the NFT minter address
* @param _nftMinter Address of the NFT minter contract
*/
function setNFTMinter(address _nftMinter) external;
/**
* @notice Adds a new farm
* @param _lpToken LP token contract address
* @param _pointsPerBlock Points generated per block
* @param _minStakeAmount Minimum amount that must be staked
*/
function addFarm(IERC20 _lpToken, uint256 _pointsPerBlock, uint256 _minStakeAmount) external returns (uint256);
/**
* @notice Updates farm status and parameters
* @param _farmId ID of the farm to update
* @param _active Whether the farm should be active
* @param _pointsPerBlock New points per block rate
* @param _minStakeAmount Minimum amount that must be staked
*/
function updateFarmStatus(uint256 _farmId, bool _active, uint256 _pointsPerBlock, uint256 _minStakeAmount)
external;
/**
* @notice Updates farm rewards
* @param _farmId ID of the farm to update
*/
function updateFarm(uint256 _farmId) external;
/**
* @notice Stakes LP tokens in a farm
* @param _farmId ID of the farm
* @param _amount Amount of LP tokens to stake
*/
function stake(uint256 _farmId, uint256 _amount) external;
/**
* @notice Unstakes LP tokens from a farm
* @param _farmId ID of the farm
* @param _amount Amount of LP tokens to unstake
*/
function unstake(uint256 _farmId, uint256 _amount) external;
/**
* @notice Claims pending points from a farm
* @param _farmId ID of the farm
*/
function claimPoints(uint256 _farmId) external;
/**
* @notice Distributes points to multiple users in batch
* @param _users Array of user addresses
* @param _points Array of points to distribute
*/
function batchDistributePoints(address[] calldata _users, uint256[] calldata _points) external;
/**
* @notice Spends user's points
* @param _user Address of the user
* @param _amount Amount of points to spend
*/
function spendPoints(address _user, uint256 _amount) external;
/**
* @notice Emergency function to recover tokens
* @param _token Address of the token to recover
* @param receiver Address to receive the tokens
*/
function sweepTokens(address _token, address receiver) external;
/**
* @notice Gets pending points for a user in a farm
* @param _farmId ID of the farm
* @param _user Address of the user
* @return Amount of pending points
*/
function pendingPoints(uint256 _farmId, address _user) external view returns (uint256);
/**
* @notice Gets real-time points for a user
* @param _user Address of the user
* @return claimedPoints points that the user has already claimed
* @return pendingTotalPoints points that the user has not claimed yet
*/
function getRealTimePoints(address _user)
external
view
returns (uint256 claimedPoints, uint256 pendingTotalPoints);
/**
* @notice Gets total points for a user
* @param _user Address of the user
* @return Total points
*/
function getTotalPoints(address _user) external view returns (uint256);
/**
* @notice Gets the number of farms
* @return Number of farms
*/
function getFarmsLength() external view returns (uint256);
}{
"codegen": "yul",
"enableEraVMExtensions": true,
"evmVersion": "cancun",
"forceEVMLA": false,
"libraries": {},
"metadata": {},
"optimizer": {
"disable_system_request_memoization": true,
"enabled": true,
"mode": "3",
"size_fallback": false
},
"outputSelection": {
"*": {
"*": [
"abi"
]
}
},
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalAddresses","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalPoints","type":"uint256"}],"name":"BatchPointsDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"farmId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"points","type":"uint256"}],"name":"ClaimPoints","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"farmId","type":"uint256"},{"indexed":false,"internalType":"address","name":"lpToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"pointsPerBlock","type":"uint256"}],"name":"FarmAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"farmId","type":"uint256"}],"name":"FarmUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nftMinter","type":"address"}],"name":"NFTMinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nftMinter","type":"address"}],"name":"NFTMinterSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PointsSpent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"farmId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"farmId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstake","type":"event"},{"inputs":[],"name":"POINTS_PER_BLOCK_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCALAR_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_lpToken","type":"address"},{"internalType":"uint256","name":"_pointsPerBlock","type":"uint256"},{"internalType":"uint256","name":"_minStakeAmount","type":"uint256"}],"name":"addFarm","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"},{"internalType":"uint256[]","name":"_points","type":"uint256[]"}],"name":"batchDistributePoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_farmId","type":"uint256"}],"name":"claimPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"farms","outputs":[{"internalType":"contract IERC20","name":"lpToken","type":"address"},{"internalType":"uint256","name":"pointsPerBlock","type":"uint256"},{"internalType":"uint256","name":"totalStaked","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"internalType":"uint256","name":"accPointsPerShare","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"minStakeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCountFarms","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFarmsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getRealTimePoints","outputs":[{"internalType":"uint256","name":"claimedPoints","type":"uint256"},{"internalType":"uint256","name":"pendingTotalPoints","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getTotalPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftMinter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_farmId","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftMinter","type":"address"}],"name":"setNFTMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"spendPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"spentPoints","outputs":[{"internalType":"uint256","name":"spentPoints","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_farmId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"receiver","type":"address"}],"name":"sweepTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"totalPoints","outputs":[{"internalType":"uint256","name":"totalPoints","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_farmId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_farmId","type":"uint256"}],"name":"updateFarm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_farmId","type":"uint256"},{"internalType":"bool","name":"_active","type":"bool"},{"internalType":"uint256","name":"_pointsPerBlock","type":"uint256"},{"internalType":"uint256","name":"_minStakeAmount","type":"uint256"}],"name":"updateFarmStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"farmId","type":"uint256"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"pointsDebt","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
9c4d535b0000000000000000000000000000000000000000000000000000000000000000010003db0886bb063de41ff0338e0820eee0d97b2ecdc982df6cfbda45c80e5400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000fd3f90dd1355910fef471f7a8852714ff97cbfbd
Deployed Bytecode
0x0002000000000002000b000000000002000000000801034f0001000000010355000000600110027000000366011001970000000100200190000000560000c13d0000008002000039000000400020043f000000040010008c000000790000413d000000000208043b000000e0022002700000036f0020009c0000007b0000a13d000003700020009c000000a40000a13d000003710020009c0000015e0000a13d000003720020009c000001a00000213d000003750020009c000002b70000613d000003760020009c000000790000c13d0000000002000416000000000002004b000000790000c13d000000840010008c000000790000413d0000000401800370000000000301043b0000002401800370000000000101043b000b00000001001d000000010010008c000000790000213d0000004401800370000000000401043b000000000100041a00000369021001970000000001000411000000000012004b000003130000c13d000000090040008c000003040000a13d0000000102000039000000000102041a000000000031004b0000053c0000a13d0000000001030019000000000020043f000900000003001d000a00000004001d0d940bae0000040f000000090500002900000007015000c90000039b0210009a000000000302041a000003d5033001970000000b033001af000000000032041b000003970210009a0000000a03000029000000000032041b0000039c0110009a00000064020000390000000102200367000000000202043b000000000021041b000000400100043d0000000000510435000003660010009c000003660100804100000040011002100000000002000414000003660020009c0000036602008041000000c002200210000000000112019f000003a4011001c70000800d020000390000000103000039000003a504000041000001eb0000013d0000000002000416000000000002004b000000790000c13d0000001f0210003900000367022001970000008002200039000000400020043f0000001f0310018f00000368041001980000008002400039000000670000613d0000008005000039000000000608034f000000006706043c0000000005750436000000000025004b000000630000c13d000000000003004b000000740000613d000000000448034f0000000303300210000000000502043300000000053501cf000000000535022f000000000404043b0000010003300089000000000434022f00000000033401cf000000000353019f0000000000320435000000200010008c000000790000413d000000800100043d000003690010009c000000910000a13d000000000100001900000d9600010430000003810020009c0000009b0000213d000003890020009c000000ec0000213d0000038d0020009c000001c00000613d0000038e0020009c000001c00000613d0000038f0020009c000000790000c13d0000000002000416000000000002004b000000790000c13d000000240010008c000000790000413d0000000401800370000000000101043b000003690010009c000000790000213d000000000010043f0000000501000039000001cb0000013d000003690610019800000001020000390000036a03000041000000000023041b000000d70000c13d0000039201000041000000000010043f000000040000043f000003910100004100000d9600010430000003820020009c0000013a0000213d000003860020009c000001d10000613d000003870020009c000001d80000613d000003880020009c000001400000613d000000790000013d0000037a0020009c000001450000213d0000037e0020009c000002760000613d0000037f0020009c000001f00000613d000003800020009c000000790000c13d0000000002000416000000000002004b000000790000c13d000000440010008c000000790000413d0000000401800370000000000101043b000b00000001001d000003690010009c000000790000213d0000002401800370000000000301043b0000000201000039000000000101041a00000369011001970000000002000411000000000012004b000003450000c13d000a00000003001d0000000b01000029000000000010043f0000000401000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000101043b000000000101041a0000000a0010006c000005420000813d000000400100043d0000004402100039000003c603000041000000000032043500000024021000390000001303000039000006360000013d000000000200041a0000036b03200197000000000113019f000000000010041b0000000001000414000003660010009c00000366010080410000036905200197000000c0011002100000036c011001c70000800d0200003900000003030000390000036d040000410d940d8a0000040f0000000100200190000000790000613d0000002001000039000001000010044300000120000004430000036e0100004100000d950001042e0000038a0020009c000001f50000613d0000038b0020009c000002150000613d0000038c0020009c000000790000c13d0000000002000416000000000002004b000000790000c13d000000240010008c000000790000413d0000000401800370000000000301043b0000036a01000041000000000201041a000000020020008c000002b30000613d0000000202000039000000000021041b0000000101000039000000000101041a000000000031004b0000053c0000a13d000b00000003001d0000000001000411000000000010043f0000000301000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000101043b0000000b02000029000000000020043f000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d0000000b0200002900090007002000cd000000000101043b000a00000001001d00000000010200190d940bae0000040f00000009010000290000039a0910009a000000000109041a0000000a02000029000000000202041a000003d60020009c00000000030200190000000003006019000003d60010009c0000000004010019000000000400601900000000533400a9000003b17450012a0000008006300270000003b80050009c000006190000213d0000008007700210000000000767019f000003b1084000d1000000000078004b000000010440208a0000061a0000013d000003830020009c000002300000613d000003840020009c000002530000613d000003850020009c000000790000c13d0000000001000416000000000001004b000000790000c13d0000000101000039000001cd0000013d0000037b0020009c000002a60000613d0000037c0020009c0000026d0000613d0000037d0020009c000000790000c13d0000000002000416000000000002004b000000790000c13d000000440010008c000000790000413d0000002401800370000000000201043b000003690020009c000000790000213d0000000401800370000000000101043b0d9409d40000040f000000400200043d0000000000120435000003660020009c000003660200804100000040012002100000039f011001c700000d950001042e000003770020009c000002c10000613d000003780020009c000002eb0000613d000003790020009c000000790000c13d0000000002000416000000000002004b000000790000c13d000000440010008c000000790000413d0000000402800370000000000202043b000003a70020009c000000790000213d0000002303200039000000000013004b000000790000813d0000000403200039000000000338034f000000000303043b000700000003001d000003a70030009c000000790000213d000600240020003d000000070200002900000005022002100000000602200029000000000012004b000000790000213d0000002402800370000000000302043b000003a70030009c000000790000213d0000002302300039000000000012004b000000790000813d0000000402300039000000000228034f000000000202043b000003a70020009c000000790000213d000500240030003d00000005032002100000000503300029000000000013004b000000790000213d000000000100041a000403690010019b0000000001000411000000040010006b000003130000c13d000000070020006b000007820000c13d000000070000006b0000088b0000c13d000003a101000041000000800010043f0000002001000039000000840010043f0000001101000039000000a40010043f000003ad01000041000000c40010043f000003a30100004100000d9600010430000003730020009c000002f20000613d000003740020009c000000790000c13d0000000002000416000000000002004b000000790000c13d000000240010008c000000790000413d0000000401800370000000000601043b000003690060009c000000790000213d000000000100041a00000369051001970000000002000411000000000025004b0000030e0000c13d000000000006004b000000960000613d0000036b01100197000000000161019f000000000010041b0000000001000414000003660010009c0000036601008041000000c0011002100000036c011001c70000800d0200003900000003030000390000036d04000041000001eb0000013d0000000002000416000000000002004b000000790000c13d000000240010008c000000790000413d0000000401800370000000000101043b000003690010009c000000790000213d000000000010043f0000000401000039000000200010043f0d940d7d0000040f000000000101041a000000800010043f000003af0100004100000d950001042e0000000001000416000000000001004b000000790000c13d0000006401000039000000800010043f000003af0100004100000d950001042e0000000001000416000000000001004b000000790000c13d000000000100041a00000369051001970000000002000411000000000025004b0000030e0000c13d0000036b01100197000000000010041b0000000001000414000003660010009c0000036601008041000000c0011002100000036c011001c70000800d0200003900000003030000390000036d0400004100000000060000190d940d8a0000040f0000000100200190000000790000613d000000000100001900000d950001042e0000000001000416000000000001004b000000790000c13d000000000100041a000002720000013d0000000002000416000000000002004b000000790000c13d000000440010008c000000790000413d0000000401800370000000000101043b000b00000001001d000003690010009c000000790000213d0000002401800370000000000101043b000a00000001001d000003690010009c000000790000213d000000000100041a00000369021001970000000001000411000000000012004b000003130000c13d0000000a0000006b000005780000c13d000003a101000041000000800010043f0000002001000039000000840010043f0000001801000039000000a40010043f000003d401000041000000c40010043f000003a30100004100000d96000104300000000002000416000000000002004b000000790000c13d000000440010008c000000790000413d0000000401800370000000000101043b000003690010009c000000790000213d000000000010043f0000000301000039000000200010043f000b0000000803530d940d7d0000040f0000000b0200035f0000002402200370000000000202043b000000000020043f000000200010043f0d940d7d0000040f0000000102100039000000000202041a000000000101041a000000800010043f000000a00020043f000003d10100004100000d950001042e0000000002000416000000000002004b000000790000c13d000000440010008c000000790000413d0000002401800370000000000301043b0000000401800370000000000401043b0000036a01000041000000000201041a000000020020008c000002b30000613d0000000202000039000000000021041b0000000101000039000000000201041a000000000042004b0000053c0000a13d000000000010043f00000007024000c90000039c0120009a000000000101041a000000000013004b0000034f0000813d000003a101000041000000800010043f0000002001000039000000840010043f0000001801000039000000a40010043f000003cd01000041000000c40010043f000003a30100004100000d96000104300000000002000416000000000002004b000000790000c13d000000240010008c000000790000413d0000000401800370000000000501043b000003690050009c000000790000213d000000000100041a00000369021001970000000001000411000000000012004b000003130000c13d000000000005004b0000035d0000c13d000003a101000041000000800010043f0000002001000039000000840010043f0000001201000039000000a40010043f000003c901000041000000c40010043f000003a30100004100000d96000104300000000001000416000000000001004b000000790000c13d0000000201000039000000000101041a0000036901100197000000800010043f000003af0100004100000d950001042e0000000002000416000000000002004b000000790000c13d000000240010008c000000790000413d0000000401800370000000000101043b0000000102000039000000000202041a000000000021004b000000790000813d0d9409c60000040f0000000502100039000000000202041a0000000103100039000000000303041a0000000204100039000000000404041a0000000305100039000000000505041a0000000406100039000000000606041a000000000701041a0000000601100039000000000101041a000000400800043d000000c009800039000000000019043500000080018000390000000000610435000000600180003900000000005104350000004001800039000000000041043500000020018000390000000000310435000000ff002001900000000001000039000000010100c039000000a002800039000000000012043500000369017001970000000000180435000003660080009c00000366080080410000004001800210000003c7011001c700000d950001042e0000000002000416000000000002004b000000790000c13d000000440010008c000000790000413d0000002401800370000000000301043b0000000401800370000000000401043b0000036a01000041000000000201041a000000020020008c000003180000c13d000003cf01000041000000000010043f000003d00100004100000d96000104300000000002000416000000000002004b000000790000c13d000000240010008c000000790000413d0000000401800370000000000101043b0d940bae0000040f000000000100001900000d950001042e0000000002000416000000000002004b000000790000c13d000000240010008c000000790000413d0000000401800370000000000101043b000500000001001d000003690010009c000000790000213d0000000501000029000000000010043f0000000401000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000101043b000000000101041a000100000001001d0000000101000039000000000101041a000400000001001d000000000001004b000000000d000019000003760000c13d000000400100043d00000020021000390000000000d2043500000001020000290000000000210435000003660010009c00000366010080410000004001100210000003bb011001c700000d950001042e0000000001000416000000000001004b000000790000c13d000003ae01000041000000800010043f000003af0100004100000d950001042e0000000002000416000000000002004b000000790000c13d000000640010008c000000790000413d0000000401800370000000000101043b000003690010009c000000790000213d0000002402800370000000000402043b000000000200041a00000369032001970000000002000411000000000023004b0000030e0000c13d0000000a0040008c0000036a0000813d000003a101000041000000800010043f0000002001000039000000840010043f0000001401000039000000a40010043f000003a601000041000000c40010043f000003a30100004100000d96000104300000039001000041000000000010043f000000040020043f000003910100004100000d96000104300000039002000041000000000020043f000000040010043f000003910100004100000d96000104300000000202000039000000000021041b0000000101000039000000000101041a000000000041004b0000053c0000a13d000b00000004001d000a00000003001d0000000001000411000000000010043f0000000301000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000101043b0000000b02000029000000000020043f000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000401043b000000000104041a0000000a0310006c000006280000813d000000400100043d0000004402100039000003c303000041000000000032043500000024021000390000001a03000039000006360000013d000003a101000041000000800010043f0000002001000039000000840010043f0000001f01000039000000a40010043f000003c401000041000000c40010043f000003a30100004100000d96000104300000039b0120009a000000000101041a000000ff00100190000005ae0000c13d000003a101000041000000800010043f0000002001000039000000840010043f0000001201000039000000a40010043f000003cc01000041000000c40010043f000003a30100004100000d96000104300000000203000039000000000103041a0000036b01100197000000000151019f000000000013041b0000000001000414000003660010009c0000036601008041000000c0011002100000036c011001c70000800d02000039000003c804000041000001eb0000013d0000036902100198000005f50000c13d000003a101000041000000800010043f0000002001000039000000840010043f0000001001000039000000a40010043f000003a201000041000000c40010043f000003a30100004100000d96000104300000801002000039000000000e000019000000000d000019000a0000000d001d0000000101000039000000000101041a000b0000000e001d0000000000e1004b0000053c0000a13d0000000501000029000000000010043f0000000301000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c70d940d8f0000040f00000001002001900000000b03000029000000790000613d000000000101043b000000000030043f000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000b0e0000290000000100200190000000790000613d0000000702e000c9000000000801043b0000039a0120009a000000000901041a0000039b0120009a000000000101041a000000ff00100190000004570000613d000800000009001d000900000008001d000600000002001d000003990120009a000300000001001d000000000101041a000700000001001d000003930100004100000000001004430000000001000414000003660010009c0000036601008041000000c00110021000000394011001c70000800b020000390d940d8f0000040f0000000100200190000009ab0000613d000000000101043b000000070010006c0000000b0e00002900000009080000290000000809000029000004570000a13d0000000601000029000003980210009a000000000102041a000000000001004b000004570000613d000200000002001d0000000301000029000000000101041a000700000001001d000003930100004100000000001004430000000001000414000003660010009c0000036601008041000000c00110021000000394011001c70000800b020000390d940d8f0000040f0000000100200190000009ab0000613d000000000301043b0000000705000029000000000153004b0000000a0d0000290000000b0e00002900000009080000290000000809000029000006dd0000413d0000000602000029000003970220009a000000000402041a00000000021400a9000000000053004b000003de0000613d00000000011200d9000000000041004b000006dd0000c13d000003d60020009c00000000010200190000000001006019000003ae311000d100000080041002700000008003300210000000000343019f000003b004100197000003b13530012a0000008003300210000000000343019f000003b1045000d1000000000034004b000000010550208a000003b1035001970000000001130019000003ae062000d1000000000361004b000000000500003900000001050040390000000201000029000000000101041a0000000004000415000000000553004b0000049e0000c13d000000000001004b000008cc0000613d00000000030004150000000003340049000000000300000200000000201200d900000000041600d9000003ae30100129000003b10010009c0000052c0000a13d00000000353200a9000000000031004b000000010200008a0000052e0000a13d000003b40010009c000000c0020000390000008002004039000000000621022f00000040020000390000008002004039000003b50060009c000000200220808a0000002006608270000003b60060009c000000100220808a0000001006608270000001000060008c000000080220808a0000000806608270000000100060008c00000000070600190000000407708270000000040070008c000000000807001900000002088082700000000009800089000000020080008c000000020900808a000000100060008c000000040220808a000000040070008c000000020220808a0000000002290019000000ff0620018f00000000036301cf000003d606200167000000ff0660018f0000000107500270000000000667022f000000000763019f00000000012101cf000000800310027000000000a93700d900000000062501cf0000008008600270000003b105100197000004340000013d000000000a3a0019000000010990008a000003b100a0009c0000043b0000813d000003b70090009c000004300000213d000000000b5900a9000000800ca00210000000000c8c019f0000000000cb004b000004300000213d000003b10990019700000000091900a90000008007700210000000000787019f000000000797004900000000983700d9000003b106600197000004470000013d0000000009390019000000010880008a000003b10090009c0000044e0000813d000003b70080009c000004430000213d000000000a5800a9000000800b900210000000000b6b019f0000000000ba004b000004430000213d000003b10380019700000000011300a90000008003700210000000000363019f0000000001130049000000000221022f000000090800002900000008090000290000052e0000013d0000000a0d000029000000000108041a000003d60090009c00000000020900190000000002006019000003d60010009c0000000003010019000000000300601900000000422300a9000003b16340012a0000008005200270000003b80040009c0000046a0000213d0000008006600210000000000656019f000003b1073000d1000000000067004b000000010330208a0000046b0000013d000000010330008a0000008004400210000000000454019f000003b1033001970000000004340019000003b16340012a000003b105200197000003b80040009c000004790000213d0000008002600210000000000252019f000003b1063000d1000000000026004b000000010330208a0000047a0000013d000000010330008a00000000029100a90000008004400210000000000454019f000003b1033001970000000003340019000000000323004b00000000040000390000000104004039000000000343004b000004860000c13d000003ae0120012a000004920000013d000003b90030009c0000066e0000213d000003ae4090012a000003ae1010012a00000000014100a9000003ae1010012a000000000112004b000000010330408a0000002401100270000000dc02300210000000000112019f000003ba011000d10000000102800039000000000202041a000000000121004b000006dd0000413d00000000001d001a000006dd0000413d000000000d1d0019000000010ee000390000000400e0006c0000801002000039000003790000413d000002e10000013d000000000015004b000008d20000813d000003ae3010012900000000201200d9000003b10010009c000004a70000213d00000000072300a900000000901700d9000005000000013d000000008a2300a9000000000081004b000000010900008a000005000000a13d000003b40010009c000000c0070000390000008007004039000000000971022f00000040070000390000008007004039000003b50090009c000000200770808a0000002009908270000003b60090009c000000100770808a0000001009908270000001000090008c000000080770808a0000000809908270000000100090008c000000000b090019000000040bb082700000000400b0008c000000000c0b0019000000020cc08270000000000dc000890000000200c0008c000000020d00808a000000100090008c000000040770808a0000000400b0008c000000020770808a00000000077d0019000000ff0970018f00000000089801cf000003d609700167000000ff0990018f000000010ba0027000000000099b022f00060000009801a300000000087101cf000000800980027000000006fe9000f9000000000a7a01cf00070000000a001d000000800da00270000003b10a800197000004db0000013d000000000f9f0019000000010ee0008a000003b100f0009c000004e20000813d000003b700e0009c000004d70000213d000000000bae00a9000000800cf00210000000000cdc019f0000000000cb004b000004d70000213d000003b10be00197000000000b8b00a9000000060c000029000000800cc00210000000000cdc019f0006000000bc005100000006ed9000f9000000070b000029000003b10bb00197000004f00000013d000000000e9e0019000000010dd0008a000003b100e0009c000004f70000813d000003b700d0009c000004ec0000213d000000000fad00a9000000800ce00210000000000cbc019f0000000000cf004b000004ec0000213d000003b109d0019700000000088900a9000000060900002900000080099002100000000009b9019f0000000008890049000000000978022f0000000a0d0000290000000b0e00002900000000071000890000000008710170000000000781c0d90000000007006019000000000696004b000000010550408a000000000008004b0000050e0000613d00000000068600d9000000000980008900000000088900d9000000010880003900000000055800a90000050f0000013d000000000600001900000003087000c9000000020880015f00000000097800a9000000020990008900000000088900a900000000097800a9000000020990008900000000088900a900000000097800a9000000020990008900000000088900a900000000097800a9000000020990008900000000088900a900000000097800a9000000020990008900000000088900a900000000077800a9000000020770008900000000078700a9000000000800041500000000048400490000000004000002000000000456019f00000000044700a900000009080000290000000809000029000003b10010009c000004010000213d00000000023200a900000000201200d9000000000002004b0000000001000039000000010100c039000000000014001a000006dd0000413d000000000114001a000000010110008a000000640110011a00000001011000390000000001006019000000000091001a000006dd0000413d0000000009910019000004580000013d000003a001000041000000000010043f0000003201000039000000040010043f000003910100004100000d96000104300000000b01000029000000000010043f0000000401000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000101043b000000000201041a0000000a0220006c000006dd0000413d000000000021041b0000000b01000029000000000010043f0000000501000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000101043b000000000201041a0000000a03000029000000000032001a000006dd0000413d0000000002320019000000000021041b000000400100043d0000000000310435000003660010009c000003660100804100000040011002100000000002000414000003660020009c0000036602008041000000c002200210000000000112019f000003a4011001c70000800d020000390000000203000039000003c5040000410000000b05000029000001eb0000013d000003d201000041000000800010043f0000000001000410000000840010043f0000000001000414000003660010009c0000036601008041000000c001100210000003d3011001c70000000b020000290d940d8f0000040f000000800a00003900000060031002700000036603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000005920000613d000000000801034f000000008908043c000000000a9a043600000000005a004b0000058e0000c13d000000000006004b0000059f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000006410000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c000000790000413d000000800300043d0000000b010000290000000a020000290d940d070000040f000000000100001900000d950001042e000a00000002001d000b00000004001d000900000003001d0000000001000411000000000010043f0000000301000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000101043b0000000b02000029000000000020043f000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000101043b000800000001001d0000000b010000290d940bae0000040f0000000801000029000000000101041a000000000001004b0000070e0000c13d0000000a01000029000003980110009a000000000201041a000000090020002a000006dd0000413d0000000902200029000000000021041b0000000801000029000000000201041a0000000901200029000000000021004b000006dd0000413d0000000802000029000000000012041b000003d60010009c000000000401001900000000040060190000000a020000290000039a0220009a000000000202041a000003d60020009c0000000003020019000000000300601900000000534300a9000003b17450012a0000008006300270000003b80050009c0000080a0000213d0000008007700210000000000767019f000003b1084000d1000000000078004b000000010440208a0000080b0000013d0000016001000039000000400010043f000a00000002001d000000800020043f000b00000004001d000000a00040043f000000c00000043f000003930100004100000000001004430000000001000414000003660010009c0000036601008041000000c00110021000000394011001c70000800b020000390d940d8f0000040f0000000100200190000009ab0000613d000000000301043b000000e00030043f000001000000043f0000000101000039000001200010043f00000044020000390000000102200367000000000202043b000001400020043f000000000401041a000003950040009c000006740000413d000003a001000041000000000010043f0000004101000039000000040010043f000003910100004100000d9600010430000000010440008a0000008005500210000000000565019f000003b1044001970000000005450019000003b17450012a000003b106300197000003b80050009c0000065f0000213d0000008003700210000000000363019f000003b1074000d1000000000037004b000000010440208a000006600000013d000900000004001d0000000b0100002900000007021000c9000800000002001d0000039c0220009a000000000202041a000000000023004b000006b40000813d000000400100043d0000004402100039000003c2030000410000000000320435000000240210003900000018030000390000000000320435000003a1020000410000000000210435000000040210003900000020030000390000000000320435000003660010009c00000366010080410000004001100210000003ac011001c700000d96000104300000001f0530018f0000036806300198000000400200043d00000000046200190000064c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006480000c13d000000000005004b000006590000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000003660020009c00000366020080410000004002200210000000000112019f00000d9600010430000000010440008a00000000032100a90000008005500210000000000565019f000003b1044001970000000004450019000000000434004b00000000050000390000000105004039000000000454004b0000066c0000c13d000003ae0130012a000006d60000013d000003ae0040009c000006cc0000413d000003b201000041000000000010043f0000001101000039000000200010043f000003b30100004100000d96000104300000000105400039000000000051041b000000000010043f000000800500043d000003690550019700000007044000c9000003960640009a000000000706041a0000036b07700197000000000557019f000000000056041b000003970540009a000000a00600043d000000000065041b000003980540009a000000c00600043d000000000065041b000003990540009a000000000035041b0000039a0340009a000000000003041b0000039b0340009a000000000603041a000003d50560019700000001055001bf000000000053041b0000039c0340009a000000000023041b000000000101041a000000000001004b000006dd0000613d000000010410008a000000400100043d00000040021000390000000b03000029000000000032043500000020021000390000000a030000290000000000320435000b00000004001d0000000000410435000003660010009c000003660100804100000040011002100000000002000414000003660020009c0000036602008041000000c002200210000000000112019f0000039d011001c70000800d0200003900000001030000390000039e040000410d940d8a0000040f0000000100200190000000790000613d000000400100043d0000000b020000290000000000210435000003660010009c000003660100804100000040011002100000039f011001c700000d950001042e0d940bae0000040f00000008010000290000039a0110009a000600000001001d000000000101041a0000000902000029000000000202041a000003d60020009c00000000030200190000000003006019000003d60010009c0000000004010019000000000400601900000000533400a9000003b17450012a0000008006300270000003b80050009c000007220000213d0000008007700210000000000767019f000003b1084000d1000000000078004b000000010440208a000007230000013d000003ae2020012a000003ae1010012a00000000012100a9000003ae1010012a000000000113004b000000010440408a0000002401100270000000dc02400210000000000112019f000003ba011000d1000900000009001d0000000a020000290000000102200039000800000002001d000000000202041a000000000121004b000006e30000813d000003a001000041000000000010043f0000001101000039000000040010043f000003910100004100000d9600010430000700000001001d000008860000613d0000000001000411000000000010043f0000000401000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000101043b000000000201041a0000000703000029000000000032001a000006dd0000413d0000000002320019000000000021041b0000000901000029000000000101041a0000000a02000029000000000202041a000003d60020009c00000000030200190000000003006019000003d60010009c0000000004010019000000000400601900000000533400a9000003b17450012a0000008006300270000003b80050009c000007cd0000213d0000008007700210000000000767019f000003b1084000d1000000000078004b000000010440208a000007ce0000013d000003d60010009c000000000401001900000000040060190000000a020000290000039a0220009a000000000202041a000003d60020009c0000000003020019000000000300601900000000534300a9000003b17450012a0000008006300270000003b80050009c0000078c0000213d0000008007700210000000000767019f000003b1084000d1000000000078004b000000010440208a0000078d0000013d000000010440008a0000008005500210000000000565019f000003b1044001970000000005450019000003b17450012a000003b106300197000003b80050009c000007310000213d0000008003700210000000000363019f000003b1074000d1000000000037004b000000010440208a000007320000013d000000010440008a00000000032100a90000008005500210000000000565019f000003b1044001970000000004450019000000000434004b00000000050000390000000105004039000000000454004b0000073e0000c13d000003ae0130012a0000074a0000013d000003b90040009c0000066e0000213d000003ae2020012a000003ae1010012a00000000012100a9000003ae1010012a000000000113004b000000010440408a0000002401100270000000dc02400210000000000112019f000003ba011000d100000009020000290000000102200039000500000002001d000000000202041a0007000000210053000006dd0000413d0000000001000411000000000010043f0000000401000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000101043b000000000201041a000000070020002a000006dd0000413d0000000702200029000000000021041b0000000801000029000003980110009a000000000201041a0000000a0220006c000006dd0000413d000000000021041b0000000901000029000000000101041a0000000a0110006c000006dd0000413d0000000902000029000000000012041b0000000602000029000000000202041a000003d60010009c00000000030100190000000003006019000003d60020009c0000000004020019000000000400601900000000533400a9000003b17450012a0000008006300270000003b80050009c0000091d0000213d0000008007700210000000000767019f000003b1084000d1000000000078004b000000010440208a0000091e0000013d000003a101000041000000800010043f0000002001000039000000840010043f0000001601000039000000a40010043f000003a801000041000000c40010043f000003a30100004100000d9600010430000000010440008a0000008005500210000000000565019f000003b1044001970000000005450019000003b17450012a000003b106300197000003b80050009c0000079b0000213d0000008003700210000000000363019f000003b1074000d1000000000037004b000000010440208a0000079c0000013d000000010440008a00000000031200a90000008005500210000000000565019f000003b1044001970000000004450019000000000434004b00000000050000390000000105004039000000000454004b000007a80000c13d000003ae0130012a000007b40000013d000003b90040009c0000066e0000213d000003ae1010012a000003ae2020012a00000000011200a9000003ae1010012a000000000113004b000000010440408a0000002401100270000000dc02400210000000000112019f000003ba011000d100000008020000290000000102200039000000000202041a0007000000210053000006dd0000413d0000000001000411000000000010043f0000000401000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000790000613d000000000101043b000000000201041a000000070020002a000006dd0000413d0000000702200029000000000021041b000005d30000013d000000010440008a0000008005500210000000000565019f000003b1044001970000000005450019000003b17450012a000003b106300197000003b80050009c000007dc0000213d0000008003700210000000000363019f000003b1074000d1000000000037004b000000010440208a000007dd0000013d000000010440008a00000000032100a90000008005500210000000000565019f000003b1044001970000000004450019000000000434004b00000000050000390000000105004039000000000454004b000007e90000c13d000003ae0130012a000007f50000013d000003b90040009c0000066e0000213d000003ae2020012a000003ae1010012a00000000012100a9000003ae1010012a000000000113004b000000010440408a0000002401100270000000dc02400210000000000112019f000003ba011000d10000000802000029000000000012041b000000400100043d0000002002100039000000070300002900000000003204350000000b020000290000000000210435000003660010009c000003660100804100000040011002100000000002000414000003660020009c0000036602008041000000c002200210000000000112019f000003a9011001c70000800d020000390000000203000039000003ce04000041000008820000013d000000010440008a0000008005500210000000000565019f000003b1044001970000000005450019000003b17450012a000003b106300197000003b80050009c000008190000213d0000008003700210000000000363019f000003b1074000d1000000000037004b000000010440208a0000081a0000013d000000010440008a00000000031200a90000008005500210000000000565019f000003b1044001970000000004450019000000000434004b00000000050000390000000105004039000000000454004b000008260000c13d000003ae0130012a000008320000013d000003b90040009c0000066e0000213d000003ae1010012a000003ae2020012a00000000011200a9000003ae1010012a000000000113004b000000010440408a0000002401100270000000dc02400210000000000112019f000003ba011000d10000000a02000029000003960220009a00000008030000290000000103300039000000000013041b000000000102041a000000400200043d000a00000002001d000003ca02000041000000000020043f0000000002000411000000040020043f0000000002000410000000240020043f0000000902000029000000440020043f00000000030004140000036902100197000003660030009c0000036603008041000000c001300210000003ac011001c7000800000002001d0d940d8a0000040f00000060031002700000036603300197000000200030008c000000200400003900000000040340190000001f0540018f0000002004400190000008580000613d000000000601034f0000000007000019000000006806043c0000000007870436000000000047004b000008540000c13d000000000005004b000008650000613d000000000641034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000000000003001f000000000400043d000000010040008c00000000040000390000000104006039000000000424016f000000010040008c000008da0000c13d0000000a01000029000000400010043f000000600000043f0000000a030000290000002001300039000000090200002900000000002104350000000b010000290000000000130435000003660030009c000003660300804100000040013002100000000002000414000003660020009c0000036602008041000000c002200210000000000112019f000003a9011001c70000800d020000390000000203000039000003cb0400004100000000050004110d940d8a0000040f0000000100200190000000790000613d00000001010000390000036a02000041000000000012041b000000000100001900000d950001042e00000000020000190000000004000019000a00000002001d00000005012002100000000602100029000000000228034f000000000202043b000003690020009c000000790000213d000b00000004001d000000000002004b000009160000613d000900050010002d0000000901800360000000000101043b000800000001001d000000000020043f0000000401000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f00000001002001900000000b04000029000000790000613d000000000101043b000000000201041a0000000803000029000000000032001a000006dd0000413d0000000002320019000000000021041b00000001080003670000000901800360000000000101043b000000000014001a000006dd0000413d00000000041400190000000a020000290000000102200039000000070020006c0000088d0000413d000000400100043d0000002002100039000000000042043500000007020000290000000000210435000003660010009c000003660100804100000040011002100000000002000414000003660020009c0000036602008041000000c002200210000000000112019f000003a9011001c70000800d020000390000000203000039000003aa040000410000000405000029000001eb0000013d000003a001000041000000000010043f0000001201000039000000040010043f000003910100004100000d9600010430000003b202000041000000000020043f000000000001004b00000011010000390000001201006039000000200010043f000003b30100004100000d96000104300000000100200190000008f80000613d000003be010000410000000000100443000000080100002900000004001004430000000001000414000003660010009c0000036601008041000000c001100210000003bf011001c700008002020000390d940d8f0000040f0000000100200190000009ab0000613d000000000201043b00000000010000310000000a03000029000000400030043f000000600000043f000000000002004b000008f20000613d000000000001004b000008700000613d000003c001000041000000000010043f0000000801000029000000040010043f000003910100004100000d96000104300000001f0430018f00000368053001980000000a02500029000009020000613d000000000601034f0000000a07000029000000006806043c0000000007870436000000000027004b000008fe0000c13d000000000004004b0000090f0000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000012043500000060013002100000000a02000029000003660020009c00000366020080410000004002200210000000000121019f00000d9600010430000000400100043d0000004402100039000003ab03000041000000000032043500000024021000390000001403000039000006360000013d000000010440008a0000008005500210000000000565019f000003b1044001970000000005450019000003b17450012a000003b106300197000003b80050009c0000092c0000213d0000008003700210000000000363019f000003b1074000d1000000000037004b000000010440208a0000092d0000013d000000010440008a00000000031200a90000008005500210000000000565019f000003b1044001970000000004450019000000000434004b00000000050000390000000105004039000000000454004b000009390000c13d000003ae0130012a000009450000013d000003b90040009c0000066e0000213d000003ae1010012a000003ae2020012a00000000011200a9000003ae1010012a000000000113004b000000010440408a0000002401100270000000dc02400210000000000112019f000003ba011000d10000000802000029000003960220009a0000000503000029000000000013041b000000000102041a000000400200043d000900000002001d000003bc02000041000000000020043f00000000020004110000036902200197000000040020043f0000000a02000029000000240020043f00000000030004140000036902100197000003660030009c0000036603008041000000c001300210000003bd011001c7000800000002001d0d940d8a0000040f00000060031002700000036603300197000000200030008c000000200400003900000000040340190000001f0540018f0000002004400190000009690000613d000000000601034f0000000007000019000000006806043c0000000007870436000000000047004b000009650000c13d000000000005004b000009760000613d000000000641034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000000000003001f000000000400043d000000010040008c00000000040000390000000104006039000000000424016f0000000100400190000009930000613d0000000901000029000000400010043f000000090300002900000020013000390000000a0200002900000000002104350000000b010000290000000000130435000003660030009c000003660300804100000040013002100000000002000414000003660020009c0000036602008041000000c002200210000000000112019f000003a9011001c70000800d020000390000000203000039000003c104000041000008820000013d0000000100200190000009ac0000613d000003be010000410000000000100443000000080100002900000004001004430000000001000414000003660010009c0000036601008041000000c001100210000003bf011001c700008002020000390d940d8f0000040f0000000100200190000009ab0000613d000000000201043b00000000010000310000000903000029000000400030043f000000000002004b000008f20000613d000000000001004b000009800000613d000008f20000013d000000000001042f0000001f0430018f00000368053001980000000902500029000009b60000613d000000000601034f0000000907000029000000006806043c0000000007870436000000000027004b000009b20000c13d000000000004004b000009c30000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000012043500000060013002100000000902000029000009110000013d0000000102000039000000000302041a000000000013004b000009ce0000a13d000000000020043f00000007011000c9000003960110009a000000000001042d000003a001000041000000000010043f0000003201000039000000040010043f000003910100004100000d960001043000060000000000020000000103000039000000000303041a000600000001001d000000000013004b00000b930000a13d0000036901200197000000000010043f0000000301000039000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000060200002900000b8b0000613d000000000101043b000000000020043f000000200010043f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f0000000100200190000000060200002900000b8b0000613d00000007022000c9000000000d01043b0000039a0120009a000000000e01041a0000039b0120009a000000000101041a000000ff0010019000000b4c0000613d00050000000e001d00060000000d001d000300000002001d000003990120009a000200000001001d000000000101041a000400000001001d000003930100004100000000001004430000000001000414000003660010009c0000036601008041000000c00110021000000394011001c70000800b020000390d940d8f0000040f000000010020019000000b990000613d000000000101043b000000040010006c000000060d000029000000050e00002900000b4c0000a13d0000000301000029000003980210009a000000000102041a000000000001004b00000b4c0000613d000100000002001d0000000201000029000000000101041a000400000001001d000003930100004100000000001004430000000001000414000003660010009c0000036601008041000000c00110021000000394011001c70000800b020000390d940d8f0000040f000000010020019000000b990000613d000000000301043b0000000405000029000000000153004b000000060d000029000000050e00002900000b8d0000413d0000000302000029000003970220009a000000000402041a00000000021400a9000000000053004b00000a370000613d00000000011200d9000000000041004b00000b8d0000c13d000000010700008a000000000072004b00000000010200190000000001006019000003ae311000d100000080041002700000008003300210000000000343019f000003b004100197000003b13530012a0000008003300210000000000343019f000003b1045000d1000000000034004b000000010550208a000003b1035001970000000001130019000003ae062000d1000000000361004b000000000500003900000001050040390000000101000029000000000101041a0000000004000415000000000553004b00000aaf0000c13d000000000001004b00000ba00000613d00000000030004150000000003340049000000000300000200000000201200d900000000041600d9000003ae30100129000003b10010009c00000b3d0000a13d00000000353200a9000000000031004b00000ab80000a13d000003b40010009c000000c0020000390000008002004039000000000621022f00000040020000390000008002004039000003b50060009c000000200220808a0000002006608270000003b60060009c000000100220808a0000001006608270000001000060008c000000080220808a0000000806608270000000100060008c00000000070600190000000407708270000000040070008c00000000080700190000000208808270000000020900008a000000000a800089000000020080008c000000000a098019000000100060008c000000040220808a000000040070008c000000020220808a00000000022a0019000000ff0620018f00000000036301cf000003d606200167000000ff0660018f0000000107500270000000000667022f000000000763019f00000000012101cf000000800310027000000000a93700d900000000062501cf0000008008600270000003b10510019700000a8e0000013d000000000a3a0019000000010990008a000003b100a0009c00000a950000813d000003b70090009c00000a8a0000213d000000000b5900a9000000800ca00210000000000c8c019f0000000000cb004b00000a8a0000213d000003b10990019700000000091900a90000008007700210000000000787019f000000000797004900000000983700d9000003b10660019700000aa10000013d0000000009390019000000010880008a000003b10090009c00000aa80000813d000003b70080009c00000a9d0000213d000000000a5800a9000000800b900210000000000b6b019f0000000000ba004b00000a9d0000213d000003b10380019700000000011300a90000008003700210000000000363019f0000000001130049000000000121022f00000b3f0000013d000000000015004b00000ba60000813d000003ae3010012900000000201200d9000003b10010009c00000aba0000213d00000000072300a900000000701700d900000b130000013d000000010100008a00000b3f0000013d000000008a2300a9000000000081004b00000b130000a13d000003b40010009c000000c0070000390000008007004039000000000971022f00000040070000390000008007004039000003b50090009c000000200770808a0000002009908270000003b60090009c000000100770808a0000001009908270000001000090008c000000080770808a0000000809908270000000100090008c000000000b090019000000040bb082700000000400b0008c000000000c0b0019000000020cc08270000000020d00008a000000000ec000890000000200c0008c000000000e0d8019000000100090008c000000040770808a0000000400b0008c000000020770808a00000000077e0019000000ff0970018f00000000089801cf000003d609700167000000ff0990018f000000010ba0027000000000099b022f00030000009801a300000000087101cf000000800980027000000003fe9000f9000000000a7a01cf00040000000a001d000000800da00270000003b10a80019700000aee0000013d000000000f9f0019000000010ee0008a000003b100f0009c00000af50000813d000003b700e0009c00000aea0000213d000000000bae00a9000000800cf00210000000000cdc019f0000000000cb004b00000aea0000213d000003b10be00197000000000b8b00a9000000030c000029000000800cc00210000000000cdc019f0003000000bc005100000003ed9000f9000000040b000029000003b10bb0019700000b030000013d000000000e9e0019000000010dd0008a000003b100e0009c00000b0a0000813d000003b700d0009c00000aff0000213d000000000fad00a9000000800ce00210000000000cbc019f0000000000cf004b00000aff0000213d000003b109d0019700000000088900a9000000030900002900000080099002100000000009b9019f0000000008890049000000000778022f000000060d000029000000050e00002900000000081000890000000008810170000000000981c0d90000000009006019000000000676004b00000003079000c9000000020770015f000000000a9700a9000000020aa0008900000000077a00a9000000000a9700a9000000020aa0008900000000077a00a9000000010550408a000000000a9700a9000000020aa0008900000000077a00a9000000000a9700a9000000020aa0008900000000077a00a9000000000a9700a9000000020aa0008900000000077a00a900000000099700a9000000020990008900000000077900a9000000000008004b00000b350000613d00000000068600d9000000000980008900000000088900d9000000010880003900000000055800a900000b360000013d0000000006000019000000000800041500000000048400490000000004000002000000000456019f00000000044700a9000003b10010009c00000a5b0000213d00000000023200a900000000101200d9000000000001004b0000000001000039000000010100c039000000000014001a00000b8d0000413d000000000114001a000000010110008a000000640110011a000000010110003900000000010060190000000000e1001a00000b8d0000413d000000000ee1001900000000010d041a000003d600e0009c00000000030e00190000000003006019000003d60010009c0000000002010019000000000200601900000000423200a9000003b16340012a0000008005200270000003b80040009c00000b5e0000213d0000008006600210000000000656019f000003b1073000d1000000000067004b000000010330208a00000b5f0000013d000000010330008a0000008004400210000000000454019f000003b1033001970000000004340019000003b16340012a000003b105200197000003b80040009c00000b6d0000213d0000008002600210000000000252019f000003b1063000d1000000000026004b000000010330208a00000b6e0000013d000000010330008a0000000002e100a90000008004400210000000000454019f000003b1033001970000000003340019000000000323004b00000000040000390000000104004039000000000343004b00000b7a0000c13d000003ae0120012a00000b860000013d000003ae0030009c00000b9a0000813d000003ae40e0012a000003ae1010012a00000000014100a9000003ae1010012a000000000112004b000000010330408a0000002401100270000000dc02300210000000000112019f000003ba011000d10000000102d00039000000000202041a000000000121004b00000b8d0000413d000000000001042d000000000100001900000d9600010430000003a001000041000000000010043f0000001101000039000000040010043f000003910100004100000d9600010430000003a001000041000000000010043f0000003201000039000000040010043f000003910100004100000d9600010430000000000001042f000003b201000041000000000010043f0000001101000039000000200010043f000003b30100004100000d9600010430000003a001000041000000000010043f0000001201000039000000040010043f000003910100004100000d9600010430000003b202000041000000000020043f000000000001004b00000011010000390000001201006039000000200010043f000003b30100004100000d960001043000050000000000020000000102000039000000000302041a000000000013004b00000cf40000a13d000000000020043f00000007021000c90000039b0120009a000000000101041a000000ff0010019000000cf30000613d000500000002001d000003990120009a000300000001001d000000000101041a000400000001001d000003930100004100000000001004430000000001000414000003660010009c0000036601008041000000c00110021000000394011001c70000800b020000390d940d8f0000040f000000010020019000000cfa0000613d000000000101043b000000040010006c000000050f00002900000cf30000a13d0000039802f0009a000000000202041a000000000002004b000000030e00002900000cf20000613d00000000050e041a000000000451004b00000cfb0000413d0000039703f0009a000000000603041a00000000034600a9000000000051004b00000bdd0000613d00000000044300d9000000000064004b00000cfb0000c13d000000010800008a000000000083004b00000000040300190000000004006019000003ae544000d100000080064002700000008005500210000000000565019f000003b006400197000003b15750012a0000008005500210000000000565019f000003b1067000d1000000000056004b000000010770208a000003b10570019700000000044500190000000005000415000003ae073000d1000000000474004b00000000060000390000000106004039000000000664004b00000c000000c13d00000000040004150000000004450049000000000400000200000000302300d900000000052700d9000003ae40200129000003b10020009c00000c8d0000213d00000000034300a900000000202300d900000ce20000013d000000000026004b00000d010000813d000003ae4020012900000000302300d9000003b10020009c00000c090000213d00000000083400a900000000802800d900000c630000013d000000009b3400a9000000000092004b00000c630000a13d000003b40020009c000000c0080000390000008008004039000000000a82022f00000040080000390000008008004039000003b500a0009c000000200880808a000000200aa08270000003b600a0009c000000100880808a000000100aa082700000010000a0008c000000080880808a000000080aa082700000001000a0008c000000000c0a0019000000040cc082700000000400c0008c000000000d0c0019000000020dd08270000000020e00008a000000000fd000890000000200d0008c000000000f0e80190000001000a0008c000000040880808a0000000400c0008c000000020880808a00000000088f0019000000ff0a80018f0000000009a901cf000003d60a800167000000ff0aa0018f000000010cb00270000000000aac022f0001000000a901a300000000098201cf000000800a90027000000001cfa000f9000000000b8b01cf00020000000b001d000000800eb00270000400000009001d000003b10b90019700000c3e0000013d000000000cac0019000000010ff0008a000003b100c0009c00000c450000813d000003b700f0009c00000c3a0000213d000000000dbf00a90000008009c002100000000009e9019f00000000009d004b00000c3a0000213d000003b109f0019700000004099000b9000000010c000029000000800cc00210000000000cec019f00010000009c005100000001fea000f90000000209000029000003b10c90019700000c530000013d000000000faf0019000000010ee0008a000003b100f0009c00000c5a0000813d000003b700e0009c00000c4f0000213d0000000009be00a9000000800df00210000000000dcd019f0000000000d9004b00000c4f0000213d000003b109e0019700000004099000b9000000010a000029000000800aa00210000000000aca019f00000000099a0049000000000889022f000000030e000029000000050f00002900000000092000890000000009920170000000000a92c0d9000000000a006019000000000787004b0000000308a000c9000000020880015f000000000ba800a9000000020bb0008900000000088b00a9000000000ba800a9000000020bb0008900000000088b00a9000000010660408a000000000ba800a9000000020bb0008900000000088b00a9000000000ba800a9000000020bb0008900000000088b00a9000000000ba800a9000000020bb0008900000000088b00a9000000000aa800a9000000020aa0008900000000088a00a9000000000009004b00000c850000613d00000000079700d9000000000a90008900000000099a00d9000000010990003900000000066900a900000c860000013d0000000007000019000000000900041500000000059500490000000005000002000000000567019f00000000055800a9000003b10020009c00000bfd0000a13d00000000464300a9000000000042004b00000ce10000a13d000003b40020009c000000c0030000390000008003004039000000000732022f00000040030000390000008003004039000003b50070009c000000200330808a0000002007708270000003b60070009c000000100330808a0000001007708270000001000070008c000000080330808a0000000807708270000000100070008c00000000080700190000000408808270000000040080008c00000000090800190000000209908270000000020a00008a000000000b900089000000020090008c000000000b0a8019000000100070008c000000040330808a000000040080008c000000020330808a00000000033b0019000000ff0730018f00000000047401cf000003d607300167000000ff0770018f0000000108600270000000000778022f000000000874019f00000000023201cf000000800420027000000000ba4800d900000000073601cf0000008009700270000003b10620019700000cc00000013d000000000b4b0019000000010aa0008a000003b100b0009c00000cc70000813d000003b700a0009c00000cbc0000213d000000000c6a00a9000000800db00210000000000d9d019f0000000000dc004b00000cbc0000213d000003b10aa00197000000000a2a00a90000008008800210000000000898019f0000000008a8004900000000a94800d9000003b10770019700000cd30000013d000000000a4a0019000000010990008a000003b100a0009c00000cda0000813d000003b70090009c00000ccf0000213d000000000b6900a9000000800ca00210000000000c7c019f0000000000cb004b00000ccf0000213d000003b10490019700000000022400a90000008004800210000000000474019f0000000002240049000000000232022f00000ce20000013d000000010200008a000000000002004b0000000002000039000000010200c039000000000025001a00000cfb0000413d000000000225001a000000010220008a000000640220011a000000010220003900000000020060190000039a03f0009a000000000403041a000000000024001a00000cfb0000413d0000000002240019000000000023041b00000000001e041b000000000001042d000003a001000041000000000010043f0000003201000039000000040010043f000003910100004100000d9600010430000000000001042f000003a001000041000000000010043f0000001101000039000000040010043f000003910100004100000d9600010430000003b201000041000000000010043f0000001101000039000000200010043f000003b30100004100000d960001043000020000000000020000000004010019000000400100043d000200000001001d000003bc01000041000000000010043f0000036901200197000000040010043f000000240030043f0000000001000414000003660010009c0000036601008041000000c001100210000003bd011001c7000100000004001d00000000020400190d940d8a0000040f00000060031002700000036603300197000000200030008c000000200400003900000000040340190000001f0540018f000000200440019000000d260000613d000000000601034f0000000007000019000000006806043c0000000007870436000000000047004b00000d220000c13d000000000005004b00000d330000613d000000000641034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000000000003001f000000000400043d000000010040008c00000000040000390000000104006039000000000424016f000000010040019000000d3e0000613d0000000201000029000000400010043f000000000001042d000000010020019000000d560000613d000003be010000410000000000100443000000010100002900000004001004430000000001000414000003660010009c0000036601008041000000c001100210000003bf011001c700008002020000390d940d8f0000040f000000010020019000000d740000613d000000000201043b00000000010000310000000203000029000000400030043f000000000002004b00000d750000613d000000000001004b00000d750000c13d000000000001042d0000001f0430018f0000036805300198000000020250002900000d600000613d000000000601034f0000000207000029000000006806043c0000000007870436000000000027004b00000d5c0000c13d000000000004004b00000d6d0000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000012043500000060013002100000000202000029000003660020009c00000366020080410000004002200210000000000121019f00000d9600010430000000000001042f000003c001000041000000000010043f00000001010000290000036901100197000000040010043f000003910100004100000d9600010430000000000001042f0000000001000414000003660010009c0000036601008041000000c001100210000003a9011001c700008010020000390d940d8f0000040f000000010020019000000d880000613d000000000101043b000000000001042d000000000100001900000d960001043000000d8d002104210000000102000039000000000001042d0000000002000019000000000001042d00000d92002104230000000102000039000000000001042d0000000002000019000000000001042d00000d940000043200000d950001042e00000d9600010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00ffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e00000000200000000000000000000000000000040000001000000000000000000000000000000000000000000000000000000000000000000000000007da470e900000000000000000000000000000000000000000000000000000000a9ce878000000000000000000000000000000000000000000000000000000000cc430cec00000000000000000000000000000000000000000000000000000000efe829e200000000000000000000000000000000000000000000000000000000efe829e300000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000cc430ced00000000000000000000000000000000000000000000000000000000e3e9d3c900000000000000000000000000000000000000000000000000000000a9ce878100000000000000000000000000000000000000000000000000000000bff5f32f00000000000000000000000000000000000000000000000000000000c4f4bb8a000000000000000000000000000000000000000000000000000000009e2c8a5a000000000000000000000000000000000000000000000000000000009e2c8a5b00000000000000000000000000000000000000000000000000000000a1164e7a00000000000000000000000000000000000000000000000000000000a8a77a19000000000000000000000000000000000000000000000000000000007da470ea000000000000000000000000000000000000000000000000000000008da5cb5b00000000000000000000000000000000000000000000000000000000918d24280000000000000000000000000000000000000000000000000000000057c8f3a6000000000000000000000000000000000000000000000000000000007b0472ef000000000000000000000000000000000000000000000000000000007b0472f0000000000000000000000000000000000000000000000000000000007bd1f335000000000000000000000000000000000000000000000000000000007c254a3f0000000000000000000000000000000000000000000000000000000057c8f3a700000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000007af5096e000000000000000000000000000000000000000000000000000000001609be1c000000000000000000000000000000000000000000000000000000001609be1d0000000000000000000000000000000000000000000000000000000021ce919d000000000000000000000000000000000000000000000000000000003ac795de000000000000000000000000000000000000000000000000000000000fac9100000000000000000000000000000000000000000000000000000000001088ce900000000000000000000000000000000000000000000000000000000013629616118cdaa70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000001e4fbdf70000000000000000000000000000000000000000000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd1020000020000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000100000000000000004ef1d2ad89edf8c4d91132028e8195cdf30bb4b5053d4f8cd260341d4805f30a4ef1d2ad89edf8c4d91132028e8195cdf30bb4b5053d4f8cd260341d4805f3094ef1d2ad89edf8c4d91132028e8195cdf30bb4b5053d4f8cd260341d4805f3084ef1d2ad89edf8c4d91132028e8195cdf30bb4b5053d4f8cd260341d4805f3074ef1d2ad89edf8c4d91132028e8195cdf30bb4b5053d4f8cd260341d4805f3064ef1d2ad89edf8c4d91132028e8195cdf30bb4b5053d4f8cd260341d4805f3054ef1d2ad89edf8c4d91132028e8195cdf30bb4b5053d4f8cd260341d4805f30402000000000000000000000000000000000000600000000000000000000000001dd09f68aa4db65609048a3df9956331c7af14f3be4947a465dbe2eb5111097b00000000000000000000000000000000000000200000000000000000000000004e487b710000000000000000000000000000000000000000000000000000000008c379a000000000000000000000000000000000000000000000000000000000496e76616c6964206c7020746f6b656e0000000000000000000000000000000000000000000000000000000000000000000000640000008000000000000000000200000000000000000000000000000000000020000000000000000000000000dfc6dcf27ce9b06323e51aa357be4568ae42dfa29228c97d2f4e020f94fbad2b506f696e7473206d757374206265206774203130000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff417272617973206c656e677468206d69736d61746368000000000000000000000200000000000000000000000000000000000040000000000000000000000000abd04b33b87ac0c0d555b2cd0c1ea20528db91242039eb0358dd8d7704674035496e76616c69642075736572206164647265737300000000000000000000000000000000000000000000000000000000000000640000000000000000000000004e6f2075736572732070726f76696465640000000000000000000000000000000000000000000000000000000000000000c097ce7bc90715b34b9f1000000000000000000000000000000000000000000000002000000080000000000000000000000000000000000000000000000000fffffffffffffffffffffff00000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000004e487b7100000000000000000000000000000000000000240000001c000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000fffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000000000000000000000c097ce7bc90715b34b9f0fffffffff356317ffa45f828d2a41175b2aed3a20e7fdd4a4e46cc11944d93b01be7b17110000000000000000000000000000000000000040000000000000000000000000a9059cbb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8302000002000000000000000000000000000000240000000000000000000000005274afe700000000000000000000000000000000000000000000000000000000f960dbf9e5d0682f7a298ed974e33a28b4464914b7a2bfac12ae419a9afeb28052656d61696e696e67206d757374206265206774206d696e0000000000000000496e73756666696369656e74207374616b656420616d6f756e740000000000004f6e6c79204e46544d696e7465722063616e207370656e6420706f696e747300e468e4bd9f7603e9acc4484edbd2aa85bc8f378431137b6b9eccb46ef9c4da49496e73756666696369656e7420706f696e74730000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000004eac300b07203fbb623811117a3e85be9e3f0b587a61eb4a9e974e8a5a7f4086496e76616c6964206e6674206d696e746572000000000000000000000000000023b872dd000000000000000000000000000000000000000000000000000000005af417134f72a9d41143ace85b0a26dce6f550f894f2cbc1eeee8810603d91b64661726d206973206e6f74206163746976650000000000000000000000000000416d6f756e74206c74206d696e5374616b65416d6f756e7400000000000000003e092a883af33ee546d17fff529b409581fa4e09034021577ffafe5672910eb23ee5aeb5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004000000080000000000000000070a08231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000800000000000000000496e76616c696420726563656976657220616464726573730000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000a2646970667358221220bbc1095125280b56d8525f44c2ad65286127d1f7732f839a75ee6d345b4969ee64736f6c6378247a6b736f6c633a312e352e31353b736f6c633a302e382e32383b6c6c766d3a312e302e310055
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000fd3f90dd1355910fef471f7a8852714ff97cbfbd
-----Decoded View---------------
Arg [0] : _owner (address): 0xfD3f90DD1355910feF471f7A8852714FF97cBfBD
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000fd3f90dd1355910fef471f7a8852714ff97cbfbd
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.