Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 243555861 | 533 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
StopLoss
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 20000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;
import {IERC20, GPv2Order, IConditionalOrder, BaseConditionalOrder} from "../BaseConditionalOrder.sol";
import {IAggregatorV3Interface} from "../interfaces/IAggregatorV3Interface.sol";
import {ConditionalOrdersUtilsLib as Utils} from "./ConditionalOrdersUtilsLib.sol";
// --- error strings
/// @dev Invalid price data returned by the oracle
string constant ORACLE_INVALID_PRICE = "oracle invalid price";
/// @dev The oracle has returned stale data
string constant ORACLE_STALE_PRICE = "oracle stale price";
/// @dev The strike price has not been reached
string constant STRIKE_NOT_REACHED = "strike not reached";
/// @dev The order is not valid anymore
string constant ORDER_EXPIRED = "order expired";
/**
* @title StopLoss conditional order
* Requires providing two price oracles (e.g. chainlink) and a strike price. If the sellToken price falls below the strike price, the order will be triggered
* @notice Both oracles need to be denominated in the same quote currency (e.g. GNO/ETH and USD/ETH for GNO/USD stop loss orders)
* @dev This order type has replay protection due to the `validTo` parameter, ensuring it will just execute one time
*/
contract StopLoss is BaseConditionalOrder {
/// @dev Scaling factor for the strike price
int256 constant SCALING_FACTOR = 10 ** 18;
/**
* Defines the parameters of a StopLoss order
* @param sellToken: the token to be sold
* @param buyToken: the token to be bought
* @param sellAmount: In case of a sell order, the exact amount of tokens the order is willing to sell. In case of a buy order, the maximium amount of tokens it is willing to sell
* @param buyAmount: In case of a sell order, the min amount of tokens the order is wants to receive. In case of a buy order, the exact amount of tokens it is willing to receive
* @param appData: The IPFS hash of the appData associated with the order
* @param receiver: The account that should receive the proceeds of the trade
* @param isSellOrder: Whether this is a sell or buy order
* @param isPartiallyFillable: Whether solvers are allowed to only fill a fraction of the order (useful if exact sell or buy amount isn't know at time of placement)
* @param validTo: The UNIX timestamp before which this order is valid
* @param sellTokenPriceOracle: A chainlink-like oracle returning the current sell token price in a given numeraire
* @param buyTokenPriceOracle: A chainlink-like oracle returning the current buy token price in the same numeraire
* @param strike: The exchange rate (denominated in sellToken/buyToken) which triggers the StopLoss order if the oracle price falls below. Specified in base / quote with 18 decimals.
* @param maxTimeSinceLastOracleUpdate: The maximum time since the last oracle update. If the oracle hasn't been updated in this time, the order will be considered invalid
*/
struct Data {
IERC20 sellToken;
IERC20 buyToken;
uint256 sellAmount;
uint256 buyAmount;
bytes32 appData;
address receiver;
bool isSellOrder;
bool isPartiallyFillable;
uint32 validTo;
IAggregatorV3Interface sellTokenPriceOracle;
IAggregatorV3Interface buyTokenPriceOracle;
int256 strike;
uint256 maxTimeSinceLastOracleUpdate;
}
function getTradeableOrder(address, address, bytes32, bytes calldata staticInput, bytes calldata)
public
view
override
returns (GPv2Order.Data memory order)
{
Data memory data = abi.decode(staticInput, (Data));
// scope variables to avoid stack too deep error
{
/// @dev Guard against expired orders
if (data.validTo < block.timestamp) {
revert IConditionalOrder.OrderNotValid(ORDER_EXPIRED);
}
(, int256 basePrice,, uint256 sellUpdatedAt,) = data.sellTokenPriceOracle.latestRoundData();
(, int256 quotePrice,, uint256 buyUpdatedAt,) = data.buyTokenPriceOracle.latestRoundData();
/// @dev Guard against invalid price data
if (!(basePrice > 0 && quotePrice > 0)) {
revert IConditionalOrder.OrderNotValid(ORACLE_INVALID_PRICE);
}
/// @dev Guard against stale data at a user-specified interval. The maxTimeSinceLastOracleUpdate should at least exceed the both oracles' update intervals.
if (
!(
sellUpdatedAt >= block.timestamp - data.maxTimeSinceLastOracleUpdate
&& buyUpdatedAt >= block.timestamp - data.maxTimeSinceLastOracleUpdate
)
) {
revert IConditionalOrder.PollTryNextBlock(ORACLE_STALE_PRICE);
}
// Normalize the decimals for basePrice and quotePrice, scaling them to 18 decimals
// Caution: Ensure that base and quote have the same numeraires (e.g. both are denominated in USD)
basePrice = Utils.scalePrice(basePrice, data.sellTokenPriceOracle.decimals(), 18);
quotePrice = Utils.scalePrice(quotePrice, data.buyTokenPriceOracle.decimals(), 18);
/// @dev Scale the strike price to 18 decimals.
if (!(basePrice * SCALING_FACTOR / quotePrice <= data.strike)) {
revert IConditionalOrder.PollTryNextBlock(STRIKE_NOT_REACHED);
}
}
order = GPv2Order.Data(
data.sellToken,
data.buyToken,
data.receiver,
data.sellAmount,
data.buyAmount,
data.validTo,
data.appData,
0, // use zero fee for limit orders
data.isSellOrder ? GPv2Order.KIND_SELL : GPv2Order.KIND_BUY,
data.isPartiallyFillable,
GPv2Order.BALANCE_ERC20,
GPv2Order.BALANCE_ERC20
);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
import {GPv2Order, IERC20} from "cowprotocol/contracts/libraries/GPv2Order.sol";
import {IERC165, IConditionalOrder, IConditionalOrderGenerator} from "./interfaces/IConditionalOrder.sol";
// --- error strings
/// @dev This error is returned by the `verify` function if the *generated* order hash does not match
/// the hash passed as a parameter.
string constant INVALID_HASH = "invalid hash";
/**
* @title Base logic for conditional orders.
* @dev Enforces the order verification logic for conditional orders, allowing developers
* to focus on the logic for generating the tradeable order.
* @author mfw78 <[email protected]>
*/
abstract contract BaseConditionalOrder is IConditionalOrderGenerator {
/**
* @inheritdoc IConditionalOrder
* @dev As an order generator, the `GPv2Order.Data` passed as a parameter is ignored / not validated.
*/
function verify(
address owner,
address sender,
bytes32 _hash,
bytes32 domainSeparator,
bytes32 ctx,
bytes calldata staticInput,
bytes calldata offchainInput,
GPv2Order.Data calldata
) external view override {
GPv2Order.Data memory generatedOrder = getTradeableOrder(owner, sender, ctx, staticInput, offchainInput);
/// @dev Verify that the *generated* order is valid and matches the payload.
if (!(_hash == GPv2Order.hash(generatedOrder, domainSeparator))) {
revert IConditionalOrder.OrderNotValid(INVALID_HASH);
}
}
/**
* @dev Set the visibility of this function to `public` to allow `verify` to call it.
* @inheritdoc IConditionalOrderGenerator
*/
function getTradeableOrder(
address owner,
address sender,
bytes32 ctx,
bytes calldata staticInput,
bytes calldata offchainInput
) public view virtual override returns (GPv2Order.Data memory);
/**
* @inheritdoc IERC165
*/
function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {
return interfaceId == type(IConditionalOrderGenerator).interfaceId || interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;
interface IAggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
function getRoundData(uint80 _roundId)
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
function latestRoundData()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; /** * @title ConditionalOrdersUtilsLib - Utility functions for standardising conditional orders. * @author mfw78 <[email protected]> */ library ConditionalOrdersUtilsLib { uint256 constant MAX_BPS = 10000; /** * Given the width of the validity bucket, return the timestamp of the *end* of the bucket. * @param validity The width of the validity bucket in seconds. */ function validToBucket(uint32 validity) internal view returns (uint32 validTo) { validTo = ((uint32(block.timestamp) / validity) * validity) + validity; } /** * Given a price returned by a chainlink-like oracle, scale it to the desired amount of decimals * @param oraclePrice return by a chainlink-like oracle * @param fromDecimals the decimals the oracle returned (e.g. 8 for USDC) * @param toDecimals the amount of decimals the price should be scaled to */ function scalePrice(int256 oraclePrice, uint8 fromDecimals, uint8 toDecimals) internal pure returns (int256) { if (fromDecimals < toDecimals) { return oraclePrice * int256(10 ** uint256(toDecimals - fromDecimals)); } else if (fromDecimals > toDecimals) { return oraclePrice / int256(10 ** uint256(fromDecimals - toDecimals)); } return oraclePrice; } }
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity >=0.7.6 <0.9.0;
import "../interfaces/IERC20.sol";
/// @title Gnosis Protocol v2 Order Library
/// @author Gnosis Developers
library GPv2Order {
/// @dev The complete data for a Gnosis Protocol order. This struct contains
/// all order parameters that are signed for submitting to GP.
struct Data {
IERC20 sellToken;
IERC20 buyToken;
address receiver;
uint256 sellAmount;
uint256 buyAmount;
uint32 validTo;
bytes32 appData;
uint256 feeAmount;
bytes32 kind;
bool partiallyFillable;
bytes32 sellTokenBalance;
bytes32 buyTokenBalance;
}
/// @dev The order EIP-712 type hash for the [`GPv2Order.Data`] struct.
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256(
/// "Order(" +
/// "address sellToken," +
/// "address buyToken," +
/// "address receiver," +
/// "uint256 sellAmount," +
/// "uint256 buyAmount," +
/// "uint32 validTo," +
/// "bytes32 appData," +
/// "uint256 feeAmount," +
/// "string kind," +
/// "bool partiallyFillable," +
/// "string sellTokenBalance," +
/// "string buyTokenBalance" +
/// ")"
/// )
/// ```
bytes32 internal constant TYPE_HASH =
hex"d5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e489";
/// @dev The marker value for a sell order for computing the order struct
/// hash. This allows the EIP-712 compatible wallets to display a
/// descriptive string for the order kind (instead of 0 or 1).
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256("sell")
/// ```
bytes32 internal constant KIND_SELL =
hex"f3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee346775";
/// @dev The OrderKind marker value for a buy order for computing the order
/// struct hash.
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256("buy")
/// ```
bytes32 internal constant KIND_BUY =
hex"6ed88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc";
/// @dev The TokenBalance marker value for using direct ERC20 balances for
/// computing the order struct hash.
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256("erc20")
/// ```
bytes32 internal constant BALANCE_ERC20 =
hex"5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9";
/// @dev The TokenBalance marker value for using Balancer Vault external
/// balances (in order to re-use Vault ERC20 approvals) for computing the
/// order struct hash.
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256("external")
/// ```
bytes32 internal constant BALANCE_EXTERNAL =
hex"abee3b73373acd583a130924aad6dc38cfdc44ba0555ba94ce2ff63980ea0632";
/// @dev The TokenBalance marker value for using Balancer Vault internal
/// balances for computing the order struct hash.
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256("internal")
/// ```
bytes32 internal constant BALANCE_INTERNAL =
hex"4ac99ace14ee0a5ef932dc609df0943ab7ac16b7583634612f8dc35a4289a6ce";
/// @dev Marker address used to indicate that the receiver of the trade
/// proceeds should the owner of the order.
///
/// This is chosen to be `address(0)` for gas efficiency as it is expected
/// to be the most common case.
address internal constant RECEIVER_SAME_AS_OWNER = address(0);
/// @dev The byte length of an order unique identifier.
uint256 internal constant UID_LENGTH = 56;
/// @dev Returns the actual receiver for an order. This function checks
/// whether or not the [`receiver`] field uses the marker value to indicate
/// it is the same as the order owner.
///
/// @return receiver The actual receiver of trade proceeds.
function actualReceiver(
Data memory order,
address owner
) internal pure returns (address receiver) {
if (order.receiver == RECEIVER_SAME_AS_OWNER) {
receiver = owner;
} else {
receiver = order.receiver;
}
}
/// @dev Return the EIP-712 signing hash for the specified order.
///
/// @param order The order to compute the EIP-712 signing hash for.
/// @param domainSeparator The EIP-712 domain separator to use.
/// @return orderDigest The 32 byte EIP-712 struct hash.
function hash(
Data memory order,
bytes32 domainSeparator
) internal pure returns (bytes32 orderDigest) {
bytes32 structHash;
// NOTE: Compute the EIP-712 order struct hash in place. As suggested
// in the EIP proposal, noting that the order struct has 12 fields, and
// prefixing the type hash `(1 + 12) * 32 = 416` bytes to hash.
// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#rationale-for-encodedata>
// solhint-disable-next-line no-inline-assembly
assembly {
let dataStart := sub(order, 32)
let temp := mload(dataStart)
mstore(dataStart, TYPE_HASH)
structHash := keccak256(dataStart, 416)
mstore(dataStart, temp)
}
// NOTE: Now that we have the struct hash, compute the EIP-712 signing
// hash using scratch memory past the free memory pointer. The signing
// hash is computed from `"\x19\x01" || domainSeparator || structHash`.
// <https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html#layout-in-memory>
// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#specification>
// solhint-disable-next-line no-inline-assembly
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, "\x19\x01")
mstore(add(freeMemoryPointer, 2), domainSeparator)
mstore(add(freeMemoryPointer, 34), structHash)
orderDigest := keccak256(freeMemoryPointer, 66)
}
}
/// @dev Packs order UID parameters into the specified memory location. The
/// result is equivalent to `abi.encodePacked(...)` with the difference that
/// it allows re-using the memory for packing the order UID.
///
/// This function reverts if the order UID buffer is not the correct size.
///
/// @param orderUid The buffer pack the order UID parameters into.
/// @param orderDigest The EIP-712 struct digest derived from the order
/// parameters.
/// @param owner The address of the user who owns this order.
/// @param validTo The epoch time at which the order will stop being valid.
function packOrderUidParams(
bytes memory orderUid,
bytes32 orderDigest,
address owner,
uint32 validTo
) internal pure {
require(orderUid.length == UID_LENGTH, "GPv2: uid buffer overflow");
// NOTE: Write the order UID to the allocated memory buffer. The order
// parameters are written to memory in **reverse order** as memory
// operations write 32-bytes at a time and we want to use a packed
// encoding. This means, for example, that after writing the value of
// `owner` to bytes `20:52`, writing the `orderDigest` to bytes `0:32`
// will **overwrite** bytes `20:32`. This is desirable as addresses are
// only 20 bytes and `20:32` should be `0`s:
//
// | 1111111111222222222233333333334444444444555555
// byte | 01234567890123456789012345678901234567890123456789012345
// -------+---------------------------------------------------------
// field | [.........orderDigest..........][......owner.......][vT]
// -------+---------------------------------------------------------
// mstore | [000000000000000000000000000.vT]
// | [00000000000.......owner.......]
// | [.........orderDigest..........]
//
// Additionally, since Solidity `bytes memory` are length prefixed,
// 32 needs to be added to all the offsets.
//
// solhint-disable-next-line no-inline-assembly
assembly {
mstore(add(orderUid, 56), validTo)
mstore(add(orderUid, 52), owner)
mstore(add(orderUid, 32), orderDigest)
}
}
/// @dev Extracts specific order information from the standardized unique
/// order id of the protocol.
///
/// @param orderUid The unique identifier used to represent an order in
/// the protocol. This uid is the packed concatenation of the order digest,
/// the validTo order parameter and the address of the user who created the
/// order. It is used by the user to interface with the contract directly,
/// and not by calls that are triggered by the solvers.
/// @return orderDigest The EIP-712 signing digest derived from the order
/// parameters.
/// @return owner The address of the user who owns this order.
/// @return validTo The epoch time at which the order will stop being valid.
function extractOrderUidParams(
bytes calldata orderUid
)
internal
pure
returns (bytes32 orderDigest, address owner, uint32 validTo)
{
require(orderUid.length == UID_LENGTH, "GPv2: invalid uid");
// Use assembly to efficiently decode packed calldata.
// solhint-disable-next-line no-inline-assembly
assembly {
orderDigest := calldataload(orderUid.offset)
owner := shr(96, calldataload(add(orderUid.offset, 32)))
validTo := shr(224, calldataload(add(orderUid.offset, 52)))
}
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0 <0.9.0;
import {GPv2Order} from "cowprotocol/contracts/libraries/GPv2Order.sol";
import {GPv2Interaction} from "cowprotocol/contracts/libraries/GPv2Interaction.sol";
import {IERC165} from "safe/interfaces/IERC165.sol";
/**
* @title Conditional Order Interface
* @author CoW Protocol Developers + mfw78 <[email protected]>
*/
interface IConditionalOrder {
/// @dev This error is returned by the `getTradeableOrder` function if the order condition is not met.
/// A parameter of `string` type is included to allow the caller to specify the reason for the failure.
error OrderNotValid(string);
// --- errors specific for polling
// Signal to a watch tower that polling should be attempted again.
error PollTryNextBlock(string reason);
// Signal to a watch tower that polling should be attempted again at a specific block number.
error PollTryAtBlock(uint256 blockNumber, string reason);
// Signal to a watch tower that polling should be attempted again at a specific epoch (unix timestamp).
error PollTryAtEpoch(uint256 timestamp, string reason);
// Signal to a watch tower that the conditional order should not be polled again (delete).
error PollNever(string reason);
/**
* @dev This struct is used to uniquely identify a conditional order for an owner.
* H(handler || salt || staticInput) **MUST** be unique for an owner.
*/
struct ConditionalOrderParams {
IConditionalOrder handler;
bytes32 salt;
bytes staticInput;
}
/**
* Verify if a given discrete order is valid.
* @dev Used in combination with `isValidSafeSignature` to verify that the order is signed by the Safe.
* **MUST** revert if the order condition is not met.
* @dev The `order` parameter is ignored / not validated by the `IConditionalOrderGenerator` implementation.
* This parameter is included to allow more granular control over the order verification logic, and to
* allow a watch tower / user to propose a discrete order without it being generated by on-chain logic.
* @param owner the contract who is the owner of the order
* @param sender the `msg.sender` of the transaction
* @param _hash the hash of the order
* @param domainSeparator the domain separator used to sign the order
* @param ctx the context key of the order (bytes32(0) if a merkle tree is used, otherwise H(params)) with which to lookup the cabinet
* @param staticInput the static input for all discrete orders cut from this conditional order
* @param offchainInput dynamic off-chain input for a discrete order cut from this conditional order
* @param order `GPv2Order.Data` of a discrete order to be verified (if *not* an `IConditionalOrderGenerator`).
*/
function verify(
address owner,
address sender,
bytes32 _hash,
bytes32 domainSeparator,
bytes32 ctx,
bytes calldata staticInput,
bytes calldata offchainInput,
GPv2Order.Data calldata order
) external view;
}
/**
* @title Conditional Order Generator Interface
* @author mfw78 <[email protected]>
*/
interface IConditionalOrderGenerator is IConditionalOrder, IERC165 {
/**
* @dev This event is emitted when a new conditional order is created.
* @param owner the address that has created the conditional order
* @param params the address / salt / data of the conditional order
*/
event ConditionalOrderCreated(address indexed owner, IConditionalOrder.ConditionalOrderParams params);
/**
* @dev Get a tradeable order that can be posted to the CoW Protocol API and would pass signature validation.
* **MUST** revert if the order condition is not met.
* @param owner the contract who is the owner of the order
* @param sender the `msg.sender` of the parent `isValidSignature` call
* @param ctx the context of the order (bytes32(0) if merkle tree is used, otherwise the H(params))
* @param staticInput the static input for all discrete orders cut from this conditional order
* @param offchainInput dynamic off-chain input for a discrete order cut from this conditional order
* @return the tradeable order for submission to the CoW Protocol API
*/
function getTradeableOrder(
address owner,
address sender,
bytes32 ctx,
bytes calldata staticInput,
bytes calldata offchainInput
) external view returns (GPv2Order.Data memory);
}// SPDX-License-Identifier: MIT
// Vendored from OpenZeppelin contracts with minor modifications:
// - Modified Solidity version
// - Formatted code
// - Added `name`, `symbol` and `decimals` function declarations
// <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/token/ERC20/IERC20.sol>
pragma solidity >=0.7.6 <0.9.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(
address owner,
address spender
) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity >=0.7.6 <0.9.0;
/// @title Gnosis Protocol v2 Interaction Library
/// @author Gnosis Developers
library GPv2Interaction {
/// @dev Interaction data for performing arbitrary contract interactions.
/// Submitted to [`GPv2Settlement.settle`] for code execution.
struct Data {
address target;
uint256 value;
bytes callData;
}
/// @dev Execute an arbitrary contract interaction.
///
/// @param interaction Interaction data.
function execute(Data calldata interaction) internal {
address target = interaction.target;
uint256 value = interaction.value;
bytes calldata callData = interaction.callData;
// NOTE: Use assembly to call the interaction instead of a low level
// call for two reasons:
// - We don't want to copy the return data, since we discard it for
// interactions.
// - Solidity will under certain conditions generate code to copy input
// calldata twice to memory (the second being a "memcopy loop").
// <https://github.com/gnosis/gp-v2-contracts/pull/417#issuecomment-775091258>
// solhint-disable-next-line no-inline-assembly
assembly {
let freeMemoryPointer := mload(0x40)
calldatacopy(freeMemoryPointer, callData.offset, callData.length)
if iszero(
call(
gas(),
target,
value,
freeMemoryPointer,
callData.length,
0,
0
)
) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
/// @dev Extracts the Solidity ABI selector for the specified interaction.
///
/// @param interaction Interaction data.
/// @return result The 4 byte function selector of the call encoded in
/// this interaction.
function selector(
Data calldata interaction
) internal pure returns (bytes4 result) {
bytes calldata callData = interaction.callData;
if (callData.length >= 4) {
// NOTE: Read the first word of the interaction's calldata. The
// value does not need to be shifted since `bytesN` values are left
// aligned, and the value does not need to be masked since masking
// occurs when the value is accessed and not stored:
// <https://docs.soliditylang.org/en/v0.7.6/abi-spec.html#encoding-of-indexed-event-parameters>
// <https://docs.soliditylang.org/en/v0.7.6/assembly.html#access-to-external-variables-functions-and-libraries>
// solhint-disable-next-line no-inline-assembly
assembly {
result := calldataload(callData.offset)
}
}
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/// @notice More details at https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/introspection/IERC165.sol
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by `interfaceId`.
* See the corresponding EIP section
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified
* 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);
}{
"remappings": [
"@openzeppelin/=lib/@openzeppelin/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/@openzeppelin/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"murky/=lib/murky/src/",
"openzeppelin-contracts/=lib/murky/lib/openzeppelin-contracts/",
"safe/=lib/safe/contracts/",
"cowprotocol/=lib/cowprotocol/src/",
"openzeppelin/=lib/@openzeppelin/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 20000
},
"modelChecker": {
"contracts": {
"/workspaces/composable-cow/src/types/twap/libraries/TWAPOrderMathLib.sol": [
"TWAPOrderMathLib"
]
},
"engine": "chc",
"timeout": 100000,
"targets": [
"assert",
"underflow",
"overflow",
"divByZero",
"constantCondition",
"popEmptyArray",
"outOfBounds",
"balance"
]
},
"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":[{"internalType":"string","name":"","type":"string"}],"name":"OrderNotValid","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"PollNever","type":"error"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"string","name":"reason","type":"string"}],"name":"PollTryAtBlock","type":"error"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"string","name":"reason","type":"string"}],"name":"PollTryAtEpoch","type":"error"},{"inputs":[{"internalType":"string","name":"reason","type":"string"}],"name":"PollTryNextBlock","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"contract IConditionalOrder","name":"handler","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"staticInput","type":"bytes"}],"indexed":false,"internalType":"struct IConditionalOrder.ConditionalOrderParams","name":"params","type":"tuple"}],"name":"ConditionalOrderCreated","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"staticInput","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"getTradeableOrder","outputs":[{"components":[{"internalType":"contract IERC20","name":"sellToken","type":"address"},{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes32","name":"kind","type":"bytes32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"bytes32","name":"sellTokenBalance","type":"bytes32"},{"internalType":"bytes32","name":"buyTokenBalance","type":"bytes32"}],"internalType":"struct GPv2Order.Data","name":"order","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"},{"internalType":"bytes32","name":"ctx","type":"bytes32"},{"internalType":"bytes","name":"staticInput","type":"bytes"},{"internalType":"bytes","name":"offchainInput","type":"bytes"},{"components":[{"internalType":"contract IERC20","name":"sellToken","type":"address"},{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes32","name":"kind","type":"bytes32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"bytes32","name":"sellTokenBalance","type":"bytes32"},{"internalType":"bytes32","name":"buyTokenBalance","type":"bytes32"}],"internalType":"struct GPv2Order.Data","name":"","type":"tuple"}],"name":"verify","outputs":[],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b506110a3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806301ffc9a71461004657806314a2a7841461006e578063b8296fc414610083575b600080fd5b610059610054366004610885565b6100a3565b60405190151581526020015b60405180910390f35b61008161007c366004610945565b61013c565b005b610096610091366004610a33565b610259565b6040516100659190610ad2565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fb8296fc400000000000000000000000000000000000000000000000000000000148061013657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b600061014d8b8b8989898989610259565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810180517fd5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e48982526101a0822091526040517f19010000000000000000000000000000000000000000000000000000000000008152600281018b9052602281019190915260429020909150891461024c57604080518082018252600c81527f696e76616c696420686173680000000000000000000000000000000000000000602082015290517fc8fc27250000000000000000000000000000000000000000000000000000000081526102439190600401610bc0565b60405180910390fd5b5050505050505050505050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290526101608101829052906102c686860187610ca1565b90504281610100015163ffffffff16101561034057604080518082018252600d81527f6f72646572206578706972656400000000000000000000000000000000000000602082015290517fc8fc27250000000000000000000000000000000000000000000000000000000081526102439190600401610bc0565b60008082610120015173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b79190610d98565b5093505092505060008084610140015173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610411573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104359190610d98565b5093505092505060008413801561044c5750600082135b6104b557604080518082018252601481527f6f7261636c6520696e76616c6964207072696365000000000000000000000000602082015290517fc8fc27250000000000000000000000000000000000000000000000000000000081526102439190600401610bc0565b6101808501516104c59042610e17565b83101580156104e357506101808501516104df9042610e17565b8110155b61054c57604080518082018252601281527f6f7261636c65207374616c652070726963650000000000000000000000000000602082015290517fd05f30650000000000000000000000000000000000000000000000000000000081526102439190600401610bc0565b6105cb8486610120015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c49190610e2a565b6012610812565b93506106218286610140015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105a0573d6000803e3d6000fd5b6101608601519092508261063d670de0b6b3a764000087610e4d565b6106479190610e99565b13156106b257604080518082018252601281527f737472696b65206e6f7420726561636865640000000000000000000000000000602082015290517fd05f30650000000000000000000000000000000000000000000000000000000081526102439190600401610bc0565b50505050604051806101800160405280826000015173ffffffffffffffffffffffffffffffffffffffff168152602001826020015173ffffffffffffffffffffffffffffffffffffffff1681526020018260a0015173ffffffffffffffffffffffffffffffffffffffff168152602001826040015181526020018260600151815260200182610100015163ffffffff16815260200182608001518152602001600081526020018260c00151610787577f6ed88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc6107a9565b7ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee3467755b81526020018260e00151151581526020017f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc981526020017f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9815250915050979650505050505050565b60008160ff168360ff16101561084b5761082c8383610f28565b61083a9060ff16600a611061565b6108449085610e4d565b905061087e565b8160ff168360ff16111561087b576108638284610f28565b6108719060ff16600a611061565b6108449085610e99565b50825b9392505050565b60006020828403121561089757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461087e57600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146108e957600080fd5b50565b80356108f7816108c7565b919050565b60008083601f84011261090e57600080fd5b50813567ffffffffffffffff81111561092657600080fd5b60208301915083602082850101111561093e57600080fd5b9250929050565b6000806000806000806000806000806102608b8d03121561096557600080fd5b61096f8b356108c7565b8a35995060208b0135610981816108c7565b985060408b0135975060608b0135965060808b0135955060a08b013567ffffffffffffffff808211156109b357600080fd5b6109bf8e838f016108fc565b909750955060c08d01359150808211156109d857600080fd5b506109e58d828e016108fc565b9094509250506101808b8d037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20011215610a1e57600080fd5b60e08b0190509295989b9194979a5092959850565b600080600080600080600060a0888a031215610a4e57600080fd5b8735610a59816108c7565b96506020880135610a69816108c7565b955060408801359450606088013567ffffffffffffffff80821115610a8d57600080fd5b610a998b838c016108fc565b909650945060808a0135915080821115610ab257600080fd5b50610abf8a828b016108fc565b989b979a50959850939692959293505050565b815173ffffffffffffffffffffffffffffffffffffffff16815261018081016020830151610b18602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040830151610b40604084018273ffffffffffffffffffffffffffffffffffffffff169052565b50606083015160608301526080830151608083015260a0830151610b6c60a084018263ffffffff169052565b5060c083015160c083015260e083015160e083015261010080840151818401525061012080840151610ba18285018215159052565b5050610140838101519083015261016092830151929091019190915290565b600060208083528351808285015260005b81811015610bed57858101830151858201604001528201610bd1565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6040516101a0810167ffffffffffffffff81118282101715610c77577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290565b803580151581146108f757600080fd5b803563ffffffff811681146108f757600080fd5b60006101a08284031215610cb457600080fd5b610cbc610c2c565b610cc5836108ec565b8152610cd3602084016108ec565b6020820152604083013560408201526060830135606082015260808301356080820152610d0260a084016108ec565b60a0820152610d1360c08401610c7d565b60c0820152610d2460e08401610c7d565b60e0820152610100610d37818501610c8d565b90820152610120610d498482016108ec565b90820152610140610d5b8482016108ec565b908201526101608381013590820152610180928301359281019290925250919050565b805169ffffffffffffffffffff811681146108f757600080fd5b600080600080600060a08688031215610db057600080fd5b610db986610d7e565b9450602086015193506040860151925060608601519150610ddc60808701610d7e565b90509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561013657610136610de8565b600060208284031215610e3c57600080fd5b815160ff8116811461087e57600080fd5b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615610e8557610e85610de8565b818105831482151761013657610136610de8565b600082610ecf577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615610f2357610f23610de8565b500590565b60ff828116828216039081111561013657610136610de8565b600181815b80851115610f9a57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610f8057610f80610de8565b80851615610f8d57918102915b93841c9390800290610f46565b509250929050565b600082610fb157506001610136565b81610fbe57506000610136565b8160018114610fd45760028114610fde57610ffa565b6001915050610136565b60ff841115610fef57610fef610de8565b50506001821b610136565b5060208310610133831016604e8410600b841016171561101d575081810a610136565b6110278383610f41565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561105957611059610de8565b029392505050565b600061087e8383610fa256fea26469706673582212209fa3327f516265e18ab94702bbed1cbc326856415eb2fa4b4c99515fcc0fdc4a64736f6c63430008130033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100415760003560e01c806301ffc9a71461004657806314a2a7841461006e578063b8296fc414610083575b600080fd5b610059610054366004610885565b6100a3565b60405190151581526020015b60405180910390f35b61008161007c366004610945565b61013c565b005b610096610091366004610a33565b610259565b6040516100659190610ad2565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fb8296fc400000000000000000000000000000000000000000000000000000000148061013657507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b600061014d8b8b8989898989610259565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810180517fd5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e48982526101a0822091526040517f19010000000000000000000000000000000000000000000000000000000000008152600281018b9052602281019190915260429020909150891461024c57604080518082018252600c81527f696e76616c696420686173680000000000000000000000000000000000000000602082015290517fc8fc27250000000000000000000000000000000000000000000000000000000081526102439190600401610bc0565b60405180910390fd5b5050505050505050505050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290526101608101829052906102c686860187610ca1565b90504281610100015163ffffffff16101561034057604080518082018252600d81527f6f72646572206578706972656400000000000000000000000000000000000000602082015290517fc8fc27250000000000000000000000000000000000000000000000000000000081526102439190600401610bc0565b60008082610120015173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b79190610d98565b5093505092505060008084610140015173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610411573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104359190610d98565b5093505092505060008413801561044c5750600082135b6104b557604080518082018252601481527f6f7261636c6520696e76616c6964207072696365000000000000000000000000602082015290517fc8fc27250000000000000000000000000000000000000000000000000000000081526102439190600401610bc0565b6101808501516104c59042610e17565b83101580156104e357506101808501516104df9042610e17565b8110155b61054c57604080518082018252601281527f6f7261636c65207374616c652070726963650000000000000000000000000000602082015290517fd05f30650000000000000000000000000000000000000000000000000000000081526102439190600401610bc0565b6105cb8486610120015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c49190610e2a565b6012610812565b93506106218286610140015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105a0573d6000803e3d6000fd5b6101608601519092508261063d670de0b6b3a764000087610e4d565b6106479190610e99565b13156106b257604080518082018252601281527f737472696b65206e6f7420726561636865640000000000000000000000000000602082015290517fd05f30650000000000000000000000000000000000000000000000000000000081526102439190600401610bc0565b50505050604051806101800160405280826000015173ffffffffffffffffffffffffffffffffffffffff168152602001826020015173ffffffffffffffffffffffffffffffffffffffff1681526020018260a0015173ffffffffffffffffffffffffffffffffffffffff168152602001826040015181526020018260600151815260200182610100015163ffffffff16815260200182608001518152602001600081526020018260c00151610787577f6ed88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc6107a9565b7ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee3467755b81526020018260e00151151581526020017f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc981526020017f5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9815250915050979650505050505050565b60008160ff168360ff16101561084b5761082c8383610f28565b61083a9060ff16600a611061565b6108449085610e4d565b905061087e565b8160ff168360ff16111561087b576108638284610f28565b6108719060ff16600a611061565b6108449085610e99565b50825b9392505050565b60006020828403121561089757600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461087e57600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146108e957600080fd5b50565b80356108f7816108c7565b919050565b60008083601f84011261090e57600080fd5b50813567ffffffffffffffff81111561092657600080fd5b60208301915083602082850101111561093e57600080fd5b9250929050565b6000806000806000806000806000806102608b8d03121561096557600080fd5b61096f8b356108c7565b8a35995060208b0135610981816108c7565b985060408b0135975060608b0135965060808b0135955060a08b013567ffffffffffffffff808211156109b357600080fd5b6109bf8e838f016108fc565b909750955060c08d01359150808211156109d857600080fd5b506109e58d828e016108fc565b9094509250506101808b8d037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff20011215610a1e57600080fd5b60e08b0190509295989b9194979a5092959850565b600080600080600080600060a0888a031215610a4e57600080fd5b8735610a59816108c7565b96506020880135610a69816108c7565b955060408801359450606088013567ffffffffffffffff80821115610a8d57600080fd5b610a998b838c016108fc565b909650945060808a0135915080821115610ab257600080fd5b50610abf8a828b016108fc565b989b979a50959850939692959293505050565b815173ffffffffffffffffffffffffffffffffffffffff16815261018081016020830151610b18602084018273ffffffffffffffffffffffffffffffffffffffff169052565b506040830151610b40604084018273ffffffffffffffffffffffffffffffffffffffff169052565b50606083015160608301526080830151608083015260a0830151610b6c60a084018263ffffffff169052565b5060c083015160c083015260e083015160e083015261010080840151818401525061012080840151610ba18285018215159052565b5050610140838101519083015261016092830151929091019190915290565b600060208083528351808285015260005b81811015610bed57858101830151858201604001528201610bd1565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6040516101a0810167ffffffffffffffff81118282101715610c77577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405290565b803580151581146108f757600080fd5b803563ffffffff811681146108f757600080fd5b60006101a08284031215610cb457600080fd5b610cbc610c2c565b610cc5836108ec565b8152610cd3602084016108ec565b6020820152604083013560408201526060830135606082015260808301356080820152610d0260a084016108ec565b60a0820152610d1360c08401610c7d565b60c0820152610d2460e08401610c7d565b60e0820152610100610d37818501610c8d565b90820152610120610d498482016108ec565b90820152610140610d5b8482016108ec565b908201526101608381013590820152610180928301359281019290925250919050565b805169ffffffffffffffffffff811681146108f757600080fd5b600080600080600060a08688031215610db057600080fd5b610db986610d7e565b9450602086015193506040860151925060608601519150610ddc60808701610d7e565b90509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561013657610136610de8565b600060208284031215610e3c57600080fd5b815160ff8116811461087e57600080fd5b808202600082127f800000000000000000000000000000000000000000000000000000000000000084141615610e8557610e85610de8565b818105831482151761013657610136610de8565b600082610ecf577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83147f800000000000000000000000000000000000000000000000000000000000000083141615610f2357610f23610de8565b500590565b60ff828116828216039081111561013657610136610de8565b600181815b80851115610f9a57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610f8057610f80610de8565b80851615610f8d57918102915b93841c9390800290610f46565b509250929050565b600082610fb157506001610136565b81610fbe57506000610136565b8160018114610fd45760028114610fde57610ffa565b6001915050610136565b60ff841115610fef57610fef610de8565b50506001821b610136565b5060208310610133831016604e8410600b841016171561101d575081810a610136565b6110278383610f41565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561105957611059610de8565b029392505050565b600061087e8383610fa256fea26469706673582212209fa3327f516265e18ab94702bbed1cbc326856415eb2fa4b4c99515fcc0fdc4a64736f6c63430008130033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
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.