Source Code
Overview
S Balance
S Value
$0.00Cross-Chain Transactions
Loading...
Loading
Contract Name:
ShadowV2GaugeConnector
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IFarmConnector, Farm } from "contracts/interfaces/IFarmConnector.sol";
import { INuriGauge } from "contracts/interfaces/external/nuri/INuriGauge.sol";
import {
ShadowRewardBehavior,
ShadowV2GaugeClaim
} from "contracts/connectors/shadow/ShadowGaugeClaim.sol";
struct ShadowClaimExtraData {
address[] claimTokens;
ShadowRewardBehavior behavior;
}
contract ShadowV2GaugeConnector is IFarmConnector, ShadowV2GaugeClaim {
function deposit(
Farm calldata farm,
address token,
bytes memory // _extraData
) external payable override {
uint256 amount = IERC20(token).balanceOf(address(this));
SafeTransferLib.safeApprove(token, farm.stakingContract, amount);
INuriGauge(farm.stakingContract).deposit(amount);
}
function withdraw(
Farm calldata farm,
uint256 amount,
bytes memory // _extraData
) external override {
INuriGauge(farm.stakingContract).withdraw(amount);
}
function claim(
Farm calldata farm,
bytes memory extraData
) external override {
ShadowClaimExtraData memory extra =
abi.decode(extraData, (ShadowClaimExtraData));
_claimGaugeRewards(
farm.stakingContract, extra.claimTokens, extra.behavior
);
}
function balanceOf(
Farm calldata farm,
address user
) external view override returns (uint256) {
return INuriGauge(farm.stakingContract).balanceOf(user);
}
function earned(
Farm calldata farm,
address user,
address[] calldata rewardTokens
) external view override returns (uint256[] memory) {
uint256[] memory rewards = new uint256[](rewardTokens.length);
for (uint256 i = 0; i < rewardTokens.length; i++) {
rewards[i] =
INuriGauge(farm.stakingContract).earned(rewardTokens[i], user);
}
return rewards;
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
error ETHTransferFailed();
error TransferFromFailed();
error TransferFailed();
error ApproveFailed();
/*//////////////////////////////////////////////////////////////
ETH OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferETH(address to, uint256 amount) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
if (!success) revert ETHTransferFailed();
}
/*//////////////////////////////////////////////////////////////
ERC20 OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferFrom(
address token,
address from,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
if (!success) revert TransferFromFailed();
}
function safeTransfer(
address token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
if (!success) revert TransferFailed();
}
function safeApprove(
address token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
if (!success) revert ApproveFailed();
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the 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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, 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 `from` to `to` 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 from,
address to,
uint256 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Farm } from "contracts/structs/FarmStrategyStructs.sol";
interface IFarmConnector {
function deposit(
Farm calldata farm,
address token,
bytes memory extraData
) external payable;
function withdraw(
Farm calldata farm,
uint256 amount,
bytes memory extraData
) external;
function claim(Farm calldata farm, bytes memory extraData) external;
function balanceOf(
Farm calldata farm,
address user
) external view returns (uint256);
function earned(
Farm calldata farm,
address user,
address[] calldata rewardTokens
) external view returns (uint256[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface INuriGauge {
function initialize(
address _stake,
address _feeDist,
address _voter,
bool _forPair
) external;
function getReward(address account, address[] calldata tokens) external;
function claimFees()
external
returns (uint256 claimed0, uint256 claimed1);
function left(
address token
) external view returns (uint256);
function rewardsListLength() external view returns (uint256);
function rewardsList() external view returns (address[] memory);
function earned(
address token,
address account
) external view returns (uint256);
function balanceOf(
address
) external view returns (uint256);
function notifyRewardAmount(address token, uint256 amount) external;
struct Reward {
uint256 rewardRate;
uint256 periodFinish;
uint256 lastUpdateTime;
uint256 rewardPerTokenStored;
}
function rewardData(
address token
) external view returns (Reward memory);
function deposit(
uint256 amount
) external;
function withdraw(
uint256 amount
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IShadowGaugeV3 } from
"contracts/interfaces/external/shadow/IShadowGaugeV3.sol";
import { INuriGauge } from "contracts/interfaces/external/nuri/INuriGauge.sol";
interface IXShadow {
function exit(
uint256 amount
) external returns (uint256 exitedAmount);
}
interface IX33 {
function deposit(
uint256 assets,
address receiver
) external returns (uint256 shares);
}
enum ShadowRewardBehavior {
Exit, // Exit to Shadow (50% penalty)
X33, // Deposit into X33
Keep // Keep in xShadow on Sickle
}
contract ShadowAddresses {
address constant X_SHADOW = 0x5050bc082FF4A74Fb6B0B04385dEfdDB114b2424;
address constant X33_ADAPTER = 0x9710E10A8f6FbA8C391606fee18614885684548d;
}
contract ShadowV3GaugeClaim is ShadowAddresses {
// Shadow rewards are in xShadow, which is not transferable.
// When claiming, there are three options:
// 1. Exit to Shadow (50% penalty)
// 2. Deposit into X33 (no penalty)
// 3. Keep in xShadow on Sickle
// This function supports all three options.
function _claimGaugeRewards(
address gauge,
uint256 tokenId,
address[] memory rewardTokens,
ShadowRewardBehavior behavior
) internal {
IShadowGaugeV3(gauge).getReward(tokenId, rewardTokens);
uint256 rewards = IERC20(X_SHADOW).balanceOf(address(this));
if (rewards > 0) {
if (behavior == ShadowRewardBehavior.X33) {
IERC20(X_SHADOW).approve(X33_ADAPTER, rewards);
IX33(X33_ADAPTER).deposit(rewards, address(this));
} else if (behavior == ShadowRewardBehavior.Exit) {
IXShadow(X_SHADOW).exit(rewards);
} // else keep in xShadow on Sickle
}
}
}
contract ShadowV2GaugeClaim is ShadowAddresses {
function _claimGaugeRewards(
address gauge,
address[] memory rewardTokens,
ShadowRewardBehavior behavior
) internal {
INuriGauge(gauge).getReward(address(this), rewardTokens);
uint256 rewards = IERC20(X_SHADOW).balanceOf(address(this));
if (rewards > 0) {
if (behavior == ShadowRewardBehavior.X33) {
IERC20(X_SHADOW).approve(X33_ADAPTER, rewards);
IX33(X33_ADAPTER).deposit(rewards, address(this));
} else if (behavior == ShadowRewardBehavior.Exit) {
IXShadow(X_SHADOW).exit(rewards);
} // else keep in xShadow on Sickle
}
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { ZapIn, ZapOut } from "contracts/libraries/ZapLib.sol";
import { SwapParams } from "contracts/structs/LiquidityStructs.sol";
struct Farm {
address stakingContract;
uint256 poolIndex;
}
struct DepositParams {
Farm farm;
address[] tokensIn;
uint256[] amountsIn;
ZapIn zap;
bytes extraData;
}
struct WithdrawParams {
bytes extraData;
ZapOut zap;
address[] tokensOut;
}
struct HarvestParams {
SwapParams[] swaps;
bytes extraData;
address[] tokensOut;
}
struct CompoundParams {
Farm claimFarm;
bytes claimExtraData;
address[] rewardTokens;
ZapIn zap;
Farm depositFarm;
bytes depositExtraData;
}
struct SimpleDepositParams {
Farm farm;
address lpToken;
uint256 amountIn;
bytes extraData;
}
struct SimpleHarvestParams {
address[] rewardTokens;
bytes extraData;
}
struct SimpleWithdrawParams {
address lpToken;
uint256 amountOut;
bytes extraData;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8;
interface IShadowGaugeV3 {
error NOT_AUTHORIZED();
error NOT_VOTER();
error NOT_GT_ZERO(uint256 amt);
error CANT_CLAIM_FUTURE();
error RETRO();
/// @notice Emitted when a reward notification is made.
/// @param from The address from which the reward is notified.
/// @param reward The address of the reward token.
/// @param amount The amount of rewards notified.
/// @param period The period for which the rewards are notified.
event NotifyReward(
address indexed from,
address indexed reward,
uint256 amount,
uint256 period
);
/// @notice Emitted when a bribe is made.
/// @param from The address from which the bribe is made.
/// @param reward The address of the reward token.
/// @param amount The amount of tokens bribed.
/// @param period The period for which the bribe is made.
event Bribe(
address indexed from,
address indexed reward,
uint256 amount,
uint256 period
);
/// @notice Emitted when rewards are claimed.
/// @param period The period for which the rewards are claimed.
/// @param _positionHash The identifier of the NFP for which rewards are
/// claimed.
/// @param receiver The address of the receiver of the claimed rewards.
/// @param reward The address of the reward token.
/// @param amount The amount of rewards claimed.
event ClaimRewards(
uint256 period,
bytes32 _positionHash,
address receiver,
address reward,
uint256 amount
);
/// @notice Emitted when a new reward token was pushed to the rewards array
event RewardAdded(address reward);
/// @notice Emitted when a reward token was removed from the rewards array
event RewardRemoved(address reward);
/// @notice Retrieves the value of the firstPeriod variable.
/// @return The value of the firstPeriod variable.
function firstPeriod() external returns (uint256);
/// @notice Retrieves the total supply of a specific token for a given
/// period.
/// @param period The period for which to retrieve the total supply.
/// @param token The address of the token for which to retrieve the total
/// supply.
/// @return The total supply of the specified token for the given period.
function tokenTotalSupplyByPeriod(
uint256 period,
address token
) external view returns (uint256);
/// @notice Retrieves the getTokenTotalSupplyByPeriod of the current period.
/// @dev included to support voter's left() check during distribute().
/// @param token The address of the token for which to retrieve the
/// remaining amount.
/// @return The amount of tokens left to distribute in this period.
function left(
address token
) external view returns (uint256);
/// @notice Retrieves the reward rate for a specific reward address.
/// @dev this method returns the base rate without boost
/// @param token The address of the reward for which to retrieve the reward
/// rate.
/// @return The reward rate for the specified reward address.
function rewardRate(
address token
) external view returns (uint256);
/// @notice Retrieves the claimed amount for a specific period, position
/// hash, and user address.
/// @param period The period for which to retrieve the claimed amount.
/// @param _positionHash The identifier of the NFP for which to retrieve the
/// claimed amount.
/// @param reward The address of the token for the claimed amount.
/// @return The claimed amount for the specified period, token ID, and user
/// address.
function periodClaimedAmount(
uint256 period,
bytes32 _positionHash,
address reward
) external view returns (uint256);
/// @notice Retrieves the last claimed period for a specific token, token ID
/// combination.
/// @param token The address of the reward token for which to retrieve the
/// last claimed period.
/// @param _positionHash The identifier of the NFP for which to retrieve the
/// last claimed period.
/// @return The last claimed period for the specified token and token ID.
function lastClaimByToken(
address token,
bytes32 _positionHash
) external view returns (uint256);
/// @notice Retrieves the reward address at the specified index in the
/// rewards array.
/// @param index The index of the reward address to retrieve.
/// @return The reward address at the specified index.
function rewards(
uint256 index
) external view returns (address);
/// @notice Checks if a given address is a valid reward.
/// @param reward The address to check.
/// @return A boolean indicating whether the address is a valid reward.
function isReward(
address reward
) external view returns (bool);
/// @notice Returns an array of reward token addresses.
/// @return An array of reward token addresses.
function getRewardTokens() external view returns (address[] memory);
/// @notice Returns the hash used to store positions in a mapping
/// @param owner The address of the position owner
/// @param index The index of the position
/// @param tickLower The lower tick boundary of the position
/// @param tickUpper The upper tick boundary of the position
/// @return _hash The hash used to store positions in a mapping
function positionHash(
address owner,
uint256 index,
int24 tickLower,
int24 tickUpper
) external pure returns (bytes32);
/*
/// @notice Retrieves the liquidity and boosted liquidity for a specific
NFP.
/// @param tokenId The identifier of the NFP.
/// @return liquidity The liquidity of the position token.
function positionInfo(
uint256 tokenId
) external view returns (uint128 liquidity);
*/
/// @notice Returns the amount of rewards earned for an NFP.
/// @param token The address of the token for which to retrieve the earned
/// rewards.
/// @param tokenId The identifier of the specific NFP for which to retrieve
/// the earned rewards.
/// @return reward The amount of rewards earned for the specified NFP and
/// tokens.
function earned(
address token,
uint256 tokenId
) external view returns (uint256 reward);
/// @notice Returns the amount of rewards earned during a period for an NFP.
/// @param period The period for which to retrieve the earned rewards.
/// @param token The address of the token for which to retrieve the earned
/// rewards.
/// @param tokenId The identifier of the specific NFP for which to retrieve
/// the earned rewards.
/// @return reward The amount of rewards earned for the specified NFP and
/// tokens.
function periodEarned(
uint256 period,
address token,
uint256 tokenId
) external view returns (uint256);
/// @notice Retrieves the earned rewards for a specific period, token,
/// owner, index, tickLower, and tickUpper.
/// @param period The period for which to retrieve the earned rewards.
/// @param token The address of the token for which to retrieve the earned
/// rewards.
/// @param owner The address of the owner for which to retrieve the earned
/// rewards.
/// @param index The index for which to retrieve the earned rewards.
/// @param tickLower The tick lower bound for which to retrieve the earned
/// rewards.
/// @param tickUpper The tick upper bound for which to retrieve the earned
/// rewards.
/// @return The earned rewards for the specified period, token, owner,
/// index, tickLower, and tickUpper.
function periodEarned(
uint256 period,
address token,
address owner,
uint256 index,
int24 tickLower,
int24 tickUpper
) external view returns (uint256);
/// @notice Retrieves the earned rewards for a specific period, token,
/// owner, index, tickLower, and tickUpper.
/// @dev used by getReward() and saves gas by saving states
/// @param period The period for which to retrieve the earned rewards.
/// @param token The address of the token for which to retrieve the earned
/// rewards.
/// @param owner The address of the owner for which to retrieve the earned
/// rewards.
/// @param index The index for which to retrieve the earned rewards.
/// @param tickLower The tick lower bound for which to retrieve the earned
/// rewards.
/// @param tickUpper The tick upper bound for which to retrieve the earned
/// rewards.
/// @param caching Whether to cache the results or not.
/// @return The earned rewards for the specified period, token, owner,
/// index, tickLower, and tickUpper.
function cachePeriodEarned(
uint256 period,
address token,
address owner,
uint256 index,
int24 tickLower,
int24 tickUpper,
bool caching
) external returns (uint256);
/// @notice Notifies the contract about the amount of rewards to be
/// distributed for a specific token.
/// @param token The address of the token for which to notify the reward
/// amount.
/// @param amount The amount of rewards to be distributed.
function notifyRewardAmount(address token, uint256 amount) external;
/// @notice Retrieves the reward amount for a specific period, NFP, and
/// token addresses.
/// @param period The period for which to retrieve the reward amount.
/// @param tokens The addresses of the tokens for which to retrieve the
/// reward amount.
/// @param tokenId The identifier of the specific NFP for which to retrieve
/// the reward amount.
/// @param receiver The address of the receiver of the reward amount.
function getPeriodReward(
uint256 period,
address[] calldata tokens,
uint256 tokenId,
address receiver
) external;
/// @notice Retrieves the rewards for a specific period, set of tokens,
/// owner, index, tickLower, tickUpper, and receiver.
/// @param period The period for which to retrieve the rewards.
/// @param tokens An array of token addresses for which to retrieve the
/// rewards.
/// @param owner The address of the owner for which to retrieve the rewards.
/// @param index The index for which to retrieve the rewards.
/// @param tickLower The tick lower bound for which to retrieve the rewards.
/// @param tickUpper The tick upper bound for which to retrieve the rewards.
/// @param receiver The address of the receiver of the rewards.
function getPeriodReward(
uint256 period,
address[] calldata tokens,
address owner,
uint256 index,
int24 tickLower,
int24 tickUpper,
address receiver
) external;
/// @notice retrieves rewards based on an NFP id and an array of tokens
function getReward(uint256 tokenId, address[] memory tokens) external;
/// @notice retrieves rewards based on an array of NFP ids and an array of
/// tokens
function getReward(
uint256[] calldata tokenIds,
address[] memory tokens
) external;
/// @notice get reward for an owner of an NFP
function getRewardForOwner(
uint256 tokenId,
address[] memory tokens
) external;
function addRewards(
address reward
) external;
function removeRewards(
address reward
) external;
/// @notice Notifies rewards for periods greater than current period
/// @dev does not push fees
/// @dev requires reward token to be whitelisted
function notifyRewardAmountForPeriod(
address token,
uint256 amount,
uint256 period
) external;
/// @notice Notifies rewards for the next period
/// @dev does not push fees
/// @dev requires reward token to be whitelisted
function notifyRewardAmountNextPeriod(
address token,
uint256 amount
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import {
SwapParams,
AddLiquidityParams
} from "contracts/structs/LiquidityStructs.sol";
import { ILiquidityConnector } from
"contracts/interfaces/ILiquidityConnector.sol";
import { ConnectorRegistry } from "contracts/ConnectorRegistry.sol";
import { DelegateModule } from "contracts/modules/DelegateModule.sol";
import { ZapIn, ZapOut } from "contracts/structs/ZapStructs.sol";
import { IZapLib } from "contracts/interfaces/libraries/IZapLib.sol";
import { ISwapLib } from "contracts/interfaces/libraries/ISwapLib.sol";
contract ZapLib is DelegateModule, IZapLib {
error LiquidityAmountError(); // 0x4d0ab6b4
ISwapLib public immutable swapLib;
ConnectorRegistry public immutable connectorRegistry;
constructor(ConnectorRegistry connectorRegistry_, ISwapLib swapLib_) {
connectorRegistry = connectorRegistry_;
swapLib = swapLib_;
}
function zapIn(
ZapIn memory zap
) external payable {
uint256 swapDataLength = zap.swaps.length;
for (uint256 i; i < swapDataLength;) {
_delegateTo(
address(swapLib), abi.encodeCall(ISwapLib.swap, (zap.swaps[i]))
);
unchecked {
i++;
}
}
if (zap.addLiquidityParams.lpToken == address(0)) {
return;
}
bool atLeastOneNonZero = false;
AddLiquidityParams memory addLiquidityParams = zap.addLiquidityParams;
uint256 addLiquidityParamsTokensLength =
addLiquidityParams.tokens.length;
for (uint256 i; i < addLiquidityParamsTokensLength; i++) {
if (addLiquidityParams.tokens[i] == address(0)) {
continue;
}
if (addLiquidityParams.desiredAmounts[i] == 0) {
addLiquidityParams.desiredAmounts[i] = IERC20(
addLiquidityParams.tokens[i]
).balanceOf(address(this));
}
if (addLiquidityParams.desiredAmounts[i] > 0) {
atLeastOneNonZero = true;
// In case there is USDT or similar dust approval, revoke it
SafeTransferLib.safeApprove(
addLiquidityParams.tokens[i], addLiquidityParams.router, 0
);
SafeTransferLib.safeApprove(
addLiquidityParams.tokens[i],
addLiquidityParams.router,
addLiquidityParams.desiredAmounts[i]
);
}
}
if (!atLeastOneNonZero) {
revert LiquidityAmountError();
}
address routerConnector =
connectorRegistry.connectorOf(addLiquidityParams.router);
_delegateTo(
routerConnector,
abi.encodeCall(
ILiquidityConnector.addLiquidity, (addLiquidityParams)
)
);
for (uint256 i; i < addLiquidityParamsTokensLength;) {
if (addLiquidityParams.tokens[i] != address(0)) {
// Revoke any dust approval in case the amount was estimated
SafeTransferLib.safeApprove(
addLiquidityParams.tokens[i], addLiquidityParams.router, 0
);
}
unchecked {
i++;
}
}
}
function zapOut(
ZapOut memory zap
) external {
if (zap.removeLiquidityParams.lpToken != address(0)) {
if (zap.removeLiquidityParams.lpAmountIn > 0) {
SafeTransferLib.safeApprove(
zap.removeLiquidityParams.lpToken,
zap.removeLiquidityParams.router,
zap.removeLiquidityParams.lpAmountIn
);
}
address routerConnector =
connectorRegistry.connectorOf(zap.removeLiquidityParams.router);
_delegateTo(
address(routerConnector),
abi.encodeCall(
ILiquidityConnector.removeLiquidity,
zap.removeLiquidityParams
)
);
}
uint256 swapDataLength = zap.swaps.length;
for (uint256 i; i < swapDataLength;) {
_delegateTo(
address(swapLib), abi.encodeCall(ISwapLib.swap, (zap.swaps[i]))
);
unchecked {
i++;
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
struct AddLiquidityParams {
address router;
address lpToken;
address[] tokens;
uint256[] desiredAmounts;
uint256[] minAmounts;
bytes extraData;
}
struct RemoveLiquidityParams {
address router;
address lpToken;
address[] tokens;
uint256 lpAmountIn;
uint256[] minAmountsOut;
bytes extraData;
}
struct SwapParams {
address router;
uint256 amountIn;
uint256 minAmountOut;
address tokenIn;
bytes extraData;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {
AddLiquidityParams,
RemoveLiquidityParams,
SwapParams
} from "contracts/structs/LiquidityStructs.sol";
interface ILiquidityConnector {
error InvalidPrice();
function addLiquidity(
AddLiquidityParams memory addLiquidityParams
) external payable;
function removeLiquidity(
RemoveLiquidityParams memory removeLiquidityParams
) external;
function swapExactTokensForTokens(
SwapParams memory swap
) external payable;
function swapExactETHForTokens(
SwapParams memory swap
) external payable;
function getPoolPrice(
address lpToken,
uint256 baseTokenIndex,
uint256 quoteTokenIndex
) external view returns (uint256);
function getReserves(
address lpToken
) external view returns (uint256[] memory reserves);
function getTokens(
address lpToken
) external view returns (address[] memory tokens);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { Admin } from "contracts/base/Admin.sol";
import { TimelockAdmin } from "contracts/base/TimelockAdmin.sol";
error ConnectorNotRegistered(address target);
error CustomRegistryAlreadyRegistered();
interface ICustomConnectorRegistry {
function connectorOf(
address target
) external view returns (address);
}
contract ConnectorRegistry is Admin, TimelockAdmin {
event ConnectorChanged(address target, address connector);
event CustomRegistryAdded(address registry);
event CustomRegistryRemoved(address registry);
error ConnectorAlreadySet(address target);
error ConnectorNotSet(address target);
error ArrayLengthMismatch();
ICustomConnectorRegistry[] public customRegistries;
mapping(address target => address connector) private connectors_;
constructor(
address admin_,
address timelockAdmin_
) Admin(admin_) TimelockAdmin(timelockAdmin_) { }
/// Admin functions
/// @notice Update connector addresses for a batch of targets.
/// @dev Controls which connector contracts are used for the specified
/// targets.
/// @custom:access Restricted to protocol admin.
function setConnectors(
address[] calldata targets,
address[] calldata connectors
) external onlyAdmin {
if (targets.length != connectors.length) {
revert ArrayLengthMismatch();
}
for (uint256 i; i != targets.length;) {
if (connectors_[targets[i]] != address(0)) {
revert ConnectorAlreadySet(targets[i]);
}
connectors_[targets[i]] = connectors[i];
emit ConnectorChanged(targets[i], connectors[i]);
unchecked {
++i;
}
}
}
function updateConnectors(
address[] calldata targets,
address[] calldata connectors
) external onlyTimelockAdmin {
if (targets.length != connectors.length) {
revert ArrayLengthMismatch();
}
for (uint256 i; i != targets.length;) {
if (connectors_[targets[i]] == address(0)) {
revert ConnectorNotSet(targets[i]);
}
connectors_[targets[i]] = connectors[i];
emit ConnectorChanged(targets[i], connectors[i]);
unchecked {
++i;
}
}
}
/// @notice Append an address to the custom registries list.
/// @custom:access Restricted to protocol admin.
function addCustomRegistry(
ICustomConnectorRegistry registry
) external onlyAdmin {
if (isCustomRegistry(registry)) {
revert CustomRegistryAlreadyRegistered();
}
customRegistries.push(registry);
emit CustomRegistryAdded(address(registry));
}
/// @notice Replace an address in the custom registries list.
/// @custom:access Restricted to protocol admin.
function updateCustomRegistry(
uint256 index,
ICustomConnectorRegistry newRegistry
) external onlyTimelockAdmin {
ICustomConnectorRegistry oldRegistry = customRegistries[index];
emit CustomRegistryRemoved(address(oldRegistry));
customRegistries[index] = newRegistry;
if (address(newRegistry) != address(0)) {
emit CustomRegistryAdded(address(newRegistry));
}
}
/// Public functions
function connectorOf(
address target
) external view returns (address) {
address connector = _getConnector(target);
if (connector != address(0)) {
return connector;
}
revert ConnectorNotRegistered(target);
}
function hasConnector(
address target
) external view returns (bool) {
return _getConnector(target) != address(0);
}
function isCustomRegistry(
ICustomConnectorRegistry registry
) public view returns (bool) {
for (uint256 i; i != customRegistries.length;) {
if (address(customRegistries[i]) == address(registry)) {
return true;
}
unchecked {
++i;
}
}
return false;
}
/// Internal functions
function _getConnector(
address target
) internal view returns (address) {
address connector = connectors_[target];
if (connector != address(0)) {
return connector;
}
uint256 length = customRegistries.length;
for (uint256 i; i != length;) {
if (address(customRegistries[i]) != address(0)) {
(bool success, bytes memory data) = address(customRegistries[i])
.staticcall(
abi.encodeWithSelector(
ICustomConnectorRegistry.connectorOf.selector, target
)
);
if (success && data.length == 32) {
address _connector = abi.decode(data, (address));
if (_connector != address(0)) {
return _connector;
}
}
}
unchecked {
++i;
}
}
return address(0);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract DelegateModule {
function _delegateTo(
address to,
bytes memory data
) internal returns (bytes memory) {
(bool success, bytes memory result) = to.delegatecall(data);
if (!success) {
if (result.length == 0) revert();
assembly {
revert(add(32, result), mload(result))
}
}
return result;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {
SwapParams,
AddLiquidityParams,
RemoveLiquidityParams
} from "contracts/structs/LiquidityStructs.sol";
struct ZapIn {
SwapParams[] swaps;
AddLiquidityParams addLiquidityParams;
}
struct ZapOut {
RemoveLiquidityParams removeLiquidityParams;
SwapParams[] swaps;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ZapIn, ZapOut } from "contracts/structs/ZapStructs.sol";
interface IZapLib {
function zapIn(
ZapIn memory zap
) external payable;
function zapOut(
ZapOut memory zap
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { SwapParams } from "contracts/structs/LiquidityStructs.sol";
interface ISwapLib {
function swap(
SwapParams memory swap
) external payable;
function swapMultiple(
SwapParams[] memory swaps
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/// @title Admin contract
/// @author vfat.tools
/// @notice Provides an administration mechanism allowing restricted functions
abstract contract Admin {
/// ERRORS ///
/// @notice Thrown when the caller is not the admin
error NotAdminError(); //0xb5c42b3b
/// EVENTS ///
/// @notice Emitted when a new admin is set
/// @param oldAdmin Address of the old admin
/// @param newAdmin Address of the new admin
event AdminSet(address oldAdmin, address newAdmin);
/// STORAGE ///
/// @notice Address of the current admin
address public admin;
/// MODIFIERS ///
/// @dev Restricts a function to the admin
modifier onlyAdmin() {
if (msg.sender != admin) revert NotAdminError();
_;
}
/// WRITE FUNCTIONS ///
/// @param admin_ Address of the admin
constructor(
address admin_
) {
emit AdminSet(address(0), admin_);
admin = admin_;
}
/// @notice Sets a new admin
/// @param newAdmin Address of the new admin
/// @custom:access Restricted to protocol admin.
function setAdmin(
address newAdmin
) external onlyAdmin {
emit AdminSet(admin, newAdmin);
admin = newAdmin;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/// @title TimelockAdmin contract
/// @author vfat.tools
/// @notice Provides an timelockAdministration mechanism allowing restricted
/// functions
abstract contract TimelockAdmin {
/// ERRORS ///
/// @notice Thrown when the caller is not the timelockAdmin
error NotTimelockAdminError();
/// EVENTS ///
/// @notice Emitted when a new timelockAdmin is set
/// @param oldTimelockAdmin Address of the old timelockAdmin
/// @param newTimelockAdmin Address of the new timelockAdmin
event TimelockAdminSet(address oldTimelockAdmin, address newTimelockAdmin);
/// STORAGE ///
/// @notice Address of the current timelockAdmin
address public timelockAdmin;
/// MODIFIERS ///
/// @dev Restricts a function to the timelockAdmin
modifier onlyTimelockAdmin() {
if (msg.sender != timelockAdmin) revert NotTimelockAdminError();
_;
}
/// WRITE FUNCTIONS ///
/// @param timelockAdmin_ Address of the timelockAdmin
constructor(address timelockAdmin_) {
emit TimelockAdminSet(timelockAdmin, timelockAdmin_);
timelockAdmin = timelockAdmin_;
}
/// @notice Sets a new timelockAdmin
/// @dev Can only be called by the current timelockAdmin
/// @param newTimelockAdmin Address of the new timelockAdmin
function setTimelockAdmin(address newTimelockAdmin)
external
onlyTimelockAdmin
{
emit TimelockAdminSet(timelockAdmin, newTimelockAdmin);
timelockAdmin = newTimelockAdmin;
}
}{
"remappings": [
"solmate/=lib/solmate/src/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"@morpho-blue/=lib/morpho-blue/src/",
"ds-test/=lib/solmate/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"morpho-blue/=lib/morpho-blue/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"ApproveFailed","type":"error"},{"inputs":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"address","name":"user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address[]","name":"rewardTokens","type":"address[]"}],"name":"earned","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50610cb4806100206000396000f3fe60806040526004361061004a5760003560e01c80631b89f2001461004f5780638bddf187146100715780639a47bf0814610091578063dd89e3d2146100c7578063dd9e02cd146100da575b600080fd5b34801561005b57600080fd5b5061006f61006a366004610859565b610108565b005b34801561007d57600080fd5b5061006f61008c3660046108b1565b610179565b34801561009d57600080fd5b506100b16100ac366004610918565b6101b2565b6040516100be91906109ac565b60405180910390f35b61006f6100d53660046109f0565b6102f1565b3480156100e657600080fd5b506100fa6100f5366004610a3b565b6103e7565b6040519081526020016100be565b6101156020840184610a73565b6001600160a01b0316632e1a7d4d836040518263ffffffff1660e01b815260040161014291815260200190565b600060405180830381600087803b15801561015c57600080fd5b505af1158015610170573d6000803e3d6000fd5b50505050505050565b60008180602001905181019061018f9190610aa4565b90506101ad6101a16020850185610a73565b82516020840151610469565b505050565b606060008267ffffffffffffffff8111156101cf576101cf610779565b6040519080825280602002602001820160405280156101f8578160200160208202803683370190505b50905060005b838110156102e7576102136020880188610a73565b6001600160a01b031663211dc32d86868481811061023357610233610b94565b90506020020160208101906102489190610a73565b6040516001600160e01b031960e084901b1681526001600160a01b0391821660048201529089166024820152604401602060405180830381865afa158015610294573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b89190610baa565b8282815181106102ca576102ca610b94565b6020908102919091010152806102df81610bc3565b9150506101fe565b5095945050505050565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610338573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035c9190610baa565b90506103758361036f6020870187610a73565b8361070a565b6103826020850185610a73565b6001600160a01b031663b6b55f25826040518263ffffffff1660e01b81526004016103af91815260200190565b600060405180830381600087803b1580156103c957600080fd5b505af11580156103dd573d6000803e3d6000fd5b5050505050505050565b60006103f66020840184610a73565b6040516370a0823160e01b81526001600160a01b03848116600483015291909116906370a0823190602401602060405180830381865afa15801561043e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104629190610baa565b9392505050565b6040516331279d3d60e01b81526001600160a01b038416906331279d3d906104979030908690600401610bea565b600060405180830381600087803b1580156104b157600080fd5b505af11580156104c5573d6000803e3d6000fd5b50506040516370a0823160e01b815230600482015260009250735050bc082ff4a74fb6b0b04385defddb114b242491506370a0823190602401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190610baa565b9050801561070457600182600281111561055b5761055b610c46565b036106735760405163095ea7b360e01b8152739710e10a8f6fba8c391606fee18614885684548d600482015260248101829052735050bc082ff4a74fb6b0b04385defddb114b24249063095ea7b3906044016020604051808303816000875af11580156105cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f09190610c5c565b50604051636e553f6560e01b815260048101829052306024820152739710e10a8f6fba8c391606fee18614885684548d90636e553f65906044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610baa565b50610704565b600082600281111561068757610687610c46565b0361070457604051637f8661a160e01b815260048101829052735050bc082ff4a74fb6b0b04385defddb114b242490637f8661a1906024016020604051808303816000875af11580156106de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107029190610baa565b505b50505050565b600060405163095ea7b360e01b8152836004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061070457604051633e3f8f7360e01b815260040160405180910390fd5b60006040828403121561077357600080fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156107b2576107b2610779565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156107e1576107e1610779565b604052919050565b600082601f8301126107fa57600080fd5b813567ffffffffffffffff81111561081457610814610779565b610827601f8201601f19166020016107b8565b81815284602083860101111561083c57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006080848603121561086e57600080fd5b6108788585610761565b925060408401359150606084013567ffffffffffffffff81111561089b57600080fd5b6108a7868287016107e9565b9150509250925092565b600080606083850312156108c457600080fd5b6108ce8484610761565b9150604083013567ffffffffffffffff8111156108ea57600080fd5b6108f6858286016107e9565b9150509250929050565b6001600160a01b038116811461091557600080fd5b50565b6000806000806080858703121561092e57600080fd5b6109388686610761565b9350604085013561094881610900565b9250606085013567ffffffffffffffff8082111561096557600080fd5b818701915087601f83011261097957600080fd5b81358181111561098857600080fd5b8860208260051b850101111561099d57600080fd5b95989497505060200194505050565b6020808252825182820181905260009190848201906040850190845b818110156109e4578351835292840192918401916001016109c8565b50909695505050505050565b600080600060808486031215610a0557600080fd5b610a0f8585610761565b92506040840135610a1f81610900565b9150606084013567ffffffffffffffff81111561089b57600080fd5b60008060608385031215610a4e57600080fd5b610a588484610761565b91506040830135610a6881610900565b809150509250929050565b600060208284031215610a8557600080fd5b813561046281610900565b805160038110610a9f57600080fd5b919050565b60006020808385031215610ab757600080fd5b825167ffffffffffffffff80821115610acf57600080fd5b9084019060408287031215610ae357600080fd5b610aeb61078f565b825182811115610afa57600080fd5b8301601f81018813610b0b57600080fd5b805183811115610b1d57610b1d610779565b8060051b9350610b2e8685016107b8565b818152938201860193868101908a861115610b4857600080fd5b928701925b85841015610b725783519250610b6283610900565b8282529287019290870190610b4d565b845250610b83915050838501610a90565b848201528094505050505092915050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215610bbc57600080fd5b5051919050565b600060018201610be357634e487b7160e01b600052601160045260246000fd5b5060010190565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b81811015610c38578551851683529483019491830191600101610c1a565b509098975050505050505050565b634e487b7160e01b600052602160045260246000fd5b600060208284031215610c6e57600080fd5b8151801515811461046257600080fdfea2646970667358221220ece59e4f4bf9f7e265feed3dc996a1e65e1609fe58cbf4703aa03d43d6b6c4d864736f6c63430008130033
Deployed Bytecode
0x60806040526004361061004a5760003560e01c80631b89f2001461004f5780638bddf187146100715780639a47bf0814610091578063dd89e3d2146100c7578063dd9e02cd146100da575b600080fd5b34801561005b57600080fd5b5061006f61006a366004610859565b610108565b005b34801561007d57600080fd5b5061006f61008c3660046108b1565b610179565b34801561009d57600080fd5b506100b16100ac366004610918565b6101b2565b6040516100be91906109ac565b60405180910390f35b61006f6100d53660046109f0565b6102f1565b3480156100e657600080fd5b506100fa6100f5366004610a3b565b6103e7565b6040519081526020016100be565b6101156020840184610a73565b6001600160a01b0316632e1a7d4d836040518263ffffffff1660e01b815260040161014291815260200190565b600060405180830381600087803b15801561015c57600080fd5b505af1158015610170573d6000803e3d6000fd5b50505050505050565b60008180602001905181019061018f9190610aa4565b90506101ad6101a16020850185610a73565b82516020840151610469565b505050565b606060008267ffffffffffffffff8111156101cf576101cf610779565b6040519080825280602002602001820160405280156101f8578160200160208202803683370190505b50905060005b838110156102e7576102136020880188610a73565b6001600160a01b031663211dc32d86868481811061023357610233610b94565b90506020020160208101906102489190610a73565b6040516001600160e01b031960e084901b1681526001600160a01b0391821660048201529089166024820152604401602060405180830381865afa158015610294573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b89190610baa565b8282815181106102ca576102ca610b94565b6020908102919091010152806102df81610bc3565b9150506101fe565b5095945050505050565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610338573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061035c9190610baa565b90506103758361036f6020870187610a73565b8361070a565b6103826020850185610a73565b6001600160a01b031663b6b55f25826040518263ffffffff1660e01b81526004016103af91815260200190565b600060405180830381600087803b1580156103c957600080fd5b505af11580156103dd573d6000803e3d6000fd5b5050505050505050565b60006103f66020840184610a73565b6040516370a0823160e01b81526001600160a01b03848116600483015291909116906370a0823190602401602060405180830381865afa15801561043e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104629190610baa565b9392505050565b6040516331279d3d60e01b81526001600160a01b038416906331279d3d906104979030908690600401610bea565b600060405180830381600087803b1580156104b157600080fd5b505af11580156104c5573d6000803e3d6000fd5b50506040516370a0823160e01b815230600482015260009250735050bc082ff4a74fb6b0b04385defddb114b242491506370a0823190602401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190610baa565b9050801561070457600182600281111561055b5761055b610c46565b036106735760405163095ea7b360e01b8152739710e10a8f6fba8c391606fee18614885684548d600482015260248101829052735050bc082ff4a74fb6b0b04385defddb114b24249063095ea7b3906044016020604051808303816000875af11580156105cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f09190610c5c565b50604051636e553f6560e01b815260048101829052306024820152739710e10a8f6fba8c391606fee18614885684548d90636e553f65906044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610baa565b50610704565b600082600281111561068757610687610c46565b0361070457604051637f8661a160e01b815260048101829052735050bc082ff4a74fb6b0b04385defddb114b242490637f8661a1906024016020604051808303816000875af11580156106de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107029190610baa565b505b50505050565b600060405163095ea7b360e01b8152836004820152826024820152602060006044836000895af13d15601f3d116001600051141617169150508061070457604051633e3f8f7360e01b815260040160405180910390fd5b60006040828403121561077357600080fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156107b2576107b2610779565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156107e1576107e1610779565b604052919050565b600082601f8301126107fa57600080fd5b813567ffffffffffffffff81111561081457610814610779565b610827601f8201601f19166020016107b8565b81815284602083860101111561083c57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060006080848603121561086e57600080fd5b6108788585610761565b925060408401359150606084013567ffffffffffffffff81111561089b57600080fd5b6108a7868287016107e9565b9150509250925092565b600080606083850312156108c457600080fd5b6108ce8484610761565b9150604083013567ffffffffffffffff8111156108ea57600080fd5b6108f6858286016107e9565b9150509250929050565b6001600160a01b038116811461091557600080fd5b50565b6000806000806080858703121561092e57600080fd5b6109388686610761565b9350604085013561094881610900565b9250606085013567ffffffffffffffff8082111561096557600080fd5b818701915087601f83011261097957600080fd5b81358181111561098857600080fd5b8860208260051b850101111561099d57600080fd5b95989497505060200194505050565b6020808252825182820181905260009190848201906040850190845b818110156109e4578351835292840192918401916001016109c8565b50909695505050505050565b600080600060808486031215610a0557600080fd5b610a0f8585610761565b92506040840135610a1f81610900565b9150606084013567ffffffffffffffff81111561089b57600080fd5b60008060608385031215610a4e57600080fd5b610a588484610761565b91506040830135610a6881610900565b809150509250929050565b600060208284031215610a8557600080fd5b813561046281610900565b805160038110610a9f57600080fd5b919050565b60006020808385031215610ab757600080fd5b825167ffffffffffffffff80821115610acf57600080fd5b9084019060408287031215610ae357600080fd5b610aeb61078f565b825182811115610afa57600080fd5b8301601f81018813610b0b57600080fd5b805183811115610b1d57610b1d610779565b8060051b9350610b2e8685016107b8565b818152938201860193868101908a861115610b4857600080fd5b928701925b85841015610b725783519250610b6283610900565b8282529287019290870190610b4d565b845250610b83915050838501610a90565b848201528094505050505092915050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215610bbc57600080fd5b5051919050565b600060018201610be357634e487b7160e01b600052601160045260246000fd5b5060010190565b6001600160a01b038381168252604060208084018290528451918401829052600092858201929091906060860190855b81811015610c38578551851683529483019491830191600101610c1a565b509098975050505050505050565b634e487b7160e01b600052602160045260246000fd5b600060208284031215610c6e57600080fd5b8151801515811461046257600080fdfea2646970667358221220ece59e4f4bf9f7e265feed3dc996a1e65e1609fe58cbf4703aa03d43d6b6c4d864736f6c63430008130033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in S
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.