Source Code
Overview
S Balance
More Info
ContractCreator
Multichain Info
N/A
Loading...
Loading
Contract Name:
OtcMarketplace
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
/**
* @title OtcMarketplace
* @notice OTC Marketplace for buying and selling MCGP tokens with USDC
* @dev Only admin can fund/withdraw and update price phases
*/
contract OtcMarketplace is Ownable, ReentrancyGuard, Pausable {
using SafeERC20 for IERC20;
IERC20 public immutable mcgpToken;
IERC20 public immutable usdcToken;
// Price phases configuration
struct PricePhase {
uint256 price; // Price in USDC (with 6 decimals) per MCGP (18 decimals)
bool isActive;
bool isBuyPhase; // true for buy phases, false for sell phases
string name; // e.g., "1000X down", "2X up"
}
PricePhase[] public buyPhases;
PricePhase[] public sellPhases;
uint256 public activeBuyPhaseIndex;
uint256 public activeSellPhaseIndex;
// Max price to prevent overflow/DoS ($1,000,000 per MCGP)
uint256 public constant MAX_PRICE = 1e12;
// Events
event Bought(address indexed buyer, uint256 mcgpAmount, uint256 usdcAmount, uint256 indexed phaseIndex);
event Sold(address indexed seller, uint256 mcgpAmount, uint256 usdcAmount, uint256 indexed phaseIndex);
event PhaseChanged(bool indexed isBuyPhase, uint256 indexed newPhaseIndex);
event PriceUpdated(bool indexed isBuyPhase, uint256 indexed phaseIndex, uint256 newPrice);
event Funded(address indexed token, uint256 amount);
event Withdrawn(address indexed token, uint256 amount);
/**
* @param _mcgpToken Address of MCGP token
* @param _usdcToken Address of USDC token
*/
constructor(address _mcgpToken, address _usdcToken) Ownable(msg.sender) {
require(_mcgpToken != address(0), "Invalid MCGP address");
require(_usdcToken != address(0), "Invalid USDC address");
mcgpToken = IERC20(_mcgpToken);
usdcToken = IERC20(_usdcToken);
// Initialize sell phases (presale price = $0.01)
// Price is in USDC (6 decimals) per MCGP (18 decimals)
// 1000X down = $0.00001 = 10 USDC (6 decimals) per 1 MCGP (18 decimals)
sellPhases.push(PricePhase({
price: 10, // $0.00001 per MCGP
isActive: true,
isBuyPhase: false,
name: "1000X down"
}));
sellPhases.push(PricePhase({
price: 100, // $0.0001 per MCGP
isActive: false,
isBuyPhase: false,
name: "100X down"
}));
sellPhases.push(PricePhase({
price: 1000, // $0.001 per MCGP
isActive: false,
isBuyPhase: false,
name: "10X down"
}));
sellPhases.push(PricePhase({
price: 10000, // $0.01 per MCGP (presale price)
isActive: false,
isBuyPhase: false,
name: "1X up"
}));
sellPhases.push(PricePhase({
price: 100000, // $0.1 per MCGP
isActive: false,
isBuyPhase: false,
name: "10X up"
}));
sellPhases.push(PricePhase({
price: 1000000, // $1 per MCGP
isActive: false,
isBuyPhase: false,
name: "100X up"
}));
sellPhases.push(PricePhase({
price: 10000000, // $10 per MCGP
isActive: false,
isBuyPhase: false,
name: "1000X up"
}));
// Initialize buy phases
// 2X up = $0.02 per MCGP
buyPhases.push(PricePhase({
price: 20000, // $0.02 per MCGP
isActive: true,
isBuyPhase: true,
name: "2X up"
}));
buyPhases.push(PricePhase({
price: 200000, // $0.2 per MCGP
isActive: false,
isBuyPhase: true,
name: "20X up"
}));
buyPhases.push(PricePhase({
price: 2000000, // $2 per MCGP
isActive: false,
isBuyPhase: true,
name: "200X up"
}));
buyPhases.push(PricePhase({
price: 20000000, // $20 per MCGP
isActive: false,
isBuyPhase: true,
name: "2000X up"
}));
activeBuyPhaseIndex = 0;
activeSellPhaseIndex = 0;
}
/**
* @notice Calculate USDC amount needed for buying MCGP
* @param mcgpAmount Amount of MCGP to buy (18 decimals)
* @return USDC amount needed (6 decimals)
*/
function calculateBuyPrice(uint256 mcgpAmount) public view returns (uint256) {
PricePhase memory phase = buyPhases[activeBuyPhaseIndex];
require(phase.isActive, "Buy phase not active");
// price is USDC (6 decimals) per MCGP (18 decimals)
// usdcAmount = (mcgpAmount * price) / 1e18
return (mcgpAmount * phase.price) / 1e18;
}
/**
* @notice Calculate USDC amount received for selling MCGP
* @param mcgpAmount Amount of MCGP to sell (18 decimals)
* @return USDC amount received (6 decimals)
*/
function calculateSellPrice(uint256 mcgpAmount) public view returns (uint256) {
PricePhase memory phase = sellPhases[activeSellPhaseIndex];
require(phase.isActive, "Sell phase not active");
// price is USDC (6 decimals) per MCGP (18 decimals)
// usdcAmount = (mcgpAmount * price) / 1e18
return (mcgpAmount * phase.price) / 1e18;
}
/**
* @notice Buy MCGP with USDC
* @param mcgpAmount Amount of MCGP to buy (18 decimals)
* @param maxUsdcAmount Maximum USDC willing to pay (slippage protection)
*/
function buy(uint256 mcgpAmount, uint256 maxUsdcAmount) external nonReentrant whenNotPaused {
require(mcgpAmount > 0, "Amount must be greater than 0");
uint256 usdcAmount = calculateBuyPrice(mcgpAmount);
require(usdcAmount > 0, "USDC amount must be greater than 0");
require(usdcAmount <= maxUsdcAmount, "Slippage exceeded");
// Check contract has enough MCGP
require(mcgpToken.balanceOf(address(this)) >= mcgpAmount, "Insufficient MCGP in contract");
// Transfer USDC from buyer to contract
usdcToken.safeTransferFrom(msg.sender, address(this), usdcAmount);
// Transfer MCGP from contract to buyer
mcgpToken.safeTransfer(msg.sender, mcgpAmount);
emit Bought(msg.sender, mcgpAmount, usdcAmount, activeBuyPhaseIndex);
}
/**
* @notice Sell MCGP for USDC
* @param mcgpAmount Amount of MCGP to sell (18 decimals)
* @param minUsdcAmount Minimum USDC willing to receive (slippage protection)
*/
function sell(uint256 mcgpAmount, uint256 minUsdcAmount) external nonReentrant whenNotPaused {
require(mcgpAmount > 0, "Amount must be greater than 0");
uint256 usdcAmount = calculateSellPrice(mcgpAmount);
require(usdcAmount > 0, "USDC amount must be greater than 0");
require(usdcAmount >= minUsdcAmount, "Slippage exceeded");
// Check contract has enough USDC
require(usdcToken.balanceOf(address(this)) >= usdcAmount, "Insufficient USDC in contract");
// Transfer MCGP from seller to contract
mcgpToken.safeTransferFrom(msg.sender, address(this), mcgpAmount);
// Transfer USDC from contract to seller
usdcToken.safeTransfer(msg.sender, usdcAmount);
emit Sold(msg.sender, mcgpAmount, usdcAmount, activeSellPhaseIndex);
}
/**
* @notice Set active buy phase (only owner)
* @param phaseIndex Index of the phase to activate
*/
function setActiveBuyPhase(uint256 phaseIndex) external onlyOwner {
require(phaseIndex < buyPhases.length, "Invalid phase index");
// Deactivate current phase
buyPhases[activeBuyPhaseIndex].isActive = false;
// Activate new phase
activeBuyPhaseIndex = phaseIndex;
buyPhases[phaseIndex].isActive = true;
emit PhaseChanged(true, phaseIndex);
}
/**
* @notice Set active sell phase (only owner)
* @param phaseIndex Index of the phase to activate
*/
function setActiveSellPhase(uint256 phaseIndex) external onlyOwner {
require(phaseIndex < sellPhases.length, "Invalid phase index");
// Deactivate current phase
sellPhases[activeSellPhaseIndex].isActive = false;
// Activate new phase
activeSellPhaseIndex = phaseIndex;
sellPhases[phaseIndex].isActive = true;
emit PhaseChanged(false, phaseIndex);
}
/**
* @notice Update price for a specific phase (only owner)
* @param isBuyPhase True for buy phase, false for sell phase
* @param phaseIndex Index of the phase to update
* @param newPrice New price in USDC (6 decimals) per MCGP (18 decimals)
*/
function updatePhasePrice(bool isBuyPhase, uint256 phaseIndex, uint256 newPrice) external onlyOwner {
require(newPrice > 0, "Price must be greater than 0");
require(newPrice <= MAX_PRICE, "Price exceeds maximum");
if (isBuyPhase) {
require(phaseIndex < buyPhases.length, "Invalid phase index");
buyPhases[phaseIndex].price = newPrice;
} else {
require(phaseIndex < sellPhases.length, "Invalid phase index");
sellPhases[phaseIndex].price = newPrice;
}
emit PriceUpdated(isBuyPhase, phaseIndex, newPrice);
}
/**
* @notice Fund contract with tokens (only owner)
* @param token Address of token to fund
* @param amount Amount to fund
*/
function fund(address token, uint256 amount) external onlyOwner {
require(token == address(mcgpToken) || token == address(usdcToken), "Invalid token");
require(amount > 0, "Amount must be greater than 0");
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
emit Funded(token, amount);
}
/**
* @notice Withdraw tokens from contract (only owner)
* @param token Address of token to withdraw
* @param amount Amount to withdraw
*/
function withdraw(address token, uint256 amount) external onlyOwner {
require(token == address(mcgpToken) || token == address(usdcToken), "Invalid token");
require(amount > 0, "Amount must be greater than 0");
require(IERC20(token).balanceOf(address(this)) >= amount, "Insufficient balance");
IERC20(token).safeTransfer(msg.sender, amount);
emit Withdrawn(token, amount);
}
/**
* @notice Pause trading (only owner)
*/
function pause() external onlyOwner {
_pause();
}
/**
* @notice Unpause trading (only owner)
*/
function unpause() external onlyOwner {
_unpause();
}
/**
* @notice Get all buy phases
*/
function getBuyPhases() external view returns (PricePhase[] memory) {
return buyPhases;
}
/**
* @notice Get all sell phases
*/
function getSellPhases() external view returns (PricePhase[] memory) {
return sellPhases;
}
/**
* @notice Get contract balances
*/
function getBalances() external view returns (uint256 mcgpBalance, uint256 usdcBalance) {
mcgpBalance = mcgpToken.balanceOf(address(this));
usdcBalance = usdcToken.balanceOf(address(this));
}
}// 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 {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev 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 _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @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 _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* 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 {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev 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 high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// 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.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/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
bool private _paused;
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @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].
*/
abstract contract ReentrancyGuard {
// 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;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = 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();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = 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 _status == ENTERED;
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract ABI
API[{"inputs":[{"internalType":"address","name":"_mcgpToken","type":"address"},{"internalType":"address","name":"_usdcToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"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":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"mcgpAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usdcAmount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"phaseIndex","type":"uint256"}],"name":"Bought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Funded","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":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isBuyPhase","type":"bool"},{"indexed":true,"internalType":"uint256","name":"newPhaseIndex","type":"uint256"}],"name":"PhaseChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bool","name":"isBuyPhase","type":"bool"},{"indexed":true,"internalType":"uint256","name":"phaseIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"PriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"uint256","name":"mcgpAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usdcAmount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"phaseIndex","type":"uint256"}],"name":"Sold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"MAX_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeBuyPhaseIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeSellPhaseIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mcgpAmount","type":"uint256"},{"internalType":"uint256","name":"maxUsdcAmount","type":"uint256"}],"name":"buy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"buyPhases","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isBuyPhase","type":"bool"},{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mcgpAmount","type":"uint256"}],"name":"calculateBuyPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mcgpAmount","type":"uint256"}],"name":"calculateSellPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"fund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBalances","outputs":[{"internalType":"uint256","name":"mcgpBalance","type":"uint256"},{"internalType":"uint256","name":"usdcBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBuyPhases","outputs":[{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isBuyPhase","type":"bool"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct OtcMarketplace.PricePhase[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSellPhases","outputs":[{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isBuyPhase","type":"bool"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct OtcMarketplace.PricePhase[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mcgpToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"mcgpAmount","type":"uint256"},{"internalType":"uint256","name":"minUsdcAmount","type":"uint256"}],"name":"sell","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"sellPhases","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isBuyPhase","type":"bool"},{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"phaseIndex","type":"uint256"}],"name":"setActiveBuyPhase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"phaseIndex","type":"uint256"}],"name":"setActiveSellPhase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isBuyPhase","type":"bool"},{"internalType":"uint256","name":"phaseIndex","type":"uint256"},{"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"updatePhasePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"usdcToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c06040523480156200001157600080fd5b506040516200288238038062002882833981016040819052620000349162000a66565b33806200005c57604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b6200006781620009f9565b50600180556001600160a01b038216620000c45760405162461bcd60e51b815260206004820152601460248201527f496e76616c6964204d4347502061646472657373000000000000000000000000604482015260640162000053565b6001600160a01b0381166200011c5760405162461bcd60e51b815260206004820152601460248201527f496e76616c696420555344432061646472657373000000000000000000000000604482015260640162000053565b6001600160a01b03808316608090815290821660a052604080519182018152600a808352600160208085018281526000868601818152865180880190975294865269189818182c103237bbb760b11b92860192909252606086019485526004805493840181559091528451600390920260008051602062002862833981519152810192835590516000805160206200282283398151915282018054945115156101000261ff00199215159290921661ffff19909516949094171790925591516000805160206200284283398151915290910190620001fb908262000b43565b5050604080516080810182526064815260006020808301828152838501838152855180870190965260098652681898182c103237bbb760b91b92860192909252606084019485526004805460018101825593528351600390930260008051602062002862833981519152810193845590516000805160206200282283398151915282018054935115156101000261ff00199215159290921661ffff199094169390931717909155925191935091600080516020620028428339815191520190620002c6908262000b43565b5050604080516080810182526103e88152600060208083018281528385018381528551808701909652600886526718982c103237bbb760c11b92860192909252606084019485526004805460018101825593528351600390930260008051602062002862833981519152810193845590516000805160206200282283398151915282018054935115156101000261ff00199215159290921661ffff19909416939093171790915592519193509160008051602062002842833981519152019062000391908262000b43565b50506040805160808101825261271081526000602080830182815283850183815285518087019096526005865264031582075760dc1b92860192909252606084019485526004805460018101825593528351600390930260008051602062002862833981519152810193845590516000805160206200282283398151915282018054935115156101000261ff00199215159290921661ffff19909416939093171790915592519193509160008051602062002842833981519152019062000459908262000b43565b505060408051608081018252620186a08152600060208083018281528385018381528551808701909652600686526503130582075760d41b92860192909252606084019485526004805460018101825593528351600390930260008051602062002862833981519152810193845590516000805160206200282283398151915282018054935115156101000261ff00199215159290921661ffff19909416939093171790915592519193509160008051602062002842833981519152019062000523908262000b43565b505060408051608081018252620f4240815260006020808301828152838501838152855180870190965260078652660313030582075760cc1b92860192909252606084019485526004805460018101825593528351600390930260008051602062002862833981519152810193845590516000805160206200282283398151915282018054935115156101000261ff00199215159290921661ffff199094169390931717909155925191935091600080516020620028428339815191520190620005ee908262000b43565b5050604080516080810182526298968081526000602080830182815283850183815285518087019096526008865267031303030582075760c41b92860192909252606084019485526004805460018101825593528351600390930260008051602062002862833981519152810193845590516000805160206200282283398151915282018054935115156101000261ff00199215159290921661ffff199094169390931717909155925191935091600080516020620028428339815191520190620006ba908262000b43565b505060408051608081018252614e2081526001602080830182815283850183815285518087019096526005865264032582075760dc1b9286019290925260608401948552600380549384018155600081905284519302600080516020620027e283398151915281019384559051600080516020620027c283398151915282018054935115156101000261ff00199215159290921661ffff19909416939093171790915592519193509160008051602062002802833981519152019062000781908262000b43565b50506040805160808101825262030d4081526000602080830182815260018486018181528651808801909752600687526503230582075760d41b93870193909352606085019586526003805491820181559384905284519302600080516020620027e283398151915281019384559051600080516020620027c283398151915282018054935115156101000261ff00199215159290921661ffff1990941693909317179091559251919350916000805160206200280283398151915201906200084b908262000b43565b505060408051608081018252621e84808152600060208083018281526001848601818152865180880190975260078752660323030582075760cc1b93870193909352606085019586526003805491820181559384905284519302600080516020620027e283398151915281019384559051600080516020620027c283398151915282018054935115156101000261ff00199215159290921661ffff19909416939093171790915592519193509160008051602062002802833981519152019062000916908262000b43565b5050604080516080810182526301312d00815260006020808301828152600184860181815286518088019097526008875267032303030582075760c41b93870193909352606085019586526003805491820181559384905284519302600080516020620027e283398151915281019384559051600080516020620027c283398151915282018054935115156101000261ff00199215159290921661ffff199094169390931717909155925191935091600080516020620028028339815191520190620009e3908262000b43565b5050600060058190556006555062000c0f915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811462000a6157600080fd5b919050565b6000806040838503121562000a7a57600080fd5b62000a858362000a49565b915062000a956020840162000a49565b90509250929050565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168062000ac957607f821691505b60208210810362000aea57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000b3e57600081815260208120601f850160051c8101602086101562000b195750805b601f850160051c820191505b8181101562000b3a5782815560010162000b25565b5050505b505050565b81516001600160401b0381111562000b5f5762000b5f62000a9e565b62000b778162000b70845462000ab4565b8462000af0565b602080601f83116001811462000baf576000841562000b965750858301515b600019600386901b1c1916600185901b17855562000b3a565b600085815260208120601f198616915b8281101562000be05788860151825594840194600190910190840162000bbf565b508582101562000bff5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a051611b3962000c89600039600081816101b80152818161042201528181610be401528181611061015281816111c2015281816112c501526113aa0152600081816102340152818161039f01528181610ba901528181610f930152818161109601528181611290015261136f0152611b396000f3fe608060405234801561001057600080fd5b50600436106101725760003560e01c8063715018a6116100de5780638de37e7f11610097578063d6febde811610071578063d6febde814610331578063d79875eb14610344578063f2fde38b14610357578063f3fef3a31461036a57600080fd5b80638de37e7f14610303578063ad4a154d1461030b578063c205d6dc1461031e57600080fd5b8063715018a6146102b3578063722c631f146102bb57806374d1a4a4146102c45780637b1837de146102d75780638456cb59146102ea5780638da5cb5b146102f257600080fd5b80633b3413f2116101305780633b3413f21461022f5780633f4ba83a146102565780634634ea7b1461025e57806358b9a996146102815780635c975abb146102945780636c77c1f3146102aa57600080fd5b8062113e081461017757806301c11d961461019957806311eac855146101b35780632d007541146101f25780632e5e2b3b14610207578063348cdd6b1461021a575b600080fd5b61017f61037d565b604080519283526020830191909152015b60405180910390f35b6101a564e8d4a5100081565b604051908152602001610190565b6101da7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610190565b6101fa61049b565b604051610190919061180f565b6101a561021536600461189e565b6105ba565b61022d6102283660046118b7565b610725565b005b6101da7f000000000000000000000000000000000000000000000000000000000000000081565b61022d6108a4565b61027161026c36600461189e565b6108b6565b60405161019094939291906118f1565b6101a561028f36600461189e565b610980565b60025460ff166040519015158152602001610190565b6101a560065481565b61022d610abe565b6101a560055481565b61022d6102d236600461189e565b610ad0565b61022d6102e5366004611940565b610b9f565b61022d610cd0565b6000546001600160a01b03166101da565b6101fa610ce0565b61022d61031936600461189e565b610df6565b61027161032c36600461189e565b610ecb565b61022d61033f36600461196a565b610edb565b61022d61035236600461196a565b61110a565b61022d61036536600461198c565b611327565b61022d610378366004611940565b611365565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156103e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040a91906119a7565b6040516370a0823160e01b81523060048201529092507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610471573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049591906119a7565b90509091565b60606003805480602002602001604051908101604052809291908181526020016000905b828210156105b1576000848152602090819020604080516080810182526003860290920180548352600181015460ff8082161515958501959095526101009004909316151590820152600282018054919291606084019190610520906119c0565b80601f016020809104026020016040519081016040528092919081815260200182805461054c906119c0565b80156105995780601f1061056e57610100808354040283529160200191610599565b820191906000526020600020905b81548152906001019060200180831161057c57829003601f168201915b505050505081525050815260200190600101906104bf565b50505050905090565b6000806004600654815481106105d2576105d26119fa565b600091825260209182902060408051608081018252600390930290910180548352600181015460ff808216151595850195909552610100900490931615159082015260028201805491929160608401919061062c906119c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610658906119c0565b80156106a55780601f1061067a576101008083540402835291602001916106a5565b820191906000526020600020905b81548152906001019060200180831161068857829003601f168201915b505050505081525050905080602001516106fe5760405162461bcd60e51b815260206004820152601560248201527453656c6c207068617365206e6f742061637469766560581b60448201526064015b60405180910390fd5b8051670de0b6b3a7640000906107149085611a10565b61071e9190611a3b565b9392505050565b61072d611538565b6000811161077d5760405162461bcd60e51b815260206004820152601c60248201527f5072696365206d7573742062652067726561746572207468616e20300000000060448201526064016106f5565b64e8d4a510008111156107ca5760405162461bcd60e51b815260206004820152601560248201527450726963652065786365656473206d6178696d756d60581b60448201526064016106f5565b821561081b5760035482106107f15760405162461bcd60e51b81526004016106f590611a5d565b8060038381548110610805576108056119fa565b6000918252602090912060039091020155610862565b600454821061083c5760405162461bcd60e51b81526004016106f590611a5d565b8060048381548110610850576108506119fa565b60009182526020909120600390910201555b818315157f1c8f6d94f4fe1f18a92ced0503f4f49f4eb87c32a28f5cc2d32f01239e305bb48360405161089791815260200190565b60405180910390a3505050565b6108ac611538565b6108b4611565565b565b600381815481106108c657600080fd5b600091825260209091206003909102018054600182015460028301805492945060ff8083169461010090930416926108fd906119c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610929906119c0565b80156109765780601f1061094b57610100808354040283529160200191610976565b820191906000526020600020905b81548152906001019060200180831161095957829003601f168201915b5050505050905084565b600080600360055481548110610998576109986119fa565b600091825260209182902060408051608081018252600390930290910180548352600181015460ff80821615159585019590955261010090049093161515908201526002820180549192916060840191906109f2906119c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1e906119c0565b8015610a6b5780601f10610a4057610100808354040283529160200191610a6b565b820191906000526020600020905b815481529060010190602001808311610a4e57829003601f168201915b505050505081525050905080602001516106fe5760405162461bcd60e51b8152602060048201526014602482015273427579207068617365206e6f742061637469766560601b60448201526064016106f5565b610ac6611538565b6108b460006115b7565b610ad8611538565b6004548110610af95760405162461bcd60e51b81526004016106f590611a5d565b6000600460065481548110610b1057610b106119fa565b600091825260209091206003909102016001908101805460ff19169215159290921790915560068290556004805483908110610b4e57610b4e6119fa565b60009182526020822060039190910201600101805460ff1916921515929092179091556040518291907f2556b22513064d557ca3c72657a7683d576284f8424e1b42e1e9fbc6353bd184908290a350565b610ba7611538565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161480610c1857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316145b610c545760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016106f5565b60008111610c745760405162461bcd60e51b81526004016106f590611a8a565b610c896001600160a01b038316333084611607565b816001600160a01b03167f5af8184bef8e4b45eb9f6ed7734d04da38ced226495548f46e0c8ff8d7d9a52482604051610cc491815260200190565b60405180910390a25050565b610cd8611538565b6108b4611674565b60606004805480602002602001604051908101604052809291908181526020016000905b828210156105b1576000848152602090819020604080516080810182526003860290920180548352600181015460ff8082161515958501959095526101009004909316151590820152600282018054919291606084019190610d65906119c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610d91906119c0565b8015610dde5780601f10610db357610100808354040283529160200191610dde565b820191906000526020600020905b815481529060010190602001808311610dc157829003601f168201915b50505050508152505081526020019060010190610d04565b610dfe611538565b6003548110610e1f5760405162461bcd60e51b81526004016106f590611a5d565b6000600360055481548110610e3657610e366119fa565b906000526020600020906003020160010160006101000a81548160ff02191690831515021790555080600581905550600160038281548110610e7a57610e7a6119fa565b60009182526020822060016003909202018101805493151560ff19909416939093179092556040518392917f2556b22513064d557ca3c72657a7683d576284f8424e1b42e1e9fbc6353bd18491a350565b600481815481106108c657600080fd5b610ee36116b1565b610eeb6116db565b60008211610f0b5760405162461bcd60e51b81526004016106f590611a8a565b6000610f1683610980565b905060008111610f385760405162461bcd60e51b81526004016106f590611ac1565b81811115610f7c5760405162461bcd60e51b815260206004820152601160248201527014db1a5c1c1859d948195e18d959591959607a1b60448201526064016106f5565b6040516370a0823160e01b815230600482015283907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610fe2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100691906119a7565b10156110545760405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e74204d43475020696e20636f6e747261637400000060448201526064016106f5565b6110896001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084611607565b6110bd6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633856116ff565b600554604080518581526020810184905233917fedba86fd2b22962d534e70ad9b0ff8730de46f636146f2bab6a72cbb1ebbcc5391015b60405180910390a35061110660018055565b5050565b6111126116b1565b61111a6116db565b6000821161113a5760405162461bcd60e51b81526004016106f590611a8a565b6000611145836105ba565b9050600081116111675760405162461bcd60e51b81526004016106f590611ac1565b818110156111ab5760405162461bcd60e51b815260206004820152601160248201527014db1a5c1c1859d948195e18d959591959607a1b60448201526064016106f5565b6040516370a0823160e01b815230600482015281907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611211573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123591906119a7565b10156112835760405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e74205553444320696e20636f6e747261637400000060448201526064016106f5565b6112b86001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333086611607565b6112ec6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836116ff565b600654604080518581526020810184905233917fe029f26dbcf8c42dd2f352c10214a7fc26773dc62482c6241334a0402ac09a8091016110f4565b61132f611538565b6001600160a01b03811661135957604051631e4fbdf760e01b8152600060048201526024016106f5565b611362816115b7565b50565b61136d611538565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614806113de57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316145b61141a5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016106f5565b6000811161143a5760405162461bcd60e51b81526004016106f590611a8a565b6040516370a0823160e01b815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa158015611480573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a491906119a7565b10156114e95760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b60448201526064016106f5565b6114fd6001600160a01b03831633836116ff565b816001600160a01b03167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d582604051610cc491815260200190565b6000546001600160a01b031633146108b45760405163118cdaa760e01b81523360048201526024016106f5565b61156d611735565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b03848116602483015283811660448301526064820183905261166e9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611758565b50505050565b61167c6116db565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861159a3390565b6002600154036116d457604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b60025460ff16156108b45760405163d93c066560e01b815260040160405180910390fd5b6040516001600160a01b0383811660248301526044820183905261173091859182169063a9059cbb9060640161163c565b505050565b60025460ff166108b457604051638dfc202b60e01b815260040160405180910390fd5b600080602060008451602086016000885af18061177b576040513d6000823e3d81fd5b50506000513d915081156117935780600114156117a0565b6001600160a01b0384163b155b1561166e57604051635274afe760e01b81526001600160a01b03851660048201526024016106f5565b6000815180845260005b818110156117ef576020818501810151868301820152016117d3565b506000602082860101526020601f19601f83011685010191505092915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561189057888303603f19018552815180518452878101511515888501528681015115158785015260609081015160809185018290529061187c818601836117c9565b968901969450505090860190600101611836565b509098975050505050505050565b6000602082840312156118b057600080fd5b5035919050565b6000806000606084860312156118cc57600080fd5b833580151581146118dc57600080fd5b95602085013595506040909401359392505050565b8481528315156020820152821515604082015260806060820152600061191a60808301846117c9565b9695505050505050565b80356001600160a01b038116811461193b57600080fd5b919050565b6000806040838503121561195357600080fd5b61195c83611924565b946020939093013593505050565b6000806040838503121561197d57600080fd5b50508035926020909101359150565b60006020828403121561199e57600080fd5b61071e82611924565b6000602082840312156119b957600080fd5b5051919050565b600181811c908216806119d457607f821691505b6020821081036119f457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417611a3557634e487b7160e01b600052601160045260246000fd5b92915050565b600082611a5857634e487b7160e01b600052601260045260246000fd5b500490565b602080825260139082015272092dcecc2d8d2c840e0d0c2e6ca40d2dcc8caf606b1b604082015260600190565b6020808252601d908201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604082015260600190565b60208082526022908201527f5553444320616d6f756e74206d7573742062652067726561746572207468616e604082015261020360f41b60608201526080019056fea2646970667358221220063e4102e8e1b2c07a4e3154fb8bb0071ea7a36707f73609b5ea4111f141907e64736f6c63430008140033c2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85cc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85bc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85d8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19c8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19d8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b000000000000000000000000517600323e5e2938207fa2e2e915b9d80e5b2b21000000000000000000000000a4879fed32ecbef99399e5cbc247e533421c4ec6
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101725760003560e01c8063715018a6116100de5780638de37e7f11610097578063d6febde811610071578063d6febde814610331578063d79875eb14610344578063f2fde38b14610357578063f3fef3a31461036a57600080fd5b80638de37e7f14610303578063ad4a154d1461030b578063c205d6dc1461031e57600080fd5b8063715018a6146102b3578063722c631f146102bb57806374d1a4a4146102c45780637b1837de146102d75780638456cb59146102ea5780638da5cb5b146102f257600080fd5b80633b3413f2116101305780633b3413f21461022f5780633f4ba83a146102565780634634ea7b1461025e57806358b9a996146102815780635c975abb146102945780636c77c1f3146102aa57600080fd5b8062113e081461017757806301c11d961461019957806311eac855146101b35780632d007541146101f25780632e5e2b3b14610207578063348cdd6b1461021a575b600080fd5b61017f61037d565b604080519283526020830191909152015b60405180910390f35b6101a564e8d4a5100081565b604051908152602001610190565b6101da7f000000000000000000000000a4879fed32ecbef99399e5cbc247e533421c4ec681565b6040516001600160a01b039091168152602001610190565b6101fa61049b565b604051610190919061180f565b6101a561021536600461189e565b6105ba565b61022d6102283660046118b7565b610725565b005b6101da7f000000000000000000000000517600323e5e2938207fa2e2e915b9d80e5b2b2181565b61022d6108a4565b61027161026c36600461189e565b6108b6565b60405161019094939291906118f1565b6101a561028f36600461189e565b610980565b60025460ff166040519015158152602001610190565b6101a560065481565b61022d610abe565b6101a560055481565b61022d6102d236600461189e565b610ad0565b61022d6102e5366004611940565b610b9f565b61022d610cd0565b6000546001600160a01b03166101da565b6101fa610ce0565b61022d61031936600461189e565b610df6565b61027161032c36600461189e565b610ecb565b61022d61033f36600461196a565b610edb565b61022d61035236600461196a565b61110a565b61022d61036536600461198c565b611327565b61022d610378366004611940565b611365565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000517600323e5e2938207fa2e2e915b9d80e5b2b2116906370a0823190602401602060405180830381865afa1580156103e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040a91906119a7565b6040516370a0823160e01b81523060048201529092507f000000000000000000000000a4879fed32ecbef99399e5cbc247e533421c4ec66001600160a01b0316906370a0823190602401602060405180830381865afa158015610471573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049591906119a7565b90509091565b60606003805480602002602001604051908101604052809291908181526020016000905b828210156105b1576000848152602090819020604080516080810182526003860290920180548352600181015460ff8082161515958501959095526101009004909316151590820152600282018054919291606084019190610520906119c0565b80601f016020809104026020016040519081016040528092919081815260200182805461054c906119c0565b80156105995780601f1061056e57610100808354040283529160200191610599565b820191906000526020600020905b81548152906001019060200180831161057c57829003601f168201915b505050505081525050815260200190600101906104bf565b50505050905090565b6000806004600654815481106105d2576105d26119fa565b600091825260209182902060408051608081018252600390930290910180548352600181015460ff808216151595850195909552610100900490931615159082015260028201805491929160608401919061062c906119c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610658906119c0565b80156106a55780601f1061067a576101008083540402835291602001916106a5565b820191906000526020600020905b81548152906001019060200180831161068857829003601f168201915b505050505081525050905080602001516106fe5760405162461bcd60e51b815260206004820152601560248201527453656c6c207068617365206e6f742061637469766560581b60448201526064015b60405180910390fd5b8051670de0b6b3a7640000906107149085611a10565b61071e9190611a3b565b9392505050565b61072d611538565b6000811161077d5760405162461bcd60e51b815260206004820152601c60248201527f5072696365206d7573742062652067726561746572207468616e20300000000060448201526064016106f5565b64e8d4a510008111156107ca5760405162461bcd60e51b815260206004820152601560248201527450726963652065786365656473206d6178696d756d60581b60448201526064016106f5565b821561081b5760035482106107f15760405162461bcd60e51b81526004016106f590611a5d565b8060038381548110610805576108056119fa565b6000918252602090912060039091020155610862565b600454821061083c5760405162461bcd60e51b81526004016106f590611a5d565b8060048381548110610850576108506119fa565b60009182526020909120600390910201555b818315157f1c8f6d94f4fe1f18a92ced0503f4f49f4eb87c32a28f5cc2d32f01239e305bb48360405161089791815260200190565b60405180910390a3505050565b6108ac611538565b6108b4611565565b565b600381815481106108c657600080fd5b600091825260209091206003909102018054600182015460028301805492945060ff8083169461010090930416926108fd906119c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610929906119c0565b80156109765780601f1061094b57610100808354040283529160200191610976565b820191906000526020600020905b81548152906001019060200180831161095957829003601f168201915b5050505050905084565b600080600360055481548110610998576109986119fa565b600091825260209182902060408051608081018252600390930290910180548352600181015460ff80821615159585019590955261010090049093161515908201526002820180549192916060840191906109f2906119c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610a1e906119c0565b8015610a6b5780601f10610a4057610100808354040283529160200191610a6b565b820191906000526020600020905b815481529060010190602001808311610a4e57829003601f168201915b505050505081525050905080602001516106fe5760405162461bcd60e51b8152602060048201526014602482015273427579207068617365206e6f742061637469766560601b60448201526064016106f5565b610ac6611538565b6108b460006115b7565b610ad8611538565b6004548110610af95760405162461bcd60e51b81526004016106f590611a5d565b6000600460065481548110610b1057610b106119fa565b600091825260209091206003909102016001908101805460ff19169215159290921790915560068290556004805483908110610b4e57610b4e6119fa565b60009182526020822060039190910201600101805460ff1916921515929092179091556040518291907f2556b22513064d557ca3c72657a7683d576284f8424e1b42e1e9fbc6353bd184908290a350565b610ba7611538565b7f000000000000000000000000517600323e5e2938207fa2e2e915b9d80e5b2b216001600160a01b0316826001600160a01b03161480610c1857507f000000000000000000000000a4879fed32ecbef99399e5cbc247e533421c4ec66001600160a01b0316826001600160a01b0316145b610c545760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016106f5565b60008111610c745760405162461bcd60e51b81526004016106f590611a8a565b610c896001600160a01b038316333084611607565b816001600160a01b03167f5af8184bef8e4b45eb9f6ed7734d04da38ced226495548f46e0c8ff8d7d9a52482604051610cc491815260200190565b60405180910390a25050565b610cd8611538565b6108b4611674565b60606004805480602002602001604051908101604052809291908181526020016000905b828210156105b1576000848152602090819020604080516080810182526003860290920180548352600181015460ff8082161515958501959095526101009004909316151590820152600282018054919291606084019190610d65906119c0565b80601f0160208091040260200160405190810160405280929190818152602001828054610d91906119c0565b8015610dde5780601f10610db357610100808354040283529160200191610dde565b820191906000526020600020905b815481529060010190602001808311610dc157829003601f168201915b50505050508152505081526020019060010190610d04565b610dfe611538565b6003548110610e1f5760405162461bcd60e51b81526004016106f590611a5d565b6000600360055481548110610e3657610e366119fa565b906000526020600020906003020160010160006101000a81548160ff02191690831515021790555080600581905550600160038281548110610e7a57610e7a6119fa565b60009182526020822060016003909202018101805493151560ff19909416939093179092556040518392917f2556b22513064d557ca3c72657a7683d576284f8424e1b42e1e9fbc6353bd18491a350565b600481815481106108c657600080fd5b610ee36116b1565b610eeb6116db565b60008211610f0b5760405162461bcd60e51b81526004016106f590611a8a565b6000610f1683610980565b905060008111610f385760405162461bcd60e51b81526004016106f590611ac1565b81811115610f7c5760405162461bcd60e51b815260206004820152601160248201527014db1a5c1c1859d948195e18d959591959607a1b60448201526064016106f5565b6040516370a0823160e01b815230600482015283907f000000000000000000000000517600323e5e2938207fa2e2e915b9d80e5b2b216001600160a01b0316906370a0823190602401602060405180830381865afa158015610fe2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100691906119a7565b10156110545760405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e74204d43475020696e20636f6e747261637400000060448201526064016106f5565b6110896001600160a01b037f000000000000000000000000a4879fed32ecbef99399e5cbc247e533421c4ec616333084611607565b6110bd6001600160a01b037f000000000000000000000000517600323e5e2938207fa2e2e915b9d80e5b2b211633856116ff565b600554604080518581526020810184905233917fedba86fd2b22962d534e70ad9b0ff8730de46f636146f2bab6a72cbb1ebbcc5391015b60405180910390a35061110660018055565b5050565b6111126116b1565b61111a6116db565b6000821161113a5760405162461bcd60e51b81526004016106f590611a8a565b6000611145836105ba565b9050600081116111675760405162461bcd60e51b81526004016106f590611ac1565b818110156111ab5760405162461bcd60e51b815260206004820152601160248201527014db1a5c1c1859d948195e18d959591959607a1b60448201526064016106f5565b6040516370a0823160e01b815230600482015281907f000000000000000000000000a4879fed32ecbef99399e5cbc247e533421c4ec66001600160a01b0316906370a0823190602401602060405180830381865afa158015611211573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123591906119a7565b10156112835760405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e74205553444320696e20636f6e747261637400000060448201526064016106f5565b6112b86001600160a01b037f000000000000000000000000517600323e5e2938207fa2e2e915b9d80e5b2b2116333086611607565b6112ec6001600160a01b037f000000000000000000000000a4879fed32ecbef99399e5cbc247e533421c4ec61633836116ff565b600654604080518581526020810184905233917fe029f26dbcf8c42dd2f352c10214a7fc26773dc62482c6241334a0402ac09a8091016110f4565b61132f611538565b6001600160a01b03811661135957604051631e4fbdf760e01b8152600060048201526024016106f5565b611362816115b7565b50565b61136d611538565b7f000000000000000000000000517600323e5e2938207fa2e2e915b9d80e5b2b216001600160a01b0316826001600160a01b031614806113de57507f000000000000000000000000a4879fed32ecbef99399e5cbc247e533421c4ec66001600160a01b0316826001600160a01b0316145b61141a5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016106f5565b6000811161143a5760405162461bcd60e51b81526004016106f590611a8a565b6040516370a0823160e01b815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa158015611480573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a491906119a7565b10156114e95760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b60448201526064016106f5565b6114fd6001600160a01b03831633836116ff565b816001600160a01b03167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d582604051610cc491815260200190565b6000546001600160a01b031633146108b45760405163118cdaa760e01b81523360048201526024016106f5565b61156d611735565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b03848116602483015283811660448301526064820183905261166e9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611758565b50505050565b61167c6116db565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861159a3390565b6002600154036116d457604051633ee5aeb560e01b815260040160405180910390fd5b6002600155565b60025460ff16156108b45760405163d93c066560e01b815260040160405180910390fd5b6040516001600160a01b0383811660248301526044820183905261173091859182169063a9059cbb9060640161163c565b505050565b60025460ff166108b457604051638dfc202b60e01b815260040160405180910390fd5b600080602060008451602086016000885af18061177b576040513d6000823e3d81fd5b50506000513d915081156117935780600114156117a0565b6001600160a01b0384163b155b1561166e57604051635274afe760e01b81526001600160a01b03851660048201526024016106f5565b6000815180845260005b818110156117ef576020818501810151868301820152016117d3565b506000602082860101526020601f19601f83011685010191505092915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561189057888303603f19018552815180518452878101511515888501528681015115158785015260609081015160809185018290529061187c818601836117c9565b968901969450505090860190600101611836565b509098975050505050505050565b6000602082840312156118b057600080fd5b5035919050565b6000806000606084860312156118cc57600080fd5b833580151581146118dc57600080fd5b95602085013595506040909401359392505050565b8481528315156020820152821515604082015260806060820152600061191a60808301846117c9565b9695505050505050565b80356001600160a01b038116811461193b57600080fd5b919050565b6000806040838503121561195357600080fd5b61195c83611924565b946020939093013593505050565b6000806040838503121561197d57600080fd5b50508035926020909101359150565b60006020828403121561199e57600080fd5b61071e82611924565b6000602082840312156119b957600080fd5b5051919050565b600181811c908216806119d457607f821691505b6020821081036119f457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417611a3557634e487b7160e01b600052601160045260246000fd5b92915050565b600082611a5857634e487b7160e01b600052601260045260246000fd5b500490565b602080825260139082015272092dcecc2d8d2c840e0d0c2e6ca40d2dcc8caf606b1b604082015260600190565b6020808252601d908201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604082015260600190565b60208082526022908201527f5553444320616d6f756e74206d7573742062652067726561746572207468616e604082015261020360f41b60608201526080019056fea2646970667358221220063e4102e8e1b2c07a4e3154fb8bb0071ea7a36707f73609b5ea4111f141907e64736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000517600323e5e2938207fa2e2e915b9d80e5b2b21000000000000000000000000a4879fed32ecbef99399e5cbc247e533421c4ec6
-----Decoded View---------------
Arg [0] : _mcgpToken (address): 0x517600323e5E2938207fA2e2e915B9D80e5B2b21
Arg [1] : _usdcToken (address): 0xA4879Fed32Ecbef99399e5cbC247E533421C4eC6
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000517600323e5e2938207fa2e2e915b9d80e5b2b21
Arg [1] : 000000000000000000000000a4879fed32ecbef99399e5cbc247e533421c4ec6
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.