Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 37 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Transfer Remaini... | 15730930 | 1260 days ago | IN | 0 ETH | 0.00076998 | ||||
| End Sale | 15730905 | 1260 days ago | IN | 0 ETH | 0.00066513 | ||||
| Buy Tokens | 15475718 | 1297 days ago | IN | 0.012 ETH | 0.0007892 | ||||
| Buy Tokens | 15396364 | 1310 days ago | IN | 0.00497701 ETH | 0.00120532 | ||||
| Buy Tokens | 15385300 | 1312 days ago | IN | 0.0365 ETH | 0.00108089 | ||||
| Buy Tokens | 15366877 | 1315 days ago | IN | 0.04927425 ETH | 0.00164088 | ||||
| Buy Tokens | 15366872 | 1315 days ago | IN | 0.03856246 ETH | 0.00194897 | ||||
| Buy Tokens | 15248308 | 1333 days ago | IN | 0.025 ETH | 0.00080173 | ||||
| Buy Tokens | 15184543 | 1343 days ago | IN | 0.01 ETH | 0.00126425 | ||||
| Buy Tokens | 15179959 | 1344 days ago | IN | 0.02891954 ETH | 0.00414126 | ||||
| Buy Tokens | 15169205 | 1346 days ago | IN | 0.01 ETH | 0.0030418 | ||||
| Buy Tokens | 15165560 | 1346 days ago | IN | 0.05 ETH | 0.00462529 | ||||
| Buy Tokens | 15150773 | 1348 days ago | IN | 0.01 ETH | 0.00151676 | ||||
| Buy Tokens | 15150560 | 1348 days ago | IN | 0.01 ETH | 0.00219723 | ||||
| Buy Tokens | 15148777 | 1349 days ago | IN | 0.05 ETH | 0.00462994 | ||||
| Buy Tokens | 15110642 | 1355 days ago | IN | 0.08211434 ETH | 0.00318062 | ||||
| Buy Tokens | 15110535 | 1355 days ago | IN | 0.03284573 ETH | 0.00460904 | ||||
| Buy Tokens | 15110531 | 1355 days ago | IN | 0.03284573 ETH | 0.00483431 | ||||
| Buy Tokens | 15106505 | 1355 days ago | IN | 0.00559155 ETH | 0.00176831 | ||||
| Buy Tokens | 15102361 | 1356 days ago | IN | 0.075 ETH | 0.00617472 | ||||
| Buy Tokens | 15102123 | 1356 days ago | IN | 0.912 ETH | 0.00501846 | ||||
| Buy Tokens | 15101723 | 1356 days ago | IN | 0.05571391 ETH | 0.00218234 | ||||
| Buy Tokens | 15099591 | 1356 days ago | IN | 0.02 ETH | 0.00291042 | ||||
| Buy Tokens | 15099567 | 1356 days ago | IN | 0.03200025 ETH | 0.00240261 | ||||
| Buy Tokens | 15098123 | 1357 days ago | IN | 0.0813094 ETH | 0.01123248 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Transfer | 15475718 | 1297 days ago | 0.012 ETH | ||||
| Transfer | 15396364 | 1310 days ago | 0.00497701 ETH | ||||
| Transfer | 15385300 | 1312 days ago | 0.0365 ETH | ||||
| Transfer | 15366877 | 1315 days ago | 0.04927425 ETH | ||||
| Transfer | 15366872 | 1315 days ago | 0.03856246 ETH | ||||
| Transfer | 15248308 | 1333 days ago | 0.025 ETH | ||||
| Transfer | 15184543 | 1343 days ago | 0.01 ETH | ||||
| Transfer | 15179959 | 1344 days ago | 0.02891954 ETH | ||||
| Transfer | 15169205 | 1346 days ago | 0.01 ETH | ||||
| Transfer | 15165560 | 1346 days ago | 0.05 ETH | ||||
| Transfer | 15150773 | 1348 days ago | 0.01 ETH | ||||
| Transfer | 15150560 | 1348 days ago | 0.01 ETH | ||||
| Transfer | 15148777 | 1349 days ago | 0.05 ETH | ||||
| Transfer | 15110642 | 1355 days ago | 0.08211434 ETH | ||||
| Transfer | 15110535 | 1355 days ago | 0.03284573 ETH | ||||
| Transfer | 15110531 | 1355 days ago | 0.03284573 ETH | ||||
| Transfer | 15106505 | 1355 days ago | 0.00559155 ETH | ||||
| Transfer | 15102361 | 1356 days ago | 0.075 ETH | ||||
| Transfer | 15102123 | 1356 days ago | 0.912 ETH | ||||
| Transfer | 15101723 | 1356 days ago | 0.05571391 ETH | ||||
| Transfer | 15099591 | 1356 days ago | 0.02 ETH | ||||
| Transfer | 15099567 | 1356 days ago | 0.03200025 ETH | ||||
| Transfer | 15098123 | 1357 days ago | 0.0813094 ETH | ||||
| Transfer | 15097798 | 1357 days ago | 0.29015305 ETH | ||||
| Transfer | 15097790 | 1357 days ago | 4.19109974 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AcademySale
Compiler Version
v0.8.7+commit.e28d00a7
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./TokenSaleContract.sol";
// creates a Token Sale called Pre-Sale and initalizes the variables
contract AcademySale is TokenSaleContract {
constructor(
uint256 _startUnixTime,
uint256 _saleAmount,
address _gpo,
address payable _fundWallet,
address _ethUsdAggregator
)
TokenSaleContract("AcademySale", _startUnixTime, _saleAmount, _gpo, _fundWallet, 40, _ethUsdAggregator)
{
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title Helps contracts guard against reentrancy attacks.
* @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io>
* @dev If you mark a function `nonReentrant`, you should also
* mark it `external`.
*/
contract ReentrancyGuard {
/// @dev counter to allow mutex lock with only one SSTORE operation
uint256 private _guardCounter;
constructor() {
// The counter starts at one to prevent changing it from zero to a non-zero
// value, which is a more expensive operation.
_guardCounter = 1;
}
/**
* @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 make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_guardCounter += 1;
uint256 localCounter = _guardCounter;
_;
require(localCounter == _guardCounter);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "../GPO.sol";
import "../utils/NonReentrancy.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract TokenSaleContract is ReentrancyGuard, Ownable {
// Chainlink Aggregator used to retrieve the live Ethereum price
AggregatorV3Interface internal priceFeed;
// Name of the Token Sale
string public saleName;
// Start time of the Token Sale (Unix Time)
uint256 public startUnixTime;
// Total Amount of Tokens for Sale
uint256 public saleAmount;
// Total Sale Amount
uint256 public amountSold;
// GPO Contract
GPO public gpo;
// Wallet address where sale funds are transferred to
address payable private fundWallet;
// Price per token in USD Cents
uint256 public priceInUSDCents;
// State of the Sale
bool public saleEnded;
// Event is emitted anytime tokens are purchased
event TokensPurchased(
address indexed purchaser,
uint256 value,
uint256 amount,
uint256 timestamp
);
// Sale has started and has not ended
modifier duringSale() {
require(block.timestamp >= startUnixTime && !saleEnded, "Not during sale");
_;
}
// Sale has ended
modifier afterSale() {
require(saleEnded);
_;
}
// Sale has not started
modifier beforeSale() {
require(block.timestamp <= startUnixTime);
_;
}
// Constructor is only executed once when the contract is deployed and initalizes the state variables for the specific sale
constructor(
string memory _saleName,
uint256 _startUnixTime,
uint256 _saleAmount,
address _gpo,
address payable _fundWallet,
uint256 _priceInUSDCents,
address _ethUsdAggregator
) {
saleName = _saleName;
startUnixTime = _startUnixTime;
saleAmount = _saleAmount * 10**18;
gpo = GPO(_gpo);
priceInUSDCents = _priceInUSDCents;
priceFeed = AggregatorV3Interface(_ethUsdAggregator);
amountSold = 0;
fundWallet = _fundWallet;
saleEnded = false;
}
// fetches the price of each token in Ethereum at the moment of the purchase
function getSalePriceInETH() public view returns (uint256) {
(,int256 price,,,) = priceFeed.latestRoundData();
return (priceInUSDCents * 10**24) / uint256(price);
}
// Amount of GPO per Ethereum
function tentativeAmountGPOPerETH(uint256 amount) public view returns (uint256) {
return (amount * 10**18) / getSalePriceInETH();
}
// Executes the buy order as long as there are enough tokens left for sale and the user requesting to purchase tokens will not breach the wallet hard cap of 100,000
// Once the tokens are successful purchased and transferred to the user, their wallet is locked.
function buyTokens() public payable nonReentrant duringSale {
require(_msgSender() != address(0), "No address 0");
require(msg.value > 0, "Msg value = 0");
uint256 tentativeAmountGPO = tentativeAmountGPOPerETH(msg.value);
require(gpo.balanceOf(address(this)) >= tentativeAmountGPO, "Do not have enough GPO");
gpo.transfer(_msgSender(), tentativeAmountGPO);
gpo.lockUnlockWallet(_msgSender(), true, tentativeAmountGPO);
amountSold = amountSold + tentativeAmountGPO;
emit TokensPurchased(_msgSender(), msg.value, tentativeAmountGPO, block.timestamp);
transferFunds();
}
// After the Sale is finished the remaining GPO tokens are transferred back to the GPO contract address
function transferRemainingTokens() public afterSale onlyOwner {
require(amountSold != saleAmount);
gpo.transfer(address(gpo), gpo.balanceOf(address(this)));
}
// Sets the wallet address that recieves the sale proceeds of the token sale
function setFundWallet(address payable _fundWallet) public onlyOwner {
fundWallet = _fundWallet;
}
// Transfer the sale proceeds to the "FundWallet"
function transferFunds() internal {
fundWallet.transfer(address(this).balance);
}
// Enables GoldPesa to end the sale early
function endSale() public duringSale onlyOwner {
saleEnded = true;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
/**
____________________________
Description:
GoldPesa Option Contract (GPO) - 1 GPO represents the option to purchase 1 GPX at spot gold price + 1 %.
__________________________________
*/
contract GPO is ERC20PresetFixedSupply, Pausable, Ownable, AccessControl {
// TokenSwaped event is emitted anytime there is a swap between GPO and USDC on the GoldPesa.com decentralized exchange powered by Uniswap
event TokensSwaped(
address indexed purchaser,
uint256 amountIn,
uint256 amountOut,
bool direction // false: GPO-X, true: X-GPO
);
event ReserveTokenTransfer(
address indexed to,
uint256 amount
);
event WalletWhitelistChanged(
address indexed wallet,
bool whitelist
);
event PoolParametersChanged(
address token,
uint24 poolFee
);
event FreeTradeChanged(
bool freeTrade
);
event SwapPermChanged(
bool swapPerm
);
event FeeSplitsChanged(
uint256 length,
FeeSplit[] feeSplitsArray
);
event WalletLockChanged(
address indexed wallet,
uint256 lockValue
);
// FeeSplit stores the "recipient" wallet address and the respective percentage of the feeOnSwap which are to be sent to it.
struct FeeSplit {
address recipient;
uint16 fee;
}
// Token Name
string public constant _name = "GoldPesa Option";
// Token Symbol
string public constant _symbol = "GPO";
// GPO Hard Cap
uint256 public constant fixedSupply = 100_000_000;
// Wallet Hard Cap
uint256 public constant capOnWallet = 100_000;
// GoldPesa fee on swap percentage
uint256 public feeOnSwap = 10;
// Uniswap Router Address
ISwapRouter public immutable swapRouter;
// USDC ERC20 token Address
address public addrUSDC;
// Uniswap V3 Pool Fee * 10000 = 1 %
uint24 private swapPoolFee = 10000;
// Uniswap V3 GPO/USDC liquidity pool address
address public authorizedPool;
// Time when Pre-Sale and Sale tokens will be unlocked (Unix Time)
uint256 public walletsTimelockedUntil;
// When freeTrade is true the token bypasses the hard cap on wallet and can be traded freely on any exchange
bool public freeTrade = false;
// The feeOnSwap percentage is distributed to the addresses and their respective percentage which are held in the feeSplits array
FeeSplit[] public feeSplits;
// Keeps a record of the number of addresses in the feeSplits array
uint256 public feeSplitsLength;
// Defines an Access Control role called "CAN_LOCK" which is granted to addresses which are allowed to lock wallet addresses during the Sale and Pre-Sale phase
bytes32 public constant AUTHORIZED_LOCK =
keccak256("CAN_LOCK");
modifier authorizedLocker() {
require(hasRole(AUTHORIZED_LOCK, _msgSender()));
_;
}
// Mapping which holds information of the wallet addresses which are locked (true) /unlocked (false)
mapping(address => bool) public lockedWallets;
// Mapping which holds details of the wallet addresses which bypass the wallet hard cap and are able to swap with the Uniswap GPO/USDC liquidity pool
mapping(address => bool) public whitelistedWallets;
// Mapping which holds details of the amount of GPO tokens are locked in the lockedWallets mapping
mapping(address => uint256) public lockedWalletsAmount;
bool public swapEnabled = false;
// Upon deployment, the constructor is only executed once
constructor(
ISwapRouter _swapRouter,
uint256 _walletsTimelockedUntil
) ERC20PresetFixedSupply(_name, _symbol, hardCapOnToken(), address(this)) {
swapRouter = _swapRouter;
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
walletsTimelockedUntil = _walletsTimelockedUntil;
whitelistedWallets[address(0x0)] = true;
whitelistedWallets[address(this)] = true;
}
// Enables GoldPesa to manually transfer GPO tokens from the GPO contract to another wallet address
function transferTokensTo(address _to, uint256 amount) external onlyOwner {
_transfer(address(this), _to, amount);
emit ReserveTokenTransfer(_to, amount);
}
// Enables GoldPesa to manually add or remove wallet addresses from the whitelistedWallets mapping
function changeWalletWhitelist(address _addr, bool yesOrNo) external onlyOwner {
whitelistedWallets[_addr] = yesOrNo;
emit WalletWhitelistChanged(_addr, yesOrNo);
}
// Sets the USDC contract address, the Uniswap pool fee and accordingly includes the derived Uniswap liquidity pool address to the whitelistedWallets mapping
function setPoolParameters(address USDC, uint24 poolFee) external onlyOwner {
require(USDC != address(0x0));
addrUSDC = USDC;
swapPoolFee = poolFee;
whitelistedWallets[authorizedPool] = false;
// taken from @uniswap/v3-periphery/contracts/libraries/PoolAddress.sol
address token0 = address(this);
address token1 = USDC;
if (token0 > token1) (token0, token1) = (token1, token0);
authorizedPool = address(
uint160(
uint256(
keccak256(
abi.encodePacked(
hex'ff',
0x1F98431c8aD98523631AE4a59f267346ea31F984,
keccak256(abi.encode(token0, token1, poolFee)),
bytes32(0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54)
)
)
)
)
);
whitelistedWallets[authorizedPool] = true;
emit PoolParametersChanged(USDC, poolFee);
}
// Enables GoldPesa to set the state of the contract to "freeTrade"
function switchFreeTrade() external onlyOwner {
freeTrade = !freeTrade;
}
function switchSwapEnabled() external onlyOwner {
swapEnabled = !swapEnabled;
}
// Enables GoldPesa to set the feeOnSwap
function setFeeOnSwap(uint24 _feeOnSwap) external onlyOwner {
feeOnSwap = _feeOnSwap;
}
// Enables GoldPesa to set the "feeOnSwap" distribution details
// Only GoldPesa executes this
function setFeeSplits(FeeSplit[] memory _feeSplits) external onlyOwner {
uint256 grandTotal = 0;
for (uint256 i = 0; i < _feeSplits.length; i++) {
FeeSplit memory f = _feeSplits[i];
grandTotal += f.fee;
}
require(grandTotal == 100);
delete feeSplits;
for (uint256 i = 0; i < _feeSplits.length; i++) {
feeSplits.push(_feeSplits[i]);
}
feeSplitsLength = _feeSplits.length;
emit FeeSplitsChanged(feeSplitsLength, feeSplits);
}
// Distributes the feeOnSwap amount collected during any swap transaction to the addresses defined in the "feeSplits" array
function distributeFee(uint256 amount) internal {
uint256 grandTotal = 0;
for (uint256 i = 0; i < feeSplits.length; i++) {
FeeSplit storage f = feeSplits[i];
uint256 distributeAmount = amount * f.fee / 100;
TransferHelper.safeTransfer(addrUSDC, f.recipient, distributeAmount);
grandTotal += distributeAmount;
}
if (grandTotal != amount && feeSplits.length > 0) {
FeeSplit storage f = feeSplits[0];
TransferHelper.safeTransfer(addrUSDC, f.recipient, amount - grandTotal);
}
}
// Defines the rules that must be satisfied before GPO can be transferred
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual override {
super._beforeTokenTransfer(from, to, amount);
// Ensures that GPO token holders cannot burn their own tokens, unless rhzy ez <hirzliqrzs
require(to != address(0x0) || whitelistedWallets[from], "GPO_ERR: Cannot burn");
// Ensures that GPO token holders cannot execute a swap directly with the GPO/USDC liquidity pool on Uniswap. All swaps must be executed on the GoldPesa DEX unless
// "freeTrade" has be enabled
if (authorizedPool != address(0x0) && (from == authorizedPool || to == authorizedPool))
require(freeTrade || (whitelistedWallets[to] && whitelistedWallets[from]), "GPO_ERR: UniswapV3 functionality is only allowed through GPO's protocol");
// Unless "freeTrade" has been enabled this require statement rejects any transfers to wallets which will break the 100,000 GPO wallet hard cap unless the
// receiving wallet address is a "whitelistedWallet"
require(
freeTrade ||
from == address(0x0) ||
whitelistedWallets[to] ||
balanceOf(to) + amount <= hardCapOnWallet(),
"GPO_ERR: Hard cap on wallet reached"
);
// Disables all GPO transfers if the token has been paused by GoldPesa
require(!paused(), "ERC20Pausable: token transfer while paused");
// Rejects transfers made from locked wallets which are greater than the wallet's "lockedWalletsAmount" until the date where all tokens are unlocked
require(block.timestamp >= walletsTimelockedUntil ||
!lockedWallets[from] ||
(lockedWallets[from] && amount <= (balanceOf(from) - lockedWalletsAmount[from])), "Cannot transfer token as the wallet is locked");
}
// Internal mint function which cannot be called externally after the GPO contract is deployed ensuring that the GPO token hard cap of 100,000,000 is not breached
function _mint(address account, uint256 amount) internal virtual override {
// Ensures that GPO token hard cap of 100,000,000 is not breached even if the mint function is called internally
require(
ERC20.totalSupply() + amount <= hardCapOnToken(),
"ERC20Capped: cap exceeded"
);
super._mint(account, amount);
}
// Returns the GPO token hard cap ("fixedSupply") in wei
function hardCapOnToken() public view returns (uint256) {
return fixedSupply * (10**(uint256(decimals())));
}
// Returns the GPO token wallet hard cap ("capOnWallet") in wei
function hardCapOnWallet() public view returns (uint256) {
return capOnWallet * (10**(uint256(decimals())));
}
// Returns the GoldPesa feeOnSwap in USDC which is used in the swap functions
function calculateFeeOnSwap(uint256 amount)
internal
view
returns (uint256)
{
return amount * feeOnSwap / 100;
}
// Enables GoldPesa to lock and unlock wallet address manually
function lockUnlockWallet(address account, bool yesOrNo, uint256 amount) external authorizedLocker {
lockedWallets[account] = yesOrNo;
if (yesOrNo) {
uint256 lockedValue = lockedWalletsAmount[account] + amount;
require(lockedValue <= balanceOf(account), "Cannot lock more than what the wallet has");
lockedWalletsAmount[account] = lockedValue;
emit WalletLockChanged(account, lockedValue);
} else {
lockedWalletsAmount[account] = 0;
emit WalletLockChanged(account, 0);
}
}
// Pause the GPO token transfers
function pause() external onlyOwner {
_pause();
}
// Unpause the GPO token transfer
function unpause() external onlyOwner {
_unpause();
}
// User defines the exact amount of USDC they would like to receive while swaping GPO for USDC using the GPO/USDC Uniswap V3 liquidity pool.
// Any extra GPO tokens not used in the Swap are returned back to the user.
function swapToExactOutput(uint256 amountInMaximum, uint256 amountOut, uint256 deadline) external returns (uint256 amountIn) {
require(amountInMaximum > 0 && amountOut > 0);
require(swapEnabled || whitelistedWallets[_msgSender()]);
_transfer(_msgSender(), address(this), amountInMaximum);
_approve(address(this), address(swapRouter), amountInMaximum);
if (deadline == 0)
deadline = block.timestamp + 30*60;
ISwapRouter.ExactOutputSingleParams memory params =
ISwapRouter.ExactOutputSingleParams({
tokenIn: address(this),
tokenOut: addrUSDC,
fee: swapPoolFee,
recipient: address(this),
deadline: deadline,
amountOut: amountOut,
amountInMaximum: amountInMaximum,
sqrtPriceLimitX96: 0
});
amountIn = swapRouter.exactOutputSingle(params);
uint256 fee = calculateFeeOnSwap(amountOut);
uint256 amountSwap = amountOut - fee;
TransferHelper.safeTransfer(addrUSDC, _msgSender(), amountSwap);
distributeFee(fee);
if (amountIn < amountInMaximum) {
_transfer(address(this), _msgSender(), amountInMaximum - amountIn);
}
emit TokensSwaped(_msgSender(), amountIn, amountOut, false);
}
// User defines the exact amount of GPO they would like to spend while swaping GPO for USDC using the GPO/USDC Uniswap V3 liquidity pool.
function swapToExactInput(uint256 amountIn, uint256 amountOutMinimum, uint256 deadline ) external returns (uint256 amountOut) {
require(amountIn > 0);
require(swapEnabled || whitelistedWallets[_msgSender()]);
_transfer(_msgSender(), address(this), amountIn);
_approve(address(this), address(swapRouter), amountIn);
if (deadline == 0)
deadline = block.timestamp + 30*60;
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
.ExactInputSingleParams({
tokenIn: address(this),
tokenOut: addrUSDC,
fee: swapPoolFee,
recipient: address(this),
deadline: deadline,
amountIn: amountIn,
amountOutMinimum: amountOutMinimum,
sqrtPriceLimitX96: 0
});
amountOut = swapRouter.exactInputSingle(params);
uint256 fee = calculateFeeOnSwap(amountOut);
uint256 amountSwap = amountOut - fee;
TransferHelper.safeTransfer(addrUSDC, _msgSender(), amountSwap);
distributeFee(fee);
emit TokensSwaped(_msgSender(), amountIn, amountOut, false);
return amountSwap;
}
// User defines the exact amount of GPO they would like to receive while swaping USDC for GPO using the GPO/USDC Uniswap V3 liquidity pool.
// Any extra USDC tokens not used in the Swap are returned back to the user.
function swapFromExactOutput(uint256 amountInMaximum, uint256 amountOut, uint256 deadline) external returns (uint256 amountIn) {
require(swapEnabled || whitelistedWallets[_msgSender()]);
require(amountInMaximum > 0 && amountOut > 0);
TransferHelper.safeTransferFrom(addrUSDC, _msgSender(), address(this), amountInMaximum);
uint256 fee = calculateFeeOnSwap(amountInMaximum);
uint256 amountSwap = amountInMaximum - fee;
distributeFee(fee);
if (deadline == 0)
deadline = block.timestamp + 30*60;
TransferHelper.safeApprove(addrUSDC, address(swapRouter), amountSwap);
ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({
tokenIn: addrUSDC,
tokenOut: address(this),
fee: swapPoolFee,
recipient: address(this),
deadline: deadline,
amountOut: amountOut,
amountInMaximum: amountSwap,
sqrtPriceLimitX96: 0
});
amountIn = swapRouter.exactOutputSingle(params);
_transfer(address(this), _msgSender(), amountOut);
if (amountIn < amountSwap) {
TransferHelper.safeTransfer(addrUSDC, _msgSender(), amountSwap - amountIn);
}
emit TokensSwaped(_msgSender(), amountIn, amountOut, true);
}
// User defines the exact amount of USDC they would like to spend while swaping USDC for GPO using the GPO/USDC Uniswap V3 liquidity pool.
function swapFromExactInput(uint256 amountIn, uint256 amountOutMinimum, uint256 deadline) external returns (uint256 amountOut) {
require(swapEnabled || whitelistedWallets[_msgSender()]);
require(amountIn > 0 && amountOutMinimum > 0);
uint256 fee = calculateFeeOnSwap(amountIn);
TransferHelper.safeTransferFrom(addrUSDC, _msgSender(), address(this), amountIn);
uint256 amountSwap = amountIn - fee;
distributeFee(fee);
TransferHelper.safeApprove(addrUSDC, address(swapRouter), amountSwap);
if (deadline == 0)
deadline = block.timestamp + 30*60;
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
.ExactInputSingleParams({
tokenIn: addrUSDC,
tokenOut: address(this),
fee: swapPoolFee,
recipient: address(this),
deadline: deadline,
amountIn: amountSwap,
amountOutMinimum: amountOutMinimum,
sqrtPriceLimitX96: 0
});
amountOut = swapRouter.exactInputSingle(params);
_transfer(address(this), _msgSender(), amountOut);
emit TokensSwaped(_msgSender(), amountIn, amountOut, true);
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.0;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
library TransferHelper {
/// @notice Transfers tokens from the targeted address to the given destination
/// @notice Errors with 'STF' if transfer fails
/// @param token The contract address of the token to be transferred
/// @param from The originating address from which the tokens will be transferred
/// @param to The destination address of the transfer
/// @param value The amount to be transferred
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
}
/// @notice Transfers tokens from msg.sender to a recipient
/// @dev Errors with ST if transfer fails
/// @param token The contract address of the token which will be transferred
/// @param to The recipient of the transfer
/// @param value The value of the transfer
function safeTransfer(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
}
/// @notice Approves the stipulated contract to spend the given allowance in the given token
/// @dev Errors with 'SA' if transfer fails
/// @param token The contract address of the token to be approved
/// @param to The target of the approval
/// @param value The amount of the given token the target will be allowed to spend
function safeApprove(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');
}
/// @notice Transfers ETH to the recipient address
/// @dev Fails with `STE`
/// @param to The destination of the transfer
/// @param value The value to be transferred
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'STE');
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Callback for IUniswapV3PoolActions#swap
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
interface IUniswapV3SwapCallback {
/// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
/// @dev In the implementation you must pay the pool tokens owed for the swap.
/// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
/// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
/// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
/// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
/// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* 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[EIP 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
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @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;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../extensions/ERC20Burnable.sol";
/**
* @dev {ERC20} token, including:
*
* - Preminted initial supply
* - Ability for holders to burn (destroy) their tokens
* - No access control mechanism (for minting/pausing) and hence no governance
*
* This contract uses {ERC20Burnable} to include burn capabilities - head to
* its documentation for details.
*
* _Available since v3.4._
*/
contract ERC20PresetFixedSupply is ERC20Burnable {
/**
* @dev Mints `initialSupply` amount of token and transfers them to `owner`.
*
* See {ERC20-constructor}.
*/
constructor(
string memory name,
string memory symbol,
uint256 initialSupply,
address owner
) ERC20(name, symbol) {
_mint(owner, initialSupply);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../ERC20.sol";
import "../../../utils/Context.sol";
/**
* @dev Extension of {ERC20} that allows token holders to destroy both their own
* tokens and those that they have an allowance for, in a way that can be
* recognized off-chain (via event analysis).
*/
abstract contract ERC20Burnable is Context, ERC20 {
/**
* @dev Destroys `amount` tokens from the caller.
*
* See {ERC20-_burn}.
*/
function burn(uint256 amount) public virtual {
_burn(_msgSender(), amount);
}
/**
* @dev Destroys `amount` tokens from `account`, deducting from the caller's
* allowance.
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller must have allowance for ``accounts``'s tokens of at least
* `amount`.
*/
function burnFrom(address account, uint256 amount) public virtual {
uint256 currentAllowance = allowance(account, _msgSender());
require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");
unchecked {
_approve(account, _msgSender(), currentAllowance - amount);
}
_burn(account, amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) 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 `amount` 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 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @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);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* Requirements:
*
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../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 {
/**
* @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);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @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
pragma solidity ^0.8.0;
import "../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.
*
* By default, the owner account will be the one that deploys the contract. 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;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_setOwner(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_setOwner(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 {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role, _msgSender());
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) private {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) private {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface AggregatorV3Interface {
function decimals()
external
view
returns (
uint8
);
function description()
external
view
returns (
string memory
);
function version()
external
view
returns (
uint256
);
// getRoundData and latestRoundData should both raise "No data present"
// if they do not have data to report, instead of returning unset values
// which could be misinterpreted as actual reported values.
function getRoundData(
uint80 _roundId
)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}{
"remappings": [],
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "london",
"libraries": {},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"_startUnixTime","type":"uint256"},{"internalType":"uint256","name":"_saleAmount","type":"uint256"},{"internalType":"address","name":"_gpo","type":"address"},{"internalType":"address payable","name":"_fundWallet","type":"address"},{"internalType":"address","name":"_ethUsdAggregator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"purchaser","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TokensPurchased","type":"event"},{"inputs":[],"name":"amountSold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"endSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getSalePriceInETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gpo","outputs":[{"internalType":"contract GPO","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceInUSDCents","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"saleAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"saleEnded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"saleName","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_fundWallet","type":"address"}],"name":"setFundWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startUnixTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"tentativeAmountGPOPerETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferRemainingTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b5060405162001041380380620010418339810160408190526200003491620001f7565b60408051808201909152600b81526a41636164656d7953616c6560a81b60208201526001600055858585856028866200006d33620000ff565b8651620000829060039060208a019062000151565b5060048690556200009c85670de0b6b3a76400006200025f565b600555600780546001600160a01b039586166001600160a01b031991821617909155600992909255600280549185169183169190911790556000600655600880549290931691161790555050600a805460ff1916905550620002e3945050505050565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8280546200015f906200028d565b90600052602060002090601f016020900481019282620001835760008555620001ce565b82601f106200019e57805160ff1916838001178555620001ce565b82800160010185558215620001ce579182015b82811115620001ce578251825591602001919060010190620001b1565b50620001dc929150620001e0565b5090565b5b80821115620001dc5760008155600101620001e1565b600080600080600060a086880312156200021057600080fd5b855194506020860151935060408601516200022b81620002ca565b60608701519093506200023e81620002ca565b60808701519092506200025181620002ca565b809150509295509295909350565b60008160001904831182151516156200028857634e487b7160e01b600052601160045260246000fd5b500290565b600181811c90821680620002a257607f821691505b60208210811415620002c457634e487b7160e01b600052602260045260246000fd5b50919050565b6001600160a01b0381168114620002e057600080fd5b50565b610d4e80620002f36000396000f3fe6080604052600436106100f35760003560e01c8063715018a61161008a5780639b8906ae116100595780639b8906ae1461025c578063d0febe4c14610286578063ed6c91811461028e578063f2fde38b146102a357600080fd5b8063715018a6146101f15780638aae995a146102065780638adf55651461021c5780638da5cb5b1461023e57600080fd5b8063380d831b116100c6578063380d831b1461018f57806352a16bb0146101a657806355ce3b9a146101bc57806363cc4aa2146101dc57600080fd5b80630122ffc0146100f85780631a1d0aca1461012157806321a653831461015957806329627abe1461016f575b600080fd5b34801561010457600080fd5b5061010e60045481565b6040519081526020015b60405180910390f35b34801561012d57600080fd5b50600754610141906001600160a01b031681565b6040516001600160a01b039091168152602001610118565b34801561016557600080fd5b5061010e60095481565b34801561017b57600080fd5b5061010e61018a366004610b4d565b6102c3565b34801561019b57600080fd5b506101a46102ef565b005b3480156101b257600080fd5b5061010e60065481565b3480156101c857600080fd5b506101a46101d7366004610b07565b610380565b3480156101e857600080fd5b506101a46103cc565b3480156101fd57600080fd5b506101a461051c565b34801561021257600080fd5b5061010e60055481565b34801561022857600080fd5b50610231610552565b6040516101189190610bcf565b34801561024a57600080fd5b506001546001600160a01b0316610141565b34801561026857600080fd5b50600a546102769060ff1681565b6040519015158152602001610118565b6101a46105e0565b34801561029a57600080fd5b5061010e610911565b3480156102af57600080fd5b506101a46102be366004610b07565b6109c9565b60006102cd610911565b6102df83670de0b6b3a7640000610c93565b6102e99190610c71565b92915050565b60045442101580156103045750600a5460ff16155b6103475760405162461bcd60e51b815260206004820152600f60248201526e4e6f7420647572696e672073616c6560881b60448201526064015b60405180910390fd5b6001546001600160a01b031633146103715760405162461bcd60e51b815260040161033e90610c24565b600a805460ff19166001179055565b6001546001600160a01b031633146103aa5760405162461bcd60e51b815260040161033e90610c24565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b600a5460ff166103db57600080fd5b6001546001600160a01b031633146104055760405162461bcd60e51b815260040161033e90610c24565b600554600654141561041657600080fd5b6007546040516370a0823160e01b81523060048201526001600160a01b039091169063a9059cbb90829081906370a082319060240160206040518083038186803b15801561046357600080fd5b505afa158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b9190610b66565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b1580156104e157600080fd5b505af11580156104f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105199190610b2b565b50565b6001546001600160a01b031633146105465760405162461bcd60e51b815260040161033e90610c24565b6105506000610a5d565b565b6003805461055f90610cb2565b80601f016020809104026020016040519081016040528092919081815260200182805461058b90610cb2565b80156105d85780601f106105ad576101008083540402835291602001916105d8565b820191906000526020600020905b8154815290600101906020018083116105bb57829003601f168201915b505050505081565b60016000808282546105f29190610c59565b9091555050600054600454421080159061060f5750600a5460ff16155b61064d5760405162461bcd60e51b815260206004820152600f60248201526e4e6f7420647572696e672073616c6560881b604482015260640161033e565b336106895760405162461bcd60e51b815260206004820152600c60248201526b04e6f206164647265737320360a41b604482015260640161033e565b600034116106c95760405162461bcd60e51b815260206004820152600d60248201526c04d73672076616c7565203d203609c1b604482015260640161033e565b60006106d4346102c3565b6007546040516370a0823160e01b815230600482015291925082916001600160a01b03909116906370a082319060240160206040518083038186803b15801561071c57600080fd5b505afa158015610730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190610b66565b101561079b5760405162461bcd60e51b8152602060048201526016602482015275446f206e6f74206861766520656e6f7567682047504f60501b604482015260640161033e565b6007546001600160a01b031663a9059cbb336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b1580156107f557600080fd5b505af1158015610809573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082d9190610b2b565b506007546001600160a01b031663e266903b336040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526001602482015260448101849052606401600060405180830381600087803b15801561088f57600080fd5b505af11580156108a3573d6000803e3d6000fd5b50505050806006546108b59190610c59565b60065560408051348152602081018390524281830152905133917f0d1a0d5e3d583a0e92588799dd06e50fd78c07daf05f0cc06d7b848b1ca445f1919081900360600190a2610902610aaf565b50600054811461051957600080fd5b600080600260009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561096257600080fd5b505afa158015610976573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099a9190610b7f565b5050509150508060095469d3c21bcecceda10000006109b99190610c93565b6109c39190610c71565b91505090565b6001546001600160a01b031633146109f35760405162461bcd60e51b815260040161033e90610c24565b6001600160a01b038116610a585760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161033e565b610519815b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6008546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610519573d6000803e3d6000fd5b805169ffffffffffffffffffff81168114610b0257600080fd5b919050565b600060208284031215610b1957600080fd5b8135610b2481610d03565b9392505050565b600060208284031215610b3d57600080fd5b81518015158114610b2457600080fd5b600060208284031215610b5f57600080fd5b5035919050565b600060208284031215610b7857600080fd5b5051919050565b600080600080600060a08688031215610b9757600080fd5b610ba086610ae8565b9450602086015193506040860151925060608601519150610bc360808701610ae8565b90509295509295909350565b600060208083528351808285015260005b81811015610bfc57858101830151858201604001528201610be0565b81811115610c0e576000604083870101525b50601f01601f1916929092016040019392505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60008219821115610c6c57610c6c610ced565b500190565b600082610c8e57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615610cad57610cad610ced565b500290565b600181811c90821680610cc657607f821691505b60208210811415610ce757634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461051957600080fdfea26469706673582212202d500db669ad02f811033e548c0fbf715cb8258b080364ae6d3810a452960a1e64736f6c6343000807003300000000000000000000000000000000000000000000000000000000622a910000000000000000000000000000000000000000000000000000000000000f42400000000000000000000000004ad7a056191f4c9519facd6d75fa94ca26003ace0000000000000000000000003076f89fb7e0363e2d73ee5a7d1f555c61b9e8530000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419
Deployed Bytecode
0x6080604052600436106100f35760003560e01c8063715018a61161008a5780639b8906ae116100595780639b8906ae1461025c578063d0febe4c14610286578063ed6c91811461028e578063f2fde38b146102a357600080fd5b8063715018a6146101f15780638aae995a146102065780638adf55651461021c5780638da5cb5b1461023e57600080fd5b8063380d831b116100c6578063380d831b1461018f57806352a16bb0146101a657806355ce3b9a146101bc57806363cc4aa2146101dc57600080fd5b80630122ffc0146100f85780631a1d0aca1461012157806321a653831461015957806329627abe1461016f575b600080fd5b34801561010457600080fd5b5061010e60045481565b6040519081526020015b60405180910390f35b34801561012d57600080fd5b50600754610141906001600160a01b031681565b6040516001600160a01b039091168152602001610118565b34801561016557600080fd5b5061010e60095481565b34801561017b57600080fd5b5061010e61018a366004610b4d565b6102c3565b34801561019b57600080fd5b506101a46102ef565b005b3480156101b257600080fd5b5061010e60065481565b3480156101c857600080fd5b506101a46101d7366004610b07565b610380565b3480156101e857600080fd5b506101a46103cc565b3480156101fd57600080fd5b506101a461051c565b34801561021257600080fd5b5061010e60055481565b34801561022857600080fd5b50610231610552565b6040516101189190610bcf565b34801561024a57600080fd5b506001546001600160a01b0316610141565b34801561026857600080fd5b50600a546102769060ff1681565b6040519015158152602001610118565b6101a46105e0565b34801561029a57600080fd5b5061010e610911565b3480156102af57600080fd5b506101a46102be366004610b07565b6109c9565b60006102cd610911565b6102df83670de0b6b3a7640000610c93565b6102e99190610c71565b92915050565b60045442101580156103045750600a5460ff16155b6103475760405162461bcd60e51b815260206004820152600f60248201526e4e6f7420647572696e672073616c6560881b60448201526064015b60405180910390fd5b6001546001600160a01b031633146103715760405162461bcd60e51b815260040161033e90610c24565b600a805460ff19166001179055565b6001546001600160a01b031633146103aa5760405162461bcd60e51b815260040161033e90610c24565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b600a5460ff166103db57600080fd5b6001546001600160a01b031633146104055760405162461bcd60e51b815260040161033e90610c24565b600554600654141561041657600080fd5b6007546040516370a0823160e01b81523060048201526001600160a01b039091169063a9059cbb90829081906370a082319060240160206040518083038186803b15801561046357600080fd5b505afa158015610477573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049b9190610b66565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b1580156104e157600080fd5b505af11580156104f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105199190610b2b565b50565b6001546001600160a01b031633146105465760405162461bcd60e51b815260040161033e90610c24565b6105506000610a5d565b565b6003805461055f90610cb2565b80601f016020809104026020016040519081016040528092919081815260200182805461058b90610cb2565b80156105d85780601f106105ad576101008083540402835291602001916105d8565b820191906000526020600020905b8154815290600101906020018083116105bb57829003601f168201915b505050505081565b60016000808282546105f29190610c59565b9091555050600054600454421080159061060f5750600a5460ff16155b61064d5760405162461bcd60e51b815260206004820152600f60248201526e4e6f7420647572696e672073616c6560881b604482015260640161033e565b336106895760405162461bcd60e51b815260206004820152600c60248201526b04e6f206164647265737320360a41b604482015260640161033e565b600034116106c95760405162461bcd60e51b815260206004820152600d60248201526c04d73672076616c7565203d203609c1b604482015260640161033e565b60006106d4346102c3565b6007546040516370a0823160e01b815230600482015291925082916001600160a01b03909116906370a082319060240160206040518083038186803b15801561071c57600080fd5b505afa158015610730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190610b66565b101561079b5760405162461bcd60e51b8152602060048201526016602482015275446f206e6f74206861766520656e6f7567682047504f60501b604482015260640161033e565b6007546001600160a01b031663a9059cbb336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401602060405180830381600087803b1580156107f557600080fd5b505af1158015610809573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061082d9190610b2b565b506007546001600160a01b031663e266903b336040516001600160e01b031960e084901b1681526001600160a01b0390911660048201526001602482015260448101849052606401600060405180830381600087803b15801561088f57600080fd5b505af11580156108a3573d6000803e3d6000fd5b50505050806006546108b59190610c59565b60065560408051348152602081018390524281830152905133917f0d1a0d5e3d583a0e92588799dd06e50fd78c07daf05f0cc06d7b848b1ca445f1919081900360600190a2610902610aaf565b50600054811461051957600080fd5b600080600260009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561096257600080fd5b505afa158015610976573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099a9190610b7f565b5050509150508060095469d3c21bcecceda10000006109b99190610c93565b6109c39190610c71565b91505090565b6001546001600160a01b031633146109f35760405162461bcd60e51b815260040161033e90610c24565b6001600160a01b038116610a585760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161033e565b610519815b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6008546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610519573d6000803e3d6000fd5b805169ffffffffffffffffffff81168114610b0257600080fd5b919050565b600060208284031215610b1957600080fd5b8135610b2481610d03565b9392505050565b600060208284031215610b3d57600080fd5b81518015158114610b2457600080fd5b600060208284031215610b5f57600080fd5b5035919050565b600060208284031215610b7857600080fd5b5051919050565b600080600080600060a08688031215610b9757600080fd5b610ba086610ae8565b9450602086015193506040860151925060608601519150610bc360808701610ae8565b90509295509295909350565b600060208083528351808285015260005b81811015610bfc57858101830151858201604001528201610be0565b81811115610c0e576000604083870101525b50601f01601f1916929092016040019392505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60008219821115610c6c57610c6c610ced565b500190565b600082610c8e57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615610cad57610cad610ced565b500290565b600181811c90821680610cc657607f821691505b60208210811415610ce757634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6001600160a01b038116811461051957600080fdfea26469706673582212202d500db669ad02f811033e548c0fbf715cb8258b080364ae6d3810a452960a1e64736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000622a910000000000000000000000000000000000000000000000000000000000000f42400000000000000000000000004ad7a056191f4c9519facd6d75fa94ca26003ace0000000000000000000000003076f89fb7e0363e2d73ee5a7d1f555c61b9e8530000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419
-----Decoded View---------------
Arg [0] : _startUnixTime (uint256): 1646956800
Arg [1] : _saleAmount (uint256): 1000000
Arg [2] : _gpo (address): 0x4ad7a056191F4c9519fAcd6D75FA94CA26003aCE
Arg [3] : _fundWallet (address): 0x3076f89fB7e0363E2d73ee5A7D1F555c61B9e853
Arg [4] : _ethUsdAggregator (address): 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000622a9100
Arg [1] : 00000000000000000000000000000000000000000000000000000000000f4240
Arg [2] : 0000000000000000000000004ad7a056191f4c9519facd6d75fa94ca26003ace
Arg [3] : 0000000000000000000000003076f89fb7e0363e2d73ee5a7d1f555c61b9e853
Arg [4] : 0000000000000000000000005f4ec3df9cbd43714fe2740f5e3616155c5b8419
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.