Source Code
Latest 25 from a total of 27,828 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Cam Zap From Vau... | 75785743 | 148 days ago | IN | 0 POL | 0.01353648 | ||||
| Cam Zap From Vau... | 75784393 | 148 days ago | IN | 0 POL | 0.00488994 | ||||
| Cam Zap From Vau... | 75596194 | 153 days ago | IN | 0 POL | 0.01427016 | ||||
| Cam Zap From Vau... | 74399893 | 182 days ago | IN | 0 POL | 0.01437996 | ||||
| Cam Zap From Vau... | 74240315 | 186 days ago | IN | 0 POL | 0.01396896 | ||||
| Cam Zap From Vau... | 74207085 | 187 days ago | IN | 0 POL | 0.01462542 | ||||
| Cam Zap From Vau... | 74206605 | 187 days ago | IN | 0 POL | 0.01511367 | ||||
| Cam Zap From Vau... | 73141872 | 214 days ago | IN | 0 POL | 0.01455822 | ||||
| Cam Zap From Vau... | 73141799 | 214 days ago | IN | 0 POL | 0.01353648 | ||||
| Cam Zap From Vau... | 73141745 | 214 days ago | IN | 0 POL | 0.01355856 | ||||
| Cam Zap From Vau... | 73141693 | 214 days ago | IN | 0 POL | 0.01437996 | ||||
| Cam Zap From Vau... | 71305423 | 260 days ago | IN | 0 POL | 0.0557088 | ||||
| Cam Zap From Vau... | 71140518 | 264 days ago | IN | 0 POL | 0.0143961 | ||||
| Cam Zap From Vau... | 69740897 | 298 days ago | IN | 0 POL | 0.01353618 | ||||
| Cam Zap From Vau... | 66430012 | 381 days ago | IN | 0 POL | 0.01424959 | ||||
| Cam Zap From Vau... | 66428968 | 381 days ago | IN | 0 POL | 0.01275504 | ||||
| Cam Zap From Vau... | 66348604 | 383 days ago | IN | 0 POL | 0.00488964 | ||||
| Cam Zap From Vau... | 66274509 | 385 days ago | IN | 0 POL | 0.02257312 | ||||
| Cam Zap From Vau... | 66274294 | 385 days ago | IN | 0 POL | 0.02032816 | ||||
| Cam Zap From Vau... | 66000866 | 392 days ago | IN | 0 POL | 0.03374617 | ||||
| Cam Zap From Vau... | 65758424 | 398 days ago | IN | 0 POL | 0.0320664 | ||||
| Cam Zap From Vau... | 65443730 | 406 days ago | IN | 0 POL | 0.01396926 | ||||
| Cam Zap From Vau... | 65432264 | 407 days ago | IN | 0 POL | 0.0150463 | ||||
| Cam Zap From Vau... | 65114625 | 415 days ago | IN | 0 POL | 0.02347663 | ||||
| Cam Zap From Vau... | 65006810 | 417 days ago | IN | 0 POL | 0.01423993 |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
camZapper
Compiler Version
v0.5.16+commit.9c3226ce
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;
import "./interfaces/ILendingPool.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/lifecycle/Pausable.sol";
import "./camToken.sol";
import "./erc20Stablecoin/erc20QiStablecoin.sol";
import "./interfaces/IAToken.sol";
contract camZapper is Ownable, Pausable, IERC721Receiver {
using SafeMath for uint256;
struct CamChain {
IERC20 asset;
IAToken amToken;
camToken _camToken;
erc20QiStablecoin camTokenVault;
}
mapping (bytes32 => CamChain) private _chainWhiteList;
ILendingPool aavePolyPool = ILendingPool(0x8dFf5E27EA6b7AC08EbFdf9eB090F32ee9a30fcf);
event AssetZapped(address indexed asset, uint256 indexed amount, uint256 vaultId);
event AssetUnZapped(address indexed asset, uint256 indexed amount, uint256 vaultId);
function _camZapToVault(uint256 amount, uint256 vaultId, CamChain memory chain) internal whenNotPaused returns (uint256) {
require(amount > 0, "You need to deposit at least some tokens");
uint256 allowance = chain.asset.allowance(msg.sender, address(this));
require(allowance >= amount, "Check the token allowance");
chain.asset.transferFrom(msg.sender, address(this), amount);
chain.asset.approve(address(aavePolyPool), amount);
aavePolyPool.deposit(address(chain.asset), amount, address(this), 0);
chain.amToken.approve(address(chain._camToken), amount);
chain._camToken.enter(amount);
uint256 camTokenBal = chain._camToken.balanceOf(address(this));
if(vaultId == 0){
chain.asset.transferFrom(address(this), msg.sender, camTokenBal);
emit AssetZapped(address(chain.asset), amount, vaultId);
} else {
chain._camToken.approve(address(chain.camTokenVault), camTokenBal);
chain.camTokenVault.depositCollateral(vaultId, camTokenBal);
emit AssetZapped(address(chain.asset), amount, vaultId);
}
return camTokenBal;
}
function _camZapFromVault(uint256 amount, uint256 vaultId, CamChain memory chain) internal whenNotPaused returns (uint256) {
require(amount > 0, "You need to withdraw at least some tokens");
require(chain.camTokenVault.getApproved(vaultId) == address(this), "Need to have approval");
require(chain.camTokenVault.ownerOf(vaultId) == msg.sender, "You can only zap out of vaults you own");
chain._camToken.approve(address(chain.camTokenVault), amount);
chain.camTokenVault.safeTransferFrom(msg.sender, address(this), vaultId);
uint256 camTokenBalanceBeforeWithdraw = chain._camToken.balanceOf(address(this));
chain.camTokenVault.withdrawCollateral(vaultId, amount);
uint256 camTokenBalanceToUnzap = chain._camToken.balanceOf(address(this)).sub(camTokenBalanceBeforeWithdraw);
chain.camTokenVault.approve(msg.sender, vaultId);
chain.camTokenVault.safeTransferFrom(address(this), msg.sender, vaultId);
uint256 amTokenBalanceBeforeWithdraw = chain.amToken.balanceOf(address(this));
chain._camToken.leave(camTokenBalanceToUnzap);
uint256 amTokenBalanceToUnzap = chain.amToken.balanceOf(address(this)).sub(amTokenBalanceBeforeWithdraw);
chain.amToken.approve(address(aavePolyPool), amTokenBalanceToUnzap);
aavePolyPool.withdraw(address(chain.asset), amTokenBalanceToUnzap, msg.sender);
emit AssetUnZapped(address(chain.asset), amount, vaultId);
return chain.asset.balanceOf(msg.sender);
}
function _buildCamChain(address _asset, address _amAsset, address _camAsset, address _camAssetVault) internal returns (CamChain memory){
CamChain memory chain;
chain.asset = IERC20(_asset);
chain.amToken = IAToken(_amAsset);
chain._camToken = camToken(_camAsset);
chain.camTokenVault = erc20QiStablecoin(_camAssetVault);
return chain;
}
function _hashCamChain(CamChain memory chain) internal returns (bytes32){
return keccak256(
abi.encodePacked(address(chain.asset), address(chain.amToken), address(chain._camToken), address(chain.camTokenVault)));
}
function isWhiteListed(CamChain memory chain) public returns (bool){
return address(_chainWhiteList[_hashCamChain(chain)].asset) != address(0x0);
}
function addChainToWhiteList(address _asset, address _amAsset, address _camAsset, address _camAssetVault) public onlyOwner {
CamChain memory chain = _buildCamChain(_asset, _amAsset, _camAsset, _camAssetVault);
if(!isWhiteListed(chain)){
_chainWhiteList[_hashCamChain(chain)] = chain;
} else {
revert("Chain already in White List");
}
}
function removeChainFromWhiteList(address _asset, address _amAsset, address _camAsset, address _camAssetVault) public onlyOwner {
CamChain memory chain = _buildCamChain(_asset, _amAsset, _camAsset, _camAssetVault);
if(isWhiteListed(chain)){
delete _chainWhiteList[_hashCamChain(chain)];
} else {
revert("Chain not in white List");
}
}
function pauseZapping() public onlyOwner {
pause();
}
function resumeZapping() public onlyOwner {
unpause();
}
function camZapToVault(uint256 amount, uint256 vaultId, address _asset, address _amAsset, address _camAsset, address _camAssetVault) public whenNotPaused returns (uint256) {
CamChain memory chain = _buildCamChain(_asset, _amAsset, _camAsset, _camAssetVault);
require(isWhiteListed(chain), "camToken chain not in on allowable list");
return _camZapToVault(amount, vaultId, chain);
}
function camZapFromVault(uint256 amount, uint256 vaultId, address _asset, address _amAsset, address _camAsset, address _camAssetVault) public whenNotPaused returns (uint256) {
CamChain memory chain = _buildCamChain(_asset, _amAsset, _camAsset, _camAssetVault);
require(isWhiteListed(chain), "camToken chain not in on allowable list");
return _camZapFromVault(amount, vaultId, chain);
}
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) public returns (bytes4) {
return this.onERC721Received.selector;
}
}// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;
interface ILendingPool {
/**
* @dev Emitted on deposit()
* @param reserve The address of the underlying asset of the reserve
* @param user The address initiating the deposit
* @param onBehalfOf The beneficiary of the deposit, receiving the aTokens
* @param amount The amount deposited
* @param referral The referral code used
**/
event Deposit(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint16 indexed referral
);
/**
* @dev Emitted on withdraw()
* @param reserve The address of the underlyng asset being withdrawn
* @param user The address initiating the withdrawal, owner of aTokens
* @param to Address that will receive the underlying
* @param amount The amount to be withdrawn
**/
event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
/**
* @dev Emitted on borrow() and flashLoan() when debt needs to be opened
* @param reserve The address of the underlying asset being borrowed
* @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
* initiator of the transaction on flashLoan()
* @param onBehalfOf The address that will be getting the debt
* @param amount The amount borrowed out
* @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable
* @param borrowRate The numeric rate at which the user has borrowed
* @param referral The referral code used
**/
event Borrow(
address indexed reserve,
address user,
address indexed onBehalfOf,
uint256 amount,
uint256 borrowRateMode,
uint256 borrowRate,
uint16 indexed referral
);
/**
* @dev Emitted on repay()
* @param reserve The address of the underlying asset of the reserve
* @param user The beneficiary of the repayment, getting his debt reduced
* @param repayer The address of the user initiating the repay(), providing the funds
* @param amount The amount repaid
**/
event Repay(
address indexed reserve,
address indexed user,
address indexed repayer,
uint256 amount
);
/**
* @dev Emitted on swapBorrowRateMode()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user swapping his rate mode
* @param rateMode The rate mode that the user wants to swap to
**/
event Swap(address indexed reserve, address indexed user, uint256 rateMode);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on setUserUseReserveAsCollateral()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user enabling the usage as collateral
**/
event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);
/**
* @dev Emitted on rebalanceStableBorrowRate()
* @param reserve The address of the underlying asset of the reserve
* @param user The address of the user for which the rebalance has been executed
**/
event RebalanceStableBorrowRate(address indexed reserve, address indexed user);
/**
* @dev Emitted on flashLoan()
* @param target The address of the flash loan receiver contract
* @param initiator The address initiating the flash loan
* @param asset The address of the asset being flash borrowed
* @param amount The amount flash borrowed
* @param premium The fee flash borrowed
* @param referralCode The referral code used
**/
event FlashLoan(
address indexed target,
address indexed initiator,
address indexed asset,
uint256 amount,
uint256 premium,
uint16 referralCode
);
/**
* @dev Emitted when the pause is triggered.
*/
event Paused();
/**
* @dev Emitted when the pause is lifted.
*/
event Unpaused();
/**
* @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via
* LendingPoolCollateral manager using a DELEGATECALL
* This allows to have the events in the generated ABI for LendingPool.
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param liquidatedCollateralAmount The amount of collateral received by the liiquidator
* @param liquidator The address of the liquidator
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
event LiquidationCall(
address indexed collateralAsset,
address indexed debtAsset,
address indexed user,
uint256 debtToCover,
uint256 liquidatedCollateralAmount,
address liquidator,
bool receiveAToken
);
/**
* @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared
* in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,
* the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it
* gets added to the LendingPool ABI
* @param reserve The address of the underlying asset of the reserve
* @param liquidityRate The new liquidity rate
* @param stableBorrowRate The new stable borrow rate
* @param variableBorrowRate The new variable borrow rate
* @param liquidityIndex The new liquidity index
* @param variableBorrowIndex The new variable borrow index
**/
event ReserveDataUpdated(
address indexed reserve,
uint256 liquidityRate,
uint256 stableBorrowRate,
uint256 variableBorrowRate,
uint256 liquidityIndex,
uint256 variableBorrowIndex
);
/**
* @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User deposits 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to deposit
* @param amount The amount to be deposited
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
/**
* @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param asset The address of the underlying asset to withdraw
* @param amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param to Address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
* @return The final amount withdrawn
**/
function withdraw(
address asset,
uint256 amount,
address to
) external returns (uint256);
/**
* @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already deposited enough collateral, or he was given enough allowance by a credit delegator on the
* corresponding debt token (StableDebtToken or VariableDebtToken)
* - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
* and 100 stable/variable debt tokens, depending on the `interestRateMode`
* @param asset The address of the underlying asset to borrow
* @param amount The amount to be borrowed
* @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance
**/
function borrow(
address asset,
uint256 amount,
uint256 interestRateMode,
uint16 referralCode,
address onBehalfOf
) external;
/**
* @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
* - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
* @return The final amount repaid
**/
function repay(
address asset,
uint256 amount,
uint256 rateMode,
address onBehalfOf
) external returns (uint256);
/**
* @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa
* @param asset The address of the underlying asset borrowed
* @param rateMode The rate mode that the user wants to swap to
**/
function swapBorrowRateMode(address asset, uint256 rateMode) external;
/**
* @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.
* - Users can be rebalanced if the following conditions are satisfied:
* 1. Usage ratio is above 95%
* 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been
* borrowed at a stable rate and depositors are not earning enough
* @param asset The address of the underlying asset borrowed
* @param user The address of the user to be rebalanced
**/
function rebalanceStableBorrowRate(address asset, address user) external;
/**
* @dev Allows depositors to enable/disable a specific deposited asset as collateral
* @param asset The address of the underlying asset deposited
* @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise
**/
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
/**
* @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
* - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
* @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
* @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
* @param user The address of the borrower getting liquidated
* @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
* @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants
* to receive the underlying collateral asset directly
**/
function liquidationCall(
address collateralAsset,
address debtAsset,
address user,
uint256 debtToCover,
bool receiveAToken
) external;
/**
* @dev Allows smartcontracts to access the liquidity of the pool within one transaction,
* as long as the amount taken plus a fee is returned.
* IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration.
* For further details please visit https://developers.aave.com
* @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface
* @param assets The addresses of the assets being flash-borrowed
* @param amounts The amounts amounts being flash-borrowed
* @param modes Types of the debt to open if the flash loan is not returned:
* 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
* 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
* @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2
* @param params Variadic packed params to pass to the receiver as extra information
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function flashLoan(
address receiverAddress,
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata modes,
address onBehalfOf,
bytes calldata params,
uint16 referralCode
) external;
/**
* @dev Returns the user account data across all the reserves
* @param user The address of the user
* @return totalCollateralETH the total collateral in ETH of the user
* @return totalDebtETH the total debt in ETH of the user
* @return availableBorrowsETH the borrowing power left of the user
* @return currentLiquidationThreshold the liquidation threshold of the user
* @return ltv the loan to value of the user
* @return healthFactor the current health factor of the user
**/
function getUserAccountData(address user)
external
view
returns (
uint256 totalCollateralETH,
uint256 totalDebtETH,
uint256 availableBorrowsETH,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
function initReserve(
address reserve,
address aTokenAddress,
address stableDebtAddress,
address variableDebtAddress,
address interestRateStrategyAddress
) external;
function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress)
external;
function setConfiguration(address reserve, uint256 configuration) external;
/**
* @dev Returns the normalized income normalized income of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The reserve's normalized income
*/
function getReserveNormalizedIncome(address asset) external view returns (uint256);
/**
* @dev Returns the normalized variable debt per unit of asset
* @param asset The address of the underlying asset of the reserve
* @return The reserve normalized variable debt
*/
function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);
function finalizeTransfer(
address asset,
address from,
address to,
uint256 amount,
uint256 balanceFromAfter,
uint256 balanceToBefore
) external;
function getReservesList() external view returns (address[] memory);
function setPause(bool val) external;
function paused() external view returns (bool);
}pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.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 {ERC20Mintable}.
*
* 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 guidelines: functions revert instead
* of 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 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view 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 returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public 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 returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
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 returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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 returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* This is 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 {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(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
*
* - `to` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(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 {
require(account != address(0), "ERC20: burn from the zero address");
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
*
* This is 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 {
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 Destroys `amount` tokens from `account`.`amount` is then deducted
* from the caller's allowance.
*
* See {_burn} and {_approve}.
*/
function _burnFrom(address account, uint256 amount) internal {
_burn(account, amount);
_approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
}
}pragma solidity ^0.5.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
contract IERC721Receiver {
/**
* @notice Handle the receipt of an NFT
* @dev The ERC721 smart contract calls this function on the recipient
* after a {IERC721-safeTransferFrom}. This function MUST return the function selector,
* otherwise the caller will revert the transaction. The selector to be
* returned can be obtained as `this.onERC721Received.selector`. This
* function MAY throw to revert and reject the transfer.
* Note: the ERC721 contract address is always the message sender.
* @param operator The address which called `safeTransferFrom` function
* @param from The address which previously owned the token
* @param tokenId The NFT identifier which is being transferred
* @param data Additional data with no specified format
* @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
*/
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
public returns (bytes4);
}pragma solidity ^0.5.0;
import "../GSN/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.
*
* 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.
*/
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 () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/
function isOwner() public view returns (bool) {
return _msgSender() == _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 onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = 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 onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}pragma solidity ^0.5.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}pragma solidity ^0.5.0;
import "../GSN/Context.sol";
import "../access/roles/PauserRole.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.
*/
contract Pausable is Context, PauserRole {
/**
* @dev Emitted when the pause is triggered by a pauser (`account`).
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by a pauser (`account`).
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state. Assigns the Pauser role
* to the deployer.
*/
constructor () internal {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!_paused, "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*/
modifier whenPaused() {
require(_paused, "Pausable: not paused");
_;
}
/**
* @dev Called by a pauser to pause, triggers stopped state.
*/
function pause() public onlyPauser whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Called by a pauser to unpause, returns to normal state.
*/
function unpause() public onlyPauser whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// contracts/shareOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.5.16;
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "./interfaces/IAaveIncentivesController.sol";
import "./interfaces/ILendingPool.sol";
interface Uni {
function swapExactTokensForTokens(
uint256,
uint256,
address[] calldata,
address,
uint256
) external;
}
// stake Token to earn more Token (from farming)
contract camToken is ERC20, ERC20Detailed {
using SafeMath for uint256;
using SafeERC20 for IERC20;
address public Token;
address public AaveContract;
address public wMatic;
address public constant LENDING_POOL = 0x8dFf5E27EA6b7AC08EbFdf9eB090F32ee9a30fcf;
address public uni; // QuickSwap
address public treasury;
address public operator;
address public usdc;
uint16 public depositFeeBP;
// Define the compounding aave market token contract
constructor(address amToken, address underlying, string memory name, string memory symbol, uint8 decimals) ERC20Detailed(name, symbol, decimals) public {
Token=amToken; //amusdc
usdc=underlying;
AaveContract = 0x357D51124f59836DeD84c8a1730D72B749d8BC23; // aave incentives controller
wMatic = 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270;
uni = 0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff; // quickswap
treasury = 0x86fE8d6D4C8A007353617587988552B6921514Cb;
depositFeeBP = 0;
operator = address(0);
}
modifier onlyOperator() {
require(operator==address(0) || msg.sender == operator, "onlyOperator: not allowed");
_;
}
function updateOperator(address _operator) public {
require(treasury==msg.sender, "updateOperator: not allowed.");
operator=_operator;
}
function updateTreasury(address _treasury) public {
require(treasury==msg.sender, "updateTreasury: not allowed.");
treasury=_treasury;
}
function updateUniV2Router(address _router) public {
require(treasury==msg.sender, "updateUniV2Router: not allowed.");
uni=_router;
}
function updateDepositFee(uint16 _depositFee) public {
require(treasury==msg.sender, "updateDepositFee: not allowed.");
depositFeeBP=_depositFee;
}
// Locks amToken and mints camToken (shares)
function enter(uint256 _amount) public {
uint256 totalTokenLocked = IERC20(Token).balanceOf(address(this));
uint256 totalShares = totalSupply(); // Gets the amount of camToken in existence
// Lock the Token in the contract
IERC20(Token).transferFrom(msg.sender, address(this), _amount);
if (totalShares == 0 || totalTokenLocked == 0) { // If no camToken exists, mint it 1:1 to the amount put in
if(depositFeeBP > 0){
// calculate depositFeeBP
uint256 depositFee = _amount.mul(depositFeeBP).div(10000);
_mint(treasury, depositFee);
_mint(msg.sender, _amount.sub(depositFee));
}else{
_mint(msg.sender, _amount);
}
} else {
uint256 camTokenAmount = _amount.mul(totalShares).div(totalTokenLocked);
if(depositFeeBP > 0){
uint256 depositFee = camTokenAmount.mul(depositFeeBP).div(10000);
_mint(treasury, depositFee);
_mint(msg.sender, camTokenAmount.sub(depositFee));
}else{
_mint(msg.sender, camTokenAmount);
}
}
}
function claimAaveRewards() public onlyOperator() {
// we're only checking for one asset (Token which is an interest bearing amToken)
address[] memory rewardsPath = new address[](1);
rewardsPath[0] = Token;
// check how many matic are available to claim
uint256 rewardBalance = IAaveIncentivesController(AaveContract).getRewardsBalance(rewardsPath, address(this));
// we should only claim rewards if its over 0.
if(rewardBalance > 2){
IAaveIncentivesController(AaveContract).claimRewards(rewardsPath, rewardBalance, address(this));
}
}
function harvestMaticIntoToken() public onlyOperator() {
// claims any available Matic from the Aave Incentives contract.
uint256 _wmaticBalance = IERC20(wMatic).balanceOf(address(this));
if(_wmaticBalance > 2) {
address[] memory path = new address[](2);
path[0] = wMatic;
path[1] = usdc;
IERC20(wMatic).safeApprove(uni, 0);
IERC20(wMatic).safeApprove(uni, _wmaticBalance);
// if successful this should increase the total MiMatic held by contract
Uni(uni).swapExactTokensForTokens(_wmaticBalance, uint256(0), path, address(this), now.add(1800));
uint256 newBalance = IERC20(usdc).balanceOf(address(this));
// Just being safe
IERC20(usdc).safeApprove(LENDING_POOL, 0);
// Approve Transfer _amount usdc to lending pool
IERC20(usdc).safeApprove(LENDING_POOL, newBalance);
// then we need to deposit it into the lending pool
ILendingPool(LENDING_POOL).deposit(usdc, newBalance, address(this), 0);
}
}
// claim amToken by burning camToken
function leave(uint256 _share) public {
if(_share>0){
uint256 totalShares = totalSupply(); // Gets the amount of camToken in existence
uint256 amTokenAmount = _share.mul(IERC20(Token).balanceOf(address(this))).div(totalShares);
_burn(msg.sender, _share);
// Now we withdraw the amToken from the camToken Pool and send to user as amToken.
//IERC20(usdc).safeApprove(address(this), amTokenAmount);
IERC20(Token).transfer(msg.sender, amTokenAmount);
}
}
}pragma solidity 0.5.16;
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "./erc20Stablecoin.sol";
contract erc20QiStablecoin is erc20Stablecoin, Ownable {
constructor(
address ethPriceSourceAddress,
uint256 minimumCollateralPercentage,
string memory name,
string memory symbol,
address _mai,
address _collateral,
address meta,
string memory baseURI
) erc20Stablecoin(
ethPriceSourceAddress,
minimumCollateralPercentage,
name,
symbol,
_mai,
_collateral,
meta,
baseURI
) public {
treasury=0;
}
function setGainRatio(uint256 _gainRatio) external onlyOwner() {
gainRatio=_gainRatio;
}
function setDebtRatio(uint256 _debtRatio) external onlyOwner() {
debtRatio=_debtRatio;
}
// management function
function transferToken(address to, address token, uint256 amountToken) external onlyOwner() {
ERC20(token).transfer(to, amountToken);
}
function changeEthPriceSource(address ethPriceSourceAddress) external onlyOwner() {
ethPriceSource = shareOracle(ethPriceSourceAddress);
}
function setTokenPeg(uint256 _tokenPeg) external onlyOwner() {
tokenPeg = _tokenPeg;
}
function setStabilityPool(address _pool) external onlyOwner() {
stabilityPool = _pool;
}
function setMinCollateralRatio(uint256 minimumCollateralPercentage) external onlyOwner() {
_minimumCollateralPercentage = minimumCollateralPercentage;
}
function setClosingFee(uint256 amount) external onlyOwner() {
closingFee = amount;
}
function setOpeningFee(uint256 amount) external onlyOwner() {
openingFee = amount;
}
function setTreasury(uint256 _treasury) external onlyOwner() {
require(_exists(_treasury), "Vault does not exist");
treasury = _treasury;
}
function transferToken(uint256 amountToken) public onlyOwner() {
// Transfer reserve tokens back to main MAI contract
mai.transfer(address(mai), amountToken);
}
function setBaseURI(string memory baseURI) public onlyOwner() {
_setBaseURI(baseURI);
}
}pragma solidity ^0.5.0;
/**
* @title Aave ERC20 AToken
*
* @dev Implementation of the interest bearing token for the DLP protocol.
* @author Aave
*/
interface IAToken {
/**
* @dev redirects the interest generated to a target address.
* when the interest is redirected, the user balance is added to
* the recepient redirected balance.
* @param _to the address to which the interest will be redirected
**/
function redirectInterestStream(address _to) external;
/**
* @dev redirects the interest generated by _from to a target address.
* when the interest is redirected, the user balance is added to
* the recepient redirected balance. The caller needs to have allowance on
* the interest redirection to be able to execute the function.
* @param _from the address of the user whom interest is being redirected
* @param _to the address to which the interest will be redirected
**/
function redirectInterestStreamOf(address _from, address _to) external;
/**
* @dev gives allowance to an address to execute the interest redirection
* on behalf of the caller.
* @param _to the address to which the interest will be redirected. Pass address(0) to reset
* the allowance.
**/
function allowInterestRedirectionTo(address _to) external;
/**
* @dev redeems aToken for the underlying asset
* @param _amount the amount being redeemed
**/
function redeem(uint256 _amount) external;
/**
* @dev mints token in the event of users depositing the underlying asset into the lending pool
* only lending pools can call this function
* @param _account the address receiving the minted tokens
* @param _amount the amount of tokens to mint
*/
function mintOnDeposit(address _account, uint256 _amount) external;
/**
* @dev burns token in the event of a borrow being liquidated, in case the liquidators reclaims the underlying asset
* Transfer of the liquidated asset is executed by the lending pool contract.
* only lending pools can call this function
* @param _account the address from which burn the aTokens
* @param _value the amount to burn
**/
function burnOnLiquidation(address _account, uint256 _value) external;
/**
* @dev transfers tokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken
* only lending pools can call this function
* @param _from the address from which transfer the aTokens
* @param _to the destination address
* @param _value the amount to transfer
**/
function transferOnLiquidation(address _from, address _to, uint256 _value) external;
/**
* @dev calculates the balance of the user, which is the
* principal balance + interest generated by the principal balance + interest generated by the redirected balance
* @param _user the user for which the balance is being calculated
* @return the total balance of the user
**/
function balanceOf(address _user) external view returns(uint256);
/**
* @dev returns the principal balance of the user. The principal balance is the last
* updated stored balance, which does not consider the perpetually accruing interest.
* @param _user the address of the user
* @return the principal balance of the user
**/
function principalBalanceOf(address _user) external view returns(uint256);
/**
* @dev calculates the total supply of the specific aToken
* since the balance of every single user increases over time, the total supply
* does that too.
* @return the current total supply
**/
function totalSupply() external view returns(uint256);
/**
* @dev Used to validate transfers before actually executing them.
* @param _user address of the user to check
* @param _amount the amount to check
* @return true if the _user can transfer _amount, false otherwise
**/
function isTransferAllowed(address _user, uint256 _amount) external view returns (bool);
/**
* @dev returns the last index of the user, used to calculate the balance of the user
* @param _user address of the user
* @return the last user index
**/
function getUserIndex(address _user) external view returns(uint256);
/**
* @dev returns the address to which the interest is redirected
* @param _user address of the user
* @return 0 if there is no redirection, an address otherwise
**/
function getInterestRedirectionAddress(address _user) external view returns(address);
/**
* @dev returns the redirected balance of the user. The redirected balance is the balance
* redirected by other accounts to the user, that is accrueing interest for him.
* @param _user address of the user
* @return the total redirected balance
**/
function getRedirectedBalance(address _user) external view returns(uint256);
function approve(address spender, uint256 amount) external returns (bool);
}pragma solidity ^0.5.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 GSN 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.
*/
contract Context {
// Empty internal constructor, to prevent people from mistakenly deploying
// an instance of this contract, which should be used via inheritance.
constructor () internal { }
// solhint-disable-previous-line no-empty-blocks
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}pragma solidity ^0.5.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/
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);
}pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "../Roles.sol";
contract PauserRole is Context {
using Roles for Roles.Role;
event PauserAdded(address indexed account);
event PauserRemoved(address indexed account);
Roles.Role private _pausers;
constructor () internal {
_addPauser(_msgSender());
}
modifier onlyPauser() {
require(isPauser(_msgSender()), "PauserRole: caller does not have the Pauser role");
_;
}
function isPauser(address account) public view returns (bool) {
return _pausers.has(account);
}
function addPauser(address account) public onlyPauser {
_addPauser(account);
}
function renouncePauser() public {
_removePauser(_msgSender());
}
function _addPauser(address account) internal {
_pausers.add(account);
emit PauserAdded(account);
}
function _removePauser(address account) internal {
_pausers.remove(account);
emit PauserRemoved(account);
}
}pragma solidity ^0.5.0;
/**
* @title Roles
* @dev Library for managing addresses assigned to a Role.
*/
library Roles {
struct Role {
mapping (address => bool) bearer;
}
/**
* @dev Give an account access to this role.
*/
function add(Role storage role, address account) internal {
require(!has(role, account), "Roles: account already has role");
role.bearer[account] = true;
}
/**
* @dev Remove an account's access to this role.
*/
function remove(Role storage role, address account) internal {
require(has(role, account), "Roles: account does not have role");
role.bearer[account] = false;
}
/**
* @dev Check if an account has this role.
* @return bool
*/
function has(Role storage role, address account) internal view returns (bool) {
require(account != address(0), "Roles: account is the zero address");
return role.bearer[account];
}
}pragma solidity ^0.5.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 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 ERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @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).
*/
function callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(address(token).isContract(), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}pragma solidity ^0.5.0;
import "./IERC20.sol";
/**
* @dev Optional functions from the ERC20 standard.
*/
contract ERC20Detailed is IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
/**
* @dev Sets the values for `name`, `symbol`, and `decimals`. All three of
* these values are immutable: they can only be set once during
* construction.
*/
constructor (string memory name, string memory symbol, uint8 decimals) public {
_name = name;
_symbol = symbol;
_decimals = decimals;
}
/**
* @dev Returns the name of the token.
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view 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.
*
* 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 returns (uint8) {
return _decimals;
}
}// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;
interface IAaveIncentivesController {
event RewardsAccrued(address indexed user, uint256 amount);
event RewardsClaimed(address indexed user, address indexed to, uint256 amount);
event RewardsClaimed(
address indexed user,
address indexed to,
address indexed claimer,
uint256 amount
);
event ClaimerSet(address indexed user, address indexed claimer);
/*
* @dev Returns the configuration of the distribution for a certain asset
* @param asset The address of the reference asset of the distribution
* @return The asset index, the emission per second and the last updated timestamp
**/
function getAssetData(address asset)
external
view
returns (
uint256,
uint256,
uint256
);
/**
* @dev Whitelists an address to claim the rewards on behalf of another address
* @param user The address of the user
* @param claimer The address of the claimer
*/
function setClaimer(address user, address claimer) external;
/**
* @dev Returns the whitelisted claimer for a certain address (0x0 if not set)
* @param user The address of the user
* @return The claimer address
*/
function getClaimer(address user) external view returns (address);
/**
* @dev Configure assets for a certain rewards emission
* @param assets The assets to incentivize
* @param emissionsPerSecond The emission for each asset
*/
function configureAssets(address[] calldata assets, uint256[] calldata emissionsPerSecond)
external;
/**
* @dev Called by the corresponding asset on any update that affects the rewards distribution
* @param asset The address of the user
* @param userBalance The balance of the user of the asset in the lending pool
* @param totalSupply The total supply of the asset in the lending pool
**/
function handleAction(
address asset,
uint256 userBalance,
uint256 totalSupply
) external;
/**
* @dev Returns the total of rewards of an user, already accrued + not yet accrued
* @param user The address of the user
* @return The rewards
**/
function getRewardsBalance(address[] calldata assets, address user)
external
view
returns (uint256);
/**
* @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards
* @param amount Amount of rewards to claim
* @param to Address that will be receiving the rewards
* @return Rewards claimed
**/
function claimRewards(
address[] calldata assets,
uint256 amount,
address to
) external returns (uint256);
/**
* @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending rewards. The caller must
* be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager
* @param amount Amount of rewards to claim
* @param user Address to check and claim rewards
* @param to Address that will be receiving the rewards
* @return Rewards claimed
**/
function claimRewardsOnBehalf(
address[] calldata assets,
uint256 amount,
address user,
address to
) external returns (uint256);
/**
* @dev returns the unclaimed rewards of the user
* @param user the address of the user
* @return the unclaimed user rewards
*/
function getUserUnclaimedRewards(address user) external view returns (uint256);
/**
* @dev returns the unclaimed rewards of the user
* @param user the address of the user
* @param asset The asset to incentivize
* @return the user index for the asset
*/
function getUserAssetData(address user, address asset) external view returns (uint256);
/**
* @dev for backward compatibility with previous implementation of the Incentives controller
*/
function REWARD_TOKEN() external view returns (address);
/**
* @dev for backward compatibility with previous implementation of the Incentives controller
*/
function PRECISION() external view returns (uint8);
}pragma solidity ^0.5.5;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly { codehash := extcodehash(account) }
return (codehash != accountHash && codehash != 0x0);
}
/**
* @dev Converts an `address` into `address payable`. Note that this is
* simply a type cast: the actual underlying value is not changed.
*
* _Available since v2.4.0._
*/
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*
* _Available since v2.4.0._
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-call-value
(bool success, ) = recipient.call.value(amount)("");
require(success, "Address: unable to send value, recipient may have reverted");
}
}pragma solidity 0.5.16;
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "../oracles/shareOracle.sol";
import "../MyVaultV3.sol";
contract erc20Stablecoin is ReentrancyGuard, VaultNFTv3 {
shareOracle public ethPriceSource;
using SafeMath for uint256;
using SafeERC20 for IERC20;
uint256 public _minimumCollateralPercentage;
uint256 public vaultCount;
uint256 public closingFee;
uint256 public openingFee;
uint256 public treasury;
uint256 public tokenPeg;
mapping(uint256 => uint256) public vaultCollateral;
mapping(uint256 => uint256) public vaultDebt;
uint256 public debtRatio;
uint256 public gainRatio;
address public stabilityPool;
IERC20 public collateral;
IERC20 public mai;
uint256 public collateralDecimals;
event CreateVault(uint256 vaultID, address creator);
event DestroyVault(uint256 vaultID);
event TransferVault(uint256 vaultID, address from, address to);
event DepositCollateral(uint256 vaultID, uint256 amount);
event WithdrawCollateral(uint256 vaultID, uint256 amount);
event BorrowToken(uint256 vaultID, uint256 amount);
event PayBackToken(uint256 vaultID, uint256 amount, uint256 closingFee);
event LiquidateVault(uint256 vaultID, address owner, address buyer, uint256 debtRepaid, uint256 collateralLiquidated, uint256 closingFee);
mapping(address => uint256) public maticDebt;
constructor(
address ethPriceSourceAddress,
uint256 minimumCollateralPercentage,
string memory name,
string memory symbol,
address _mai,
address _collateral,
address meta,
string memory baseURI
) VaultNFTv3(name, symbol, meta, baseURI) public {
assert(ethPriceSourceAddress != address(0));
assert(minimumCollateralPercentage != 0);
// | decimals start here
closingFee=50; // 0.5%
openingFee=0; // 0.0%
ethPriceSource = shareOracle(ethPriceSourceAddress);
stabilityPool = address(0);
tokenPeg = 100000000; // $1
debtRatio = 2; // 1/2, pay back 50%
gainRatio = 1100;// /10 so 1.1
_minimumCollateralPercentage = minimumCollateralPercentage;
collateral = IERC20(_collateral);
mai = IERC20(_mai);
collateralDecimals = 8;
}
modifier onlyVaultOwner(uint256 vaultID) {
require(_exists(vaultID), "Vault does not exist");
require(ownerOf(vaultID) == msg.sender, "Vault is not owned by you");
_;
}
function getDebtCeiling() public view returns (uint256){
return mai.balanceOf(address(this));
}
function exists(uint256 vaultID) external view returns (bool){
return _exists(vaultID);
}
function getClosingFee() external view returns (uint256){
return closingFee;
}
function getOpeningFee() external view returns (uint256){
return openingFee;
}
function getTokenPriceSource() public view returns (uint256){
return tokenPeg;
}
function getEthPriceSource() public view returns (uint256){
(,int256 price,,,) = ethPriceSource.latestRoundData();
return uint256(price);
}
function calculateCollateralProperties(uint256 collateral, uint256 debt) private view returns (uint256, uint256) {
assert(getEthPriceSource() != 0);
assert(getTokenPriceSource() != 0);
uint256 collateralValue = collateral.mul(getEthPriceSource() );
assert(collateralValue >= collateral);
uint256 debtValue = debt.mul(getTokenPriceSource());
assert(debtValue >= debt);
uint256 collateralValueTimes100 = collateralValue.mul(100);
assert(collateralValueTimes100 > collateralValue);
return (collateralValueTimes100, debtValue);
}
function isValidCollateral(uint256 collateral, uint256 debt) private view returns (bool) {
(uint256 collateralValueTimes100, uint256 debtValue) = calculateCollateralProperties(collateral, debt);
uint256 collateralPercentage = collateralValueTimes100.div(debtValue);
return collateralPercentage >= _minimumCollateralPercentage;
}
function createVault() external returns (uint256) {
uint256 id = vaultCount;
vaultCount = vaultCount.add(1);
assert(vaultCount >= id);
_mint(msg.sender,id);
emit CreateVault(id, msg.sender);
return id;
}
function destroyVault(uint256 vaultID) external onlyVaultOwner(vaultID) nonReentrant {
require(vaultDebt[vaultID] == 0, "Vault has outstanding debt");
if(vaultCollateral[vaultID]!=0) {
// withdraw leftover collateral
collateral.safeTransfer(ownerOf(vaultID), vaultCollateral[vaultID]);
}
_burn(vaultID);
delete vaultCollateral[vaultID];
delete vaultDebt[vaultID];
emit DestroyVault(vaultID);
}
function depositCollateral(uint256 vaultID, uint256 amount) external {
collateral.safeTransferFrom(msg.sender, address(this), amount);
uint256 newCollateral = vaultCollateral[vaultID].add(amount);
assert(newCollateral >= vaultCollateral[vaultID]);
vaultCollateral[vaultID] = newCollateral;
emit DepositCollateral(vaultID, amount);
}
function withdrawCollateral(uint256 vaultID, uint256 amount) external onlyVaultOwner(vaultID) nonReentrant {
require(vaultCollateral[vaultID] >= amount, "Vault does not have enough collateral");
uint256 newCollateral = vaultCollateral[vaultID].sub(amount);
if(vaultDebt[vaultID] != 0) {
require(isValidCollateral(newCollateral, vaultDebt[vaultID]), "Withdrawal would put vault below minimum collateral percentage");
}
vaultCollateral[vaultID] = newCollateral;
collateral.safeTransfer(msg.sender, amount);
emit WithdrawCollateral(vaultID, amount);
}
function borrowToken(uint256 vaultID, uint256 amount) external onlyVaultOwner(vaultID) {
require(amount > 0, "Must borrow non-zero amount");
require(amount <= getDebtCeiling(), "borrowToken: Cannot mint over available supply.");
uint256 newDebt = vaultDebt[vaultID].add(amount);
assert(newDebt > vaultDebt[vaultID]);
require(isValidCollateral(vaultCollateral[vaultID], newDebt), "Borrow would put vault below minimum collateral percentage");
vaultDebt[vaultID] = newDebt;
// mai
mai.safeTransfer(msg.sender, amount);
emit BorrowToken(vaultID, amount);
}
function payBackToken(uint256 vaultID, uint256 amount) external {
require(mai.balanceOf(msg.sender) >= amount, "Token balance too low");
require(vaultDebt[vaultID] >= amount, "Vault debt less than amount to pay back");
uint256 _closingFee = (amount.mul(closingFee).mul(getTokenPriceSource())).div(getEthPriceSource().mul(10000));
//mai
mai.safeTransferFrom(msg.sender, address(this), amount);
vaultDebt[vaultID] = vaultDebt[vaultID].sub(amount);
vaultCollateral[vaultID]=vaultCollateral[vaultID].sub(_closingFee);
vaultCollateral[treasury]=vaultCollateral[treasury].add(_closingFee);
emit PayBackToken(vaultID, amount, _closingFee);
}
function getPaid() public nonReentrant {
require(maticDebt[msg.sender]!=0, "Don't have anything for you.");
uint256 amount = maticDebt[msg.sender];
maticDebt[msg.sender]=0;
collateral.safeTransfer(msg.sender, amount);
}
function checkCost(uint256 vaultID) public view returns (uint256) {
if(vaultCollateral[vaultID] == 0 || vaultDebt[vaultID]==0 || !checkLiquidation(vaultID) ){
return 0;
}
(uint256 collateralValueTimes100, uint256 debtValue) = calculateCollateralProperties(vaultCollateral[vaultID], vaultDebt[vaultID]);
if(debtValue==0){
return 0;
}
uint256 collateralPercentage = collateralValueTimes100.div(debtValue);
debtValue = debtValue.div(10 ** collateralDecimals);
uint256 halfDebt = debtValue.div(debtRatio); //debtRatio (2)
return(halfDebt);
}
function checkExtract(uint256 vaultID) public view returns (uint256) {
if(vaultCollateral[vaultID] == 0|| !checkLiquidation(vaultID) ) {
return 0;
}
(uint256 collateralValueTimes100, uint256 debtValue) = calculateCollateralProperties(vaultCollateral[vaultID], vaultDebt[vaultID]);
uint256 halfDebt = debtValue.div(debtRatio); //debtRatio (2)
if(halfDebt==0){
return 0;
}
return halfDebt.mul(gainRatio).div(1000).div(getEthPriceSource());
}
function checkCollateralPercentage(uint256 vaultID) public view returns(uint256){
require(_exists(vaultID), "Vault does not exist");
if(vaultCollateral[vaultID] == 0 || vaultDebt[vaultID]==0){
return 0;
}
(uint256 collateralValueTimes100, uint256 debtValue) = calculateCollateralProperties(vaultCollateral[vaultID], vaultDebt[vaultID]);
return collateralValueTimes100.div(debtValue);
}
function checkLiquidation(uint256 vaultID) public view returns (bool) {
require(_exists(vaultID), "Vault does not exist");
if(vaultCollateral[vaultID] == 0 || vaultDebt[vaultID]==0){
return false;
}
(uint256 collateralValueTimes100, uint256 debtValue) = calculateCollateralProperties(vaultCollateral[vaultID], vaultDebt[vaultID]);
uint256 collateralPercentage = collateralValueTimes100.div(debtValue);
if(collateralPercentage < _minimumCollateralPercentage){
return true;
} else{
return false;
}
}
function liquidateVault(uint256 vaultID) external {
require(_exists(vaultID), "Vault does not exist");
require(stabilityPool==address(0) || msg.sender == stabilityPool, "liquidation is disabled for public");
(uint256 collateralValueTimes100, uint256 debtValue) = calculateCollateralProperties(vaultCollateral[vaultID], vaultDebt[vaultID]);
uint256 collateralPercentage = collateralValueTimes100.div(debtValue);
require(collateralPercentage < _minimumCollateralPercentage, "Vault is not below minimum collateral percentage");
debtValue = debtValue.div(10 ** collateralDecimals);
uint256 halfDebt = debtValue.div(debtRatio); //debtRatio (2)
require(mai.balanceOf(msg.sender) >= halfDebt, "Token balance too low to pay off outstanding debt");
//mai
mai.safeTransferFrom(msg.sender, address(this), halfDebt);
uint256 maticExtract = checkExtract(vaultID);
vaultDebt[vaultID] = vaultDebt[vaultID].sub(halfDebt); // we paid back half of its debt.
uint256 _closingFee = (halfDebt.mul(closingFee).mul(getTokenPriceSource()) ).div(getEthPriceSource().mul(10000));
vaultCollateral[vaultID]=vaultCollateral[vaultID].sub(_closingFee);
vaultCollateral[treasury]=vaultCollateral[treasury].add(_closingFee);
// deduct the amount from the vault's collateral
vaultCollateral[vaultID] = vaultCollateral[vaultID].sub(maticExtract);
// let liquidator take the collateral
maticDebt[msg.sender] = maticDebt[msg.sender].add(maticExtract);
emit LiquidateVault(vaultID, ownerOf(vaultID), msg.sender, halfDebt, maticExtract, _closingFee);
}
}pragma solidity ^0.5.0;
/**
* @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 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].
*
* _Since v2.5.0:_ this module is now much more gas efficient, given net gas
* metering changes introduced in the Istanbul hardfork.
*/
contract ReentrancyGuard {
bool private _notEntered;
constructor () internal {
// Storing an initial 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 percetange 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.
_notEntered = true;
}
/**
* @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() {
// On the first call to nonReentrant, _notEntered will be true
require(_notEntered, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_notEntered = false;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_notEntered = true;
}
}// contracts/shareOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.5.16;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "../PriceSource.sol";
contract shareOracle {
using SafeMath for uint256;
// this should just be vieweing a chainlink oracle's price
// then it would check the balances of that contract in the token that its checking.
// it should return the price per token based on the camToken's balance
PriceSource public priceSource;
ERC20 public underlying;
ERC20 public shares;
uint256 public fallbackPrice;
event FallbackPrice(
uint80 roundId,
int256 price,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
// price Source gives underlying price per token
// shareToken should hold underlying and we need to calculate a PPS
constructor(address _priceSource, address _underlying, address _shares) public {
priceSource = PriceSource(_priceSource);
underlying = ERC20(_underlying);
shares = ERC20(_shares);
}
// to integrate we just need to inherit that same interface the other page uses.
function latestRoundData() public view
returns
(uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
){
// we should passthrough all the data from the chainlink call. This would allow for transparency over the information sent.
// Then we can filter as needed but this could be a cool standard we use for share-based tokens (like the compounding tokens)
// check how much underlying does the share contract have.
// underlying.balanceOf(address(shares))
// then we check how many shares do we have outstanding
// shares.totalSupply()
// now we divide the total value of underlying held in the contract by the number of tokens
(
uint80 roundId,
int256 price,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
) = priceSource.latestRoundData();
uint256 _price;
if(price>0){
_price=uint256(price);
} else {
_price=fallbackPrice;
}
uint256 newPrice = ((underlying.balanceOf(address(shares))).mul(_price).div(shares.totalSupply()));
return(roundId, int256(newPrice), startedAt, updatedAt, answeredInRound);
}
function getUnderlying() public view returns (uint256, uint256) {
return (underlying.balanceOf(address(shares)), shares.totalSupply());
}
function updateFallbackPrice() public {
(
uint80 roundId,
int256 price,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
) = priceSource.latestRoundData();
if (price > 0) {
fallbackPrice = uint256(price);
emit FallbackPrice(roundId,price,startedAt,updatedAt,answeredInRound);
}
}
}// contracts/MyVaultNFT.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.5.16;
import "@openzeppelin/contracts/token/ERC721/ERC721Full.sol";
import "./interfaces/IVaultMetaProvider.sol";
import "./interfaces/IVaultMetaRegistry.sol";
contract VaultNFTv3 is ERC721Full {
address public _meta;
string public base;
constructor(string memory name, string memory symbol, address meta, string memory baseURI)
public
ERC721Full(name, symbol)
{
_meta = meta;
base=baseURI;
}
function tokenURI(uint256 tokenId) public view returns (string memory) {
require(_exists(tokenId));
IVaultMetaRegistry registry = IVaultMetaRegistry(_meta);
IVaultMetaProvider provider = IVaultMetaProvider(registry.getMetaProvider(address(this)));
return bytes(base).length > 0 ? string(abi.encodePacked(base, provider.getTokenURI(address(this), tokenId))) : "";
}
}pragma solidity ^0.5.0;
interface PriceSource {
function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}pragma solidity ^0.5.0;
import "./ERC721.sol";
import "./ERC721Enumerable.sol";
import "./ERC721Metadata.sol";
/**
* @title Full ERC721 Token
* @dev This implementation includes all the required and some optional functionality of the ERC721 standard
* Moreover, it includes approve all functionality using operator terminology.
*
* See https://eips.ethereum.org/EIPS/eip-721
*/
contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata {
constructor (string memory name, string memory symbol) public ERC721Metadata(name, symbol) {
// solhint-disable-previous-line no-empty-blocks
}
}pragma solidity 0.5.16;
interface IVaultMetaProvider {
function getTokenURI(address vault_address, uint256 tokenId) external view returns (string memory);
function getBaseURI() external view returns (string memory);
}pragma solidity 0.5.16;
interface IVaultMetaRegistry {
function getMetaProvider(address vault_address) external view returns (address);
}pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
import "../../drafts/Counters.sol";
import "../../introspection/ERC165.sol";
/**
* @title ERC721 Non-Fungible Token Standard basic implementation
* @dev see https://eips.ethereum.org/EIPS/eip-721
*/
contract ERC721 is Context, ERC165, IERC721 {
using SafeMath for uint256;
using Address for address;
using Counters for Counters.Counter;
// Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
// which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
// Mapping from token ID to owner
mapping (uint256 => address) private _tokenOwner;
// Mapping from token ID to approved address
mapping (uint256 => address) private _tokenApprovals;
// Mapping from owner to number of owned token
mapping (address => Counters.Counter) private _ownedTokensCount;
// Mapping from owner to operator approvals
mapping (address => mapping (address => bool)) private _operatorApprovals;
/*
* bytes4(keccak256('balanceOf(address)')) == 0x70a08231
* bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
* bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
* bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
* bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
* bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
* bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
*
* => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
* 0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
*/
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
constructor () public {
// register the supported interfaces to conform to ERC721 via ERC165
_registerInterface(_INTERFACE_ID_ERC721);
}
/**
* @dev Gets the balance of the specified address.
* @param owner address to query the balance of
* @return uint256 representing the amount owned by the passed address
*/
function balanceOf(address owner) public view returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _ownedTokensCount[owner].current();
}
/**
* @dev Gets the owner of the specified token ID.
* @param tokenId uint256 ID of the token to query the owner of
* @return address currently marked as the owner of the given token ID
*/
function ownerOf(uint256 tokenId) public view returns (address) {
address owner = _tokenOwner[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev Approves another address to transfer the given token ID
* The zero address indicates there is no approved address.
* There can only be one approved address per token at a given time.
* Can only be called by the token owner or an approved operator.
* @param to address to be approved for the given token ID
* @param tokenId uint256 ID of the token to be approved
*/
function approve(address to, uint256 tokenId) public {
address owner = ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_tokenApprovals[tokenId] = to;
emit Approval(owner, to, tokenId);
}
/**
* @dev Gets the approved address for a token ID, or zero if no address set
* Reverts if the token ID does not exist.
* @param tokenId uint256 ID of the token to query the approval of
* @return address currently approved for the given token ID
*/
function getApproved(uint256 tokenId) public view returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev Sets or unsets the approval of a given operator
* An operator is allowed to transfer all tokens of the sender on their behalf.
* @param to operator address to set the approval
* @param approved representing the status of the approval to be set
*/
function setApprovalForAll(address to, bool approved) public {
require(to != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][to] = approved;
emit ApprovalForAll(_msgSender(), to, approved);
}
/**
* @dev Tells whether an operator is approved by a given owner.
* @param owner owner address which you want to query the approval of
* @param operator operator address which you want to query the approval of
* @return bool whether the given operator is approved by the given owner
*/
function isApprovedForAll(address owner, address operator) public view returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev Transfers the ownership of a given token ID to another address.
* Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
* Requires the msg.sender to be the owner, approved, or operator.
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function transferFrom(address from, address to, uint256 tokenId) public {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transferFrom(from, to, tokenId);
}
/**
* @dev Safely transfers the ownership of a given token ID to another address
* If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* Requires the msg.sender to be the owner, approved, or operator
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev Safely transfers the ownership of a given token ID to another address
* If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* Requires the _msgSender() to be the owner, approved, or operator
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes data to send along with a safe transfer check
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransferFrom(from, to, tokenId, _data);
}
/**
* @dev Safely transfers the ownership of a given token ID to another address
* If the target address is a contract, it must implement `onERC721Received`,
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* Requires the msg.sender to be the owner, approved, or operator
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes data to send along with a safe transfer check
*/
function _safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) internal {
_transferFrom(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether the specified token exists.
* @param tokenId uint256 ID of the token to query the existence of
* @return bool whether the token exists
*/
function _exists(uint256 tokenId) internal view returns (bool) {
address owner = _tokenOwner[tokenId];
return owner != address(0);
}
/**
* @dev Returns whether the given spender can transfer a given token ID.
* @param spender address of the spender to query
* @param tokenId uint256 ID of the token to be transferred
* @return bool whether the msg.sender is approved for the given token ID,
* is an operator of the owner, or is the owner of the token
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Internal function to safely mint a new token.
* Reverts if the given token ID already exists.
* If the target address is a contract, it must implement `onERC721Received`,
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* @param to The address that will own the minted token
* @param tokenId uint256 ID of the token to be minted
*/
function _safeMint(address to, uint256 tokenId) internal {
_safeMint(to, tokenId, "");
}
/**
* @dev Internal function to safely mint a new token.
* Reverts if the given token ID already exists.
* If the target address is a contract, it must implement `onERC721Received`,
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* @param to The address that will own the minted token
* @param tokenId uint256 ID of the token to be minted
* @param _data bytes data to send along with a safe transfer check
*/
function _safeMint(address to, uint256 tokenId, bytes memory _data) internal {
_mint(to, tokenId);
require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Internal function to mint a new token.
* Reverts if the given token ID already exists.
* @param to The address that will own the minted token
* @param tokenId uint256 ID of the token to be minted
*/
function _mint(address to, uint256 tokenId) internal {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_tokenOwner[tokenId] = to;
_ownedTokensCount[to].increment();
emit Transfer(address(0), to, tokenId);
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* Deprecated, use {_burn} instead.
* @param owner owner of the token to burn
* @param tokenId uint256 ID of the token being burned
*/
function _burn(address owner, uint256 tokenId) internal {
require(ownerOf(tokenId) == owner, "ERC721: burn of token that is not own");
_clearApproval(tokenId);
_ownedTokensCount[owner].decrement();
_tokenOwner[tokenId] = address(0);
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* @param tokenId uint256 ID of the token being burned
*/
function _burn(uint256 tokenId) internal {
_burn(ownerOf(tokenId), tokenId);
}
/**
* @dev Internal function to transfer ownership of a given token ID to another address.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function _transferFrom(address from, address to, uint256 tokenId) internal {
require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_clearApproval(tokenId);
_ownedTokensCount[from].decrement();
_ownedTokensCount[to].increment();
_tokenOwner[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* This is an internal detail of the `ERC721` contract and its use is deprecated.
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
internal returns (bool)
{
if (!to.isContract()) {
return true;
}
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = to.call(abi.encodeWithSelector(
IERC721Receiver(to).onERC721Received.selector,
_msgSender(),
from,
tokenId,
_data
));
if (!success) {
if (returndata.length > 0) {
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert("ERC721: transfer to non ERC721Receiver implementer");
}
} else {
bytes4 retval = abi.decode(returndata, (bytes4));
return (retval == _ERC721_RECEIVED);
}
}
/**
* @dev Private function to clear current approval of a given token ID.
* @param tokenId uint256 ID of the token to be transferred
*/
function _clearApproval(uint256 tokenId) private {
if (_tokenApprovals[tokenId] != address(0)) {
_tokenApprovals[tokenId] = address(0);
}
}
}pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./IERC721Enumerable.sol";
import "./ERC721.sol";
import "../../introspection/ERC165.sol";
/**
* @title ERC-721 Non-Fungible Token with optional enumeration extension logic
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
contract ERC721Enumerable is Context, ERC165, ERC721, IERC721Enumerable {
// Mapping from owner to list of owned token IDs
mapping(address => uint256[]) private _ownedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] private _allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
/*
* bytes4(keccak256('totalSupply()')) == 0x18160ddd
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
* bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
*
* => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
*/
bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
/**
* @dev Constructor function.
*/
constructor () public {
// register the supported interface to conform to ERC721Enumerable via ERC165
_registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
}
/**
* @dev Gets the token ID at a given index of the tokens list of the requested owner.
* @param owner address owning the tokens list to be accessed
* @param index uint256 representing the index to be accessed of the requested tokens list
* @return uint256 token ID at the given index of the tokens list owned by the requested address
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) {
require(index < balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev Gets the total amount of tokens stored by the contract.
* @return uint256 representing the total amount of tokens
*/
function totalSupply() public view returns (uint256) {
return _allTokens.length;
}
/**
* @dev Gets the token ID at a given index of all the tokens in this contract
* Reverts if the index is greater or equal to the total number of tokens.
* @param index uint256 representing the index to be accessed of the tokens list
* @return uint256 token ID at the given index of the tokens list
*/
function tokenByIndex(uint256 index) public view returns (uint256) {
require(index < totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
/**
* @dev Internal function to transfer ownership of a given token ID to another address.
* As opposed to transferFrom, this imposes no restrictions on msg.sender.
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function _transferFrom(address from, address to, uint256 tokenId) internal {
super._transferFrom(from, to, tokenId);
_removeTokenFromOwnerEnumeration(from, tokenId);
_addTokenToOwnerEnumeration(to, tokenId);
}
/**
* @dev Internal function to mint a new token.
* Reverts if the given token ID already exists.
* @param to address the beneficiary that will own the minted token
* @param tokenId uint256 ID of the token to be minted
*/
function _mint(address to, uint256 tokenId) internal {
super._mint(to, tokenId);
_addTokenToOwnerEnumeration(to, tokenId);
_addTokenToAllTokensEnumeration(tokenId);
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* Deprecated, use {ERC721-_burn} instead.
* @param owner owner of the token to burn
* @param tokenId uint256 ID of the token being burned
*/
function _burn(address owner, uint256 tokenId) internal {
super._burn(owner, tokenId);
_removeTokenFromOwnerEnumeration(owner, tokenId);
// Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund
_ownedTokensIndex[tokenId] = 0;
_removeTokenFromAllTokensEnumeration(tokenId);
}
/**
* @dev Gets the list of token IDs of the requested owner.
* @param owner address owning the tokens
* @return uint256[] List of token IDs owned by the requested address
*/
function _tokensOfOwner(address owner) internal view returns (uint256[] storage) {
return _ownedTokens[owner];
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
_ownedTokensIndex[tokenId] = _ownedTokens[to].length;
_ownedTokens[to].push(tokenId);
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
_ownedTokens[from].length--;
// Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by
// lastTokenId, or just over the end of the array if the token was the last one).
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length.sub(1);
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
_allTokens.length--;
_allTokensIndex[tokenId] = 0;
}
}pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./ERC721.sol";
import "./IERC721Metadata.sol";
import "../../introspection/ERC165.sol";
contract ERC721Metadata is Context, ERC165, ERC721, IERC721Metadata {
// Token name
string private _name;
// Token symbol
string private _symbol;
// Base URI
string private _baseURI;
// Optional mapping for token URIs
mapping(uint256 => string) private _tokenURIs;
/*
* bytes4(keccak256('name()')) == 0x06fdde03
* bytes4(keccak256('symbol()')) == 0x95d89b41
* bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
*
* => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
*/
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
/**
* @dev Constructor function
*/
constructor (string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
// register the supported interfaces to conform to ERC721 via ERC165
_registerInterface(_INTERFACE_ID_ERC721_METADATA);
}
/**
* @dev Gets the token name.
* @return string representing the token name
*/
function name() external view returns (string memory) {
return _name;
}
/**
* @dev Gets the token symbol.
* @return string representing the token symbol
*/
function symbol() external view returns (string memory) {
return _symbol;
}
/**
* @dev Returns the URI for a given token ID. May return an empty string.
*
* If the token's URI is non-empty and a base URI was set (via
* {_setBaseURI}), it will be added to the token ID's URI as a prefix.
*
* Reverts if the token ID does not exist.
*/
function tokenURI(uint256 tokenId) external view returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
// Even if there is a base URI, it is only appended to non-empty token-specific URIs
if (bytes(_tokenURI).length == 0) {
return "";
} else {
// abi.encodePacked is being used to concatenate strings
return string(abi.encodePacked(_baseURI, _tokenURI));
}
}
/**
* @dev Internal function to set the token URI for a given token.
*
* Reverts if the token ID does not exist.
*
* TIP: if all token IDs share a prefix (e.g. if your URIs look like
* `http://api.myproject.com/token/<id>`), use {_setBaseURI} to store
* it and save gas.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
/**
* @dev Internal function to set the base URI for all token IDs. It is
* automatically added as a prefix to the value returned in {tokenURI}.
*
* _Available since v2.5.0._
*/
function _setBaseURI(string memory baseURI) internal {
_baseURI = baseURI;
}
/**
* @dev Returns the base URI set via {_setBaseURI}. This will be
* automatically added as a preffix in {tokenURI} to each token's URI, when
* they are non-empty.
*
* _Available since v2.5.0._
*/
function baseURI() external view returns (string memory) {
return _baseURI;
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* Deprecated, use _burn(uint256) instead.
* @param owner owner of the token to burn
* @param tokenId uint256 ID of the token being burned by the msg.sender
*/
function _burn(address owner, uint256 tokenId) internal {
super._burn(owner, tokenId);
// Clear metadata (if any)
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
}
}pragma solidity ^0.5.0;
import "../../introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
contract IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of NFTs in `owner`'s account.
*/
function balanceOf(address owner) public view returns (uint256 balance);
/**
* @dev Returns the owner of the NFT specified by `tokenId`.
*/
function ownerOf(uint256 tokenId) public view returns (address owner);
/**
* @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
* another (`to`).
*
*
*
* Requirements:
* - `from`, `to` cannot be zero.
* - `tokenId` must be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this
* NFT by either {approve} or {setApprovalForAll}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public;
/**
* @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
* another (`to`).
*
* Requirements:
* - If the caller is not `from`, it must be approved to move this NFT by
* either {approve} or {setApprovalForAll}.
*/
function transferFrom(address from, address to, uint256 tokenId) public;
function approve(address to, uint256 tokenId) public;
function getApproved(uint256 tokenId) public view returns (address operator);
function setApprovalForAll(address operator, bool _approved) public;
function isApprovedForAll(address owner, address operator) public view returns (bool);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
}pragma solidity ^0.5.0;
import "../math/SafeMath.sol";
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
* Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}
* overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
* directly accessed.
*/
library Counters {
using SafeMath for uint256;
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
// The {SafeMath} overflow check can be skipped here, see the comment at the top
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value.sub(1);
}
}pragma solidity ^0.5.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts may inherit from this and call {_registerInterface} to declare
* their support of an interface.
*/
contract ERC165 is IERC165 {
/*
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
*/
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
/**
* @dev Mapping of interface ids to whether or not it's supported.
*/
mapping(bytes4 => bool) private _supportedInterfaces;
constructor () internal {
// Derived contracts need only register support for their own interfaces,
// we register support for ERC165 itself here
_registerInterface(_INTERFACE_ID_ERC165);
}
/**
* @dev See {IERC165-supportsInterface}.
*
* Time complexity O(1), guaranteed to always use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool) {
return _supportedInterfaces[interfaceId];
}
/**
* @dev Registers the contract as an implementer of the interface defined by
* `interfaceId`. Support of the actual ERC165 interface is automatic and
* registering its interface id is not required.
*
* See {IERC165-supportsInterface}.
*
* Requirements:
*
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
*/
function _registerInterface(bytes4 interfaceId) internal {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}pragma solidity ^0.5.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);
}pragma solidity ^0.5.0;
import "./IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
contract IERC721Enumerable is IERC721 {
function totalSupply() public view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256 tokenId);
function tokenByIndex(uint256 index) public view returns (uint256);
}pragma solidity ^0.5.0;
import "./IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
contract IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}{
"optimizer": {
"enabled": true,
"runs": 1000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"AssetUnZapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"AssetZapped","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":"address","name":"account","type":"address"}],"name":"PauserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"PauserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"constant":false,"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_amAsset","type":"address"},{"internalType":"address","name":"_camAsset","type":"address"},{"internalType":"address","name":"_camAssetVault","type":"address"}],"name":"addChainToWhiteList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addPauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_amAsset","type":"address"},{"internalType":"address","name":"_camAsset","type":"address"},{"internalType":"address","name":"_camAssetVault","type":"address"}],"name":"camZapFromVault","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_amAsset","type":"address"},{"internalType":"address","name":"_camAsset","type":"address"},{"internalType":"address","name":"_camAssetVault","type":"address"}],"name":"camZapToVault","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isPauser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"contract IAToken","name":"amToken","type":"address"},{"internalType":"contract camToken","name":"_camToken","type":"address"},{"internalType":"contract erc20QiStablecoin","name":"camTokenVault","type":"address"}],"internalType":"struct camZapper.CamChain","name":"chain","type":"tuple"}],"name":"isWhiteListed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"pauseZapping","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_amAsset","type":"address"},{"internalType":"address","name":"_camAsset","type":"address"},{"internalType":"address","name":"_camAssetVault","type":"address"}],"name":"removeChainFromWhiteList","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renouncePauser","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"resumeZapping","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052600480546001600160a01b031916738dff5e27ea6b7ac08ebfdf9eb090f32ee9a30fcf17905560006200003f6001600160e01b03620000bf16565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350620000af620000a06001600160e01b03620000bf16565b6001600160e01b03620000c316565b6002805460ff1916905562000277565b3390565b620000de8160016200011560201b620018ef1790919060201c565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b6200012a82826001600160e01b036200017816565b15620001535760405162461bcd60e51b81526004016200014a9062000244565b60405180910390fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b60006001600160a01b038216620001a35760405162461bcd60e51b81526004016200014a906200025c565b506001600160a01b03166000908152602091909152604090205460ff1690565b6000620001d2601f836200026e565b7f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500815260200192915050565b60006200020d6022836200026e565b7f526f6c65733a206163636f756e7420697320746865207a65726f206164647265815261737360f01b602082015260400192915050565b602080825281016200025681620001c3565b92915050565b602080825281016200025681620001fe565b90815260200190565b6125eb80620002876000396000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c8063715018a6116100b25780638f32d59b11610081578063d0ae34de11610066578063d0ae34de1461023f578063db0baaa914610247578063f2fde38b1461025a57610136565b80638f32d59b14610224578063a809e09f1461022c57610136565b8063715018a6146101ec57806382dc1ec4146101f45780638456cb59146102075780638da5cb5b1461020f57610136565b806346fbf68e116101095780636b4be2a7116100ee5780636b4be2a7146101b15780636e2e90c2146101c45780636ef8d66d146101e457610136565b806346fbf68e146101895780635c975abb146101a957610136565b8063102c32f21461013b578063150b7a02146101505780631e3ce73a146101795780633f4ba83a14610181575b600080fd5b61014e610149366004611acf565b61026d565b005b61016361015e366004611b30565b61036f565b6040516101709190612319565b60405180910390f35b61014e610399565b61014e6103c7565b61019c610197366004611a93565b61045a565b604051610170919061230b565b61019c610473565b61019c6101bf366004611bbb565b61047c565b6101d76101d2366004611bf7565b6104ad565b6040516101709190612438565b61014e610525565b61014e610535565b61014e610202366004611a93565b6105b0565b61014e6105e3565b610217610663565b604051610170919061220b565b61019c610672565b6101d761023a366004611bf7565b610696565b61014e610702565b61014e610255366004611acf565b61072e565b61014e610268366004611a93565b6107ed565b610275610672565b61029a5760405162461bcd60e51b8152600401610291906123d8565b60405180910390fd5b6102a2611967565b6102ae8585858561081a565b90506102b98161047c565b6103505780600360006102cb84610853565b815260208082019290925260409081016000208351815473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b03928316178355938501516001830180548616918316919091179055918401516002820180548516918416919091179055606090930151600390930180549092169216919091179055610368565b60405162461bcd60e51b8152600401610291906123b8565b5050505050565b7f150b7a02000000000000000000000000000000000000000000000000000000005b949350505050565b6103a1610672565b6103bd5760405162461bcd60e51b8152600401610291906123d8565b6103c56105e3565b565b6103d2610197610899565b6103ee5760405162461bcd60e51b815260040161029190612358565b60025460ff166104105760405162461bcd60e51b815260040161029190612338565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa610443610899565b6040516104509190612219565b60405180910390a1565b600061046d60018363ffffffff61089d16565b92915050565b60025460ff1690565b60008060038161048b85610853565b81526020810191909152604001600020546001600160a01b0316141592915050565b60025460009060ff16156104d35760405162461bcd60e51b815260040161029190612378565b6104db611967565b6104e78686868661081a565b90506104f28161047c565b61050e5760405162461bcd60e51b8152600401610291906123a8565b6105198888836108e5565b98975050505050505050565b6103c5610530610899565b611132565b61053d610672565b6105595760405162461bcd60e51b8152600401610291906123d8565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b6105bb610197610899565b6105d75760405162461bcd60e51b815260040161029190612358565b6105e08161117a565b50565b6105ee610197610899565b61060a5760405162461bcd60e51b815260040161029190612358565b60025460ff161561062d5760405162461bcd60e51b815260040161029190612378565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610443610899565b6000546001600160a01b031690565b600080546001600160a01b0316610687610899565b6001600160a01b031614905090565b60025460009060ff16156106bc5760405162461bcd60e51b815260040161029190612378565b6106c4611967565b6106d08686868661081a565b90506106db8161047c565b6106f75760405162461bcd60e51b8152600401610291906123a8565b6105198888836111c2565b61070a610672565b6107265760405162461bcd60e51b8152600401610291906123d8565b6103c56103c7565b610736610672565b6107525760405162461bcd60e51b8152600401610291906123d8565b61075a611967565b6107668585858561081a565b90506107718161047c565b156107d5576003600061078383610853565b81526020810191909152604001600020805473ffffffffffffffffffffffffffffffffffffffff1990811682556001820180548216905560028201805482169055600390910180549091169055610368565b60405162461bcd60e51b8152600401610291906123f8565b6107f5610672565b6108115760405162461bcd60e51b8152600401610291906123d8565b6105e0816117d7565b610822611967565b61082a611967565b6001600160a01b0395861681529385166020850152509083166040830152909116606082015290565b6000816000015182602001518360400151846060015160405160200161087c94939291906121c3565b604051602081830303815290604052805190602001209050919050565b3390565b60006001600160a01b0382166108c55760405162461bcd60e51b8152600401610291906123e8565b506001600160a01b03166000908152602091909152604090205460ff1690565b60025460009060ff161561090b5760405162461bcd60e51b815260040161029190612378565b6000841161092b5760405162461bcd60e51b815260040161029190612418565b60608201516040517f081812fc00000000000000000000000000000000000000000000000000000000815230916001600160a01b03169063081812fc90610976908790600401612438565b60206040518083038186803b15801561098e57600080fd5b505afa1580156109a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506109c69190810190611ab1565b6001600160a01b0316146109ec5760405162461bcd60e51b815260040161029190612428565b60608201516040517f6352211e00000000000000000000000000000000000000000000000000000000815233916001600160a01b031690636352211e90610a37908790600401612438565b60206040518083038186803b158015610a4f57600080fd5b505afa158015610a63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610a879190810190611ab1565b6001600160a01b031614610aad5760405162461bcd60e51b8152600401610291906123c8565b81604001516001600160a01b031663095ea7b38360600151866040518363ffffffff1660e01b8152600401610ae39291906122a0565b602060405180830381600087803b158015610afd57600080fd5b505af1158015610b11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b359190810190611b9d565b5081606001516001600160a01b03166342842e0e3330866040518463ffffffff1660e01b8152600401610b6a93929190612242565b600060405180830381600087803b158015610b8457600080fd5b505af1158015610b98573d6000803e3d6000fd5b50505050600082604001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610bce919061220b565b60206040518083038186803b158015610be657600080fd5b505afa158015610bfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610c1e9190810190611bd9565b60608401516040517f767a7b050000000000000000000000000000000000000000000000000000000081529192506001600160a01b03169063767a7b0590610c6c9087908990600401612446565b600060405180830381600087803b158015610c8657600080fd5b505af1158015610c9a573d6000803e3d6000fd5b505050506000610d308285604001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610cd4919061220b565b60206040518083038186803b158015610cec57600080fd5b505afa158015610d00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610d249190810190611bd9565b9063ffffffff61186516565b606085015160405163095ea7b360e01b81529192506001600160a01b03169063095ea7b390610d65903390899060040161226a565b600060405180830381600087803b158015610d7f57600080fd5b505af1158015610d93573d6000803e3d6000fd5b5050505083606001516001600160a01b03166342842e0e3033886040518463ffffffff1660e01b8152600401610dcb93929190612285565b600060405180830381600087803b158015610de557600080fd5b505af1158015610df9573d6000803e3d6000fd5b50505050600084602001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610e2f919061220b565b60206040518083038186803b158015610e4757600080fd5b505afa158015610e5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610e7f9190810190611bd9565b905084604001516001600160a01b03166367dfd4c9836040518263ffffffff1660e01b8152600401610eb19190612438565b600060405180830381600087803b158015610ecb57600080fd5b505af1158015610edf573d6000803e3d6000fd5b505050506000610f198287602001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610cd4919061220b565b60208701516004805460405163095ea7b360e01b81529394506001600160a01b039283169363095ea7b393610f53939216918691016122a0565b602060405180830381600087803b158015610f6d57600080fd5b505af1158015610f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610fa59190810190611b9d565b506004805487516040517f69328dec0000000000000000000000000000000000000000000000000000000081526001600160a01b03909216926369328dec92610ff3929186913391016122ae565b602060405180830381600087803b15801561100d57600080fd5b505af1158015611021573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506110459190810190611bd9565b508786600001516001600160a01b03167f3e47dad970f8ef4dc53e82b8ac03c2623f966d35e7424ca85ca183e61f0b5970896040516110849190612438565b60405180910390a385516040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906370a08231906110d4903390600401612219565b60206040518083038186803b1580156110ec57600080fd5b505afa158015611100573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506111249190810190611bd9565b9450505050505b9392505050565b61114360018263ffffffff6118a716565b6040516001600160a01b038216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b61118b60018263ffffffff6118ef16565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b60025460009060ff16156111e85760405162461bcd60e51b815260040161029190612378565b600084116112085760405162461bcd60e51b815260040161029190612408565b81516040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526000916001600160a01b03169063dd62ed3e906112539033903090600401612227565b60206040518083038186803b15801561126b57600080fd5b505afa15801561127f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112a39190810190611bd9565b9050848110156112c55760405162461bcd60e51b815260040161029190612388565b82516040516323b872dd60e01b81526001600160a01b03909116906323b872dd906112f890339030908a90600401612242565b602060405180830381600087803b15801561131257600080fd5b505af1158015611326573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061134a9190810190611b9d565b5082516004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b39361138093909116918a91016122a0565b602060405180830381600087803b15801561139a57600080fd5b505af11580156113ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113d29190810190611b9d565b506004805484516040517fe8eda9df0000000000000000000000000000000000000000000000000000000081526001600160a01b039092169263e8eda9df9261142392918a913091600091016122d6565b600060405180830381600087803b15801561143d57600080fd5b505af1158015611451573d6000803e3d6000fd5b5050505082602001516001600160a01b031663095ea7b38460400151876040518363ffffffff1660e01b815260040161148b9291906122a0565b602060405180830381600087803b1580156114a557600080fd5b505af11580156114b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114dd9190810190611b9d565b5082604001516001600160a01b031663a59f3e0c866040518263ffffffff1660e01b815260040161150e9190612438565b600060405180830381600087803b15801561152857600080fd5b505af115801561153c573d6000803e3d6000fd5b50505050600083604001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611572919061220b565b60206040518083038186803b15801561158a57600080fd5b505afa15801561159e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115c29190810190611bd9565b90508461169a5783516040516323b872dd60e01b81526001600160a01b03909116906323b872dd906115fc90309033908690600401612285565b602060405180830381600087803b15801561161657600080fd5b505af115801561162a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061164e9190810190611b9d565b508584600001516001600160a01b03167fcaf66a9205f42f65dd261245228682b34c5b81d1cf49f7b2d01058199dcd671a8760405161168d9190612438565b60405180910390a36117ce565b83604001516001600160a01b031663095ea7b38560600151836040518363ffffffff1660e01b81526004016116d09291906122a0565b602060405180830381600087803b1580156116ea57600080fd5b505af11580156116fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117229190810190611b9d565b5083606001516001600160a01b031663ece1373286836040518363ffffffff1660e01b8152600401611755929190612446565b600060405180830381600087803b15801561176f57600080fd5b505af1158015611783573d6000803e3d6000fd5b505050508584600001516001600160a01b03167fcaf66a9205f42f65dd261245228682b34c5b81d1cf49f7b2d01058199dcd671a876040516117c59190612438565b60405180910390a35b95945050505050565b6001600160a01b0381166117fd5760405162461bcd60e51b815260040161029190612368565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600061112b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061193b565b6118b1828261089d565b6118cd5760405162461bcd60e51b815260040161029190612398565b6001600160a01b0316600090815260209190915260409020805460ff19169055565b6118f9828261089d565b156119165760405162461bcd60e51b815260040161029190612348565b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6000818484111561195f5760405162461bcd60e51b81526004016102919190612327565b505050900390565b60408051608081018252600080825260208201819052918101829052606081019190915290565b803561046d81612579565b805161046d81612579565b805161046d8161258d565b600082601f8301126119c057600080fd5b81356119d36119ce8261247b565b612454565b915080825260208301602083018583830111156119ef57600080fd5b6119fa83828461251c565b50505092915050565b803561046d81612596565b600060808284031215611a2057600080fd5b611a2a6080612454565b90506000611a388484611a03565b8252506020611a4984848301611a03565b6020830152506040611a5d84828501611a03565b6040830152506060611a7184828501611a03565b60608301525092915050565b803561046d8161259f565b805161046d8161259f565b600060208284031215611aa557600080fd5b6000610391848461198e565b600060208284031215611ac357600080fd5b60006103918484611999565b60008060008060808587031215611ae557600080fd5b6000611af1878761198e565b9450506020611b028782880161198e565b9350506040611b138782880161198e565b9250506060611b248782880161198e565b91505092959194509250565b60008060008060808587031215611b4657600080fd5b6000611b52878761198e565b9450506020611b638782880161198e565b9350506040611b7487828801611a7d565b925050606085013567ffffffffffffffff811115611b9157600080fd5b611b24878288016119af565b600060208284031215611baf57600080fd5b600061039184846119a4565b600060808284031215611bcd57600080fd5b60006103918484611a0e565b600060208284031215611beb57600080fd5b60006103918484611a88565b60008060008060008060c08789031215611c1057600080fd5b6000611c1c8989611a7d565b9650506020611c2d89828a01611a7d565b9550506040611c3e89828a0161198e565b9450506060611c4f89828a0161198e565b9350506080611c6089828a0161198e565b92505060a0611c7189828a0161198e565b9150509295509295509295565b611c8781612506565b82525050565b611c87816124b0565b611c87611ca2826124b0565b612558565b611c87816124bb565b611c87816124c0565b611c8781612511565b6000611ccd826124a3565b611cd781856124a7565b9350611ce7818560208601612528565b611cf081612569565b9093019392505050565b6000611d076014836124a7565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000815260200192915050565b6000611d40601f836124a7565b7f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500815260200192915050565b6000611d796030836124a7565b7f506175736572526f6c653a2063616c6c657220646f6573206e6f74206861766581527f207468652050617573657220726f6c6500000000000000000000000000000000602082015260400192915050565b6000611dd86026836124a7565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181527f6464726573730000000000000000000000000000000000000000000000000000602082015260400192915050565b6000611e376010836124a7565b7f5061757361626c653a2070617573656400000000000000000000000000000000815260200192915050565b6000611e706019836124a7565b7f436865636b2074686520746f6b656e20616c6c6f77616e636500000000000000815260200192915050565b6000611ea96021836124a7565b7f526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c81527f6500000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000611f086027836124a7565b7f63616d546f6b656e20636861696e206e6f7420696e206f6e20616c6c6f77616281527f6c65206c69737400000000000000000000000000000000000000000000000000602082015260400192915050565b6000611f67601b836124a7565b7f436861696e20616c726561647920696e205768697465204c6973740000000000815260200192915050565b6000611fa06026836124a7565b7f596f752063616e206f6e6c79207a6170206f7574206f66207661756c7473207981527f6f75206f776e0000000000000000000000000000000000000000000000000000602082015260400192915050565b6000611fff6020836124a7565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572815260200192915050565b60006120386022836124a7565b7f526f6c65733a206163636f756e7420697320746865207a65726f20616464726581527f7373000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b60006120976017836124a7565b7f436861696e206e6f7420696e207768697465204c697374000000000000000000815260200192915050565b60006120d06028836124a7565b7f596f75206e65656420746f206465706f736974206174206c6561737420736f6d81527f6520746f6b656e73000000000000000000000000000000000000000000000000602082015260400192915050565b600061212f6029836124a7565b7f596f75206e65656420746f207769746864726177206174206c6561737420736f81527f6d6520746f6b656e730000000000000000000000000000000000000000000000602082015260400192915050565b600061218e6015836124a7565b7f4e65656420746f206861766520617070726f76616c0000000000000000000000815260200192915050565b611c8781612503565b60006121cf8287611c96565b6014820191506121df8286611c96565b6014820191506121ef8285611c96565b6014820191506121ff8284611c96565b50601401949350505050565b6020810161046d8284611c8d565b6020810161046d8284611c7e565b604081016122358285611c7e565b61112b6020830184611c8d565b606081016122508286611c7e565b61225d6020830185611c8d565b61039160408301846121ba565b604081016122788285611c7e565b61112b60208301846121ba565b606081016122938286611c8d565b61225d6020830185611c7e565b604081016122788285611c8d565b606081016122bc8286611c8d565b6122c960208301856121ba565b6103916040830184611c7e565b608081016122e48287611c8d565b6122f160208301866121ba565b6122fe6040830185611c8d565b6117ce6060830184611cb9565b6020810161046d8284611ca7565b6020810161046d8284611cb0565b6020808252810161112b8184611cc2565b6020808252810161046d81611cfa565b6020808252810161046d81611d33565b6020808252810161046d81611d6c565b6020808252810161046d81611dcb565b6020808252810161046d81611e2a565b6020808252810161046d81611e63565b6020808252810161046d81611e9c565b6020808252810161046d81611efb565b6020808252810161046d81611f5a565b6020808252810161046d81611f93565b6020808252810161046d81611ff2565b6020808252810161046d8161202b565b6020808252810161046d8161208a565b6020808252810161046d816120c3565b6020808252810161046d81612122565b6020808252810161046d81612181565b6020810161046d82846121ba565b6040810161227882856121ba565b60405181810167ffffffffffffffff8111828210171561247357600080fd5b604052919050565b600067ffffffffffffffff82111561249257600080fd5b506020601f91909101601f19160190565b5190565b90815260200190565b600061046d826124f7565b151590565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b600061046d826124b0565b61ffff1690565b6001600160a01b031690565b90565b600061046d826124e5565b600061046d826124f0565b82818337506000910152565b60005b8381101561254357818101518382015260200161252b565b83811115612552576000848401525b50505050565b600061046d82600061046d82612573565b601f01601f191690565b60601b90565b612582816124b0565b81146105e057600080fd5b612582816124bb565b612582816124e5565b6125828161250356fea365627a7a72315820c1570f19d5e955ee5bfa07cc81c21b6aca94ba46a9bf57ad2771bc40fbc2f5986c6578706572696d656e74616cf564736f6c63430005100040
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101365760003560e01c8063715018a6116100b25780638f32d59b11610081578063d0ae34de11610066578063d0ae34de1461023f578063db0baaa914610247578063f2fde38b1461025a57610136565b80638f32d59b14610224578063a809e09f1461022c57610136565b8063715018a6146101ec57806382dc1ec4146101f45780638456cb59146102075780638da5cb5b1461020f57610136565b806346fbf68e116101095780636b4be2a7116100ee5780636b4be2a7146101b15780636e2e90c2146101c45780636ef8d66d146101e457610136565b806346fbf68e146101895780635c975abb146101a957610136565b8063102c32f21461013b578063150b7a02146101505780631e3ce73a146101795780633f4ba83a14610181575b600080fd5b61014e610149366004611acf565b61026d565b005b61016361015e366004611b30565b61036f565b6040516101709190612319565b60405180910390f35b61014e610399565b61014e6103c7565b61019c610197366004611a93565b61045a565b604051610170919061230b565b61019c610473565b61019c6101bf366004611bbb565b61047c565b6101d76101d2366004611bf7565b6104ad565b6040516101709190612438565b61014e610525565b61014e610535565b61014e610202366004611a93565b6105b0565b61014e6105e3565b610217610663565b604051610170919061220b565b61019c610672565b6101d761023a366004611bf7565b610696565b61014e610702565b61014e610255366004611acf565b61072e565b61014e610268366004611a93565b6107ed565b610275610672565b61029a5760405162461bcd60e51b8152600401610291906123d8565b60405180910390fd5b6102a2611967565b6102ae8585858561081a565b90506102b98161047c565b6103505780600360006102cb84610853565b815260208082019290925260409081016000208351815473ffffffffffffffffffffffffffffffffffffffff199081166001600160a01b03928316178355938501516001830180548616918316919091179055918401516002820180548516918416919091179055606090930151600390930180549092169216919091179055610368565b60405162461bcd60e51b8152600401610291906123b8565b5050505050565b7f150b7a02000000000000000000000000000000000000000000000000000000005b949350505050565b6103a1610672565b6103bd5760405162461bcd60e51b8152600401610291906123d8565b6103c56105e3565b565b6103d2610197610899565b6103ee5760405162461bcd60e51b815260040161029190612358565b60025460ff166104105760405162461bcd60e51b815260040161029190612338565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa610443610899565b6040516104509190612219565b60405180910390a1565b600061046d60018363ffffffff61089d16565b92915050565b60025460ff1690565b60008060038161048b85610853565b81526020810191909152604001600020546001600160a01b0316141592915050565b60025460009060ff16156104d35760405162461bcd60e51b815260040161029190612378565b6104db611967565b6104e78686868661081a565b90506104f28161047c565b61050e5760405162461bcd60e51b8152600401610291906123a8565b6105198888836108e5565b98975050505050505050565b6103c5610530610899565b611132565b61053d610672565b6105595760405162461bcd60e51b8152600401610291906123d8565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b6105bb610197610899565b6105d75760405162461bcd60e51b815260040161029190612358565b6105e08161117a565b50565b6105ee610197610899565b61060a5760405162461bcd60e51b815260040161029190612358565b60025460ff161561062d5760405162461bcd60e51b815260040161029190612378565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610443610899565b6000546001600160a01b031690565b600080546001600160a01b0316610687610899565b6001600160a01b031614905090565b60025460009060ff16156106bc5760405162461bcd60e51b815260040161029190612378565b6106c4611967565b6106d08686868661081a565b90506106db8161047c565b6106f75760405162461bcd60e51b8152600401610291906123a8565b6105198888836111c2565b61070a610672565b6107265760405162461bcd60e51b8152600401610291906123d8565b6103c56103c7565b610736610672565b6107525760405162461bcd60e51b8152600401610291906123d8565b61075a611967565b6107668585858561081a565b90506107718161047c565b156107d5576003600061078383610853565b81526020810191909152604001600020805473ffffffffffffffffffffffffffffffffffffffff1990811682556001820180548216905560028201805482169055600390910180549091169055610368565b60405162461bcd60e51b8152600401610291906123f8565b6107f5610672565b6108115760405162461bcd60e51b8152600401610291906123d8565b6105e0816117d7565b610822611967565b61082a611967565b6001600160a01b0395861681529385166020850152509083166040830152909116606082015290565b6000816000015182602001518360400151846060015160405160200161087c94939291906121c3565b604051602081830303815290604052805190602001209050919050565b3390565b60006001600160a01b0382166108c55760405162461bcd60e51b8152600401610291906123e8565b506001600160a01b03166000908152602091909152604090205460ff1690565b60025460009060ff161561090b5760405162461bcd60e51b815260040161029190612378565b6000841161092b5760405162461bcd60e51b815260040161029190612418565b60608201516040517f081812fc00000000000000000000000000000000000000000000000000000000815230916001600160a01b03169063081812fc90610976908790600401612438565b60206040518083038186803b15801561098e57600080fd5b505afa1580156109a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506109c69190810190611ab1565b6001600160a01b0316146109ec5760405162461bcd60e51b815260040161029190612428565b60608201516040517f6352211e00000000000000000000000000000000000000000000000000000000815233916001600160a01b031690636352211e90610a37908790600401612438565b60206040518083038186803b158015610a4f57600080fd5b505afa158015610a63573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610a879190810190611ab1565b6001600160a01b031614610aad5760405162461bcd60e51b8152600401610291906123c8565b81604001516001600160a01b031663095ea7b38360600151866040518363ffffffff1660e01b8152600401610ae39291906122a0565b602060405180830381600087803b158015610afd57600080fd5b505af1158015610b11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610b359190810190611b9d565b5081606001516001600160a01b03166342842e0e3330866040518463ffffffff1660e01b8152600401610b6a93929190612242565b600060405180830381600087803b158015610b8457600080fd5b505af1158015610b98573d6000803e3d6000fd5b50505050600082604001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610bce919061220b565b60206040518083038186803b158015610be657600080fd5b505afa158015610bfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610c1e9190810190611bd9565b60608401516040517f767a7b050000000000000000000000000000000000000000000000000000000081529192506001600160a01b03169063767a7b0590610c6c9087908990600401612446565b600060405180830381600087803b158015610c8657600080fd5b505af1158015610c9a573d6000803e3d6000fd5b505050506000610d308285604001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610cd4919061220b565b60206040518083038186803b158015610cec57600080fd5b505afa158015610d00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610d249190810190611bd9565b9063ffffffff61186516565b606085015160405163095ea7b360e01b81529192506001600160a01b03169063095ea7b390610d65903390899060040161226a565b600060405180830381600087803b158015610d7f57600080fd5b505af1158015610d93573d6000803e3d6000fd5b5050505083606001516001600160a01b03166342842e0e3033886040518463ffffffff1660e01b8152600401610dcb93929190612285565b600060405180830381600087803b158015610de557600080fd5b505af1158015610df9573d6000803e3d6000fd5b50505050600084602001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610e2f919061220b565b60206040518083038186803b158015610e4757600080fd5b505afa158015610e5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610e7f9190810190611bd9565b905084604001516001600160a01b03166367dfd4c9836040518263ffffffff1660e01b8152600401610eb19190612438565b600060405180830381600087803b158015610ecb57600080fd5b505af1158015610edf573d6000803e3d6000fd5b505050506000610f198287602001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610cd4919061220b565b60208701516004805460405163095ea7b360e01b81529394506001600160a01b039283169363095ea7b393610f53939216918691016122a0565b602060405180830381600087803b158015610f6d57600080fd5b505af1158015610f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610fa59190810190611b9d565b506004805487516040517f69328dec0000000000000000000000000000000000000000000000000000000081526001600160a01b03909216926369328dec92610ff3929186913391016122ae565b602060405180830381600087803b15801561100d57600080fd5b505af1158015611021573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506110459190810190611bd9565b508786600001516001600160a01b03167f3e47dad970f8ef4dc53e82b8ac03c2623f966d35e7424ca85ca183e61f0b5970896040516110849190612438565b60405180910390a385516040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906370a08231906110d4903390600401612219565b60206040518083038186803b1580156110ec57600080fd5b505afa158015611100573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506111249190810190611bd9565b9450505050505b9392505050565b61114360018263ffffffff6118a716565b6040516001600160a01b038216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b61118b60018263ffffffff6118ef16565b6040516001600160a01b038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b60025460009060ff16156111e85760405162461bcd60e51b815260040161029190612378565b600084116112085760405162461bcd60e51b815260040161029190612408565b81516040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526000916001600160a01b03169063dd62ed3e906112539033903090600401612227565b60206040518083038186803b15801561126b57600080fd5b505afa15801561127f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112a39190810190611bd9565b9050848110156112c55760405162461bcd60e51b815260040161029190612388565b82516040516323b872dd60e01b81526001600160a01b03909116906323b872dd906112f890339030908a90600401612242565b602060405180830381600087803b15801561131257600080fd5b505af1158015611326573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061134a9190810190611b9d565b5082516004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b39361138093909116918a91016122a0565b602060405180830381600087803b15801561139a57600080fd5b505af11580156113ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506113d29190810190611b9d565b506004805484516040517fe8eda9df0000000000000000000000000000000000000000000000000000000081526001600160a01b039092169263e8eda9df9261142392918a913091600091016122d6565b600060405180830381600087803b15801561143d57600080fd5b505af1158015611451573d6000803e3d6000fd5b5050505082602001516001600160a01b031663095ea7b38460400151876040518363ffffffff1660e01b815260040161148b9291906122a0565b602060405180830381600087803b1580156114a557600080fd5b505af11580156114b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114dd9190810190611b9d565b5082604001516001600160a01b031663a59f3e0c866040518263ffffffff1660e01b815260040161150e9190612438565b600060405180830381600087803b15801561152857600080fd5b505af115801561153c573d6000803e3d6000fd5b50505050600083604001516001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611572919061220b565b60206040518083038186803b15801561158a57600080fd5b505afa15801561159e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115c29190810190611bd9565b90508461169a5783516040516323b872dd60e01b81526001600160a01b03909116906323b872dd906115fc90309033908690600401612285565b602060405180830381600087803b15801561161657600080fd5b505af115801561162a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061164e9190810190611b9d565b508584600001516001600160a01b03167fcaf66a9205f42f65dd261245228682b34c5b81d1cf49f7b2d01058199dcd671a8760405161168d9190612438565b60405180910390a36117ce565b83604001516001600160a01b031663095ea7b38560600151836040518363ffffffff1660e01b81526004016116d09291906122a0565b602060405180830381600087803b1580156116ea57600080fd5b505af11580156116fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506117229190810190611b9d565b5083606001516001600160a01b031663ece1373286836040518363ffffffff1660e01b8152600401611755929190612446565b600060405180830381600087803b15801561176f57600080fd5b505af1158015611783573d6000803e3d6000fd5b505050508584600001516001600160a01b03167fcaf66a9205f42f65dd261245228682b34c5b81d1cf49f7b2d01058199dcd671a876040516117c59190612438565b60405180910390a35b95945050505050565b6001600160a01b0381166117fd5760405162461bcd60e51b815260040161029190612368565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b600061112b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061193b565b6118b1828261089d565b6118cd5760405162461bcd60e51b815260040161029190612398565b6001600160a01b0316600090815260209190915260409020805460ff19169055565b6118f9828261089d565b156119165760405162461bcd60e51b815260040161029190612348565b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6000818484111561195f5760405162461bcd60e51b81526004016102919190612327565b505050900390565b60408051608081018252600080825260208201819052918101829052606081019190915290565b803561046d81612579565b805161046d81612579565b805161046d8161258d565b600082601f8301126119c057600080fd5b81356119d36119ce8261247b565b612454565b915080825260208301602083018583830111156119ef57600080fd5b6119fa83828461251c565b50505092915050565b803561046d81612596565b600060808284031215611a2057600080fd5b611a2a6080612454565b90506000611a388484611a03565b8252506020611a4984848301611a03565b6020830152506040611a5d84828501611a03565b6040830152506060611a7184828501611a03565b60608301525092915050565b803561046d8161259f565b805161046d8161259f565b600060208284031215611aa557600080fd5b6000610391848461198e565b600060208284031215611ac357600080fd5b60006103918484611999565b60008060008060808587031215611ae557600080fd5b6000611af1878761198e565b9450506020611b028782880161198e565b9350506040611b138782880161198e565b9250506060611b248782880161198e565b91505092959194509250565b60008060008060808587031215611b4657600080fd5b6000611b52878761198e565b9450506020611b638782880161198e565b9350506040611b7487828801611a7d565b925050606085013567ffffffffffffffff811115611b9157600080fd5b611b24878288016119af565b600060208284031215611baf57600080fd5b600061039184846119a4565b600060808284031215611bcd57600080fd5b60006103918484611a0e565b600060208284031215611beb57600080fd5b60006103918484611a88565b60008060008060008060c08789031215611c1057600080fd5b6000611c1c8989611a7d565b9650506020611c2d89828a01611a7d565b9550506040611c3e89828a0161198e565b9450506060611c4f89828a0161198e565b9350506080611c6089828a0161198e565b92505060a0611c7189828a0161198e565b9150509295509295509295565b611c8781612506565b82525050565b611c87816124b0565b611c87611ca2826124b0565b612558565b611c87816124bb565b611c87816124c0565b611c8781612511565b6000611ccd826124a3565b611cd781856124a7565b9350611ce7818560208601612528565b611cf081612569565b9093019392505050565b6000611d076014836124a7565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000815260200192915050565b6000611d40601f836124a7565b7f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500815260200192915050565b6000611d796030836124a7565b7f506175736572526f6c653a2063616c6c657220646f6573206e6f74206861766581527f207468652050617573657220726f6c6500000000000000000000000000000000602082015260400192915050565b6000611dd86026836124a7565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206181527f6464726573730000000000000000000000000000000000000000000000000000602082015260400192915050565b6000611e376010836124a7565b7f5061757361626c653a2070617573656400000000000000000000000000000000815260200192915050565b6000611e706019836124a7565b7f436865636b2074686520746f6b656e20616c6c6f77616e636500000000000000815260200192915050565b6000611ea96021836124a7565b7f526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c81527f6500000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b6000611f086027836124a7565b7f63616d546f6b656e20636861696e206e6f7420696e206f6e20616c6c6f77616281527f6c65206c69737400000000000000000000000000000000000000000000000000602082015260400192915050565b6000611f67601b836124a7565b7f436861696e20616c726561647920696e205768697465204c6973740000000000815260200192915050565b6000611fa06026836124a7565b7f596f752063616e206f6e6c79207a6170206f7574206f66207661756c7473207981527f6f75206f776e0000000000000000000000000000000000000000000000000000602082015260400192915050565b6000611fff6020836124a7565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572815260200192915050565b60006120386022836124a7565b7f526f6c65733a206163636f756e7420697320746865207a65726f20616464726581527f7373000000000000000000000000000000000000000000000000000000000000602082015260400192915050565b60006120976017836124a7565b7f436861696e206e6f7420696e207768697465204c697374000000000000000000815260200192915050565b60006120d06028836124a7565b7f596f75206e65656420746f206465706f736974206174206c6561737420736f6d81527f6520746f6b656e73000000000000000000000000000000000000000000000000602082015260400192915050565b600061212f6029836124a7565b7f596f75206e65656420746f207769746864726177206174206c6561737420736f81527f6d6520746f6b656e730000000000000000000000000000000000000000000000602082015260400192915050565b600061218e6015836124a7565b7f4e65656420746f206861766520617070726f76616c0000000000000000000000815260200192915050565b611c8781612503565b60006121cf8287611c96565b6014820191506121df8286611c96565b6014820191506121ef8285611c96565b6014820191506121ff8284611c96565b50601401949350505050565b6020810161046d8284611c8d565b6020810161046d8284611c7e565b604081016122358285611c7e565b61112b6020830184611c8d565b606081016122508286611c7e565b61225d6020830185611c8d565b61039160408301846121ba565b604081016122788285611c7e565b61112b60208301846121ba565b606081016122938286611c8d565b61225d6020830185611c7e565b604081016122788285611c8d565b606081016122bc8286611c8d565b6122c960208301856121ba565b6103916040830184611c7e565b608081016122e48287611c8d565b6122f160208301866121ba565b6122fe6040830185611c8d565b6117ce6060830184611cb9565b6020810161046d8284611ca7565b6020810161046d8284611cb0565b6020808252810161112b8184611cc2565b6020808252810161046d81611cfa565b6020808252810161046d81611d33565b6020808252810161046d81611d6c565b6020808252810161046d81611dcb565b6020808252810161046d81611e2a565b6020808252810161046d81611e63565b6020808252810161046d81611e9c565b6020808252810161046d81611efb565b6020808252810161046d81611f5a565b6020808252810161046d81611f93565b6020808252810161046d81611ff2565b6020808252810161046d8161202b565b6020808252810161046d8161208a565b6020808252810161046d816120c3565b6020808252810161046d81612122565b6020808252810161046d81612181565b6020810161046d82846121ba565b6040810161227882856121ba565b60405181810167ffffffffffffffff8111828210171561247357600080fd5b604052919050565b600067ffffffffffffffff82111561249257600080fd5b506020601f91909101601f19160190565b5190565b90815260200190565b600061046d826124f7565b151590565b7fffffffff000000000000000000000000000000000000000000000000000000001690565b600061046d826124b0565b61ffff1690565b6001600160a01b031690565b90565b600061046d826124e5565b600061046d826124f0565b82818337506000910152565b60005b8381101561254357818101518382015260200161252b565b83811115612552576000848401525b50505050565b600061046d82600061046d82612573565b601f01601f191690565b60601b90565b612582816124b0565b81146105e057600080fd5b612582816124bb565b612582816124e5565b6125828161250356fea365627a7a72315820c1570f19d5e955ee5bfa07cc81c21b6aca94ba46a9bf57ad2771bc40fbc2f5986c6578706572696d656e74616cf564736f6c63430005100040
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in POL
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.